Add tests for resource tracking in compute - 1

This patch adds resource usage tracking tests for overwritten
situations within a draw/dispatch when we call multiple
SetBindGroup. We should track the overwritten resources
even though they are not used in render/compute pass.

Bug: dawn:357

Change-Id: I7467db1c0b43fed8513ddb7604adbbd1be55866f
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/20160
Commit-Queue: Yunchao He <yunchao.he@intel.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
Yunchao He 2020-04-30 22:08:18 +00:00 committed by Commit Bot service account
parent 129dc00c69
commit 2ba90d6654
1 changed files with 145 additions and 26 deletions

View File

@ -29,7 +29,7 @@ namespace {
return device.CreateBuffer(&descriptor); return device.CreateBuffer(&descriptor);
} }
wgpu::Texture CreateTexture(wgpu::TextureUsage usage, wgpu::TextureFormat format) { wgpu::Texture CreateTexture(wgpu::TextureUsage usage) {
wgpu::TextureDescriptor descriptor; wgpu::TextureDescriptor descriptor;
descriptor.dimension = wgpu::TextureDimension::e2D; descriptor.dimension = wgpu::TextureDimension::e2D;
descriptor.size = {1, 1, 1}; descriptor.size = {1, 1, 1};
@ -37,10 +37,12 @@ namespace {
descriptor.sampleCount = 1; descriptor.sampleCount = 1;
descriptor.mipLevelCount = 1; descriptor.mipLevelCount = 1;
descriptor.usage = usage; descriptor.usage = usage;
descriptor.format = format; descriptor.format = kFormat;
return device.CreateTexture(&descriptor); return device.CreateTexture(&descriptor);
} }
static constexpr wgpu::TextureFormat kFormat = wgpu::TextureFormat::RGBA8Unorm;
}; };
// Test that using a single buffer in multiple read usages in the same pass is allowed. // Test that using a single buffer in multiple read usages in the same pass is allowed.
@ -421,7 +423,67 @@ namespace {
} }
} }
// TODO (yunchao.he@intel.com) test compute pass // test compute pass
{
// Create buffers that will be used as index and storage buffers
wgpu::Buffer buffer0 = CreateBuffer(512, wgpu::BufferUsage::Storage);
wgpu::Buffer buffer1 = CreateBuffer(4, wgpu::BufferUsage::Storage);
// Create the bind group to use the buffer as storage
wgpu::BindGroupLayout writeBGL = utils::MakeBindGroupLayout(
device, {{0, wgpu::ShaderStage::Compute, wgpu::BindingType::StorageBuffer}});
wgpu::BindGroupLayout readBGL = utils::MakeBindGroupLayout(
device,
{{0, wgpu::ShaderStage::Compute, wgpu::BindingType::ReadonlyStorageBuffer}});
wgpu::BindGroup writeBG0 = utils::MakeBindGroup(device, writeBGL, {{0, buffer0, 0, 4}});
wgpu::BindGroup readBG0 = utils::MakeBindGroup(device, readBGL, {{0, buffer0, 256, 4}});
wgpu::BindGroup readBG1 = utils::MakeBindGroup(device, readBGL, {{0, buffer1, 0, 4}});
// Create a passthrough compute pipeline
wgpu::ShaderModule csModule =
utils::CreateShaderModule(device, utils::SingleShaderStage::Compute, R"(
#version 450
void main() {
})");
wgpu::ComputePipelineDescriptor pipelineDescriptor;
pipelineDescriptor.layout = utils::MakeBasicPipelineLayout(device, &writeBGL);
pipelineDescriptor.computeStage.module = csModule;
pipelineDescriptor.computeStage.entryPoint = "main";
wgpu::ComputePipeline cp = device.CreateComputePipeline(&pipelineDescriptor);
// Set bind group against the same index twice. The second one overwrites the first one.
// Then no buffer is used as both read and write in the same pass. But the overwritten
// bind group still take effect.
{
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
pass.SetBindGroup(0, writeBG0);
pass.SetBindGroup(1, readBG0);
pass.SetBindGroup(1, readBG1);
pass.SetPipeline(cp);
pass.Dispatch(1);
pass.EndPass();
// TODO (yunchao.he@intel.com): add buffer usage tracking for compute
// ASSERT_DEVICE_ERROR(encoder.Finish());
encoder.Finish();
}
// Set bind group against the same index twice. The second one overwrites the first one.
// Then buffer0 is used as both read and write in the same pass
{
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
pass.SetBindGroup(0, writeBG0);
pass.SetBindGroup(1, readBG1);
pass.SetBindGroup(1, readBG0);
pass.SetPipeline(cp);
pass.Dispatch(1);
pass.EndPass();
// TODO (yunchao.he@intel.com): add buffer usage tracking for compute
// ASSERT_DEVICE_ERROR(encoder.Finish());
encoder.Finish();
}
}
} }
// Test that it is invalid to have resource usage conflicts even when all bindings are not // Test that it is invalid to have resource usage conflicts even when all bindings are not
@ -653,8 +715,7 @@ namespace {
{ {
// Create a texture that will be used as both a sampled texture and a render target // Create a texture that will be used as both a sampled texture and a render target
wgpu::Texture texture = wgpu::Texture texture =
CreateTexture(wgpu::TextureUsage::Sampled | wgpu::TextureUsage::OutputAttachment, CreateTexture(wgpu::TextureUsage::Sampled | wgpu::TextureUsage::OutputAttachment);
wgpu::TextureFormat::RGBA8Unorm);
wgpu::TextureView view = texture.CreateView(); wgpu::TextureView view = texture.CreateView();
// Create the bind group to use the texture as sampled // Create the bind group to use the texture as sampled
@ -684,12 +745,10 @@ namespace {
{ {
// Create a texture that will be used both as a sampled texture and a render target // Create a texture that will be used both as a sampled texture and a render target
wgpu::Texture t0 = wgpu::Texture t0 =
CreateTexture(wgpu::TextureUsage::Sampled | wgpu::TextureUsage::OutputAttachment, CreateTexture(wgpu::TextureUsage::Sampled | wgpu::TextureUsage::OutputAttachment);
wgpu::TextureFormat::RGBA8Unorm);
wgpu::TextureView v0 = t0.CreateView(); wgpu::TextureView v0 = t0.CreateView();
wgpu::Texture t1 = wgpu::Texture t1 =
CreateTexture(wgpu::TextureUsage::Sampled | wgpu::TextureUsage::OutputAttachment, CreateTexture(wgpu::TextureUsage::Sampled | wgpu::TextureUsage::OutputAttachment);
wgpu::TextureFormat::RGBA8Unorm);
wgpu::TextureView v1 = t1.CreateView(); wgpu::TextureView v1 = t1.CreateView();
// Create the bind group to use the texture as sampled // Create the bind group to use the texture as sampled
@ -731,12 +790,10 @@ namespace {
// allowed. // allowed.
TEST_F(ResourceUsageTrackingTest, TextureCopyAndTextureUsageInPass) { TEST_F(ResourceUsageTrackingTest, TextureCopyAndTextureUsageInPass) {
// Create textures that will be used as both a sampled texture and a render target // Create textures that will be used as both a sampled texture and a render target
wgpu::Texture texture0 = wgpu::Texture texture0 = CreateTexture(wgpu::TextureUsage::CopySrc);
CreateTexture(wgpu::TextureUsage::CopySrc, wgpu::TextureFormat::RGBA8Unorm);
wgpu::Texture texture1 = wgpu::Texture texture1 =
CreateTexture(wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::Sampled | CreateTexture(wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::Sampled |
wgpu::TextureUsage::OutputAttachment, wgpu::TextureUsage::OutputAttachment);
wgpu::TextureFormat::RGBA8Unorm);
wgpu::TextureView view0 = texture0.CreateView(); wgpu::TextureView view0 = texture0.CreateView();
wgpu::TextureView view1 = texture1.CreateView(); wgpu::TextureView view1 = texture1.CreateView();
@ -777,12 +834,10 @@ namespace {
{ {
// Create textures that will be used as both a sampled texture and a render target // Create textures that will be used as both a sampled texture and a render target
wgpu::Texture texture0 = wgpu::Texture texture0 =
CreateTexture(wgpu::TextureUsage::Sampled | wgpu::TextureUsage::OutputAttachment, CreateTexture(wgpu::TextureUsage::Sampled | wgpu::TextureUsage::OutputAttachment);
wgpu::TextureFormat::RGBA8Unorm);
wgpu::TextureView view0 = texture0.CreateView(); wgpu::TextureView view0 = texture0.CreateView();
wgpu::Texture texture1 = wgpu::Texture texture1 =
CreateTexture(wgpu::TextureUsage::Sampled | wgpu::TextureUsage::OutputAttachment, CreateTexture(wgpu::TextureUsage::Sampled | wgpu::TextureUsage::OutputAttachment);
wgpu::TextureFormat::RGBA8Unorm);
wgpu::TextureView view1 = texture1.CreateView(); wgpu::TextureView view1 = texture1.CreateView();
// Create the bind group to use the texture as sampled // Create the bind group to use the texture as sampled
@ -818,23 +873,87 @@ namespace {
} }
} }
// TODO (yunchao.he@intel.com) Test compute pass. Test code is ready, but it depends on // Test compute pass
// writeonly storage buffer support. {
// Create a texture that will be used both as storage texture
wgpu::Texture texture0 = CreateTexture(wgpu::TextureUsage::Storage);
wgpu::TextureView view0 = texture0.CreateView();
wgpu::Texture texture1 = CreateTexture(wgpu::TextureUsage::Storage);
wgpu::TextureView view1 = texture1.CreateView();
// Create the bind group to use the texture as readonly and writeonly bindings
wgpu::BindGroupLayout writeBGL = utils::MakeBindGroupLayout(
device, {{0, wgpu::ShaderStage::Compute, wgpu::BindingType::WriteonlyStorageTexture,
false, false, wgpu::TextureViewDimension::Undefined,
wgpu::TextureViewDimension::Undefined, wgpu::TextureComponentType::Float,
kFormat}});
wgpu::BindGroupLayout readBGL = utils::MakeBindGroupLayout(
device, {{0, wgpu::ShaderStage::Compute, wgpu::BindingType::ReadonlyStorageTexture,
false, false, wgpu::TextureViewDimension::Undefined,
wgpu::TextureViewDimension::Undefined, wgpu::TextureComponentType::Float,
kFormat}});
wgpu::BindGroup writeBG0 = utils::MakeBindGroup(device, writeBGL, {{0, view0}});
wgpu::BindGroup readBG0 = utils::MakeBindGroup(device, readBGL, {{0, view0}});
wgpu::BindGroup readBG1 = utils::MakeBindGroup(device, readBGL, {{0, view1}});
// Create a passthrough compute pipeline
wgpu::ShaderModule csModule =
utils::CreateShaderModule(device, utils::SingleShaderStage::Compute, R"(
#version 450
void main() {
})");
wgpu::ComputePipelineDescriptor pipelineDescriptor;
pipelineDescriptor.layout = utils::MakeBasicPipelineLayout(device, &writeBGL);
pipelineDescriptor.computeStage.module = csModule;
pipelineDescriptor.computeStage.entryPoint = "main";
wgpu::ComputePipeline cp = device.CreateComputePipeline(&pipelineDescriptor);
// Set bind group on the same index twice. The second one overwrites the first one.
// No texture is used as both readonly and writeonly storage in the same pass. But the
// overwritten texture still take effect during resource tracking.
{
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
pass.SetBindGroup(0, writeBG0);
pass.SetBindGroup(1, readBG0);
pass.SetBindGroup(1, readBG1);
pass.SetPipeline(cp);
pass.Dispatch(1);
pass.EndPass();
// TODO (yunchao.he@intel.com): add texture usage tracking for compute
// ASSERT_DEVICE_ERROR(encoder.Finish());
encoder.Finish();
}
// Set bind group on the same index twice. The second one overwrites the first one.
// texture0 is used as both writeonly and readonly storage in the same pass.
{
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
pass.SetBindGroup(0, writeBG0);
pass.SetBindGroup(1, readBG1);
pass.SetBindGroup(1, readBG0);
pass.SetPipeline(cp);
pass.Dispatch(1);
pass.EndPass();
// TODO (yunchao.he@intel.com): add texture usage tracking for compute
// ASSERT_DEVICE_ERROR(encoder.Finish());
encoder.Finish();
}
}
} }
// TODO (yunchao.he@intel.com): Test that all unused bindings bindGroup still take effect for // TODO (yunchao.he@intel.com): Test that all unused bindings bindGroup still take effect for
// resource tracking. Test code is ready, but it depends on writeonly storage buffer support // resource tracking. Test code is ready, but it depends on writeonly storage buffer support
// TODO (yunchao.he@intel.com): // TODO (yunchao.he@intel.com):
// 1. Add tests for overritten tests: // * useless bindings in bind groups. For example, a bind group includes bindings for compute
// 1) multiple SetBindGroup on the same index
// 2) multiple SetVertexBuffer on the same index
// 3) multiple SetIndexBuffer
// 2. useless bindings in bind groups. For example, a bind group includes bindings for compute
// stage, but the bind group is used in render pass. // stage, but the bind group is used in render pass.
// 3. more read write tracking tests for texture which need readonly storage texture and // * more read write tracking tests for texture which need readonly storage texture and
// writeonly storage texture support // writeonly storage texture support
// 4. resource write and read dependency // * resource write and read dependency
// 1) across passes (render + render, compute + compute, compute and render mixed) is valid // 1) across passes (render + render, compute + compute, compute and render mixed) is valid
// 2) across draws/dispatches is invalid // 2) across draws/dispatches is invalid