mirror of
https://git.743378673.xyz/MeloNX/MeloNX.git
synced 2025-08-02 08:47:11 +02:00
Stop using glTransformFeedbackVaryings and use explicit layout on the shader (#3012)
* Stop using glTransformFeedbackVarying and use explicit layout on the shader * This is no longer needed * Shader cache version bump * Fix gl_PerVertex output for tessellation control shaders
This commit is contained in:
parent
4c4bd46cc3
commit
73d10233ef
19 changed files with 192 additions and 164 deletions
|
@ -13,6 +13,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
private readonly ReadOnlyMemory<byte> _cb1Data;
|
||||
private readonly GuestGpuAccessorHeader _header;
|
||||
private readonly Dictionary<int, GuestTextureDescriptor> _textureDescriptors;
|
||||
private readonly TransformFeedbackDescriptor[] _tfd;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the cached GPU state accessor for shader translation.
|
||||
|
@ -27,7 +28,8 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
ReadOnlyMemory<byte> data,
|
||||
ReadOnlyMemory<byte> cb1Data,
|
||||
GuestGpuAccessorHeader header,
|
||||
IReadOnlyDictionary<int, GuestTextureDescriptor> guestTextureDescriptors) : base(context)
|
||||
IReadOnlyDictionary<int, GuestTextureDescriptor> guestTextureDescriptors,
|
||||
TransformFeedbackDescriptor[] tfd) : base(context)
|
||||
{
|
||||
_data = data;
|
||||
_cb1Data = cb1Data;
|
||||
|
@ -38,6 +40,8 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
{
|
||||
_textureDescriptors.Add(guestTextureDescriptor.Key, guestTextureDescriptor.Value);
|
||||
}
|
||||
|
||||
_tfd = tfd;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -177,6 +181,35 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
return textureDescriptor;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Queries transform feedback enable state.
|
||||
/// </summary>
|
||||
/// <returns>True if the shader uses transform feedback, false otherwise</returns>
|
||||
public bool QueryTransformFeedbackEnabled()
|
||||
{
|
||||
return _tfd != null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Queries the varying locations that should be written to the transform feedback buffer.
|
||||
/// </summary>
|
||||
/// <param name="bufferIndex">Index of the transform feedback buffer</param>
|
||||
/// <returns>Varying locations for the specified buffer</returns>
|
||||
public ReadOnlySpan<byte> QueryTransformFeedbackVaryingLocations(int bufferIndex)
|
||||
{
|
||||
return _tfd[bufferIndex].VaryingLocations;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Queries the stride (in bytes) of the per vertex data written into the transform feedback buffer.
|
||||
/// </summary>
|
||||
/// <param name="bufferIndex">Index of the transform feedback buffer</param>
|
||||
/// <returns>Stride for the specified buffer</returns>
|
||||
public int QueryTransformFeedbackStride(int bufferIndex)
|
||||
{
|
||||
return _tfd[bufferIndex].Stride;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Queries if host state forces early depth testing.
|
||||
/// </summary>
|
||||
|
|
|
@ -222,6 +222,35 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Queries transform feedback enable state.
|
||||
/// </summary>
|
||||
/// <returns>True if the shader uses transform feedback, false otherwise</returns>
|
||||
public bool QueryTransformFeedbackEnabled()
|
||||
{
|
||||
return _state.TransformFeedbackDescriptors != null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Queries the varying locations that should be written to the transform feedback buffer.
|
||||
/// </summary>
|
||||
/// <param name="bufferIndex">Index of the transform feedback buffer</param>
|
||||
/// <returns>Varying locations for the specified buffer</returns>
|
||||
public ReadOnlySpan<byte> QueryTransformFeedbackVaryingLocations(int bufferIndex)
|
||||
{
|
||||
return _state.TransformFeedbackDescriptors[bufferIndex].VaryingLocations;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Queries the stride (in bytes) of the per vertex data written into the transform feedback buffer.
|
||||
/// </summary>
|
||||
/// <param name="bufferIndex">Index of the transform feedback buffer</param>
|
||||
/// <returns>Stride for the specified buffer</returns>
|
||||
public int QueryTransformFeedbackStride(int bufferIndex)
|
||||
{
|
||||
return _state.TransformFeedbackDescriptors[bufferIndex].Stride;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Queries if host state forces early depth testing.
|
||||
/// </summary>
|
||||
|
|
|
@ -38,6 +38,11 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
/// </summary>
|
||||
public TessMode TessellationMode { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Transform feedback information, if the shader uses transform feedback. Otherwise, should be null.
|
||||
/// </summary>
|
||||
public TransformFeedbackDescriptor[] TransformFeedbackDescriptors { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the GPU accessor state.
|
||||
/// </summary>
|
||||
|
@ -61,6 +66,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
EarlyZForce = earlyZForce;
|
||||
Topology = topology;
|
||||
TessellationMode = tessellationMode;
|
||||
TransformFeedbackDescriptors = null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -40,7 +40,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
/// <summary>
|
||||
/// Version of the codegen (to be changed when codegen or guest format change).
|
||||
/// </summary>
|
||||
private const ulong ShaderCodeGenVersion = 2972;
|
||||
private const ulong ShaderCodeGenVersion = 3012;
|
||||
|
||||
// Progress reporting helpers
|
||||
private volatile int _shaderCount;
|
||||
|
@ -227,7 +227,8 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
binaryCode,
|
||||
binaryCode.Slice(binaryCode.Length - entry.Header.Cb1DataSize),
|
||||
entry.Header.GpuAccessorHeader,
|
||||
entry.TextureDescriptors);
|
||||
entry.TextureDescriptors,
|
||||
null);
|
||||
|
||||
var options = new TranslationOptions(TargetLanguage.Glsl, TargetApi.OpenGL, DefaultFlags | TranslationFlags.Compute);
|
||||
program = Translator.CreateContext(0, gpuAccessor, options).Translate(out shaderProgramInfo);
|
||||
|
@ -251,7 +252,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
|
||||
// Compile shader and create program as the shader program binary got invalidated.
|
||||
shader.HostShader = _context.Renderer.CompileShader(ShaderStage.Compute, program.Code);
|
||||
hostProgram = _context.Renderer.CreateProgram(new IShader[] { shader.HostShader }, null);
|
||||
hostProgram = _context.Renderer.CreateProgram(new IShader[] { shader.HostShader });
|
||||
|
||||
task.OnCompiled(hostProgram, (bool isNewProgramValid, ShaderCompileTask task) =>
|
||||
{
|
||||
|
@ -293,13 +294,6 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
|
||||
TransformFeedbackDescriptor[] tfd = CacheHelper.ReadTransformFeedbackInformation(ref guestProgramReadOnlySpan, fileHeader);
|
||||
|
||||
TranslationFlags flags = DefaultFlags;
|
||||
|
||||
if (tfd != null)
|
||||
{
|
||||
flags |= TranslationFlags.Feedback;
|
||||
}
|
||||
|
||||
TranslationCounts counts = new TranslationCounts();
|
||||
|
||||
HostShaderCacheEntry[] hostShaderEntries = null;
|
||||
|
@ -343,15 +337,16 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
binaryCode,
|
||||
binaryCode.Slice(binaryCode.Length - entry.Header.Cb1DataSize),
|
||||
entry.Header.GpuAccessorHeader,
|
||||
entry.TextureDescriptors);
|
||||
entry.TextureDescriptors,
|
||||
tfd);
|
||||
|
||||
var options = new TranslationOptions(TargetLanguage.Glsl, TargetApi.OpenGL, flags);
|
||||
var options = new TranslationOptions(TargetLanguage.Glsl, TargetApi.OpenGL, DefaultFlags);
|
||||
|
||||
shaderContexts[i + 1] = Translator.CreateContext(0, gpuAccessor, options, counts);
|
||||
|
||||
if (entry.Header.SizeA != 0)
|
||||
{
|
||||
var options2 = new TranslationOptions(TargetLanguage.Glsl, TargetApi.OpenGL, flags | TranslationFlags.VertexA);
|
||||
var options2 = new TranslationOptions(TargetLanguage.Glsl, TargetApi.OpenGL, DefaultFlags | TranslationFlags.VertexA);
|
||||
|
||||
shaderContexts[0] = Translator.CreateContext((ulong)entry.Header.Size, gpuAccessor, options2, counts);
|
||||
}
|
||||
|
@ -431,7 +426,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
hostShaders.Add(hostShader);
|
||||
}
|
||||
|
||||
hostProgram = _context.Renderer.CreateProgram(hostShaders.ToArray(), tfd);
|
||||
hostProgram = _context.Renderer.CreateProgram(hostShaders.ToArray());
|
||||
|
||||
task.OnCompiled(hostProgram, (bool isNewProgramValid, ShaderCompileTask task) =>
|
||||
{
|
||||
|
@ -622,7 +617,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
|
||||
shader.HostShader = _context.Renderer.CompileShader(ShaderStage.Compute, shader.Program.Code);
|
||||
|
||||
IProgram hostProgram = _context.Renderer.CreateProgram(new IShader[] { shader.HostShader }, null);
|
||||
IProgram hostProgram = _context.Renderer.CreateProgram(new IShader[] { shader.HostShader });
|
||||
|
||||
cpShader = new ShaderBundle(hostProgram, shader);
|
||||
|
||||
|
@ -684,25 +679,20 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
|
||||
TransformFeedbackDescriptor[] tfd = GetTransformFeedbackDescriptors(ref state);
|
||||
|
||||
TranslationFlags flags = DefaultFlags;
|
||||
|
||||
if (tfd != null)
|
||||
{
|
||||
flags |= TranslationFlags.Feedback;
|
||||
}
|
||||
gas.TransformFeedbackDescriptors = tfd;
|
||||
|
||||
TranslationCounts counts = new TranslationCounts();
|
||||
|
||||
if (addresses.VertexA != 0)
|
||||
{
|
||||
shaderContexts[0] = DecodeGraphicsShader(channel, gas, counts, flags | TranslationFlags.VertexA, ShaderStage.Vertex, addresses.VertexA);
|
||||
shaderContexts[0] = DecodeGraphicsShader(channel, gas, counts, DefaultFlags | TranslationFlags.VertexA, ShaderStage.Vertex, addresses.VertexA);
|
||||
}
|
||||
|
||||
shaderContexts[1] = DecodeGraphicsShader(channel, gas, counts, flags, ShaderStage.Vertex, addresses.Vertex);
|
||||
shaderContexts[2] = DecodeGraphicsShader(channel, gas, counts, flags, ShaderStage.TessellationControl, addresses.TessControl);
|
||||
shaderContexts[3] = DecodeGraphicsShader(channel, gas, counts, flags, ShaderStage.TessellationEvaluation, addresses.TessEvaluation);
|
||||
shaderContexts[4] = DecodeGraphicsShader(channel, gas, counts, flags, ShaderStage.Geometry, addresses.Geometry);
|
||||
shaderContexts[5] = DecodeGraphicsShader(channel, gas, counts, flags, ShaderStage.Fragment, addresses.Fragment);
|
||||
shaderContexts[1] = DecodeGraphicsShader(channel, gas, counts, DefaultFlags, ShaderStage.Vertex, addresses.Vertex);
|
||||
shaderContexts[2] = DecodeGraphicsShader(channel, gas, counts, DefaultFlags, ShaderStage.TessellationControl, addresses.TessControl);
|
||||
shaderContexts[3] = DecodeGraphicsShader(channel, gas, counts, DefaultFlags, ShaderStage.TessellationEvaluation, addresses.TessEvaluation);
|
||||
shaderContexts[4] = DecodeGraphicsShader(channel, gas, counts, DefaultFlags, ShaderStage.Geometry, addresses.Geometry);
|
||||
shaderContexts[5] = DecodeGraphicsShader(channel, gas, counts, DefaultFlags, ShaderStage.Fragment, addresses.Fragment);
|
||||
|
||||
bool isShaderCacheEnabled = _cacheManager != null;
|
||||
bool isShaderCacheReadOnly = false;
|
||||
|
@ -765,7 +755,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
hostShaders.Add(hostShader);
|
||||
}
|
||||
|
||||
IProgram hostProgram = _context.Renderer.CreateProgram(hostShaders.ToArray(), tfd);
|
||||
IProgram hostProgram = _context.Renderer.CreateProgram(hostShaders.ToArray());
|
||||
|
||||
gpShaders = new ShaderBundle(hostProgram, shaders);
|
||||
|
||||
|
|
19
Ryujinx.Graphics.Gpu/Shader/TransformFeedbackDescriptor.cs
Normal file
19
Ryujinx.Graphics.Gpu/Shader/TransformFeedbackDescriptor.cs
Normal file
|
@ -0,0 +1,19 @@
|
|||
using System;
|
||||
|
||||
namespace Ryujinx.Graphics.Gpu.Shader
|
||||
{
|
||||
struct TransformFeedbackDescriptor
|
||||
{
|
||||
public int BufferIndex { get; }
|
||||
public int Stride { get; }
|
||||
|
||||
public byte[] VaryingLocations { get; }
|
||||
|
||||
public TransformFeedbackDescriptor(int bufferIndex, int stride, byte[] varyingLocations)
|
||||
{
|
||||
BufferIndex = bufferIndex;
|
||||
Stride = stride;
|
||||
VaryingLocations = varyingLocations ?? throw new ArgumentNullException(nameof(varyingLocations));
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue