From f95b7c58779f01d9077996da67953d8d9acd058c Mon Sep 17 00:00:00 2001 From: gdkchan Date: Sat, 29 Jul 2023 18:47:03 -0300 Subject: Fix incorrect fragment origin when YNegate is enabled (#4673) * Fix incorrect fragment origin when YNegate is enabled * Shader cache version bump * Do not update support buffer if shader does not read gl_FragCoord * Pass unscaled viewport size to the support buffer --- .../Engine/Threed/SpecializationStateUpdater.cs | 14 +++++++ .../Engine/Threed/StateUpdater.cs | 47 ++++++++++++++++++++-- 2 files changed, 58 insertions(+), 3 deletions(-) (limited to 'src/Ryujinx.Graphics.Gpu/Engine') diff --git a/src/Ryujinx.Graphics.Gpu/Engine/Threed/SpecializationStateUpdater.cs b/src/Ryujinx.Graphics.Gpu/Engine/Threed/SpecializationStateUpdater.cs index cbf1573c..b2935a5b 100644 --- a/src/Ryujinx.Graphics.Gpu/Engine/Threed/SpecializationStateUpdater.cs +++ b/src/Ryujinx.Graphics.Gpu/Engine/Threed/SpecializationStateUpdater.cs @@ -342,5 +342,19 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed Signal(); } } + + /// + /// Sets the Y negate enabled state. + /// + /// True if Y negate of the fragment coordinates is enabled + public void SetYNegateEnabled(bool enabled) + { + if (enabled != _graphics.YNegateEnabled) + { + _graphics.YNegateEnabled = enabled; + + Signal(); + } + } } } diff --git a/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs b/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs index b4f56245..c0c2d5b3 100644 --- a/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs +++ b/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs @@ -37,6 +37,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed private ProgramPipelineState _pipeline; + private bool _fsReadsFragCoord; private bool _vsUsesDrawParameters; private bool _vtgWritesRtLayer; private byte _vsClipDistancesWritten; @@ -692,12 +693,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed var face = _state.State.FaceState; bool disableTransform = _state.State.ViewportTransformEnable == 0; + bool yNegate = yControl.HasFlag(YControl.NegateY); UpdateFrontFace(yControl, face.FrontFace); UpdateDepthMode(); - bool flipY = yControl.HasFlag(YControl.NegateY); - Span viewports = stackalloc Viewport[Constants.TotalViewports]; for (int index = 0; index < Constants.TotalViewports; index++) @@ -719,7 +719,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed float scaleX = MathF.Abs(transform.ScaleX); float scaleY = transform.ScaleY; - if (flipY) + if (yNegate) { scaleY = -scaleY; } @@ -771,8 +771,17 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed _channel.TextureManager.RenderTargetScale, disableTransform); + // Viewport size is only used on the shader when YNegate is enabled, + // and if the fragment shader accesses gl_FragCoord, + // so there's no need to update it in other cases. + if (yNegate && _fsReadsFragCoord) + { + UpdateSupportBufferViewportSize(); + } + _currentSpecState.SetViewportTransformDisable(disableTransform); _currentSpecState.SetDepthMode(GetDepthMode() == DepthMode.MinusOneToOne); + _currentSpecState.SetYNegateEnabled(yNegate); } /// @@ -1415,9 +1424,41 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed _currentProgramInfo[stageIndex] = info; } + if (gs.Shaders[5]?.Info.UsesFragCoord == true) + { + // Make sure we update the viewport size on the support buffer if it will be consumed on the new shader. + + if (!_fsReadsFragCoord && _state.State.YControl.HasFlag(YControl.NegateY)) + { + UpdateSupportBufferViewportSize(); + } + + _fsReadsFragCoord = true; + } + else + { + _fsReadsFragCoord = false; + } + _context.Renderer.Pipeline.SetProgram(gs.HostProgram); } + /// + /// Updates the viewport size on the support buffer for fragment shader access. + /// + private void UpdateSupportBufferViewportSize() + { + ref var transform = ref _state.State.ViewportTransform[0]; + + float scaleX = MathF.Abs(transform.ScaleX); + float scaleY = transform.ScaleY; + + float width = scaleX * 2; + float height = scaleY * 2; + + _context.SupportBufferUpdater.SetViewportSize(width, MathF.Abs(height)); + } + /// /// Updates bindings consumed by the shader on the texture and buffer managers. /// -- cgit v1.2.3