1
0
Fork 0
forked from suyu/suyu

renderer_opengl: Fix sRGB blits

Removes the sRGB hack of tracking if a frame used an sRGB rendertarget
to apply at least once to blit the final texture as sRGB. Instead of
doing this apply sRGB if the presented image has sRGB.

Also enable sRGB by default on Maxwell3D registers as some games seem to
assume this.
This commit is contained in:
ReinUsesLisp 2019-09-03 01:05:23 -03:00
parent 34b2c60f95
commit 78574746bd
6 changed files with 10 additions and 43 deletions

View file

@ -89,6 +89,9 @@ void Maxwell3D::InitializeRegisterDefaults() {
// Commercial games seem to assume this value is enabled and nouveau sets this value manually. // Commercial games seem to assume this value is enabled and nouveau sets this value manually.
regs.rt_separate_frag_data = 1; regs.rt_separate_frag_data = 1;
// Some games (like Super Mario Odyssey) assume that SRGB is enabled.
regs.framebuffer_srgb = 1;
} }
#define DIRTY_REGS_POS(field_name) (offsetof(Maxwell3D::DirtyRegs, field_name)) #define DIRTY_REGS_POS(field_name) (offsetof(Maxwell3D::DirtyRegs, field_name))

View file

@ -485,15 +485,6 @@ std::pair<bool, bool> RasterizerOpenGL::ConfigureFramebuffers(
View color_surface{ View color_surface{
texture_cache.GetColorBufferSurface(*single_color_target, preserve_contents)}; texture_cache.GetColorBufferSurface(*single_color_target, preserve_contents)};
if (color_surface) {
// Assume that a surface will be written to if it is used as a framebuffer, even if
// the shader doesn't actually write to it.
texture_cache.MarkColorBufferInUse(*single_color_target);
// Workaround for and issue in nvidia drivers
// https://devtalk.nvidia.com/default/topic/776591/opengl/gl_framebuffer_srgb-functions-incorrectly/
state.framebuffer_srgb.enabled |= color_surface->GetSurfaceParams().srgb_conversion;
}
fbkey.is_single_buffer = true; fbkey.is_single_buffer = true;
fbkey.color_attachments[0] = fbkey.color_attachments[0] =
GL_COLOR_ATTACHMENT0 + static_cast<GLenum>(*single_color_target); GL_COLOR_ATTACHMENT0 + static_cast<GLenum>(*single_color_target);
@ -508,17 +499,6 @@ std::pair<bool, bool> RasterizerOpenGL::ConfigureFramebuffers(
for (std::size_t index = 0; index < Maxwell::NumRenderTargets; ++index) { for (std::size_t index = 0; index < Maxwell::NumRenderTargets; ++index) {
View color_surface{texture_cache.GetColorBufferSurface(index, preserve_contents)}; View color_surface{texture_cache.GetColorBufferSurface(index, preserve_contents)};
if (color_surface) {
// Assume that a surface will be written to if it is used as a framebuffer, even
// if the shader doesn't actually write to it.
texture_cache.MarkColorBufferInUse(index);
// Enable sRGB only for supported formats
// Workaround for and issue in nvidia drivers
// https://devtalk.nvidia.com/default/topic/776591/opengl/gl_framebuffer_srgb-functions-incorrectly/
state.framebuffer_srgb.enabled |=
color_surface->GetSurfaceParams().srgb_conversion;
}
fbkey.color_attachments[index] = fbkey.color_attachments[index] =
GL_COLOR_ATTACHMENT0 + regs.rt_control.GetMap(index); GL_COLOR_ATTACHMENT0 + regs.rt_control.GetMap(index);
fbkey.colors[index] = color_surface; fbkey.colors[index] = color_surface;
@ -906,6 +886,7 @@ bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& config,
} }
screen_info.display_texture = surface->GetTexture(); screen_info.display_texture = surface->GetTexture();
screen_info.display_srgb = surface->GetSurfaceParams().srgb_conversion;
return true; return true;
} }

View file

