diff --git a/src/dawn_native/BindGroupAndStorageBarrierTracker.h b/src/dawn_native/BindGroupAndStorageBarrierTracker.h index 94a2be8d65..8227d84953 100644 --- a/src/dawn_native/BindGroupAndStorageBarrierTracker.h +++ b/src/dawn_native/BindGroupAndStorageBarrierTracker.h @@ -17,6 +17,8 @@ #include "dawn_native/BindGroup.h" #include "dawn_native/BindGroupTracker.h" +#include "dawn_native/Buffer.h" +#include "dawn_native/Texture.h" namespace dawn_native { @@ -34,8 +36,8 @@ namespace dawn_native { uint32_t dynamicOffsetCount, uint32_t* dynamicOffsets) { if (this->mBindGroups[index] != bindGroup) { - mBuffers[index] = {}; - mBuffersNeedingBarrier[index] = {}; + mBindings[index] = {}; + mBindingsNeedingBarrier[index] = {}; const BindGroupLayoutBase* layout = bindGroup->GetLayout(); @@ -58,16 +60,23 @@ namespace dawn_native { break; case wgpu::BindingType::StorageBuffer: - mBuffersNeedingBarrier[index].set(bindingIndex); - mBuffers[index][bindingIndex] = - bindGroup->GetBindingAsBufferBinding(bindingIndex).buffer; + mBindingsNeedingBarrier[index].set(bindingIndex); + mBindings[index][bindingIndex] = static_cast( + 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( + bindGroup->GetBindingAsTextureView(bindingIndex)); break; case wgpu::BindingType::StorageTexture: - case wgpu::BindingType::ReadonlyStorageTexture: - case wgpu::BindingType::WriteonlyStorageTexture: // Not implemented. - default: UNREACHABLE(); break; @@ -79,10 +88,10 @@ namespace dawn_native { } protected: - std::array, kMaxBindGroups> mBuffersNeedingBarrier = {}; + std::array, kMaxBindGroups> mBindingsNeedingBarrier = {}; std::array, kMaxBindGroups> mBindingTypes = {}; - std::array, kMaxBindGroups> mBuffers = {}; + std::array, kMaxBindGroups> mBindings = {}; }; } // namespace dawn_native diff --git a/src/dawn_native/d3d12/CommandBufferD3D12.cpp b/src/dawn_native/d3d12/CommandBufferD3D12.cpp index cea95160f5..9a5b66321f 100644 --- a/src/dawn_native/d3d12/CommandBufferD3D12.cpp +++ b/src/dawn_native/d3d12/CommandBufferD3D12.cpp @@ -148,11 +148,11 @@ namespace dawn_native { namespace d3d12 { if (mInCompute) { 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]; switch (bindingType) { case wgpu::BindingType::StorageBuffer: - ToBackend(mBuffers[index][binding]) + static_cast(mBindings[index][binding]) ->TrackUsageAndTransitionNow(commandContext, wgpu::BufferUsage::Storage); break; diff --git a/src/dawn_native/vulkan/CommandBufferVk.cpp b/src/dawn_native/vulkan/CommandBufferVk.cpp index 5ab1b8f95e..53f2602282 100644 --- a/src/dawn_native/vulkan/CommandBufferVk.cpp +++ b/src/dawn_native/vulkan/CommandBufferVk.cpp @@ -140,17 +140,24 @@ namespace dawn_native { namespace vulkan { mDynamicOffsetCounts, mDynamicOffsets); for (uint32_t index : IterateBitSet(mBindGroupLayoutsMask)) { - for (uint32_t bindingIndex : IterateBitSet(mBuffersNeedingBarrier[index])) { + for (uint32_t bindingIndex : IterateBitSet(mBindingsNeedingBarrier[index])) { switch (mBindingTypes[index][bindingIndex]) { case wgpu::BindingType::StorageBuffer: - ToBackend(mBuffers[index][bindingIndex]) + static_cast(mBindings[index][bindingIndex]) ->TransitionUsageNow(recordingContext, wgpu::BufferUsage::Storage); break; - case wgpu::BindingType::StorageTexture: case wgpu::BindingType::ReadonlyStorageTexture: case wgpu::BindingType::WriteonlyStorageTexture: + ToBackend( + static_cast(mBindings[index][bindingIndex]) + ->GetTexture()) + ->TransitionUsageNow(recordingContext, + wgpu::TextureUsage::Storage); + break; + + case wgpu::BindingType::StorageTexture: // Not implemented. case wgpu::BindingType::UniformBuffer: diff --git a/src/dawn_native/vulkan/TextureVk.cpp b/src/dawn_native/vulkan/TextureVk.cpp index 35ade8bf79..681e0cf801 100644 --- a/src/dawn_native/vulkan/TextureVk.cpp +++ b/src/dawn_native/vulkan/TextureVk.cpp @@ -120,9 +120,11 @@ namespace dawn_native { namespace vulkan { // combination of GENERAL and TRANSFER_SRC_OPTIMAL. This would be a problem, so we // make CopySrc use GENERAL. case wgpu::TextureUsage::CopySrc: - // Writable storage textures must use general. If we could know the texture is read - // only we could use SHADER_READ_ONLY_OPTIMAL + // 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::TextureUsage::Storage: + case kReadonlyStorageTexture: return VK_IMAGE_LAYOUT_GENERAL; case wgpu::TextureUsage::OutputAttachment: if (format.HasDepthOrStencil()) { @@ -149,11 +151,15 @@ namespace dawn_native { namespace vulkan { if (usage & (wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst)) { 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 | VK_PIPELINE_STAGE_FRAGMENT_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 (format.HasDepthOrStencil()) { flags |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | diff --git a/src/tests/end2end/StorageTextureTests.cpp b/src/tests/end2end/StorageTextureTests.cpp index da9d98339d..9e6764c752 100644 --- a/src/tests/end2end/StorageTextureTests.cpp +++ b/src/tests/end2end/StorageTextureTests.cpp @@ -176,6 +176,7 @@ class StorageTextureTests : public DawnTest { #version 450 void main() { gl_Position = vec4(0.f, 0.f, 0.f, 1.f); + gl_PointSize = 1.0f; })"; 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_P(StorageTextureTests, ReadonlyStorageTextureInComputeShader) { - // TODO(jiawei.shao@intel.com): support read-only storage texture on D3D12, Vulkan and OpenGL. - DAWN_SKIP_TEST_IF(IsD3D12() || IsVulkan() || IsOpenGL()); + // TODO(jiawei.shao@intel.com): support read-only storage texture on D3D12 and OpenGL. + DAWN_SKIP_TEST_IF(IsD3D12() || IsOpenGL()); // Prepare the read-only storage texture and fill it with the expected data. // 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_P(StorageTextureTests, ReadonlyStorageTextureInVertexShader) { - // TODO(jiawei.shao@intel.com): support read-only storage texture on D3D12, Vulkan and OpenGL. - DAWN_SKIP_TEST_IF(IsD3D12() || IsVulkan() || IsOpenGL()); + // TODO(jiawei.shao@intel.com): support read-only storage texture on D3D12 and OpenGL. + DAWN_SKIP_TEST_IF(IsD3D12() || IsOpenGL()); // 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. @@ -321,6 +322,7 @@ TEST_P(StorageTextureTests, ReadonlyStorageTextureInVertexShader) { } else { o_color = vec4(1.f, 0.f, 0.f, 1.f); } + gl_PointSize = 1.0f; })"; const char* kFragmentShader = R"( #version 450 @@ -334,8 +336,8 @@ TEST_P(StorageTextureTests, ReadonlyStorageTextureInVertexShader) { // Test that read-only storage textures are supported in fragment shader. TEST_P(StorageTextureTests, ReadonlyStorageTextureInFragmentShader) { - // TODO(jiawei.shao@intel.com): support read-only storage texture on D3D12, Vulkan and OpenGL. - DAWN_SKIP_TEST_IF(IsD3D12() || IsVulkan() || IsOpenGL()); + // TODO(jiawei.shao@intel.com): support read-only storage texture on D3D12 and OpenGL. + DAWN_SKIP_TEST_IF(IsD3D12() || IsOpenGL()); // 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. @@ -370,8 +372,8 @@ TEST_P(StorageTextureTests, ReadonlyStorageTextureInFragmentShader) { // Test that write-only storage textures are supported in compute shader. TEST_P(StorageTextureTests, WriteonlyStorageTextureInComputeShader) { - // TODO(jiawei.shao@intel.com): support read-only storage texture on D3D12, Vulkan and OpenGL. - DAWN_SKIP_TEST_IF(IsD3D12() || IsVulkan() || IsOpenGL()); + // TODO(jiawei.shao@intel.com): support read-only storage texture on D3D12 and OpenGL. + DAWN_SKIP_TEST_IF(IsD3D12() || IsOpenGL()); // Prepare the write-only storage texture. // 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_P(StorageTextureTests, WriteonlyStorageTextureInFragmentShader) { - // TODO(jiawei.shao@intel.com): support read-only storage texture on D3D12, Vulkan and OpenGL. - DAWN_SKIP_TEST_IF(IsD3D12() || IsVulkan() || IsOpenGL()); + // TODO(jiawei.shao@intel.com): support read-only storage texture on D3D12 and OpenGL. + DAWN_SKIP_TEST_IF(IsD3D12() || IsOpenGL()); // Prepare the write-only storage texture. // TODO(jiawei.shao@intel.com): test more texture formats.