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
This commit is contained in:
gdkchan 2023-07-29 18:47:03 -03:00 committed by GitHub
parent eb528ae0f0
commit f95b7c5877
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 207 additions and 26 deletions

View file

@ -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<Viewport> 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);
}
/// <summary>
@ -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);
}
/// <summary>
/// Updates the viewport size on the support buffer for fragment shader access.
/// </summary>
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));
}
/// <summary>
/// Updates bindings consumed by the shader on the texture and buffer managers.
/// </summary>