mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-16 16:37:08 +00:00
Vulkan: Fix layout of Sampled+ROStorage texture.
Vulkan requires that storage images be in the GENERAL layout, and requires that we choose a layout at VkDescriptorSet creation. This means that since Sampled+ROStorage texture may sometimes be used as both usages in the same pass, they must always be in the GENERAL layout even for SampledTexture bindings. Fix this by looking at the texture's creation usage in VulkanImageLayout for wgpu::TextureUsage::Sampled. Also add a regression test that triggers a Vulkan Validation Layer error without this fix. Bug: dawn:635 Change-Id: I4a5b94e1af20839b3b8cc080d36fca59d79f09bb Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/38107 Commit-Queue: Corentin Wallez <cwallez@chromium.org> Auto-Submit: Corentin Wallez <cwallez@chromium.org> Reviewed-by: Austin Eng <enga@chromium.org>
This commit is contained in:
committed by
Commit Bot service account
parent
f091fb71f7
commit
e10e6b0db8
@@ -234,6 +234,75 @@ TEST_P(GpuMemorySyncTests, ComputePassToRenderPass) {
|
||||
EXPECT_PIXEL_RGBA8_EQ(RGBA8(2, 0, 0, 255), renderPass.color, 0, 0);
|
||||
}
|
||||
|
||||
// Use an image as both sampled and readonly storage in a compute pass. This is a regression test
|
||||
// for the Vulkan backend choosing different layouts for Sampled and ReadOnlyStorage.
|
||||
TEST_P(GpuMemorySyncTests, SampledAndROStorageTextureInComputePass) {
|
||||
// TODO(dawn:483): Test is skipped on OpenGL because it uses WriteTexture which is
|
||||
// unimplemented.
|
||||
DAWN_SKIP_TEST_IF(IsOpenGL() || IsOpenGLES());
|
||||
|
||||
// Create a storage + sampled texture of one texel initialized to 1
|
||||
wgpu::TextureDescriptor texDesc;
|
||||
texDesc.format = wgpu::TextureFormat::R32Uint;
|
||||
texDesc.size = {1, 1, 1};
|
||||
texDesc.usage =
|
||||
wgpu::TextureUsage::Storage | wgpu::TextureUsage::Sampled | wgpu::TextureUsage::CopyDst;
|
||||
wgpu::Texture tex = device.CreateTexture(&texDesc);
|
||||
|
||||
wgpu::TextureCopyView copyView;
|
||||
copyView.texture = tex;
|
||||
wgpu::TextureDataLayout layout;
|
||||
wgpu::Extent3D copySize = {1, 1, 1};
|
||||
uint32_t kOne = 1;
|
||||
queue.WriteTexture(©View, &kOne, sizeof(kOne), &layout, ©Size);
|
||||
|
||||
// Create a pipeline that loads the texture from both the sampled and storage paths.
|
||||
wgpu::ComputePipelineDescriptor pipelineDesc;
|
||||
pipelineDesc.computeStage.entryPoint = "main";
|
||||
pipelineDesc.computeStage.module = utils::CreateShaderModuleFromWGSL(device, R"(
|
||||
[[block]] struct Output {
|
||||
[[offset(0)]] sampledOut: u32;
|
||||
[[offset(4)]] storageOut: u32;
|
||||
};
|
||||
[[group(0), binding(0)]] var<storage_buffer> output : [[access(write)]] Output;
|
||||
[[group(0), binding(1)]] var<uniform_constant> sampledTex : texture_2d<u32>;
|
||||
[[group(0), binding(2)]] var<uniform_constant> storageTex : [[access(read)]] texture_storage_2d<r32uint>;
|
||||
|
||||
[[stage(compute)]] fn main() -> void {
|
||||
output.sampledOut = textureLoad(sampledTex, vec2<i32>(0, 0), 0).x;
|
||||
output.storageOut = textureLoad(storageTex, vec2<i32>(0, 0)).x;
|
||||
}
|
||||
)");
|
||||
wgpu::ComputePipeline pipeline = device.CreateComputePipeline(&pipelineDesc);
|
||||
|
||||
// Run the compute pipeline and store the result in the buffer.
|
||||
wgpu::BufferDescriptor outputDesc;
|
||||
outputDesc.size = 8;
|
||||
outputDesc.usage = wgpu::BufferUsage::Storage | wgpu::BufferUsage::CopySrc;
|
||||
wgpu::Buffer outputBuffer = device.CreateBuffer(&outputDesc);
|
||||
|
||||
wgpu::BindGroup bg = utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0),
|
||||
{
|
||||
{0, outputBuffer},
|
||||
{1, tex.CreateView()},
|
||||
{2, tex.CreateView()},
|
||||
});
|
||||
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
|
||||
pass.SetBindGroup(0, bg);
|
||||
pass.SetPipeline(pipeline);
|
||||
pass.Dispatch(1);
|
||||
pass.EndPass();
|
||||
|
||||
wgpu::CommandBuffer commands = encoder.Finish();
|
||||
queue.Submit(1, &commands);
|
||||
|
||||
// Check the buffer's content is what we expect.
|
||||
EXPECT_BUFFER_U32_EQ(1, outputBuffer, 0);
|
||||
EXPECT_BUFFER_U32_EQ(1, outputBuffer, 4);
|
||||
}
|
||||
|
||||
DAWN_INSTANTIATE_TEST(GpuMemorySyncTests,
|
||||
D3D12Backend(),
|
||||
MetalBackend(),
|
||||
|
||||
Reference in New Issue
Block a user