diff options
Diffstat (limited to 'src/Ryujinx.Graphics.Gpu')
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); } |