Initializing stencil reference for render pass in D3D12

When creating a new render pass in D3D12, call the OMSetStencilRef
to set the stencil reference value to zero.

Bug: dawn:1097
Change-Id: I5dd94691b1b354b601c06a02d3d5fa619d8b58ee
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/63360
Commit-Queue: Jiawei Shao <jiawei.shao@intel.com>
Reviewed-by: Jiawei Shao <jiawei.shao@intel.com>
Reviewed-by: Austin Eng <enga@chromium.org>
This commit is contained in:
Zhaoming Jiang 2021-09-08 02:21:33 +00:00 committed by Dawn LUCI CQ
parent 9e10acee8a
commit c6140d5c95
2 changed files with 87 additions and 6 deletions

View File

@ -1304,6 +1304,8 @@ namespace dawn_native { namespace d3d12 {
static constexpr std::array<float, 4> defaultBlendFactor = {0, 0, 0, 0}; static constexpr std::array<float, 4> defaultBlendFactor = {0, 0, 0, 0};
commandList->OMSetBlendFactor(&defaultBlendFactor[0]); commandList->OMSetBlendFactor(&defaultBlendFactor[0]);
commandList->OMSetStencilRef(0);
} }
RenderPipeline* lastPipeline = nullptr; RenderPipeline* lastPipeline = nullptr;

View File

