mirror of
https://git.ryujinx.app/ryubing/ryujinx.git
synced 2025-07-06 05:26:26 +02:00
Geometry shader emulation for macOS (#5551)
* Implement vertex and geometry shader conversion to compute * Call InitializeReservedCounts for compute too * PR feedback * Set clip distance mask for geometry and tessellation shaders too * Transform feedback emulation only for vertex
This commit is contained in:
parent
93d78f9ac4
commit
f09bba82b9
65 changed files with 3912 additions and 593 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue