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:
@ -103,6 +103,18 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
return _info.Functions[id];
|
||||
}
|
||||
|
||||
public TransformFeedbackOutput GetTransformFeedbackOutput(int location, int component)
|
||||
{
|
||||
int index = (AttributeConsts.UserAttributeBase / 4) + location * 4 + component;
|
||||
return _info.TransformFeedbackOutputs[index];
|
||||
}
|
||||
|
||||
public TransformFeedbackOutput GetTransformFeedbackOutput(int location)
|
||||
{
|
||||
int index = location / 4;
|
||||
return _info.TransformFeedbackOutputs[index];
|
||||
}
|
||||
|
||||
private void UpdateIndentation()
|
||||
{
|
||||
_indentation = GetIndentation(_level);
|
||||
|
@ -191,6 +191,20 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
|
||||
context.AppendLine();
|
||||
}
|
||||
|
||||
if (context.Config.Stage != ShaderStage.Compute &&
|
||||
context.Config.Stage != ShaderStage.Fragment &&
|
||||
context.Config.TransformFeedbackEnabled)
|
||||
{
|
||||
var tfOutput = context.GetTransformFeedbackOutput(AttributeConsts.PositionX);
|
||||
if (tfOutput.Valid)
|
||||
{
|
||||
context.AppendLine($"layout (xfb_buffer = {tfOutput.Buffer}, xfb_offset = {tfOutput.Offset}, xfb_stride = {tfOutput.Stride}) out gl_PerVertex");
|
||||
context.EnterScope();
|
||||
context.AppendLine("vec4 gl_Position;");
|
||||
context.LeaveScope(context.Config.Stage == ShaderStage.TessellationControl ? " gl_out[];" : ";");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -514,7 +528,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
string pass = (context.Config.PassthroughAttributes & (1 << attr)) != 0 ? "passthrough, " : string.Empty;
|
||||
string name = $"{DefaultNames.IAttributePrefix}{attr}";
|
||||
|
||||
if ((context.Config.Options.Flags & TranslationFlags.Feedback) != 0)
|
||||
if (context.Config.TransformFeedbackEnabled && context.Config.Stage != ShaderStage.Vertex)
|
||||
{
|
||||
for (int c = 0; c < 4; c++)
|
||||
{
|
||||
@ -559,13 +573,21 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
string suffix = OperandManager.IsArrayAttribute(context.Config.Stage, isOutAttr: true) ? "[]" : string.Empty;
|
||||
string name = $"{DefaultNames.OAttributePrefix}{attr}{suffix}";
|
||||
|
||||
if ((context.Config.Options.Flags & TranslationFlags.Feedback) != 0)
|
||||
if (context.Config.TransformFeedbackEnabled && context.Config.Stage != ShaderStage.Fragment)
|
||||
{
|
||||
for (int c = 0; c < 4; c++)
|
||||
{
|
||||
char swzMask = "xyzw"[c];
|
||||
|
||||
context.AppendLine($"layout (location = {attr}, component = {c}) out float {name}_{swzMask};");
|
||||
string xfb = string.Empty;
|
||||
|
||||
var tfOutput = context.GetTransformFeedbackOutput(attr, c);
|
||||
if (tfOutput.Valid)
|
||||
{
|
||||
xfb = $", xfb_buffer = {tfOutput.Buffer}, xfb_offset = {tfOutput.Offset}, xfb_stride = {tfOutput.Stride}";
|
||||
}
|
||||
|
||||
context.AppendLine($"layout (location = {attr}, component = {c}{xfb}) out float {name}_{swzMask};");
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -194,7 +194,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
|
||||
return name + $"[{(value >> 4)}]." + swzMask;
|
||||
}
|
||||
else if (config.Options.Flags.HasFlag(TranslationFlags.Feedback))
|
||||
else if (config.TransformFeedbackEnabled && (config.Stage != ShaderStage.Vertex || isOutAttr))
|
||||
{
|
||||
string name = $"{prefix}{(value >> 4)}_{swzMask}";
|
||||
|
||||
|
@ -1,69 +0,0 @@
|
||||
using Ryujinx.Graphics.Shader.Translation;
|
||||
|
||||
namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
{
|
||||
public static class Varying
|
||||
{
|
||||
public static string GetName(int offset)
|
||||
{
|
||||
offset <<= 2;
|
||||
|
||||
if (offset >= AttributeConsts.UserAttributeBase &&
|
||||
offset < AttributeConsts.UserAttributeEnd)
|
||||
{
|
||||
offset -= AttributeConsts.UserAttributeBase;
|
||||
|
||||
string name = $"{ DefaultNames.OAttributePrefix}{(offset >> 4)}";
|
||||
|
||||
name += "_" + "xyzw"[(offset >> 2) & 3];
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
switch (offset)
|
||||
{
|
||||
case AttributeConsts.PositionX:
|
||||
case AttributeConsts.PositionY:
|
||||
case AttributeConsts.PositionZ:
|
||||
case AttributeConsts.PositionW:
|
||||
return "gl_Position";
|
||||
case AttributeConsts.PointSize:
|
||||
return "gl_PointSize";
|
||||
case AttributeConsts.ClipDistance0:
|
||||
return "gl_ClipDistance[0]";
|
||||
case AttributeConsts.ClipDistance1:
|
||||
return "gl_ClipDistance[1]";
|
||||
case AttributeConsts.ClipDistance2:
|
||||
return "gl_ClipDistance[2]";
|
||||
case AttributeConsts.ClipDistance3:
|
||||
return "gl_ClipDistance[3]";
|
||||
case AttributeConsts.ClipDistance4:
|
||||
return "gl_ClipDistance[4]";
|
||||
case AttributeConsts.ClipDistance5:
|
||||
return "gl_ClipDistance[5]";
|
||||
case AttributeConsts.ClipDistance6:
|
||||
return "gl_ClipDistance[6]";
|
||||
case AttributeConsts.ClipDistance7:
|
||||
return "gl_ClipDistance[7]";
|
||||
case AttributeConsts.VertexId:
|
||||
return "gl_VertexID";
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static int GetSize(int offset)
|
||||
{
|
||||
switch (offset << 2)
|
||||
{
|
||||
case AttributeConsts.PositionX:
|
||||
case AttributeConsts.PositionY:
|
||||
case AttributeConsts.PositionZ:
|
||||
case AttributeConsts.PositionW:
|
||||
return 4;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
@ -131,6 +131,21 @@ namespace Ryujinx.Graphics.Shader
|
||||
return TextureFormat.R8G8B8A8Unorm;
|
||||
}
|
||||
|
||||
bool QueryTransformFeedbackEnabled()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ReadOnlySpan<byte> QueryTransformFeedbackVaryingLocations(int bufferIndex)
|
||||
{
|
||||
return ReadOnlySpan<byte>.Empty;
|
||||
}
|
||||
|
||||
int QueryTransformFeedbackStride(int bufferIndex)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool QueryEarlyZForce()
|
||||
{
|
||||
return false;
|
||||
|
@ -64,6 +64,24 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
|
||||
context.LeaveFunction();
|
||||
}
|
||||
|
||||
if (config.TransformFeedbackEnabled)
|
||||
{
|
||||
for (int tfbIndex = 0; tfbIndex < 4; tfbIndex++)
|
||||
{
|
||||
var locations = config.GpuAccessor.QueryTransformFeedbackVaryingLocations(tfbIndex);
|
||||
var stride = config.GpuAccessor.QueryTransformFeedbackStride(tfbIndex);
|
||||
|
||||
for (int j = 0; j < locations.Length; j++)
|
||||
{
|
||||
byte location = locations[j];
|
||||
if (location < 0x80)
|
||||
{
|
||||
context.Info.TransformFeedbackOutputs[location] = new TransformFeedbackOutput(tfbIndex, j * 4, stride);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return context.Info;
|
||||
}
|
||||
|
||||
|
@ -2,15 +2,35 @@ using System.Collections.Generic;
|
||||
|
||||
namespace Ryujinx.Graphics.Shader.StructuredIr
|
||||
{
|
||||
struct TransformFeedbackOutput
|
||||
{
|
||||
public readonly bool Valid;
|
||||
public readonly int Buffer;
|
||||
public readonly int Offset;
|
||||
public readonly int Stride;
|
||||
|
||||
public TransformFeedbackOutput(int buffer, int offset, int stride)
|
||||
{
|
||||
Valid = true;
|
||||
Buffer = buffer;
|
||||
Offset = offset;
|
||||
Stride = stride;
|
||||
}
|
||||
}
|
||||
|
||||
class StructuredProgramInfo
|
||||
{
|
||||
public List<StructuredFunction> Functions { get; }
|
||||
|
||||
public HelperFunctionsMask HelperFunctionsMask { get; set; }
|
||||
|
||||
public TransformFeedbackOutput[] TransformFeedbackOutputs { get; }
|
||||
|
||||
public StructuredProgramInfo()
|
||||
{
|
||||
Functions = new List<StructuredFunction>();
|
||||
|
||||
TransformFeedbackOutputs = new TransformFeedbackOutput[0x80];
|
||||
}
|
||||
}
|
||||
}
|
@ -33,6 +33,8 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
|
||||
public TranslationOptions Options { get; }
|
||||
|
||||
public bool TransformFeedbackEnabled { get; }
|
||||
|
||||
public int Size { get; private set; }
|
||||
|
||||
public byte ClipDistancesWritten { get; private set; }
|
||||
@ -128,6 +130,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
OmapTargets = header.OmapTargets;
|
||||
OmapSampleMask = header.OmapSampleMask;
|
||||
OmapDepth = header.OmapDepth;
|
||||
TransformFeedbackEnabled = gpuAccessor.QueryTransformFeedbackEnabled();
|
||||
}
|
||||
|
||||
public int GetDepthRegister()
|
||||
|
@ -9,7 +9,6 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
|
||||
VertexA = 1 << 0,
|
||||
Compute = 1 << 1,
|
||||
Feedback = 1 << 2,
|
||||
DebugMode = 1 << 3
|
||||
DebugMode = 1 << 2
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user