diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2024-05-14 11:47:16 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-05-14 16:47:16 +0200 |
| commit | 3a3b51893ee272af49d762387da5b27743786d56 (patch) | |
| tree | e37f41f9a6cd65f8c9f53359b378740b6fbe00af /src/Ryujinx.Graphics.Gpu/Shader | |
| parent | 44dbab3848c8831d27e50f7252d759a2494ad556 (diff) | |
Add support for bindless textures from storage buffer on Vulkan (#6721)
* Halve primitive ID when converting quads to triangles
* Shader cache version bump
* Add support for bindless textures from storage buffer on Vulkan
Diffstat (limited to 'src/Ryujinx.Graphics.Gpu/Shader')
6 files changed, 45 insertions, 12 deletions
diff --git a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheGpuAccessor.cs b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheGpuAccessor.cs index 45f32e2d..3c7664b7 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheGpuAccessor.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheGpuAccessor.cs @@ -18,6 +18,8 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache private readonly ShaderSpecializationState _newSpecState; private readonly int _stageIndex; private readonly bool _isVulkan; + private readonly bool _hasGeometryShader; + private readonly bool _supportsQuads; /// <summary> /// Creates a new instance of the cached GPU state accessor for shader translation. @@ -29,6 +31,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache /// <param name="newSpecState">Shader specialization state of the recompiled shader</param> /// <param name="counts">Resource counts shared across all shader stages</param> /// <param name="stageIndex">Shader stage index</param> + /// <param name="hasGeometryShader">Indicates if a geometry shader is present</param> public DiskCacheGpuAccessor( GpuContext context, ReadOnlyMemory<byte> data, @@ -36,7 +39,8 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache ShaderSpecializationState oldSpecState, ShaderSpecializationState newSpecState, ResourceCounts counts, - int stageIndex) : base(context, counts, stageIndex) + int stageIndex, + bool hasGeometryShader) : base(context, counts, stageIndex) { _data = data; _cb1Data = cb1Data; @@ -44,6 +48,8 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache _newSpecState = newSpecState; _stageIndex = stageIndex; _isVulkan = context.Capabilities.Api == TargetApi.Vulkan; + _hasGeometryShader = hasGeometryShader; + _supportsQuads = context.Capabilities.SupportsQuads; if (stageIndex == (int)ShaderStage.Geometry - 1) { @@ -100,7 +106,11 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache /// <inheritdoc/> public GpuGraphicsState QueryGraphicsState() { - return _oldSpecState.GraphicsState.CreateShaderGraphicsState(!_isVulkan, _isVulkan || _oldSpecState.GraphicsState.YNegateEnabled); + return _oldSpecState.GraphicsState.CreateShaderGraphicsState( + !_isVulkan, + _supportsQuads, + _hasGeometryShader, + _isVulkan || _oldSpecState.GraphicsState.YNegateEnabled); } /// <inheritdoc/> diff --git a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs index 2c19cc4b..ea54049c 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs @@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache private const ushort FileFormatVersionMajor = 1; private const ushort FileFormatVersionMinor = 2; private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor; - private const uint CodeGenVersion = 6577; + private const uint CodeGenVersion = 5936; private const string SharedTocFileName = "shared.toc"; private const string SharedDataFileName = "shared.data"; diff --git a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/ParallelDiskCacheLoader.cs b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/ParallelDiskCacheLoader.cs index 153fc442..20f96462 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/ParallelDiskCacheLoader.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/ParallelDiskCacheLoader.cs @@ -601,6 +601,8 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache TargetApi api = _context.Capabilities.Api; + bool hasCachedGs = guestShaders[4].HasValue; + for (int stageIndex = Constants.ShaderStages - 1; stageIndex >= 0; stageIndex--) { if (guestShaders[stageIndex + 1].HasValue) @@ -610,7 +612,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache byte[] guestCode = shader.Code; byte[] cb1Data = shader.Cb1Data; - DiskCacheGpuAccessor gpuAccessor = new(_context, guestCode, cb1Data, specState, newSpecState, counts, stageIndex); + DiskCacheGpuAccessor gpuAccessor = new(_context, guestCode, cb1Data, specState, newSpecState, counts, stageIndex, hasCachedGs); TranslatorContext currentStage = DecodeGraphicsShader(gpuAccessor, api, DefaultFlags, 0); if (nextStage != null) @@ -623,7 +625,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache byte[] guestCodeA = guestShaders[0].Value.Code; byte[] cb1DataA = guestShaders[0].Value.Cb1Data; - DiskCacheGpuAccessor gpuAccessorA = new(_context, guestCodeA, cb1DataA, specState, newSpecState, counts, 0); + DiskCacheGpuAccessor gpuAccessorA = new(_context, guestCodeA, cb1DataA, specState, newSpecState, counts, 0, hasCachedGs); translatorContexts[0] = DecodeGraphicsShader(gpuAccessorA, api, DefaultFlags | TranslationFlags.VertexA, 0); } @@ -711,7 +713,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache GuestCodeAndCbData shader = guestShaders[0].Value; ResourceCounts counts = new(); ShaderSpecializationState newSpecState = new(ref specState.ComputeState); - DiskCacheGpuAccessor gpuAccessor = new(_context, shader.Code, shader.Cb1Data, specState, newSpecState, counts, 0); + DiskCacheGpuAccessor gpuAccessor = new(_context, shader.Code, shader.Cb1Data, specState, newSpecState, counts, 0, false); gpuAccessor.InitializeReservedCounts(tfEnabled: false, vertexAsCompute: false); TranslatorContext translatorContext = DecodeComputeShader(gpuAccessor, _context.Capabilities.Api, 0); diff --git a/src/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs b/src/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs index 04949690..1be75f24 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs @@ -17,6 +17,8 @@ namespace Ryujinx.Graphics.Gpu.Shader private readonly int _stageIndex; private readonly bool _compute; private readonly bool _isVulkan; + private readonly bool _hasGeometryShader; + private readonly bool _supportsQuads; /// <summary> /// Creates a new instance of the GPU state accessor for graphics shader translation. @@ -25,12 +27,20 @@ namespace Ryujinx.Graphics.Gpu.Shader /// <param name="channel">GPU channel</param> /// <param name="state">Current GPU state</param> /// <param name="stageIndex">Graphics shader stage index (0 = Vertex, 4 = Fragment)</param> - public GpuAccessor(GpuContext context, GpuChannel channel, GpuAccessorState state, int stageIndex) : base(context, state.ResourceCounts, stageIndex) + /// <param name="hasGeometryShader">Indicates if a geometry shader is present</param> + public GpuAccessor( + GpuContext context, + GpuChannel channel, + GpuAccessorState state, + int stageIndex, + bool hasGeometryShader) : base(context, state.ResourceCounts, stageIndex) { - _isVulkan = context.Capabilities.Api == TargetApi.Vulkan; _channel = channel; _state = state; _stageIndex = stageIndex; + _isVulkan = context.Capabilities.Api == TargetApi.Vulkan; + _hasGeometryShader = hasGeometryShader; + _supportsQuads = context.Capabilities.SupportsQuads; if (stageIndex == (int)ShaderStage.Geometry - 1) { @@ -105,7 +115,11 @@ namespace Ryujinx.Graphics.Gpu.Shader /// <inheritdoc/> public GpuGraphicsState QueryGraphicsState() { - return _state.GraphicsState.CreateShaderGraphicsState(!_isVulkan, _isVulkan || _state.GraphicsState.YNegateEnabled); + return _state.GraphicsState.CreateShaderGraphicsState( + !_isVulkan, + _supportsQuads, + _hasGeometryShader, + _isVulkan || _state.GraphicsState.YNegateEnabled); } /// <inheritdoc/> diff --git a/src/Ryujinx.Graphics.Gpu/Shader/GpuChannelGraphicsState.cs b/src/Ryujinx.Graphics.Gpu/Shader/GpuChannelGraphicsState.cs index b5bc4df3..765bef7d 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/GpuChannelGraphicsState.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/GpuChannelGraphicsState.cs @@ -106,8 +106,11 @@ namespace Ryujinx.Graphics.Gpu.Shader /// Creates a new graphics state from this state that can be used for shader generation. /// </summary> /// <param name="hostSupportsAlphaTest">Indicates if the host API supports alpha test operations</param> + /// <param name="hostSupportsQuads">Indicates if the host API supports quad primitives</param> + /// <param name="hasGeometryShader">Indicates if a geometry shader is used</param> + /// <param name="originUpperLeft">If true, indicates that the fragment origin is the upper left corner of the viewport, otherwise it is the lower left corner</param> /// <returns>GPU graphics state that can be used for shader translation</returns> - public readonly GpuGraphicsState CreateShaderGraphicsState(bool hostSupportsAlphaTest, bool originUpperLeft) + public readonly GpuGraphicsState CreateShaderGraphicsState(bool hostSupportsAlphaTest, bool hostSupportsQuads, bool hasGeometryShader, bool originUpperLeft) { AlphaTestOp alphaTestOp; @@ -130,6 +133,9 @@ namespace Ryujinx.Graphics.Gpu.Shader }; } + bool isQuad = Topology == PrimitiveTopology.Quads || Topology == PrimitiveTopology.QuadStrip; + bool halvePrimitiveId = !hostSupportsQuads && !hasGeometryShader && isQuad; + return new GpuGraphicsState( EarlyZForce, ConvertToInputTopology(Topology, TessellationMode), @@ -149,7 +155,8 @@ namespace Ryujinx.Graphics.Gpu.Shader in FragmentOutputTypes, DualSourceBlendEnable, YNegateEnabled, - originUpperLeft); + originUpperLeft, + halvePrimitiveId); } /// <summary> diff --git a/src/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs b/src/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs index 31cc94a2..4fc66c4c 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs @@ -339,7 +339,7 @@ namespace Ryujinx.Graphics.Gpu.Shader if (gpuVa != 0) { - GpuAccessor gpuAccessor = new(_context, channel, gpuAccessorState, stageIndex); + GpuAccessor gpuAccessor = new(_context, channel, gpuAccessorState, stageIndex, addresses.Geometry != 0); TranslatorContext currentStage = DecodeGraphicsShader(gpuAccessor, api, DefaultFlags, gpuVa); if (nextStage != null) |
