aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Graphics.Gpu/Shader
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2024-05-14 11:47:16 -0300
committerGitHub <noreply@github.com>2024-05-14 16:47:16 +0200
commit3a3b51893ee272af49d762387da5b27743786d56 (patch)
treee37f41f9a6cd65f8c9f53359b378740b6fbe00af /src/Ryujinx.Graphics.Gpu/Shader
parent44dbab3848c8831d27e50f7252d759a2494ad556 (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')
-rw-r--r--src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheGpuAccessor.cs14
-rw-r--r--src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs2
-rw-r--r--src/Ryujinx.Graphics.Gpu/Shader/DiskCache/ParallelDiskCacheLoader.cs8
-rw-r--r--src/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs20
-rw-r--r--src/Ryujinx.Graphics.Gpu/Shader/GpuChannelGraphicsState.cs11
-rw-r--r--src/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs2
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)