aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Graphics.Gpu
diff options
context:
space:
mode:
Diffstat (limited to 'src/Ryujinx.Graphics.Gpu')
-rw-r--r--src/Ryujinx.Graphics.Gpu/Engine/Threed/SpecializationStateUpdater.cs14
-rw-r--r--src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs47
-rw-r--r--src/Ryujinx.Graphics.Gpu/Memory/SupportBufferUpdater.cs30
-rw-r--r--src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheGpuAccessor.cs6
-rw-r--r--src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs9
-rw-r--r--src/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs16
-rw-r--r--src/Ryujinx.Graphics.Gpu/Shader/GpuChannelGraphicsState.cs12
-rw-r--r--src/Ryujinx.Graphics.Gpu/Shader/ShaderSpecializationState.cs5
8 files changed, 128 insertions, 11 deletions
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();
}
}
+
+ /// <summary>
+ /// Sets the Y negate enabled state.
+ /// </summary>
+ /// <param name="enabled">True if Y negate of the fragment coordinates is enabled</param>
+ 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<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,10 +1424,42 @@ 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>
/// <param name="bindings">Bindings for the active shader</param>
diff --git a/src/Ryujinx.Graphics.Gpu/Memory/SupportBufferUpdater.cs b/src/Ryujinx.Graphics.Gpu/Memory/SupportBufferUpdater.cs
index 50c042fb..b236476e 100644
--- a/src/Ryujinx.Graphics.Gpu/Memory/SupportBufferUpdater.cs
+++ b/src/Ryujinx.Graphics.Gpu/Memory/SupportBufferUpdater.cs
@@ -113,6 +113,17 @@ namespace Ryujinx.Graphics.Gpu.Memory
}
/// <summary>
+ /// Updates the viewport size vector.
+ /// </summary>
+ /// <param name="data">Viewport size vector</param>
+ private void UpdateViewportSize(Vector4<float> data)
+ {
+ _data.ViewportSize = data;
+
+ MarkDirty(SupportBuffer.ViewportSizeOffset, SupportBuffer.FieldSize);
+ }
+
+ /// <summary>
/// Sets the scale of all output render targets (they should all have the same scale).
/// </summary>
/// <param name="scale">Scale value</param>
@@ -193,6 +204,25 @@ namespace Ryujinx.Graphics.Gpu.Memory
}
/// <summary>
+ /// Sets the viewport size, used to invert the fragment coordinates Y value.
+ /// </summary>
+ /// <param name="viewportWidth">Value used as viewport width</param>
+ /// <param name="viewportHeight">Value used as viewport height</param>
+ public void SetViewportSize(float viewportWidth, float viewportHeight)
+ {
+ if (_data.ViewportSize.X != viewportWidth || _data.ViewportSize.Y != viewportHeight)
+ {
+ UpdateViewportSize(new Vector4<float>
+ {
+ X = viewportWidth,
+ Y = viewportHeight,
+ Z = 1,
+ W = 0
+ });
+ }
+ }
+
+ /// <summary>
/// Submits all pending buffer updates to the GPU.
/// </summary>
public void Commit()
diff --git a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheGpuAccessor.cs b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheGpuAccessor.cs
index 7f01aca6..b5f9395e 100644
--- a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheGpuAccessor.cs
+++ b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheGpuAccessor.cs
@@ -248,6 +248,12 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
}
/// <inheritdoc/>
+ public bool QueryYNegateEnabled()
+ {
+ return _oldSpecState.GraphicsState.YNegateEnabled;
+ }
+
+ /// <inheritdoc/>
public void RegisterTexture(int handle, int cbufSlot)
{
if (!_oldSpecState.TextureRegistered(_stageIndex, handle, cbufSlot))
diff --git a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs
index 672b3b8d..4bab165d 100644
--- a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs
+++ b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs
@@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
private const ushort FileFormatVersionMajor = 1;
private const ushort FileFormatVersionMinor = 2;
private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor;
- private const uint CodeGenVersion = 5266;
+ private const uint CodeGenVersion = 4675;
private const string SharedTocFileName = "shared.toc";
private const string SharedDataFileName = "shared.data";
@@ -141,6 +141,11 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
public ShaderStage Stage;
/// <summary>
+ /// Indicates if the fragment shader accesses the fragment coordinate built-in variable.
+ /// </summary>
+ public bool UsesFragCoord;
+
+ /// <summary>
/// Indicates if the shader accesses the Instance ID built-in variable.
/// </summary>
public bool UsesInstanceId;
@@ -781,6 +786,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
ShaderIdentification.None,
0,
dataInfo.Stage,
+ dataInfo.UsesFragCoord,
dataInfo.UsesInstanceId,
dataInfo.UsesDrawParameters,
dataInfo.UsesRtLayer,
@@ -807,6 +813,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
TexturesCount = (ushort)info.Textures.Count,
ImagesCount = (ushort)info.Images.Count,
Stage = info.Stage,
+ UsesFragCoord = info.UsesFragCoord,
UsesInstanceId = info.UsesInstanceId,
UsesDrawParameters = info.UsesDrawParameters,
UsesRtLayer = info.UsesRtLayer,
diff --git a/src/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs b/src/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs
index ca9c883e..1fcc93c5 100644
--- a/src/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs
+++ b/src/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs
@@ -114,6 +114,13 @@ namespace Ryujinx.Graphics.Gpu.Shader
}
/// <inheritdoc/>
+ public bool QueryEarlyZForce()
+ {
+ _state.SpecializationState?.RecordEarlyZForce();
+ return _state.GraphicsState.EarlyZForce;
+ }
+
+ /// <inheritdoc/>
public AttributeType QueryFragmentOutputType(int location)
{
return _state.GraphicsState.FragmentOutputTypes[location];
@@ -276,16 +283,15 @@ namespace Ryujinx.Graphics.Gpu.Shader
}
/// <inheritdoc/>
- public bool QueryEarlyZForce()
+ public bool QueryViewportTransformDisable()
{
- _state.SpecializationState?.RecordEarlyZForce();
- return _state.GraphicsState.EarlyZForce;
+ return _state.GraphicsState.ViewportTransformDisable;
}
/// <inheritdoc/>
- public bool QueryViewportTransformDisable()
+ public bool QueryYNegateEnabled()
{
- return _state.GraphicsState.ViewportTransformDisable;
+ return _state.GraphicsState.YNegateEnabled;
}
/// <inheritdoc/>
diff --git a/src/Ryujinx.Graphics.Gpu/Shader/GpuChannelGraphicsState.cs b/src/Ryujinx.Graphics.Gpu/Shader/GpuChannelGraphicsState.cs
index 544e689a..f392491c 100644
--- a/src/Ryujinx.Graphics.Gpu/Shader/GpuChannelGraphicsState.cs
+++ b/src/Ryujinx.Graphics.Gpu/Shader/GpuChannelGraphicsState.cs
@@ -98,6 +98,11 @@ namespace Ryujinx.Graphics.Gpu.Shader
public bool DualSourceBlendEnable;
/// <summary>
+ /// Indicates whether Y negate of the fragment coordinates is enabled.
+ /// </summary>
+ public bool YNegateEnabled;
+
+ /// <summary>
/// Creates a new GPU graphics state.
/// </summary>
/// <param name="earlyZForce">Early Z force enable</param>
@@ -116,7 +121,8 @@ namespace Ryujinx.Graphics.Gpu.Shader
/// <param name="hasConstantBufferDrawParameters">Indicates that the draw is writing the base vertex, base instance and draw index to Constant Buffer 0</param>
/// <param name="hasUnalignedStorageBuffer">Indicates that any storage buffer use is unaligned</param>
/// <param name="fragmentOutputTypes">Type of the fragment shader outputs</param>
- /// <param name="dualSourceBlendEnable">Type of the vertex attributes consumed by the shader</param>
+ /// <param name="dualSourceBlendEnable">Indicates whether dual source blend is enabled</param>
+ /// <param name="yNegateEnabled">Indicates whether Y negate of the fragment coordinates is enabled</param>
public GpuChannelGraphicsState(
bool earlyZForce,
PrimitiveTopology topology,
@@ -134,7 +140,8 @@ namespace Ryujinx.Graphics.Gpu.Shader
bool hasConstantBufferDrawParameters,
bool hasUnalignedStorageBuffer,
ref Array8<AttributeType> fragmentOutputTypes,
- bool dualSourceBlendEnable)
+ bool dualSourceBlendEnable,
+ bool yNegateEnabled)
{
EarlyZForce = earlyZForce;
Topology = topology;
@@ -153,6 +160,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
HasUnalignedStorageBuffer = hasUnalignedStorageBuffer;
FragmentOutputTypes = fragmentOutputTypes;
DualSourceBlendEnable = dualSourceBlendEnable;
+ YNegateEnabled = yNegateEnabled;
}
}
}
diff --git a/src/Ryujinx.Graphics.Gpu/Shader/ShaderSpecializationState.cs b/src/Ryujinx.Graphics.Gpu/Shader/ShaderSpecializationState.cs
index 775bfb2a..b33f96c5 100644
--- a/src/Ryujinx.Graphics.Gpu/Shader/ShaderSpecializationState.cs
+++ b/src/Ryujinx.Graphics.Gpu/Shader/ShaderSpecializationState.cs
@@ -540,6 +540,11 @@ namespace Ryujinx.Graphics.Gpu.Shader
return false;
}
+ if (graphicsState.YNegateEnabled != GraphicsState.YNegateEnabled)
+ {
+ return false;
+ }
+
return Matches(channel, ref poolState, checkTextures, isCompute: false);
}