GS/OGL: Avoid framebuffer swaps when depth is being alternated

This commit is contained in:
Stenzek 2023-02-25 17:39:27 +10:00 committed by refractionpcsx2
parent 1b607a8c4d
commit b4beacfc43
5 changed files with 40 additions and 26 deletions

View File

@ -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);

View File

@ -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

View File

@ -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());

View File

@ -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);

View File

@ -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)