Accept StencilFaceState with Undefined when there is not stencil.
The TrivialFrontendDefaults happen after validation in this case so
Undefined value must be handled explicitly. Also moves UsesStencil as a
getter on the RenderPipeline instead of a freestanding function.
Fixed: dawn:2475
Change-Id: Ibaf74421a1ffc33b05088efcc1092f7aa6ddf66c
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/183241
Reviewed-by: Austin Eng <enga@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/dawn/native/RenderPipeline.cpp b/src/dawn/native/RenderPipeline.cpp
index eff2434..212180c 100644
--- a/src/dawn/native/RenderPipeline.cpp
+++ b/src/dawn/native/RenderPipeline.cpp
@@ -273,6 +273,26 @@
return {};
}
+MaybeError ValidateStencilFaceUnused(StencilFaceState face) {
+ DAWN_INVALID_IF((face.compare != wgpu::CompareFunction::Always) &&
+ (face.compare != wgpu::CompareFunction::Undefined),
+ "compare (%s) is defined and not %s.", face.compare,
+ wgpu::CompareFunction::Always);
+ DAWN_INVALID_IF((face.failOp != wgpu::StencilOperation::Keep) &&
+ (face.failOp != wgpu::StencilOperation::Undefined),
+ "failOp (%s) is defined and not %s.", face.failOp,
+ wgpu::StencilOperation::Keep);
+ DAWN_INVALID_IF((face.depthFailOp != wgpu::StencilOperation::Keep) &&
+ (face.depthFailOp != wgpu::StencilOperation::Undefined),
+ "depthFailOp (%s) is defined and not %s.", face.depthFailOp,
+ wgpu::StencilOperation::Keep);
+ DAWN_INVALID_IF((face.passOp != wgpu::StencilOperation::Keep) &&
+ (face.passOp != wgpu::StencilOperation::Undefined),
+ "passOp (%s) is defined and not %s.", face.passOp,
+ wgpu::StencilOperation::Keep);
+ return {};
+}
+
MaybeError ValidateDepthStencilState(const DeviceBase* device,
const DepthStencilState* descriptor) {
DAWN_TRY_CONTEXT(ValidateCompareFunction(descriptor->depthCompare),
@@ -342,10 +362,16 @@
"Depth stencil format (%s) doesn't have depth aspect while depthWriteEnabled (%u) is true.",
descriptor->format, descriptor->depthWriteEnabled);
- DAWN_INVALID_IF(!format->HasStencil() && StencilTestEnabled(descriptor),
- "Depth stencil format (%s) doesn't have stencil aspect while stencil "
- "test or stencil write is enabled.",
- descriptor->format);
+ if (!format->HasStencil()) {
+ DAWN_TRY_CONTEXT(ValidateStencilFaceUnused(descriptor->stencilFront),
+ "validating that stencilFront doesn't use stencil when the depth-stencil "
+ "format (%s) doesn't have a stencil aspect.",
+ descriptor->format);
+ DAWN_TRY_CONTEXT(ValidateStencilFaceUnused(descriptor->stencilBack),
+ "validating that stencilBack doesn't use stencil when the depth-stencil "
+ "format (%s) doesn't have a stencil aspect.",
+ descriptor->format);
+ }
return {};
}
@@ -840,17 +866,6 @@
return stages;
}
-bool StencilTestEnabled(const DepthStencilState* depthStencil) {
- return depthStencil->stencilBack.compare != wgpu::CompareFunction::Always ||
- depthStencil->stencilBack.failOp != wgpu::StencilOperation::Keep ||
- depthStencil->stencilBack.depthFailOp != wgpu::StencilOperation::Keep ||
- depthStencil->stencilBack.passOp != wgpu::StencilOperation::Keep ||
- depthStencil->stencilFront.compare != wgpu::CompareFunction::Always ||
- depthStencil->stencilFront.failOp != wgpu::StencilOperation::Keep ||
- depthStencil->stencilFront.depthFailOp != wgpu::StencilOperation::Keep ||
- depthStencil->stencilFront.passOp != wgpu::StencilOperation::Keep;
-}
-
// RenderPipelineBase
RenderPipelineBase::RenderPipelineBase(DeviceBase* device,
@@ -1078,6 +1093,17 @@
return &mDepthStencil;
}
+bool RenderPipelineBase::UsesStencil() const {
+ return mDepthStencil.stencilBack.compare != wgpu::CompareFunction::Always ||
+ mDepthStencil.stencilBack.failOp != wgpu::StencilOperation::Keep ||
+ mDepthStencil.stencilBack.depthFailOp != wgpu::StencilOperation::Keep ||
+ mDepthStencil.stencilBack.passOp != wgpu::StencilOperation::Keep ||
+ mDepthStencil.stencilFront.compare != wgpu::CompareFunction::Always ||
+ mDepthStencil.stencilFront.failOp != wgpu::StencilOperation::Keep ||
+ mDepthStencil.stencilFront.depthFailOp != wgpu::StencilOperation::Keep ||
+ mDepthStencil.stencilFront.passOp != wgpu::StencilOperation::Keep;
+}
+
wgpu::PrimitiveTopology RenderPipelineBase::GetPrimitiveTopology() const {
DAWN_ASSERT(!IsError());
return mPrimitive.topology;
diff --git a/src/dawn/native/RenderPipeline.h b/src/dawn/native/RenderPipeline.h
index 987eae5..3a460cf 100644
--- a/src/dawn/native/RenderPipeline.h
+++ b/src/dawn/native/RenderPipeline.h
@@ -70,8 +70,6 @@
bool IsStripPrimitiveTopology(wgpu::PrimitiveTopology primitiveTopology);
-bool StencilTestEnabled(const DepthStencilState* depthStencil);
-
struct VertexAttributeInfo {
wgpu::VertexFormat format;
uint64_t offset;
@@ -98,6 +96,7 @@
ObjectType GetType() const override;
+ // Vertex getters
const VertexAttributeMask& GetAttributeLocationsUsed() const;
const VertexAttributeInfo& GetAttribute(VertexAttributeLocation location) const;
const VertexBufferMask& GetVertexBuffersUsed() const;
@@ -106,25 +105,34 @@
const VertexBufferInfo& GetVertexBuffer(VertexBufferSlot slot) const;
uint32_t GetVertexBufferCount() const;
+ // Color attachment getters
const ColorTargetState* GetColorTargetState(ColorAttachmentIndex attachmentSlot) const;
- const DepthStencilState* GetDepthStencilState() const;
+ ColorAttachmentMask GetColorAttachmentsMask() const;
+ wgpu::TextureFormat GetColorAttachmentFormat(ColorAttachmentIndex attachment) const;
+
+ // Primitive getters
wgpu::PrimitiveTopology GetPrimitiveTopology() const;
wgpu::IndexFormat GetStripIndexFormat() const;
wgpu::CullMode GetCullMode() const;
wgpu::FrontFace GetFrontFace() const;
+
+ // Depth-stencil getters
+ const DepthStencilState* GetDepthStencilState() const;
+ bool HasDepthStencilAttachment() const;
+ bool UsesStencil() const;
+ wgpu::TextureFormat GetDepthStencilFormat() const;
bool IsDepthBiasEnabled() const;
int32_t GetDepthBias() const;
float GetDepthBiasSlopeScale() const;
float GetDepthBiasClamp() const;
bool HasUnclippedDepth() const;
- ColorAttachmentMask GetColorAttachmentsMask() const;
- bool HasDepthStencilAttachment() const;
- wgpu::TextureFormat GetColorAttachmentFormat(ColorAttachmentIndex attachment) const;
- wgpu::TextureFormat GetDepthStencilFormat() const;
+ // Multisample getters
uint32_t GetSampleCount() const;
uint32_t GetSampleMask() const;
bool IsAlphaToCoverageEnabled() const;
+
+ // Shader builtin getters
bool WritesDepth() const;
bool WritesStencil() const;
bool UsesFragDepth() const;
diff --git a/src/dawn/native/d3d11/RenderPipelineD3D11.cpp b/src/dawn/native/d3d11/RenderPipelineD3D11.cpp
index 69299d0..03cc7be 100644
--- a/src/dawn/native/d3d11/RenderPipelineD3D11.cpp
+++ b/src/dawn/native/d3d11/RenderPipelineD3D11.cpp
@@ -412,7 +412,7 @@
state->depthWriteEnabled ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
depthStencilDesc.DepthFunc = ToD3D11ComparisonFunc(state->depthCompare);
- depthStencilDesc.StencilEnable = StencilTestEnabled(state) ? TRUE : FALSE;
+ depthStencilDesc.StencilEnable = UsesStencil() ? TRUE : FALSE;
depthStencilDesc.StencilReadMask = static_cast<UINT8>(state->stencilReadMask);
depthStencilDesc.StencilWriteMask = static_cast<UINT8>(state->stencilWriteMask);
diff --git a/src/dawn/native/d3d12/RenderPipelineD3D12.cpp b/src/dawn/native/d3d12/RenderPipelineD3D12.cpp
index 3efdd1d..9c71063 100644
--- a/src/dawn/native/d3d12/RenderPipelineD3D12.cpp
+++ b/src/dawn/native/d3d12/RenderPipelineD3D12.cpp
@@ -288,26 +288,6 @@
return desc;
}
-D3D12_DEPTH_STENCIL_DESC ComputeDepthStencilDesc(const DepthStencilState* descriptor) {
- D3D12_DEPTH_STENCIL_DESC depthStencilDescriptor = {};
- depthStencilDescriptor.DepthEnable =
- (descriptor->depthCompare == wgpu::CompareFunction::Always &&
- !descriptor->depthWriteEnabled)
- ? FALSE
- : TRUE;
- depthStencilDescriptor.DepthWriteMask =
- descriptor->depthWriteEnabled ? D3D12_DEPTH_WRITE_MASK_ALL : D3D12_DEPTH_WRITE_MASK_ZERO;
- depthStencilDescriptor.DepthFunc = ToD3D12ComparisonFunc(descriptor->depthCompare);
-
- depthStencilDescriptor.StencilEnable = StencilTestEnabled(descriptor) ? TRUE : FALSE;
- depthStencilDescriptor.StencilReadMask = static_cast<UINT8>(descriptor->stencilReadMask);
- depthStencilDescriptor.StencilWriteMask = static_cast<UINT8>(descriptor->stencilWriteMask);
-
- depthStencilDescriptor.FrontFace = StencilOpDesc(descriptor->stencilFront);
- depthStencilDescriptor.BackFace = StencilOpDesc(descriptor->stencilBack);
- return depthStencilDescriptor;
-}
-
D3D12_INDEX_BUFFER_STRIP_CUT_VALUE ComputeIndexBufferStripCutValue(
wgpu::PrimitiveTopology primitiveTopology,
wgpu::IndexFormat indexFormat) {
@@ -442,7 +422,7 @@
descriptorD3D12.BlendState.AlphaToCoverageEnable = IsAlphaToCoverageEnabled();
descriptorD3D12.BlendState.IndependentBlendEnable = TRUE;
- descriptorD3D12.DepthStencilState = ComputeDepthStencilDesc(GetDepthStencilState());
+ descriptorD3D12.DepthStencilState = ComputeDepthStencilDesc();
descriptorD3D12.SampleMask = GetSampleMask();
descriptorD3D12.PrimitiveTopologyType = D3D12PrimitiveTopologyType(GetPrimitiveTopology());
@@ -569,4 +549,26 @@
return inputLayoutDescriptor;
}
+D3D12_DEPTH_STENCIL_DESC RenderPipeline::ComputeDepthStencilDesc() {
+ const DepthStencilState* descriptor = GetDepthStencilState();
+
+ D3D12_DEPTH_STENCIL_DESC depthStencilDescriptor = {};
+ depthStencilDescriptor.DepthEnable =
+ (descriptor->depthCompare == wgpu::CompareFunction::Always &&
+ !descriptor->depthWriteEnabled)
+ ? FALSE
+ : TRUE;
+ depthStencilDescriptor.DepthWriteMask =
+ descriptor->depthWriteEnabled ? D3D12_DEPTH_WRITE_MASK_ALL : D3D12_DEPTH_WRITE_MASK_ZERO;
+ depthStencilDescriptor.DepthFunc = ToD3D12ComparisonFunc(descriptor->depthCompare);
+
+ depthStencilDescriptor.StencilEnable = UsesStencil() ? TRUE : FALSE;
+ depthStencilDescriptor.StencilReadMask = static_cast<UINT8>(descriptor->stencilReadMask);
+ depthStencilDescriptor.StencilWriteMask = static_cast<UINT8>(descriptor->stencilWriteMask);
+
+ depthStencilDescriptor.FrontFace = StencilOpDesc(descriptor->stencilFront);
+ depthStencilDescriptor.BackFace = StencilOpDesc(descriptor->stencilBack);
+ return depthStencilDescriptor;
+}
+
} // namespace dawn::native::d3d12
diff --git a/src/dawn/native/d3d12/RenderPipelineD3D12.h b/src/dawn/native/d3d12/RenderPipelineD3D12.h
index 2e4d449..f8b6cfc 100644
--- a/src/dawn/native/d3d12/RenderPipelineD3D12.h
+++ b/src/dawn/native/d3d12/RenderPipelineD3D12.h
@@ -66,6 +66,7 @@
using RenderPipelineBase::RenderPipelineBase;
D3D12_INPUT_LAYOUT_DESC ComputeInputLayout(
std::array<D3D12_INPUT_ELEMENT_DESC, kMaxVertexAttributes>* inputElementDescriptors);
+ D3D12_DEPTH_STENCIL_DESC ComputeDepthStencilDesc();
D3D12_PRIMITIVE_TOPOLOGY mD3d12PrimitiveTopology;
ComPtr<ID3D12PipelineState> mPipelineState;
diff --git a/src/dawn/native/metal/RenderPipelineMTL.h b/src/dawn/native/metal/RenderPipelineMTL.h
index 3021f3b..a9d9d61 100644
--- a/src/dawn/native/metal/RenderPipelineMTL.h
+++ b/src/dawn/native/metal/RenderPipelineMTL.h
@@ -67,6 +67,7 @@
using RenderPipelineBase::RenderPipelineBase;
NSRef<MTLVertexDescriptor> MakeVertexDesc() const;
+ NSRef<MTLDepthStencilDescriptor> MakeDepthStencilDesc();
MTLPrimitiveType mMtlPrimitiveTopology;
MTLWinding mMtlFrontFace;
diff --git a/src/dawn/native/metal/RenderPipelineMTL.mm b/src/dawn/native/metal/RenderPipelineMTL.mm
index 56a58b5..f0ddef5 100644
--- a/src/dawn/native/metal/RenderPipelineMTL.mm
+++ b/src/dawn/native/metal/RenderPipelineMTL.mm
@@ -282,50 +282,6 @@
DAWN_UNREACHABLE();
}
-NSRef<MTLDepthStencilDescriptor> MakeDepthStencilDesc(const DepthStencilState* descriptor) {
- NSRef<MTLDepthStencilDescriptor> mtlDepthStencilDescRef =
- AcquireNSRef([MTLDepthStencilDescriptor new]);
- MTLDepthStencilDescriptor* mtlDepthStencilDescriptor = mtlDepthStencilDescRef.Get();
-
- mtlDepthStencilDescriptor.depthCompareFunction =
- ToMetalCompareFunction(descriptor->depthCompare);
- mtlDepthStencilDescriptor.depthWriteEnabled = descriptor->depthWriteEnabled;
-
- if (StencilTestEnabled(descriptor)) {
- NSRef<MTLStencilDescriptor> backFaceStencilRef = AcquireNSRef([MTLStencilDescriptor new]);
- MTLStencilDescriptor* backFaceStencil = backFaceStencilRef.Get();
- NSRef<MTLStencilDescriptor> frontFaceStencilRef = AcquireNSRef([MTLStencilDescriptor new]);
- MTLStencilDescriptor* frontFaceStencil = frontFaceStencilRef.Get();
-
- backFaceStencil.stencilCompareFunction =
- ToMetalCompareFunction(descriptor->stencilBack.compare);
- backFaceStencil.stencilFailureOperation =
- MetalStencilOperation(descriptor->stencilBack.failOp);
- backFaceStencil.depthFailureOperation =
- MetalStencilOperation(descriptor->stencilBack.depthFailOp);
- backFaceStencil.depthStencilPassOperation =
- MetalStencilOperation(descriptor->stencilBack.passOp);
- backFaceStencil.readMask = descriptor->stencilReadMask;
- backFaceStencil.writeMask = descriptor->stencilWriteMask;
-
- frontFaceStencil.stencilCompareFunction =
- ToMetalCompareFunction(descriptor->stencilFront.compare);
- frontFaceStencil.stencilFailureOperation =
- MetalStencilOperation(descriptor->stencilFront.failOp);
- frontFaceStencil.depthFailureOperation =
- MetalStencilOperation(descriptor->stencilFront.depthFailOp);
- frontFaceStencil.depthStencilPassOperation =
- MetalStencilOperation(descriptor->stencilFront.passOp);
- frontFaceStencil.readMask = descriptor->stencilReadMask;
- frontFaceStencil.writeMask = descriptor->stencilWriteMask;
-
- mtlDepthStencilDescriptor.backFaceStencil = backFaceStencil;
- mtlDepthStencilDescriptor.frontFaceStencil = frontFaceStencil;
- }
-
- return mtlDepthStencilDescRef;
-}
-
MTLWinding MTLFrontFace(wgpu::FrontFace face) {
switch (face) {
case wgpu::FrontFace::CW:
@@ -494,8 +450,7 @@
// Create depth stencil state and cache it, fetch the cached depth stencil state when we
// call setDepthStencilState() for a given render pipeline in CommandEncoder, in order
// to improve performance.
- NSRef<MTLDepthStencilDescriptor> depthStencilDesc =
- MakeDepthStencilDesc(GetDepthStencilState());
+ NSRef<MTLDepthStencilDescriptor> depthStencilDesc = MakeDepthStencilDesc();
mMtlDepthStencilState =
AcquireNSPRef([mtlDevice newDepthStencilStateWithDescriptor:depthStencilDesc.Get()]);
@@ -582,4 +537,50 @@
return AcquireNSRef(mtlVertexDescriptor);
}
+NSRef<MTLDepthStencilDescriptor> RenderPipeline::MakeDepthStencilDesc() {
+ const DepthStencilState* descriptor = GetDepthStencilState();
+
+ NSRef<MTLDepthStencilDescriptor> mtlDepthStencilDescRef =
+ AcquireNSRef([MTLDepthStencilDescriptor new]);
+ MTLDepthStencilDescriptor* mtlDepthStencilDescriptor = mtlDepthStencilDescRef.Get();
+
+ mtlDepthStencilDescriptor.depthCompareFunction =
+ ToMetalCompareFunction(descriptor->depthCompare);
+ mtlDepthStencilDescriptor.depthWriteEnabled = descriptor->depthWriteEnabled;
+
+ if (UsesStencil()) {
+ NSRef<MTLStencilDescriptor> backFaceStencilRef = AcquireNSRef([MTLStencilDescriptor new]);
+ MTLStencilDescriptor* backFaceStencil = backFaceStencilRef.Get();
+ NSRef<MTLStencilDescriptor> frontFaceStencilRef = AcquireNSRef([MTLStencilDescriptor new]);
+ MTLStencilDescriptor* frontFaceStencil = frontFaceStencilRef.Get();
+
+ backFaceStencil.stencilCompareFunction =
+ ToMetalCompareFunction(descriptor->stencilBack.compare);
+ backFaceStencil.stencilFailureOperation =
+ MetalStencilOperation(descriptor->stencilBack.failOp);
+ backFaceStencil.depthFailureOperation =
+ MetalStencilOperation(descriptor->stencilBack.depthFailOp);
+ backFaceStencil.depthStencilPassOperation =
+ MetalStencilOperation(descriptor->stencilBack.passOp);
+ backFaceStencil.readMask = descriptor->stencilReadMask;
+ backFaceStencil.writeMask = descriptor->stencilWriteMask;
+
+ frontFaceStencil.stencilCompareFunction =
+ ToMetalCompareFunction(descriptor->stencilFront.compare);
+ frontFaceStencil.stencilFailureOperation =
+ MetalStencilOperation(descriptor->stencilFront.failOp);
+ frontFaceStencil.depthFailureOperation =
+ MetalStencilOperation(descriptor->stencilFront.depthFailOp);
+ frontFaceStencil.depthStencilPassOperation =
+ MetalStencilOperation(descriptor->stencilFront.passOp);
+ frontFaceStencil.readMask = descriptor->stencilReadMask;
+ frontFaceStencil.writeMask = descriptor->stencilWriteMask;
+
+ mtlDepthStencilDescriptor.backFaceStencil = backFaceStencil;
+ mtlDepthStencilDescriptor.frontFaceStencil = frontFaceStencil;
+ }
+
+ return mtlDepthStencilDescRef;
+}
+
} // namespace dawn::native::metal
diff --git a/src/dawn/native/opengl/RenderPipelineGL.cpp b/src/dawn/native/opengl/RenderPipelineGL.cpp
index 86103f0..a4c2b08 100644
--- a/src/dawn/native/opengl/RenderPipelineGL.cpp
+++ b/src/dawn/native/opengl/RenderPipelineGL.cpp
@@ -200,46 +200,6 @@
DAWN_UNREACHABLE();
}
-void ApplyDepthStencilState(const OpenGLFunctions& gl,
- const DepthStencilState* descriptor,
- PersistentPipelineState* persistentPipelineState) {
- // Depth writes only occur if depth is enabled
- if (descriptor->depthCompare == wgpu::CompareFunction::Always &&
- !descriptor->depthWriteEnabled) {
- gl.Disable(GL_DEPTH_TEST);
- } else {
- gl.Enable(GL_DEPTH_TEST);
- }
-
- if (descriptor->depthWriteEnabled) {
- gl.DepthMask(GL_TRUE);
- } else {
- gl.DepthMask(GL_FALSE);
- }
-
- gl.DepthFunc(ToOpenGLCompareFunction(descriptor->depthCompare));
-
- if (StencilTestEnabled(descriptor)) {
- gl.Enable(GL_STENCIL_TEST);
- } else {
- gl.Disable(GL_STENCIL_TEST);
- }
-
- GLenum backCompareFunction = ToOpenGLCompareFunction(descriptor->stencilBack.compare);
- GLenum frontCompareFunction = ToOpenGLCompareFunction(descriptor->stencilFront.compare);
- persistentPipelineState->SetStencilFuncsAndMask(gl, backCompareFunction, frontCompareFunction,
- descriptor->stencilReadMask);
-
- gl.StencilOpSeparate(GL_BACK, OpenGLStencilOperation(descriptor->stencilBack.failOp),
- OpenGLStencilOperation(descriptor->stencilBack.depthFailOp),
- OpenGLStencilOperation(descriptor->stencilBack.passOp));
- gl.StencilOpSeparate(GL_FRONT, OpenGLStencilOperation(descriptor->stencilFront.failOp),
- OpenGLStencilOperation(descriptor->stencilFront.depthFailOp),
- OpenGLStencilOperation(descriptor->stencilFront.passOp));
-
- gl.StencilMask(descriptor->stencilWriteMask);
-}
-
} // anonymous namespace
// static
@@ -323,7 +283,7 @@
ApplyFrontFaceAndCulling(gl, GetFrontFace(), GetCullMode());
- ApplyDepthStencilState(gl, GetDepthStencilState(), &persistentPipelineState);
+ ApplyDepthStencilState(gl, &persistentPipelineState);
gl.SampleMaski(0, GetSampleMask());
if (IsAlphaToCoverageEnabled()) {
@@ -379,4 +339,45 @@
}
}
+void RenderPipeline::ApplyDepthStencilState(const OpenGLFunctions& gl,
+ PersistentPipelineState* persistentPipelineState) {
+ const DepthStencilState* descriptor = GetDepthStencilState();
+
+ // Depth writes only occur if depth is enabled
+ if (descriptor->depthCompare == wgpu::CompareFunction::Always &&
+ !descriptor->depthWriteEnabled) {
+ gl.Disable(GL_DEPTH_TEST);
+ } else {
+ gl.Enable(GL_DEPTH_TEST);
+ }
+
+ if (descriptor->depthWriteEnabled) {
+ gl.DepthMask(GL_TRUE);
+ } else {
+ gl.DepthMask(GL_FALSE);
+ }
+
+ gl.DepthFunc(ToOpenGLCompareFunction(descriptor->depthCompare));
+
+ if (UsesStencil()) {
+ gl.Enable(GL_STENCIL_TEST);
+ } else {
+ gl.Disable(GL_STENCIL_TEST);
+ }
+
+ GLenum backCompareFunction = ToOpenGLCompareFunction(descriptor->stencilBack.compare);
+ GLenum frontCompareFunction = ToOpenGLCompareFunction(descriptor->stencilFront.compare);
+ persistentPipelineState->SetStencilFuncsAndMask(gl, backCompareFunction, frontCompareFunction,
+ descriptor->stencilReadMask);
+
+ gl.StencilOpSeparate(GL_BACK, OpenGLStencilOperation(descriptor->stencilBack.failOp),
+ OpenGLStencilOperation(descriptor->stencilBack.depthFailOp),
+ OpenGLStencilOperation(descriptor->stencilBack.passOp));
+ gl.StencilOpSeparate(GL_FRONT, OpenGLStencilOperation(descriptor->stencilFront.failOp),
+ OpenGLStencilOperation(descriptor->stencilFront.depthFailOp),
+ OpenGLStencilOperation(descriptor->stencilFront.passOp));
+
+ gl.StencilMask(descriptor->stencilWriteMask);
+}
+
} // namespace dawn::native::opengl
diff --git a/src/dawn/native/opengl/RenderPipelineGL.h b/src/dawn/native/opengl/RenderPipelineGL.h
index 499c3ab..80f411d 100644
--- a/src/dawn/native/opengl/RenderPipelineGL.h
+++ b/src/dawn/native/opengl/RenderPipelineGL.h
@@ -60,6 +60,9 @@
void CreateVAOForVertexState();
+ void ApplyDepthStencilState(const OpenGLFunctions& gl,
+ PersistentPipelineState* persistentPipelineState);
+
// TODO(yunchao.he@intel.com): vao need to be deduplicated between pipelines.
GLuint mVertexArrayObject;
GLenum mGlPrimitiveTopology;
diff --git a/src/dawn/native/vulkan/RenderPipelineVk.cpp b/src/dawn/native/vulkan/RenderPipelineVk.cpp
index 1a78fed..b8a7441 100644
--- a/src/dawn/native/vulkan/RenderPipelineVk.cpp
+++ b/src/dawn/native/vulkan/RenderPipelineVk.cpp
@@ -320,49 +320,6 @@
DAWN_UNREACHABLE();
}
-VkPipelineDepthStencilStateCreateInfo ComputeDepthStencilDesc(const DepthStencilState* descriptor) {
- VkPipelineDepthStencilStateCreateInfo depthStencilState;
- depthStencilState.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
- depthStencilState.pNext = nullptr;
- depthStencilState.flags = 0;
-
- // Depth writes only occur if depth is enabled
- depthStencilState.depthTestEnable =
- (descriptor->depthCompare == wgpu::CompareFunction::Always &&
- !descriptor->depthWriteEnabled)
- ? VK_FALSE
- : VK_TRUE;
- depthStencilState.depthWriteEnable = descriptor->depthWriteEnabled ? VK_TRUE : VK_FALSE;
- depthStencilState.depthCompareOp = ToVulkanCompareOp(descriptor->depthCompare);
- depthStencilState.depthBoundsTestEnable = false;
- depthStencilState.minDepthBounds = 0.0f;
- depthStencilState.maxDepthBounds = 1.0f;
-
- depthStencilState.stencilTestEnable = StencilTestEnabled(descriptor) ? VK_TRUE : VK_FALSE;
-
- depthStencilState.front.failOp = VulkanStencilOp(descriptor->stencilFront.failOp);
- depthStencilState.front.passOp = VulkanStencilOp(descriptor->stencilFront.passOp);
- depthStencilState.front.depthFailOp = VulkanStencilOp(descriptor->stencilFront.depthFailOp);
- depthStencilState.front.compareOp = ToVulkanCompareOp(descriptor->stencilFront.compare);
-
- depthStencilState.back.failOp = VulkanStencilOp(descriptor->stencilBack.failOp);
- depthStencilState.back.passOp = VulkanStencilOp(descriptor->stencilBack.passOp);
- depthStencilState.back.depthFailOp = VulkanStencilOp(descriptor->stencilBack.depthFailOp);
- depthStencilState.back.compareOp = ToVulkanCompareOp(descriptor->stencilBack.compare);
-
- // Dawn doesn't have separate front and back stencil masks.
- depthStencilState.front.compareMask = descriptor->stencilReadMask;
- depthStencilState.back.compareMask = descriptor->stencilReadMask;
- depthStencilState.front.writeMask = descriptor->stencilWriteMask;
- depthStencilState.back.writeMask = descriptor->stencilWriteMask;
-
- // The stencil reference is always dynamic
- depthStencilState.front.reference = 0;
- depthStencilState.back.reference = 0;
-
- return depthStencilState;
-}
-
} // anonymous namespace
// static
@@ -486,8 +443,7 @@
multisample.alphaToCoverageEnable = IsAlphaToCoverageEnabled();
multisample.alphaToOneEnable = VK_FALSE;
- VkPipelineDepthStencilStateCreateInfo depthStencilState =
- ComputeDepthStencilDesc(GetDepthStencilState());
+ VkPipelineDepthStencilStateCreateInfo depthStencilState = ComputeDepthStencilDesc();
VkPipelineColorBlendStateCreateInfo colorBlend;
// colorBlend may hold pointers to elements in colorBlendAttachments, so it must have a
@@ -667,6 +623,51 @@
return createInfo;
}
+VkPipelineDepthStencilStateCreateInfo RenderPipeline::ComputeDepthStencilDesc() {
+ const DepthStencilState* descriptor = GetDepthStencilState();
+
+ VkPipelineDepthStencilStateCreateInfo depthStencilState;
+ depthStencilState.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
+ depthStencilState.pNext = nullptr;
+ depthStencilState.flags = 0;
+
+ // Depth writes only occur if depth is enabled
+ depthStencilState.depthTestEnable =
+ (descriptor->depthCompare == wgpu::CompareFunction::Always &&
+ !descriptor->depthWriteEnabled)
+ ? VK_FALSE
+ : VK_TRUE;
+ depthStencilState.depthWriteEnable = descriptor->depthWriteEnabled ? VK_TRUE : VK_FALSE;
+ depthStencilState.depthCompareOp = ToVulkanCompareOp(descriptor->depthCompare);
+ depthStencilState.depthBoundsTestEnable = false;
+ depthStencilState.minDepthBounds = 0.0f;
+ depthStencilState.maxDepthBounds = 1.0f;
+
+ depthStencilState.stencilTestEnable = UsesStencil() ? VK_TRUE : VK_FALSE;
+
+ depthStencilState.front.failOp = VulkanStencilOp(descriptor->stencilFront.failOp);
+ depthStencilState.front.passOp = VulkanStencilOp(descriptor->stencilFront.passOp);
+ depthStencilState.front.depthFailOp = VulkanStencilOp(descriptor->stencilFront.depthFailOp);
+ depthStencilState.front.compareOp = ToVulkanCompareOp(descriptor->stencilFront.compare);
+
+ depthStencilState.back.failOp = VulkanStencilOp(descriptor->stencilBack.failOp);
+ depthStencilState.back.passOp = VulkanStencilOp(descriptor->stencilBack.passOp);
+ depthStencilState.back.depthFailOp = VulkanStencilOp(descriptor->stencilBack.depthFailOp);
+ depthStencilState.back.compareOp = ToVulkanCompareOp(descriptor->stencilBack.compare);
+
+ // Dawn doesn't have separate front and back stencil masks.
+ depthStencilState.front.compareMask = descriptor->stencilReadMask;
+ depthStencilState.back.compareMask = descriptor->stencilReadMask;
+ depthStencilState.front.writeMask = descriptor->stencilWriteMask;
+ depthStencilState.back.writeMask = descriptor->stencilWriteMask;
+
+ // The stencil reference is always dynamic
+ depthStencilState.front.reference = 0;
+ depthStencilState.back.reference = 0;
+
+ return depthStencilState;
+}
+
RenderPipeline::~RenderPipeline() = default;
void RenderPipeline::DestroyImpl() {
diff --git a/src/dawn/native/vulkan/RenderPipelineVk.h b/src/dawn/native/vulkan/RenderPipelineVk.h
index 077a3cc..003aec3 100644
--- a/src/dawn/native/vulkan/RenderPipelineVk.h
+++ b/src/dawn/native/vulkan/RenderPipelineVk.h
@@ -61,6 +61,7 @@
};
VkPipelineVertexInputStateCreateInfo ComputeVertexInputDesc(
PipelineVertexInputStateCreateInfoTemporaryAllocations* temporaryAllocations);
+ VkPipelineDepthStencilStateCreateInfo ComputeDepthStencilDesc();
VkPipeline mHandle = VK_NULL_HANDLE;
};
diff --git a/src/dawn/tests/unittests/validation/RenderPipelineValidationTests.cpp b/src/dawn/tests/unittests/validation/RenderPipelineValidationTests.cpp
index a43dbe4..e4292ac 100644
--- a/src/dawn/tests/unittests/validation/RenderPipelineValidationTests.cpp
+++ b/src/dawn/tests/unittests/validation/RenderPipelineValidationTests.cpp
@@ -155,6 +155,42 @@
device.CreateRenderPipeline(&descriptor);
}
+ // Control case, stencil faces with Keep/Always are valid when the format doesn't have stencil
+ {
+ utils::ComboRenderPipelineDescriptor descriptor;
+ descriptor.vertex.module = vsModule;
+ descriptor.cFragment.module = fsModule;
+ wgpu::DepthStencilState* depthStencil =
+ descriptor.EnableDepthStencil(wgpu::TextureFormat::Depth24Plus);
+ depthStencil->stencilFront.compare = wgpu::CompareFunction::Always;
+ depthStencil->stencilFront.failOp = wgpu::StencilOperation::Keep;
+ depthStencil->stencilFront.depthFailOp = wgpu::StencilOperation::Keep;
+ depthStencil->stencilFront.passOp = wgpu::StencilOperation::Keep;
+ depthStencil->stencilBack.compare = wgpu::CompareFunction::Always;
+ depthStencil->stencilBack.failOp = wgpu::StencilOperation::Keep;
+ depthStencil->stencilBack.depthFailOp = wgpu::StencilOperation::Keep;
+ depthStencil->stencilBack.passOp = wgpu::StencilOperation::Keep;
+ device.CreateRenderPipeline(&descriptor);
+ }
+
+ // Control case, stencil faces with Undefined are valid when the format doesn't have stencil
+ {
+ utils::ComboRenderPipelineDescriptor descriptor;
+ descriptor.vertex.module = vsModule;
+ descriptor.cFragment.module = fsModule;
+ wgpu::DepthStencilState* depthStencil =
+ descriptor.EnableDepthStencil(wgpu::TextureFormat::Depth24Plus);
+ depthStencil->stencilFront.compare = wgpu::CompareFunction::Undefined;
+ depthStencil->stencilFront.failOp = wgpu::StencilOperation::Undefined;
+ depthStencil->stencilFront.depthFailOp = wgpu::StencilOperation::Undefined;
+ depthStencil->stencilFront.passOp = wgpu::StencilOperation::Undefined;
+ depthStencil->stencilBack.compare = wgpu::CompareFunction::Undefined;
+ depthStencil->stencilBack.failOp = wgpu::StencilOperation::Undefined;
+ depthStencil->stencilBack.depthFailOp = wgpu::StencilOperation::Undefined;
+ depthStencil->stencilBack.passOp = wgpu::StencilOperation::Undefined;
+ device.CreateRenderPipeline(&descriptor);
+ }
+
// It is invalid if the texture format doesn't have stencil aspect while stencil test is
// enabled (depthStencilState.stencilFront are not default values).
{