@ -16,7 +16,6 @@ namespace OpenGL {
using Maxwell = Tegra::Engines::Maxwell3D::Regs; using Maxwell = Tegra::Engines::Maxwell3D::Regs;
OpenGLState OpenGLState::cur_state; OpenGLState OpenGLState::cur_state;
bool OpenGLState::s_rgb_used;
namespace { namespace {
@ -282,8 +281,6 @@ void OpenGLState::ApplySRgb() const {
return; return;
cur_state.framebuffer_srgb.enabled = framebuffer_srgb.enabled; cur_state.framebuffer_srgb.enabled = framebuffer_srgb.enabled;
if (framebuffer_srgb.enabled) { if (framebuffer_srgb.enabled) {
// Track if sRGB is used
s_rgb_used = true;
glEnable(GL_FRAMEBUFFER_SRGB); glEnable(GL_FRAMEBUFFER_SRGB);
} else { } else {
glDisable(GL_FRAMEBUFFER_SRGB); glDisable(GL_FRAMEBUFFER_SRGB);

View file

@ -175,14 +175,6 @@ public:
return cur_state; return cur_state;
} }
static bool GetsRGBUsed() {
return s_rgb_used;
}
static void ClearsRGBUsed() {
s_rgb_used = false;
}
void SetDefaultViewports(); void SetDefaultViewports();
/// Apply this state as the current OpenGL state /// Apply this state as the current OpenGL state
void Apply(); void Apply();
@ -253,8 +245,6 @@ public:
private: private:
static OpenGLState cur_state; static OpenGLState cur_state;
// Workaround for sRGB problems caused by QT not supporting srgb output
static bool s_rgb_used;
struct { struct {
bool blend_state; bool blend_state;
bool stencil_state; bool stencil_state;

View file

@ -264,7 +264,6 @@ void RendererOpenGL::CreateRasterizer() {
if (rasterizer) { if (rasterizer) {
return; return;
} }
OpenGLState::ClearsRGBUsed();
rasterizer = std::make_unique<RasterizerOpenGL>(system, emu_window, screen_info); rasterizer = std::make_unique<RasterizerOpenGL>(system, emu_window, screen_info);
} }
@ -342,10 +341,8 @@ void RendererOpenGL::DrawScreenTriangles(const ScreenInfo& screen_info, float x,
ScreenRectVertex(x + w, y + h, texcoords.bottom * scale_u, right * scale_v), ScreenRectVertex(x + w, y + h, texcoords.bottom * scale_u, right * scale_v),
}}; }};
state.textures[0] = screen_info.display_texture; state.textures[0].texture = screen_info.display_texture;
// Workaround brigthness problems in SMO by enabling sRGB in the final output state.framebuffer_srgb.enabled = screen_info.display_srgb;
// if it has been used in the frame. Needed because of this bug in QT: QTBUG-50987
state.framebuffer_srgb.enabled = OpenGLState::GetsRGBUsed();
state.AllDirty(); state.AllDirty();
state.Apply(); state.Apply();
glNamedBufferSubData(vertex_buffer.handle, 0, sizeof(vertices), vertices.data()); glNamedBufferSubData(vertex_buffer.handle, 0, sizeof(vertices), vertices.data());
@ -355,8 +352,6 @@ void RendererOpenGL::DrawScreenTriangles(const ScreenInfo& screen_info, float x,
state.textures[0] = 0; state.textures[0] = 0;
state.AllDirty(); state.AllDirty();
state.Apply(); state.Apply();
// Clear sRGB state for the next frame
OpenGLState::ClearsRGBUsed();
} }
/** /**
@ -406,8 +401,8 @@ void RendererOpenGL::CaptureScreenshot() {
GLuint renderbuffer; GLuint renderbuffer;
glGenRenderbuffers(1, &renderbuffer); glGenRenderbuffers(1, &renderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer); glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, state.GetsRGBUsed() ? GL_SRGB8 : GL_RGB8, layout.width, glRenderbufferStorage(GL_RENDERBUFFER, screen_info.display_srgb ? GL_SRGB8 : GL_RGB8,
layout.height); layout.width, layout.height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
DrawScreen(layout); DrawScreen(layout);

View file

@ -38,7 +38,8 @@ struct TextureInfo {
/// Structure used for storing information about the display target for the Switch screen /// Structure used for storing information about the display target for the Switch screen
struct ScreenInfo { struct ScreenInfo {
GLuint display_texture; GLuint display_texture{};
bool display_srgb{};
const Common::Rectangle<float> display_texcoords{0.0f, 0.0f, 1.0f, 1.0f}; const Common::Rectangle<float> display_texcoords{0.0f, 0.0f, 1.0f, 1.0f};
TextureInfo texture; TextureInfo texture;
}; };