Compare commits

...

4 commits

Author SHA1 Message Date
Keaton
5d005b5785 Merge branch 'feature/vulkan-index-buff-compute' into 'master'
Vulkan: Use compute shader for non-indirect unsupported topology index buffer conversions

See merge request ryubing/ryujinx!15
2025-03-29 20:31:11 -05:00
Yeager
5d8451b41a Update Swedish in locales.json 2025-03-29 20:22:23 -05:00
Isaac Marovitz
6b51cd01a9 Fix >16 primitives 2025-03-27 18:23:15 -05:00
Isaac Marovitz
c32e8e1a57 Use compute shader for non indirect index buffer conversion 2025-03-27 18:23:15 -05:00
3 changed files with 37 additions and 71 deletions

View file

@ -874,57 +874,42 @@ namespace Ryujinx.Graphics.Vulkan
public unsafe void ConvertIndexBuffer(VulkanRenderer gd, public unsafe void ConvertIndexBuffer(VulkanRenderer gd,
CommandBufferScoped cbs, CommandBufferScoped cbs,
BufferHolder src, BufferHolder srcIndexBuffer,
BufferHolder dst, BufferHolder dstIndexBuffer,
IndexBufferPattern pattern, IndexBufferPattern pattern,
int indexSize, int indexSize,
int srcOffset, int srcOffset,
int indexCount) int indexCount)
{ {
// TODO: Support conversion with primitive restart enabled. // TODO: Support conversion with primitive restart enabled.
// TODO: Convert with a compute shader?
int primitiveCount = pattern.GetPrimitiveCount(indexCount);
int convertedCount = pattern.GetConvertedCount(indexCount); int convertedCount = pattern.GetConvertedCount(indexCount);
int outputIndexSize = 4; int outputIndexSize = 4;
Buffer dstBuffer = dstIndexBuffer.GetBuffer().Get(cbs, 0, convertedCount * outputIndexSize).Value;
Buffer srcBuffer = src.GetBuffer().Get(cbs, srcOffset, indexCount * indexSize).Value; const int ParamsBufferSize = 16 * sizeof(int);
Buffer dstBuffer = dst.GetBuffer().Get(cbs, 0, convertedCount * outputIndexSize).Value;
gd.Api.CmdFillBuffer(cbs.CommandBuffer, dstBuffer, 0, Vk.WholeSize, 0); Span<int> shaderParams = stackalloc int[ParamsBufferSize / sizeof(int)];
List<BufferCopy> bufferCopy = []; shaderParams[8] = pattern.PrimitiveVertices;
int outputOffset = 0; shaderParams[9] = pattern.PrimitiveVerticesOut;
shaderParams[10] = indexSize;
shaderParams[11] = outputIndexSize;
shaderParams[12] = pattern.BaseIndex;
shaderParams[13] = pattern.IndexStride;
shaderParams[14] = srcOffset;
shaderParams[15] = primitiveCount;
// Try to merge copies of adjacent indices to reduce copy count. pattern.OffsetIndex.CopyTo(shaderParams[..pattern.OffsetIndex.Length]);
int sequenceStart = 0;
int sequenceLength = 0;
foreach (int index in pattern.GetIndexMapping(indexCount)) using var patternScoped = gd.BufferManager.ReserveOrCreate(gd, cbs, ParamsBufferSize);
{ var patternBuffer = patternScoped.Holder;
if (sequenceLength > 0)
{
if (index == sequenceStart + sequenceLength && indexSize == outputIndexSize)
{
sequenceLength++;
continue;
}
// Commit the copy so far. patternBuffer.SetDataUnchecked<int>(patternScoped.Offset, shaderParams);
bufferCopy.Add(new BufferCopy((ulong)(srcOffset + sequenceStart * indexSize), (ulong)outputOffset, (ulong)(indexSize * sequenceLength)));
outputOffset += outputIndexSize * sequenceLength;
}
sequenceStart = index; _pipeline.SetCommandBuffer(cbs);
sequenceLength = 1;
}
if (sequenceLength > 0)
{
// Commit final pending copy.
bufferCopy.Add(new BufferCopy((ulong)(srcOffset + sequenceStart * indexSize), (ulong)outputOffset, (ulong)(indexSize * sequenceLength)));
}
BufferCopy[] bufferCopyArray = bufferCopy.ToArray();
BufferHolder.InsertBufferBarrier( BufferHolder.InsertBufferBarrier(
gd, gd,
@ -937,10 +922,11 @@ namespace Ryujinx.Graphics.Vulkan
0, 0,
convertedCount * outputIndexSize); convertedCount * outputIndexSize);
fixed (BufferCopy* pBufferCopy = bufferCopyArray) _pipeline.SetUniformBuffers([new BufferAssignment(0, new BufferRange(patternScoped.Handle, patternScoped.Offset, ParamsBufferSize))]);
{ _pipeline.SetStorageBuffers(1, new[] { srcIndexBuffer.GetBuffer(), dstIndexBuffer.GetBuffer() });
gd.Api.CmdCopyBuffer(cbs.CommandBuffer, srcBuffer, dstBuffer, (uint)bufferCopyArray.Length, pBufferCopy);
} _pipeline.SetProgram(_programConvertIndexBuffer);
_pipeline.DispatchCompute(BitUtils.DivRoundUp(primitiveCount, 16), 1, 1);
BufferHolder.InsertBufferBarrier( BufferHolder.InsertBufferBarrier(
gd, gd,
@ -952,6 +938,8 @@ namespace Ryujinx.Graphics.Vulkan
PipelineStageFlags.AllCommandsBit, PipelineStageFlags.AllCommandsBit,
0, 0,
convertedCount * outputIndexSize); convertedCount * outputIndexSize);
_pipeline.Finish(gd, cbs);
} }
public void CopyIncompatibleFormats( public void CopyIncompatibleFormats(

View file

@ -47,28 +47,6 @@ namespace Ryujinx.Graphics.Vulkan
return primitiveCount * OffsetIndex.Length; return primitiveCount * OffsetIndex.Length;
} }
public IEnumerable<int> GetIndexMapping(int indexCount)
{
int primitiveCount = GetPrimitiveCount(indexCount);
int index = BaseIndex;
for (int i = 0; i < primitiveCount; i++)
{
if (RepeatStart)
{
// Used for triangle fan
yield return 0;
}
for (int j = RepeatStart ? 1 : 0; j < OffsetIndex.Length; j++)
{
yield return index + OffsetIndex[j];
}
index += IndexStride;
}
}
public BufferHandle GetRepeatingBuffer(int vertexCount, out int indexCount) public BufferHandle GetRepeatingBuffer(int vertexCount, out int indexCount)
{ {
int primitiveCount = GetPrimitiveCount(vertexCount); int primitiveCount = GetPrimitiveCount(vertexCount);

View file

@ -4939,7 +4939,7 @@
"pl_PL": "", "pl_PL": "",
"pt_BR": "", "pt_BR": "",
"ru_RU": "", "ru_RU": "",
"sv_SE": "", "sv_SE": "Multiplikator för turboläge:",
"th_TH": "", "th_TH": "",
"tr_TR": "", "tr_TR": "",
"uk_UA": "", "uk_UA": "",
@ -4964,7 +4964,7 @@
"pl_PL": "", "pl_PL": "",
"pt_BR": "", "pt_BR": "",
"ru_RU": "", "ru_RU": "",
"sv_SE": "", "sv_SE": "Målvärdet för multiplikatorn i turboläget. \n\nLämna den på 200 om du är osäker.",
"th_TH": "", "th_TH": "",
"tr_TR": "", "tr_TR": "",
"uk_UA": "", "uk_UA": "",
@ -4989,7 +4989,7 @@
"pl_PL": "", "pl_PL": "",
"pt_BR": "", "pt_BR": "",
"ru_RU": "", "ru_RU": "",
"sv_SE": "", "sv_SE": "Turboläget är en emulatorfunktion som effektivt ökar eller sänker hastigheten när ett spel inte är känsligt för bildfrekvens.\nDu kan växla denna funktion i spelet med en snabbtangent, konfigurerbar i Ryujinx inställningar för snabbtangenter.\n\nLämna den på 200 om du är osäker.",
"th_TH": "", "th_TH": "",
"tr_TR": "", "tr_TR": "",
"uk_UA": "", "uk_UA": "",
@ -10014,7 +10014,7 @@
"pl_PL": "", "pl_PL": "",
"pt_BR": "", "pt_BR": "",
"ru_RU": "Enter (блок цифр)", "ru_RU": "Enter (блок цифр)",
"sv_SE": "", "sv_SE": "Enter (numerisk)",
"th_TH": "", "th_TH": "",
"tr_TR": "", "tr_TR": "",
"uk_UA": "Enter (цифровий блок)", "uk_UA": "Enter (цифровий блок)",
@ -11064,7 +11064,7 @@
"pl_PL": "", "pl_PL": "",
"pt_BR": "", "pt_BR": "",
"ru_RU": "Тачпад", "ru_RU": "Тачпад",
"sv_SE": "", "sv_SE": "Pekplatta",
"th_TH": "", "th_TH": "",
"tr_TR": "", "tr_TR": "",
"uk_UA": "Сенсорна панель", "uk_UA": "Сенсорна панель",
@ -18189,7 +18189,7 @@
"pl_PL": "", "pl_PL": "",
"pt_BR": "", "pt_BR": "",
"ru_RU": "", "ru_RU": "",
"sv_SE": "", "sv_SE": "{0} bilder/s ({1}ms)",
"th_TH": "", "th_TH": "",
"tr_TR": "", "tr_TR": "",
"uk_UA": "", "uk_UA": "",
@ -18214,7 +18214,7 @@
"pl_PL": "", "pl_PL": "",
"pt_BR": "", "pt_BR": "",
"ru_RU": "", "ru_RU": "",
"sv_SE": "", "sv_SE": "{0} bilder/s ({1}ms), Turbo ({2}%)",
"th_TH": "", "th_TH": "",
"tr_TR": "", "tr_TR": "",
"uk_UA": "", "uk_UA": "",
@ -23964,7 +23964,7 @@
"pl_PL": "", "pl_PL": "",
"pt_BR": "", "pt_BR": "",
"ru_RU": "", "ru_RU": "",
"sv_SE": "", "sv_SE": "Turboläge:",
"th_TH": "", "th_TH": "",
"tr_TR": "", "tr_TR": "",
"uk_UA": "", "uk_UA": "",
@ -23989,7 +23989,7 @@
"pl_PL": "", "pl_PL": "",
"pt_BR": "", "pt_BR": "",
"ru_RU": "", "ru_RU": "",
"sv_SE": "", "sv_SE": "Snabbtangenten för turboläge.\nKonfigurera beteendet för turboläge i Ryujinx CPU-inställningar.\n\nLämna Obunden om du är osäker.",
"th_TH": "", "th_TH": "",
"tr_TR": "", "tr_TR": "",
"uk_UA": "", "uk_UA": "",
@ -24014,7 +24014,7 @@
"pl_PL": "", "pl_PL": "",
"pt_BR": "", "pt_BR": "",
"ru_RU": "", "ru_RU": "",
"sv_SE": "", "sv_SE": "Endast när du trycker ner",
"th_TH": "", "th_TH": "",
"tr_TR": "", "tr_TR": "",
"uk_UA": "", "uk_UA": "",