diff options
Diffstat (limited to 'src/Ryujinx.Graphics.Gpu')
5 files changed, 96 insertions, 327 deletions
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(); + } } /// <inheritdoc/> @@ -70,48 +75,6 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache } /// <inheritdoc/> - public bool QueryAlphaToCoverageDitherEnable() - { - return _oldSpecState.GraphicsState.AlphaToCoverageEnable && _oldSpecState.GraphicsState.AlphaToCoverageDitherEnable; - } - - /// <inheritdoc/> - 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, - }; - } - - /// <inheritdoc/> - public float QueryAlphaTestReference() => _oldSpecState.GraphicsState.AlphaTestReference; - - /// <inheritdoc/> - public AttributeType QueryAttributeType(int location) - { - return _oldSpecState.GraphicsState.AttributeTypes[location]; - } - - /// <inheritdoc/> - public AttributeType QueryFragmentOutputType(int location) - { - return _oldSpecState.GraphicsState.FragmentOutputTypes[location]; - } - - /// <inheritdoc/> public int QueryComputeLocalSizeX() => _oldSpecState.ComputeState.LocalSizeX; /// <inheritdoc/> @@ -134,52 +97,15 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache } /// <inheritdoc/> - public bool QueryHasConstantBufferDrawParameters() - { - return _oldSpecState.GraphicsState.HasConstantBufferDrawParameters; - } - - /// <inheritdoc/> - public bool QueryDualSourceBlendEnable() - { - return _oldSpecState.GraphicsState.DualSourceBlendEnable; - } - - /// <inheritdoc/> - 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); } /// <inheritdoc/> - public bool QueryProgramPointSize() - { - return _oldSpecState.GraphicsState.ProgramPointSizeEnable; - } - - /// <inheritdoc/> - public float QueryPointSize() - { - return _oldSpecState.GraphicsState.PointSize; - } - - /// <inheritdoc/> - public bool QueryTessCw() - { - return _oldSpecState.GraphicsState.TessellationMode.UnpackCw(); - } - - /// <inheritdoc/> - public TessPatchType QueryTessPatchType() - { - return _oldSpecState.GraphicsState.TessellationMode.UnpackPatchType(); - } - - /// <inheritdoc/> - public TessSpacing QueryTessSpacing() + public bool QueryHasConstantBufferDrawParameters() { - return _oldSpecState.GraphicsState.TessellationMode.UnpackSpacing(); + return _oldSpecState.GraphicsState.HasConstantBufferDrawParameters; } /// <inheritdoc/> @@ -205,12 +131,6 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache } /// <inheritdoc/> - public bool QueryTransformDepthMinusOneToOne() - { - return _oldSpecState.GraphicsState.DepthMode; - } - - /// <inheritdoc/> public bool QueryTransformFeedbackEnabled() { return _oldSpecState.TransformFeedbackDescriptors != null; @@ -229,31 +149,12 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache } /// <inheritdoc/> - public bool QueryEarlyZForce() - { - _newSpecState.RecordEarlyZForce(); - return _oldSpecState.GraphicsState.EarlyZForce; - } - - /// <inheritdoc/> public bool QueryHasUnalignedStorageBuffer() { return _oldSpecState.GraphicsState.HasUnalignedStorageBuffer || _oldSpecState.ComputeState.HasUnalignedStorageBuffer; } /// <inheritdoc/> - public bool QueryViewportTransformDisable() - { - return _oldSpecState.GraphicsState.ViewportTransformDisable; - } - - /// <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/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(); + } } /// <summary> @@ -75,58 +80,6 @@ namespace Ryujinx.Graphics.Gpu.Shader } /// <inheritdoc/> - public bool QueryAlphaToCoverageDitherEnable() - { - return _state.GraphicsState.AlphaToCoverageEnable && _state.GraphicsState.AlphaToCoverageDitherEnable; - } - - /// <inheritdoc/> - 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, - }; - } - - /// <inheritdoc/> - public float QueryAlphaTestReference() - { - return _state.GraphicsState.AlphaTestReference; - } - - /// <inheritdoc/> - public AttributeType QueryAttributeType(int location) - { - return _state.GraphicsState.AttributeTypes[location]; - } - - /// <inheritdoc/> - public bool QueryEarlyZForce() - { - _state.SpecializationState?.RecordEarlyZForce(); - return _state.GraphicsState.EarlyZForce; - } - - /// <inheritdoc/> - public AttributeType QueryFragmentOutputType(int location) - { - return _state.GraphicsState.FragmentOutputTypes[location]; - } - - /// <inheritdoc/> public int QueryComputeLocalSizeX() => _state.ComputeState.LocalSizeX; /// <inheritdoc/> @@ -153,58 +106,21 @@ namespace Ryujinx.Graphics.Gpu.Shader } /// <inheritdoc/> - public bool QueryHasConstantBufferDrawParameters() + public GpuGraphicsState QueryGraphicsState() { - return _state.GraphicsState.HasConstantBufferDrawParameters; + return _state.GraphicsState.CreateShaderGraphicsState(!_isVulkan, _isVulkan || _state.GraphicsState.YNegateEnabled); } /// <inheritdoc/> - public bool QueryHasUnalignedStorageBuffer() - { - return _state.GraphicsState.HasUnalignedStorageBuffer || _state.ComputeState.HasUnalignedStorageBuffer; - } - - /// <inheritdoc/> - public bool QueryDualSourceBlendEnable() - { - return _state.GraphicsState.DualSourceBlendEnable; - } - - /// <inheritdoc/> - public InputTopology QueryPrimitiveTopology() - { - _state.SpecializationState?.RecordPrimitiveTopology(); - return ConvertToInputTopology(_state.GraphicsState.Topology, _state.GraphicsState.TessellationMode); - } - - /// <inheritdoc/> - public bool QueryProgramPointSize() - { - return _state.GraphicsState.ProgramPointSizeEnable; - } - - /// <inheritdoc/> - public float QueryPointSize() - { - return _state.GraphicsState.PointSize; - } - - /// <inheritdoc/> - public bool QueryTessCw() - { - return _state.GraphicsState.TessellationMode.UnpackCw(); - } - - /// <inheritdoc/> - public TessPatchType QueryTessPatchType() + public bool QueryHasConstantBufferDrawParameters() { - return _state.GraphicsState.TessellationMode.UnpackPatchType(); + return _state.GraphicsState.HasConstantBufferDrawParameters; } /// <inheritdoc/> - public TessSpacing QueryTessSpacing() + public bool QueryHasUnalignedStorageBuffer() { - return _state.GraphicsState.TessellationMode.UnpackSpacing(); + return _state.GraphicsState.HasUnalignedStorageBuffer || _state.ComputeState.HasUnalignedStorageBuffer; } //// <inheritdoc/> @@ -259,12 +175,6 @@ namespace Ryujinx.Graphics.Gpu.Shader } /// <inheritdoc/> - public bool QueryTransformDepthMinusOneToOne() - { - return _state.GraphicsState.DepthMode; - } - - /// <inheritdoc/> public bool QueryTransformFeedbackEnabled() { return _state.TransformFeedbackDescriptors != null; @@ -283,18 +193,6 @@ namespace Ryujinx.Graphics.Gpu.Shader } /// <inheritdoc/> - public bool QueryViewportTransformDisable() - { - return _state.GraphicsState.ViewportTransformDisable; - } - - /// <inheritdoc/> - public bool QueryYNegateEnabled() - { - return _state.GraphicsState.YNegateEnabled; - } - - /// <inheritdoc/> public void RegisterTexture(int handle, int cbufSlot) { _state.SpecializationState?.RegisterTexture(_stageIndex, handle, cbufSlot, GetTextureDescriptor(handle, 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 }; } - - /// <summary> - /// Converts the Maxwell primitive topology to the shader translator topology. - /// </summary> - /// <param name="topology">Maxwell primitive topology</param> - /// <param name="tessellationMode">Maxwell tessellation mode</param> - /// <returns>Shader translator topology</returns> - 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; /// <summary> - /// Creates a new GPU graphics state. - /// </summary> - /// <param name="earlyZForce">Early Z force enable</param> - /// <param name="topology">Primitive topology</param> - /// <param name="tessellationMode">Tessellation mode</param> - /// <param name="alphaToCoverageEnable">Indicates whether alpha-to-coverage is enabled</param> - /// <param name="alphaToCoverageDitherEnable">Indicates whether alpha-to-coverage dithering is enabled</param> - /// <param name="viewportTransformDisable">Indicates whether the viewport transform is disabled</param> - /// <param name="depthMode">Depth mode zero to one or minus one to one</param> - /// <param name="programPointSizeEnable">Indicates if the point size is set on the shader or is fixed</param> - /// <param name="pointSize">Point size if not set from shader</param> - /// <param name="alphaTestEnable">Indicates whether alpha test is enabled</param> - /// <param name="alphaTestCompare">When alpha test is enabled, indicates the comparison that decides if the fragment should be discarded</param> - /// <param name="alphaTestReference">When alpha test is enabled, indicates the value to compare with the fragment output alpha</param> - /// <param name="attributeTypes">Type of the vertex attributes consumed by the shader</param> - /// <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">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, - TessMode tessellationMode, - bool alphaToCoverageEnable, - bool alphaToCoverageDitherEnable, - bool viewportTransformDisable, - bool depthMode, - bool programPointSizeEnable, - float pointSize, - bool alphaTestEnable, - CompareOp alphaTestCompare, - float alphaTestReference, - ref Array32<AttributeType> attributeTypes, - bool hasConstantBufferDrawParameters, - bool hasUnalignedStorageBuffer, - ref Array8<AttributeType> fragmentOutputTypes, - bool dualSourceBlendEnable, - bool yNegateEnabled) + /// Creates a new graphics state from this state that can be used for shader generation. + /// </summary> + /// <param name="hostSupportsAlphaTest">Indicates if the host API supports alpha test operations</param> + /// <returns>GPU graphics state that can be used for shader translation</returns> + 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); + } + + /// <summary> + /// Converts the Maxwell primitive topology to the shader translator topology. + /// </summary> + /// <param name="topology">Maxwell primitive topology</param> + /// <param name="tessellationMode">Maxwell tessellation mode</param> + /// <returns>Shader translator topology</returns> + 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, } @@ -265,14 +263,6 @@ namespace Ryujinx.Graphics.Gpu.Shader } /// <summary> - /// Indicates that the shader accesses the early Z force state. - /// </summary> - public void RecordEarlyZForce() - { - _queriedState |= QueriedStateFlags.EarlyZForce; - } - - /// <summary> /// Indicates that the shader accesses the primitive topology state. /// </summary> public void RecordPrimitiveTopology() @@ -281,14 +271,6 @@ namespace Ryujinx.Graphics.Gpu.Shader } /// <summary> - /// Indicates that the shader accesses the tessellation mode state. - /// </summary> - public void RecordTessellationMode() - { - _queriedState |= QueriedStateFlags.TessellationMode; - } - - /// <summary> /// Indicates that the shader accesses the constant buffer use state. /// </summary> /// <param name="stageIndex">Shader stage index</param> |