From 4c0eb91d7e6bdbe42ffa6e950e3288f8066de089 Mon Sep 17 00:00:00 2001 From: riperiperi Date: Tue, 20 Sep 2022 22:38:48 +0100 Subject: Convert Quads to Triangles in Vulkan (#3715) * Add Index Buffer conversion for quads to Vulkan Also adds a reusable repeating pattern index buffer to use for non-indexed draws, and generalizes the conversion cache for buffers. * Fix some issues * End render pass before conversion * Resume transform feedback after we ensure we're in a pass. * Always generate UInt32 type indices for topology conversion * No it's not. * Remove unused code * Rely on TopologyRemap to convert quads to tris. * Remove double newline * Ensure render pass ends before stride or I8 conversion --- Ryujinx.Graphics.Vulkan/HelperShader.cs | 81 +++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) (limited to 'Ryujinx.Graphics.Vulkan/HelperShader.cs') diff --git a/Ryujinx.Graphics.Vulkan/HelperShader.cs b/Ryujinx.Graphics.Vulkan/HelperShader.cs index 2eec92f0..0201de0a 100644 --- a/Ryujinx.Graphics.Vulkan/HelperShader.cs +++ b/Ryujinx.Graphics.Vulkan/HelperShader.cs @@ -4,6 +4,7 @@ using Ryujinx.Graphics.Shader.Translation; using Ryujinx.Graphics.Vulkan.Shaders; using Silk.NET.Vulkan; using System; +using System.Collections.Generic; using VkFormat = Silk.NET.Vulkan.Format; namespace Ryujinx.Graphics.Vulkan @@ -399,6 +400,86 @@ namespace Ryujinx.Graphics.Vulkan newSize); } + public unsafe void ConvertIndexBuffer(VulkanRenderer gd, + CommandBufferScoped cbs, + BufferHolder src, + BufferHolder dst, + IndexBufferPattern pattern, + int indexSize, + int srcOffset, + int indexCount) + { + int convertedCount = pattern.GetConvertedCount(indexCount); + int outputIndexSize = 4; + + // TODO: Do this with a compute shader? + var srcBuffer = src.GetBuffer().Get(cbs, srcOffset, indexCount * indexSize).Value; + var dstBuffer = dst.GetBuffer().Get(cbs, 0, convertedCount * outputIndexSize).Value; + + gd.Api.CmdFillBuffer(cbs.CommandBuffer, dstBuffer, 0, Vk.WholeSize, 0); + + var bufferCopy = new List(); + int outputOffset = 0; + + // Try to merge copies of adjacent indices to reduce copy count. + int sequenceStart = 0; + int sequenceLength = 0; + + foreach (var index in pattern.GetIndexMapping(indexCount)) + { + if (sequenceLength > 0) + { + if (index == sequenceStart + sequenceLength && indexSize == outputIndexSize) + { + sequenceLength++; + continue; + } + + // Commit the copy so far. + bufferCopy.Add(new BufferCopy((ulong)(srcOffset + sequenceStart * indexSize), (ulong)outputOffset, (ulong)(indexSize * sequenceLength))); + outputOffset += outputIndexSize * sequenceLength; + } + + sequenceStart = index; + sequenceLength = 1; + } + + if (sequenceLength > 0) + { + // Commit final pending copy. + bufferCopy.Add(new BufferCopy((ulong)(srcOffset + sequenceStart * indexSize), (ulong)outputOffset, (ulong)(indexSize * sequenceLength))); + } + + var bufferCopyArray = bufferCopy.ToArray(); + + BufferHolder.InsertBufferBarrier( + gd, + cbs.CommandBuffer, + dstBuffer, + BufferHolder.DefaultAccessFlags, + AccessFlags.AccessTransferWriteBit, + PipelineStageFlags.PipelineStageAllCommandsBit, + PipelineStageFlags.PipelineStageTransferBit, + 0, + convertedCount * outputIndexSize); + + fixed (BufferCopy* pBufferCopy = bufferCopyArray) + { + gd.Api.CmdCopyBuffer(cbs.CommandBuffer, srcBuffer, dstBuffer, (uint)bufferCopyArray.Length, pBufferCopy); + } + + BufferHolder.InsertBufferBarrier( + gd, + cbs.CommandBuffer, + dstBuffer, + AccessFlags.AccessTransferWriteBit, + BufferHolder.DefaultAccessFlags, + PipelineStageFlags.PipelineStageTransferBit, + PipelineStageFlags.PipelineStageAllCommandsBit, + 0, + convertedCount * outputIndexSize); + } + protected virtual void Dispose(bool disposing) { if (disposing) -- cgit v1.2.3