From b9081dd624b6434677a9327e23516b06c08c9c01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 8 Feb 2018 16:20:56 +0100 Subject: [PATCH 1/4] GL: Set a plain render state in DrawActiveTexture, without relying on the caller having called DisableState --- GPU/GLES/FramebufferManagerGLES.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index 9cde5bf55d..dc56db2a40 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -423,6 +423,12 @@ void FramebufferManagerGLES::DrawActiveTexture(float x, float y, float w, float pos[i * 3 + 1] = pos[i * 3 + 1] * invDestH - 1.0f; } + // We always want a plain state here. + render_->SetNoBlendAndMask(0xF); + render_->SetDepth(false, false, GL_ALWAYS); + render_->SetStencilDisabled(); + render_->SetRaster(false, GL_CCW, GL_FALSE, GL_FALSE); + // Upscaling postshaders don't look well with linear if (flags & DRAWTEX_LINEAR) { render_->SetTextureSampler(0, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_LINEAR, GL_LINEAR, 0.0f); From 86cfc411a48ca909c3da8937764db17e65a36922 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 8 Feb 2018 16:21:41 +0100 Subject: [PATCH 2/4] Remove the confusing "DisableState" across the codebase --- GPU/Common/FramebufferCommon.cpp | 5 ----- GPU/Common/FramebufferCommon.h | 1 - GPU/D3D11/FramebufferManagerD3D11.cpp | 9 --------- GPU/D3D11/FramebufferManagerD3D11.h | 2 -- GPU/Directx9/FramebufferDX9.cpp | 23 ++++++++--------------- GPU/Directx9/FramebufferDX9.h | 1 - GPU/Directx9/StencilBufferDX9.cpp | 1 - GPU/GLES/FramebufferManagerGLES.cpp | 6 ------ GPU/GLES/FramebufferManagerGLES.h | 1 - GPU/GLES/StencilBufferGLES.cpp | 3 +-- GPU/Vulkan/FramebufferVulkan.h | 1 - 11 files changed, 9 insertions(+), 44 deletions(-) diff --git a/GPU/Common/FramebufferCommon.cpp b/GPU/Common/FramebufferCommon.cpp index 1447ca62ff..03c0aad4c8 100644 --- a/GPU/Common/FramebufferCommon.cpp +++ b/GPU/Common/FramebufferCommon.cpp @@ -690,7 +690,6 @@ void FramebufferManagerCommon::UpdateFromMemory(u32 addr, int size, bool safe) { FlushBeforeCopy(); if (useBufferedRendering_ && vfb->fbo) { - DisableState(); GEBufferFormat fmt = vfb->format; if (vfb->last_frame_render + 1 < gpuStats.numFlips && isDisplayBuf) { // If we're not rendering to it, format may be wrong. Use displayFormat_ instead. @@ -731,7 +730,6 @@ void FramebufferManagerCommon::DrawPixels(VirtualFramebuffer *vfb, int dstX, int SetViewport2D(x, y, w, h); draw_->SetScissorRect(0, 0, pixelWidth_, pixelHeight_); } - DisableState(); MakePixelTexture(srcPixels, srcPixelFormat, srcStride, width, height, u1, v1); @@ -775,8 +773,6 @@ void FramebufferManagerCommon::DrawFramebufferToOutput(const u8 *srcPixels, GEBu float v0 = 0.0f, v1 = 1.0f; MakePixelTexture(srcPixels, srcPixelFormat, srcStride, 512, 272, u1, v1); - DisableState(); - struct CardboardSettings cardboardSettings; GetCardboardSettings(&cardboardSettings); @@ -951,7 +947,6 @@ void FramebufferManagerCommon::CopyDisplayToOutput() { if (vfb->fbo) { DEBUG_LOG(FRAMEBUF, "Displaying FBO %08x", vfb->fb_address); - DisableState(); int uvRotation = useBufferedRendering_ ? g_Config.iInternalScreenRotation : ROTATION_LOCKED_HORIZONTAL; diff --git a/GPU/Common/FramebufferCommon.h b/GPU/Common/FramebufferCommon.h index 9ab59a4b0b..d88dced994 100644 --- a/GPU/Common/FramebufferCommon.h +++ b/GPU/Common/FramebufferCommon.h @@ -312,7 +312,6 @@ protected: bool UpdateSize(); void SetNumExtraFBOs(int num); - virtual void DisableState() = 0; void FlushBeforeCopy(); virtual void DecimateFBOs(); // keeping it virtual to let D3D do a little extra diff --git a/GPU/D3D11/FramebufferManagerD3D11.cpp b/GPU/D3D11/FramebufferManagerD3D11.cpp index c45ec45cd5..9cd78f97dc 100644 --- a/GPU/D3D11/FramebufferManagerD3D11.cpp +++ b/GPU/D3D11/FramebufferManagerD3D11.cpp @@ -197,13 +197,6 @@ void FramebufferManagerD3D11::SetDrawEngine(DrawEngineD3D11 *td) { drawEngine_ = td; } -void FramebufferManagerD3D11::DisableState() { - context_->OMSetBlendState(stockD3D11.blendStateDisabledWithColorMask[0xF], nullptr, 0xFFFFFFFF); - context_->RSSetState(stockD3D11.rasterStateNoCull); - context_->OMSetDepthStencilState(stockD3D11.depthStencilDisabled, 0xFF); - gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE); -} - void FramebufferManagerD3D11::CompilePostShader() { std::string vsSource; std::string psSource; @@ -731,8 +724,6 @@ void FramebufferManagerD3D11::DestroyAllFBOs() { tempFBOs_.clear(); SetNumExtraFBOs(0); - - DisableState(); } void FramebufferManagerD3D11::Resized() { diff --git a/GPU/D3D11/FramebufferManagerD3D11.h b/GPU/D3D11/FramebufferManagerD3D11.h index d951d60e7f..253bc8dd6e 100644 --- a/GPU/D3D11/FramebufferManagerD3D11.h +++ b/GPU/D3D11/FramebufferManagerD3D11.h @@ -65,8 +65,6 @@ public: } protected: - void DisableState() override; - // Used by ReadFramebufferToMemory and later framebuffer block copies void BlitFramebuffer(VirtualFramebuffer *dst, int dstX, int dstY, VirtualFramebuffer *src, int srcX, int srcY, int w, int h, int bpp) override; diff --git a/GPU/Directx9/FramebufferDX9.cpp b/GPU/Directx9/FramebufferDX9.cpp index 6b6296097e..3d7e7c03b7 100644 --- a/GPU/Directx9/FramebufferDX9.cpp +++ b/GPU/Directx9/FramebufferDX9.cpp @@ -81,17 +81,6 @@ static const D3DVERTEXELEMENT9 g_FramebufferVertexElements[] = { D3DDECL_END() }; - void FramebufferManagerDX9::DisableState() { - dxstate.blend.disable(); - dxstate.cullMode.set(false, false); - dxstate.depthTest.disable(); - dxstate.scissorTest.disable(); - dxstate.stencilTest.disable(); - dxstate.colorMask.set(true, true, true, true); - dxstate.stencilMask.set(0xFF); - gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_RASTER_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_VIEWPORTSCISSOR_STATE); - } - FramebufferManagerDX9::FramebufferManagerDX9(Draw::DrawContext *draw) : FramebufferManagerCommon(draw), drawPixelsTex_(0), @@ -249,7 +238,7 @@ static const D3DVERTEXELEMENT9 g_FramebufferVertexElements[] = { } void FramebufferManagerDX9::DrawActiveTexture(float x, float y, float w, float h, float destW, float destH, float u0, float v0, float u1, float v1, int uvRotation, int flags) { - // TODO: StretchRect instead? + // TODO: StretchRect instead when possible? float coord[20] = { x,y,0, u0,v0, x+w,y,0, u1,v0, @@ -297,7 +286,13 @@ static const D3DVERTEXELEMENT9 g_FramebufferVertexElements[] = { } dxstate.texMipLodBias.set(0.0f); dxstate.texMaxMipLevel.set(0); - device_->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + dxstate.blend.disable(); + dxstate.cullMode.set(false, false); + dxstate.depthTest.disable(); + dxstate.scissorTest.disable(); + dxstate.stencilTest.disable(); + dxstate.colorMask.set(true, true, true, true); + dxstate.stencilMask.set(0xFF); HRESULT hr = device_->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, coord, 5 * sizeof(float)); if (FAILED(hr)) { ERROR_LOG_REPORT(G3D, "DrawActiveTexture() failed: %08x", hr); @@ -725,8 +720,6 @@ static const D3DVERTEXELEMENT9 g_FramebufferVertexElements[] = { offscreenSurfaces_.clear(); SetNumExtraFBOs(0); - - DisableState(); } void FramebufferManagerDX9::Resized() { diff --git a/GPU/Directx9/FramebufferDX9.h b/GPU/Directx9/FramebufferDX9.h index dd1b3bd2ca..bc2ce7c31d 100644 --- a/GPU/Directx9/FramebufferDX9.h +++ b/GPU/Directx9/FramebufferDX9.h @@ -73,7 +73,6 @@ protected: void Bind2DShader() override; void BindPostShader(const PostShaderUniforms &uniforms) override; void SetViewport2D(int x, int y, int w, int h) override; - void DisableState() override; void DecimateFBOs() override; // Used by ReadFramebufferToMemory and later framebuffer block copies diff --git a/GPU/Directx9/StencilBufferDX9.cpp b/GPU/Directx9/StencilBufferDX9.cpp index 95f7b42718..6f51582cf2 100644 --- a/GPU/Directx9/StencilBufferDX9.cpp +++ b/GPU/Directx9/StencilBufferDX9.cpp @@ -181,7 +181,6 @@ bool FramebufferManagerDX9::NotifyStencilUpload(u32 addr, int size, bool skipZer shaderManagerDX9_->DirtyLastShader(); - DisableState(); dxstate.colorMask.set(false, false, false, true); dxstate.stencilTest.enable(); dxstate.stencilOp.set(D3DSTENCILOP_REPLACE, D3DSTENCILOP_REPLACE, D3DSTENCILOP_REPLACE); diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index dc56db2a40..00f7da4195 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -80,10 +80,6 @@ const int MAX_PBO = 2; void ConvertFromRGBA8888(u8 *dst, const u8 *src, u32 dstStride, u32 srcStride, u32 width, u32 height, GEBufferFormat format); -void FramebufferManagerGLES::DisableState() { - gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_RASTER_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_VIEWPORTSCISSOR_STATE); -} - void FramebufferManagerGLES::CompileDraw2DProgram() { if (!draw2dprogram_) { std::string errorString; @@ -784,8 +780,6 @@ void FramebufferManagerGLES::DestroyAllFBOs() { tempFBOs_.clear(); SetNumExtraFBOs(0); - - DisableState(); } void FramebufferManagerGLES::Resized() { diff --git a/GPU/GLES/FramebufferManagerGLES.h b/GPU/GLES/FramebufferManagerGLES.h index c3f0594637..fb00c41858 100644 --- a/GPU/GLES/FramebufferManagerGLES.h +++ b/GPU/GLES/FramebufferManagerGLES.h @@ -69,7 +69,6 @@ public: protected: void SetViewport2D(int x, int y, int w, int h) override; - void DisableState() override; // Used by ReadFramebufferToMemory and later framebuffer block copies void BlitFramebuffer(VirtualFramebuffer *dst, int dstX, int dstY, VirtualFramebuffer *src, int srcX, int srcY, int w, int h, int bpp) override; diff --git a/GPU/GLES/StencilBufferGLES.cpp b/GPU/GLES/StencilBufferGLES.cpp index 093694dddd..d29e2bbf56 100644 --- a/GPU/GLES/StencilBufferGLES.cpp +++ b/GPU/GLES/StencilBufferGLES.cpp @@ -142,8 +142,6 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe shaderManagerGL_->DirtyLastShader(); - DisableState(); - bool useBlit = gstate_c.Supports(GPU_SUPPORTS_ARB_FRAMEBUFFER_BLIT | GPU_SUPPORTS_NV_FRAMEBUFFER_BLIT); // Our fragment shader (and discard) is slow. Since the source is 1x, we can stencil to 1x. @@ -169,6 +167,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_->SetDepth(false, false, GL_ALWAYS); 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_); diff --git a/GPU/Vulkan/FramebufferVulkan.h b/GPU/Vulkan/FramebufferVulkan.h index 10d739642c..197802e4bc 100644 --- a/GPU/Vulkan/FramebufferVulkan.h +++ b/GPU/Vulkan/FramebufferVulkan.h @@ -89,7 +89,6 @@ protected: void Bind2DShader() override; void BindPostShader(const PostShaderUniforms &uniforms) override; void SetViewport2D(int x, int y, int w, int h) override; - void DisableState() override {} // Used by ReadFramebufferToMemory and later framebuffer block copies void BlitFramebuffer(VirtualFramebuffer *dst, int dstX, int dstY, VirtualFramebuffer *src, int srcX, int srcY, int w, int h, int bpp) override; From 0fe4e70aefa60e305777d12e1d09ab4751fef901 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 8 Feb 2018 16:47:04 +0100 Subject: [PATCH 3/4] Fix another way the scissor test could accidentally get disabled --- ext/native/thin3d/GLQueueRunner.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 3f5389cd6b..c8faa9958b 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -588,11 +588,12 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { #endif break; case GLRRenderCommand::CLEAR: - if (c.clear.scissorW > 0) { - glEnable(GL_SCISSOR_TEST); - glScissor(c.clear.scissorX, c.clear.scissorY, c.clear.scissorW, c.clear.scissorH); - } else { + // Scissor test is on, and should be on after leaving this case. If we disable it, + // we re-enable it at the end. + if (c.clear.scissorW == 0) { glDisable(GL_SCISSOR_TEST); + } else { + glScissor(c.clear.scissorX, c.clear.scissorY, c.clear.scissorW, c.clear.scissorH); } 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); @@ -614,9 +615,7 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { glClearStencil(c.clear.clearStencil); } glClear(c.clear.clearMask); - if (c.clear.scissorW > 0) { - glDisable(GL_SCISSOR_TEST); - } else { + if (c.clear.scissorW == 0) { glEnable(GL_SCISSOR_TEST); } break; From 625595c6cce2a103fad8eb301a864fec25c959ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 8 Feb 2018 16:59:03 +0100 Subject: [PATCH 4/4] For some reason we use DrawActiveTexture in the GL stencil stuff, don't want to disable stencil unconditionally.. --- GPU/Common/FramebufferCommon.h | 1 + GPU/GLES/FramebufferManagerGLES.cpp | 8 +++++--- GPU/GLES/StencilBufferGLES.cpp | 5 +++-- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/GPU/Common/FramebufferCommon.h b/GPU/Common/FramebufferCommon.h index d88dced994..89db174c8e 100644 --- a/GPU/Common/FramebufferCommon.h +++ b/GPU/Common/FramebufferCommon.h @@ -150,6 +150,7 @@ enum DrawTextureFlags { DRAWTEX_NEAREST = 0, DRAWTEX_LINEAR = 1, DRAWTEX_KEEP_TEX = 2, + DRAWTEX_KEEP_STENCIL = 4, }; inline Draw::DataFormat GEFormatToThin3D(int geFormat) { diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index 00f7da4195..e951ec2467 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -419,11 +419,13 @@ void FramebufferManagerGLES::DrawActiveTexture(float x, float y, float w, float pos[i * 3 + 1] = pos[i * 3 + 1] * invDestH - 1.0f; } - // We always want a plain state here. + // We always want a plain state here, well, except for when it's used by the stencil stuff... render_->SetNoBlendAndMask(0xF); render_->SetDepth(false, false, GL_ALWAYS); - render_->SetStencilDisabled(); - render_->SetRaster(false, GL_CCW, GL_FALSE, GL_FALSE); + render_->SetRaster(false, GL_CCW, GL_FRONT, GL_FALSE); + if (!(flags & DRAWTEX_KEEP_STENCIL)) { + render_->SetStencilDisabled(); + } // Upscaling postshaders don't look well with linear if (flags & DRAWTEX_LINEAR) { diff --git a/GPU/GLES/StencilBufferGLES.cpp b/GPU/GLES/StencilBufferGLES.cpp index d29e2bbf56..170fb997f4 100644 --- a/GPU/GLES/StencilBufferGLES.cpp +++ b/GPU/GLES/StencilBufferGLES.cpp @@ -170,6 +170,7 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe render_->SetDepth(false, false, GL_ALWAYS); 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_->SetRaster(false, GL_CCW, GL_FRONT, GL_FALSE); render_->BindProgram(stencilUploadProgram_); render_->SetNoBlendAndMask(0x8); @@ -188,14 +189,14 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe render_->SetStencilOp(i, GL_REPLACE, GL_REPLACE, GL_REPLACE); render_->SetUniformF1(&u_stencilValue, i * (1.0f / 255.0f)); } - DrawActiveTexture(0, 0, dstBuffer->width, dstBuffer->height, dstBuffer->bufferWidth, dstBuffer->bufferHeight, 0.0f, 0.0f, u1, v1, ROTATION_LOCKED_HORIZONTAL, DRAWTEX_NEAREST); + DrawActiveTexture(0, 0, dstBuffer->width, dstBuffer->height, dstBuffer->bufferWidth, dstBuffer->bufferHeight, 0.0f, 0.0f, u1, v1, ROTATION_LOCKED_HORIZONTAL, DRAWTEX_NEAREST | DRAWTEX_KEEP_STENCIL); } if (useBlit) { draw_->BlitFramebuffer(blitFBO, 0, 0, w, h, dstBuffer->fbo, 0, 0, dstBuffer->renderWidth, dstBuffer->renderHeight, Draw::FB_STENCIL_BIT, Draw::FB_BLIT_NEAREST); } - gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_VIEWPORTSCISSOR_STATE); + gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_RASTER_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_VIEWPORTSCISSOR_STATE); RebindFramebuffer(); return true; }