aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorriperiperi <rhy3756547@hotmail.com>2023-09-02 21:58:15 +0100
committerGitHub <noreply@github.com>2023-09-02 17:58:15 -0300
commit93cd327873bed829c3a0aad938cb8d2cca2ff806 (patch)
treef1ee059c8008370c70917615eb853008096c942e
parent12cbacffca7b04a7f377e8fdf09ce78445351913 (diff)
Vulkan: Device Local and higher invocation count for buffer conversions (#5623)1.1.1005
Just some simple changes to the buffer conversion shaders. (stride conversion, D32S8 to D24S8) The first change is using a device local buffer for converted vertex buffers, since they're only read/written on the GPU. These paths don't trigger on NVIDIA, but if you force them to use it demonstrates the full extent writing to host owned memory from compute absolutely destroys them. AMD GPUs are less heavily affected by this issue, but since the game in question was writing 230MB from compute, I imagine it should have some effect. The second change is allowing the buffer conversion shaders to scale their work group count. While dividing the work between 32 invocations works OK for M1 macs, it's not so great for anything with more cores like AMD GPUs, which should be able to do a lot more parallel copies. Now, it scales by roughly 100 elements per invocation. Some stride change cases could be improved further by either limiting vertex buffer size somehow (reading the index buffer could help, but is always risky) or only updating regions that changed, rather than invalidating the whole thing.
-rw-r--r--src/Ryujinx.Graphics.Vulkan/BufferHolder.cs6
-rw-r--r--src/Ryujinx.Graphics.Vulkan/HelperShader.cs6
-rw-r--r--src/Ryujinx.Graphics.Vulkan/Shaders/ChangeBufferStrideShaderSource.comp4
-rw-r--r--src/Ryujinx.Graphics.Vulkan/Shaders/ConvertD32S8ToD24S8ShaderSource.comp4
-rw-r--r--src/Ryujinx.Graphics.Vulkan/Shaders/SpirvBinaries/ChangeBufferStride.spvbin3812 -> 3932 bytes
-rw-r--r--src/Ryujinx.Graphics.Vulkan/Shaders/SpirvBinaries/ConvertD32S8ToD24S8.spvbin3236 -> 3356 bytes
6 files changed, 10 insertions, 10 deletions
diff --git a/src/Ryujinx.Graphics.Vulkan/BufferHolder.cs b/src/Ryujinx.Graphics.Vulkan/BufferHolder.cs
index c767a57a..a93ced0e 100644
--- a/src/Ryujinx.Graphics.Vulkan/BufferHolder.cs
+++ b/src/Ryujinx.Graphics.Vulkan/BufferHolder.cs
@@ -967,7 +967,7 @@ namespace Ryujinx.Graphics.Vulkan
if (!_cachedConvertedBuffers.TryGetValue(offset, size, key, out var holder))
{
- holder = _gd.BufferManager.Create(_gd, (size * 2 + 3) & ~3);
+ holder = _gd.BufferManager.Create(_gd, (size * 2 + 3) & ~3, baseType: BufferAllocationType.DeviceLocal);
_gd.PipelineInternal.EndRenderPass();
_gd.HelperShader.ConvertI8ToI16(_gd, cbs, this, holder, offset, size);
@@ -993,7 +993,7 @@ namespace Ryujinx.Graphics.Vulkan
{
int alignedStride = (stride + (alignment - 1)) & -alignment;
- holder = _gd.BufferManager.Create(_gd, (size / stride) * alignedStride);
+ holder = _gd.BufferManager.Create(_gd, (size / stride) * alignedStride, baseType: BufferAllocationType.DeviceLocal);
_gd.PipelineInternal.EndRenderPass();
_gd.HelperShader.ChangeStride(_gd, cbs, this, holder, offset, size, stride, alignedStride);
@@ -1023,7 +1023,7 @@ namespace Ryujinx.Graphics.Vulkan
int convertedCount = pattern.GetConvertedCount(indexCount);
- holder = _gd.BufferManager.Create(_gd, convertedCount * 4);
+ holder = _gd.BufferManager.Create(_gd, convertedCount * 4, baseType: BufferAllocationType.DeviceLocal);
_gd.PipelineInternal.EndRenderPass();
_gd.HelperShader.ConvertIndexBuffer(_gd, cbs, this, holder, pattern, indexSize, offset, indexCount);
diff --git a/src/Ryujinx.Graphics.Vulkan/HelperShader.cs b/src/Ryujinx.Graphics.Vulkan/HelperShader.cs
index a6d23764..5be4a932 100644
--- a/src/Ryujinx.Graphics.Vulkan/HelperShader.cs
+++ b/src/Ryujinx.Graphics.Vulkan/HelperShader.cs
@@ -5,7 +5,6 @@ using Ryujinx.Graphics.Shader.Translation;
using Silk.NET.Vulkan;
using System;
using System.Collections.Generic;
-using System.IO;
using System.Numerics;
using CompareOp = Ryujinx.Graphics.GAL.CompareOp;
using Format = Ryujinx.Graphics.GAL.Format;
@@ -27,6 +26,7 @@ namespace Ryujinx.Graphics.Vulkan
class HelperShader : IDisposable
{
private const int UniformBufferAlignment = 256;
+ private const int ConvertElementsPerWorkgroup = 32 * 100; // Work group size of 32 times 100 elements.
private const string ShaderBinariesPath = "Ryujinx.Graphics.Vulkan/Shaders/SpirvBinaries";
private readonly PipelineHelperShader _pipeline;
@@ -894,7 +894,7 @@ namespace Ryujinx.Graphics.Vulkan
_pipeline.SetStorageBuffers(1, sbRanges);
_pipeline.SetProgram(_programStrideChange);
- _pipeline.DispatchCompute(1, 1, 1);
+ _pipeline.DispatchCompute(1 + elems / ConvertElementsPerWorkgroup, 1, 1);
gd.BufferManager.Delete(bufferHandle);
@@ -1742,7 +1742,7 @@ namespace Ryujinx.Graphics.Vulkan
_pipeline.SetStorageBuffers(1, sbRanges);
_pipeline.SetProgram(_programConvertD32S8ToD24S8);
- _pipeline.DispatchCompute(1, 1, 1);
+ _pipeline.DispatchCompute(1 + inSize / ConvertElementsPerWorkgroup, 1, 1);
gd.BufferManager.Delete(bufferHandle);
diff --git a/src/Ryujinx.Graphics.Vulkan/Shaders/ChangeBufferStrideShaderSource.comp b/src/Ryujinx.Graphics.Vulkan/Shaders/ChangeBufferStrideShaderSource.comp
index 081fc119..4deba30d 100644
--- a/src/Ryujinx.Graphics.Vulkan/Shaders/ChangeBufferStrideShaderSource.comp
+++ b/src/Ryujinx.Graphics.Vulkan/Shaders/ChangeBufferStrideShaderSource.comp
@@ -29,7 +29,7 @@ void main()
int sourceOffset = stride_arguments_data.w;
int strideRemainder = targetStride - sourceStride;
- int invocations = int(gl_WorkGroupSize.x);
+ int invocations = int(gl_WorkGroupSize.x * gl_NumWorkGroups.x);
int copiesRequired = bufferSize / sourceStride;
@@ -39,7 +39,7 @@ void main()
int allInvocationCopies = copiesRequired / invocations;
// - Extra remainder copy that this invocation performs.
- int index = int(gl_LocalInvocationID.x);
+ int index = int(gl_GlobalInvocationID.x);
int extra = (index < (copiesRequired % invocations)) ? 1 : 0;
int copyCount = allInvocationCopies + extra;
diff --git a/src/Ryujinx.Graphics.Vulkan/Shaders/ConvertD32S8ToD24S8ShaderSource.comp b/src/Ryujinx.Graphics.Vulkan/Shaders/ConvertD32S8ToD24S8ShaderSource.comp
index d3a74b1c..96cbdebb 100644
--- a/src/Ryujinx.Graphics.Vulkan/Shaders/ConvertD32S8ToD24S8ShaderSource.comp
+++ b/src/Ryujinx.Graphics.Vulkan/Shaders/ConvertD32S8ToD24S8ShaderSource.comp
@@ -23,7 +23,7 @@ layout (std430, set = 1, binding = 2) buffer out_s
void main()
{
// Determine what slice of the stride copies this invocation will perform.
- int invocations = int(gl_WorkGroupSize.x);
+ int invocations = int(gl_WorkGroupSize.x * gl_NumWorkGroups.x);
int copiesRequired = pixelCount;
@@ -33,7 +33,7 @@ void main()
int allInvocationCopies = copiesRequired / invocations;
// - Extra remainder copy that this invocation performs.
- int index = int(gl_LocalInvocationID.x);
+ int index = int(gl_GlobalInvocationID.x);
int extra = (index < (copiesRequired % invocations)) ? 1 : 0;
int copyCount = allInvocationCopies + extra;
diff --git a/src/Ryujinx.Graphics.Vulkan/Shaders/SpirvBinaries/ChangeBufferStride.spv b/src/Ryujinx.Graphics.Vulkan/Shaders/SpirvBinaries/ChangeBufferStride.spv
index 49e7d23f..1e0d8810 100644
--- a/src/Ryujinx.Graphics.Vulkan/Shaders/SpirvBinaries/ChangeBufferStride.spv
+++ b/src/Ryujinx.Graphics.Vulkan/Shaders/SpirvBinaries/ChangeBufferStride.spv
Binary files differ
diff --git a/src/Ryujinx.Graphics.Vulkan/Shaders/SpirvBinaries/ConvertD32S8ToD24S8.spv b/src/Ryujinx.Graphics.Vulkan/Shaders/SpirvBinaries/ConvertD32S8ToD24S8.spv
index fb543e44..d8e19ff6 100644
--- a/src/Ryujinx.Graphics.Vulkan/Shaders/SpirvBinaries/ConvertD32S8ToD24S8.spv
+++ b/src/Ryujinx.Graphics.Vulkan/Shaders/SpirvBinaries/ConvertD32S8ToD24S8.spv
Binary files differ