diff --git a/src/Ryujinx.Graphics.GAL/Capabilities.cs b/src/Ryujinx.Graphics.GAL/Capabilities.cs index a5c6eb5c8..cdbd44fad 100644 --- a/src/Ryujinx.Graphics.GAL/Capabilities.cs +++ b/src/Ryujinx.Graphics.GAL/Capabilities.cs @@ -50,6 +50,10 @@ namespace Ryujinx.Graphics.GAL public readonly bool SupportsViewportSwizzle; public readonly bool SupportsIndirectParameters; public readonly bool SupportsDepthClipControl; + public readonly bool SupportsExtendedDynamicState; + public readonly bool SupportsExtendedDynamicState2; + public readonly bool SupportsLogicOpDynamicState; + public readonly bool SupportsPatchControlPointsDynamicState; public readonly int UniformBufferSetIndex; public readonly int StorageBufferSetIndex; @@ -116,6 +120,10 @@ namespace Ryujinx.Graphics.GAL bool supportsViewportSwizzle, bool supportsIndirectParameters, bool supportsDepthClipControl, + bool supportsExtendedDynamicState, + bool supportsExtendedDynamicState2, + bool supportsLogicOpDynamicState, + bool supportsPatchControlPointsDynamicState, int uniformBufferSetIndex, int storageBufferSetIndex, int textureSetIndex, @@ -177,6 +185,10 @@ namespace Ryujinx.Graphics.GAL SupportsViewportSwizzle = supportsViewportSwizzle; SupportsIndirectParameters = supportsIndirectParameters; SupportsDepthClipControl = supportsDepthClipControl; + SupportsExtendedDynamicState = supportsExtendedDynamicState; + SupportsExtendedDynamicState2 = supportsExtendedDynamicState2; + SupportsLogicOpDynamicState = supportsLogicOpDynamicState; + SupportsPatchControlPointsDynamicState = supportsPatchControlPointsDynamicState; UniformBufferSetIndex = uniformBufferSetIndex; StorageBufferSetIndex = storageBufferSetIndex; TextureSetIndex = textureSetIndex; diff --git a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs index a5c5abd4b..3f3c3723d 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 = 7331; + private const uint CodeGenVersion = 7332; private const string SharedTocFileName = "shared.toc"; private const string SharedDataFileName = "shared.data"; diff --git a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/ParallelDiskCacheLoader.cs b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/ParallelDiskCacheLoader.cs index 20f96462e..2db19096c 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/ParallelDiskCacheLoader.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/ParallelDiskCacheLoader.cs @@ -232,10 +232,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache for (int index = 0; index < ThreadCount; index++) { - workThreads[index] = new Thread(ProcessAsyncQueue) - { - Name = $"GPU.AsyncTranslationThread.{index}", - }; + workThreads[index] = new Thread(ProcessAsyncQueue) { Name = $"GPU.AsyncTranslationThread.{index}", }; } int programCount = _hostStorage.GetProgramCount(); @@ -305,6 +302,9 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache using var streams = _hostStorage.GetOutputStreams(_context); int packagedShaders = 0; + ProgramPipelineState previousPipelineState = default; + ProgramPipelineState currentPipelineState = default; + foreach (var kv in _programList) { if (!Active) @@ -314,9 +314,53 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache (CachedShaderProgram program, byte[] binaryCode) = kv.Value; - _hostStorage.AddShader(_context, program, binaryCode, streams); + if (program.SpecializationState.PipelineState.HasValue && _context.Capabilities.SupportsExtendedDynamicState) + { + currentPipelineState = program.SpecializationState.PipelineState.Value; - _stateChangeCallback(ShaderCacheState.Packaging, ++packagedShaders, _programList.Count); + if (_context.Capabilities.SupportsExtendedDynamicState) + { + currentPipelineState.StencilTest = default; + + currentPipelineState.CullMode = 0; + currentPipelineState.FrontFace = 0; + currentPipelineState.DepthTest = default; + currentPipelineState.Topology = ConvertToClass(currentPipelineState.Topology); + } + + if (_context.Capabilities.SupportsExtendedDynamicState2) + { + currentPipelineState.PrimitiveRestartEnable = false; + currentPipelineState.BiasEnable = 0; + currentPipelineState.RasterizerDiscard = false; + + } + + if (_context.Capabilities.SupportsLogicOpDynamicState) + { + currentPipelineState.LogicOp = 0; + } + + if (_context.Capabilities.SupportsPatchControlPointsDynamicState) + { + currentPipelineState.PatchControlPoints = 0; + } + + currentPipelineState = program.SpecializationState.PipelineState.Value; + } + + + if (currentPipelineState.Equals(previousPipelineState) || !_context.Capabilities.SupportsExtendedDynamicState) + { + _hostStorage.AddShader(_context, program, binaryCode, streams); + + _stateChangeCallback(ShaderCacheState.Packaging, ++packagedShaders, _programList.Count); + } + + if (_context.Capabilities.SupportsExtendedDynamicState) + { + previousPipelineState = currentPipelineState; + } } Logger.Info?.Print(LogClass.Gpu, $"Rebuilt {_programList.Count} shaders successfully."); @@ -343,6 +387,28 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache _stateChangeCallback(ShaderCacheState.Loaded, programCount, programCount); } + private PrimitiveTopology ConvertToClass(PrimitiveTopology topology) + { + return topology switch + { + PrimitiveTopology.Points => PrimitiveTopology.Points, + PrimitiveTopology.Lines or + PrimitiveTopology.LineStrip or + PrimitiveTopology.LinesAdjacency or + PrimitiveTopology.LineStripAdjacency => PrimitiveTopology.Lines, + PrimitiveTopology.Triangles or + PrimitiveTopology.TriangleStrip or + PrimitiveTopology.TriangleFan or + PrimitiveTopology.TrianglesAdjacency or + PrimitiveTopology.TriangleStripAdjacency or + PrimitiveTopology.Polygon => PrimitiveTopology.TriangleStrip, + PrimitiveTopology.Patches => PrimitiveTopology.Patches, + PrimitiveTopology.Quads => PrimitiveTopology.Quads, + PrimitiveTopology.QuadStrip => PrimitiveTopology.QuadStrip, + PrimitiveTopology.LineLoop => PrimitiveTopology.LineLoop, + }; + } + /// /// Enqueues a host program for compilation. /// diff --git a/src/Ryujinx.Graphics.OpenGL/OpenGLRenderer.cs b/src/Ryujinx.Graphics.OpenGL/OpenGLRenderer.cs index ba9cd45c6..df2ca30de 100644 --- a/src/Ryujinx.Graphics.OpenGL/OpenGLRenderer.cs +++ b/src/Ryujinx.Graphics.OpenGL/OpenGLRenderer.cs @@ -187,6 +187,10 @@ namespace Ryujinx.Graphics.OpenGL supportsViewportSwizzle: HwCapabilities.SupportsViewportSwizzle, supportsIndirectParameters: HwCapabilities.SupportsIndirectParameters, supportsDepthClipControl: true, + supportsExtendedDynamicState: false, + supportsExtendedDynamicState2: false, + supportsLogicOpDynamicState: false, + supportsPatchControlPointsDynamicState: false, uniformBufferSetIndex: 0, storageBufferSetIndex: 1, textureSetIndex: 2, diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs index 376eb47ef..4ae0de460 100644 --- a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs +++ b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs @@ -793,6 +793,10 @@ namespace Ryujinx.Graphics.Vulkan supportsViewportSwizzle: false, supportsIndirectParameters: true, supportsDepthClipControl: Capabilities.SupportsDepthClipControl, + supportsExtendedDynamicState: Capabilities.SupportsExtendedDynamicState, + supportsExtendedDynamicState2: Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2, + supportsLogicOpDynamicState: Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2LogicOp, + supportsPatchControlPointsDynamicState: Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints, uniformBufferSetIndex: PipelineBase.UniformSetIndex, storageBufferSetIndex: PipelineBase.StorageSetIndex, textureSetIndex: PipelineBase.TextureSetIndex,