From 3e5e983799c0df845c9a095a6b10935e03c3ffb3 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Tue, 3 Sep 2019 01:05:23 -0300 Subject: [PATCH 1/3] 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. --- src/video_core/engines/maxwell_3d.cpp | 3 +++ .../renderer_opengl/gl_rasterizer.cpp | 21 +------------------ src/video_core/renderer_opengl/gl_state.cpp | 3 --- src/video_core/renderer_opengl/gl_state.h | 10 --------- .../renderer_opengl/renderer_opengl.cpp | 13 ++++-------- .../renderer_opengl/renderer_opengl.h | 3 ++- 6 files changed, 10 insertions(+), 43 deletions(-) diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index c8c92757ab..965c4c06bc 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp @@ -89,6 +89,9 @@ void Maxwell3D::InitializeRegisterDefaults() { // Commercial games seem to assume this value is enabled and nouveau sets this value manually. 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)) diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 4e266cdad2..f7397dd64c 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -485,15 +485,6 @@ std::pair RasterizerOpenGL::ConfigureFramebuffers( View color_surface{ 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.color_attachments[0] = GL_COLOR_ATTACHMENT0 + static_cast(*single_color_target); @@ -508,17 +499,6 @@ std::pair RasterizerOpenGL::ConfigureFramebuffers( for (std::size_t index = 0; index < Maxwell::NumRenderTargets; ++index) { 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] = GL_COLOR_ATTACHMENT0 + regs.rt_control.GetMap(index); 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_srgb = surface->GetSurfaceParams().srgb_conversion; return true; } diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp index 6eabf4fac3..bf86b5a0b8 100644 --- a/src/video_core/renderer_opengl/gl_state.cpp +++ b/src/video_core/renderer_opengl/gl_state.cpp @@ -16,7 +16,6 @@ namespace OpenGL { using Maxwell = Tegra::Engines::Maxwell3D::Regs; OpenGLState OpenGLState::cur_state; -bool OpenGLState::s_rgb_used; namespace { @@ -282,8 +281,6 @@ void OpenGLState::ApplySRgb() const { return; cur_state.framebuffer_srgb.enabled = framebuffer_srgb.enabled; if (framebuffer_srgb.enabled) { - // Track if sRGB is used - s_rgb_used = true; glEnable(GL_FRAMEBUFFER_SRGB); } else { glDisable(GL_FRAMEBUFFER_SRGB); diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h index 949b13051a..c358d3b383 100644 --- a/src/video_core/renderer_opengl/gl_state.h +++ b/src/video_core/renderer_opengl/gl_state.h @@ -175,14 +175,6 @@ public: return cur_state; } - static bool GetsRGBUsed() { - return s_rgb_used; - } - - static void ClearsRGBUsed() { - s_rgb_used = false; - } - void SetDefaultViewports(); /// Apply this state as the current OpenGL state void Apply(); @@ -253,8 +245,6 @@ public: private: static OpenGLState cur_state; - // Workaround for sRGB problems caused by QT not supporting srgb output - static bool s_rgb_used; struct { bool blend_state; bool stencil_state; diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 8391781521..d6e1e5aba4 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -264,7 +264,6 @@ void RendererOpenGL::CreateRasterizer() { if (rasterizer) { return; } - OpenGLState::ClearsRGBUsed(); rasterizer = std::make_unique(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), }}; - state.textures[0] = screen_info.display_texture; - // Workaround brigthness problems in SMO by enabling sRGB in the final output - // if it has been used in the frame. Needed because of this bug in QT: QTBUG-50987 - state.framebuffer_srgb.enabled = OpenGLState::GetsRGBUsed(); + state.textures[0].texture = screen_info.display_texture; + state.framebuffer_srgb.enabled = screen_info.display_srgb; state.AllDirty(); state.Apply(); 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.AllDirty(); state.Apply(); - // Clear sRGB state for the next frame - OpenGLState::ClearsRGBUsed(); } /** @@ -406,8 +401,8 @@ void RendererOpenGL::CaptureScreenshot() { GLuint renderbuffer; glGenRenderbuffers(1, &renderbuffer); glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer); - glRenderbufferStorage(GL_RENDERBUFFER, state.GetsRGBUsed() ? GL_SRGB8 : GL_RGB8, layout.width, - layout.height); + glRenderbufferStorage(GL_RENDERBUFFER, screen_info.display_srgb ? GL_SRGB8 : GL_RGB8, + layout.width, layout.height); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer); DrawScreen(layout); diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h index 9bd0863689..cf26628ca4 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.h +++ b/src/video_core/renderer_opengl/renderer_opengl.h @@ -38,7 +38,8 @@ struct TextureInfo { /// Structure used for storing information about the display target for the Switch screen struct ScreenInfo { - GLuint display_texture; + GLuint display_texture{}; + bool display_srgb{}; const Common::Rectangle display_texcoords{0.0f, 0.0f, 1.0f, 1.0f}; TextureInfo texture; }; From 997f808f69e5eec6bdb61e83f82e07c2e38b2949 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Sat, 7 Sep 2019 19:26:16 -0400 Subject: [PATCH 2/3] gl_rasterizer: Correct sRGB Fix regression --- src/video_core/renderer_opengl/gl_rasterizer.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index f7397dd64c..4dd08bccba 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -485,6 +485,12 @@ std::pair RasterizerOpenGL::ConfigureFramebuffers( View color_surface{ 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); + } + fbkey.is_single_buffer = true; fbkey.color_attachments[0] = GL_COLOR_ATTACHMENT0 + static_cast(*single_color_target); @@ -499,6 +505,12 @@ std::pair RasterizerOpenGL::ConfigureFramebuffers( for (std::size_t index = 0; index < Maxwell::NumRenderTargets; ++index) { 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); + } + fbkey.color_attachments[index] = GL_COLOR_ATTACHMENT0 + regs.rt_control.GetMap(index); fbkey.colors[index] = color_surface; From 8718c70d99880bd3dde8be3e5a9cd4291bc19bc5 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Wed, 11 Sep 2019 00:09:37 -0300 Subject: [PATCH 3/3] renderer_opengl: Fix rebase mistake --- src/video_core/renderer_opengl/renderer_opengl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index d6e1e5aba4..1e6ef66abd 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -341,7 +341,7 @@ void RendererOpenGL::DrawScreenTriangles(const ScreenInfo& screen_info, float x, ScreenRectVertex(x + w, y + h, texcoords.bottom * scale_u, right * scale_v), }}; - state.textures[0].texture = screen_info.display_texture; + state.textures[0] = screen_info.display_texture; state.framebuffer_srgb.enabled = screen_info.display_srgb; state.AllDirty(); state.Apply();