From b423197619dd8d9dda1c255a76105bf30e255dae Mon Sep 17 00:00:00 2001 From: gdkchan Date: Sun, 13 Aug 2023 22:26:42 -0300 Subject: Delete ShaderConfig and organize shader resources/definitions better (#5509) * Move some properties out of ShaderConfig * Stop using ShaderConfig on backends * Replace ShaderConfig usages on Translator and passes * Move remaining properties out of ShaderConfig and delete ShaderConfig * Remove ResourceManager property from TranslatorContext * Move Rewriter passes to separate transform pass files * Fix TransformPasses.RunPass on cases where a node is removed * Move remaining ClipDistancePrimitivesWritten and UsedFeatures updates to decode stage * Reduce excessive parameter passing a bit by using structs more * Remove binding parameter from ShaderProperties methods since it is redundant * Replace decoder instruction checks with switch statement * Put GLSL on the same plan as SPIR-V for input/output declaration * Stop mutating TranslatorContext state when Translate is called * Pass most of the graphics state using a struct instead of individual query methods * Auto-format * Auto-format * Add backend logging interface * Auto-format * Remove unnecessary use of interpolated strings * Remove more modifications of AttributeUsage after decode * PR feedback * gl_Layer is not supported on compute --- .../Shader/DiskCache/DiskCacheGpuAccessor.cs | 119 ++----------------- src/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs | 126 ++------------------ src/Ryujinx.Graphics.Gpu/Shader/GpuAccessorBase.cs | 29 ----- .../Shader/GpuChannelGraphicsState.cs | 131 ++++++++++++--------- .../Shader/ShaderSpecializationState.cs | 18 --- 5 files changed, 96 insertions(+), 327 deletions(-) (limited to 'src/Ryujinx.Graphics.Gpu/Shader') diff --git a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheGpuAccessor.cs b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheGpuAccessor.cs index b5f9395e..93d293f6 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheGpuAccessor.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheGpuAccessor.cs @@ -1,5 +1,4 @@ using Ryujinx.Common.Logging; -using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.Gpu.Image; using Ryujinx.Graphics.Shader; using Ryujinx.Graphics.Shader.Translation; @@ -44,6 +43,12 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache _newSpecState = newSpecState; _stageIndex = stageIndex; _isVulkan = context.Capabilities.Api == TargetApi.Vulkan; + + if (stageIndex == (int)ShaderStage.Geometry - 1) + { + // Only geometry shaders require the primitive topology. + newSpecState.RecordPrimitiveTopology(); + } } /// @@ -69,48 +74,6 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache return MemoryMarshal.Cast(_data.Span[(int)address..]); } - /// - public bool QueryAlphaToCoverageDitherEnable() - { - return _oldSpecState.GraphicsState.AlphaToCoverageEnable && _oldSpecState.GraphicsState.AlphaToCoverageDitherEnable; - } - - /// - public AlphaTestOp QueryAlphaTestCompare() - { - if (!_isVulkan || !_oldSpecState.GraphicsState.AlphaTestEnable) - { - return AlphaTestOp.Always; - } - - return _oldSpecState.GraphicsState.AlphaTestCompare switch - { - CompareOp.Never or CompareOp.NeverGl => AlphaTestOp.Never, - CompareOp.Less or CompareOp.LessGl => AlphaTestOp.Less, - CompareOp.Equal or CompareOp.EqualGl => AlphaTestOp.Equal, - CompareOp.LessOrEqual or CompareOp.LessOrEqualGl => AlphaTestOp.LessOrEqual, - CompareOp.Greater or CompareOp.GreaterGl => AlphaTestOp.Greater, - CompareOp.NotEqual or CompareOp.NotEqualGl => AlphaTestOp.NotEqual, - CompareOp.GreaterOrEqual or CompareOp.GreaterOrEqualGl => AlphaTestOp.GreaterOrEqual, - _ => AlphaTestOp.Always, - }; - } - - /// - public float QueryAlphaTestReference() => _oldSpecState.GraphicsState.AlphaTestReference; - - /// - public AttributeType QueryAttributeType(int location) - { - return _oldSpecState.GraphicsState.AttributeTypes[location]; - } - - /// - public AttributeType QueryFragmentOutputType(int location) - { - return _oldSpecState.GraphicsState.FragmentOutputTypes[location]; - } - /// public int QueryComputeLocalSizeX() => _oldSpecState.ComputeState.LocalSizeX; @@ -134,52 +97,15 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache } /// - public bool QueryHasConstantBufferDrawParameters() - { - return _oldSpecState.GraphicsState.HasConstantBufferDrawParameters; - } - - /// - public bool QueryDualSourceBlendEnable() - { - return _oldSpecState.GraphicsState.DualSourceBlendEnable; - } - - /// - public InputTopology QueryPrimitiveTopology() + public GpuGraphicsState QueryGraphicsState() { - _newSpecState.RecordPrimitiveTopology(); - return ConvertToInputTopology(_oldSpecState.GraphicsState.Topology, _oldSpecState.GraphicsState.TessellationMode); + return _oldSpecState.GraphicsState.CreateShaderGraphicsState(!_isVulkan, _isVulkan || _oldSpecState.GraphicsState.YNegateEnabled); } /// - public bool QueryProgramPointSize() - { - return _oldSpecState.GraphicsState.ProgramPointSizeEnable; - } - - /// - public float QueryPointSize() - { - return _oldSpecState.GraphicsState.PointSize; - } - - /// - public bool QueryTessCw() - { - return _oldSpecState.GraphicsState.TessellationMode.UnpackCw(); - } - - /// - public TessPatchType QueryTessPatchType() - { - return _oldSpecState.GraphicsState.TessellationMode.UnpackPatchType(); - } - - /// - public TessSpacing QueryTessSpacing() + public bool QueryHasConstantBufferDrawParameters() { - return _oldSpecState.GraphicsState.TessellationMode.UnpackSpacing(); + return _oldSpecState.GraphicsState.HasConstantBufferDrawParameters; } /// @@ -204,12 +130,6 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache return _oldSpecState.GetCoordNormalized(_stageIndex, handle, cbufSlot); } - /// - public bool QueryTransformDepthMinusOneToOne() - { - return _oldSpecState.GraphicsState.DepthMode; - } - /// public bool QueryTransformFeedbackEnabled() { @@ -228,31 +148,12 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache return _oldSpecState.TransformFeedbackDescriptors[bufferIndex].Stride; } - /// - public bool QueryEarlyZForce() - { - _newSpecState.RecordEarlyZForce(); - return _oldSpecState.GraphicsState.EarlyZForce; - } - /// public bool QueryHasUnalignedStorageBuffer() { return _oldSpecState.GraphicsState.HasUnalignedStorageBuffer || _oldSpecState.ComputeState.HasUnalignedStorageBuffer; } - /// - public bool QueryViewportTransformDisable() - { - return _oldSpecState.GraphicsState.ViewportTransformDisable; - } - - /// - public bool QueryYNegateEnabled() - { - return _oldSpecState.GraphicsState.YNegateEnabled; - } - /// public void RegisterTexture(int handle, int cbufSlot) { diff --git a/src/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs b/src/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs index 1fcc93c5..b4f4a439 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs @@ -1,5 +1,4 @@ using Ryujinx.Common.Logging; -using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.Gpu.Image; using Ryujinx.Graphics.Shader; using Ryujinx.Graphics.Shader.Translation; @@ -36,6 +35,12 @@ namespace Ryujinx.Graphics.Gpu.Shader _channel = channel; _state = state; _stageIndex = stageIndex; + + if (stageIndex == (int)ShaderStage.Geometry - 1) + { + // Only geometry shaders require the primitive topology. + _state.SpecializationState.RecordPrimitiveTopology(); + } } /// @@ -74,58 +79,6 @@ namespace Ryujinx.Graphics.Gpu.Shader return MemoryMarshal.Cast(_channel.MemoryManager.GetSpan(address, size)); } - /// - public bool QueryAlphaToCoverageDitherEnable() - { - return _state.GraphicsState.AlphaToCoverageEnable && _state.GraphicsState.AlphaToCoverageDitherEnable; - } - - /// - public AlphaTestOp QueryAlphaTestCompare() - { - if (!_isVulkan || !_state.GraphicsState.AlphaTestEnable) - { - return AlphaTestOp.Always; - } - - return _state.GraphicsState.AlphaTestCompare switch - { - CompareOp.Never or CompareOp.NeverGl => AlphaTestOp.Never, - CompareOp.Less or CompareOp.LessGl => AlphaTestOp.Less, - CompareOp.Equal or CompareOp.EqualGl => AlphaTestOp.Equal, - CompareOp.LessOrEqual or CompareOp.LessOrEqualGl => AlphaTestOp.LessOrEqual, - CompareOp.Greater or CompareOp.GreaterGl => AlphaTestOp.Greater, - CompareOp.NotEqual or CompareOp.NotEqualGl => AlphaTestOp.NotEqual, - CompareOp.GreaterOrEqual or CompareOp.GreaterOrEqualGl => AlphaTestOp.GreaterOrEqual, - _ => AlphaTestOp.Always, - }; - } - - /// - public float QueryAlphaTestReference() - { - return _state.GraphicsState.AlphaTestReference; - } - - /// - public AttributeType QueryAttributeType(int location) - { - return _state.GraphicsState.AttributeTypes[location]; - } - - /// - public bool QueryEarlyZForce() - { - _state.SpecializationState?.RecordEarlyZForce(); - return _state.GraphicsState.EarlyZForce; - } - - /// - public AttributeType QueryFragmentOutputType(int location) - { - return _state.GraphicsState.FragmentOutputTypes[location]; - } - /// public int QueryComputeLocalSizeX() => _state.ComputeState.LocalSizeX; @@ -153,58 +106,21 @@ namespace Ryujinx.Graphics.Gpu.Shader } /// - public bool QueryHasConstantBufferDrawParameters() + public GpuGraphicsState QueryGraphicsState() { - return _state.GraphicsState.HasConstantBufferDrawParameters; + return _state.GraphicsState.CreateShaderGraphicsState(!_isVulkan, _isVulkan || _state.GraphicsState.YNegateEnabled); } /// - public bool QueryHasUnalignedStorageBuffer() - { - return _state.GraphicsState.HasUnalignedStorageBuffer || _state.ComputeState.HasUnalignedStorageBuffer; - } - - /// - public bool QueryDualSourceBlendEnable() - { - return _state.GraphicsState.DualSourceBlendEnable; - } - - /// - public InputTopology QueryPrimitiveTopology() - { - _state.SpecializationState?.RecordPrimitiveTopology(); - return ConvertToInputTopology(_state.GraphicsState.Topology, _state.GraphicsState.TessellationMode); - } - - /// - public bool QueryProgramPointSize() - { - return _state.GraphicsState.ProgramPointSizeEnable; - } - - /// - public float QueryPointSize() - { - return _state.GraphicsState.PointSize; - } - - /// - public bool QueryTessCw() - { - return _state.GraphicsState.TessellationMode.UnpackCw(); - } - - /// - public TessPatchType QueryTessPatchType() + public bool QueryHasConstantBufferDrawParameters() { - return _state.GraphicsState.TessellationMode.UnpackPatchType(); + return _state.GraphicsState.HasConstantBufferDrawParameters; } /// - public TessSpacing QueryTessSpacing() + public bool QueryHasUnalignedStorageBuffer() { - return _state.GraphicsState.TessellationMode.UnpackSpacing(); + return _state.GraphicsState.HasUnalignedStorageBuffer || _state.ComputeState.HasUnalignedStorageBuffer; } //// @@ -258,12 +174,6 @@ namespace Ryujinx.Graphics.Gpu.Shader } } - /// - public bool QueryTransformDepthMinusOneToOne() - { - return _state.GraphicsState.DepthMode; - } - /// public bool QueryTransformFeedbackEnabled() { @@ -282,18 +192,6 @@ namespace Ryujinx.Graphics.Gpu.Shader return _state.TransformFeedbackDescriptors[bufferIndex].Stride; } - /// - public bool QueryViewportTransformDisable() - { - return _state.GraphicsState.ViewportTransformDisable; - } - - /// - public bool QueryYNegateEnabled() - { - return _state.GraphicsState.YNegateEnabled; - } - /// public void RegisterTexture(int handle, int cbufSlot) { diff --git a/src/Ryujinx.Graphics.Gpu/Shader/GpuAccessorBase.cs b/src/Ryujinx.Graphics.Gpu/Shader/GpuAccessorBase.cs index 07b7ddc2..6d27f18d 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/GpuAccessorBase.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/GpuAccessorBase.cs @@ -1,6 +1,5 @@ using Ryujinx.Common.Logging; using Ryujinx.Graphics.GAL; -using Ryujinx.Graphics.Gpu.Engine.Threed; using Ryujinx.Graphics.Gpu.Image; using Ryujinx.Graphics.Shader; using Ryujinx.Graphics.Shader.Translation; @@ -232,33 +231,5 @@ namespace Ryujinx.Graphics.Gpu.Shader #pragma warning restore IDE0055 }; } - - /// - /// Converts the Maxwell primitive topology to the shader translator topology. - /// - /// Maxwell primitive topology - /// Maxwell tessellation mode - /// Shader translator topology - protected static InputTopology ConvertToInputTopology(PrimitiveTopology topology, TessMode tessellationMode) - { - return topology switch - { - PrimitiveTopology.Points => InputTopology.Points, - PrimitiveTopology.Lines or - PrimitiveTopology.LineLoop or - PrimitiveTopology.LineStrip => InputTopology.Lines, - PrimitiveTopology.LinesAdjacency or - PrimitiveTopology.LineStripAdjacency => InputTopology.LinesAdjacency, - PrimitiveTopology.Triangles or - PrimitiveTopology.TriangleStrip or - PrimitiveTopology.TriangleFan => InputTopology.Triangles, - PrimitiveTopology.TrianglesAdjacency or - PrimitiveTopology.TriangleStripAdjacency => InputTopology.TrianglesAdjacency, - PrimitiveTopology.Patches => tessellationMode.UnpackPatchType() == TessPatchType.Isolines - ? InputTopology.Lines - : InputTopology.Triangles, - _ => InputTopology.Points, - }; - } } } diff --git a/src/Ryujinx.Graphics.Gpu/Shader/GpuChannelGraphicsState.cs b/src/Ryujinx.Graphics.Gpu/Shader/GpuChannelGraphicsState.cs index f392491c..b5bc4df3 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/GpuChannelGraphicsState.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/GpuChannelGraphicsState.cs @@ -103,64 +103,81 @@ namespace Ryujinx.Graphics.Gpu.Shader public bool YNegateEnabled; /// - /// Creates a new GPU graphics state. - /// - /// Early Z force enable - /// Primitive topology - /// Tessellation mode - /// Indicates whether alpha-to-coverage is enabled - /// Indicates whether alpha-to-coverage dithering is enabled - /// Indicates whether the viewport transform is disabled - /// Depth mode zero to one or minus one to one - /// Indicates if the point size is set on the shader or is fixed - /// Point size if not set from shader - /// Indicates whether alpha test is enabled - /// When alpha test is enabled, indicates the comparison that decides if the fragment should be discarded - /// When alpha test is enabled, indicates the value to compare with the fragment output alpha - /// Type of the vertex attributes consumed by the shader - /// Indicates that the draw is writing the base vertex, base instance and draw index to Constant Buffer 0 - /// Indicates that any storage buffer use is unaligned - /// Type of the fragment shader outputs - /// Indicates whether dual source blend is enabled - /// Indicates whether Y negate of the fragment coordinates is enabled - public GpuChannelGraphicsState( - bool earlyZForce, - PrimitiveTopology topology, - TessMode tessellationMode, - bool alphaToCoverageEnable, - bool alphaToCoverageDitherEnable, - bool viewportTransformDisable, - bool depthMode, - bool programPointSizeEnable, - float pointSize, - bool alphaTestEnable, - CompareOp alphaTestCompare, - float alphaTestReference, - ref Array32 attributeTypes, - bool hasConstantBufferDrawParameters, - bool hasUnalignedStorageBuffer, - ref Array8 fragmentOutputTypes, - bool dualSourceBlendEnable, - bool yNegateEnabled) + /// Creates a new graphics state from this state that can be used for shader generation. + /// + /// Indicates if the host API supports alpha test operations + /// GPU graphics state that can be used for shader translation + public readonly GpuGraphicsState CreateShaderGraphicsState(bool hostSupportsAlphaTest, bool originUpperLeft) + { + AlphaTestOp alphaTestOp; + + if (hostSupportsAlphaTest || !AlphaTestEnable) + { + alphaTestOp = AlphaTestOp.Always; + } + else + { + alphaTestOp = AlphaTestCompare switch + { + CompareOp.Never or CompareOp.NeverGl => AlphaTestOp.Never, + CompareOp.Less or CompareOp.LessGl => AlphaTestOp.Less, + CompareOp.Equal or CompareOp.EqualGl => AlphaTestOp.Equal, + CompareOp.LessOrEqual or CompareOp.LessOrEqualGl => AlphaTestOp.LessOrEqual, + CompareOp.Greater or CompareOp.GreaterGl => AlphaTestOp.Greater, + CompareOp.NotEqual or CompareOp.NotEqualGl => AlphaTestOp.NotEqual, + CompareOp.GreaterOrEqual or CompareOp.GreaterOrEqualGl => AlphaTestOp.GreaterOrEqual, + _ => AlphaTestOp.Always, + }; + } + + return new GpuGraphicsState( + EarlyZForce, + ConvertToInputTopology(Topology, TessellationMode), + TessellationMode.UnpackCw(), + TessellationMode.UnpackPatchType(), + TessellationMode.UnpackSpacing(), + AlphaToCoverageEnable, + AlphaToCoverageDitherEnable, + ViewportTransformDisable, + DepthMode, + ProgramPointSizeEnable, + PointSize, + alphaTestOp, + AlphaTestReference, + in AttributeTypes, + HasConstantBufferDrawParameters, + in FragmentOutputTypes, + DualSourceBlendEnable, + YNegateEnabled, + originUpperLeft); + } + + /// + /// Converts the Maxwell primitive topology to the shader translator topology. + /// + /// Maxwell primitive topology + /// Maxwell tessellation mode + /// Shader translator topology + private static InputTopology ConvertToInputTopology(PrimitiveTopology topology, TessMode tessellationMode) { - EarlyZForce = earlyZForce; - Topology = topology; - TessellationMode = tessellationMode; - AlphaToCoverageEnable = alphaToCoverageEnable; - AlphaToCoverageDitherEnable = alphaToCoverageDitherEnable; - ViewportTransformDisable = viewportTransformDisable; - DepthMode = depthMode; - ProgramPointSizeEnable = programPointSizeEnable; - PointSize = pointSize; - AlphaTestEnable = alphaTestEnable; - AlphaTestCompare = alphaTestCompare; - AlphaTestReference = alphaTestReference; - AttributeTypes = attributeTypes; - HasConstantBufferDrawParameters = hasConstantBufferDrawParameters; - HasUnalignedStorageBuffer = hasUnalignedStorageBuffer; - FragmentOutputTypes = fragmentOutputTypes; - DualSourceBlendEnable = dualSourceBlendEnable; - YNegateEnabled = yNegateEnabled; + return topology switch + { + PrimitiveTopology.Points => InputTopology.Points, + PrimitiveTopology.Lines or + PrimitiveTopology.LineLoop or + PrimitiveTopology.LineStrip => InputTopology.Lines, + PrimitiveTopology.LinesAdjacency or + PrimitiveTopology.LineStripAdjacency => InputTopology.LinesAdjacency, + PrimitiveTopology.Triangles or + PrimitiveTopology.TriangleStrip or + PrimitiveTopology.TriangleFan => InputTopology.Triangles, + PrimitiveTopology.TrianglesAdjacency or + PrimitiveTopology.TriangleStripAdjacency => InputTopology.TrianglesAdjacency, + PrimitiveTopology.Patches => tessellationMode.UnpackPatchType() == TessPatchType.Isolines + ? InputTopology.Lines + : InputTopology.Triangles, + _ => InputTopology.Points, + }; } } } diff --git a/src/Ryujinx.Graphics.Gpu/Shader/ShaderSpecializationState.cs b/src/Ryujinx.Graphics.Gpu/Shader/ShaderSpecializationState.cs index b33f96c5..fcd95375 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/ShaderSpecializationState.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/ShaderSpecializationState.cs @@ -28,9 +28,7 @@ namespace Ryujinx.Graphics.Gpu.Shader [Flags] private enum QueriedStateFlags { - EarlyZForce = 1 << 0, PrimitiveTopology = 1 << 1, - TessellationMode = 1 << 2, TransformFeedback = 1 << 3, } @@ -264,14 +262,6 @@ namespace Ryujinx.Graphics.Gpu.Shader PipelineState = pipelineState; } - /// - /// Indicates that the shader accesses the early Z force state. - /// - public void RecordEarlyZForce() - { - _queriedState |= QueriedStateFlags.EarlyZForce; - } - /// /// Indicates that the shader accesses the primitive topology state. /// @@ -280,14 +270,6 @@ namespace Ryujinx.Graphics.Gpu.Shader _queriedState |= QueriedStateFlags.PrimitiveTopology; } - /// - /// Indicates that the shader accesses the tessellation mode state. - /// - public void RecordTessellationMode() - { - _queriedState |= QueriedStateFlags.TessellationMode; - } - /// /// Indicates that the shader accesses the constant buffer use state. /// -- cgit v1.2.3