Add basic supports of storage textures on Vulkan
This patch adds the basic supports of read-only and write-only storage textures on Vulkan. The subresource tracking and barriers on the subresources used as read-only and write-only storage textures are not included in this patch. BUG=dawn:267 TEST=dawn_end2end_tests Change-Id: I6831b96202a97182763ecd28bc41ab03df904a7c Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/20560 Commit-Queue: Jiawei Shao <jiawei.shao@intel.com> Reviewed-by: Austin Eng <enga@chromium.org>
This commit is contained in:
parent
c85ef7927f
commit
754c161fd3
|
@ -17,6 +17,8 @@
|
||||||
|
|
||||||
#include "dawn_native/BindGroup.h"
|
#include "dawn_native/BindGroup.h"
|
||||||
#include "dawn_native/BindGroupTracker.h"
|
#include "dawn_native/BindGroupTracker.h"
|
||||||
|
#include "dawn_native/Buffer.h"
|
||||||
|
#include "dawn_native/Texture.h"
|
||||||
|
|
||||||
namespace dawn_native {
|
namespace dawn_native {
|
||||||
|
|
||||||
|
@ -34,8 +36,8 @@ namespace dawn_native {
|
||||||
uint32_t dynamicOffsetCount,
|
uint32_t dynamicOffsetCount,
|
||||||
uint32_t* dynamicOffsets) {
|
uint32_t* dynamicOffsets) {
|
||||||
if (this->mBindGroups[index] != bindGroup) {
|
if (this->mBindGroups[index] != bindGroup) {
|
||||||
mBuffers[index] = {};
|
mBindings[index] = {};
|
||||||
mBuffersNeedingBarrier[index] = {};
|
mBindingsNeedingBarrier[index] = {};
|
||||||
|
|
||||||
const BindGroupLayoutBase* layout = bindGroup->GetLayout();
|
const BindGroupLayoutBase* layout = bindGroup->GetLayout();
|
||||||
|
|
||||||
|
@ -58,16 +60,23 @@ namespace dawn_native {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case wgpu::BindingType::StorageBuffer:
|
case wgpu::BindingType::StorageBuffer:
|
||||||
mBuffersNeedingBarrier[index].set(bindingIndex);
|
mBindingsNeedingBarrier[index].set(bindingIndex);
|
||||||
mBuffers[index][bindingIndex] =
|
mBindings[index][bindingIndex] = static_cast<ObjectBase*>(
|
||||||
bindGroup->GetBindingAsBufferBinding(bindingIndex).buffer;
|
bindGroup->GetBindingAsBufferBinding(bindingIndex).buffer);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Read-only and write-only storage textures must use general layout
|
||||||
|
// because load and store operations on storage images can only be done on
|
||||||
|
// the images in VK_IMAGE_LAYOUT_GENERAL layout.
|
||||||
|
case wgpu::BindingType::ReadonlyStorageTexture:
|
||||||
|
case wgpu::BindingType::WriteonlyStorageTexture:
|
||||||
|
mBindingsNeedingBarrier[index].set(bindingIndex);
|
||||||
|
mBindings[index][bindingIndex] = static_cast<ObjectBase*>(
|
||||||
|
bindGroup->GetBindingAsTextureView(bindingIndex));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case wgpu::BindingType::StorageTexture:
|
case wgpu::BindingType::StorageTexture:
|
||||||
case wgpu::BindingType::ReadonlyStorageTexture:
|
|
||||||
case wgpu::BindingType::WriteonlyStorageTexture:
|
|
||||||
// Not implemented.
|
// Not implemented.
|
||||||
|
|
||||||
default:
|
default:
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
break;
|
break;
|
||||||
|
@ -79,10 +88,10 @@ namespace dawn_native {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::array<std::bitset<kMaxBindingsPerGroup>, kMaxBindGroups> mBuffersNeedingBarrier = {};
|
std::array<std::bitset<kMaxBindingsPerGroup>, kMaxBindGroups> mBindingsNeedingBarrier = {};
|
||||||
std::array<std::array<wgpu::BindingType, kMaxBindingsPerGroup>, kMaxBindGroups>
|
std::array<std::array<wgpu::BindingType, kMaxBindingsPerGroup>, kMaxBindGroups>
|
||||||
mBindingTypes = {};
|
mBindingTypes = {};
|
||||||
std::array<std::array<BufferBase*, kMaxBindingsPerGroup>, kMaxBindGroups> mBuffers = {};
|
std::array<std::array<ObjectBase*, kMaxBindingsPerGroup>, kMaxBindGroups> mBindings = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dawn_native
|
} // namespace dawn_native
|
||||||
|
|
|
@ -148,11 +148,11 @@ namespace dawn_native { namespace d3d12 {
|
||||||
|
|
||||||
if (mInCompute) {
|
if (mInCompute) {
|
||||||
for (uint32_t index : IterateBitSet(mBindGroupLayoutsMask)) {
|
for (uint32_t index : IterateBitSet(mBindGroupLayoutsMask)) {
|
||||||
for (uint32_t binding : IterateBitSet(mBuffersNeedingBarrier[index])) {
|
for (uint32_t binding : IterateBitSet(mBindingsNeedingBarrier[index])) {
|
||||||
wgpu::BindingType bindingType = mBindingTypes[index][binding];
|
wgpu::BindingType bindingType = mBindingTypes[index][binding];
|
||||||
switch (bindingType) {
|
switch (bindingType) {
|
||||||
case wgpu::BindingType::StorageBuffer:
|
case wgpu::BindingType::StorageBuffer:
|
||||||
ToBackend(mBuffers[index][binding])
|
static_cast<Buffer*>(mBindings[index][binding])
|
||||||
->TrackUsageAndTransitionNow(commandContext,
|
->TrackUsageAndTransitionNow(commandContext,
|
||||||
wgpu::BufferUsage::Storage);
|
wgpu::BufferUsage::Storage);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -140,17 +140,24 @@ namespace dawn_native { namespace vulkan {
|
||||||
mDynamicOffsetCounts, mDynamicOffsets);
|
mDynamicOffsetCounts, mDynamicOffsets);
|
||||||
|
|
||||||
for (uint32_t index : IterateBitSet(mBindGroupLayoutsMask)) {
|
for (uint32_t index : IterateBitSet(mBindGroupLayoutsMask)) {
|
||||||
for (uint32_t bindingIndex : IterateBitSet(mBuffersNeedingBarrier[index])) {
|
for (uint32_t bindingIndex : IterateBitSet(mBindingsNeedingBarrier[index])) {
|
||||||
switch (mBindingTypes[index][bindingIndex]) {
|
switch (mBindingTypes[index][bindingIndex]) {
|
||||||
case wgpu::BindingType::StorageBuffer:
|
case wgpu::BindingType::StorageBuffer:
|
||||||
ToBackend(mBuffers[index][bindingIndex])
|
static_cast<Buffer*>(mBindings[index][bindingIndex])
|
||||||
->TransitionUsageNow(recordingContext,
|
->TransitionUsageNow(recordingContext,
|
||||||
wgpu::BufferUsage::Storage);
|
wgpu::BufferUsage::Storage);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case wgpu::BindingType::StorageTexture:
|
|
||||||
case wgpu::BindingType::ReadonlyStorageTexture:
|
case wgpu::BindingType::ReadonlyStorageTexture:
|
||||||
case wgpu::BindingType::WriteonlyStorageTexture:
|
case wgpu::BindingType::WriteonlyStorageTexture:
|
||||||
|
ToBackend(
|
||||||
|
static_cast<TextureViewBase*>(mBindings[index][bindingIndex])
|
||||||
|
->GetTexture())
|
||||||
|
->TransitionUsageNow(recordingContext,
|
||||||
|
wgpu::TextureUsage::Storage);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case wgpu::BindingType::StorageTexture:
|
||||||
// Not implemented.
|
// Not implemented.
|
||||||
|
|
||||||
case wgpu::BindingType::UniformBuffer:
|
case wgpu::BindingType::UniformBuffer:
|
||||||
|
|
|
@ -120,9 +120,11 @@ namespace dawn_native { namespace vulkan {
|
||||||
// combination of GENERAL and TRANSFER_SRC_OPTIMAL. This would be a problem, so we
|
// combination of GENERAL and TRANSFER_SRC_OPTIMAL. This would be a problem, so we
|
||||||
// make CopySrc use GENERAL.
|
// make CopySrc use GENERAL.
|
||||||
case wgpu::TextureUsage::CopySrc:
|
case wgpu::TextureUsage::CopySrc:
|
||||||
// Writable storage textures must use general. If we could know the texture is read
|
// Read-only and write-only storage textures must use general layout because load
|
||||||
// only we could use SHADER_READ_ONLY_OPTIMAL
|
// and store operations on storage images can only be done on the images in
|
||||||
|
// VK_IMAGE_LAYOUT_GENERAL layout.
|
||||||
case wgpu::TextureUsage::Storage:
|
case wgpu::TextureUsage::Storage:
|
||||||
|
case kReadonlyStorageTexture:
|
||||||
return VK_IMAGE_LAYOUT_GENERAL;
|
return VK_IMAGE_LAYOUT_GENERAL;
|
||||||
case wgpu::TextureUsage::OutputAttachment:
|
case wgpu::TextureUsage::OutputAttachment:
|
||||||
if (format.HasDepthOrStencil()) {
|
if (format.HasDepthOrStencil()) {
|
||||||
|
@ -149,11 +151,15 @@ namespace dawn_native { namespace vulkan {
|
||||||
if (usage & (wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst)) {
|
if (usage & (wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst)) {
|
||||||
flags |= VK_PIPELINE_STAGE_TRANSFER_BIT;
|
flags |= VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||||
}
|
}
|
||||||
if (usage & (wgpu::TextureUsage::Sampled | wgpu::TextureUsage::Storage)) {
|
if (usage & (wgpu::TextureUsage::Sampled | kReadonlyStorageTexture)) {
|
||||||
flags |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
|
flags |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
|
||||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
|
||||||
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
|
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
|
||||||
}
|
}
|
||||||
|
if (usage & wgpu::TextureUsage::Storage) {
|
||||||
|
flags |=
|
||||||
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
|
||||||
|
}
|
||||||
if (usage & wgpu::TextureUsage::OutputAttachment) {
|
if (usage & wgpu::TextureUsage::OutputAttachment) {
|
||||||
if (format.HasDepthOrStencil()) {
|
if (format.HasDepthOrStencil()) {
|
||||||
flags |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
|
flags |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
|
||||||
|
|
|
@ -176,6 +176,7 @@ class StorageTextureTests : public DawnTest {
|
||||||
#version 450
|
#version 450
|
||||||
void main() {
|
void main() {
|
||||||
gl_Position = vec4(0.f, 0.f, 0.f, 1.f);
|
gl_Position = vec4(0.f, 0.f, 0.f, 1.f);
|
||||||
|
gl_PointSize = 1.0f;
|
||||||
})";
|
})";
|
||||||
|
|
||||||
const char* kCommonReadOnlyTestCode_uimage2D = R"(
|
const char* kCommonReadOnlyTestCode_uimage2D = R"(
|
||||||
|
@ -236,8 +237,8 @@ TEST_P(StorageTextureTests, BindGroupLayoutWithStorageTextureBindingType) {
|
||||||
|
|
||||||
// Test that read-only storage textures are supported in compute shader.
|
// Test that read-only storage textures are supported in compute shader.
|
||||||
TEST_P(StorageTextureTests, ReadonlyStorageTextureInComputeShader) {
|
TEST_P(StorageTextureTests, ReadonlyStorageTextureInComputeShader) {
|
||||||
// TODO(jiawei.shao@intel.com): support read-only storage texture on D3D12, Vulkan and OpenGL.
|
// TODO(jiawei.shao@intel.com): support read-only storage texture on D3D12 and OpenGL.
|
||||||
DAWN_SKIP_TEST_IF(IsD3D12() || IsVulkan() || IsOpenGL());
|
DAWN_SKIP_TEST_IF(IsD3D12() || IsOpenGL());
|
||||||
|
|
||||||
// Prepare the read-only storage texture and fill it with the expected data.
|
// Prepare the read-only storage texture and fill it with the expected data.
|
||||||
// TODO(jiawei.shao@intel.com): test more texture formats.
|
// TODO(jiawei.shao@intel.com): test more texture formats.
|
||||||
|
@ -291,8 +292,8 @@ TEST_P(StorageTextureTests, ReadonlyStorageTextureInComputeShader) {
|
||||||
|
|
||||||
// Test that read-only storage textures are supported in vertex shader.
|
// Test that read-only storage textures are supported in vertex shader.
|
||||||
TEST_P(StorageTextureTests, ReadonlyStorageTextureInVertexShader) {
|
TEST_P(StorageTextureTests, ReadonlyStorageTextureInVertexShader) {
|
||||||
// TODO(jiawei.shao@intel.com): support read-only storage texture on D3D12, Vulkan and OpenGL.
|
// TODO(jiawei.shao@intel.com): support read-only storage texture on D3D12 and OpenGL.
|
||||||
DAWN_SKIP_TEST_IF(IsD3D12() || IsVulkan() || IsOpenGL());
|
DAWN_SKIP_TEST_IF(IsD3D12() || IsOpenGL());
|
||||||
|
|
||||||
// When we run dawn_end2end_tests with "--use-spvc-parser", extracting the binding type of a
|
// When we run dawn_end2end_tests with "--use-spvc-parser", extracting the binding type of a
|
||||||
// read-only image will always return shaderc_spvc_binding_type_writeonly_storage_texture.
|
// read-only image will always return shaderc_spvc_binding_type_writeonly_storage_texture.
|
||||||
|
@ -321,6 +322,7 @@ TEST_P(StorageTextureTests, ReadonlyStorageTextureInVertexShader) {
|
||||||
} else {
|
} else {
|
||||||
o_color = vec4(1.f, 0.f, 0.f, 1.f);
|
o_color = vec4(1.f, 0.f, 0.f, 1.f);
|
||||||
}
|
}
|
||||||
|
gl_PointSize = 1.0f;
|
||||||
})";
|
})";
|
||||||
const char* kFragmentShader = R"(
|
const char* kFragmentShader = R"(
|
||||||
#version 450
|
#version 450
|
||||||
|
@ -334,8 +336,8 @@ TEST_P(StorageTextureTests, ReadonlyStorageTextureInVertexShader) {
|
||||||
|
|
||||||
// Test that read-only storage textures are supported in fragment shader.
|
// Test that read-only storage textures are supported in fragment shader.
|
||||||
TEST_P(StorageTextureTests, ReadonlyStorageTextureInFragmentShader) {
|
TEST_P(StorageTextureTests, ReadonlyStorageTextureInFragmentShader) {
|
||||||
// TODO(jiawei.shao@intel.com): support read-only storage texture on D3D12, Vulkan and OpenGL.
|
// TODO(jiawei.shao@intel.com): support read-only storage texture on D3D12 and OpenGL.
|
||||||
DAWN_SKIP_TEST_IF(IsD3D12() || IsVulkan() || IsOpenGL());
|
DAWN_SKIP_TEST_IF(IsD3D12() || IsOpenGL());
|
||||||
|
|
||||||
// When we run dawn_end2end_tests with "--use-spvc-parser", extracting the binding type of a
|
// When we run dawn_end2end_tests with "--use-spvc-parser", extracting the binding type of a
|
||||||
// read-only image will always return shaderc_spvc_binding_type_writeonly_storage_texture.
|
// read-only image will always return shaderc_spvc_binding_type_writeonly_storage_texture.
|
||||||
|
@ -370,8 +372,8 @@ TEST_P(StorageTextureTests, ReadonlyStorageTextureInFragmentShader) {
|
||||||
|
|
||||||
// Test that write-only storage textures are supported in compute shader.
|
// Test that write-only storage textures are supported in compute shader.
|
||||||
TEST_P(StorageTextureTests, WriteonlyStorageTextureInComputeShader) {
|
TEST_P(StorageTextureTests, WriteonlyStorageTextureInComputeShader) {
|
||||||
// TODO(jiawei.shao@intel.com): support read-only storage texture on D3D12, Vulkan and OpenGL.
|
// TODO(jiawei.shao@intel.com): support read-only storage texture on D3D12 and OpenGL.
|
||||||
DAWN_SKIP_TEST_IF(IsD3D12() || IsVulkan() || IsOpenGL());
|
DAWN_SKIP_TEST_IF(IsD3D12() || IsOpenGL());
|
||||||
|
|
||||||
// Prepare the write-only storage texture.
|
// Prepare the write-only storage texture.
|
||||||
// TODO(jiawei.shao@intel.com): test more texture formats.
|
// TODO(jiawei.shao@intel.com): test more texture formats.
|
||||||
|
@ -400,8 +402,8 @@ TEST_P(StorageTextureTests, WriteonlyStorageTextureInComputeShader) {
|
||||||
|
|
||||||
// Test that write-only storage textures are supported in fragment shader.
|
// Test that write-only storage textures are supported in fragment shader.
|
||||||
TEST_P(StorageTextureTests, WriteonlyStorageTextureInFragmentShader) {
|
TEST_P(StorageTextureTests, WriteonlyStorageTextureInFragmentShader) {
|
||||||
// TODO(jiawei.shao@intel.com): support read-only storage texture on D3D12, Vulkan and OpenGL.
|
// TODO(jiawei.shao@intel.com): support read-only storage texture on D3D12 and OpenGL.
|
||||||
DAWN_SKIP_TEST_IF(IsD3D12() || IsVulkan() || IsOpenGL());
|
DAWN_SKIP_TEST_IF(IsD3D12() || IsOpenGL());
|
||||||
|
|
||||||
// Prepare the write-only storage texture.
|
// Prepare the write-only storage texture.
|
||||||
// TODO(jiawei.shao@intel.com): test more texture formats.
|
// TODO(jiawei.shao@intel.com): test more texture formats.
|
||||||
|
|
Loading…
Reference in New Issue