Fix transform feedback on Intel, gl_Position feedback and clears to inexistent depth buffers

This commit is contained in:
gdk 2022-01-26 09:36:20 -03:00 committed by riperiperi
parent 0fe19f51c0
commit 52249e50dd
3 changed files with 59 additions and 27 deletions

View file

@ -196,12 +196,36 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
context.Config.Stage != ShaderStage.Fragment && context.Config.Stage != ShaderStage.Fragment &&
context.Config.TransformFeedbackEnabled) context.Config.TransformFeedbackEnabled)
{ {
var tfOutput = context.GetTransformFeedbackOutput(AttributeConsts.PositionX); var tfPosition = context.GetTransformFeedbackOutput(AttributeConsts.PositionX);
if (tfOutput.Valid) 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.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[];" : ";"); 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) public static void DeclareLocals(CodeGenContext context, StructuredFunction function)
{ {
foreach (AstOperand decl in function.Locals) foreach (AstOperand decl in function.Locals)

View file

@ -2,7 +2,6 @@
using Ryujinx.Graphics.Shader; using Ryujinx.Graphics.Shader;
using Silk.NET.Vulkan; using Silk.NET.Vulkan;
using System; using System;
using System.Runtime.InteropServices;
namespace Ryujinx.Graphics.Vulkan namespace Ryujinx.Graphics.Vulkan
{ {
@ -62,6 +61,7 @@ namespace Ryujinx.Graphics.Vulkan
private bool _needsVertexBuffersRebind; private bool _needsVertexBuffersRebind;
private bool _tfEnabled; private bool _tfEnabled;
private bool _tfActive;
public ulong DrawCount { get; private set; } public ulong DrawCount { get; private set; }
@ -128,12 +128,8 @@ namespace Ryujinx.Graphics.Vulkan
public void BeginTransformFeedback(GAL.PrimitiveTopology topology) public void BeginTransformFeedback(GAL.PrimitiveTopology topology)
{ {
if (!_tfEnabled)
{
BeginTransformFeedbackInternal();
_tfEnabled = true; _tfEnabled = true;
} }
}
public void ClearBuffer(BufferHandle destination, int offset, int size, uint value) public void ClearBuffer(BufferHandle destination, int offset, int size, uint value)
{ {
@ -171,7 +167,7 @@ namespace Ryujinx.Graphics.Vulkan
{ {
// TODO: Use stencilMask (fully) // TODO: Use stencilMask (fully)
if (_framebuffer == null) if (_framebuffer == null || !FramebufferParams.HasDepthStencil)
{ {
return; return;
} }
@ -237,6 +233,7 @@ namespace Ryujinx.Graphics.Vulkan
BeginRenderPass(); BeginRenderPass();
RecreatePipelineIfNeeded(PipelineBindPoint.Graphics); RecreatePipelineIfNeeded(PipelineBindPoint.Graphics);
ResumeTransformFeedbackInternal();
DrawCount++; DrawCount++;
if (_topology == GAL.PrimitiveTopology.Quads) if (_topology == GAL.PrimitiveTopology.Quads)
@ -265,6 +262,7 @@ namespace Ryujinx.Graphics.Vulkan
BeginRenderPass(); BeginRenderPass();
RecreatePipelineIfNeeded(PipelineBindPoint.Graphics); RecreatePipelineIfNeeded(PipelineBindPoint.Graphics);
ResumeTransformFeedbackInternal();
DrawCount++; DrawCount++;
if (_topology == GAL.PrimitiveTopology.Quads) if (_topology == GAL.PrimitiveTopology.Quads)
@ -334,12 +332,9 @@ namespace Ryujinx.Graphics.Vulkan
public void EndTransformFeedback() public void EndTransformFeedback()
{ {
if (_tfEnabled) PauseTransformFeedbackInternal();
{
EndTransformFeedbackInternal();
_tfEnabled = false; _tfEnabled = false;
} }
}
public void MultiDrawIndirectCount(BufferRange indirectBuffer, BufferRange parameterBuffer, int maxDrawCount, int stride) public void MultiDrawIndirectCount(BufferRange indirectBuffer, BufferRange parameterBuffer, int maxDrawCount, int stride)
{ {
@ -355,6 +350,7 @@ namespace Ryujinx.Graphics.Vulkan
BeginRenderPass(); BeginRenderPass();
RecreatePipelineIfNeeded(PipelineBindPoint.Graphics); RecreatePipelineIfNeeded(PipelineBindPoint.Graphics);
ResumeTransformFeedbackInternal();
DrawCount++; DrawCount++;
var buffer = Gd.BufferManager.GetBuffer(CommandBuffer, indirectBuffer.Handle, true).Get(Cbs, indirectBuffer.Offset, indirectBuffer.Size).Value; 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, (ulong)parameterBuffer.Offset,
(uint)maxDrawCount, (uint)maxDrawCount,
(uint)stride); (uint)stride);
PauseTransformFeedbackInternal();
} }
public void MultiDrawIndexedIndirectCount(BufferRange indirectBuffer, BufferRange parameterBuffer, int maxDrawCount, int stride) public void MultiDrawIndexedIndirectCount(BufferRange indirectBuffer, BufferRange parameterBuffer, int maxDrawCount, int stride)
@ -384,6 +382,7 @@ namespace Ryujinx.Graphics.Vulkan
BeginRenderPass(); BeginRenderPass();
RecreatePipelineIfNeeded(PipelineBindPoint.Graphics); RecreatePipelineIfNeeded(PipelineBindPoint.Graphics);
ResumeTransformFeedbackInternal();
DrawCount++; DrawCount++;
var buffer = Gd.BufferManager.GetBuffer(CommandBuffer, indirectBuffer.Handle, true).Get(Cbs, indirectBuffer.Offset, indirectBuffer.Size).Value; 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, (ulong)parameterBuffer.Offset,
(uint)maxDrawCount, (uint)maxDrawCount,
(uint)stride); (uint)stride);
PauseTransformFeedbackInternal();
} }
public void SetAlphaTest(bool enable, float reference, GAL.CompareOp op) public void SetAlphaTest(bool enable, float reference, GAL.CompareOp op)
@ -713,8 +714,6 @@ namespace Ryujinx.Graphics.Vulkan
_transformFeedbackBuffers[i] = BufferState.Null; _transformFeedbackBuffers[i] = BufferState.Null;
} }
} }
ResumeTransformFeedbackInternal();
} }
public void SetUniformBuffers(int first, ReadOnlySpan<BufferRange> buffers) public void SetUniformBuffers(int first, ReadOnlySpan<BufferRange> buffers)
@ -744,7 +743,6 @@ namespace Ryujinx.Graphics.Vulkan
} }
_newState.VertexAttributeDescriptionsCount = (uint)count; _newState.VertexAttributeDescriptionsCount = (uint)count;
SignalStateChange(); SignalStateChange();
} }
@ -789,7 +787,6 @@ namespace Ryujinx.Graphics.Vulkan
} }
_newState.VertexBindingDescriptionsCount = (uint)validCount; _newState.VertexBindingDescriptionsCount = (uint)validCount;
SignalStateChange(); SignalStateChange();
} }
@ -1067,7 +1064,6 @@ namespace Ryujinx.Graphics.Vulkan
_transformFeedbackBuffers[i].BindTransformFeedbackBuffer(Gd, Cbs, (uint)i); _transformFeedbackBuffers[i].BindTransformFeedbackBuffer(Gd, Cbs, (uint)i);
} }
ResumeTransformFeedbackInternal();
_needsTransformFeedbackBuffersRebind = false; _needsTransformFeedbackBuffersRebind = false;
} }
@ -1106,6 +1102,7 @@ namespace Ryujinx.Graphics.Vulkan
// _pipeline?.Dispose(); // _pipeline?.Dispose();
Pipeline = pipeline; Pipeline = pipeline;
PauseTransformFeedbackInternal();
Gd.Api.CmdBindPipeline(CommandBuffer, pbp, Pipeline.Get(Cbs).Value); Gd.Api.CmdBindPipeline(CommandBuffer, pbp, Pipeline.Get(Cbs).Value);
} }
} }
@ -1137,25 +1134,28 @@ namespace Ryujinx.Graphics.Vulkan
{ {
if (_renderPassActive) if (_renderPassActive)
{ {
PauseTransformFeedbackInternal();
// System.Console.WriteLine("render pass ended " + caller); // System.Console.WriteLine("render pass ended " + caller);
Gd.Api.CmdEndRenderPass(CommandBuffer); Gd.Api.CmdEndRenderPass(CommandBuffer);
_renderPassActive = false; _renderPassActive = false;
} }
} }
protected void PauseTransformFeedbackInternal() private void PauseTransformFeedbackInternal()
{ {
if (_tfEnabled) if (_tfEnabled && _tfActive)
{ {
EndTransformFeedbackInternal(); EndTransformFeedbackInternal();
_tfActive = false;
} }
} }
protected void ResumeTransformFeedbackInternal() private void ResumeTransformFeedbackInternal()
{ {
if (_tfEnabled) if (_tfEnabled && !_tfActive)
{ {
BeginTransformFeedbackInternal(); BeginTransformFeedbackInternal();
_tfActive = true;
} }
} }

View file

@ -249,7 +249,6 @@ namespace Ryujinx.Graphics.Vulkan
// System.Console.WriteLine("flush by " + caller); // System.Console.WriteLine("flush by " + caller);
EndRenderPass(); EndRenderPass();
PauseTransformFeedbackInternal();
foreach (var queryPool in _activeQueries) foreach (var queryPool in _activeQueries)
{ {
@ -277,7 +276,6 @@ namespace Ryujinx.Graphics.Vulkan
Gd.Api.CmdBeginQuery(CommandBuffer, queryPool, 0, 0); Gd.Api.CmdBeginQuery(CommandBuffer, queryPool, 0, 0);
} }
ResumeTransformFeedbackInternal();
SignalCommandBufferChange(); SignalCommandBufferChange();
} }