@ -92,6 +92,7 @@ class DepthStencilStateTest : public DawnTest {
float depth; float depth;
uint32_t stencil; uint32_t stencil;
wgpu::FrontFace frontFace = wgpu::FrontFace::CCW; wgpu::FrontFace frontFace = wgpu::FrontFace::CCW;
bool setStencilReference = true;
}; };
// Check whether a depth comparison function works as expected // Check whether a depth comparison function works as expected
@ -265,7 +266,8 @@ class DepthStencilStateTest : public DawnTest {
// expected colors for the frontfaces and backfaces // expected colors for the frontfaces and backfaces
void DoTest(const std::vector<TestSpec>& testParams, void DoTest(const std::vector<TestSpec>& testParams,
const RGBA8& expectedFront, const RGBA8& expectedFront,
const RGBA8& expectedBack) { const RGBA8& expectedBack,
bool isSingleEncoderMultiplePass = false) {
wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
struct TriangleData { struct TriangleData {
@ -274,11 +276,32 @@ class DepthStencilStateTest : public DawnTest {
}; };
utils::ComboRenderPassDescriptor renderPass({renderTargetView}, depthTextureView); utils::ComboRenderPassDescriptor renderPass({renderTargetView}, depthTextureView);
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass); wgpu::RenderPassEncoder pass;
if (isSingleEncoderMultiplePass) {
// The render pass to clear up the depthTextureView (using LoadOp = clear)
utils::ComboRenderPassDescriptor clearingPass({renderTargetView}, depthTextureView);
// The render pass to do the test with depth and stencil result kept
renderPass.cDepthStencilAttachmentInfo.depthLoadOp = wgpu::LoadOp::Load;
renderPass.cDepthStencilAttachmentInfo.stencilLoadOp = wgpu::LoadOp::Load;
// Clear the depthStencilView at the beginning
{
pass = encoder.BeginRenderPass(&renderPass);
pass.EndPass();
}
} else {
pass = encoder.BeginRenderPass(&renderPass);
}
for (size_t i = 0; i < testParams.size(); ++i) { for (size_t i = 0; i < testParams.size(); ++i) {
const TestSpec& test = testParams[i]; const TestSpec& test = testParams[i];
if (isSingleEncoderMultiplePass) {
pass = encoder.BeginRenderPass(&renderPass);
}
TriangleData data = { TriangleData data = {
{static_cast<float>(test.color.r) / 255.f, static_cast<float>(test.color.g) / 255.f, {static_cast<float>(test.color.r) / 255.f, static_cast<float>(test.color.g) / 255.f,
static_cast<float>(test.color.b) / 255.f}, static_cast<float>(test.color.b) / 255.f},
@ -305,12 +328,21 @@ class DepthStencilStateTest : public DawnTest {
device, pipeline.GetBindGroupLayout(0), {{0, buffer, 0, sizeof(TriangleData)}}); device, pipeline.GetBindGroupLayout(0), {{0, buffer, 0, sizeof(TriangleData)}});
pass.SetPipeline(pipeline); pass.SetPipeline(pipeline);
if (test.setStencilReference) {
pass.SetStencilReference(test.stencil); // Set the stencil reference pass.SetStencilReference(test.stencil); // Set the stencil reference
}
pass.SetBindGroup(0, pass.SetBindGroup(0,
bindGroup); // Set the bind group which contains color and depth data bindGroup); // Set the bind group which contains color and depth data
pass.Draw(6); pass.Draw(6);
}
if (isSingleEncoderMultiplePass) {
pass.EndPass(); pass.EndPass();
}
}
if (!isSingleEncoderMultiplePass) {
pass.EndPass();
}
wgpu::CommandBuffer commands = encoder.Finish(); wgpu::CommandBuffer commands = encoder.Finish();
queue.Submit(1, &commands); queue.Submit(1, &commands);
@ -321,8 +353,10 @@ class DepthStencilStateTest : public DawnTest {
<< "Back face check failed"; << "Back face check failed";
} }
void DoTest(const std::vector<TestSpec>& testParams, const RGBA8& expected) { void DoTest(const std::vector<TestSpec>& testParams,
DoTest(testParams, expected, expected); const RGBA8& expected,
bool isSingleEncoderMultiplePass = false) {
DoTest(testParams, expected, expected, isSingleEncoderMultiplePass);
} }
wgpu::Texture renderTarget; wgpu::Texture renderTarget;
@ -752,6 +786,51 @@ TEST_P(DepthStencilStateTest, StencilFrontAndBackFace) {
DoTest({{state, RGBA8::kRed, 0.f, 0u, wgpu::FrontFace::CW}}, RGBA8::kZero, RGBA8::kRed); DoTest({{state, RGBA8::kRed, 0.f, 0u, wgpu::FrontFace::CW}}, RGBA8::kZero, RGBA8::kRed);
} }
// Test that the depth reference of a new render pass is initialized to default value 0
TEST_P(DepthStencilStateTest, StencilReferenceInitialized) {
wgpu::DepthStencilState stencilAlwaysReplaceState;
stencilAlwaysReplaceState.stencilFront.compare = wgpu::CompareFunction::Always;
stencilAlwaysReplaceState.stencilFront.passOp = wgpu::StencilOperation::Replace;
stencilAlwaysReplaceState.stencilBack.compare = wgpu::CompareFunction::Always;
stencilAlwaysReplaceState.stencilBack.passOp = wgpu::StencilOperation::Replace;
wgpu::DepthStencilState stencilEqualKeepState;
stencilEqualKeepState.stencilFront.compare = wgpu::CompareFunction::Equal;
stencilEqualKeepState.stencilFront.passOp = wgpu::StencilOperation::Keep;
stencilEqualKeepState.stencilBack.compare = wgpu::CompareFunction::Equal;
stencilEqualKeepState.stencilBack.passOp = wgpu::StencilOperation::Keep;
// Test that stencil reference is not inherited
{
// First pass sets the stencil to 0x1, and the second pass tests the stencil
// Only set the stencil reference in the first pass, and test that for other pass it should
// be default value rather than inherited
std::vector<TestSpec> testParams = {
{stencilAlwaysReplaceState, RGBA8::kRed, 0.f, 0x1, wgpu::FrontFace::CCW, true},
{stencilEqualKeepState, RGBA8::kGreen, 0.f, 0x0, wgpu::FrontFace::CCW, false}};
// Since the stencil reference is not inherited, second draw won't pass the stencil test
std::pair<RGBA8, RGBA8> expectation = {RGBA8::kZero, RGBA8::kZero};
DoTest(testParams, expectation.first, expectation.second, true);
}
// Test that stencil reference is initialized as zero for new render pass
{
// First pass sets the stencil to 0x1, the second pass sets the stencil to its default
// value, and the third pass tests if the stencil is zero
std::vector<TestSpec> testParams = {
{stencilAlwaysReplaceState, RGBA8::kRed, 0.f, 0x1, wgpu::FrontFace::CCW, true},
{stencilAlwaysReplaceState, RGBA8::kGreen, 0.f, 0x1, wgpu::FrontFace::CCW, false},
{stencilEqualKeepState, RGBA8::kBlue, 0.f, 0x0, wgpu::FrontFace::CCW, true}};
// The third draw should pass the stencil test since the second pass set it to default zero
std::pair<RGBA8, RGBA8> expectation = {RGBA8::kBlue, RGBA8::kBlue};
DoTest(testParams, expectation.first, expectation.second, true);
}
}
DAWN_INSTANTIATE_TEST(DepthStencilStateTest, DAWN_INSTANTIATE_TEST(DepthStencilStateTest,
D3D12Backend(), D3D12Backend(),
MetalBackend(), MetalBackend(),