aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Graphics.Gpu/Shader/ShaderInfoBuilder.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Ryujinx.Graphics.Gpu/Shader/ShaderInfoBuilder.cs')
-rw-r--r--src/Ryujinx.Graphics.Gpu/Shader/ShaderInfoBuilder.cs63
1 files changed, 45 insertions, 18 deletions
diff --git a/src/Ryujinx.Graphics.Gpu/Shader/ShaderInfoBuilder.cs b/src/Ryujinx.Graphics.Gpu/Shader/ShaderInfoBuilder.cs
index af1e1ee3..bea916a6 100644
--- a/src/Ryujinx.Graphics.Gpu/Shader/ShaderInfoBuilder.cs
+++ b/src/Ryujinx.Graphics.Gpu/Shader/ShaderInfoBuilder.cs
@@ -33,6 +33,8 @@ namespace Ryujinx.Graphics.Gpu.Shader
private readonly int _reservedConstantBuffers;
private readonly int _reservedStorageBuffers;
+ private readonly int _reservedTextures;
+ private readonly int _reservedImages;
private readonly List<ResourceDescriptor>[] _resourceDescriptors;
private readonly List<ResourceUsage>[] _resourceUsages;
@@ -42,7 +44,8 @@ namespace Ryujinx.Graphics.Gpu.Shader
/// </summary>
/// <param name="context">GPU context that owns the shaders that will be added to the builder</param>
/// <param name="tfEnabled">Indicates if the graphics shader is used with transform feedback enabled</param>
- public ShaderInfoBuilder(GpuContext context, bool tfEnabled)
+ /// <param name="vertexAsCompute">Indicates that the vertex shader will be emulated on a compute shader</param>
+ public ShaderInfoBuilder(GpuContext context, bool tfEnabled, bool vertexAsCompute = false)
{
_context = context;
@@ -60,27 +63,34 @@ namespace Ryujinx.Graphics.Gpu.Shader
AddDescriptor(SupportBufferStages, ResourceType.UniformBuffer, UniformSetIndex, 0, 1);
AddUsage(SupportBufferStages, ResourceType.UniformBuffer, ResourceAccess.Read, UniformSetIndex, 0, 1);
- _reservedConstantBuffers = 1; // For the support buffer.
+ ResourceReservationCounts rrc = new(!context.Capabilities.SupportsTransformFeedback && tfEnabled, vertexAsCompute);
- if (!context.Capabilities.SupportsTransformFeedback && tfEnabled)
- {
- _reservedStorageBuffers = 5;
+ _reservedConstantBuffers = rrc.ReservedConstantBuffers;
+ _reservedStorageBuffers = rrc.ReservedStorageBuffers;
+ _reservedTextures = rrc.ReservedTextures;
+ _reservedImages = rrc.ReservedImages;
- AddDescriptor(VtgStages, ResourceType.StorageBuffer, StorageSetIndex, 0, 5);
- AddUsage(VtgStages, ResourceType.StorageBuffer, ResourceAccess.Read, StorageSetIndex, 0, 1);
- AddUsage(VtgStages, ResourceType.StorageBuffer, ResourceAccess.Write, StorageSetIndex, 1, 4);
- }
- else
- {
- _reservedStorageBuffers = 0;
- }
+ // TODO: Handle that better? Maybe we should only set the binding that are really needed on each shader.
+ ResourceStages stages = vertexAsCompute ? ResourceStages.Compute | ResourceStages.Vertex : VtgStages;
+
+ PopulateDescriptorAndUsages(stages, ResourceType.UniformBuffer, ResourceAccess.Read, UniformSetIndex, 1, rrc.ReservedConstantBuffers - 1);
+ PopulateDescriptorAndUsages(stages, ResourceType.StorageBuffer, ResourceAccess.ReadWrite, StorageSetIndex, 0, rrc.ReservedStorageBuffers);
+ PopulateDescriptorAndUsages(stages, ResourceType.BufferTexture, ResourceAccess.Read, TextureSetIndex, 0, rrc.ReservedTextures);
+ PopulateDescriptorAndUsages(stages, ResourceType.BufferImage, ResourceAccess.ReadWrite, ImageSetIndex, 0, rrc.ReservedImages);
+ }
+
+ private void PopulateDescriptorAndUsages(ResourceStages stages, ResourceType type, ResourceAccess access, int setIndex, int start, int count)
+ {
+ AddDescriptor(stages, type, setIndex, start, count);
+ AddUsage(stages, type, access, setIndex, start, count);
}
/// <summary>
/// Adds information from a given shader stage.
/// </summary>
/// <param name="info">Shader stage information</param>
- public void AddStageInfo(ShaderProgramInfo info)
+ /// <param name="vertexAsCompute">True if the shader stage has been converted into a compute shader</param>
+ public void AddStageInfo(ShaderProgramInfo info, bool vertexAsCompute = false)
{
if (info.Stage == ShaderStage.Fragment)
{
@@ -96,7 +106,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
_ => 0,
});
- ResourceStages stages = info.Stage switch
+ ResourceStages stages = vertexAsCompute ? ResourceStages.Compute : info.Stage switch
{
ShaderStage.Compute => ResourceStages.Compute,
ShaderStage.Vertex => ResourceStages.Vertex,
@@ -114,8 +124,8 @@ namespace Ryujinx.Graphics.Gpu.Shader
int uniformBinding = _reservedConstantBuffers + stageIndex * uniformsPerStage;
int storageBinding = _reservedStorageBuffers + stageIndex * storagesPerStage;
- int textureBinding = stageIndex * texturesPerStage * 2;
- int imageBinding = stageIndex * imagesPerStage * 2;
+ int textureBinding = _reservedTextures + stageIndex * texturesPerStage * 2;
+ int imageBinding = _reservedImages + stageIndex * imagesPerStage * 2;
AddDescriptor(stages, ResourceType.UniformBuffer, UniformSetIndex, uniformBinding, uniformsPerStage);
AddDescriptor(stages, ResourceType.StorageBuffer, StorageSetIndex, storageBinding, storagesPerStage);
@@ -285,11 +295,28 @@ namespace Ryujinx.Graphics.Gpu.Shader
/// <returns>Shader information</returns>
public static ShaderInfo BuildForCompute(GpuContext context, ShaderProgramInfo info, bool fromCache = false)
{
- ShaderInfoBuilder builder = new(context, tfEnabled: false);
+ ShaderInfoBuilder builder = new(context, tfEnabled: false, vertexAsCompute: false);
builder.AddStageInfo(info);
return builder.Build(null, fromCache);
}
+
+ /// <summary>
+ /// Builds shader information for a vertex or geometry shader thas was converted to compute shader.
+ /// </summary>
+ /// <param name="context">GPU context that owns the shader</param>
+ /// <param name="info">Compute shader information</param>
+ /// <param name="tfEnabled">Indicates if the graphics shader is used with transform feedback enabled</param>
+ /// <param name="fromCache">True if the compute shader comes from a disk cache, false otherwise</param>
+ /// <returns>Shader information</returns>
+ public static ShaderInfo BuildForVertexAsCompute(GpuContext context, ShaderProgramInfo info, bool tfEnabled, bool fromCache = false)
+ {
+ ShaderInfoBuilder builder = new(context, tfEnabled, vertexAsCompute: true);
+
+ builder.AddStageInfo(info, vertexAsCompute: true);
+
+ return builder.Build(null, fromCache);
+ }
}
}