OpenGL: Unconditionally set glFrontFace

Previously glFrontFace was called only if some cull mode was set. This
was incorrect because the front face also influences whether a triangle
uses stencilFront or stencilBack.

Because OpenGL default to GL_CCW (which with the Y-flip is the inverse
of wgpu::FrontFace::CCW that's default in the descriptor), if
stencilFront != stencilBack and cull mode is none, then the incorrect
stencil face descriptor was used.

Also adds a regression test for this issue.

Bug: dawn:508
Change-Id: I00d93bda6d4f030cf9db472a9f2b0deefc72707f
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/26880
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
Corentin Wallez 2020-08-18 12:30:06 +00:00 committed by Commit Bot service account
parent d95180dede
commit 7268e7d36f
2 changed files with 18 additions and 4 deletions

View File

@ -43,15 +43,16 @@ namespace dawn_native { namespace opengl {
void ApplyFrontFaceAndCulling(const OpenGLFunctions& gl, void ApplyFrontFaceAndCulling(const OpenGLFunctions& gl,
wgpu::FrontFace face, wgpu::FrontFace face,
wgpu::CullMode mode) { wgpu::CullMode mode) {
if (mode == wgpu::CullMode::None) {
gl.Disable(GL_CULL_FACE);
} else {
gl.Enable(GL_CULL_FACE);
// Note that we invert winding direction in OpenGL. Because Y axis is up in OpenGL, // Note that we invert winding direction in OpenGL. Because Y axis is up in OpenGL,
// which is different from WebGPU and other backends (Y axis is down). // which is different from WebGPU and other backends (Y axis is down).
GLenum direction = (face == wgpu::FrontFace::CCW) ? GL_CW : GL_CCW; GLenum direction = (face == wgpu::FrontFace::CCW) ? GL_CW : GL_CCW;
gl.FrontFace(direction); gl.FrontFace(direction);
if (mode == wgpu::CullMode::None) {
gl.Disable(GL_CULL_FACE);
} else {
gl.Enable(GL_CULL_FACE);
GLenum cullMode = (mode == wgpu::CullMode::Front) ? GL_FRONT : GL_BACK; GLenum cullMode = (mode == wgpu::CullMode::Front) ? GL_FRONT : GL_BACK;
gl.CullFace(cullMode); gl.CullFace(cullMode);
} }

View File

@ -85,6 +85,7 @@ class DepthStencilStateTest : public DawnTest {
RGBA8 color; RGBA8 color;
float depth; float depth;
uint32_t stencil; uint32_t stencil;
wgpu::FrontFace frontFace = wgpu::FrontFace::CCW;
}; };
// Check whether a depth comparison function works as expected // Check whether a depth comparison function works as expected
@ -288,6 +289,7 @@ class DepthStencilStateTest : public DawnTest {
descriptor.cFragmentStage.module = fsModule; descriptor.cFragmentStage.module = fsModule;
descriptor.cDepthStencilState = test.depthStencilState; descriptor.cDepthStencilState = test.depthStencilState;
descriptor.cDepthStencilState.format = wgpu::TextureFormat::Depth24PlusStencil8; descriptor.cDepthStencilState.format = wgpu::TextureFormat::Depth24PlusStencil8;
descriptor.cRasterizationState.frontFace = test.frontFace;
descriptor.depthStencilState = &descriptor.cDepthStencilState; descriptor.depthStencilState = &descriptor.cDepthStencilState;
wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&descriptor); wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&descriptor);
@ -734,6 +736,17 @@ TEST_P(DepthStencilStateTest, CreatePipelineWithAllFormats) {
} }
} }
// Test that the front and back stencil states are set correctly (and take frontFace into account)
TEST_P(DepthStencilStateTest, StencilFrontAndBackFace) {
wgpu::DepthStencilStateDescriptor state;
state.stencilFront.compare = wgpu::CompareFunction::Always;
state.stencilBack.compare = wgpu::CompareFunction::Never;
// The front facing triangle passes the stencil comparison but the back facing one doesn't.
DoTest({{state, RGBA8::kRed, 0.f, 0u, wgpu::FrontFace::CCW}}, RGBA8::kRed, RGBA8::kZero);
DoTest({{state, RGBA8::kRed, 0.f, 0u, wgpu::FrontFace::CW}}, RGBA8::kZero, RGBA8::kRed);
}
DAWN_INSTANTIATE_TEST(DepthStencilStateTest, DAWN_INSTANTIATE_TEST(DepthStencilStateTest,
D3D12Backend(), D3D12Backend(),
MetalBackend(), MetalBackend(),