Add end2end test for readonly stencil attachment on D3D12
The new test can pass without further implementation changes on D3D12 because: - stencil aspect shares the same resource state with depth: D3D12_RESOURCE_STATE_DEPTH_READ. - stencil flag (D3D12_DSV_FLAG_READ_ONLY_STENCIL) for readonly DepthStencilView descriptor has already been added into Dawn in previous patch. Bug: dawn:485 Change-Id: I87aaaac0f01744d3533f2d97f987ee23ad0a1f53 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/69300 Commit-Queue: Yunchao He <yunchao.he@intel.com> Reviewed-by: Austin Eng <enga@chromium.org>
This commit is contained in:
parent
7065c21fbb
commit
de014a8d0a
|
@ -28,7 +28,13 @@ namespace {
|
||||||
class ReadOnlyDepthStencilAttachmentTests
|
class ReadOnlyDepthStencilAttachmentTests
|
||||||
: public DawnTestWithParams<ReadOnlyDepthStencilAttachmentTestsParams> {
|
: public DawnTestWithParams<ReadOnlyDepthStencilAttachmentTestsParams> {
|
||||||
protected:
|
protected:
|
||||||
wgpu::RenderPipeline CreateRenderPipeline(wgpu::TextureFormat format) {
|
struct DepthStencilValues {
|
||||||
|
float depthInitValue;
|
||||||
|
uint32_t stencilInitValue;
|
||||||
|
uint32_t stencilRefValue;
|
||||||
|
};
|
||||||
|
wgpu::RenderPipeline CreateRenderPipeline(wgpu::TextureAspect aspect,
|
||||||
|
wgpu::TextureFormat format) {
|
||||||
utils::ComboRenderPipelineDescriptor pipelineDescriptor;
|
utils::ComboRenderPipelineDescriptor pipelineDescriptor;
|
||||||
|
|
||||||
// Draw a rectangle via two triangles. The depth value of the top of the rectangle is 0.4.
|
// Draw a rectangle via two triangles. The depth value of the top of the rectangle is 0.4.
|
||||||
|
@ -50,6 +56,7 @@ class ReadOnlyDepthStencilAttachmentTests
|
||||||
return vec4<f32>(pos[VertexIndex], 1.0);
|
return vec4<f32>(pos[VertexIndex], 1.0);
|
||||||
})");
|
})");
|
||||||
|
|
||||||
|
if (aspect == wgpu::TextureAspect::DepthOnly) {
|
||||||
pipelineDescriptor.cFragment.module = utils::CreateShaderModule(device, R"(
|
pipelineDescriptor.cFragment.module = utils::CreateShaderModule(device, R"(
|
||||||
[[group(0), binding(0)]] var samp : sampler;
|
[[group(0), binding(0)]] var samp : sampler;
|
||||||
[[group(0), binding(1)]] var tex : texture_depth_2d;
|
[[group(0), binding(1)]] var tex : texture_depth_2d;
|
||||||
|
@ -62,6 +69,21 @@ class ReadOnlyDepthStencilAttachmentTests
|
||||||
// Enable depth test. But depth write is not enabled.
|
// Enable depth test. But depth write is not enabled.
|
||||||
wgpu::DepthStencilState* depthStencil = pipelineDescriptor.EnableDepthStencil(format);
|
wgpu::DepthStencilState* depthStencil = pipelineDescriptor.EnableDepthStencil(format);
|
||||||
depthStencil->depthCompare = wgpu::CompareFunction::LessEqual;
|
depthStencil->depthCompare = wgpu::CompareFunction::LessEqual;
|
||||||
|
} else {
|
||||||
|
ASSERT(aspect == wgpu::TextureAspect::StencilOnly);
|
||||||
|
pipelineDescriptor.cFragment.module = utils::CreateShaderModule(device, R"(
|
||||||
|
[[group(0), binding(0)]] var tex : texture_2d<u32>;
|
||||||
|
|
||||||
|
[[stage(fragment)]]
|
||||||
|
fn main([[builtin(position)]] FragCoord : vec4<f32>) -> [[location(0)]] vec4<f32> {
|
||||||
|
var texel = textureLoad(tex, vec2<i32>(FragCoord.xy), 0);
|
||||||
|
return vec4<f32>(f32(texel[0]) / 255.0, 0.0, 0.0, 0.0);
|
||||||
|
})");
|
||||||
|
|
||||||
|
// Enable stencil test. But stencil write is not enabled.
|
||||||
|
wgpu::DepthStencilState* depthStencil = pipelineDescriptor.EnableDepthStencil(format);
|
||||||
|
depthStencil->stencilFront.compare = wgpu::CompareFunction::LessEqual;
|
||||||
|
}
|
||||||
|
|
||||||
return device.CreateRenderPipeline(&pipelineDescriptor);
|
return device.CreateRenderPipeline(&pipelineDescriptor);
|
||||||
}
|
}
|
||||||
|
@ -74,48 +96,62 @@ class ReadOnlyDepthStencilAttachmentTests
|
||||||
return device.CreateTexture(&descriptor);
|
return device.CreateTexture(&descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestDepth(wgpu::TextureFormat format, wgpu::Texture colorTexture) {
|
void DoTest(wgpu::TextureAspect aspect,
|
||||||
|
wgpu::TextureFormat format,
|
||||||
|
wgpu::Texture colorTexture,
|
||||||
|
DepthStencilValues* values) {
|
||||||
wgpu::Texture depthStencilTexture = CreateTexture(
|
wgpu::Texture depthStencilTexture = CreateTexture(
|
||||||
format, wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::TextureBinding);
|
format, wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::TextureBinding);
|
||||||
|
|
||||||
// Note that we can only select one single aspect for texture view used in pipeline.
|
|
||||||
wgpu::TextureViewDescriptor viewDesc = {};
|
|
||||||
viewDesc.aspect = wgpu::TextureAspect::DepthOnly;
|
|
||||||
wgpu::TextureView depthStencilViewInPipeline = depthStencilTexture.CreateView(&viewDesc);
|
|
||||||
|
|
||||||
wgpu::Sampler sampler = device.CreateSampler();
|
|
||||||
|
|
||||||
wgpu::RenderPipeline pipeline = CreateRenderPipeline(format);
|
|
||||||
wgpu::BindGroup bindGroup =
|
|
||||||
utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0),
|
|
||||||
{{0, sampler}, {1, depthStencilViewInPipeline}});
|
|
||||||
wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
|
wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
|
||||||
|
|
||||||
// Create a render pass to initialize the depth attachment.
|
|
||||||
// Note that we must encompass all aspects for texture view used in attachment.
|
// Note that we must encompass all aspects for texture view used in attachment.
|
||||||
wgpu::TextureView depthStencilViewInAttachment = depthStencilTexture.CreateView();
|
wgpu::TextureView depthStencilViewInAttachment = depthStencilTexture.CreateView();
|
||||||
utils::ComboRenderPassDescriptor passDescriptorInit({}, depthStencilViewInAttachment);
|
utils::ComboRenderPassDescriptor passDescriptorInit({}, depthStencilViewInAttachment);
|
||||||
passDescriptorInit.cDepthStencilAttachmentInfo.clearDepth = 0.2;
|
if (aspect == wgpu::TextureAspect::DepthOnly) {
|
||||||
|
passDescriptorInit.cDepthStencilAttachmentInfo.clearDepth = values->depthInitValue;
|
||||||
|
} else {
|
||||||
|
ASSERT(aspect == wgpu::TextureAspect::StencilOnly);
|
||||||
|
passDescriptorInit.cDepthStencilAttachmentInfo.clearStencil = values->stencilInitValue;
|
||||||
|
}
|
||||||
wgpu::RenderPassEncoder passInit = commandEncoder.BeginRenderPass(&passDescriptorInit);
|
wgpu::RenderPassEncoder passInit = commandEncoder.BeginRenderPass(&passDescriptorInit);
|
||||||
passInit.EndPass();
|
passInit.EndPass();
|
||||||
|
|
||||||
// Create a render pass with readonly depth attachment. The readonly depth attachment
|
// Note that we can only select one single aspect for texture view used in bind group.
|
||||||
// has already been initialized. The pipeline in this render pass will sample from the
|
wgpu::TextureViewDescriptor viewDesc = {};
|
||||||
// depth attachment. The pipeline will read from the depth attachment to do depth test too.
|
viewDesc.aspect = aspect;
|
||||||
|
wgpu::TextureView depthStencilViewInBindGroup = depthStencilTexture.CreateView(&viewDesc);
|
||||||
|
|
||||||
|
// Create a render pass to initialize the depth/stencil attachment.
|
||||||
utils::ComboRenderPassDescriptor passDescriptor({colorTexture.CreateView()},
|
utils::ComboRenderPassDescriptor passDescriptor({colorTexture.CreateView()},
|
||||||
depthStencilViewInAttachment);
|
depthStencilViewInAttachment);
|
||||||
|
// Set both aspects to readonly. We have to do this if the format has both aspects, or
|
||||||
|
// it doesn't impact anything if the format has only one aspect.
|
||||||
passDescriptor.cDepthStencilAttachmentInfo.depthReadOnly = true;
|
passDescriptor.cDepthStencilAttachmentInfo.depthReadOnly = true;
|
||||||
passDescriptor.cDepthStencilAttachmentInfo.depthLoadOp = wgpu::LoadOp::Load;
|
passDescriptor.cDepthStencilAttachmentInfo.depthLoadOp = wgpu::LoadOp::Load;
|
||||||
passDescriptor.cDepthStencilAttachmentInfo.depthStoreOp = wgpu::StoreOp::Store;
|
passDescriptor.cDepthStencilAttachmentInfo.depthStoreOp = wgpu::StoreOp::Store;
|
||||||
// Set stencilReadOnly if the format has both depth and stencil aspects.
|
|
||||||
if (format == wgpu::TextureFormat::Depth24PlusStencil8) {
|
|
||||||
passDescriptor.cDepthStencilAttachmentInfo.stencilReadOnly = true;
|
passDescriptor.cDepthStencilAttachmentInfo.stencilReadOnly = true;
|
||||||
passDescriptor.cDepthStencilAttachmentInfo.stencilLoadOp = wgpu::LoadOp::Load;
|
passDescriptor.cDepthStencilAttachmentInfo.stencilLoadOp = wgpu::LoadOp::Load;
|
||||||
passDescriptor.cDepthStencilAttachmentInfo.stencilStoreOp = wgpu::StoreOp::Store;
|
passDescriptor.cDepthStencilAttachmentInfo.stencilStoreOp = wgpu::StoreOp::Store;
|
||||||
}
|
|
||||||
|
// Create a render pass with readonly depth/stencil attachment. The attachment has already
|
||||||
|
// been initialized. The pipeline in this render pass will sample from the attachment.
|
||||||
|
// The pipeline will read from the attachment to do depth/stencil test too.
|
||||||
wgpu::RenderPassEncoder pass = commandEncoder.BeginRenderPass(&passDescriptor);
|
wgpu::RenderPassEncoder pass = commandEncoder.BeginRenderPass(&passDescriptor);
|
||||||
|
wgpu::RenderPipeline pipeline = CreateRenderPipeline(aspect, format);
|
||||||
pass.SetPipeline(pipeline);
|
pass.SetPipeline(pipeline);
|
||||||
|
if (aspect == wgpu::TextureAspect::DepthOnly) {
|
||||||
|
wgpu::BindGroup bindGroup = utils::MakeBindGroup(
|
||||||
|
device, pipeline.GetBindGroupLayout(0),
|
||||||
|
{{0, device.CreateSampler()}, {1, depthStencilViewInBindGroup}});
|
||||||
pass.SetBindGroup(0, bindGroup);
|
pass.SetBindGroup(0, bindGroup);
|
||||||
|
} else {
|
||||||
|
ASSERT(aspect == wgpu::TextureAspect::StencilOnly);
|
||||||
|
wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0),
|
||||||
|
{{0, depthStencilViewInBindGroup}});
|
||||||
|
pass.SetBindGroup(0, bindGroup);
|
||||||
|
pass.SetStencilReference(values->stencilRefValue);
|
||||||
|
}
|
||||||
pass.Draw(6);
|
pass.Draw(6);
|
||||||
pass.EndPass();
|
pass.EndPass();
|
||||||
|
|
||||||
|
@ -124,13 +160,18 @@ class ReadOnlyDepthStencilAttachmentTests
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_P(ReadOnlyDepthStencilAttachmentTests, Depth) {
|
class ReadOnlyDepthAttachmentTests : public ReadOnlyDepthStencilAttachmentTests {};
|
||||||
|
|
||||||
|
TEST_P(ReadOnlyDepthAttachmentTests, Test) {
|
||||||
wgpu::Texture colorTexture =
|
wgpu::Texture colorTexture =
|
||||||
CreateTexture(wgpu::TextureFormat::RGBA8Unorm,
|
CreateTexture(wgpu::TextureFormat::RGBA8Unorm,
|
||||||
wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc);
|
wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc);
|
||||||
|
|
||||||
wgpu::TextureFormat depthStencilFormat = GetParam().mTextureFormat;
|
wgpu::TextureFormat depthFormat = GetParam().mTextureFormat;
|
||||||
TestDepth(depthStencilFormat, colorTexture);
|
|
||||||
|
DepthStencilValues values;
|
||||||
|
values.depthInitValue = 0.2;
|
||||||
|
DoTest(wgpu::TextureAspect::DepthOnly, depthFormat, colorTexture, &values);
|
||||||
|
|
||||||
// The top part is not rendered by the pipeline. Its color is the default clear color for
|
// The top part is not rendered by the pipeline. Its color is the default clear color for
|
||||||
// color attachment.
|
// color attachment.
|
||||||
|
@ -144,7 +185,37 @@ TEST_P(ReadOnlyDepthStencilAttachmentTests, Depth) {
|
||||||
{kSize, kSize / 2});
|
{kSize, kSize / 2});
|
||||||
}
|
}
|
||||||
|
|
||||||
DAWN_INSTANTIATE_TEST_P(ReadOnlyDepthStencilAttachmentTests,
|
class ReadOnlyStencilAttachmentTests : public ReadOnlyDepthStencilAttachmentTests {};
|
||||||
|
|
||||||
|
TEST_P(ReadOnlyStencilAttachmentTests, Test) {
|
||||||
|
wgpu::Texture colorTexture =
|
||||||
|
CreateTexture(wgpu::TextureFormat::RGBA8Unorm,
|
||||||
|
wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc);
|
||||||
|
|
||||||
|
wgpu::TextureFormat stencilFormat = GetParam().mTextureFormat;
|
||||||
|
|
||||||
|
DepthStencilValues values;
|
||||||
|
values.stencilInitValue = 3;
|
||||||
|
values.stencilRefValue = 2;
|
||||||
|
// stencilRefValue < stencilValue (stencilInitValue), so stencil test passes. The pipeline
|
||||||
|
// samples from stencil buffer and writes into color buffer.
|
||||||
|
DoTest(wgpu::TextureAspect::StencilOnly, stencilFormat, colorTexture, &values);
|
||||||
|
const std::vector<RGBA8> kSampledColors(kSize * kSize, {3, 0, 0, 0});
|
||||||
|
EXPECT_TEXTURE_EQ(kSampledColors.data(), colorTexture, {0, 0}, {kSize, kSize});
|
||||||
|
|
||||||
|
values.stencilInitValue = 1;
|
||||||
|
// stencilRefValue > stencilValue (stencilInitValue), so stencil test fails. The pipeline
|
||||||
|
// doesn't change color buffer. Sampled data from stencil buffer is discarded.
|
||||||
|
DoTest(wgpu::TextureAspect::StencilOnly, stencilFormat, colorTexture, &values);
|
||||||
|
const std::vector<RGBA8> kInitColors(kSize * kSize, {0, 0, 0, 0});
|
||||||
|
EXPECT_TEXTURE_EQ(kInitColors.data(), colorTexture, {0, 0}, {kSize, kSize});
|
||||||
|
}
|
||||||
|
|
||||||
|
DAWN_INSTANTIATE_TEST_P(ReadOnlyDepthAttachmentTests,
|
||||||
{D3D12Backend()},
|
{D3D12Backend()},
|
||||||
std::vector<wgpu::TextureFormat>(utils::kDepthStencilFormats.begin(),
|
std::vector<wgpu::TextureFormat>(utils::kDepthFormats.begin(),
|
||||||
utils::kDepthStencilFormats.end()));
|
utils::kDepthFormats.end()));
|
||||||
|
DAWN_INSTANTIATE_TEST_P(ReadOnlyStencilAttachmentTests,
|
||||||
|
{D3D12Backend()},
|
||||||
|
std::vector<wgpu::TextureFormat>(utils::kStencilFormats.begin(),
|
||||||
|
utils::kStencilFormats.end()));
|
||||||
|
|
|
@ -181,11 +181,17 @@ namespace utils {
|
||||||
|
|
||||||
// TODO(dawn:666, 570, 690): Add more depth/stencil formats if Stencil8, Depth16Unorm,
|
// TODO(dawn:666, 570, 690): Add more depth/stencil formats if Stencil8, Depth16Unorm,
|
||||||
// Depth24UnormStencil8, Depth32FloatStencil8 are implemented.
|
// Depth24UnormStencil8, Depth32FloatStencil8 are implemented.
|
||||||
static constexpr std::array<wgpu::TextureFormat, 3> kDepthStencilFormats = {
|
static constexpr std::array<wgpu::TextureFormat, 3> kDepthFormats = {
|
||||||
wgpu::TextureFormat::Depth32Float,
|
wgpu::TextureFormat::Depth32Float,
|
||||||
wgpu::TextureFormat::Depth24Plus,
|
wgpu::TextureFormat::Depth24Plus,
|
||||||
wgpu::TextureFormat::Depth24PlusStencil8,
|
wgpu::TextureFormat::Depth24PlusStencil8,
|
||||||
};
|
};
|
||||||
|
static constexpr std::array<wgpu::TextureFormat, 1> kStencilFormats = {
|
||||||
|
wgpu::TextureFormat::Depth24PlusStencil8,
|
||||||
|
};
|
||||||
|
static constexpr std::array<wgpu::TextureFormat, 1> kDepthAndStencilFormats = {
|
||||||
|
wgpu::TextureFormat::Depth24PlusStencil8,
|
||||||
|
};
|
||||||
|
|
||||||
bool TextureFormatSupportsStorageTexture(wgpu::TextureFormat format);
|
bool TextureFormatSupportsStorageTexture(wgpu::TextureFormat format);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue