Skip to content

Commit

Permalink
Apply stencil writemask when clearing properly again, see #17478
Browse files Browse the repository at this point in the history
Also renames vpAndScissor to vpAndScissor_ for consistency.
  • Loading branch information
hrydgard committed Jun 12, 2023
1 parent 1f4142e commit 53aa2cc
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 19 deletions.
6 changes: 3 additions & 3 deletions GPU/GLES/DrawEngineGLES.cpp
Expand Up @@ -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();
Expand Down Expand Up @@ -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)) {
Expand Down
4 changes: 3 additions & 1 deletion GPU/GLES/DrawEngineGLES.h
Expand Up @@ -141,7 +141,9 @@ class DrawEngineGLES : public DrawEngineCommon {
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;
Expand Down
28 changes: 13 additions & 15 deletions GPU/GLES/StateMappingGLES.cpp
Expand Up @@ -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
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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.
}

Expand Down

0 comments on commit 53aa2cc

Please sign in to comment.