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:
parent
9e10acee8a
commit
c6140d5c95
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
pass.SetStencilReference(test.stencil); // Set the stencil reference
|
if (test.setStencilReference) {
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isSingleEncoderMultiplePass) {
|
||||||
|
pass.EndPass();
|
||||||
}
|
}
|
||||||
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(),
|
||||||
|
|
Loading…
Reference in New Issue