From 52249e50dd9bb358f709e4690a8ce1f6ed1ccc5c Mon Sep 17 00:00:00 2001 From: gdk Date: Wed, 26 Jan 2022 09:36:20 -0300 Subject: [PATCH] Fix transform feedback on Intel, gl_Position feedback and clears to inexistent depth buffers --- .../CodeGen/Glsl/Declarations.cs | 42 +++++++++++++++++-- Ryujinx.Graphics.Vulkan/PipelineBase.cs | 42 +++++++++---------- Ryujinx.Graphics.Vulkan/PipelineFull.cs | 2 - 3 files changed, 59 insertions(+), 27 deletions(-) diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs index d99f4df2a..8dcd0ac12 100644 --- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs +++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs @@ -196,12 +196,36 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl context.Config.Stage != ShaderStage.Fragment && context.Config.TransformFeedbackEnabled) { - var tfOutput = context.GetTransformFeedbackOutput(AttributeConsts.PositionX); - if (tfOutput.Valid) + var tfPosition = context.GetTransformFeedbackOutput(AttributeConsts.PositionX); + var tfPointSize = context.GetTransformFeedbackOutput(AttributeConsts.PointSize); + var tfClipDistance = context.GetTransformFeedbackOutput(AttributeConsts.ClipDistance0); + + if (tfPosition.Valid || tfPointSize.Valid || tfClipDistance.Valid) { - context.AppendLine($"layout (xfb_buffer = {tfOutput.Buffer}, xfb_offset = {tfOutput.Offset}, xfb_stride = {tfOutput.Stride}) out gl_PerVertex"); + context.AppendLine("out gl_PerVertex"); context.EnterScope(); - context.AppendLine("vec4 gl_Position;"); + context.AppendLine($"{GetTfLayout(tfPosition)}vec4 gl_Position;"); + context.AppendLine($"{GetTfLayout(tfPointSize)}float gl_PointSize;"); + + if (tfClipDistance.Valid) + { + int clipDistanceCount = 1; + + for (; clipDistanceCount < 8; clipDistanceCount++) + { + if (!context.GetTransformFeedbackOutput(AttributeConsts.ClipDistance0 + clipDistanceCount).Valid) + { + break; + } + } + + context.AppendLine($"{GetTfLayout(tfClipDistance)}float gl_ClipDistance[{clipDistanceCount}];"); + } + else + { + context.AppendLine("float gl_ClipDistance[];"); + } + context.LeaveScope(context.Config.Stage == ShaderStage.TessellationControl ? " gl_out[];" : ";"); } } @@ -311,6 +335,16 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl } } + private static string GetTfLayout(TransformFeedbackOutput tfOutput) + { + if (tfOutput.Valid) + { + return $"layout (xfb_buffer = {tfOutput.Buffer}, xfb_offset = {tfOutput.Offset}, xfb_stride = {tfOutput.Stride}) "; + } + + return string.Empty; + } + public static void DeclareLocals(CodeGenContext context, StructuredFunction function) { foreach (AstOperand decl in function.Locals) diff --git a/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 52790efcb..dd952f82c 100644 --- a/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -2,7 +2,6 @@ using Ryujinx.Graphics.Shader; using Silk.NET.Vulkan; using System; -using System.Runtime.InteropServices; namespace Ryujinx.Graphics.Vulkan { @@ -62,6 +61,7 @@ namespace Ryujinx.Graphics.Vulkan private bool _needsVertexBuffersRebind; private bool _tfEnabled; + private bool _tfActive; public ulong DrawCount { get; private set; } @@ -128,11 +128,7 @@ namespace Ryujinx.Graphics.Vulkan public void BeginTransformFeedback(GAL.PrimitiveTopology topology) { - if (!_tfEnabled) - { - BeginTransformFeedbackInternal(); - _tfEnabled = true; - } + _tfEnabled = true; } public void ClearBuffer(BufferHandle destination, int offset, int size, uint value) @@ -171,7 +167,7 @@ namespace Ryujinx.Graphics.Vulkan { // TODO: Use stencilMask (fully) - if (_framebuffer == null) + if (_framebuffer == null || !FramebufferParams.HasDepthStencil) { return; } @@ -237,6 +233,7 @@ namespace Ryujinx.Graphics.Vulkan BeginRenderPass(); RecreatePipelineIfNeeded(PipelineBindPoint.Graphics); + ResumeTransformFeedbackInternal(); DrawCount++; if (_topology == GAL.PrimitiveTopology.Quads) @@ -265,6 +262,7 @@ namespace Ryujinx.Graphics.Vulkan BeginRenderPass(); RecreatePipelineIfNeeded(PipelineBindPoint.Graphics); + ResumeTransformFeedbackInternal(); DrawCount++; if (_topology == GAL.PrimitiveTopology.Quads) @@ -334,11 +332,8 @@ namespace Ryujinx.Graphics.Vulkan public void EndTransformFeedback() { - if (_tfEnabled) - { - EndTransformFeedbackInternal(); - _tfEnabled = false; - } + PauseTransformFeedbackInternal(); + _tfEnabled = false; } public void MultiDrawIndirectCount(BufferRange indirectBuffer, BufferRange parameterBuffer, int maxDrawCount, int stride) @@ -355,6 +350,7 @@ namespace Ryujinx.Graphics.Vulkan BeginRenderPass(); RecreatePipelineIfNeeded(PipelineBindPoint.Graphics); + ResumeTransformFeedbackInternal(); DrawCount++; var buffer = Gd.BufferManager.GetBuffer(CommandBuffer, indirectBuffer.Handle, true).Get(Cbs, indirectBuffer.Offset, indirectBuffer.Size).Value; @@ -368,6 +364,8 @@ namespace Ryujinx.Graphics.Vulkan (ulong)parameterBuffer.Offset, (uint)maxDrawCount, (uint)stride); + + PauseTransformFeedbackInternal(); } public void MultiDrawIndexedIndirectCount(BufferRange indirectBuffer, BufferRange parameterBuffer, int maxDrawCount, int stride) @@ -384,6 +382,7 @@ namespace Ryujinx.Graphics.Vulkan BeginRenderPass(); RecreatePipelineIfNeeded(PipelineBindPoint.Graphics); + ResumeTransformFeedbackInternal(); DrawCount++; var buffer = Gd.BufferManager.GetBuffer(CommandBuffer, indirectBuffer.Handle, true).Get(Cbs, indirectBuffer.Offset, indirectBuffer.Size).Value; @@ -397,6 +396,8 @@ namespace Ryujinx.Graphics.Vulkan (ulong)parameterBuffer.Offset, (uint)maxDrawCount, (uint)stride); + + PauseTransformFeedbackInternal(); } public void SetAlphaTest(bool enable, float reference, GAL.CompareOp op) @@ -713,8 +714,6 @@ namespace Ryujinx.Graphics.Vulkan _transformFeedbackBuffers[i] = BufferState.Null; } } - - ResumeTransformFeedbackInternal(); } public void SetUniformBuffers(int first, ReadOnlySpan buffers) @@ -744,7 +743,6 @@ namespace Ryujinx.Graphics.Vulkan } _newState.VertexAttributeDescriptionsCount = (uint)count; - SignalStateChange(); } @@ -789,7 +787,6 @@ namespace Ryujinx.Graphics.Vulkan } _newState.VertexBindingDescriptionsCount = (uint)validCount; - SignalStateChange(); } @@ -1067,7 +1064,6 @@ namespace Ryujinx.Graphics.Vulkan _transformFeedbackBuffers[i].BindTransformFeedbackBuffer(Gd, Cbs, (uint)i); } - ResumeTransformFeedbackInternal(); _needsTransformFeedbackBuffersRebind = false; } @@ -1106,6 +1102,7 @@ namespace Ryujinx.Graphics.Vulkan // _pipeline?.Dispose(); Pipeline = pipeline; + PauseTransformFeedbackInternal(); Gd.Api.CmdBindPipeline(CommandBuffer, pbp, Pipeline.Get(Cbs).Value); } } @@ -1137,25 +1134,28 @@ namespace Ryujinx.Graphics.Vulkan { if (_renderPassActive) { + PauseTransformFeedbackInternal(); // System.Console.WriteLine("render pass ended " + caller); Gd.Api.CmdEndRenderPass(CommandBuffer); _renderPassActive = false; } } - protected void PauseTransformFeedbackInternal() + private void PauseTransformFeedbackInternal() { - if (_tfEnabled) + if (_tfEnabled && _tfActive) { EndTransformFeedbackInternal(); + _tfActive = false; } } - protected void ResumeTransformFeedbackInternal() + private void ResumeTransformFeedbackInternal() { - if (_tfEnabled) + if (_tfEnabled && !_tfActive) { BeginTransformFeedbackInternal(); + _tfActive = true; } } diff --git a/Ryujinx.Graphics.Vulkan/PipelineFull.cs b/Ryujinx.Graphics.Vulkan/PipelineFull.cs index 15a68ea31..e496649b8 100644 --- a/Ryujinx.Graphics.Vulkan/PipelineFull.cs +++ b/Ryujinx.Graphics.Vulkan/PipelineFull.cs @@ -249,7 +249,6 @@ namespace Ryujinx.Graphics.Vulkan // System.Console.WriteLine("flush by " + caller); EndRenderPass(); - PauseTransformFeedbackInternal(); foreach (var queryPool in _activeQueries) { @@ -277,7 +276,6 @@ namespace Ryujinx.Graphics.Vulkan Gd.Api.CmdBeginQuery(CommandBuffer, queryPool, 0, 0); } - ResumeTransformFeedbackInternal(); SignalCommandBufferChange(); }