Commit fbe6c1d2 by Le Hoang Quyen Committed by Commit Bot

Metal: correctly clamp stencil reference values

According to GL spec: - If stencil ref value is larger than max value the stencil buffer can represent, clamp it to max value (2^bits - 1) - The stencil clear value & mask will be truncated to stencil buffer's bits instead of clamping. Metal API is very vague on how it handles the stencil ref value larger than the stencil bits can represent, so we need to handle it manually. In fact, the Metal API seems to have bugs when dealing with large stencil ref value, i.e. > 0xff for example. Bug: angleproject:2634 Change-Id: I86f61f0bfd19dfc0fa459c84d98785a1af857a6b Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1966185 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarJonah Ryan-Davis <jonahr@google.com>
parent 7b55aac3
...@@ -421,6 +421,9 @@ class ContextMtl : public ContextImpl, public mtl::Context ...@@ -421,6 +421,9 @@ class ContextMtl : public ContextImpl, public mtl::Context
mtl::DepthStencilDesc mDepthStencilDesc; mtl::DepthStencilDesc mDepthStencilDesc;
mtl::BlendDesc mBlendDesc; mtl::BlendDesc mBlendDesc;
MTLClearColor mClearColor; MTLClearColor mClearColor;
uint32_t mClearStencil = 0;
uint32_t mStencilRefFront = 0;
uint32_t mStencilRefBack = 0;
MTLViewport mViewport; MTLViewport mViewport;
MTLScissorRect mScissorRect; MTLScissorRect mScissorRect;
MTLWinding mWinding; MTLWinding mWinding;
......
...@@ -573,11 +573,15 @@ angle::Result ContextMtl::syncState(const gl::Context *context, ...@@ -573,11 +573,15 @@ angle::Result ContextMtl::syncState(const gl::Context *context,
break; break;
case gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT: case gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT:
mDepthStencilDesc.updateStencilFrontFuncs(glState.getDepthStencilState()); mDepthStencilDesc.updateStencilFrontFuncs(glState.getDepthStencilState());
mStencilRefFront =
gl::clamp<int, int, int>(glState.getStencilRef(), 0, mtl::kStencilMaskAll);
mDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_DESC); mDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_DESC);
mDirtyBits.set(DIRTY_BIT_STENCIL_REF); mDirtyBits.set(DIRTY_BIT_STENCIL_REF);
break; break;
case gl::State::DIRTY_BIT_STENCIL_FUNCS_BACK: case gl::State::DIRTY_BIT_STENCIL_FUNCS_BACK:
mDepthStencilDesc.updateStencilBackFuncs(glState.getDepthStencilState()); mDepthStencilDesc.updateStencilBackFuncs(glState.getDepthStencilState());
mStencilRefBack =
gl::clamp<int, int, int>(glState.getStencilBackRef(), 0, mtl::kStencilMaskAll);
mDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_DESC); mDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_DESC);
mDirtyBits.set(DIRTY_BIT_STENCIL_REF); mDirtyBits.set(DIRTY_BIT_STENCIL_REF);
break; break;
...@@ -626,6 +630,7 @@ angle::Result ContextMtl::syncState(const gl::Context *context, ...@@ -626,6 +630,7 @@ angle::Result ContextMtl::syncState(const gl::Context *context,
case gl::State::DIRTY_BIT_CLEAR_DEPTH: case gl::State::DIRTY_BIT_CLEAR_DEPTH:
break; break;
case gl::State::DIRTY_BIT_CLEAR_STENCIL: case gl::State::DIRTY_BIT_CLEAR_STENCIL:
mClearStencil = glState.getStencilClearValue() & mtl::kStencilMaskAll;
break; break;
case gl::State::DIRTY_BIT_UNPACK_STATE: case gl::State::DIRTY_BIT_UNPACK_STATE:
// This is a no-op, its only important to use the right unpack state when we do // This is a no-op, its only important to use the right unpack state when we do
...@@ -979,11 +984,11 @@ float ContextMtl::getClearDepthValue() const ...@@ -979,11 +984,11 @@ float ContextMtl::getClearDepthValue() const
} }
uint32_t ContextMtl::getClearStencilValue() const uint32_t ContextMtl::getClearStencilValue() const
{ {
return static_cast<uint32_t>(getState().getStencilClearValue()); return mClearStencil;
} }
uint32_t ContextMtl::getStencilMask() const uint32_t ContextMtl::getStencilMask() const
{ {
return getState().getDepthStencilState().stencilWritemask; return getState().getDepthStencilState().stencilWritemask & mtl::kStencilMaskAll;
} }
bool ContextMtl::getDepthMask() const bool ContextMtl::getDepthMask() const
...@@ -1430,8 +1435,8 @@ angle::Result ContextMtl::setupDraw(const gl::Context *context, ...@@ -1430,8 +1435,8 @@ angle::Result ContextMtl::setupDraw(const gl::Context *context,
ANGLE_TRY(handleDirtyDepthBias(context)); ANGLE_TRY(handleDirtyDepthBias(context));
break; break;
case DIRTY_BIT_STENCIL_REF: case DIRTY_BIT_STENCIL_REF:
mRenderEncoder.setStencilRefVals(mState.getStencilRef(), mRenderEncoder.setStencilRefVals(mStencilRefFront,
mState.getStencilBackRef()); mStencilRefBack);
break; break;
case DIRTY_BIT_BLEND_COLOR: case DIRTY_BIT_BLEND_COLOR:
mRenderEncoder.setBlendColor( mRenderEncoder.setBlendColor(
......
...@@ -512,6 +512,9 @@ RenderCommandEncoder &RenderCommandEncoder::setDepthBias(float depthBias, ...@@ -512,6 +512,9 @@ RenderCommandEncoder &RenderCommandEncoder::setDepthBias(float depthBias,
} }
RenderCommandEncoder &RenderCommandEncoder::setStencilRefVals(uint32_t frontRef, uint32_t backRef) RenderCommandEncoder &RenderCommandEncoder::setStencilRefVals(uint32_t frontRef, uint32_t backRef)
{ {
// Metal has some bugs when reference values are larger than 0xff
ASSERT(frontRef == (frontRef & kStencilMaskAll));
ASSERT(backRef == (backRef & kStencilMaskAll));
[get() setStencilFrontReferenceValue:frontRef backReferenceValue:backRef]; [get() setStencilFrontReferenceValue:frontRef backReferenceValue:backRef];
return *this; return *this;
......
...@@ -237,7 +237,7 @@ void StencilDesc::reset() ...@@ -237,7 +237,7 @@ void StencilDesc::reset()
MTLStencilOperationKeep; MTLStencilOperationKeep;
stencilCompareFunction = MTLCompareFunctionAlways; stencilCompareFunction = MTLCompareFunctionAlways;
readMask = writeMask = std::numeric_limits<uint32_t>::max(); readMask = writeMask = std::numeric_limits<uint32_t>::max() & mtl::kStencilMaskAll;
} }
// DepthStencilDesc implementation // DepthStencilDesc implementation
...@@ -361,7 +361,7 @@ void DepthStencilDesc::updateStencilFrontFuncs(const gl::DepthStencilState &dsSt ...@@ -361,7 +361,7 @@ void DepthStencilDesc::updateStencilFrontFuncs(const gl::DepthStencilState &dsSt
return; return;
} }
frontFaceStencil.stencilCompareFunction = GetCompareFunc(dsState.stencilFunc); frontFaceStencil.stencilCompareFunction = GetCompareFunc(dsState.stencilFunc);
frontFaceStencil.readMask = dsState.stencilMask; frontFaceStencil.readMask = dsState.stencilMask & mtl::kStencilMaskAll;
} }
void DepthStencilDesc::updateStencilBackFuncs(const gl::DepthStencilState &dsState) void DepthStencilDesc::updateStencilBackFuncs(const gl::DepthStencilState &dsState)
...@@ -371,7 +371,7 @@ void DepthStencilDesc::updateStencilBackFuncs(const gl::DepthStencilState &dsSta ...@@ -371,7 +371,7 @@ void DepthStencilDesc::updateStencilBackFuncs(const gl::DepthStencilState &dsSta
return; return;
} }
backFaceStencil.stencilCompareFunction = GetCompareFunc(dsState.stencilBackFunc); backFaceStencil.stencilCompareFunction = GetCompareFunc(dsState.stencilBackFunc);
backFaceStencil.readMask = dsState.stencilBackMask; backFaceStencil.readMask = dsState.stencilBackMask & mtl::kStencilMaskAll;
} }
void DepthStencilDesc::updateStencilFrontWriteMask(const gl::DepthStencilState &dsState) void DepthStencilDesc::updateStencilFrontWriteMask(const gl::DepthStencilState &dsState)
...@@ -380,7 +380,7 @@ void DepthStencilDesc::updateStencilFrontWriteMask(const gl::DepthStencilState & ...@@ -380,7 +380,7 @@ void DepthStencilDesc::updateStencilFrontWriteMask(const gl::DepthStencilState &
{ {
return; return;
} }
frontFaceStencil.writeMask = dsState.stencilWritemask; frontFaceStencil.writeMask = dsState.stencilWritemask & mtl::kStencilMaskAll;
} }
void DepthStencilDesc::updateStencilBackWriteMask(const gl::DepthStencilState &dsState) void DepthStencilDesc::updateStencilBackWriteMask(const gl::DepthStencilState &dsState)
...@@ -389,7 +389,7 @@ void DepthStencilDesc::updateStencilBackWriteMask(const gl::DepthStencilState &d ...@@ -389,7 +389,7 @@ void DepthStencilDesc::updateStencilBackWriteMask(const gl::DepthStencilState &d
{ {
return; return;
} }
backFaceStencil.writeMask = dsState.stencilBackWritemask; backFaceStencil.writeMask = dsState.stencilBackWritemask & mtl::kStencilMaskAll;
} }
size_t DepthStencilDesc::hash() const size_t DepthStencilDesc::hash() const
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment