diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2022-01-21 12:35:21 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-01-21 12:35:21 -0300 |
| commit | 7e967d796cf572377f21af3817a22755c5b01cb1 (patch) | |
| tree | 3c05dfde7d6ddfa97b667649afa744a2eb25432f /Ryujinx.Graphics.Gpu/Shader | |
| parent | 0e59573f2b55420c2c3fcfc3aaad56dba70e1492 (diff) | |
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
Diffstat (limited to 'Ryujinx.Graphics.Gpu/Shader')
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Shader/CachedGpuAccessor.cs | 35 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs | 29 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Shader/GpuAccessorState.cs | 6 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs | 46 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Shader/TransformFeedbackDescriptor.cs | 19 |
5 files changed, 106 insertions, 29 deletions
diff --git a/Ryujinx.Graphics.Gpu/Shader/CachedGpuAccessor.cs b/Ryujinx.Graphics.Gpu/Shader/CachedGpuAccessor.cs index 21d08823..d65349a5 100644 --- a/Ryujinx.Graphics.Gpu/Shader/CachedGpuAccessor.cs +++ b/Ryujinx.Graphics.Gpu/Shader/CachedGpuAccessor.cs @@ -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> @@ -178,6 +182,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 _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> /// <returns>True if early depth testing is forced</returns> diff --git a/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs b/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs index 64604a99..a5c7575f 100644 --- a/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs +++ b/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs @@ -223,6 +223,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> /// <returns>True if early depth testing is forced</returns> diff --git a/Ryujinx.Graphics.Gpu/Shader/GpuAccessorState.cs b/Ryujinx.Graphics.Gpu/Shader/GpuAccessorState.cs index ebbf3b69..6818072b 100644 --- a/Ryujinx.Graphics.Gpu/Shader/GpuAccessorState.cs +++ b/Ryujinx.Graphics.Gpu/Shader/GpuAccessorState.cs @@ -39,6 +39,11 @@ namespace Ryujinx.Graphics.Gpu.Shader 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> /// <param name="texturePoolGpuVa">GPU virtual address of the texture pool</param> @@ -61,6 +66,7 @@ namespace Ryujinx.Graphics.Gpu.Shader EarlyZForce = earlyZForce; Topology = topology; TessellationMode = tessellationMode; + TransformFeedbackDescriptors = null; } } }
\ No newline at end of file diff --git a/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs b/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs index 4c6224e3..110115e7 100644 --- a/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs +++ b/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs @@ -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); diff --git a/Ryujinx.Graphics.Gpu/Shader/TransformFeedbackDescriptor.cs b/Ryujinx.Graphics.Gpu/Shader/TransformFeedbackDescriptor.cs new file mode 100644 index 00000000..eaa889cc --- /dev/null +++ b/Ryujinx.Graphics.Gpu/Shader/TransformFeedbackDescriptor.cs @@ -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)); + } + } +} |
