Add validation tests for texture resource tracking - 2

This patch adds tests to verify that texture usage tracking is per
each pass for render, and it is per each dispatch for compute.

Bug: dawn:358
Change-Id: I7ed0f470a6457e4cc53b02cd03c3da7d68cbca9a
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/20162
Commit-Queue: Yunchao He <yunchao.he@intel.com>
Reviewed-by: Austin Eng <enga@chromium.org>
This commit is contained in:
Yunchao He 2020-05-04 17:19:19 +00:00 committed by Commit Bot service account
parent 23428ea82f
commit 07328ba0bb
1 changed files with 153 additions and 12 deletions
src/tests/unittests/validation

View File

@ -921,7 +921,7 @@ namespace {
TEST_F(ResourceUsageTrackingTest, TextureWithReadAndWriteUsageInDifferentPasses) { TEST_F(ResourceUsageTrackingTest, TextureWithReadAndWriteUsageInDifferentPasses) {
// Test render pass // Test render pass
{ {
// Create a texture that will be used both as a sampled texture and a render target // Create textures that will be used as both 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::TextureView v0 = t0.CreateView(); wgpu::TextureView v0 = t0.CreateView();
@ -929,17 +929,17 @@ namespace {
CreateTexture(wgpu::TextureUsage::Sampled | wgpu::TextureUsage::OutputAttachment); CreateTexture(wgpu::TextureUsage::Sampled | wgpu::TextureUsage::OutputAttachment);
wgpu::TextureView v1 = t1.CreateView(); wgpu::TextureView v1 = t1.CreateView();
// Create the bind group to use the texture as sampled // Create bind groups to use the texture as sampled
wgpu::BindGroupLayout bgl = utils::MakeBindGroupLayout( wgpu::BindGroupLayout bgl = utils::MakeBindGroupLayout(
device, {{0, wgpu::ShaderStage::Vertex, wgpu::BindingType::SampledTexture}}); device, {{0, wgpu::ShaderStage::Vertex, wgpu::BindingType::SampledTexture}});
wgpu::BindGroup bg0 = utils::MakeBindGroup(device, bgl, {{0, v0}}); wgpu::BindGroup bg0 = utils::MakeBindGroup(device, bgl, {{0, v0}});
wgpu::BindGroup bg1 = utils::MakeBindGroup(device, bgl, {{0, v1}}); wgpu::BindGroup bg1 = utils::MakeBindGroup(device, bgl, {{0, v1}});
// Create the render pass that will use the texture as an output attachment // Create render passes that will use the textures as output attachments
utils::ComboRenderPassDescriptor renderPass0({v1}); utils::ComboRenderPassDescriptor renderPass0({v1});
utils::ComboRenderPassDescriptor renderPass1({v0}); utils::ComboRenderPassDescriptor renderPass1({v0});
// Use the texture as both sampeld and output attachment in different passes // Use the textures as both sampled and output attachments in different passes
wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
wgpu::RenderPassEncoder pass0 = encoder.BeginRenderPass(&renderPass0); wgpu::RenderPassEncoder pass0 = encoder.BeginRenderPass(&renderPass0);
@ -953,16 +953,157 @@ namespace {
encoder.Finish(); encoder.Finish();
} }
// TODO (yunchao.he@intel.com) Test compute pass. Test code is ready, but it depends on // Test compute pass
// writeonly storage texture support. {
// TODO (yunchao.he@intel.com) Test compute pass and render pass mixed together with // Create a texture that will be used storage texture
// resource dependency. Test code is ready, but it depends on writeonly storage texture wgpu::Texture texture = CreateTexture(wgpu::TextureUsage::Storage);
// support. wgpu::TextureView view = texture.CreateView();
// Create bind groups to use the texture as readonly and writeonly bindings
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::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::BindGroup readBG = utils::MakeBindGroup(device, readBGL, {{0, view}});
wgpu::BindGroup writeBG = utils::MakeBindGroup(device, writeBGL, {{0, view}});
// Use the textures as both readonly and writeonly storages in different passes
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
wgpu::ComputePassEncoder pass0 = encoder.BeginComputePass();
pass0.SetBindGroup(0, readBG);
pass0.EndPass();
wgpu::ComputePassEncoder pass1 = encoder.BeginComputePass();
pass1.SetBindGroup(0, writeBG);
pass1.EndPass();
encoder.Finish();
}
// Test compute pass and render pass mixed together with resource dependency
{
// Create a texture that will be used a storage texture
wgpu::Texture texture = CreateTexture(wgpu::TextureUsage::Storage);
wgpu::TextureView view = texture.CreateView();
// Create bind groups 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::Fragment, wgpu::BindingType::ReadonlyStorageTexture,
false, false, wgpu::TextureViewDimension::Undefined,
wgpu::TextureViewDimension::Undefined, wgpu::TextureComponentType::Float,
kFormat}});
wgpu::BindGroup writeBG = utils::MakeBindGroup(device, writeBGL, {{0, view}});
wgpu::BindGroup readBG = utils::MakeBindGroup(device, readBGL, {{0, view}});
// Use the texture as writeonly and readonly storage in compute pass and render
// pass respectively
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
wgpu::ComputePassEncoder pass0 = encoder.BeginComputePass();
pass0.SetBindGroup(0, writeBG);
pass0.EndPass();
DummyRenderPass dummyRenderPass(device);
wgpu::RenderPassEncoder pass1 = encoder.BeginRenderPass(&dummyRenderPass);
pass1.SetBindGroup(0, readBG);
pass1.EndPass();
encoder.Finish();
}
} }
// TODO (yunchao.he@intel.com) Test that using the same texture as both readable and writable in // Test that it is invalid to use the same texture as both readable and writable in different
// the different draws/dispatches is disallowed Test code is ready, but it depends on writeonly // draws in a single render pass. But it is valid in different dispatches in a single compute
// storage texture support. // pass.
TEST_F(ResourceUsageTrackingTest, TextureWithReadAndWriteUsageOnDifferentDrawsOrDispatches) {
// Create a texture that will be used both as a sampled texture and a storage texture
wgpu::Texture texture =
CreateTexture(wgpu::TextureUsage::Sampled | wgpu::TextureUsage::Storage);
wgpu::TextureView view = texture.CreateView();
// Test render pass
{
// Create bind groups to use the texture as sampled and writeonly storage bindings
wgpu::BindGroupLayout sampledBGL = utils::MakeBindGroupLayout(
device, {{0, wgpu::ShaderStage::Fragment, wgpu::BindingType::SampledTexture}});
wgpu::BindGroupLayout writeBGL = utils::MakeBindGroupLayout(
device,
{{0, wgpu::ShaderStage::Fragment, wgpu::BindingType::WriteonlyStorageTexture, false,
false, wgpu::TextureViewDimension::Undefined,
wgpu::TextureViewDimension::Undefined, wgpu::TextureComponentType::Float,
kFormat}});
wgpu::BindGroup sampledBG = utils::MakeBindGroup(device, sampledBGL, {{0, view}});
wgpu::BindGroup writeBG = utils::MakeBindGroup(device, writeBGL, {{0, view}});
// Create a no-op render pipeline. Note that bind groups can have more bindings
// than pipeline.
wgpu::RenderPipeline rp = CreateNoOpRenderPipeline();
// It is not allowed to use the same texture as both readable and writable in different
// draws within the same render pass.
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
DummyRenderPass dummyRenderPass(device);
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&dummyRenderPass);
pass.SetPipeline(rp);
pass.SetBindGroup(0, sampledBG);
pass.Draw(3);
pass.SetBindGroup(0, writeBG);
pass.Draw(3);
pass.EndPass();
ASSERT_DEVICE_ERROR(encoder.Finish());
}
// Test compute pass
{
// Create bind groups to use the texture as readonly and writeonly storage bindings
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::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::BindGroup readBG = utils::MakeBindGroup(device, readBGL, {{0, view}});
wgpu::BindGroup writeBG = utils::MakeBindGroup(device, writeBGL, {{0, view}});
// Create a no-op compute pipeline. Note that bind groups can have more bindings
// than pipeline.
wgpu::ComputePipeline cp = CreateNoOpComputePipeline();
// It is valid to use the same texture as both readable and writable in different
// dispatches within the same compute pass.
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
pass.SetPipeline(cp);
pass.SetBindGroup(0, readBG);
pass.Dispatch(1);
pass.SetBindGroup(0, writeBG);
pass.Dispatch(1);
pass.EndPass();
encoder.Finish();
}
}
// Test that using a single texture as copy src/dst and writable/readable usage in pass is // Test that using a single texture as copy src/dst and writable/readable usage in pass is
// allowed. // allowed.