From fd2e53fdc6d831e898e1095052d340259142dbfb Mon Sep 17 00:00:00 2001 From: gdk Date: Tue, 12 Apr 2022 17:28:04 -0300 Subject: [PATCH] Raise textures limit to 64 on Vulkan --- Ryujinx.Common/Memory/StructArrayHelpers.cs | 11 +++++++++++ Ryujinx.Graphics.GAL/Capabilities.cs | 13 +++++++++++++ .../Shader/GpuAccessorBase.cs | 19 +++++++++++++++---- Ryujinx.Graphics.OpenGL/Pipeline.cs | 2 +- Ryujinx.Graphics.OpenGL/Renderer.cs | 4 ++++ Ryujinx.Graphics.Shader/SupportBuffer.cs | 8 ++++---- Ryujinx.Graphics.Vulkan/Constants.cs | 2 +- Ryujinx.Graphics.Vulkan/HelperShader.cs | 11 +++++------ Ryujinx.Graphics.Vulkan/PipelineBase.cs | 2 +- .../VulkanGraphicsDevice.cs | 4 ++++ 10 files changed, 59 insertions(+), 17 deletions(-) diff --git a/Ryujinx.Common/Memory/StructArrayHelpers.cs b/Ryujinx.Common/Memory/StructArrayHelpers.cs index fbb2902d5..bba05c10b 100644 --- a/Ryujinx.Common/Memory/StructArrayHelpers.cs +++ b/Ryujinx.Common/Memory/StructArrayHelpers.cs @@ -640,4 +640,15 @@ namespace Ryujinx.Common.Memory public ref T this[int index] => ref ToSpan()[index]; public Span ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 64); } + public struct Array73 : IArray where T : unmanaged + { +#pragma warning disable CS0169 + T _e0; + Array64 _other; + Array8 _other2; +#pragma warning restore CS0169 + public int Length => 73; + public ref T this[int index] => ref ToSpan()[index]; + public Span ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 73); + } } diff --git a/Ryujinx.Graphics.GAL/Capabilities.cs b/Ryujinx.Graphics.GAL/Capabilities.cs index af8541fb8..33c828d19 100644 --- a/Ryujinx.Graphics.GAL/Capabilities.cs +++ b/Ryujinx.Graphics.GAL/Capabilities.cs @@ -24,6 +24,11 @@ namespace Ryujinx.Graphics.GAL public readonly bool SupportsViewportSwizzle; public readonly bool SupportsIndirectParameters; + public readonly uint MaximumUniformBuffersPerStage; + public readonly uint MaximumStorageBuffersPerStage; + public readonly uint MaximumTexturesPerStage; + public readonly uint MaximumImagesPerStage; + public readonly int MaximumComputeSharedMemorySize; public readonly float MaximumSupportedAnisotropy; public readonly int StorageBufferOffsetAlignment; @@ -46,6 +51,10 @@ namespace Ryujinx.Graphics.GAL bool supportsTextureShadowLod, bool supportsViewportSwizzle, bool supportsIndirectParameters, + uint maximumUniformBuffersPerStage, + uint maximumStorageBuffersPerStage, + uint maximumTexturesPerStage, + uint maximumImagesPerStage, int maximumComputeSharedMemorySize, float maximumSupportedAnisotropy, int storageBufferOffsetAlignment) @@ -67,6 +76,10 @@ namespace Ryujinx.Graphics.GAL SupportsTextureShadowLod = supportsTextureShadowLod; SupportsViewportSwizzle = supportsViewportSwizzle; SupportsIndirectParameters = supportsIndirectParameters; + MaximumUniformBuffersPerStage = maximumUniformBuffersPerStage; + MaximumStorageBuffersPerStage = maximumStorageBuffersPerStage; + MaximumTexturesPerStage = maximumTexturesPerStage; + MaximumImagesPerStage = maximumImagesPerStage; MaximumComputeSharedMemorySize = maximumComputeSharedMemorySize; MaximumSupportedAnisotropy = maximumSupportedAnisotropy; StorageBufferOffsetAlignment = storageBufferOffsetAlignment; diff --git a/Ryujinx.Graphics.Gpu/Shader/GpuAccessorBase.cs b/Ryujinx.Graphics.Gpu/Shader/GpuAccessorBase.cs index 3da678fe3..7cf7b6e99 100644 --- a/Ryujinx.Graphics.Gpu/Shader/GpuAccessorBase.cs +++ b/Ryujinx.Graphics.Gpu/Shader/GpuAccessorBase.cs @@ -1,3 +1,4 @@ +using Ryujinx.Common.Logging; using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.Gpu.Engine.Threed; using Ryujinx.Graphics.Gpu.Image; @@ -31,7 +32,7 @@ namespace Ryujinx.Graphics.Gpu.Shader { if (_context.Capabilities.Api == TargetApi.Vulkan) { - return 1 + GetStageIndex() * 18 + index; + return 1 + GetBindingFromIndex(index, _context.Capabilities.MaximumUniformBuffersPerStage, "Uniform buffer"); } else { @@ -44,7 +45,7 @@ namespace Ryujinx.Graphics.Gpu.Shader { if (_context.Capabilities.Api == TargetApi.Vulkan) { - return GetStageIndex() * 16 + index; + return GetBindingFromIndex(index, _context.Capabilities.MaximumStorageBuffersPerStage, "Storage buffer"); } else { @@ -57,7 +58,7 @@ namespace Ryujinx.Graphics.Gpu.Shader { if (_context.Capabilities.Api == TargetApi.Vulkan) { - return GetStageIndex() * 32 + index; + return GetBindingFromIndex(index, _context.Capabilities.MaximumTexturesPerStage, "Texture"); } else { @@ -70,7 +71,7 @@ namespace Ryujinx.Graphics.Gpu.Shader { if (_context.Capabilities.Api == TargetApi.Vulkan) { - return GetStageIndex() * 8 + index; + return GetBindingFromIndex(index, _context.Capabilities.MaximumImagesPerStage, "Image"); } else { @@ -78,6 +79,16 @@ namespace Ryujinx.Graphics.Gpu.Shader } } + private int GetBindingFromIndex(int index, uint maxPerStage, string resourceName) + { + if ((uint)index >= maxPerStage) + { + Logger.Error?.Print(LogClass.Gpu, $"{resourceName} index {index} exceeds per stage limit of {maxPerStage}."); + } + + return GetStageIndex() * (int)maxPerStage + index; + } + private int GetStageIndex() { // This is just a simple remapping to ensure that most frequently used shader stages diff --git a/Ryujinx.Graphics.OpenGL/Pipeline.cs b/Ryujinx.Graphics.OpenGL/Pipeline.cs index 43711b455..40b45f37a 100644 --- a/Ryujinx.Graphics.OpenGL/Pipeline.cs +++ b/Ryujinx.Graphics.OpenGL/Pipeline.cs @@ -43,7 +43,7 @@ namespace Ryujinx.Graphics.OpenGL private CounterQueueEvent _activeConditionalRender; private Vector4[] _fpIsBgra = new Vector4[SupportBuffer.FragmentIsBgraCount]; - private Vector4[] _renderScale = new Vector4[65]; + private Vector4[] _renderScale = new Vector4[73]; private int _fragmentScaleCount; private TextureBase _unit0Texture; diff --git a/Ryujinx.Graphics.OpenGL/Renderer.cs b/Ryujinx.Graphics.OpenGL/Renderer.cs index d7ed6d004..f670fee07 100644 --- a/Ryujinx.Graphics.OpenGL/Renderer.cs +++ b/Ryujinx.Graphics.OpenGL/Renderer.cs @@ -117,6 +117,10 @@ namespace Ryujinx.Graphics.OpenGL supportsTextureShadowLod: HwCapabilities.SupportsTextureShadowLod, supportsViewportSwizzle: HwCapabilities.SupportsViewportSwizzle, supportsIndirectParameters: HwCapabilities.SupportsIndirectParameters, + maximumUniformBuffersPerStage: 13, // TODO: Avoid hardcoding those limits here and get from driver? + maximumStorageBuffersPerStage: 16, + maximumTexturesPerStage: 32, + maximumImagesPerStage: 8, maximumComputeSharedMemorySize: HwCapabilities.MaximumComputeSharedMemorySize, maximumSupportedAnisotropy: HwCapabilities.MaximumSupportedAnisotropy, storageBufferOffsetAlignment: HwCapabilities.StorageBufferOffsetAlignment); diff --git a/Ryujinx.Graphics.Shader/SupportBuffer.cs b/Ryujinx.Graphics.Shader/SupportBuffer.cs index 28a48c2ad..5fe993278 100644 --- a/Ryujinx.Graphics.Shader/SupportBuffer.cs +++ b/Ryujinx.Graphics.Shader/SupportBuffer.cs @@ -24,8 +24,8 @@ namespace Ryujinx.Graphics.Shader public static int ComputeRenderScaleOffset; public const int FragmentIsBgraCount = 8; - // One for the render target, 32 for the textures, and 8 for the images. - public const int RenderScaleMaxCount = 1 + 32 + 8; + // One for the render target, 64 for the textures, and 8 for the images. + public const int RenderScaleMaxCount = 1 + 64 + 8; private static int OffsetOf(ref SupportBuffer storage, ref T target) { @@ -52,7 +52,7 @@ namespace Ryujinx.Graphics.Shader public Vector4 ViewportInverse; public Vector4 FragmentRenderScaleCount; - // Render scale max count: 1 + 32 + 8. First scale is fragment output scale, others are textures/image inputs. - public Array41> RenderScale; + // Render scale max count: 1 + 64 + 8. First scale is fragment output scale, others are textures/image inputs. + public Array73> RenderScale; } } \ No newline at end of file diff --git a/Ryujinx.Graphics.Vulkan/Constants.cs b/Ryujinx.Graphics.Vulkan/Constants.cs index b1b540ec9..59e79a1a1 100644 --- a/Ryujinx.Graphics.Vulkan/Constants.cs +++ b/Ryujinx.Graphics.Vulkan/Constants.cs @@ -10,7 +10,7 @@ public const int MaxShaderStages = 5; public const int MaxUniformBuffersPerStage = 18; public const int MaxStorageBuffersPerStage = 16; - public const int MaxTexturesPerStage = 32; + public const int MaxTexturesPerStage = 64; public const int MaxImagesPerStage = 8; public const int MaxUniformBufferBindings = MaxUniformBuffersPerStage * MaxShaderStages; public const int MaxStorageBufferBindings = MaxStorageBuffersPerStage * MaxShaderStages; diff --git a/Ryujinx.Graphics.Vulkan/HelperShader.cs b/Ryujinx.Graphics.Vulkan/HelperShader.cs index 1df69d34c..044c9da00 100644 --- a/Ryujinx.Graphics.Vulkan/HelperShader.cs +++ b/Ryujinx.Graphics.Vulkan/HelperShader.cs @@ -31,7 +31,7 @@ void main() private const string ColorBlitFragmentShaderSource = @"#version 450 core -layout (binding = 32, set = 2) uniform sampler2D tex; +layout (binding = 64, set = 2) uniform sampler2D tex; layout (location = 0) in vec2 tex_coord; layout (location = 0) out vec4 colour; @@ -43,7 +43,7 @@ void main() private const string ColorBlitClearAlphaFragmentShaderSource = @"#version 450 core -layout (binding = 32, set = 2) uniform sampler2D tex; +layout (binding = 64, set = 2) uniform sampler2D tex; layout (location = 0) in vec2 tex_coord; layout (location = 0) out vec4 colour; @@ -83,7 +83,6 @@ void main() colour = clear_colour; }"; - private readonly PipelineHelperShader _pipeline; private readonly ISampler _samplerLinear; private readonly ISampler _samplerNearest; @@ -127,7 +126,7 @@ void main() var fragmentBindings = new ShaderBindings( Array.Empty(), Array.Empty(), - new[] { 32 }, + new[] { Constants.MaxTexturesPerStage }, Array.Empty(), Array.Empty(), Array.Empty()); @@ -191,7 +190,7 @@ void main() var sampler = linearFilter ? _samplerLinear : _samplerNearest; - _pipeline.SetTextureAndSampler(32, src, sampler); + _pipeline.SetTextureAndSampler(Constants.MaxTexturesPerStage, src, sampler); Span region = stackalloc float[RegionBufferSize / sizeof(float)]; @@ -328,7 +327,7 @@ void main() { const int RegionBufferSize = 16; - pipeline.SetTextureAndSampler(32, src, srcSampler); + pipeline.SetTextureAndSampler(Constants.MaxTexturesPerStage, src, srcSampler); Span region = stackalloc float[RegionBufferSize / sizeof(float)]; diff --git a/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/Ryujinx.Graphics.Vulkan/PipelineBase.cs index deac8e4a3..41ffe3272 100644 --- a/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -39,7 +39,7 @@ namespace Ryujinx.Graphics.Vulkan private ShaderCollection _program; - private Vector4[] _renderScale = new Vector4[65]; + private Vector4[] _renderScale = new Vector4[73]; private int _fragmentScaleCount; protected FramebufferParams FramebufferParams; diff --git a/Ryujinx.Graphics.Vulkan/VulkanGraphicsDevice.cs b/Ryujinx.Graphics.Vulkan/VulkanGraphicsDevice.cs index 66b6fa462..4153edcaf 100644 --- a/Ryujinx.Graphics.Vulkan/VulkanGraphicsDevice.cs +++ b/Ryujinx.Graphics.Vulkan/VulkanGraphicsDevice.cs @@ -318,6 +318,10 @@ namespace Ryujinx.Graphics.Vulkan supportsTextureShadowLod: false, supportsViewportSwizzle: false, supportsIndirectParameters: SupportsIndirectParameters, + maximumUniformBuffersPerStage: Constants.MaxUniformBuffersPerStage, + maximumStorageBuffersPerStage: Constants.MaxStorageBuffersPerStage, + maximumTexturesPerStage: Constants.MaxTexturesPerStage, + maximumImagesPerStage: Constants.MaxImagesPerStage, maximumComputeSharedMemorySize: (int)limits.MaxComputeSharedMemorySize, maximumSupportedAnisotropy: (int)limits.MaxSamplerAnisotropy, storageBufferOffsetAlignment: (int)limits.MinStorageBufferOffsetAlignment);