diff options
Diffstat (limited to 'Ryujinx.Graphics.Vulkan/PipelineBase.cs')
-rw-r--r-- | Ryujinx.Graphics.Vulkan/PipelineBase.cs | 116 |
1 files changed, 79 insertions, 37 deletions
diff --git a/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 5c666b09..39acc5d9 100644 --- a/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -51,13 +51,16 @@ namespace Ryujinx.Graphics.Vulkan private readonly DescriptorSetUpdater _descriptorSetUpdater; - private BufferState _indexBuffer; + private IndexBufferState _indexBuffer; + private IndexBufferPattern _indexBufferPattern; private readonly BufferState[] _transformFeedbackBuffers; private readonly VertexBufferState[] _vertexBuffers; private ulong _vertexBuffersDirty; protected Rectangle<int> ClearScissor; public SupportBufferUpdater SupportBufferUpdater; + public IndexBufferPattern QuadsToTrisPattern; + public IndexBufferPattern TriFanToTrisPattern; private bool _needsIndexBufferRebind; private bool _needsTransformFeedbackBuffersRebind; @@ -107,6 +110,9 @@ namespace Ryujinx.Graphics.Vulkan { SupportBufferUpdater = new SupportBufferUpdater(Gd); SupportBufferUpdater.UpdateRenderScale(_renderScale, 0, SupportBuffer.RenderScaleMaxCount); + + QuadsToTrisPattern = new IndexBufferPattern(Gd, 4, 6, 0, new[] { 0, 1, 2, 0, 2, 3 }, 4, false); + TriFanToTrisPattern = new IndexBufferPattern(Gd, 3, 3, 2, new[] { int.MinValue, -1, 0 }, 1, true); } public unsafe void Barrier() @@ -245,6 +251,14 @@ namespace Ryujinx.Graphics.Vulkan } } + public void DirtyIndexBuffer(Auto<DisposableBuffer> buffer) + { + if (_indexBuffer.BoundEquals(buffer)) + { + _needsIndexBufferRebind = true; + } + } + public void DispatchCompute(int groupsX, int groupsY, int groupsZ) { if (!_program.IsLinked) @@ -267,24 +281,59 @@ namespace Ryujinx.Graphics.Vulkan RecreatePipelineIfNeeded(PipelineBindPoint.Graphics); BeginRenderPass(); - ResumeTransformFeedbackInternal(); DrawCount++; - if (_topology == GAL.PrimitiveTopology.Quads) + if (Gd.TopologyUnsupported(_topology)) { - int quadsCount = vertexCount / 4; + // Temporarily bind a conversion pattern as an index buffer. + _needsIndexBufferRebind = true; - for (int i = 0; i < quadsCount; i++) + IndexBufferPattern pattern = _topology switch { - Gd.Api.CmdDraw(CommandBuffer, 4, (uint)instanceCount, (uint)(firstVertex + i * 4), (uint)firstInstance); - } + GAL.PrimitiveTopology.Quads => QuadsToTrisPattern, + GAL.PrimitiveTopology.TriangleFan => TriFanToTrisPattern, + _ => throw new NotSupportedException($"Unsupported topology: {_topology}") + }; + + BufferHandle handle = pattern.GetRepeatingBuffer(vertexCount, out int indexCount); + var buffer = Gd.BufferManager.GetBuffer(CommandBuffer, handle, false); + + Gd.Api.CmdBindIndexBuffer(CommandBuffer, buffer.Get(Cbs, 0, indexCount * sizeof(int)).Value, 0, Silk.NET.Vulkan.IndexType.Uint32); + + BeginRenderPass(); // May have been interrupted to set buffer data. + ResumeTransformFeedbackInternal(); + + Gd.Api.CmdDrawIndexed(CommandBuffer, (uint)indexCount, (uint)instanceCount, 0, firstVertex, (uint)firstInstance); } else { + ResumeTransformFeedbackInternal(); + Gd.Api.CmdDraw(CommandBuffer, (uint)vertexCount, (uint)instanceCount, (uint)firstVertex, (uint)firstInstance); } } + private void UpdateIndexBufferPattern() + { + IndexBufferPattern pattern = null; + + if (Gd.TopologyUnsupported(_topology)) + { + pattern = _topology switch + { + GAL.PrimitiveTopology.Quads => QuadsToTrisPattern, + GAL.PrimitiveTopology.TriangleFan => TriFanToTrisPattern, + _ => throw new NotSupportedException($"Unsupported topology: {_topology}") + }; + } + + if (_indexBufferPattern != pattern) + { + _indexBufferPattern = pattern; + _needsIndexBufferRebind = true; + } + } + public void DrawIndexed(int indexCount, int instanceCount, int firstIndex, int firstVertex, int firstInstance) { if (!_program.IsLinked) @@ -292,22 +341,34 @@ namespace Ryujinx.Graphics.Vulkan return; } + UpdateIndexBufferPattern(); RecreatePipelineIfNeeded(PipelineBindPoint.Graphics); BeginRenderPass(); - ResumeTransformFeedbackInternal(); DrawCount++; - if (_topology == GAL.PrimitiveTopology.Quads) + if (_indexBufferPattern != null) { - int quadsCount = indexCount / 4; + // Convert the index buffer into a supported topology. + IndexBufferPattern pattern = _indexBufferPattern; + + int convertedCount = pattern.GetConvertedCount(indexCount); - for (int i = 0; i < quadsCount; i++) + if (_needsIndexBufferRebind) { - Gd.Api.CmdDrawIndexed(CommandBuffer, 4, (uint)instanceCount, (uint)(firstIndex + i * 4), firstVertex, (uint)firstInstance); + _indexBuffer.BindConvertedIndexBuffer(Gd, Cbs, firstIndex, indexCount, convertedCount, pattern); + + _needsIndexBufferRebind = false; } + + BeginRenderPass(); // May have been interrupted to set buffer data. + ResumeTransformFeedbackInternal(); + + Gd.Api.CmdDrawIndexed(CommandBuffer, (uint)convertedCount, (uint)instanceCount, 0, firstVertex, (uint)firstInstance); } else { + ResumeTransformFeedbackInternal(); + Gd.Api.CmdDrawIndexed(CommandBuffer, (uint)indexCount, (uint)instanceCount, (uint)firstIndex, firstVertex, (uint)firstInstance); } } @@ -500,34 +561,16 @@ namespace Ryujinx.Graphics.Vulkan public void SetIndexBuffer(BufferRange buffer, GAL.IndexType type) { - _indexBuffer.Dispose(); - if (buffer.Handle != BufferHandle.Null) { - Auto<DisposableBuffer> ib = null; - int offset = buffer.Offset; - int size = buffer.Size; - - if (type == GAL.IndexType.UByte && !Gd.Capabilities.SupportsIndexTypeUint8) - { - ib = Gd.BufferManager.GetBufferI8ToI16(Cbs, buffer.Handle, offset, size); - offset = 0; - size *= 2; - type = GAL.IndexType.UShort; - } - else - { - ib = Gd.BufferManager.GetBuffer(CommandBuffer, buffer.Handle, false); - } - - _indexBuffer = new BufferState(ib, offset, size, type.Convert()); + _indexBuffer = new IndexBufferState(buffer.Handle, buffer.Offset, buffer.Size, type.Convert()); } else { - _indexBuffer = BufferState.Null; + _indexBuffer = IndexBufferState.Null; } - _indexBuffer.BindIndexBuffer(Gd.Api, Cbs); + _needsIndexBufferRebind = true; } public void SetLineParameters(float width, bool smooth) @@ -584,7 +627,7 @@ namespace Ryujinx.Graphics.Vulkan { _topology = topology; - var vkTopology = topology.Convert(); + var vkTopology = Gd.TopologyRemap(topology).Convert(); _newState.Topology = vkTopology; @@ -1127,9 +1170,9 @@ namespace Ryujinx.Graphics.Vulkan // Commit changes to the support buffer before drawing. SupportBufferUpdater.Commit(); - if (_needsIndexBufferRebind) + if (_needsIndexBufferRebind && _indexBufferPattern == null) { - _indexBuffer.BindIndexBuffer(Gd.Api, Cbs); + _indexBuffer.BindIndexBuffer(Gd, Cbs); _needsIndexBufferRebind = false; } @@ -1265,7 +1308,6 @@ namespace Ryujinx.Graphics.Vulkan { _renderPass?.Dispose(); _framebuffer?.Dispose(); - _indexBuffer.Dispose(); _newState.Dispose(); _descriptorSetUpdater.Dispose(); |