Merge pull request #17564 from hrydgard/stencil-clear-fix

OpenGL: Apply stencil writemask when clearing properly again
This commit is contained in:
Henrik Rydgård 2023-06-12 14:25:28 +02:00 committed by GitHub
commit 94e3412fd5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 19 additions and 19 deletions

View file

@ -378,8 +378,8 @@ void DrawEngineGLES::DoFlush() {
ConvertViewportAndScissor(framebufferManager_->UseBufferedRendering(),
framebufferManager_->GetRenderWidth(), framebufferManager_->GetRenderHeight(),
framebufferManager_->GetTargetBufferWidth(), framebufferManager_->GetTargetBufferHeight(),
vpAndScissor);
UpdateCachedViewportState(vpAndScissor);
vpAndScissor_);
UpdateCachedViewportState(vpAndScissor_);
}
int maxIndex = indexGen.MaxIndex();
@ -455,7 +455,7 @@ void DrawEngineGLES::DoFlush() {
if (alphaMask) target |= GL_STENCIL_BUFFER_BIT;
if (depthMask) target |= GL_DEPTH_BUFFER_BIT;
render_->Clear(clearColor, clearDepth, clearColor >> 24, target, rgbaMask, vpAndScissor.scissorX, vpAndScissor.scissorY, vpAndScissor.scissorW, vpAndScissor.scissorH);
render_->Clear(clearColor, clearDepth, clearColor >> 24, target, rgbaMask, vpAndScissor_.scissorX, vpAndScissor_.scissorY, vpAndScissor_.scissorW, vpAndScissor_.scissorH);
framebufferManager_->SetColorUpdated(gstate_c.skipDrawReason);
if (gstate_c.Use(GPU_USE_CLEAR_RAM_HACK) && colorMask && (alphaMask || gstate_c.framebufFormat == GE_FORMAT_565)) {

View file

@ -141,7 +141,9 @@ private:
Draw::DrawContext *draw_;
// Need to preserve the scissor for use when clearing.
ViewportAndScissor vpAndScissor;
ViewportAndScissor vpAndScissor_{};
// Need to preserve writemask, easiest way.
GenericStencilFuncState stencilState_{};
int bufferDecimationCounter_ = 0;
int lastRenderStepId_ = -1;

View file

@ -242,14 +242,12 @@ void DrawEngineGLES::ApplyDrawState(int prim) {
}
if (gstate_c.IsDirty(DIRTY_DEPTHSTENCIL_STATE)) {
GenericStencilFuncState stencilState;
ConvertStencilFuncState(stencilState);
ConvertStencilFuncState(stencilState_);
if (gstate.isModeClear()) {
// Depth Test
renderManager->SetStencil(
gstate.isClearModeAlphaMask(), GL_ALWAYS, 0xFF, 0xFF,
stencilState.writeMask, GL_REPLACE, GL_REPLACE, GL_REPLACE);
stencilState_.writeMask, GL_REPLACE, GL_REPLACE, GL_REPLACE);
renderManager->SetDepth(true, gstate.isClearModeDepthMask() ? true : false, GL_ALWAYS);
} else {
// Depth Test
@ -259,15 +257,15 @@ void DrawEngineGLES::ApplyDrawState(int prim) {
UpdateEverUsedEqualDepth(gstate.getDepthTestFunction());
// Stencil Test
if (stencilState.enabled) {
if (stencilState_.enabled) {
renderManager->SetStencil(
stencilState.enabled, compareOps[stencilState.testFunc], stencilState.testRef, stencilState.testMask,
stencilState.writeMask, stencilOps[stencilState.sFail], stencilOps[stencilState.zFail], stencilOps[stencilState.zPass]);
stencilState_.enabled, compareOps[stencilState_.testFunc], stencilState_.testRef, stencilState_.testMask,
stencilState_.writeMask, stencilOps[stencilState_.sFail], stencilOps[stencilState_.zFail], stencilOps[stencilState_.zPass]);
// Nasty special case for Spongebob and similar where it tries to write zeros to alpha/stencil during
// depth-fail. We can't write to alpha then because the pixel is killed. However, we can invert the depth
// test and modify the alpha function...
if (SpongebobDepthInverseConditions(stencilState)) {
if (SpongebobDepthInverseConditions(stencilState_)) {
renderManager->SetBlendAndMask(0x8, true, GL_ZERO, GL_ZERO, GL_ZERO, GL_ZERO, GL_FUNC_ADD, GL_FUNC_ADD);
renderManager->SetDepth(true, false, GL_LESS);
renderManager->SetStencil(true, GL_ALWAYS, 0xFF, 0xFF, 0xFF, GL_ZERO, GL_KEEP, GL_ZERO);
@ -285,14 +283,14 @@ void DrawEngineGLES::ApplyDrawState(int prim) {
ConvertViewportAndScissor(useBufferedRendering,
framebufferManager_->GetRenderWidth(), framebufferManager_->GetRenderHeight(),
framebufferManager_->GetTargetBufferWidth(), framebufferManager_->GetTargetBufferHeight(),
vpAndScissor);
UpdateCachedViewportState(vpAndScissor);
vpAndScissor_);
UpdateCachedViewportState(vpAndScissor_);
renderManager->SetScissor(GLRect2D{ vpAndScissor.scissorX, vpAndScissor.scissorY, vpAndScissor.scissorW, vpAndScissor.scissorH });
renderManager->SetScissor(GLRect2D{ vpAndScissor_.scissorX, vpAndScissor_.scissorY, vpAndScissor_.scissorW, vpAndScissor_.scissorH });
renderManager->SetViewport({
vpAndScissor.viewportX, vpAndScissor.viewportY,
vpAndScissor.viewportW, vpAndScissor.viewportH,
vpAndScissor.depthRangeMin, vpAndScissor.depthRangeMax });
vpAndScissor_.viewportX, vpAndScissor_.viewportY,
vpAndScissor_.viewportW, vpAndScissor_.viewportH,
vpAndScissor_.depthRangeMin, vpAndScissor_.depthRangeMax });
}
gstate_c.Clean(DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE | DIRTY_BLEND_STATE);
@ -302,7 +300,7 @@ void DrawEngineGLES::ApplyDrawState(int prim) {
void DrawEngineGLES::ApplyDrawStateLate(bool setStencilValue, int stencilValue) {
if (setStencilValue) {
render_->SetStencil(true, GL_ALWAYS, stencilValue, 255, 0xFF, GL_REPLACE, GL_REPLACE, GL_REPLACE);
render_->SetStencil(stencilState_.writeMask, GL_ALWAYS, stencilValue, 255, 0xFF, GL_REPLACE, GL_REPLACE, GL_REPLACE);
gstate_c.Dirty(DIRTY_DEPTHSTENCIL_STATE); // For the next time.
}