diff --git a/src/Ryujinx.Graphics.GAL/Capabilities.cs b/src/Ryujinx.Graphics.GAL/Capabilities.cs index 86ca0d66c..1eec80e51 100644 --- a/src/Ryujinx.Graphics.GAL/Capabilities.cs +++ b/src/Ryujinx.Graphics.GAL/Capabilities.cs @@ -50,10 +50,6 @@ 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; @@ -122,10 +118,6 @@ namespace Ryujinx.Graphics.GAL bool supportsViewportSwizzle, bool supportsIndirectParameters, bool supportsDepthClipControl, - bool supportsExtendedDynamicState, - bool supportsExtendedDynamicState2, - bool supportsLogicOpDynamicState, - bool supportsPatchControlPointsDynamicState, int uniformBufferSetIndex, int storageBufferSetIndex, int textureSetIndex, @@ -188,10 +180,6 @@ 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.GAL/Face.cs b/src/Ryujinx.Graphics.GAL/Face.cs index e204278eb..73e43cf23 100644 --- a/src/Ryujinx.Graphics.GAL/Face.cs +++ b/src/Ryujinx.Graphics.GAL/Face.cs @@ -2,7 +2,6 @@ namespace Ryujinx.Graphics.GAL { public enum Face { - None = 0, Front = 0x404, Back = 0x405, FrontAndBack = 0x408, diff --git a/src/Ryujinx.Graphics.GAL/IPipeline.cs b/src/Ryujinx.Graphics.GAL/IPipeline.cs index f10db1c2d..b8409a573 100644 --- a/src/Ryujinx.Graphics.GAL/IPipeline.cs +++ b/src/Ryujinx.Graphics.GAL/IPipeline.cs @@ -50,9 +50,9 @@ namespace Ryujinx.Graphics.GAL void SetDepthBias(PolygonModeMask enables, float factor, float units, float clamp); void SetDepthClamp(bool clamp); void SetDepthMode(DepthMode mode); - void SetDepthTest(DepthTestDescriptor depthTest, bool signalChange = true); + void SetDepthTest(DepthTestDescriptor depthTest); - void SetFaceCulling(Face face); + void SetFaceCulling(bool enable, Face face); void SetFrontFace(FrontFace frontFace); @@ -75,16 +75,16 @@ namespace Ryujinx.Graphics.GAL void SetPrimitiveRestart(bool enable, int index); - void SetPrimitiveTopology(PrimitiveTopology topology, bool signalChange = true); + void SetPrimitiveTopology(PrimitiveTopology topology); - void SetProgram(IProgram program, bool signalChange = true); + void SetProgram(IProgram program); void SetRasterizerDiscard(bool discard); - void SetRenderTargetColorMasks(ReadOnlySpan componentMask, bool signalChange = true); + void SetRenderTargetColorMasks(ReadOnlySpan componentMask); void SetRenderTargets(ITexture[] colors, ITexture depthStencil); - void SetScissors(ReadOnlySpan> regions, bool signalChange = true); + void SetScissors(ReadOnlySpan> regions); void SetStencilTest(StencilTestDescriptor stencilTest); @@ -102,7 +102,7 @@ namespace Ryujinx.Graphics.GAL void SetVertexAttribs(ReadOnlySpan vertexAttribs); void SetVertexBuffers(ReadOnlySpan vertexBuffers); - void SetViewports(ReadOnlySpan viewports, bool signalChange = true); + void SetViewports(ReadOnlySpan viewports); void TextureBarrier(); void TextureBarrierTiled(); diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetFaceCullingCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetFaceCullingCommand.cs index c88ddba63..611168f85 100644 --- a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetFaceCullingCommand.cs +++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetFaceCullingCommand.cs @@ -3,16 +3,18 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Commands struct SetFaceCullingCommand : IGALCommand, IGALCommand { public readonly CommandType CommandType => CommandType.SetFaceCulling; + private bool _enable; private Face _face; - public void Set(Face face) + public void Set(bool enable, Face face) { + _enable = enable; _face = face; } public static void Run(ref SetFaceCullingCommand command, ThreadedRenderer threaded, IRenderer renderer) { - renderer.Pipeline.SetFaceCulling(command._face); + renderer.Pipeline.SetFaceCulling(command._enable, command._face); } } } diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedPipeline.cs b/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedPipeline.cs index 7d4bda1c4..deec36648 100644 --- a/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedPipeline.cs +++ b/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedPipeline.cs @@ -159,15 +159,15 @@ namespace Ryujinx.Graphics.GAL.Multithreading _renderer.QueueCommand(); } - public void SetDepthTest(DepthTestDescriptor depthTest, bool signalChange = true) + public void SetDepthTest(DepthTestDescriptor depthTest) { _renderer.New().Set(depthTest); _renderer.QueueCommand(); } - public void SetFaceCulling(Face face) + public void SetFaceCulling(bool enable, Face face) { - _renderer.New().Set(face); + _renderer.New().Set(enable, face); _renderer.QueueCommand(); } @@ -243,13 +243,13 @@ namespace Ryujinx.Graphics.GAL.Multithreading _renderer.QueueCommand(); } - public void SetPrimitiveTopology(PrimitiveTopology topology, bool signalChange = true) + public void SetPrimitiveTopology(PrimitiveTopology topology) { _renderer.New().Set(topology); _renderer.QueueCommand(); } - public void SetProgram(IProgram program, bool signalChange = true) + public void SetProgram(IProgram program) { _renderer.New().Set(Ref(program)); _renderer.QueueCommand(); @@ -261,7 +261,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading _renderer.QueueCommand(); } - public void SetRenderTargetColorMasks(ReadOnlySpan componentMask, bool signalChange = true) + public void SetRenderTargetColorMasks(ReadOnlySpan componentMask) { _renderer.New().Set(_renderer.CopySpan(componentMask)); _renderer.QueueCommand(); @@ -273,7 +273,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading _renderer.QueueCommand(); } - public void SetScissors(ReadOnlySpan> scissors, bool signalChange = true) + public void SetScissors(ReadOnlySpan> scissors) { _renderer.New().Set(_renderer.CopySpan(scissors)); _renderer.QueueCommand(); @@ -339,7 +339,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading _renderer.QueueCommand(); } - public void SetViewports(ReadOnlySpan viewports, bool signalChange = true) + public void SetViewports(ReadOnlySpan viewports) { _renderer.New().Set(_renderer.CopySpan(viewports)); _renderer.QueueCommand(); diff --git a/src/Ryujinx.Graphics.GAL/ProgramPipelineState.cs b/src/Ryujinx.Graphics.GAL/ProgramPipelineState.cs index 5bc8e00b7..c16722af7 100644 --- a/src/Ryujinx.Graphics.GAL/ProgramPipelineState.cs +++ b/src/Ryujinx.Graphics.GAL/ProgramPipelineState.cs @@ -51,12 +51,11 @@ namespace Ryujinx.Graphics.GAL public StencilTestDescriptor StencilTest; public FrontFace FrontFace; public Face CullMode; + public bool CullEnable; public PolygonModeMask BiasEnable; - public bool AlphaToCoverageEnable; - public bool AlphaToOneEnable; - + public float LineWidth; // TODO: Polygon mode. public bool DepthClampEnable; public bool RasterizerDiscard; @@ -64,9 +63,6 @@ namespace Ryujinx.Graphics.GAL public bool PrimitiveRestartEnable; public uint PatchControlPoints; - public float DepthBiasUnits; - public float DepthBiasFactor; - public DepthMode DepthMode; public void SetVertexAttribs(ReadOnlySpan vertexAttribs) diff --git a/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs b/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs index eed9a2761..4f373ccf4 100644 --- a/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs +++ b/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs @@ -853,9 +853,6 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed enables |= (depthBias.FillEnable ? PolygonModeMask.Fill : 0); _pipeline.BiasEnable = enables; - _pipeline.DepthBiasUnits = units / 2f; - _pipeline.DepthBiasFactor = factor; - _context.Renderer.Pipeline.SetDepthBias(enables, factor, units / 2f, clamp); } @@ -1028,6 +1025,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed float width = _state.State.LineWidthSmooth; bool smooth = _state.State.LineSmoothEnable; + _pipeline.LineWidth = width; _context.Renderer.Pipeline.SetLineParameters(width, smooth); } @@ -1197,16 +1195,9 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed var yControl = _state.State.YControl; var face = _state.State.FaceState; - if (face.CullEnable) - { - _pipeline.CullMode = face.CullFace; - _context.Renderer.Pipeline.SetFaceCulling(face.CullFace); - } - else - { - _pipeline.CullMode = Face.None; - _context.Renderer.Pipeline.SetFaceCulling(Face.None); - } + _pipeline.CullEnable = face.CullEnable; + _pipeline.CullMode = face.CullFace; + _context.Renderer.Pipeline.SetFaceCulling(face.CullEnable, face.CullFace); UpdateFrontFace(yControl, face.FrontFace); } @@ -1396,8 +1387,6 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed bool alphaToCoverageEnable = (_state.State.MultisampleControl & 1) != 0; bool alphaToOneEnable = (_state.State.MultisampleControl & 0x10) != 0; - _pipeline.AlphaToCoverageEnable = alphaToCoverageEnable; - _pipeline.AlphaToOneEnable = alphaToOneEnable; _context.Renderer.Pipeline.SetMultisampleState(new MultisampleDescriptor( alphaToCoverageEnable, _state.State.AlphaToCoverageDitherEnable, diff --git a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/ParallelDiskCacheLoader.cs b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/ParallelDiskCacheLoader.cs index f92226f3e..14b1dd8b2 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/ParallelDiskCacheLoader.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/ParallelDiskCacheLoader.cs @@ -22,8 +22,6 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache private readonly CancellationToken _cancellationToken; private readonly Action _stateChangeCallback; - private readonly HashSet _pipelineStateSet = new(); - /// /// Indicates if the cache should be loaded. /// @@ -234,7 +232,10 @@ 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(); @@ -304,8 +305,6 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache using var streams = _hostStorage.GetOutputStreams(_context); int packagedShaders = 0; - ProgramPipelineState currentPipelineState = default; - foreach (var kv in _programList) { if (!Active) @@ -315,53 +314,12 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache (CachedShaderProgram program, byte[] binaryCode) = kv.Value; - if (program.SpecializationState.PipelineState.HasValue && _context.Capabilities.SupportsExtendedDynamicState) - { - currentPipelineState = program.SpecializationState.PipelineState.Value; + _hostStorage.AddShader(_context, program, binaryCode, streams); - 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; - } - } - - if (!_pipelineStateSet.Contains(currentPipelineState) || - !_context.Capabilities.SupportsExtendedDynamicState || - !program.SpecializationState.PipelineState.HasValue) - { - _hostStorage.AddShader(_context, program, binaryCode, streams); - - _stateChangeCallback(ShaderCacheState.Packaging, ++packagedShaders, _programList.Count); - - if (_context.Capabilities.SupportsExtendedDynamicState) - { - _pipelineStateSet.Add(currentPipelineState); - } - } + _stateChangeCallback(ShaderCacheState.Packaging, ++packagedShaders, _programList.Count); } - Logger.Info?.Print(LogClass.Gpu, $"Rebuilt {packagedShaders} shaders successfully."); + + Logger.Info?.Print(LogClass.Gpu, $"Rebuilt {_programList.Count} shaders successfully."); } else { @@ -385,29 +343,6 @@ 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, - _ => PrimitiveTopology.TriangleStrip, - }; - } - /// /// Enqueues a host program for compilation. /// diff --git a/src/Ryujinx.Graphics.OpenGL/OpenGLRenderer.cs b/src/Ryujinx.Graphics.OpenGL/OpenGLRenderer.cs index 581f3cd19..c241379c4 100644 --- a/src/Ryujinx.Graphics.OpenGL/OpenGLRenderer.cs +++ b/src/Ryujinx.Graphics.OpenGL/OpenGLRenderer.cs @@ -191,10 +191,6 @@ 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.OpenGL/Pipeline.cs b/src/Ryujinx.Graphics.OpenGL/Pipeline.cs index f23034806..4fb094539 100644 --- a/src/Ryujinx.Graphics.OpenGL/Pipeline.cs +++ b/src/Ryujinx.Graphics.OpenGL/Pipeline.cs @@ -898,7 +898,7 @@ namespace Ryujinx.Graphics.OpenGL } } - public void SetDepthTest(DepthTestDescriptor depthTest, bool signalChange = true) + public void SetDepthTest(DepthTestDescriptor depthTest) { if (depthTest.TestEnable) { @@ -915,11 +915,11 @@ namespace Ryujinx.Graphics.OpenGL _depthTestEnable = depthTest.TestEnable; } - public void SetFaceCulling(Face face) + public void SetFaceCulling(bool enable, Face face) { - _cullEnable = face != Face.None; + _cullEnable = enable; - if (!_cullEnable) + if (!enable) { GL.Disable(EnableCap.CullFace); return; @@ -1107,12 +1107,12 @@ namespace Ryujinx.Graphics.OpenGL GL.Enable(EnableCap.PrimitiveRestart); } - public void SetPrimitiveTopology(PrimitiveTopology topology, bool signalChange = true) + public void SetPrimitiveTopology(PrimitiveTopology topology) { _primitiveType = topology.Convert(); } - public void SetProgram(IProgram program, bool signalChange = true) + public void SetProgram(IProgram program) { Program prg = (Program)program; @@ -1154,7 +1154,7 @@ namespace Ryujinx.Graphics.OpenGL _rasterizerDiscard = discard; } - public void SetRenderTargetColorMasks(ReadOnlySpan componentMasks, bool signalChange = true) + public void SetRenderTargetColorMasks(ReadOnlySpan componentMasks) { _componentMasks = 0; @@ -1195,7 +1195,7 @@ namespace Ryujinx.Graphics.OpenGL _framebuffer.SetDrawBuffers(colors.Length); } - public void SetScissors(ReadOnlySpan> regions, bool signalChange = true) + public void SetScissors(ReadOnlySpan> regions) { int count = Math.Min(regions.Length, Constants.MaxViewports); @@ -1388,7 +1388,7 @@ namespace Ryujinx.Graphics.OpenGL _vertexArray.SetVertexBuffers(vertexBuffers); } - public void SetViewports(ReadOnlySpan viewports, bool signalChange = true) + public void SetViewports(ReadOnlySpan viewports) { Array.Resize(ref _viewportArray, viewports.Length * 4); Array.Resize(ref _depthRangeArray, viewports.Length * 2); diff --git a/src/Ryujinx.Graphics.Vulkan/Effects/SmaaPostProcessingEffect.cs b/src/Ryujinx.Graphics.Vulkan/Effects/SmaaPostProcessingEffect.cs index 6f7509453..28343cda1 100644 --- a/src/Ryujinx.Graphics.Vulkan/Effects/SmaaPostProcessingEffect.cs +++ b/src/Ryujinx.Graphics.Vulkan/Effects/SmaaPostProcessingEffect.cs @@ -254,8 +254,8 @@ namespace Ryujinx.Graphics.Vulkan.Effects scissors[0] = new Rectangle(0, 0, texture.Width, texture.Height); - _pipeline.SetRenderTarget(texture, (uint)texture.Width, (uint)texture.Height, false); - _pipeline.SetRenderTargetColorMasks(colorMasks, false); + _pipeline.SetRenderTarget(texture, (uint)texture.Width, (uint)texture.Height); + _pipeline.SetRenderTargetColorMasks(colorMasks); _pipeline.SetScissors(scissors); _pipeline.ClearRenderTargetColor(0, 0, 1, new ColorF(0f, 0f, 0f, 1f)); } diff --git a/src/Ryujinx.Graphics.Vulkan/EnumConversion.cs b/src/Ryujinx.Graphics.Vulkan/EnumConversion.cs index 753a2fd43..9d1fd9ffd 100644 --- a/src/Ryujinx.Graphics.Vulkan/EnumConversion.cs +++ b/src/Ryujinx.Graphics.Vulkan/EnumConversion.cs @@ -238,7 +238,6 @@ namespace Ryujinx.Graphics.Vulkan Face.Back => CullModeFlags.BackBit, Face.Front => CullModeFlags.FrontBit, Face.FrontAndBack => CullModeFlags.FrontAndBack, - Face.None => CullModeFlags.None, _ => LogInvalidAndReturn(face, nameof(Face), CullModeFlags.BackBit), }; } @@ -311,25 +310,6 @@ namespace Ryujinx.Graphics.Vulkan }; } - public static PrimitiveTopology ConvertToClass(this PrimitiveTopology topology) - { - return topology switch - { - PrimitiveTopology.PointList => PrimitiveTopology.PointList, - PrimitiveTopology.LineList or - PrimitiveTopology.LineStrip or - PrimitiveTopology.LineListWithAdjacency or - PrimitiveTopology.LineStripWithAdjacency => PrimitiveTopology.LineList, - PrimitiveTopology.TriangleList or - PrimitiveTopology.TriangleStrip or - PrimitiveTopology.TriangleFan or - PrimitiveTopology.TriangleListWithAdjacency or - PrimitiveTopology.TriangleStripWithAdjacency => PrimitiveTopology.TriangleStrip, - PrimitiveTopology.PatchList => PrimitiveTopology.PatchList, - _ => LogInvalidAndReturn(topology, nameof(PrimitiveTopology), PrimitiveTopology.TriangleStrip), - }; - } - public static StencilOp Convert(this GAL.StencilOp op) { return op switch diff --git a/src/Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs b/src/Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs index 9420aa31c..b6694bcb3 100644 --- a/src/Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs +++ b/src/Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs @@ -31,7 +31,6 @@ namespace Ryujinx.Graphics.Vulkan public readonly bool SupportsShaderStorageImageMultisample; public readonly bool SupportsConditionalRendering; public readonly bool SupportsExtendedDynamicState; - public readonly PhysicalDeviceExtendedDynamicState2FeaturesEXT SupportsExtendedDynamicState2; public readonly bool SupportsMultiView; public readonly bool SupportsNullDescriptors; public readonly bool SupportsPushDescriptors; @@ -47,14 +46,12 @@ namespace Ryujinx.Graphics.Vulkan public readonly bool SupportsViewportArray2; public readonly bool SupportsHostImportedMemory; public readonly bool SupportsDepthClipControl; - public readonly bool SupportsWideLines; public readonly uint SubgroupSize; public readonly SampleCountFlags SupportedSampleCounts; public readonly PortabilitySubsetFlags PortabilitySubset; public readonly uint VertexBufferAlignment; public readonly uint SubTexelPrecisionBits; public readonly ulong MinResourceAlignment; - public readonly uint MaxTessellationPatchSize; public HardwareCapabilities( bool supportsIndexTypeUint8, @@ -72,8 +69,6 @@ namespace Ryujinx.Graphics.Vulkan bool supportsShaderStorageImageMultisample, bool supportsConditionalRendering, bool supportsExtendedDynamicState, - PhysicalDeviceExtendedDynamicState2FeaturesEXT supportsExtendedDynamicState2, - uint maxTessellationPatchSize, bool supportsMultiView, bool supportsNullDescriptors, bool supportsPushDescriptors, @@ -89,7 +84,6 @@ namespace Ryujinx.Graphics.Vulkan bool supportsViewportArray2, bool supportsHostImportedMemory, bool supportsDepthClipControl, - bool supportsWideLines, uint subgroupSize, SampleCountFlags supportedSampleCounts, PortabilitySubsetFlags portabilitySubset, @@ -112,8 +106,6 @@ namespace Ryujinx.Graphics.Vulkan SupportsShaderStorageImageMultisample = supportsShaderStorageImageMultisample; SupportsConditionalRendering = supportsConditionalRendering; SupportsExtendedDynamicState = supportsExtendedDynamicState; - SupportsExtendedDynamicState2 = supportsExtendedDynamicState2; - MaxTessellationPatchSize = maxTessellationPatchSize; SupportsMultiView = supportsMultiView; SupportsNullDescriptors = supportsNullDescriptors; SupportsPushDescriptors = supportsPushDescriptors; @@ -129,7 +121,6 @@ namespace Ryujinx.Graphics.Vulkan SupportsViewportArray2 = supportsViewportArray2; SupportsHostImportedMemory = supportsHostImportedMemory; SupportsDepthClipControl = supportsDepthClipControl; - SupportsWideLines = supportsWideLines; SubgroupSize = subgroupSize; SupportedSampleCounts = supportedSampleCounts; PortabilitySubset = portabilitySubset; diff --git a/src/Ryujinx.Graphics.Vulkan/HelperShader.cs b/src/Ryujinx.Graphics.Vulkan/HelperShader.cs index 07146b231..88e6e39ea 100644 --- a/src/Ryujinx.Graphics.Vulkan/HelperShader.cs +++ b/src/Ryujinx.Graphics.Vulkan/HelperShader.cs @@ -405,35 +405,35 @@ namespace Ryujinx.Graphics.Vulkan if (dstIsDepthOrStencil) { - _pipeline.SetProgram(src.Info.Target.IsMultisample() ? _programDepthBlitMs : _programDepthBlit, false); - _pipeline.SetDepthTest(new DepthTestDescriptor(true, true, CompareOp.Always), false); + _pipeline.SetProgram(src.Info.Target.IsMultisample() ? _programDepthBlitMs : _programDepthBlit); + _pipeline.SetDepthTest(new DepthTestDescriptor(true, true, CompareOp.Always)); } else if (src.Info.Target.IsMultisample()) { - _pipeline.SetProgram(_programColorBlitMs, false); + _pipeline.SetProgram(_programColorBlitMs); } else if (clearAlpha) { - _pipeline.SetProgram(_programColorBlitClearAlpha, false); + _pipeline.SetProgram(_programColorBlitClearAlpha); } else { - _pipeline.SetProgram(_programColorBlit, false); + _pipeline.SetProgram(_programColorBlit); } int dstWidth = dst.Width; int dstHeight = dst.Height; - _pipeline.SetRenderTarget(dst, (uint)dstWidth, (uint)dstHeight, false); - _pipeline.SetRenderTargetColorMasks([0xf], false); - _pipeline.SetScissors([new Rectangle(0, 0, dstWidth, dstHeight)], false); + _pipeline.SetRenderTarget(dst, (uint)dstWidth, (uint)dstHeight); + _pipeline.SetRenderTargetColorMasks([0xf]); + _pipeline.SetScissors([new Rectangle(0, 0, dstWidth, dstHeight)]); if (clearAlpha) { _pipeline.ClearRenderTargetColor(0, 0, 1, new ColorF(0f, 0f, 0f, 1f)); } - _pipeline.SetViewports(viewports, false); + _pipeline.SetViewports(viewports); _pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip); _pipeline.Draw(4, 1, 0, 0); @@ -500,10 +500,10 @@ namespace Ryujinx.Graphics.Vulkan int dstWidth = dst.Width; int dstHeight = dst.Height; - _pipeline.SetRenderTarget(dst, (uint)dstWidth, (uint)dstHeight, false); - _pipeline.SetScissors([new Rectangle(0, 0, dstWidth, dstHeight)], false); - _pipeline.SetViewports(viewports, false); - _pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip, false); + _pipeline.SetRenderTarget(dst, (uint)dstWidth, (uint)dstHeight); + _pipeline.SetScissors([new Rectangle(0, 0, dstWidth, dstHeight)]); + _pipeline.SetViewports(viewports); + _pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip); var aspectFlags = src.Info.Format.ConvertAspectFlags(); @@ -565,12 +565,12 @@ namespace Ryujinx.Graphics.Vulkan if (isDepth) { - _pipeline.SetProgram(src.Info.Target.IsMultisample() ? _programDepthBlitMs : _programDepthBlit, false); + _pipeline.SetProgram(src.Info.Target.IsMultisample() ? _programDepthBlitMs : _programDepthBlit); _pipeline.SetDepthTest(new DepthTestDescriptor(true, true, CompareOp.Always)); } else { - _pipeline.SetProgram(src.Info.Target.IsMultisample() ? _programStencilBlitMs : _programStencilBlit, false); + _pipeline.SetProgram(src.Info.Target.IsMultisample() ? _programStencilBlitMs : _programStencilBlit); _pipeline.SetStencilTest(CreateStencilTestDescriptor(true)); } @@ -660,11 +660,11 @@ namespace Ryujinx.Graphics.Vulkan program = _programColorClearF; } - _pipeline.SetProgram(program, false); - _pipeline.SetRenderTarget(dst, (uint)dstWidth, (uint)dstHeight, false); - _pipeline.SetRenderTargetColorMasks(new[] { componentMask }, false); - _pipeline.SetViewports(viewports, false); - _pipeline.SetScissors([scissor], false); + _pipeline.SetProgram(program); + _pipeline.SetRenderTarget(dst, (uint)dstWidth, (uint)dstHeight); + _pipeline.SetRenderTargetColorMasks(new[] { componentMask }); + _pipeline.SetViewports(viewports); + _pipeline.SetScissors([scissor]); _pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip); _pipeline.Draw(4, 1, 0, 0); _pipeline.Finish(); @@ -707,12 +707,12 @@ namespace Ryujinx.Graphics.Vulkan 0f, 1f); - _pipeline.SetProgram(_programDepthStencilClear, false); - _pipeline.SetRenderTarget(dst, (uint)dstWidth, (uint)dstHeight, false); - _pipeline.SetViewports(viewports, false); - _pipeline.SetScissors([scissor], false); - _pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip, false); - _pipeline.SetDepthTest(new DepthTestDescriptor(true, depthMask, CompareOp.Always), false); + _pipeline.SetProgram(_programDepthStencilClear); + _pipeline.SetRenderTarget(dst, (uint)dstWidth, (uint)dstHeight); + _pipeline.SetViewports(viewports); + _pipeline.SetScissors([scissor]); + _pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip); + _pipeline.SetDepthTest(new DepthTestDescriptor(true, depthMask, CompareOp.Always)); _pipeline.SetStencilTest(CreateStencilTestDescriptor(stencilMask != 0, stencilValue, 0xff, stencilMask)); _pipeline.Draw(4, 1, 0, 0); _pipeline.Finish(); @@ -770,8 +770,8 @@ namespace Ryujinx.Graphics.Vulkan 0f, 1f); - pipeline.SetProgram(_programColorBlit, false); - pipeline.SetViewports(viewports, false); + pipeline.SetProgram(_programColorBlit); + pipeline.SetViewports(viewports); pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip); pipeline.Draw(4, 1, 0, 0); @@ -1093,16 +1093,16 @@ namespace Ryujinx.Graphics.Vulkan 0f, 1f); - _pipeline.SetScissors([new Rectangle(0, 0, dst.Width, dst.Height)], false); - _pipeline.SetViewports(viewports, false); - _pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip, false); + _pipeline.SetScissors([new Rectangle(0, 0, dst.Width, dst.Height)]); + _pipeline.SetViewports(viewports); + _pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip); for (int z = 0; z < depth; z++) { var srcView = Create2DLayerView(src, srcLayer + z, 0); var dstView = Create2DLayerView(dst, dstLayer + z, 0); - _pipeline.SetRenderTarget(dstView, (uint)dst.Width, (uint)dst.Height, false); + _pipeline.SetRenderTarget(dstView, (uint)dst.Width, (uint)dst.Height); CopyMSDraw(srcView, aspectFlags, fromMS: true); @@ -1215,9 +1215,9 @@ namespace Ryujinx.Graphics.Vulkan 1f); _pipeline.SetRenderTargetColorMasks([0xf]); - _pipeline.SetScissors([new Rectangle(0, 0, dst.Width, dst.Height)], false); - _pipeline.SetViewports(viewports, false); - _pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip, false); + _pipeline.SetScissors([new Rectangle(0, 0, dst.Width, dst.Height)]); + _pipeline.SetViewports(viewports); + _pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip); _pipeline.SetUniformBuffers([new BufferAssignment(0, buffer.Range)]); @@ -1228,7 +1228,7 @@ namespace Ryujinx.Graphics.Vulkan var srcView = Create2DLayerView(src, srcLayer + z, 0); var dstView = Create2DLayerView(dst, dstLayer + z, 0); - _pipeline.SetRenderTarget(dstView, (uint)dst.Width, (uint)dst.Height, false); + _pipeline.SetRenderTarget(dstView, (uint)dst.Width, (uint)dst.Height); CopyMSDraw(srcView, aspectFlags, fromMS: false); @@ -1245,7 +1245,7 @@ namespace Ryujinx.Graphics.Vulkan } else { - _pipeline.SetProgram(_programColorDrawToMs, false); + _pipeline.SetProgram(_programColorDrawToMs); var format = GetFormat(src.Info.BytesPerPixel); var vkFormat = FormatTable.GetFormat(format); @@ -1322,12 +1322,12 @@ namespace Ryujinx.Graphics.Vulkan if (isDepth) { - _pipeline.SetProgram(fromMS ? _programDepthDrawToNonMs : _programDepthDrawToMs, false); + _pipeline.SetProgram(fromMS ? _programDepthDrawToNonMs : _programDepthDrawToMs); _pipeline.SetDepthTest(new DepthTestDescriptor(true, true, CompareOp.Always)); } else { - _pipeline.SetProgram(fromMS ? _programStencilDrawToNonMs : _programStencilDrawToMs, false); + _pipeline.SetProgram(fromMS ? _programStencilDrawToNonMs : _programStencilDrawToMs); _pipeline.SetStencilTest(CreateStencilTestDescriptor(true)); } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 083ee2926..390816a56 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -72,7 +72,6 @@ namespace Ryujinx.Graphics.Vulkan private readonly BufferState[] _transformFeedbackBuffers; private readonly VertexBufferState[] _vertexBuffers; private ulong _vertexBuffersDirty; - private bool _bindingsSet; protected Rectangle ClearScissor; private readonly VertexBufferUpdater _vertexBufferUpdater; @@ -86,15 +85,10 @@ namespace Ryujinx.Graphics.Vulkan private bool _tfEnabled; private bool _tfActive; - private readonly bool _supportExtDynamic; - private readonly bool _supportExtDynamic2; - private readonly PipelineColorBlendAttachmentState[] _storedBlend; public ulong DrawCount { get; private set; } public bool RenderPassActive { get; private set; } - private readonly int[] _vertexBufferBindings; - public unsafe PipelineBase(VulkanRenderer gd, Device device) { Gd = gd; @@ -127,19 +121,7 @@ namespace Ryujinx.Graphics.Vulkan _storedBlend = new PipelineColorBlendAttachmentState[Constants.MaxRenderTargets]; - _supportExtDynamic = gd.Capabilities.SupportsExtendedDynamicState; - - _supportExtDynamic2 = gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2; - - _bindingsSet = false; - - _vertexBufferBindings = new int[Constants.MaxVertexBuffers]; - for (int i = 0; i < Constants.MaxVertexBuffers; i++) - { - _vertexBufferBindings[i] = i + 1; - } - - _newState.Initialize(gd.Capabilities); + _newState.Initialize(); } public void Initialize() @@ -645,46 +627,19 @@ namespace Ryujinx.Graphics.Vulkan { if (texture is TextureView srcTexture) { - CullModeFlags oldCullMode; - bool oldStencilTestEnable; - bool oldDepthTestEnable; - bool oldDepthWriteEnable; - PrimitiveTopology oldTopology; - Array16 oldViewports = DynamicState.Viewports; - uint oldViewportsCount; + var oldCullMode = _newState.CullMode; + var oldStencilTestEnable = _newState.StencilTestEnable; + var oldDepthTestEnable = _newState.DepthTestEnable; + var oldDepthWriteEnable = _newState.DepthWriteEnable; + var oldViewports = DynamicState.Viewports; + var oldViewportsCount = _newState.ViewportsCount; + var oldTopology = _topology; - if (_supportExtDynamic) - { - oldCullMode = DynamicState.CullMode; - oldStencilTestEnable = DynamicState.StencilTestEnable; - oldDepthTestEnable = DynamicState.DepthTestEnable; - oldDepthWriteEnable = DynamicState.DepthWriteEnable; - oldTopology = _topology; - oldViewportsCount = DynamicState.ViewportsCount; - } - else - { - oldCullMode = _newState.CullMode; - oldStencilTestEnable = _newState.StencilTestEnable; - oldDepthTestEnable = _newState.DepthTestEnable; - oldDepthWriteEnable = _newState.DepthWriteEnable; - oldTopology = _topology; - oldViewportsCount = _newState.ViewportsCount; - } - - if (_supportExtDynamic) - { - DynamicState.SetCullMode(CullModeFlags.None); - DynamicState.SetDepthTestBool(false, false); - DynamicState.SetStencilTest(false); - } - else - { - _newState.CullMode = CullModeFlags.None; - _newState.StencilTestEnable = false; - _newState.DepthTestEnable = false; - _newState.DepthWriteEnable = false; - } + _newState.CullMode = CullModeFlags.None; + _newState.StencilTestEnable = false; + _newState.DepthTestEnable = false; + _newState.DepthWriteEnable = false; + SignalStateChange(); Gd.HelperShader.DrawTexture( Gd, @@ -694,24 +649,16 @@ namespace Ryujinx.Graphics.Vulkan srcRegion, dstRegion); - if (_supportExtDynamic) - { - DynamicState.SetCullMode(oldCullMode); - DynamicState.SetStencilTest(oldStencilTestEnable); - DynamicState.SetDepthTestBool(oldDepthTestEnable, oldDepthWriteEnable); - } - else - { - _newState.CullMode = oldCullMode; - _newState.StencilTestEnable = oldStencilTestEnable; - _newState.DepthTestEnable = oldDepthTestEnable; - _newState.DepthWriteEnable = oldDepthWriteEnable; - _newState.ViewportsCount = oldViewportsCount; - } - + _newState.CullMode = oldCullMode; + _newState.StencilTestEnable = oldStencilTestEnable; + _newState.DepthTestEnable = oldDepthTestEnable; + _newState.DepthWriteEnable = oldDepthWriteEnable; SetPrimitiveTopology(oldTopology); DynamicState.SetViewports(ref oldViewports, oldViewportsCount); + + _newState.ViewportsCount = oldViewportsCount; + SignalStateChange(); } } @@ -840,101 +787,46 @@ namespace Ryujinx.Graphics.Vulkan public void SetDepthBias(PolygonModeMask enables, float factor, float units, float clamp) { - bool depthBiasEnable = (enables != 0) && (factor != 0 && units != 0); - bool changed = false; + DynamicState.SetDepthBias(factor, units, clamp); - if (_supportExtDynamic2) - { - DynamicState.SetDepthBiasEnable(depthBiasEnable); - } - else if (_newState.DepthBiasEnable != depthBiasEnable) - { - _newState.DepthBiasEnable = depthBiasEnable; - changed = true; - } - - if (depthBiasEnable) - { - DynamicState.SetDepthBias(factor, units, clamp); - } - - if (changed) - { - SignalStateChange(); - } + _newState.DepthBiasEnable = enables != 0; + SignalStateChange(); } public void SetDepthClamp(bool clamp) { _newState.DepthClampEnable = clamp; - SignalStateChange(); } public void SetDepthMode(DepthMode mode) { - bool newMode = mode == DepthMode.MinusOneToOne; - - if (_newState.DepthMode == newMode) + bool oldMode = _newState.DepthMode; + _newState.DepthMode = mode == DepthMode.MinusOneToOne; + if (_newState.DepthMode != oldMode) { - return; + SignalStateChange(); } + } - _newState.DepthMode = newMode; - + public void SetDepthTest(DepthTestDescriptor depthTest) + { + _newState.DepthTestEnable = depthTest.TestEnable; + _newState.DepthWriteEnable = depthTest.WriteEnable; + _newState.DepthCompareOp = depthTest.Func.Convert(); SignalStateChange(); } - public void SetDepthTest(DepthTestDescriptor depthTest, bool signalChange = true) + public void SetFaceCulling(bool enable, Face face) { - if (_supportExtDynamic) - { - DynamicState.SetDepthTestBool(depthTest.TestEnable, depthTest.WriteEnable); - if (depthTest.TestEnable) - { - DynamicState.SetDepthTestCompareOp(depthTest.Func.Convert()); - } - } - else - { - _newState.DepthTestEnable = depthTest.TestEnable; - _newState.DepthWriteEnable = depthTest.WriteEnable; - _newState.DepthCompareOp = depthTest.Func.Convert(); - - if (signalChange) - { - SignalStateChange(); - } - } - - } - - public void SetFaceCulling(Face face) - { - if (_supportExtDynamic) - { - DynamicState.SetCullMode(face.Convert()); - } - else - { - _newState.CullMode = face.Convert(); - - SignalStateChange(); - } + _newState.CullMode = enable ? face.Convert() : CullModeFlags.None; + SignalStateChange(); } public void SetFrontFace(FrontFace frontFace) { - if (_supportExtDynamic) - { - DynamicState.SetFrontFace(frontFace.Convert()); - } - else - { - _newState.FrontFace = frontFace.Convert(); - - SignalStateChange(); - } + _newState.FrontFace = frontFace.Convert(); + SignalStateChange(); } public void SetImage(ShaderStage stage, int binding, ITexture image) @@ -973,56 +865,28 @@ namespace Ryujinx.Graphics.Vulkan public void SetLineParameters(float width, bool smooth) { - if (!Gd.IsMoltenVk) - { - DynamicState.SetLineWidth(Gd.Capabilities.SupportsWideLines ? width : 1.0f); - } + _newState.LineWidth = width; + SignalStateChange(); } public void SetLogicOpState(bool enable, LogicalOp op) { - // Vendors other than NVIDIA have a bug where it enables logical operations even for float formats, - // so we need to force disable them here. - bool logicOpEnable = enable && (Gd.Vendor == Vendor.Nvidia || _newState.Internal.LogicOpsAllowed); - _newState.LogicOpEnable = enable; - - if (Gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2LogicOp) - { - if (logicOpEnable) - { - DynamicState.SetLogicOp(op.Convert()); - } - } - else - { - _newState.LogicOp = op.Convert(); - } - + _newState.LogicOp = op.Convert(); SignalStateChange(); } public void SetMultisampleState(MultisampleDescriptor multisample) { _newState.AlphaToCoverageEnable = multisample.AlphaToCoverageEnable; - _newState.AlphaToOneEnable = multisample.AlphaToOneEnable; - SignalStateChange(); } public void SetPatchParameters(int vertices, ReadOnlySpan defaultOuterLevel, ReadOnlySpan defaultInnerLevel) { - if (Gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints) - { - DynamicState.SetPatchControlPoints((uint)vertices); - } - else - { - _newState.PatchControlPoints = (uint)vertices; - - SignalStateChange(); - } + _newState.PatchControlPoints = (uint)vertices; + SignalStateChange(); // TODO: Default levels (likely needs emulation on shaders?) } @@ -1039,21 +903,12 @@ namespace Ryujinx.Graphics.Vulkan public void SetPrimitiveRestart(bool enable, int index) { - if (_supportExtDynamic2) - { - DynamicState.SetPrimitiveRestartEnable(enable); - } - else - { - _newState.PrimitiveRestartEnable = enable; - - SignalStateChange(); - } - + _newState.PrimitiveRestartEnable = enable; // TODO: What to do about the index? + SignalStateChange(); } - public void SetPrimitiveTopology(PrimitiveTopology topology, bool signalChange = true) + public void SetPrimitiveTopology(PrimitiveTopology topology) { _topology = topology; @@ -1061,18 +916,10 @@ namespace Ryujinx.Graphics.Vulkan _newState.Topology = vkTopology; - if (_supportExtDynamic) - { - DynamicState.SetPrimitiveTopology(vkTopology); - } - - if (signalChange) - { - SignalStateChange(); - } + SignalStateChange(); } - public void SetProgram(IProgram program, bool signalChange = true) + public void SetProgram(IProgram program) { var internalProgram = (ShaderCollection)program; var stages = internalProgram.GetInfos(); @@ -1088,10 +935,7 @@ namespace Ryujinx.Graphics.Vulkan stages.CopyTo(_newState.Stages.AsSpan()[..stages.Length]); - if (signalChange) - { - SignalStateChange(); - } + SignalStateChange(); if (internalProgram.IsCompute) { @@ -1117,26 +961,18 @@ namespace Ryujinx.Graphics.Vulkan public void SetRasterizerDiscard(bool discard) { - if (_supportExtDynamic2) - { - DynamicState.SetRasterizerDiscard(discard); - } - else - { - _newState.RasterizerDiscardEnable = discard; - - SignalStateChange(); - } + _newState.RasterizerDiscardEnable = discard; + SignalStateChange(); if (!discard && Gd.IsQualcommProprietary) { // On Adreno, enabling rasterizer discard somehow corrupts the viewport state. // Force it to be updated on next use to work around this bug. - DynamicState.ForceAllDirty(Gd); + DynamicState.ForceAllDirty(); } } - public void SetRenderTargetColorMasks(ReadOnlySpan componentMask, bool signalChange = true) + public void SetRenderTargetColorMasks(ReadOnlySpan componentMask) { int count = Math.Min(Constants.MaxRenderTargets, componentMask.Length); int writtenAttachments = 0; @@ -1176,10 +1012,7 @@ namespace Ryujinx.Graphics.Vulkan } else { - if (signalChange) - { - SignalStateChange(); - } + SignalStateChange(); if (writtenAttachments != _writtenAttachmentCount) { @@ -1203,7 +1036,7 @@ namespace Ryujinx.Graphics.Vulkan SetRenderTargetsInternal(colors, depthStencil, Gd.IsTBDR); } - public void SetScissors(ReadOnlySpan> regions, bool signalChange = true) + public void SetScissors(ReadOnlySpan> regions) { int maxScissors = Gd.Capabilities.SupportsMultiView ? Constants.MaxViewports : 1; int count = Math.Min(maxScissors, regions.Length); @@ -1212,8 +1045,6 @@ namespace Ryujinx.Graphics.Vulkan ClearScissor = regions[0]; } - DynamicState.ScissorsCount = count; - for (int i = 0; i < count; i++) { var region = regions[i]; @@ -1223,55 +1054,32 @@ namespace Ryujinx.Graphics.Vulkan DynamicState.SetScissor(i, new Rect2D(offset, extent)); } - if (!_supportExtDynamic) - { - _newState.ScissorsCount = (uint)count; + DynamicState.ScissorsCount = count; - if (signalChange) - { - SignalStateChange(); - } - } + _newState.ScissorsCount = (uint)count; + SignalStateChange(); } public void SetStencilTest(StencilTestDescriptor stencilTest) { - if (_supportExtDynamic) - { - DynamicState.SetStencilTestandOp( - stencilTest.BackSFail.Convert(), - stencilTest.BackDpPass.Convert(), - stencilTest.BackDpFail.Convert(), - stencilTest.BackFunc.Convert(), - stencilTest.FrontSFail.Convert(), - stencilTest.FrontDpPass.Convert(), - stencilTest.FrontDpFail.Convert(), - stencilTest.FrontFunc.Convert(), - stencilTest.TestEnable); - - SignalStateChange(); - } - else - { - _newState.StencilBackFailOp = stencilTest.BackSFail.Convert(); - _newState.StencilBackPassOp = stencilTest.BackDpPass.Convert(); - _newState.StencilBackDepthFailOp = stencilTest.BackDpFail.Convert(); - _newState.StencilBackCompareOp = stencilTest.BackFunc.Convert(); - _newState.StencilFrontFailOp = stencilTest.FrontSFail.Convert(); - _newState.StencilFrontPassOp = stencilTest.FrontDpPass.Convert(); - _newState.StencilFrontDepthFailOp = stencilTest.FrontDpFail.Convert(); - _newState.StencilFrontCompareOp = stencilTest.FrontFunc.Convert(); - _newState.StencilTestEnable = stencilTest.TestEnable; - - SignalStateChange(); - } - - DynamicState.SetStencilMask((uint)stencilTest.BackFuncMask, + DynamicState.SetStencilMasks( + (uint)stencilTest.BackFuncMask, (uint)stencilTest.BackMask, (uint)stencilTest.BackFuncRef, (uint)stencilTest.FrontFuncMask, (uint)stencilTest.FrontMask, (uint)stencilTest.FrontFuncRef); + + _newState.StencilTestEnable = stencilTest.TestEnable; + _newState.StencilBackFailOp = stencilTest.BackSFail.Convert(); + _newState.StencilBackPassOp = stencilTest.BackDpPass.Convert(); + _newState.StencilBackDepthFailOp = stencilTest.BackDpFail.Convert(); + _newState.StencilBackCompareOp = stencilTest.BackFunc.Convert(); + _newState.StencilFrontFailOp = stencilTest.FrontSFail.Convert(); + _newState.StencilFrontPassOp = stencilTest.FrontDpPass.Convert(); + _newState.StencilFrontDepthFailOp = stencilTest.FrontDpFail.Convert(); + _newState.StencilFrontCompareOp = stencilTest.FrontFunc.Convert(); + SignalStateChange(); } public void SetStorageBuffers(ReadOnlySpan buffers) @@ -1390,24 +1198,12 @@ namespace Ryujinx.Graphics.Vulkan { int count = Math.Min(Constants.MaxVertexBuffers, vertexBuffers.Length); + _newState.Internal.VertexBindingDescriptions[0] = new VertexInputBindingDescription(0, 0, VertexInputRate.Vertex); + int validCount = 1; - if (!_bindingsSet) - { - _newState.Internal.VertexBindingDescriptions[0] = new VertexInputBindingDescription(0, _supportExtDynamic && (!Gd.IsMoltenVk || Gd.SupportsMTL31) ? null : 0, VertexInputRate.Vertex); - - for (int i = 1; i < count; i++) - { - _newState.Internal.VertexBindingDescriptions[i] = new VertexInputBindingDescription((uint)i); - } - - _bindingsSet = true; - } - BufferHandle lastHandle = default; Auto lastBuffer = default; - bool vertexBindingDescriptionChanged = false; - bool vertexDescriptionCountChanged = false; for (int i = 0; i < count; i++) { @@ -1426,32 +1222,13 @@ namespace Ryujinx.Graphics.Vulkan if (vb != null) { + int binding = i + 1; int descriptorIndex = validCount++; - if (_supportExtDynamic && (!Gd.IsMoltenVk || Gd.SupportsMTL31)) - { - if (_newState.Internal.VertexBindingDescriptions[descriptorIndex].InputRate != inputRate || - _newState.Internal.VertexBindingDescriptions[descriptorIndex].Binding != _vertexBufferBindings[i]) - { - _newState.Internal.VertexBindingDescriptions[descriptorIndex].InputRate = inputRate; - _newState.Internal.VertexBindingDescriptions[descriptorIndex].Binding = (uint)_vertexBufferBindings[i]; - - vertexBindingDescriptionChanged = true; - } - } - else - { - if (_newState.Internal.VertexBindingDescriptions[descriptorIndex].InputRate != inputRate || - _newState.Internal.VertexBindingDescriptions[descriptorIndex].Stride != vertexBuffer.Stride || - _newState.Internal.VertexBindingDescriptions[descriptorIndex].Binding != _vertexBufferBindings[i]) - { - _newState.Internal.VertexBindingDescriptions[descriptorIndex].Binding = (uint)_vertexBufferBindings[i]; - _newState.Internal.VertexBindingDescriptions[descriptorIndex].Stride = (uint)vertexBuffer.Stride; - _newState.Internal.VertexBindingDescriptions[descriptorIndex].InputRate = inputRate; - - vertexBindingDescriptionChanged = true; - } - } + _newState.Internal.VertexBindingDescriptions[descriptorIndex] = new VertexInputBindingDescription( + (uint)binding, + (uint)vertexBuffer.Stride, + inputRate); int vbSize = vertexBuffer.Buffer.Size; @@ -1467,7 +1244,7 @@ namespace Ryujinx.Graphics.Vulkan } } - ref var buffer = ref _vertexBuffers[_vertexBufferBindings[i]]; + ref var buffer = ref _vertexBuffers[binding]; int oldScalarAlign = buffer.AttributeScalarAlignment; if (Gd.Capabilities.VertexBufferAlignment < 2 && @@ -1484,7 +1261,7 @@ namespace Ryujinx.Graphics.Vulkan vbSize, vertexBuffer.Stride); - buffer.BindVertexBuffer(Gd, Cbs, (uint)_vertexBufferBindings[i], ref _newState, _vertexBufferUpdater); + buffer.BindVertexBuffer(Gd, Cbs, (uint)binding, ref _newState, _vertexBufferUpdater); } } else @@ -1500,7 +1277,7 @@ namespace Ryujinx.Graphics.Vulkan vbSize, vertexBuffer.Stride); - _vertexBuffersDirty |= 1UL << _vertexBufferBindings[i]; + _vertexBuffersDirty |= 1UL << binding; } buffer.AttributeScalarAlignment = oldScalarAlign; @@ -1510,19 +1287,11 @@ namespace Ryujinx.Graphics.Vulkan _vertexBufferUpdater.Commit(Cbs); - if (_newState.VertexBindingDescriptionsCount != validCount) - { - _newState.VertexBindingDescriptionsCount = (uint)validCount; - vertexDescriptionCountChanged = true; - } - - if (vertexDescriptionCountChanged || vertexBindingDescriptionChanged) - { - SignalStateChange(); - } + _newState.VertexBindingDescriptionsCount = (uint)validCount; + SignalStateChange(); } - public void SetViewports(ReadOnlySpan viewports, bool signalChange = true) + public void SetViewports(ReadOnlySpan viewports) { int maxViewports = Gd.Capabilities.SupportsMultiView ? Constants.MaxViewports : 1; int count = Math.Min(maxViewports, viewports.Length); @@ -1547,15 +1316,8 @@ namespace Ryujinx.Graphics.Vulkan Clamp(viewport.DepthFar))); } - if (!_supportExtDynamic) - { - _newState.ViewportsCount = (uint)count; - - if (signalChange) - { - SignalStateChange(); - } - } + _newState.ViewportsCount = (uint)count; + SignalStateChange(); } public void SwapBuffer(Auto from, Auto to) @@ -1604,7 +1366,7 @@ namespace Ryujinx.Graphics.Vulkan _vertexBuffersDirty = ulong.MaxValue >> (64 - _vertexBuffers.Length); _descriptorSetUpdater.SignalCommandBufferChange(); - DynamicState.ForceAllDirty(Gd); + DynamicState.ForceAllDirty(); _currentPipelineHandle = 0; } @@ -1743,7 +1505,7 @@ namespace Ryujinx.Graphics.Vulkan Gd.FlushAllCommands(); } - DynamicState.ReplayIfDirty(Gd, CommandBuffer); + DynamicState.ReplayIfDirty(Gd.Api, CommandBuffer); if (_needsIndexBufferRebind && _indexBufferPattern == null) { diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs index 0ead969f8..8a895f927 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs @@ -160,83 +160,63 @@ namespace Ryujinx.Graphics.Vulkan public static PipelineState ToVulkanPipelineState(this ProgramPipelineState state, VulkanRenderer gd) { - var extendedDynamicState2 = gd.Capabilities.SupportsExtendedDynamicState2; - var extendedDynamicState = gd.Capabilities.SupportsExtendedDynamicState; - PipelineState pipeline = new(); - pipeline.Initialize(gd.Capabilities); + pipeline.Initialize(); // It is assumed that Dynamic State is enabled when this conversion is used. + + pipeline.CullMode = state.CullEnable ? state.CullMode.Convert() : CullModeFlags.None; + pipeline.DepthBoundsTestEnable = false; // Not implemented. pipeline.DepthClampEnable = state.DepthClampEnable; - pipeline.AlphaToCoverageEnable = state.AlphaToCoverageEnable; - pipeline.AlphaToOneEnable = state.AlphaToOneEnable; - + pipeline.DepthTestEnable = state.DepthTest.TestEnable; + pipeline.DepthWriteEnable = state.DepthTest.WriteEnable; + pipeline.DepthCompareOp = state.DepthTest.Func.Convert(); pipeline.DepthMode = state.DepthMode == DepthMode.MinusOneToOne; + pipeline.FrontFace = state.FrontFace.Convert(); + pipeline.HasDepthStencil = state.DepthStencilEnable; + pipeline.LineWidth = state.LineWidth; + pipeline.LogicOpEnable = state.LogicOpEnable; + pipeline.LogicOp = state.LogicOp.Convert(); + pipeline.PatchControlPoints = state.PatchControlPoints; pipeline.PolygonMode = PolygonMode.Fill; // Not implemented. - - pipeline.Topology = gd.TopologyRemap(state.Topology).Convert(); - - if (!extendedDynamicState) - { - pipeline.DepthCompareOp = state.DepthTest.Func.Convert(); - pipeline.CullMode = state.CullMode.Convert(); - - pipeline.DepthTestEnable = state.DepthTest.TestEnable; - pipeline.DepthWriteEnable = state.DepthTest.WriteEnable; - - pipeline.FrontFace = state.FrontFace.Convert(); - - if (gd.Capabilities.SupportsMultiView) - { - pipeline.ScissorsCount = Constants.MaxViewports; - pipeline.ViewportsCount = Constants.MaxViewports; - } - else - { - pipeline.ScissorsCount = 1; - pipeline.ViewportsCount = 1; - } - - pipeline.StencilTestEnable = state.StencilTest.TestEnable; - - pipeline.StencilFrontFailOp = state.StencilTest.FrontSFail.Convert(); - pipeline.StencilFrontPassOp = state.StencilTest.FrontDpPass.Convert(); - pipeline.StencilFrontDepthFailOp = state.StencilTest.FrontDpFail.Convert(); - pipeline.StencilFrontCompareOp = state.StencilTest.FrontFunc.Convert(); - - pipeline.StencilBackFailOp = state.StencilTest.BackSFail.Convert(); - pipeline.StencilBackPassOp = state.StencilTest.BackDpPass.Convert(); - pipeline.StencilBackDepthFailOp = state.StencilTest.BackDpFail.Convert(); - pipeline.StencilBackCompareOp = state.StencilTest.BackFunc.Convert(); - } - - if (!extendedDynamicState2.ExtendedDynamicState2) - { - pipeline.PrimitiveRestartEnable = state.PrimitiveRestartEnable; - pipeline.RasterizerDiscardEnable = state.RasterizerDiscard; - pipeline.DepthBiasEnable = (state.BiasEnable != 0) && - (state.DepthBiasFactor != 0 && state.DepthBiasUnits != 0); - } - - if (!extendedDynamicState2.ExtendedDynamicState2LogicOp) - { - pipeline.LogicOp = state.LogicOp.Convert(); - } - - if (!extendedDynamicState2.ExtendedDynamicState2PatchControlPoints) - { - pipeline.PatchControlPoints = state.PatchControlPoints; - } - + pipeline.PrimitiveRestartEnable = state.PrimitiveRestartEnable; + pipeline.RasterizerDiscardEnable = state.RasterizerDiscard; pipeline.SamplesCount = (uint)state.SamplesCount; - pipeline.LogicOpEnable = state.LogicOpEnable; + if (gd.Capabilities.SupportsMultiView) + { + pipeline.ScissorsCount = Constants.MaxViewports; + pipeline.ViewportsCount = Constants.MaxViewports; + } + else + { + pipeline.ScissorsCount = 1; + pipeline.ViewportsCount = 1; + } + + pipeline.DepthBiasEnable = state.BiasEnable != 0; + + // Stencil masks and ref are dynamic, so are 0 in the Vulkan pipeline. + + pipeline.StencilFrontFailOp = state.StencilTest.FrontSFail.Convert(); + pipeline.StencilFrontPassOp = state.StencilTest.FrontDpPass.Convert(); + pipeline.StencilFrontDepthFailOp = state.StencilTest.FrontDpFail.Convert(); + pipeline.StencilFrontCompareOp = state.StencilTest.FrontFunc.Convert(); + + pipeline.StencilBackFailOp = state.StencilTest.BackSFail.Convert(); + pipeline.StencilBackPassOp = state.StencilTest.BackDpPass.Convert(); + pipeline.StencilBackDepthFailOp = state.StencilTest.BackDpFail.Convert(); + pipeline.StencilBackCompareOp = state.StencilTest.BackFunc.Convert(); + + pipeline.StencilTestEnable = state.StencilTest.TestEnable; + + pipeline.Topology = gd.TopologyRemap(state.Topology).Convert(); int vaCount = Math.Min(Constants.MaxVertexAttributes, state.VertexAttribCount); int vbCount = Math.Min(Constants.MaxVertexBuffers, state.VertexBufferCount); @@ -261,7 +241,7 @@ namespace Ryujinx.Graphics.Vulkan } int descriptorIndex = 1; - pipeline.Internal.VertexBindingDescriptions[0] = new VertexInputBindingDescription(0, extendedDynamicState && (!gd.IsMoltenVk || gd.SupportsMTL31) ? null : 0, VertexInputRate.Vertex); + pipeline.Internal.VertexBindingDescriptions[0] = new VertexInputBindingDescription(0, 0, VertexInputRate.Vertex); for (int i = 0; i < vbCount; i++) { @@ -281,7 +261,7 @@ namespace Ryujinx.Graphics.Vulkan // TODO: Support divisor > 1 pipeline.Internal.VertexBindingDescriptions[descriptorIndex++] = new VertexInputBindingDescription( (uint)i + 1, - extendedDynamicState && (!gd.IsMoltenVk || gd.SupportsMTL31) ? null : (uint)alignedStride, + (uint)alignedStride, inputRate); } } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs index 143756d93..1cc33f728 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs @@ -1,8 +1,5 @@ using Ryujinx.Common.Memory; using Silk.NET.Vulkan; -using Silk.NET.Vulkan.Extensions.EXT; -using System; -using System.Numerics; namespace Ryujinx.Graphics.Vulkan { @@ -11,7 +8,6 @@ namespace Ryujinx.Graphics.Vulkan private float _depthBiasSlopeFactor; private float _depthBiasConstantFactor; private float _depthBiasClamp; - private bool _depthBiasEnable; public int ScissorsCount; private Array16 _scissors; @@ -23,42 +19,11 @@ namespace Ryujinx.Graphics.Vulkan private uint _frontWriteMask; private uint _frontReference; - private StencilOp _backFailOp; - private StencilOp _backPassOp; - private StencilOp _backDepthFailOp; - private CompareOp _backCompareOp; - private StencilOp _frontFailOp; - private StencilOp _frontPassOp; - private StencilOp _frontDepthFailOp; - private CompareOp _frontCompareOp; - - private float _lineWidth; - - public bool StencilTestEnable; - - public bool DepthTestEnable; - public bool DepthWriteEnable; - private CompareOp _depthCompareOp; - private Array4 _blendConstants; public uint ViewportsCount; public Array16 Viewports; - public CullModeFlags CullMode; - private FrontFace _frontFace; - - private bool _discard; - - private LogicOp _logicOp; - - private uint _patchControlPoints; - - public PrimitiveTopology Topology; - - private bool _primitiveRestartEnable; - - [Flags] private enum DirtyFlags { None = 0, @@ -67,21 +32,7 @@ namespace Ryujinx.Graphics.Vulkan Scissor = 1 << 2, Stencil = 1 << 3, Viewport = 1 << 4, - CullMode = 1 << 5, - FrontFace = 1 << 6, - DepthTestBool = 1 << 7, - DepthTestCompareOp = 1 << 8, - StencilTestEnableAndStencilOp = 1 << 9, - LineWidth = 1 << 10, - RasterDiscard = 1 << 11, - LogicOp = 1 << 12, - PatchControlPoints = 1 << 13, - PrimitiveRestart = 1 << 14, - PrimitiveTopology = 1 << 15, - DepthBiasEnable = 1 << 16, - Standard = Blend | DepthBias | Scissor | Stencil | Viewport, - Extended = CullMode | FrontFace | DepthTestBool | DepthTestCompareOp | StencilTestEnableAndStencilOp | PrimitiveTopology, - Extended2 = RasterDiscard | PrimitiveRestart | DepthBiasEnable, + All = Blend | DepthBias | Scissor | Stencil | Viewport, } private DirtyFlags _dirty; @@ -92,6 +43,7 @@ namespace Ryujinx.Graphics.Vulkan _blendConstants[1] = g; _blendConstants[2] = b; _blendConstants[3] = a; + _dirty |= DirtyFlags.Blend; } @@ -104,64 +56,15 @@ namespace Ryujinx.Graphics.Vulkan _dirty |= DirtyFlags.DepthBias; } - public void SetDepthBiasEnable(bool enable) - { - _depthBiasEnable = enable; - _dirty |= DirtyFlags.DepthBiasEnable; - } - public void SetScissor(int index, Rect2D scissor) { _scissors[index] = scissor; + _dirty |= DirtyFlags.Scissor; } - public void SetDepthTestBool(bool testEnable, bool writeEnable) - { - DepthTestEnable = testEnable; - DepthWriteEnable = writeEnable; - _dirty |= DirtyFlags.DepthTestBool; - } - - public void SetDepthTestCompareOp(CompareOp depthTestOp) - { - _depthCompareOp = depthTestOp; - _dirty |= DirtyFlags.DepthTestCompareOp; - } - - public void SetStencilTestandOp( - StencilOp backFailOp, - StencilOp backPassOp, - StencilOp backDepthFailOp, - CompareOp backCompareOp, - StencilOp frontFailOp, - StencilOp frontPassOp, - StencilOp frontDepthFailOp, - CompareOp frontCompareOp, - bool stencilTestEnable) - { - _backFailOp = backFailOp; - _backPassOp = backPassOp; - _backDepthFailOp = backDepthFailOp; - _backCompareOp = backCompareOp; - _frontFailOp = frontFailOp; - _frontPassOp = frontPassOp; - _frontDepthFailOp = frontDepthFailOp; - _frontCompareOp = frontCompareOp; - - StencilTestEnable = stencilTestEnable; - - _dirty |= DirtyFlags.StencilTestEnableAndStencilOp; - } - - public void SetStencilTest(bool stencilTestEnable) - { - StencilTestEnable = stencilTestEnable; - - _dirty |= DirtyFlags.StencilTestEnableAndStencilOp; - } - - public void SetStencilMask(uint backCompareMask, + public void SetStencilMasks( + uint backCompareMask, uint backWriteMask, uint backReference, uint frontCompareMask, @@ -174,180 +77,58 @@ namespace Ryujinx.Graphics.Vulkan _frontCompareMask = frontCompareMask; _frontWriteMask = frontWriteMask; _frontReference = frontReference; + _dirty |= DirtyFlags.Stencil; } public void SetViewport(int index, Viewport viewport) { Viewports[index] = viewport; + _dirty |= DirtyFlags.Viewport; } public void SetViewports(ref Array16 viewports, uint viewportsCount) { - if (!Viewports.Equals(viewports) || ViewportsCount != viewportsCount) + Viewports = viewports; + ViewportsCount = viewportsCount; + + if (ViewportsCount != 0) { - Viewports = viewports; - ViewportsCount = viewportsCount; - if (ViewportsCount != 0) - { - _dirty |= DirtyFlags.Viewport; - } + _dirty |= DirtyFlags.Viewport; } } - public void SetCullMode(CullModeFlags cullMode) + public void ForceAllDirty() { - CullMode = cullMode; - _dirty |= DirtyFlags.CullMode; + _dirty = DirtyFlags.All; } - public void SetFrontFace(FrontFace frontFace) + public void ReplayIfDirty(Vk api, CommandBuffer commandBuffer) { - _frontFace = frontFace; - _dirty |= DirtyFlags.FrontFace; - } - - public void SetLineWidth(float width) - { - _lineWidth = width; - _dirty |= DirtyFlags.LineWidth; - } - - public void SetRasterizerDiscard(bool discard) - { - _discard = discard; - _dirty |= DirtyFlags.RasterDiscard; - } - - public void SetPrimitiveRestartEnable(bool primitiveRestart) - { - _primitiveRestartEnable = primitiveRestart; - _dirty |= DirtyFlags.PrimitiveRestart; - } - - public void SetPrimitiveTopology(PrimitiveTopology primitiveTopology) - { - Topology = primitiveTopology; - _dirty |= DirtyFlags.PrimitiveTopology; - } - - public void SetLogicOp(LogicOp op) - { - _logicOp = op; - _dirty |= DirtyFlags.LogicOp; - } - - public void SetPatchControlPoints(uint points) - { - _patchControlPoints = points; - _dirty |= DirtyFlags.PatchControlPoints; - } - - public void ForceAllDirty(VulkanRenderer gd) - { - _dirty = DirtyFlags.Standard; - - if (gd.Capabilities.SupportsExtendedDynamicState) + if (_dirty.HasFlag(DirtyFlags.Blend)) { - _dirty |= DirtyFlags.Extended; + RecordBlend(api, commandBuffer); } - if (gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2) + if (_dirty.HasFlag(DirtyFlags.DepthBias)) { - _dirty |= DirtyFlags.Extended2; - - if (gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2LogicOp) - { - _dirty |= DirtyFlags.LogicOp; - } - - if (gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints) - { - _dirty |= DirtyFlags.PatchControlPoints; - } + RecordDepthBias(api, commandBuffer); } - if (!gd.IsMoltenVk) + if (_dirty.HasFlag(DirtyFlags.Scissor)) { - _dirty |= DirtyFlags.LineWidth; - } - } - - public void ReplayIfDirty(VulkanRenderer gd, CommandBuffer commandBuffer) - { - if (_dirty == DirtyFlags.None) - { - return; + RecordScissor(api, commandBuffer); } - var api = gd.Api; - var extendedStateApi = gd.ExtendedDynamicStateApi; - var extendedState2Api = gd.ExtendedDynamicState2Api; - - DirtyFlags dirtyFlags = _dirty; - - while (dirtyFlags != DirtyFlags.None) + if (_dirty.HasFlag(DirtyFlags.Stencil)) { - int bitIndex = BitOperations.TrailingZeroCount((uint)dirtyFlags); - DirtyFlags currentFlag = (DirtyFlags)(1 << bitIndex); + RecordStencilMasks(api, commandBuffer); + } - switch (currentFlag) - { - case DirtyFlags.Blend: - RecordBlend(api, commandBuffer); - break; - case DirtyFlags.DepthBias: - RecordDepthBias(api, commandBuffer); - break; - case DirtyFlags.Scissor: - RecordScissor(gd, commandBuffer); - break; - case DirtyFlags.Stencil: - RecordStencil(api, commandBuffer); - break; - case DirtyFlags.Viewport: - RecordViewport(gd, commandBuffer); - break; - case DirtyFlags.CullMode: - RecordCullMode(extendedStateApi, commandBuffer); - break; - case DirtyFlags.FrontFace: - RecordFrontFace(extendedStateApi, commandBuffer); - break; - case DirtyFlags.DepthTestBool: - RecordDepthTestBool(extendedStateApi, commandBuffer); - break; - case DirtyFlags.DepthTestCompareOp: - RecordDepthTestCompareOp(extendedStateApi, commandBuffer); - break; - case DirtyFlags.StencilTestEnableAndStencilOp: - RecordStencilTestAndOp(extendedStateApi, commandBuffer); - break; - case DirtyFlags.LineWidth: - RecordLineWidth(api, commandBuffer); - break; - case DirtyFlags.RasterDiscard: - RecordRasterizationDiscard(extendedState2Api, commandBuffer); - break; - case DirtyFlags.LogicOp: - RecordLogicOp(extendedState2Api, commandBuffer); - break; - case DirtyFlags.PatchControlPoints: - RecordPatchControlPoints(extendedState2Api, commandBuffer); - break; - case DirtyFlags.PrimitiveRestart: - RecordPrimitiveRestartEnable(gd, commandBuffer); - break; - case DirtyFlags.PrimitiveTopology: - RecordPrimitiveTopology(extendedStateApi, commandBuffer); - break; - case DirtyFlags.DepthBiasEnable: - RecordDepthBiasEnable(extendedState2Api, commandBuffer); - break; - } - - dirtyFlags &= ~currentFlag; + if (_dirty.HasFlag(DirtyFlags.Viewport)) + { + RecordViewport(api, commandBuffer); } _dirty = DirtyFlags.None; @@ -363,27 +144,15 @@ namespace Ryujinx.Graphics.Vulkan api.CmdSetDepthBias(commandBuffer, _depthBiasConstantFactor, _depthBiasClamp, _depthBiasSlopeFactor); } - private readonly void RecordDepthBiasEnable(ExtExtendedDynamicState2 gd, CommandBuffer commandBuffer) - { - gd.CmdSetDepthBiasEnable(commandBuffer, _depthBiasEnable); - } - - private void RecordScissor(VulkanRenderer gd, CommandBuffer commandBuffer) + private void RecordScissor(Vk api, CommandBuffer commandBuffer) { if (ScissorsCount != 0) { - if (gd.Capabilities.SupportsExtendedDynamicState) - { - gd.ExtendedDynamicStateApi.CmdSetScissorWithCount(commandBuffer, (uint)ScissorsCount, _scissors.AsSpan()); - } - else - { - gd.Api.CmdSetScissor(commandBuffer, 0, (uint)ScissorsCount, _scissors.AsSpan()); - } + api.CmdSetScissor(commandBuffer, 0, (uint)ScissorsCount, _scissors.AsSpan()); } } - private readonly void RecordStencil(Vk api, CommandBuffer commandBuffer) + private readonly void RecordStencilMasks(Vk api, CommandBuffer commandBuffer) { api.CmdSetStencilCompareMask(commandBuffer, StencilFaceFlags.FaceBackBit, _backCompareMask); api.CmdSetStencilWriteMask(commandBuffer, StencilFaceFlags.FaceBackBit, _backWriteMask); @@ -393,107 +162,12 @@ namespace Ryujinx.Graphics.Vulkan api.CmdSetStencilReference(commandBuffer, StencilFaceFlags.FaceFrontBit, _frontReference); } - private readonly void RecordStencilTestAndOp(ExtExtendedDynamicState api, CommandBuffer commandBuffer) + private void RecordViewport(Vk api, CommandBuffer commandBuffer) { - api.CmdSetStencilTestEnable(commandBuffer, StencilTestEnable); - - api.CmdSetStencilOp(commandBuffer, StencilFaceFlags.FaceBackBit, _backFailOp, _backPassOp, _backDepthFailOp, _backCompareOp); - api.CmdSetStencilOp(commandBuffer, StencilFaceFlags.FaceFrontBit, _frontFailOp, _frontPassOp, _frontDepthFailOp, _frontCompareOp); - } - - private void RecordViewport(VulkanRenderer gd, CommandBuffer commandBuffer) - { - if (ViewportsCount == 0) + if (ViewportsCount != 0) { - return; + api.CmdSetViewport(commandBuffer, 0, ViewportsCount, Viewports.AsSpan()); } - - if (gd.Capabilities.SupportsExtendedDynamicState) - { - gd.ExtendedDynamicStateApi.CmdSetViewportWithCount(commandBuffer, ViewportsCount, Viewports.AsSpan()); - } - else - { - gd.Api.CmdSetViewport(commandBuffer, 0, ViewportsCount, Viewports.AsSpan()); - } - } - - private readonly void RecordCullMode(ExtExtendedDynamicState api, CommandBuffer commandBuffer) - { - api.CmdSetCullMode(commandBuffer, CullMode); - } - - private readonly void RecordFrontFace(ExtExtendedDynamicState api, CommandBuffer commandBuffer) - { - api.CmdSetFrontFace(commandBuffer, _frontFace); - } - - private readonly void RecordDepthTestBool(ExtExtendedDynamicState api, CommandBuffer commandBuffer) - { - api.CmdSetDepthTestEnable(commandBuffer, DepthTestEnable); - - api.CmdSetDepthWriteEnable(commandBuffer, DepthWriteEnable); - } - - private readonly void RecordDepthTestCompareOp(ExtExtendedDynamicState api, CommandBuffer commandBuffer) - { - api.CmdSetDepthCompareOp(commandBuffer, _depthCompareOp); - } - - private readonly void RecordRasterizationDiscard(ExtExtendedDynamicState2 extendedDynamicState2Api, CommandBuffer commandBuffer) - { - extendedDynamicState2Api.CmdSetRasterizerDiscardEnable(commandBuffer, _discard); - } - - private readonly void RecordPrimitiveRestartEnable(VulkanRenderer gd, CommandBuffer commandBuffer) - { - bool primitiveRestartEnable = _primitiveRestartEnable; - - bool topologySupportsRestart; - - if (gd.Capabilities.SupportsPrimitiveTopologyListRestart) - { - topologySupportsRestart = gd.Capabilities.SupportsPrimitiveTopologyPatchListRestart || - Topology != PrimitiveTopology.PatchList; - } - else - { - topologySupportsRestart = Topology == PrimitiveTopology.LineStrip || - Topology == PrimitiveTopology.TriangleStrip || - Topology == PrimitiveTopology.TriangleFan || - Topology == PrimitiveTopology.LineStripWithAdjacency || - Topology == PrimitiveTopology.TriangleStripWithAdjacency; - } - - primitiveRestartEnable &= topologySupportsRestart; - - // Cannot disable primitiveRestartEnable for these Topologies on MacOS. - if (gd.IsMoltenVk) - { - primitiveRestartEnable = true; - } - - gd.ExtendedDynamicState2Api.CmdSetPrimitiveRestartEnable(commandBuffer, primitiveRestartEnable); - } - - private readonly void RecordPrimitiveTopology(ExtExtendedDynamicState extendedDynamicStateApi, CommandBuffer commandBuffer) - { - extendedDynamicStateApi.CmdSetPrimitiveTopology(commandBuffer, Topology); - } - - private readonly void RecordLogicOp(ExtExtendedDynamicState2 extendedDynamicState2Api, CommandBuffer commandBuffer) - { - extendedDynamicState2Api.CmdSetLogicOp(commandBuffer, _logicOp); - } - - private readonly void RecordPatchControlPoints(ExtExtendedDynamicState2 extendedDynamicState2Api, CommandBuffer commandBuffer) - { - extendedDynamicState2Api.CmdSetPatchControlPoints(commandBuffer, _patchControlPoints); - } - - private readonly void RecordLineWidth(Vk api, CommandBuffer commandBuffer) - { - api.CmdSetLineWidth(commandBuffer, _lineWidth); } } } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineFull.cs b/src/Ryujinx.Graphics.Vulkan/PipelineFull.cs index 651c6f0c7..b56e0a05f 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineFull.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineFull.cs @@ -235,7 +235,7 @@ namespace Ryujinx.Graphics.Vulkan if (Pipeline != null && Pbp == PipelineBindPoint.Graphics) { - DynamicState.ReplayIfDirty(Gd, CommandBuffer); + DynamicState.ReplayIfDirty(Gd.Api, CommandBuffer); } } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineHelperShader.cs b/src/Ryujinx.Graphics.Vulkan/PipelineHelperShader.cs index 84d8ee536..b9074dfdb 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineHelperShader.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineHelperShader.cs @@ -8,15 +8,11 @@ namespace Ryujinx.Graphics.Vulkan { } - public void SetRenderTarget(TextureView view, uint width, uint height, bool signalChange = true) + public void SetRenderTarget(TextureView view, uint width, uint height) { CreateFramebuffer(view, width, height); CreateRenderPass(); - - if (signalChange) - { - SignalStateChange(); - } + SignalStateChange(); } private void CreateFramebuffer(TextureView view, uint width, uint height) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index 5a2b17220..6b6b46a91 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -7,236 +7,296 @@ namespace Ryujinx.Graphics.Vulkan { struct PipelineState : IDisposable { - private const int MaxDynamicStatesCount = 23; + private const int RequiredSubgroupSize = 32; public PipelineUid Internal; - public PolygonMode PolygonMode + public float LineWidth { - readonly get => (PolygonMode)((Internal.Id0 >> 0) & 0x3FFFFFFF); - set => Internal.Id0 = (Internal.Id0 & 0xFFFFFFFFC0000000) | ((ulong)value << 0); + readonly get => BitConverter.Int32BitsToSingle((int)((Internal.Id0 >> 0) & 0xFFFFFFFF)); + set => Internal.Id0 = (Internal.Id0 & 0xFFFFFFFF00000000) | ((ulong)(uint)BitConverter.SingleToInt32Bits(value) << 0); } - public uint StagesCount + public float DepthBiasClamp { - readonly get => (byte)((Internal.Id0 >> 30) & 0xFF); - set => Internal.Id0 = (Internal.Id0 & 0xFFFFFFC03FFFFFFF) | ((ulong)value << 30); + readonly get => BitConverter.Int32BitsToSingle((int)((Internal.Id0 >> 32) & 0xFFFFFFFF)); + set => Internal.Id0 = (Internal.Id0 & 0xFFFFFFFF) | ((ulong)(uint)BitConverter.SingleToInt32Bits(value) << 32); } - public uint VertexAttributeDescriptionsCount + public float DepthBiasConstantFactor { - readonly get => (byte)((Internal.Id0 >> 38) & 0xFF); - set => Internal.Id0 = (Internal.Id0 & 0xFFFFC03FFFFFFFFF) | ((ulong)value << 38); + readonly get => BitConverter.Int32BitsToSingle((int)((Internal.Id1 >> 0) & 0xFFFFFFFF)); + set => Internal.Id1 = (Internal.Id1 & 0xFFFFFFFF00000000) | ((ulong)(uint)BitConverter.SingleToInt32Bits(value) << 0); } - public uint VertexBindingDescriptionsCount + public float DepthBiasSlopeFactor { - readonly get => (byte)((Internal.Id0 >> 46) & 0xFF); - set => Internal.Id0 = (Internal.Id0 & 0xFFC03FFFFFFFFFFF) | ((ulong)value << 46); + readonly get => BitConverter.Int32BitsToSingle((int)((Internal.Id1 >> 32) & 0xFFFFFFFF)); + set => Internal.Id1 = (Internal.Id1 & 0xFFFFFFFF) | ((ulong)(uint)BitConverter.SingleToInt32Bits(value) << 32); } - public uint ViewportsCount - { - readonly get => (byte)((Internal.Id0 >> 54) & 0xFF); - set => Internal.Id0 = (Internal.Id0 & 0xC03FFFFFFFFFFFFF) | ((ulong)value << 54); - } - - public uint ScissorsCount - { - readonly get => (byte)((Internal.Id1 >> 0) & 0xFF); - set => Internal.Id1 = (Internal.Id1 & 0xFFFFFFFFFFFFFF00) | ((ulong)value << 0); - } - - public uint ColorBlendAttachmentStateCount - { - readonly get => (byte)((Internal.Id1 >> 8) & 0xFF); - set => Internal.Id1 = (Internal.Id1 & 0xFFFFFFFFFFFF00FF) | ((ulong)value << 8); - } - - public PrimitiveTopology Topology - { - readonly get => (PrimitiveTopology)((Internal.Id1 >> 16) & 0xF); - set => Internal.Id1 = (Internal.Id1 & 0xFFFFFFFFFFF0FFFF) | ((ulong)value << 16); - } - - public LogicOp LogicOp - { - readonly get => (LogicOp)((Internal.Id1 >> 20) & 0xF); - set => Internal.Id1 = (Internal.Id1 & 0xFFFFFFFFFF0FFFFF) | ((ulong)value << 20); - } - - public CompareOp DepthCompareOp - { - readonly get => (CompareOp)((Internal.Id1 >> 24) & 0x7); - set => Internal.Id1 = (Internal.Id1 & 0xFFFFFFFFF8FFFFFF) | ((ulong)value << 24); - } - - public StencilOp StencilFrontFailOp - { - readonly get => (StencilOp)((Internal.Id1 >> 27) & 0x7); - set => Internal.Id1 = (Internal.Id1 & 0xFFFFFFFFC7FFFFFF) | ((ulong)value << 27); - } - - public StencilOp StencilFrontPassOp - { - readonly get => (StencilOp)((Internal.Id1 >> 30) & 0x7); - set => Internal.Id1 = (Internal.Id1 & 0xFFFFFFFE3FFFFFFF) | ((ulong)value << 30); - } - - public StencilOp StencilFrontDepthFailOp - { - readonly get => (StencilOp)((Internal.Id1 >> 33) & 0x7); - set => Internal.Id1 = (Internal.Id1 & 0xFFFFFFF1FFFFFFFF) | ((ulong)value << 33); - } - - public CompareOp StencilFrontCompareOp - { - readonly get => (CompareOp)((Internal.Id1 >> 36) & 0x7); - set => Internal.Id1 = (Internal.Id1 & 0xFFFFFF8FFFFFFFFF) | ((ulong)value << 36); - } - - public StencilOp StencilBackFailOp - { - readonly get => (StencilOp)((Internal.Id1 >> 39) & 0x7); - set => Internal.Id1 = (Internal.Id1 & 0xFFFFFC7FFFFFFFFF) | ((ulong)value << 39); - } - - public StencilOp StencilBackPassOp - { - readonly get => (StencilOp)((Internal.Id1 >> 42) & 0x7); - set => Internal.Id1 = (Internal.Id1 & 0xFFFFE3FFFFFFFFFF) | ((ulong)value << 42); - } - - public StencilOp StencilBackDepthFailOp - { - readonly get => (StencilOp)((Internal.Id1 >> 45) & 0x7); - set => Internal.Id1 = (Internal.Id1 & 0xFFFF1FFFFFFFFFFF) | ((ulong)value << 45); - } - - public CompareOp StencilBackCompareOp - { - readonly get => (CompareOp)((Internal.Id1 >> 48) & 0x7); - set => Internal.Id1 = (Internal.Id1 & 0xFFF8FFFFFFFFFFFF) | ((ulong)value << 48); - } - - public CullModeFlags CullMode - { - readonly get => (CullModeFlags)((Internal.Id1 >> 51) & 0x3); - set => Internal.Id1 = (Internal.Id1 & 0xFFE7FFFFFFFFFFFF) | ((ulong)value << 51); - } - - public bool PrimitiveRestartEnable - { - readonly get => ((Internal.Id1 >> 53) & 0x1) != 0UL; - set => Internal.Id1 = (Internal.Id1 & 0xFFDFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 53); - } - - public bool DepthClampEnable - { - readonly get => ((Internal.Id1 >> 54) & 0x1) != 0UL; - set => Internal.Id1 = (Internal.Id1 & 0xFFBFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 54); - } - - public bool RasterizerDiscardEnable - { - readonly get => ((Internal.Id1 >> 55) & 0x1) != 0UL; - set => Internal.Id1 = (Internal.Id1 & 0xFF7FFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 55); - } - - public FrontFace FrontFace - { - readonly get => (FrontFace)((Internal.Id1 >> 56) & 0x1); - set => Internal.Id1 = (Internal.Id1 & 0xFEFFFFFFFFFFFFFF) | ((ulong)value << 56); - } - - public bool DepthBiasEnable - { - readonly get => ((Internal.Id1 >> 57) & 0x1) != 0UL; - set => Internal.Id1 = (Internal.Id1 & 0xFDFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 57); - } - - public bool DepthTestEnable - { - readonly get => ((Internal.Id1 >> 58) & 0x1) != 0UL; - set => Internal.Id1 = (Internal.Id1 & 0xFBFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 58); - } - - public bool DepthWriteEnable - { - readonly get => ((Internal.Id1 >> 59) & 0x1) != 0UL; - set => Internal.Id1 = (Internal.Id1 & 0xF7FFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 59); - } - - public bool DepthBoundsTestEnable - { - readonly get => ((Internal.Id1 >> 60) & 0x1) != 0UL; - set => Internal.Id1 = (Internal.Id1 & 0xEFFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 60); - } - - public bool StencilTestEnable - { - readonly get => ((Internal.Id1 >> 61) & 0x1) != 0UL; - set => Internal.Id1 = (Internal.Id1 & 0xDFFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 61); - } - - public bool LogicOpEnable - { - readonly get => ((Internal.Id1 >> 62) & 0x1) != 0UL; - set => Internal.Id1 = (Internal.Id1 & 0xBFFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 62); - } - - public bool HasDepthStencil - { - readonly get => ((Internal.Id1 >> 63) & 0x1) != 0UL; - set => Internal.Id1 = (Internal.Id1 & 0x7FFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 63); - } - - public uint PatchControlPoints + public uint StencilFrontCompareMask { readonly get => (uint)((Internal.Id2 >> 0) & 0xFFFFFFFF); set => Internal.Id2 = (Internal.Id2 & 0xFFFFFFFF00000000) | ((ulong)value << 0); } - public uint SamplesCount + public uint StencilFrontWriteMask { readonly get => (uint)((Internal.Id2 >> 32) & 0xFFFFFFFF); set => Internal.Id2 = (Internal.Id2 & 0xFFFFFFFF) | ((ulong)value << 32); } + public uint StencilFrontReference + { + readonly get => (uint)((Internal.Id3 >> 0) & 0xFFFFFFFF); + set => Internal.Id3 = (Internal.Id3 & 0xFFFFFFFF00000000) | ((ulong)value << 0); + } + + public uint StencilBackCompareMask + { + readonly get => (uint)((Internal.Id3 >> 32) & 0xFFFFFFFF); + set => Internal.Id3 = (Internal.Id3 & 0xFFFFFFFF) | ((ulong)value << 32); + } + + public uint StencilBackWriteMask + { + readonly get => (uint)((Internal.Id4 >> 0) & 0xFFFFFFFF); + set => Internal.Id4 = (Internal.Id4 & 0xFFFFFFFF00000000) | ((ulong)value << 0); + } + + public uint StencilBackReference + { + readonly get => (uint)((Internal.Id4 >> 32) & 0xFFFFFFFF); + set => Internal.Id4 = (Internal.Id4 & 0xFFFFFFFF) | ((ulong)value << 32); + } + + public PolygonMode PolygonMode + { + readonly get => (PolygonMode)((Internal.Id5 >> 0) & 0x3FFFFFFF); + set => Internal.Id5 = (Internal.Id5 & 0xFFFFFFFFC0000000) | ((ulong)value << 0); + } + + public uint StagesCount + { + readonly get => (byte)((Internal.Id5 >> 30) & 0xFF); + set => Internal.Id5 = (Internal.Id5 & 0xFFFFFFC03FFFFFFF) | ((ulong)value << 30); + } + + public uint VertexAttributeDescriptionsCount + { + readonly get => (byte)((Internal.Id5 >> 38) & 0xFF); + set => Internal.Id5 = (Internal.Id5 & 0xFFFFC03FFFFFFFFF) | ((ulong)value << 38); + } + + public uint VertexBindingDescriptionsCount + { + readonly get => (byte)((Internal.Id5 >> 46) & 0xFF); + set => Internal.Id5 = (Internal.Id5 & 0xFFC03FFFFFFFFFFF) | ((ulong)value << 46); + } + + public uint ViewportsCount + { + readonly get => (byte)((Internal.Id5 >> 54) & 0xFF); + set => Internal.Id5 = (Internal.Id5 & 0xC03FFFFFFFFFFFFF) | ((ulong)value << 54); + } + + public uint ScissorsCount + { + readonly get => (byte)((Internal.Id6 >> 0) & 0xFF); + set => Internal.Id6 = (Internal.Id6 & 0xFFFFFFFFFFFFFF00) | ((ulong)value << 0); + } + + public uint ColorBlendAttachmentStateCount + { + readonly get => (byte)((Internal.Id6 >> 8) & 0xFF); + set => Internal.Id6 = (Internal.Id6 & 0xFFFFFFFFFFFF00FF) | ((ulong)value << 8); + } + + public PrimitiveTopology Topology + { + readonly get => (PrimitiveTopology)((Internal.Id6 >> 16) & 0xF); + set => Internal.Id6 = (Internal.Id6 & 0xFFFFFFFFFFF0FFFF) | ((ulong)value << 16); + } + + public LogicOp LogicOp + { + readonly get => (LogicOp)((Internal.Id6 >> 20) & 0xF); + set => Internal.Id6 = (Internal.Id6 & 0xFFFFFFFFFF0FFFFF) | ((ulong)value << 20); + } + + public CompareOp DepthCompareOp + { + readonly get => (CompareOp)((Internal.Id6 >> 24) & 0x7); + set => Internal.Id6 = (Internal.Id6 & 0xFFFFFFFFF8FFFFFF) | ((ulong)value << 24); + } + + public StencilOp StencilFrontFailOp + { + readonly get => (StencilOp)((Internal.Id6 >> 27) & 0x7); + set => Internal.Id6 = (Internal.Id6 & 0xFFFFFFFFC7FFFFFF) | ((ulong)value << 27); + } + + public StencilOp StencilFrontPassOp + { + readonly get => (StencilOp)((Internal.Id6 >> 30) & 0x7); + set => Internal.Id6 = (Internal.Id6 & 0xFFFFFFFE3FFFFFFF) | ((ulong)value << 30); + } + + public StencilOp StencilFrontDepthFailOp + { + readonly get => (StencilOp)((Internal.Id6 >> 33) & 0x7); + set => Internal.Id6 = (Internal.Id6 & 0xFFFFFFF1FFFFFFFF) | ((ulong)value << 33); + } + + public CompareOp StencilFrontCompareOp + { + readonly get => (CompareOp)((Internal.Id6 >> 36) & 0x7); + set => Internal.Id6 = (Internal.Id6 & 0xFFFFFF8FFFFFFFFF) | ((ulong)value << 36); + } + + public StencilOp StencilBackFailOp + { + readonly get => (StencilOp)((Internal.Id6 >> 39) & 0x7); + set => Internal.Id6 = (Internal.Id6 & 0xFFFFFC7FFFFFFFFF) | ((ulong)value << 39); + } + + public StencilOp StencilBackPassOp + { + readonly get => (StencilOp)((Internal.Id6 >> 42) & 0x7); + set => Internal.Id6 = (Internal.Id6 & 0xFFFFE3FFFFFFFFFF) | ((ulong)value << 42); + } + + public StencilOp StencilBackDepthFailOp + { + readonly get => (StencilOp)((Internal.Id6 >> 45) & 0x7); + set => Internal.Id6 = (Internal.Id6 & 0xFFFF1FFFFFFFFFFF) | ((ulong)value << 45); + } + + public CompareOp StencilBackCompareOp + { + readonly get => (CompareOp)((Internal.Id6 >> 48) & 0x7); + set => Internal.Id6 = (Internal.Id6 & 0xFFF8FFFFFFFFFFFF) | ((ulong)value << 48); + } + + public CullModeFlags CullMode + { + readonly get => (CullModeFlags)((Internal.Id6 >> 51) & 0x3); + set => Internal.Id6 = (Internal.Id6 & 0xFFE7FFFFFFFFFFFF) | ((ulong)value << 51); + } + + public bool PrimitiveRestartEnable + { + readonly get => ((Internal.Id6 >> 53) & 0x1) != 0UL; + set => Internal.Id6 = (Internal.Id6 & 0xFFDFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 53); + } + + public bool DepthClampEnable + { + readonly get => ((Internal.Id6 >> 54) & 0x1) != 0UL; + set => Internal.Id6 = (Internal.Id6 & 0xFFBFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 54); + } + + public bool RasterizerDiscardEnable + { + readonly get => ((Internal.Id6 >> 55) & 0x1) != 0UL; + set => Internal.Id6 = (Internal.Id6 & 0xFF7FFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 55); + } + + public FrontFace FrontFace + { + readonly get => (FrontFace)((Internal.Id6 >> 56) & 0x1); + set => Internal.Id6 = (Internal.Id6 & 0xFEFFFFFFFFFFFFFF) | ((ulong)value << 56); + } + + public bool DepthBiasEnable + { + readonly get => ((Internal.Id6 >> 57) & 0x1) != 0UL; + set => Internal.Id6 = (Internal.Id6 & 0xFDFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 57); + } + + public bool DepthTestEnable + { + readonly get => ((Internal.Id6 >> 58) & 0x1) != 0UL; + set => Internal.Id6 = (Internal.Id6 & 0xFBFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 58); + } + + public bool DepthWriteEnable + { + readonly get => ((Internal.Id6 >> 59) & 0x1) != 0UL; + set => Internal.Id6 = (Internal.Id6 & 0xF7FFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 59); + } + + public bool DepthBoundsTestEnable + { + readonly get => ((Internal.Id6 >> 60) & 0x1) != 0UL; + set => Internal.Id6 = (Internal.Id6 & 0xEFFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 60); + } + + public bool StencilTestEnable + { + readonly get => ((Internal.Id6 >> 61) & 0x1) != 0UL; + set => Internal.Id6 = (Internal.Id6 & 0xDFFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 61); + } + + public bool LogicOpEnable + { + readonly get => ((Internal.Id6 >> 62) & 0x1) != 0UL; + set => Internal.Id6 = (Internal.Id6 & 0xBFFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 62); + } + + public bool HasDepthStencil + { + readonly get => ((Internal.Id6 >> 63) & 0x1) != 0UL; + set => Internal.Id6 = (Internal.Id6 & 0x7FFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 63); + } + + public uint PatchControlPoints + { + readonly get => (uint)((Internal.Id7 >> 0) & 0xFFFFFFFF); + set => Internal.Id7 = (Internal.Id7 & 0xFFFFFFFF00000000) | ((ulong)value << 0); + } + + public uint SamplesCount + { + readonly get => (uint)((Internal.Id7 >> 32) & 0xFFFFFFFF); + set => Internal.Id7 = (Internal.Id7 & 0xFFFFFFFF) | ((ulong)value << 32); + } + public bool AlphaToCoverageEnable { - readonly get => ((Internal.Id3 >> 0) & 0x1) != 0UL; - set => Internal.Id3 = (Internal.Id3 & 0xFFFFFFFFFFFFFFFE) | ((value ? 1UL : 0UL) << 0); + readonly get => ((Internal.Id8 >> 0) & 0x1) != 0UL; + set => Internal.Id8 = (Internal.Id8 & 0xFFFFFFFFFFFFFFFE) | ((value ? 1UL : 0UL) << 0); } public bool AlphaToOneEnable { - readonly get => ((Internal.Id3 >> 1) & 0x1) != 0UL; - set => Internal.Id3 = (Internal.Id3 & 0xFFFFFFFFFFFFFFFD) | ((value ? 1UL : 0UL) << 1); + readonly get => ((Internal.Id8 >> 1) & 0x1) != 0UL; + set => Internal.Id8 = (Internal.Id8 & 0xFFFFFFFFFFFFFFFD) | ((value ? 1UL : 0UL) << 1); } public bool AdvancedBlendSrcPreMultiplied { - readonly get => ((Internal.Id3 >> 2) & 0x1) != 0UL; - set => Internal.Id3 = (Internal.Id3 & 0xFFFFFFFFFFFFFFFB) | ((value ? 1UL : 0UL) << 2); + readonly get => ((Internal.Id8 >> 2) & 0x1) != 0UL; + set => Internal.Id8 = (Internal.Id8 & 0xFFFFFFFFFFFFFFFB) | ((value ? 1UL : 0UL) << 2); } public bool AdvancedBlendDstPreMultiplied { - readonly get => ((Internal.Id3 >> 3) & 0x1) != 0UL; - set => Internal.Id3 = (Internal.Id3 & 0xFFFFFFFFFFFFFFF7) | ((value ? 1UL : 0UL) << 3); + readonly get => ((Internal.Id8 >> 3) & 0x1) != 0UL; + set => Internal.Id8 = (Internal.Id8 & 0xFFFFFFFFFFFFFFF7) | ((value ? 1UL : 0UL) << 3); } public BlendOverlapEXT AdvancedBlendOverlap { - readonly get => (BlendOverlapEXT)((Internal.Id3 >> 4) & 0x3); - set => Internal.Id3 = (Internal.Id3 & 0xFFFFFFFFFFFFFFCF) | ((ulong)value << 4); + readonly get => (BlendOverlapEXT)((Internal.Id8 >> 4) & 0x3); + set => Internal.Id8 = (Internal.Id8 & 0xFFFFFFFFFFFFFFCF) | ((ulong)value << 4); } public bool DepthMode { - readonly get => ((Internal.Id3 >> 6) & 0x1) != 0UL; - set => Internal.Id3 = (Internal.Id3 & 0xFFFFFFFFFFFFFFBF) | ((value ? 1UL : 0UL) << 6); + readonly get => ((Internal.Id8 >> 6) & 0x1) != 0UL; + set => Internal.Id8 = (Internal.Id8 & 0xFFFFFFFFFFFFFFBF) | ((value ? 1UL : 0UL) << 6); } public bool HasTessellationControlShader; @@ -246,11 +306,7 @@ namespace Ryujinx.Graphics.Vulkan private Array32 _vertexAttributeDescriptions2; - private bool _supportsExtDynamicState; - private PhysicalDeviceExtendedDynamicState2FeaturesEXT _supportsExtDynamicState2; - private uint _blendEnables; - - public void Initialize(HardwareCapabilities capabilities) + public void Initialize() { HasTessellationControlShader = false; Stages = new NativeArray(Constants.MaxShaderStages); @@ -259,53 +315,9 @@ namespace Ryujinx.Graphics.Vulkan AdvancedBlendDstPreMultiplied = true; AdvancedBlendOverlap = BlendOverlapEXT.UncorrelatedExt; + LineWidth = 1f; + SamplesCount = 1; DepthMode = true; - - PolygonMode = PolygonMode.Fill; - DepthBoundsTestEnable = false; - - _supportsExtDynamicState = capabilities.SupportsExtendedDynamicState; - _supportsExtDynamicState2 = capabilities.SupportsExtendedDynamicState2; - - if (_supportsExtDynamicState) - { - StencilFrontFailOp = 0; - StencilFrontPassOp = 0; - StencilFrontDepthFailOp = 0; - StencilFrontCompareOp = 0; - - StencilBackFailOp = 0; - StencilBackPassOp = 0; - StencilBackDepthFailOp = 0; - StencilBackCompareOp = 0; - - ViewportsCount = 0; - ScissorsCount = 0; - - CullMode = 0; - FrontFace = 0; - DepthTestEnable = false; - DepthWriteEnable = false; - DepthCompareOp = 0; - StencilTestEnable = false; - } - - if (_supportsExtDynamicState2.ExtendedDynamicState2) - { - PrimitiveRestartEnable = false; - DepthBiasEnable = false; - RasterizerDiscardEnable = false; - - if (_supportsExtDynamicState2.ExtendedDynamicState2LogicOp) - { - LogicOp = 0; - } - - if (_supportsExtDynamicState2.ExtendedDynamicState2PatchControlPoints) - { - PatchControlPoints = 0; - } - } } public unsafe Auto CreateComputePipeline( @@ -323,6 +335,7 @@ namespace Ryujinx.Graphics.Vulkan { SType = StructureType.ComputePipelineCreateInfo, Stage = Stages[0], + BasePipelineIndex = -1, Layout = PipelineLayout, }; @@ -358,74 +371,6 @@ namespace Ryujinx.Graphics.Vulkan return pipeline; } - - private void CheckCapability(VulkanRenderer gd) - { - // Vendors other than NVIDIA have a bug where it enables logical operations even for float formats, - // so we need to force disable them here. - LogicOpEnable = LogicOpEnable && (gd.Vendor == Vendor.Nvidia || Internal.LogicOpsAllowed); - - if (!_supportsExtDynamicState) - { - DepthWriteEnable = DepthWriteEnable && DepthTestEnable; - DepthCompareOp = DepthTestEnable ? DepthCompareOp : default; - } - - if (!_supportsExtDynamicState2.ExtendedDynamicState2LogicOp) - { - LogicOp = LogicOpEnable ? LogicOp : default; - } - - if (!_supportsExtDynamicState2.ExtendedDynamicState2) - { - bool topologySupportsRestart; - - if (gd.Capabilities.SupportsPrimitiveTopologyListRestart) - { - topologySupportsRestart = gd.Capabilities.SupportsPrimitiveTopologyPatchListRestart || - Topology != PrimitiveTopology.PatchList; - } - else - { - topologySupportsRestart = Topology == PrimitiveTopology.LineStrip || - Topology == PrimitiveTopology.TriangleStrip || - Topology == PrimitiveTopology.TriangleFan || - Topology == PrimitiveTopology.LineStripWithAdjacency || - Topology == PrimitiveTopology.TriangleStripWithAdjacency; - } - - PrimitiveRestartEnable &= topologySupportsRestart; - } - - if (_supportsExtDynamicState) - { - Topology = Topology.ConvertToClass(); - } - - Topology = HasTessellationControlShader ? PrimitiveTopology.PatchList : Topology; - - if (gd.IsMoltenVk && Internal.AttachmentIntegerFormatMask != 0) - { - _blendEnables = 0; - - // Blend can't be enabled for integer formats, so let's make sure it is disabled. - uint attachmentIntegerFormatMask = Internal.AttachmentIntegerFormatMask; - - while (attachmentIntegerFormatMask != 0) - { - int i = BitOperations.TrailingZeroCount(attachmentIntegerFormatMask); - - if (Internal.ColorBlendAttachmentState[i].BlendEnable) - { - _blendEnables |= 1u << i; - } - - Internal.ColorBlendAttachmentState[i].BlendEnable = false; - attachmentIntegerFormatMask &= ~(1u << i); - } - } - } - public unsafe Auto CreateGraphicsPipeline( VulkanRenderer gd, Device device, @@ -434,17 +379,6 @@ namespace Ryujinx.Graphics.Vulkan RenderPass renderPass, bool throwOnError = false) { - CheckCapability(gd); - - // Using patches topology without a tessellation shader is invalid. - // If we find such a case, return null pipeline to skip the draw. - if (Topology == PrimitiveTopology.PatchList && !HasTessellationControlShader) - { - program.AddGraphicsPipeline(ref Internal, null); - - return null; - } - if (program.TryGetGraphicsPipeline(ref Internal, out var pipeline)) { return pipeline; @@ -454,7 +388,7 @@ namespace Ryujinx.Graphics.Vulkan bool isMoltenVk = gd.IsMoltenVk; - if (isMoltenVk && !_supportsExtDynamicState) + if (isMoltenVk) { UpdateVertexAttributeDescriptions(gd); } @@ -468,30 +402,69 @@ namespace Ryujinx.Graphics.Vulkan { SType = StructureType.PipelineVertexInputStateCreateInfo, VertexAttributeDescriptionCount = VertexAttributeDescriptionsCount, - PVertexAttributeDescriptions = isMoltenVk && !_supportsExtDynamicState ? pVertexAttributeDescriptions2 : pVertexAttributeDescriptions, + PVertexAttributeDescriptions = isMoltenVk ? pVertexAttributeDescriptions2 : pVertexAttributeDescriptions, VertexBindingDescriptionCount = VertexBindingDescriptionsCount, PVertexBindingDescriptions = pVertexBindingDescriptions, }; + // Using patches topology without a tessellation shader is invalid. + // If we find such a case, return null pipeline to skip the draw. + if (Topology == PrimitiveTopology.PatchList && !HasTessellationControlShader) + { + program.AddGraphicsPipeline(ref Internal, null); + + return null; + } + + bool primitiveRestartEnable = PrimitiveRestartEnable; + + bool topologySupportsRestart; + + if (gd.Capabilities.SupportsPrimitiveTopologyListRestart) + { + topologySupportsRestart = gd.Capabilities.SupportsPrimitiveTopologyPatchListRestart || Topology != PrimitiveTopology.PatchList; + } + else + { + topologySupportsRestart = Topology == PrimitiveTopology.LineStrip || + Topology == PrimitiveTopology.TriangleStrip || + Topology == PrimitiveTopology.TriangleFan || + Topology == PrimitiveTopology.LineStripWithAdjacency || + Topology == PrimitiveTopology.TriangleStripWithAdjacency; + } + + primitiveRestartEnable &= topologySupportsRestart; + var inputAssemblyState = new PipelineInputAssemblyStateCreateInfo { SType = StructureType.PipelineInputAssemblyStateCreateInfo, - Topology = Topology, + PrimitiveRestartEnable = primitiveRestartEnable, + Topology = HasTessellationControlShader ? PrimitiveTopology.PatchList : Topology, }; - PipelineTessellationStateCreateInfo tessellationState; + var tessellationState = new PipelineTessellationStateCreateInfo + { + SType = StructureType.PipelineTessellationStateCreateInfo, + PatchControlPoints = PatchControlPoints, + }; var rasterizationState = new PipelineRasterizationStateCreateInfo { SType = StructureType.PipelineRasterizationStateCreateInfo, DepthClampEnable = DepthClampEnable, - // When widelines feature is not supported it must be 1.0f, this will be ignored if Line Width dynamic state is supported - LineWidth = 1.0f, + RasterizerDiscardEnable = RasterizerDiscardEnable, + PolygonMode = PolygonMode, + LineWidth = LineWidth, + CullMode = CullMode, + FrontFace = FrontFace, + DepthBiasEnable = DepthBiasEnable, }; var viewportState = new PipelineViewportStateCreateInfo { SType = StructureType.PipelineViewportStateCreateInfo, + ViewportCount = ViewportsCount, + ScissorCount = ScissorsCount, }; if (gd.Capabilities.SupportsDepthClipControl) @@ -515,75 +488,71 @@ namespace Ryujinx.Graphics.Vulkan AlphaToOneEnable = AlphaToOneEnable, }; + var stencilFront = new StencilOpState( + StencilFrontFailOp, + StencilFrontPassOp, + StencilFrontDepthFailOp, + StencilFrontCompareOp); + + var stencilBack = new StencilOpState( + StencilBackFailOp, + StencilBackPassOp, + StencilBackDepthFailOp, + StencilBackCompareOp); + var depthStencilState = new PipelineDepthStencilStateCreateInfo { SType = StructureType.PipelineDepthStencilStateCreateInfo, - DepthBoundsTestEnable = DepthBoundsTestEnable, + DepthTestEnable = DepthTestEnable, + DepthWriteEnable = DepthWriteEnable, + DepthCompareOp = DepthCompareOp, + DepthBoundsTestEnable = false, + StencilTestEnable = StencilTestEnable, + Front = stencilFront, + Back = stencilBack, }; - if (!_supportsExtDynamicState) + uint blendEnables = 0; + + if (gd.IsMoltenVk && Internal.AttachmentIntegerFormatMask != 0) { - rasterizationState.CullMode = CullMode; - rasterizationState.FrontFace = FrontFace; + // Blend can't be enabled for integer formats, so let's make sure it is disabled. + uint attachmentIntegerFormatMask = Internal.AttachmentIntegerFormatMask; - viewportState.ViewportCount = ViewportsCount; - viewportState.ScissorCount = ScissorsCount; - - var stencilFront = new StencilOpState( - StencilFrontFailOp, - StencilFrontPassOp, - StencilFrontDepthFailOp, - StencilFrontCompareOp); - - var stencilBack = new StencilOpState( - StencilBackFailOp, - StencilBackPassOp, - StencilBackDepthFailOp, - StencilBackCompareOp); - - depthStencilState.Front = stencilFront; - depthStencilState.Back = stencilBack; - depthStencilState.StencilTestEnable = StencilTestEnable; - depthStencilState.DepthTestEnable = DepthTestEnable; - depthStencilState.DepthWriteEnable = DepthWriteEnable; - depthStencilState.DepthCompareOp = DepthCompareOp; - } - - if (!_supportsExtDynamicState2.ExtendedDynamicState2) - { - - inputAssemblyState.PrimitiveRestartEnable = PrimitiveRestartEnable; - rasterizationState.DepthBiasEnable = DepthBiasEnable; - rasterizationState.RasterizerDiscardEnable = RasterizerDiscardEnable; - } - - if (!gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints) - { - tessellationState = new PipelineTessellationStateCreateInfo + while (attachmentIntegerFormatMask != 0) { - SType = StructureType.PipelineTessellationStateCreateInfo, - PatchControlPoints = PatchControlPoints, - }; + int i = BitOperations.TrailingZeroCount(attachmentIntegerFormatMask); + + if (Internal.ColorBlendAttachmentState[i].BlendEnable) + { + blendEnables |= 1u << i; + } + + Internal.ColorBlendAttachmentState[i].BlendEnable = false; + attachmentIntegerFormatMask &= ~(1u << i); + } } + // Vendors other than NVIDIA have a bug where it enables logical operations even for float formats, + // so we need to force disable them here. + bool logicOpEnable = LogicOpEnable && (gd.Vendor == Vendor.Nvidia || Internal.LogicOpsAllowed); + var colorBlendState = new PipelineColorBlendStateCreateInfo { SType = StructureType.PipelineColorBlendStateCreateInfo, + LogicOpEnable = logicOpEnable, + LogicOp = LogicOp, AttachmentCount = ColorBlendAttachmentStateCount, PAttachments = pColorBlendAttachmentState, - LogicOpEnable = LogicOpEnable, }; - if (!gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2LogicOp) - { - colorBlendState.LogicOp = LogicOp; - } + PipelineColorBlendAdvancedStateCreateInfoEXT colorBlendAdvancedState; if (!AdvancedBlendSrcPreMultiplied || !AdvancedBlendDstPreMultiplied || AdvancedBlendOverlap != BlendOverlapEXT.UncorrelatedExt) { - PipelineColorBlendAdvancedStateCreateInfoEXT colorBlendAdvancedState = new PipelineColorBlendAdvancedStateCreateInfoEXT + colorBlendAdvancedState = new PipelineColorBlendAdvancedStateCreateInfoEXT { SType = StructureType.PipelineColorBlendAdvancedStateCreateInfoExt, SrcPremultiplied = AdvancedBlendSrcPreMultiplied, @@ -594,65 +563,28 @@ namespace Ryujinx.Graphics.Vulkan colorBlendState.PNext = &colorBlendAdvancedState; } - DynamicState* dynamicStates = stackalloc DynamicState[MaxDynamicStatesCount]; + bool supportsExtDynamicState = gd.Capabilities.SupportsExtendedDynamicState; + int dynamicStatesCount = supportsExtDynamicState ? 8 : 7; - uint dynamicStatesCount = 7; + DynamicState* dynamicStates = stackalloc DynamicState[dynamicStatesCount]; dynamicStates[0] = DynamicState.Viewport; dynamicStates[1] = DynamicState.Scissor; - dynamicStates[2] = DynamicState.StencilCompareMask; - dynamicStates[3] = DynamicState.StencilWriteMask; - dynamicStates[4] = DynamicState.StencilReference; - dynamicStates[5] = DynamicState.BlendConstants; - dynamicStates[6] = DynamicState.DepthBias; + dynamicStates[2] = DynamicState.DepthBias; + dynamicStates[3] = DynamicState.StencilCompareMask; + dynamicStates[4] = DynamicState.StencilWriteMask; + dynamicStates[5] = DynamicState.StencilReference; + dynamicStates[6] = DynamicState.BlendConstants; - if (!isMoltenVk) + if (supportsExtDynamicState) { - //LineWidth dynamic state is only supported on macOS when using Metal Private API on newer version of MoltenVK - dynamicStates[dynamicStatesCount++] = DynamicState.LineWidth; - } - - if (_supportsExtDynamicState) - { - if (gd.SupportsMTL31 || !gd.IsMoltenVk) - { - // Requires Metal 3.1 and new MoltenVK, however extended dynamic states extension is not - // available on older versions of MVK, so we can safely check only OS version. - dynamicStates[dynamicStatesCount++] = DynamicState.VertexInputBindingStrideExt; - } - dynamicStates[0] = DynamicState.ViewportWithCountExt; - dynamicStates[1] = DynamicState.ScissorWithCountExt; - dynamicStates[dynamicStatesCount++] = DynamicState.CullModeExt; - dynamicStates[dynamicStatesCount++] = DynamicState.FrontFaceExt; - dynamicStates[dynamicStatesCount++] = DynamicState.DepthTestEnableExt; - dynamicStates[dynamicStatesCount++] = DynamicState.DepthWriteEnableExt; - - dynamicStates[dynamicStatesCount++] = DynamicState.DepthCompareOpExt; - dynamicStates[dynamicStatesCount++] = DynamicState.StencilTestEnableExt; - dynamicStates[dynamicStatesCount++] = DynamicState.StencilOpExt; - dynamicStates[dynamicStatesCount++] = DynamicState.PrimitiveTopologyExt; - } - - if (_supportsExtDynamicState2.ExtendedDynamicState2) - { - dynamicStates[dynamicStatesCount++] = DynamicState.DepthBiasEnableExt; - dynamicStates[dynamicStatesCount++] = DynamicState.RasterizerDiscardEnableExt; - dynamicStates[dynamicStatesCount++] = DynamicState.PrimitiveRestartEnableExt; - - if (_supportsExtDynamicState2.ExtendedDynamicState2LogicOp) - { - dynamicStates[dynamicStatesCount++] = DynamicState.LogicOpExt; - } - if (_supportsExtDynamicState2.ExtendedDynamicState2PatchControlPoints) - { - dynamicStates[dynamicStatesCount++] = DynamicState.PatchControlPointsExt; - } + dynamicStates[7] = DynamicState.VertexInputBindingStrideExt; } var pipelineDynamicStateCreateInfo = new PipelineDynamicStateCreateInfo { SType = StructureType.PipelineDynamicStateCreateInfo, - DynamicStateCount = dynamicStatesCount, + DynamicStateCount = (uint)dynamicStatesCount, PDynamicStates = dynamicStates, }; @@ -663,6 +595,7 @@ namespace Ryujinx.Graphics.Vulkan PStages = Stages.Pointer, PVertexInputState = &vertexInputState, PInputAssemblyState = &inputAssemblyState, + PTessellationState = &tessellationState, PViewportState = &viewportState, PRasterizationState = &rasterizationState, PMultisampleState = &multisampleState, @@ -673,11 +606,6 @@ namespace Ryujinx.Graphics.Vulkan RenderPass = renderPass, }; - if (!gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints) - { - pipelineCreateInfo.PTessellationState = &tessellationState; - } - Result result = gd.Api.CreateGraphicsPipelines(device, cache, 1, &pipelineCreateInfo, null, &pipelineHandle); if (throwOnError) @@ -690,21 +618,21 @@ namespace Ryujinx.Graphics.Vulkan return null; } + + // Restore previous blend enable values if we changed it. + while (blendEnables != 0) + { + int i = BitOperations.TrailingZeroCount(blendEnables); + + Internal.ColorBlendAttachmentState[i].BlendEnable = true; + blendEnables &= ~(1u << i); + } } pipeline = new Auto(new DisposablePipeline(gd.Api, device, pipelineHandle)); program.AddGraphicsPipeline(ref Internal, pipeline); - // Restore previous blend enable values if we changed it. - while (_blendEnables != 0) - { - int i = BitOperations.TrailingZeroCount(_blendEnables); - - Internal.ColorBlendAttachmentState[i].BlendEnable = true; - _blendEnables &= ~(1u << i); - } - return pipeline; } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineUid.cs b/src/Ryujinx.Graphics.Vulkan/PipelineUid.cs index 1a9e58d88..c56224216 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineUid.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineUid.cs @@ -11,17 +11,23 @@ namespace Ryujinx.Graphics.Vulkan { public ulong Id0; public ulong Id1; - public ulong Id2; public ulong Id3; - private readonly uint VertexAttributeDescriptionsCount => (byte)((Id0 >> 38) & 0xFF); - private readonly uint VertexBindingDescriptionsCount => (byte)((Id0 >> 46) & 0xFF); - private readonly uint ColorBlendAttachmentStateCount => (byte)((Id1 >> 8) & 0xFF); - private readonly bool HasDepthStencil => ((Id1 >> 63) & 0x1) != 0UL; + public ulong Id4; + public ulong Id5; + public ulong Id6; + + public ulong Id7; + public ulong Id8; + + private readonly uint VertexAttributeDescriptionsCount => (byte)((Id5 >> 38) & 0xFF); + private readonly uint VertexBindingDescriptionsCount => (byte)((Id5 >> 46) & 0xFF); + private readonly uint ColorBlendAttachmentStateCount => (byte)((Id6 >> 8) & 0xFF); + private readonly bool HasDepthStencil => ((Id6 >> 63) & 0x1) != 0UL; public Array32 VertexAttributeDescriptions; - public Array32 VertexBindingDescriptions; + public Array33 VertexBindingDescriptions; public Array8 ColorBlendAttachmentState; public Array9 AttachmentFormats; public uint AttachmentIntegerFormatMask; @@ -34,7 +40,9 @@ namespace Ryujinx.Graphics.Vulkan public bool Equals(ref PipelineUid other) { - if (!Unsafe.As>(ref Id0).Equals(Unsafe.As>(ref other.Id0))) + if (!Unsafe.As>(ref Id0).Equals(Unsafe.As>(ref other.Id0)) || + !Unsafe.As>(ref Id4).Equals(Unsafe.As>(ref other.Id4)) || + !Unsafe.As>(ref Id7).Equals(Unsafe.As>(ref other.Id7))) { return false; } @@ -72,7 +80,12 @@ namespace Ryujinx.Graphics.Vulkan ulong hash64 = Id0 * 23 ^ Id1 * 23 ^ Id2 * 23 ^ - Id3 * 23; + Id3 * 23 ^ + Id4 * 23 ^ + Id5 * 23 ^ + Id6 * 23 ^ + Id7 * 23 ^ + Id8 * 23; for (int i = 0; i < (int)VertexAttributeDescriptionsCount; i++) { diff --git a/src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs b/src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs index 089408863..0e19a0088 100644 --- a/src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs +++ b/src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs @@ -538,7 +538,7 @@ namespace Ryujinx.Graphics.Vulkan public void CreateBackgroundComputePipeline() { PipelineState pipeline = new(); - pipeline.Initialize(_gd.Capabilities); + pipeline.Initialize(); pipeline.Stages[0] = _shaders[0].GetInfo(); pipeline.StagesCount = 1; diff --git a/src/Ryujinx.Graphics.Vulkan/VertexBufferState.cs b/src/Ryujinx.Graphics.Vulkan/VertexBufferState.cs index b146a0978..f4d512f92 100644 --- a/src/Ryujinx.Graphics.Vulkan/VertexBufferState.cs +++ b/src/Ryujinx.Graphics.Vulkan/VertexBufferState.cs @@ -73,10 +73,7 @@ namespace Ryujinx.Graphics.Vulkan _buffer = autoBuffer; - if (!gd.Capabilities.SupportsExtendedDynamicState) - { - state.Internal.VertexBindingDescriptions[DescriptorIndex].Stride = (uint)stride; - } + state.Internal.VertexBindingDescriptions[DescriptorIndex].Stride = (uint)stride; } return; @@ -84,11 +81,8 @@ namespace Ryujinx.Graphics.Vulkan autoBuffer = gd.BufferManager.GetBuffer(cbs.CommandBuffer, _handle, false, out int size); - if (!gd.Capabilities.SupportsExtendedDynamicState) - { - // The original stride must be reapplied in case it was rewritten. - state.Internal.VertexBindingDescriptions[DescriptorIndex].Stride = (uint)_stride; - } + // The original stride must be reapplied in case it was rewritten. + state.Internal.VertexBindingDescriptions[DescriptorIndex].Stride = (uint)_stride; if (_offset >= size) { diff --git a/src/Ryujinx.Graphics.Vulkan/VertexBufferUpdater.cs b/src/Ryujinx.Graphics.Vulkan/VertexBufferUpdater.cs index 7dbdfcb05..94269dd76 100644 --- a/src/Ryujinx.Graphics.Vulkan/VertexBufferUpdater.cs +++ b/src/Ryujinx.Graphics.Vulkan/VertexBufferUpdater.cs @@ -51,7 +51,7 @@ namespace Ryujinx.Graphics.Vulkan { if (_count != 0) { - if (_gd.Capabilities.SupportsExtendedDynamicState && (_gd.SupportsMTL31 || !_gd.IsMoltenVk)) + if (_gd.Capabilities.SupportsExtendedDynamicState) { _gd.ExtendedDynamicStateApi.CmdBindVertexBuffers2( cbs.CommandBuffer, diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs b/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs index a5de2de3b..a66579d5e 100644 --- a/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs +++ b/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs @@ -24,7 +24,6 @@ namespace Ryujinx.Graphics.Vulkan [ ExtConditionalRendering.ExtensionName, ExtExtendedDynamicState.ExtensionName, - ExtExtendedDynamicState2.ExtensionName, ExtTransformFeedback.ExtensionName, KhrDrawIndirectCount.ExtensionName, KhrPushDescriptor.ExtensionName, @@ -315,17 +314,6 @@ namespace Ryujinx.Graphics.Vulkan features2.PNext = &supportedFeaturesCustomBorderColor; } - PhysicalDeviceExtendedDynamicState2FeaturesEXT supportedFeaturesExtExtendedDynamicState2 = new() - { - SType = StructureType.PhysicalDeviceExtendedDynamicState2FeaturesExt, - PNext = features2.PNext, - }; - - if (physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState2.ExtensionName)) - { - features2.PNext = &supportedFeaturesExtExtendedDynamicState2; - } - PhysicalDevicePrimitiveTopologyListRestartFeaturesEXT supportedFeaturesPrimitiveTopologyListRestart = new() { SType = StructureType.PhysicalDevicePrimitiveTopologyListRestartFeaturesExt, @@ -406,7 +394,6 @@ namespace Ryujinx.Graphics.Vulkan TessellationShader = supportedFeatures.TessellationShader, VertexPipelineStoresAndAtomics = supportedFeatures.VertexPipelineStoresAndAtomics, RobustBufferAccess = useRobustBufferAccess, - WideLines = supportedFeatures.WideLines, SampleRateShading = supportedFeatures.SampleRateShading, }; @@ -464,20 +451,6 @@ namespace Ryujinx.Graphics.Vulkan pExtendedFeatures = &featuresExtendedDynamicState; - if (physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState2.ExtensionName)) - { - var featuresExtendedDynamicState2 = new PhysicalDeviceExtendedDynamicState2FeaturesEXT() - { - SType = StructureType.PhysicalDeviceExtendedDynamicState2FeaturesExt, - PNext = pExtendedFeatures, - ExtendedDynamicState2 = supportedFeaturesExtExtendedDynamicState2.ExtendedDynamicState2, - ExtendedDynamicState2LogicOp = supportedFeaturesExtExtendedDynamicState2.ExtendedDynamicState2LogicOp, - ExtendedDynamicState2PatchControlPoints = supportedFeaturesExtExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints, - }; - - pExtendedFeatures = &featuresExtendedDynamicState2; - } - var featuresVk11 = new PhysicalDeviceVulkan11Features { SType = StructureType.PhysicalDeviceVulkan11Features, diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs index befb6c0f2..9d4f07736 100644 --- a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs +++ b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs @@ -38,7 +38,6 @@ namespace Ryujinx.Graphics.Vulkan internal KhrSwapchain SwapchainApi { get; private set; } internal ExtConditionalRendering ConditionalRenderingApi { get; private set; } internal ExtExtendedDynamicState ExtendedDynamicStateApi { get; private set; } - internal ExtExtendedDynamicState2 ExtendedDynamicState2Api { get; private set; } internal KhrPushDescriptor PushDescriptorApi { get; private set; } internal ExtTransformFeedback TransformFeedbackApi { get; private set; } internal KhrDrawIndirectCount DrawIndirectCountApi { get; private set; } @@ -93,7 +92,6 @@ namespace Ryujinx.Graphics.Vulkan internal bool IsIntelArc { get; private set; } internal bool IsQualcommProprietary { get; private set; } internal bool IsMoltenVk { get; private set; } - internal bool SupportsMTL31 { get; private set; } internal bool IsTBDR { get; private set; } internal bool IsSharedMemory { get; private set; } @@ -122,8 +120,6 @@ namespace Ryujinx.Graphics.Vulkan // Any device running on MacOS is using MoltenVK, even Intel and AMD vendors. IsMoltenVk = true; - - SupportsMTL31 = OperatingSystem.IsMacOSVersionAtLeast(14); } } @@ -141,11 +137,6 @@ namespace Ryujinx.Graphics.Vulkan ExtendedDynamicStateApi = extendedDynamicStateApi; } - if (Api.TryGetDeviceExtension(_instance.Instance, _device, out ExtExtendedDynamicState2 extendedDynamicState2Api)) - { - ExtendedDynamicState2Api = extendedDynamicState2Api; - } - if (Api.TryGetDeviceExtension(_instance.Instance, _device, out KhrPushDescriptor pushDescriptorApi)) { PushDescriptorApi = pushDescriptorApi; @@ -235,11 +226,6 @@ namespace Ryujinx.Graphics.Vulkan SType = StructureType.PhysicalDevicePrimitiveTopologyListRestartFeaturesExt, }; - PhysicalDeviceExtendedDynamicState2FeaturesEXT featuresExtendedDynamicState2 = new() - { - SType = StructureType.PhysicalDeviceExtendedDynamicState2FeaturesExt, - }; - PhysicalDeviceRobustness2FeaturesEXT featuresRobustness2 = new() { SType = StructureType.PhysicalDeviceRobustness2FeaturesExt, @@ -270,12 +256,6 @@ namespace Ryujinx.Graphics.Vulkan features2.PNext = &featuresPrimitiveTopologyListRestart; } - if (_physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState2.ExtensionName)) - { - featuresExtendedDynamicState2.PNext = features2.PNext; - features2.PNext = &featuresExtendedDynamicState2; - } - if (_physicalDevice.IsDeviceExtensionPresent("VK_EXT_robustness2")) { featuresRobustness2.PNext = features2.PNext; @@ -393,10 +373,6 @@ namespace Ryujinx.Graphics.Vulkan properties.Limits.FramebufferDepthSampleCounts & properties.Limits.FramebufferStencilSampleCounts; - // Temporarily disable this, can be added back at a later date, make it easy to re-enable. - // Disabled because currently causing Device Lost error on NVIDIA. - featuresExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints = false; - Capabilities = new HardwareCapabilities( _physicalDevice.IsDeviceExtensionPresent("VK_EXT_index_type_uint8"), supportsCustomBorderColor, @@ -413,8 +389,6 @@ namespace Ryujinx.Graphics.Vulkan features2.Features.ShaderStorageImageMultisample, _physicalDevice.IsDeviceExtensionPresent(ExtConditionalRendering.ExtensionName), _physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState.ExtensionName), - featuresExtendedDynamicState2, - _physicalDevice.PhysicalDeviceProperties.Limits.MaxTessellationPatchSize, features2.Features.MultiViewport && !(IsMoltenVk && Vendor == Vendor.Amd), // Workaround for AMD on MoltenVK issue featuresRobustness2.NullDescriptor || IsMoltenVk, supportsPushDescriptors && !IsMoltenVk, @@ -430,7 +404,6 @@ namespace Ryujinx.Graphics.Vulkan _physicalDevice.IsDeviceExtensionPresent("VK_NV_viewport_array2"), _physicalDevice.IsDeviceExtensionPresent(ExtExternalMemoryHost.ExtensionName), supportsDepthClipControl && featuresDepthClipControl.DepthClipControl, - _physicalDevice.PhysicalDeviceFeatures.WideLines, propertiesSubgroup.SubgroupSize, supportedSampleCounts, portabilityFlags, @@ -764,10 +737,6 @@ 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,