From 5351c9ddb3401d9fcd12816b22b882e29ec8e021 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 31 Jan 2018 17:07:20 +0100 Subject: [PATCH] gl-render-manager: Support scissored clears, as used by the GL backend. Fixes GT. --- GPU/GLES/DrawEngineGLES.cpp | 6 +++--- GPU/GLES/StencilBufferGLES.cpp | 4 ++-- ext/native/thin3d/GLQueueRunner.cpp | 11 +++++++++-- ext/native/thin3d/GLQueueRunner.h | 10 +++++++--- ext/native/thin3d/GLRenderManager.cpp | 5 ++++- ext/native/thin3d/GLRenderManager.h | 8 +++++++- ext/native/thin3d/thin3d_gl.cpp | 2 +- 7 files changed, 33 insertions(+), 13 deletions(-) diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index 77717aea19..247549dddf 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -724,13 +724,13 @@ rotateVBO: if (alphaMask) target |= GL_STENCIL_BUFFER_BIT; if (depthMask) target |= GL_DEPTH_BUFFER_BIT; - render_->Clear(clearColor, clearDepth, clearColor >> 24, target, rgbaMask); - framebufferManager_->SetColorUpdated(gstate_c.skipDrawReason); - int scissorX1 = gstate.getScissorX1(); int scissorY1 = gstate.getScissorY1(); int scissorX2 = gstate.getScissorX2() + 1; int scissorY2 = gstate.getScissorY2() + 1; + + render_->Clear(clearColor, clearDepth, clearColor >> 24, target, rgbaMask, scissorX1, scissorY1, scissorX2 - scissorX1, scissorY2 - scissorY1); + framebufferManager_->SetColorUpdated(gstate_c.skipDrawReason); framebufferManager_->SetSafeSize(scissorX2, scissorY2); if (g_Config.bBlockTransferGPU && (gstate_c.featureFlags & GPU_USE_CLEAR_RAM_HACK) && colorMask && (alphaMask || gstate.FrameBufFormat() == GE_FORMAT_565)) { diff --git a/GPU/GLES/StencilBufferGLES.cpp b/GPU/GLES/StencilBufferGLES.cpp index e86aad078f..093694dddd 100644 --- a/GPU/GLES/StencilBufferGLES.cpp +++ b/GPU/GLES/StencilBufferGLES.cpp @@ -113,7 +113,7 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe if (dstBuffer->fbo) { draw_->BindFramebufferAsRenderTarget(dstBuffer->fbo, { Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::CLEAR }); } - render_->Clear(0, 0, 0, GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT, 0x8); + render_->Clear(0, 0, 0, GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT, 0x8, 0, 0, 0, 0); gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_VIEWPORTSCISSOR_STATE); return true; } @@ -169,7 +169,7 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe textureCacheGL_->ForgetLastTexture(); // We must bind the program after starting the render pass, and set the color mask after clearing. - render_->Clear(0, 0, 0, GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, 0x8); + render_->Clear(0, 0, 0, GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, 0x8, 0, 0, 0, 0); render_->SetStencilFunc(GL_TRUE, GL_ALWAYS, 0xFF, 0xFF); render_->BindProgram(stencilUploadProgram_); render_->SetNoBlendAndMask(0x8); diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 9fd394c8be..09a45ab873 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -629,7 +629,12 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { #endif break; case GLRRenderCommand::CLEAR: - glDisable(GL_SCISSOR_TEST); + if (c.clear.scissorW > 0) { + glEnable(GL_SCISSOR_TEST); + glScissor(c.clear.scissorX, c.clear.scissorY, c.clear.scissorW, c.clear.scissorH); + } else { + glDisable(GL_SCISSOR_TEST); + } if (c.clear.colorMask != colorMask) { glColorMask(c.clear.colorMask & 1, (c.clear.colorMask >> 1) & 1, (c.clear.colorMask >> 2) & 1, (c.clear.colorMask >> 3) & 1); colorMask = c.clear.colorMask; @@ -650,7 +655,9 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { glClearStencil(c.clear.clearStencil); } glClear(c.clear.clearMask); - glEnable(GL_SCISSOR_TEST); + if (c.clear.scissorW > 0) { + glDisable(GL_SCISSOR_TEST); + } break; case GLRRenderCommand::INVALIDATE: { diff --git a/ext/native/thin3d/GLQueueRunner.h b/ext/native/thin3d/GLQueueRunner.h index 8d50e0ca44..33e979d585 100644 --- a/ext/native/thin3d/GLQueueRunner.h +++ b/ext/native/thin3d/GLQueueRunner.h @@ -122,9 +122,13 @@ struct GLRRenderData { struct { uint32_t clearColor; float clearZ; - int clearStencil; - int clearMask; // VK_IMAGE_ASPECT_COLOR_BIT etc - int colorMask; // Like blend, but for the clear. + uint8_t clearStencil; + uint8_t colorMask; // Like blend, but for the clear. + GLuint clearMask; // GL_COLOR_BUFFER_BIT etc + int16_t scissorX; + int16_t scissorY; + int16_t scissorW; + int16_t scissorH; } clear; struct { int slot; diff --git a/ext/native/thin3d/GLRenderManager.cpp b/ext/native/thin3d/GLRenderManager.cpp index abd267aee1..4e21eaf124 100644 --- a/ext/native/thin3d/GLRenderManager.cpp +++ b/ext/native/thin3d/GLRenderManager.cpp @@ -203,11 +203,14 @@ void GLRenderManager::BindFramebufferAsRenderTarget(GLRFramebuffer *fb, GLRRende data.clear.clearStencil = clearStencil; } if (clearMask) { + data.clear.scissorX = 0; + data.clear.scissorY = 0; + data.clear.scissorW = 0; + data.clear.scissorH = 0; data.clear.clearMask = clearMask; data.clear.colorMask = 0xF; step->commands.push_back(data); } - curRenderStep_ = step; // Every step clears this state. diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index 239ff0f3c0..b0b3b77f6c 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -578,14 +578,20 @@ public: curRenderStep_->commands.push_back(data); } - void Clear(uint32_t clearColor, float clearZ, int clearStencil, int clearMask, int colorMask = 0xF) { + // If scissorW == 0, no scissor is applied. + void Clear(uint32_t clearColor, float clearZ, int clearStencil, int clearMask, int colorMask, int scissorX, int scissorY, int scissorW, int scissorH) { _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); GLRRenderData data{ GLRRenderCommand::CLEAR }; + _assert_(clearMask != 0); // What would be the point? data.clear.clearMask = clearMask; data.clear.clearColor = clearColor; data.clear.clearZ = clearZ; data.clear.clearStencil = clearStencil; data.clear.colorMask = colorMask; + data.clear.scissorX = scissorX; + data.clear.scissorY = scissorY; + data.clear.scissorW = scissorW; + data.clear.scissorH = scissorH; curRenderStep_->commands.push_back(data); } diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index b831e199a0..55691e84b9 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -1023,7 +1023,7 @@ void OpenGLContext::Clear(int mask, uint32_t colorval, float depthVal, int stenc if (mask & FBChannel::FB_STENCIL_BIT) { glMask |= GL_STENCIL_BUFFER_BIT; } - renderManager_.Clear(colorval, depthVal, stencilVal, glMask); + renderManager_.Clear(colorval, depthVal, stencilVal, glMask, 0xF, 0, 0, targetWidth_, targetHeight_); } DrawContext *T3DCreateGLContext() {