From b4beacfc43d03f7e17b83dbf5c55e51dc34e45e6 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Sat, 25 Feb 2023 17:39:27 +1000 Subject: [PATCH] GS/OGL: Avoid framebuffer swaps when depth is being alternated --- pcsx2/GS/Renderers/OpenGL/GLState.cpp | 8 ++-- pcsx2/GS/Renderers/OpenGL/GLState.h | 6 ++- pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.cpp | 43 ++++++++++++++-------- pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.h | 1 + pcsx2/GS/Renderers/OpenGL/GSTextureOGL.cpp | 8 ++-- 5 files changed, 40 insertions(+), 26 deletions(-) diff --git a/pcsx2/GS/Renderers/OpenGL/GLState.cpp b/pcsx2/GS/Renderers/OpenGL/GLState.cpp index 548b2a036e..b61c9e8210 100644 --- a/pcsx2/GS/Renderers/OpenGL/GLState.cpp +++ b/pcsx2/GS/Renderers/OpenGL/GLState.cpp @@ -42,8 +42,8 @@ namespace GLState GLuint ps_ss; - GLuint rt; - GLuint ds; + GSTextureOGL* rt = nullptr; + GSTextureOGL* ds = nullptr; GLuint tex_unit[8]; GLuint64 tex_handle[8]; @@ -72,8 +72,8 @@ namespace GLState ps_ss = 0; - rt = 0; - ds = 0; + rt = nullptr; + ds = nullptr; std::fill(std::begin(tex_unit), std::end(tex_unit), 0); std::fill(std::begin(tex_handle), std::end(tex_handle), 0); diff --git a/pcsx2/GS/Renderers/OpenGL/GLState.h b/pcsx2/GS/Renderers/OpenGL/GLState.h index 0db75ecff4..46e49a78be 100644 --- a/pcsx2/GS/Renderers/OpenGL/GLState.h +++ b/pcsx2/GS/Renderers/OpenGL/GLState.h @@ -18,6 +18,8 @@ #include "GS/Renderers/OpenGL/GLLoader.h" #include "GS/GSVector.h" +class GSTextureOGL; + namespace GLState { extern GLuint fbo; // frame buffer object @@ -44,8 +46,8 @@ namespace GLState extern GLuint ps_ss; // sampler - extern GLuint rt; // render target - extern GLuint ds; // Depth-Stencil + extern GSTextureOGL* rt; // render target + extern GSTextureOGL* ds; // Depth-Stencil extern GLuint tex_unit[8]; // shader input texture extern GLuint64 tex_handle[8]; // shader input texture diff --git a/pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.cpp b/pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.cpp index 0a1bed915f..d5ccff3a9c 100644 --- a/pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.cpp +++ b/pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.cpp @@ -1600,35 +1600,27 @@ bool GSDeviceOGL::DoCAS(GSTexture* sTex, GSTexture* dTex, bool sharpen_only, con void GSDeviceOGL::OMAttachRt(GSTextureOGL* rt) { - GLuint id = 0; if (rt) - { rt->WasAttached(); - id = rt->GetID(); - } - if (GLState::rt != id) + if (GLState::rt != rt) { - GLState::rt = id; - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, id, 0); + GLState::rt = rt; + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt ? rt->GetID() : 0, 0); } } void GSDeviceOGL::OMAttachDs(GSTextureOGL* ds) { - GLuint id = 0; if (ds) - { ds->WasAttached(); - id = ds->GetID(); - } - if (GLState::ds != id) + if (GLState::ds != ds) { - GLState::ds = id; + GLState::ds = ds; const GLenum target = m_features.framebuffer_fetch ? GL_DEPTH_ATTACHMENT : GL_DEPTH_STENCIL_ATTACHMENT; - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, target, GL_TEXTURE_2D, id, 0); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, target, GL_TEXTURE_2D, ds ? ds->GetID() : 0, 0); } } @@ -1657,6 +1649,14 @@ void GSDeviceOGL::OMSetColorMaskState(OMColorMaskSelector sel) } } +void GSDeviceOGL::OMUnbindTexture(GSTextureOGL* tex) +{ + if (GLState::rt == tex) + OMAttachRt(); + if (GLState::ds == tex) + OMAttachDs(); +} + void GSDeviceOGL::OMSetBlendState(bool enable, GLenum src_factor, GLenum dst_factor, GLenum op, bool is_constant, u8 constant) { if (enable) @@ -1968,8 +1968,21 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config) s_gl_blend_factors[config.blend.dst_factor], s_gl_blend_ops[config.blend.op], config.blend.constant_enable, config.blend.constant); OMSetColorMaskState(config.colormask); + + // avoid changing framebuffer just to switch from rt+depth to rt and vice versa + GSTexture* draw_rt = hdr_rt ? hdr_rt : config.rt; + GSTexture* draw_ds = config.ds; + if (!draw_ds && GLState::ds && GLState::rt == draw_rt && config.tex != GLState::ds && + GLState::ds->GetSize() == draw_rt->GetSize()) + { + // should already be always-pass. + draw_ds = GLState::ds; + config.depth.ztst = ZTST_ALWAYS; + config.depth.zwe = false; + } + + OMSetRenderTargets(draw_rt, draw_ds, &config.scissor); SetupOM(config.depth); - OMSetRenderTargets(hdr_rt ? hdr_rt : config.rt, config.ds, &config.scissor); SendHWDraw(config, psel.ps.IsFeedbackLoop()); diff --git a/pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.h b/pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.h index c1cc2f3185..ec0a920675 100644 --- a/pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.h +++ b/pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.h @@ -357,6 +357,7 @@ public: void OMSetBlendState(bool enable = false, GLenum src_factor = GL_ONE, GLenum dst_factor = GL_ZERO, GLenum op = GL_FUNC_ADD, bool is_constant = false, u8 constant = 0); void OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVector4i* scissor = NULL); void OMSetColorMaskState(OMColorMaskSelector sel = OMColorMaskSelector()); + void OMUnbindTexture(GSTextureOGL* tex); bool CreateTextureFX(); std::string GetShaderSource(const std::string_view& entry, GLenum type, const std::string_view& common_header, const std::string_view& glsl_h_code, const std::string_view& macro_sel); diff --git a/pcsx2/GS/Renderers/OpenGL/GSTextureOGL.cpp b/pcsx2/GS/Renderers/OpenGL/GSTextureOGL.cpp index c239e7a713..20b35f8d65 100644 --- a/pcsx2/GS/Renderers/OpenGL/GSTextureOGL.cpp +++ b/pcsx2/GS/Renderers/OpenGL/GSTextureOGL.cpp @@ -174,12 +174,10 @@ GSTextureOGL::GSTextureOGL(Type type, int width, int height, int levels, Format GSTextureOGL::~GSTextureOGL() { - /* Unbind the texture from our local state */ + // Textures aren't cleared from attachments on deletion. + GSDeviceOGL::GetInstance()->OMUnbindTexture(this); - if (m_texture_id == GLState::rt) - GLState::rt = 0; - if (m_texture_id == GLState::ds) - GLState::ds = 0; + // But they are unbound. for (GLuint& tex : GLState::tex_unit) { if (m_texture_id == tex)