From 9189aacfe28d0114fbfff0e3f89e8912f5377454 Mon Sep 17 00:00:00 2001 From: FernandoS27 Date: Sat, 23 Oct 2021 15:57:05 +0200 Subject: OpenGL: Fix viewport/Scissor scaling on downscaling. --- src/video_core/renderer_opengl/gl_rasterizer.cpp | 34 +++++++++++++++++++----- 1 file changed, 28 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 4df8a684a..d8ac46d2a 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -187,6 +187,7 @@ void RasterizerOpenGL::Clear() { std::scoped_lock lock{texture_cache.mutex}; texture_cache.UpdateRenderTargets(true); state_tracker.BindFramebuffer(texture_cache.GetFramebuffer()->Handle()); + SyncViewport(); if (regs.clear_flags.scissor) { SyncScissorTest(); } else { @@ -571,6 +572,15 @@ void RasterizerOpenGL::SyncViewport() { } const bool is_rescaling{texture_cache.IsRescaling()}; const float scale = is_rescaling ? Settings::values.resolution_info.up_factor : 1.0f; + const auto conv = [scale](float value) -> GLfloat { + float new_value = value * scale; + if (scale < 1.0f) { + const bool sign = std::signbit(value); + new_value = std::round(std::abs(new_value)); + new_value = sign ? -new_value : new_value; + } + return static_cast(new_value); + }; if (dirty_viewport) { flags[Dirty::Viewports] = false; @@ -586,10 +596,11 @@ void RasterizerOpenGL::SyncViewport() { flags[Dirty::Viewport0 + index] = false; const auto& src = regs.viewport_transform[index]; - GLfloat x = (src.translate_x - src.scale_x) * scale; - GLfloat y = (src.translate_y - src.scale_y) * scale; - GLfloat width = src.scale_x * 2.0f * scale; - GLfloat height = src.scale_y * 2.0f * scale; + GLfloat x = conv(src.translate_x - src.scale_x); + GLfloat y = conv(src.translate_y - src.scale_y); + GLfloat width = conv(src.scale_x * 2.0f); + GLfloat height = conv(src.scale_y * 2.0f); + if (height < 0) { y += height; height = -height; @@ -925,8 +936,19 @@ void RasterizerOpenGL::SyncScissorTest() { const auto& resolution = Settings::values.resolution_info; const bool is_rescaling{texture_cache.IsRescaling()}; - const auto scale_up = [resolution, is_rescaling](u32 value) { - return is_rescaling ? resolution.ScaleUp(value) : value; + const u32 up_scale = is_rescaling ? resolution.up_scale : 1U; + const u32 down_shift = is_rescaling ? resolution.down_shift : 0U; + const auto scale_up = [up_scale, down_shift](u32 value) -> u32 { + if (value == 0) { + return 0U; + } + const u32 upset = value * up_scale; + u32 acumm{}; + if ((up_scale >> down_shift) == 0) { + acumm = upset % 2; + } + const u32 converted_value = upset >> down_shift; + return std::max(converted_value + acumm, 1U); }; for (std::size_t index = 0; index < Maxwell::NumViewports; ++index) { if (!force && !flags[Dirty::Scissor0 + index]) { -- cgit v1.2.3