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
mtl::DepthStencilDesc mDepthStencilDesc;
mtl::BlendDesc mBlendDesc;
MTLClearColor mClearColor;
uint32_t mClearStencil = 0;
uint32_t mStencilRefFront = 0;
uint32_t mStencilRefBack = 0;
MTLViewport mViewport;
MTLScissorRect mScissorRect;
MTLWinding mWinding;
......
......@@ -573,11 +573,15 @@ angle::Result ContextMtl::syncState(const gl::Context *context,
break;
case gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT:
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_STENCIL_REF);
break;
case gl::State::DIRTY_BIT_STENCIL_FUNCS_BACK:
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_STENCIL_REF);
break;
......@@ -626,6 +630,7 @@ angle::Result ContextMtl::syncState(const gl::Context *context,
case gl::State::DIRTY_BIT_CLEAR_DEPTH:
break;
case gl::State::DIRTY_BIT_CLEAR_STENCIL:
mClearStencil = glState.getStencilClearValue() & mtl::kStencilMaskAll;
break;
case gl::State::DIRTY_BIT_UNPACK_STATE:
// 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
}
uint32_t ContextMtl::getClearStencilValue() const
{
return static_cast<uint32_t>(getState().getStencilClearValue());
return mClearStencil;
}
uint32_t ContextMtl::getStencilMask() const
{
return getState().getDepthStencilState().stencilWritemask;
return getState().getDepthStencilState().stencilWritemask & mtl::kStencilMaskAll;
}
bool ContextMtl::getDepthMask() const
......@@ -1430,8 +1435,8 @@ angle::Result ContextMtl::setupDraw(const gl::Context *context,
ANGLE_TRY(handleDirtyDepthBias(context));
break;
case DIRTY_BIT_STENCIL_REF:
mRenderEncoder.setStencilRefVals(mState.getStencilRef(),
mState.getStencilBackRef());
mRenderEncoder.setStencilRefVals(mStencilRefFront,
mStencilRefBack);
break;
case DIRTY_BIT_BLEND_COLOR:
mRenderEncoder.setBlendColor(
......
......@@ -512,6 +512,9 @@ RenderCommandEncoder &RenderCommandEncoder::setDepthBias(float depthBias,
}
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];
return *this;
......
......@@ -237,7 +237,7 @@ void StencilDesc::reset()
MTLStencilOperationKeep;
stencilCompareFunction = MTLCompareFunctionAlways;
readMask = writeMask = std::numeric_limits<uint32_t>::max();
readMask = writeMask = std::numeric_limits<uint32_t>::max() & mtl::kStencilMaskAll;
}
// DepthStencilDesc implementation
......@@ -361,7 +361,7 @@ void DepthStencilDesc::updateStencilFrontFuncs(const gl::DepthStencilState &dsSt
return;
}
frontFaceStencil.stencilCompareFunction = GetCompareFunc(dsState.stencilFunc);
frontFaceStencil.readMask = dsState.stencilMask;
frontFaceStencil.readMask = dsState.stencilMask & mtl::kStencilMaskAll;
}
void DepthStencilDesc::updateStencilBackFuncs(const gl::DepthStencilState &dsState)
......@@ -371,7 +371,7 @@ void DepthStencilDesc::updateStencilBackFuncs(const gl::DepthStencilState &dsSta
return;
}
backFaceStencil.stencilCompareFunction = GetCompareFunc(dsState.stencilBackFunc);
backFaceStencil.readMask = dsState.stencilBackMask;
backFaceStencil.readMask = dsState.stencilBackMask & mtl::kStencilMaskAll;
}
void DepthStencilDesc::updateStencilFrontWriteMask(const gl::DepthStencilState &dsState)
......@@ -380,7 +380,7 @@ void DepthStencilDesc::updateStencilFrontWriteMask(const gl::DepthStencilState &
{
return;
}
frontFaceStencil.writeMask = dsState.stencilWritemask;
frontFaceStencil.writeMask = dsState.stencilWritemask & mtl::kStencilMaskAll;
}
void DepthStencilDesc::updateStencilBackWriteMask(const gl::DepthStencilState &dsState)
......@@ -389,7 +389,7 @@ void DepthStencilDesc::updateStencilBackWriteMask(const gl::DepthStencilState &d
{
return;
}
backFaceStencil.writeMask = dsState.stencilBackWritemask;
backFaceStencil.writeMask = dsState.stencilBackWritemask & mtl::kStencilMaskAll;
}
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