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:
parent
23428ea82f
commit
07328ba0bb
src/tests/unittests/validation
|
@ -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.
|
||||||
|
|
Loading…
Reference in New Issue