Compare commits

...

4 commits

Author SHA1 Message Date
Keaton
9dd5eec2b8 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-28 21:29:59 +00:00
Hack茶ん
1e6b2ea9ca Update Korean translation 2025-03-28 10:01:12 +00: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 39 additions and 73 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 srcBuffer = src.GetBuffer().Get(cbs, srcOffset, indexCount * indexSize).Value; Buffer dstBuffer = dstIndexBuffer.GetBuffer().Get(cbs, 0, convertedCount * outputIndexSize).Value;
Buffer dstBuffer = dst.GetBuffer().Get(cbs, 0, convertedCount * outputIndexSize).Value;
gd.Api.CmdFillBuffer(cbs.CommandBuffer, dstBuffer, 0, Vk.WholeSize, 0); const int ParamsBufferSize = 16 * sizeof(int);
List<BufferCopy> bufferCopy = []; Span<int> shaderParams = stackalloc int[ParamsBufferSize / sizeof(int)];
int outputOffset = 0;
// Try to merge copies of adjacent indices to reduce copy count. shaderParams[8] = pattern.PrimitiveVertices;
int sequenceStart = 0; shaderParams[9] = pattern.PrimitiveVerticesOut;
int sequenceLength = 0; shaderParams[10] = indexSize;
shaderParams[11] = outputIndexSize;
shaderParams[12] = pattern.BaseIndex;
shaderParams[13] = pattern.IndexStride;
shaderParams[14] = srcOffset;
shaderParams[15] = primitiveCount;
foreach (int index in pattern.GetIndexMapping(indexCount)) pattern.OffsetIndex.CopyTo(shaderParams[..pattern.OffsetIndex.Length]);
{
if (sequenceLength > 0)
{
if (index == sequenceStart + sequenceLength && indexSize == outputIndexSize)
{
sequenceLength++;
continue;
}
// Commit the copy so far. using var patternScoped = gd.BufferManager.ReserveOrCreate(gd, cbs, ParamsBufferSize);
bufferCopy.Add(new BufferCopy((ulong)(srcOffset + sequenceStart * indexSize), (ulong)outputOffset, (ulong)(indexSize * sequenceLength))); var patternBuffer = patternScoped.Holder;
outputOffset += outputIndexSize * sequenceLength;
}
sequenceStart = index; patternBuffer.SetDataUnchecked<int>(patternScoped.Offset, shaderParams);
sequenceLength = 1;
}
if (sequenceLength > 0) _pipeline.SetCommandBuffer(cbs);
{
// 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

@ -4934,7 +4934,7 @@
"he_IL": "", "he_IL": "",
"it_IT": "", "it_IT": "",
"ja_JP": "", "ja_JP": "",
"ko_KR": "", "ko_KR": "터보 모드 배수 :",
"no_NO": "Multiplikator i turbomodus:", "no_NO": "Multiplikator i turbomodus:",
"pl_PL": "", "pl_PL": "",
"pt_BR": "", "pt_BR": "",
@ -4959,7 +4959,7 @@
"he_IL": "", "he_IL": "",
"it_IT": "", "it_IT": "",
"ja_JP": "", "ja_JP": "",
"ko_KR": "", "ko_KR": "터보 모드 배수 목표 값입니다.\n\n모르면 200으로 두세요.",
"no_NO": "Målverdien for multiplikatoren i turbomodus. \n\nLa syå på 200 hvis du er usikker.", "no_NO": "Målverdien for multiplikatoren i turbomodus. \n\nLa syå på 200 hvis du er usikker.",
"pl_PL": "", "pl_PL": "",
"pt_BR": "", "pt_BR": "",
@ -4984,7 +4984,7 @@
"he_IL": "", "he_IL": "",
"it_IT": "", "it_IT": "",
"ja_JP": "", "ja_JP": "",
"ko_KR": "", "ko_KR": "터보 모드는 게임이 프레임 속도에 민감하지 않을 때 효과적으로 속도를 높이거나 낮추는 에뮬레이터 기능입니다.\n이 기능은 Ryujinx 키보드 단축키 설정에서 구성할 수 있는 단축키를 사용하여 게임 내에서 전환할 수 있습니다.\n\n모르면 200으로 두세요.",
"no_NO": "Turbo-modus er en emulatorfunksjon som effektivt øker eller senker hastigheten når et spill ikke er følsom for bildefrekvens.\nDu kan slå på denne funksjonen i spillet med en hurtigtast, som kan konfigureres i Ryujinx Keyboard Hotkeys-innstillingene.\n\nLa den stå på 200 hvis du er usikker.", "no_NO": "Turbo-modus er en emulatorfunksjon som effektivt øker eller senker hastigheten når et spill ikke er følsom for bildefrekvens.\nDu kan slå på denne funksjonen i spillet med en hurtigtast, som kan konfigureres i Ryujinx Keyboard Hotkeys-innstillingene.\n\nLa den stå på 200 hvis du er usikker.",
"pl_PL": "", "pl_PL": "",
"pt_BR": "", "pt_BR": "",
@ -18184,7 +18184,7 @@
"he_IL": "", "he_IL": "",
"it_IT": "", "it_IT": "",
"ja_JP": "", "ja_JP": "",
"ko_KR": "", "ko_KR": "{0}FPS({1}밀리초)",
"no_NO": "", "no_NO": "",
"pl_PL": "", "pl_PL": "",
"pt_BR": "", "pt_BR": "",
@ -18209,7 +18209,7 @@
"he_IL": "", "he_IL": "",
"it_IT": "", "it_IT": "",
"ja_JP": "", "ja_JP": "",
"ko_KR": "", "ko_KR": "{0}FPS({1}밀리초), ({2}%) 터보",
"no_NO": "", "no_NO": "",
"pl_PL": "", "pl_PL": "",
"pt_BR": "", "pt_BR": "",
@ -23959,7 +23959,7 @@
"he_IL": "", "he_IL": "",
"it_IT": "", "it_IT": "",
"ja_JP": "", "ja_JP": "",
"ko_KR": "", "ko_KR": "터보 모드 :",
"no_NO": "", "no_NO": "",
"pl_PL": "", "pl_PL": "",
"pt_BR": "", "pt_BR": "",
@ -23984,7 +23984,7 @@
"he_IL": "", "he_IL": "",
"it_IT": "", "it_IT": "",
"ja_JP": "", "ja_JP": "",
"ko_KR": "", "ko_KR": "터보 모드 단축키입니다.\nRyujinx CPU 설정에서 터보 모드의 동작을 구성합니다.\n\n모르면 바인딩 해제 상태로 두세요.",
"no_NO": "Hurtigtasten for turbo-modus.\nKonfigurer oppførselen til turbo-modus i Ryujinx CPU-innstillinger.\n\nLa være ubundet hvis du er usikker.", "no_NO": "Hurtigtasten for turbo-modus.\nKonfigurer oppførselen til turbo-modus i Ryujinx CPU-innstillinger.\n\nLa være ubundet hvis du er usikker.",
"pl_PL": "", "pl_PL": "",
"pt_BR": "", "pt_BR": "",
@ -24009,7 +24009,7 @@
"he_IL": "", "he_IL": "",
"it_IT": "", "it_IT": "",
"ja_JP": "", "ja_JP": "",
"ko_KR": "", "ko_KR": "누르고 있는 동안만",
"no_NO": "Bare mens du trykker på", "no_NO": "Bare mens du trykker på",
"pl_PL": "", "pl_PL": "",
"pt_BR": "", "pt_BR": "",
@ -24209,7 +24209,7 @@
"he_IL": "", "he_IL": "",
"it_IT": "", "it_IT": "",
"ja_JP": "", "ja_JP": "",
"ko_KR": "플레이 가능", "ko_KR": "원활",
"no_NO": "Spillbar", "no_NO": "Spillbar",
"pl_PL": "", "pl_PL": "",
"pt_BR": "Jogável", "pt_BR": "Jogável",
@ -24234,7 +24234,7 @@
"he_IL": "", "he_IL": "",
"it_IT": "", "it_IT": "",
"ja_JP": "", "ja_JP": "",
"ko_KR": "게임 내", "ko_KR": "가능",
"no_NO": "", "no_NO": "",
"pl_PL": "", "pl_PL": "",
"pt_BR": "No jogo", "pt_BR": "No jogo",
@ -24284,7 +24284,7 @@
"he_IL": "", "he_IL": "",
"it_IT": "", "it_IT": "",
"ja_JP": "", "ja_JP": "",
"ko_KR": "부", "ko_KR": "부",
"no_NO": "Starter", "no_NO": "Starter",
"pl_PL": "", "pl_PL": "",
"pt_BR": "Inicializa", "pt_BR": "Inicializa",
@ -24309,7 +24309,7 @@
"he_IL": "", "he_IL": "",
"it_IT": "", "it_IT": "",
"ja_JP": "", "ja_JP": "",
"ko_KR": "없음", "ko_KR": "불가능",
"no_NO": "Ingenting", "no_NO": "Ingenting",
"pl_PL": "", "pl_PL": "",
"pt_BR": "Nada", "pt_BR": "Nada",