aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2023-04-25 19:51:07 -0300
committerGitHub <noreply@github.com>2023-04-25 19:51:07 -0300
commit9f12e50a546b15533778ed0d8290202af91c10a2 (patch)
treef0e77a7b7c605face5ef29270b4248af2682301a /Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs
parent097562bc6c227c42f803ce1078fcb4adf06cd20c (diff)
Refactor attribute handling on the shader generator (#4565)1.1.733
* Refactor attribute handling on the shader generator * Implement gl_ViewportMask[] * Add back the Intel FrontFacing bug workaround * Fix GLSL transform feedback outputs mistmatch with fragment stage * Shader cache version bump * Fix geometry shader recognition * PR feedback * Delete GetOperandDef and GetOperandUse * Remove replacements that are no longer needed on GLSL compilation on Vulkan * Fix incorrect load for per-patch outputs * Fix build
Diffstat (limited to 'Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs')
-rw-r--r--Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs345
1 files changed, 47 insertions, 298 deletions
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs
index ec761fa6..92e83358 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs
@@ -1,10 +1,10 @@
+using Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions;
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using Ryujinx.Graphics.Shader.StructuredIr;
using Ryujinx.Graphics.Shader.Translation;
using System;
using System.Collections.Generic;
using System.Diagnostics;
-using System.Numerics;
using static Ryujinx.Graphics.Shader.StructuredIr.InstructionInfo;
@@ -12,82 +12,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
{
class OperandManager
{
- private static readonly string[] StagePrefixes = new string[] { "cp", "vp", "tcp", "tep", "gp", "fp" };
-
- private readonly struct BuiltInAttribute
- {
- public string Name { get; }
-
- public AggregateType Type { get; }
-
- public BuiltInAttribute(string name, AggregateType type)
- {
- Name = name;
- Type = type;
- }
- }
-
- private static Dictionary<int, BuiltInAttribute> _builtInAttributes = new Dictionary<int, BuiltInAttribute>()
- {
- { AttributeConsts.Layer, new BuiltInAttribute("gl_Layer", AggregateType.S32) },
- { AttributeConsts.PointSize, new BuiltInAttribute("gl_PointSize", AggregateType.FP32) },
- { AttributeConsts.PositionX, new BuiltInAttribute("gl_Position.x", AggregateType.FP32) },
- { AttributeConsts.PositionY, new BuiltInAttribute("gl_Position.y", AggregateType.FP32) },
- { AttributeConsts.PositionZ, new BuiltInAttribute("gl_Position.z", AggregateType.FP32) },
- { AttributeConsts.PositionW, new BuiltInAttribute("gl_Position.w", AggregateType.FP32) },
- { AttributeConsts.ClipDistance0, new BuiltInAttribute("gl_ClipDistance[0]", AggregateType.FP32) },
- { AttributeConsts.ClipDistance1, new BuiltInAttribute("gl_ClipDistance[1]", AggregateType.FP32) },
- { AttributeConsts.ClipDistance2, new BuiltInAttribute("gl_ClipDistance[2]", AggregateType.FP32) },
- { AttributeConsts.ClipDistance3, new BuiltInAttribute("gl_ClipDistance[3]", AggregateType.FP32) },
- { AttributeConsts.ClipDistance4, new BuiltInAttribute("gl_ClipDistance[4]", AggregateType.FP32) },
- { AttributeConsts.ClipDistance5, new BuiltInAttribute("gl_ClipDistance[5]", AggregateType.FP32) },
- { AttributeConsts.ClipDistance6, new BuiltInAttribute("gl_ClipDistance[6]", AggregateType.FP32) },
- { AttributeConsts.ClipDistance7, new BuiltInAttribute("gl_ClipDistance[7]", AggregateType.FP32) },
- { AttributeConsts.PointCoordX, new BuiltInAttribute("gl_PointCoord.x", AggregateType.FP32) },
- { AttributeConsts.PointCoordY, new BuiltInAttribute("gl_PointCoord.y", AggregateType.FP32) },
- { AttributeConsts.TessCoordX, new BuiltInAttribute("gl_TessCoord.x", AggregateType.FP32) },
- { AttributeConsts.TessCoordY, new BuiltInAttribute("gl_TessCoord.y", AggregateType.FP32) },
- { AttributeConsts.InstanceId, new BuiltInAttribute("gl_InstanceID", AggregateType.S32) },
- { AttributeConsts.VertexId, new BuiltInAttribute("gl_VertexID", AggregateType.S32) },
- { AttributeConsts.BaseInstance, new BuiltInAttribute("gl_BaseInstanceARB", AggregateType.S32) },
- { AttributeConsts.BaseVertex, new BuiltInAttribute("gl_BaseVertexARB", AggregateType.S32) },
- { AttributeConsts.InstanceIndex, new BuiltInAttribute("gl_InstanceIndex", AggregateType.S32) },
- { AttributeConsts.VertexIndex, new BuiltInAttribute("gl_VertexIndex", AggregateType.S32) },
- { AttributeConsts.DrawIndex, new BuiltInAttribute("gl_DrawIDARB", AggregateType.S32) },
- { AttributeConsts.FrontFacing, new BuiltInAttribute("gl_FrontFacing", AggregateType.Bool) },
-
- // Special.
- { AttributeConsts.FragmentOutputDepth, new BuiltInAttribute("gl_FragDepth", AggregateType.FP32) },
- { AttributeConsts.ThreadKill, new BuiltInAttribute("gl_HelperInvocation", AggregateType.Bool) },
- { AttributeConsts.ThreadIdX, new BuiltInAttribute("gl_LocalInvocationID.x", AggregateType.U32) },
- { AttributeConsts.ThreadIdY, new BuiltInAttribute("gl_LocalInvocationID.y", AggregateType.U32) },
- { AttributeConsts.ThreadIdZ, new BuiltInAttribute("gl_LocalInvocationID.z", AggregateType.U32) },
- { AttributeConsts.CtaIdX, new BuiltInAttribute("gl_WorkGroupID.x", AggregateType.U32) },
- { AttributeConsts.CtaIdY, new BuiltInAttribute("gl_WorkGroupID.y", AggregateType.U32) },
- { AttributeConsts.CtaIdZ, new BuiltInAttribute("gl_WorkGroupID.z", AggregateType.U32) },
- { AttributeConsts.LaneId, new BuiltInAttribute(null, AggregateType.U32) },
- { AttributeConsts.InvocationId, new BuiltInAttribute("gl_InvocationID", AggregateType.S32) },
- { AttributeConsts.PrimitiveId, new BuiltInAttribute("gl_PrimitiveID", AggregateType.S32) },
- { AttributeConsts.PatchVerticesIn, new BuiltInAttribute("gl_PatchVerticesIn", AggregateType.S32) },
- { AttributeConsts.EqMask, new BuiltInAttribute(null, AggregateType.U32) },
- { AttributeConsts.GeMask, new BuiltInAttribute(null, AggregateType.U32) },
- { AttributeConsts.GtMask, new BuiltInAttribute(null, AggregateType.U32) },
- { AttributeConsts.LeMask, new BuiltInAttribute(null, AggregateType.U32) },
- { AttributeConsts.LtMask, new BuiltInAttribute(null, AggregateType.U32) },
-
- // Support uniforms.
- { AttributeConsts.FragmentOutputIsBgraBase + 0, new BuiltInAttribute($"{DefaultNames.SupportBlockIsBgraName}[0]", AggregateType.Bool) },
- { AttributeConsts.FragmentOutputIsBgraBase + 4, new BuiltInAttribute($"{DefaultNames.SupportBlockIsBgraName}[1]", AggregateType.Bool) },
- { AttributeConsts.FragmentOutputIsBgraBase + 8, new BuiltInAttribute($"{DefaultNames.SupportBlockIsBgraName}[2]", AggregateType.Bool) },
- { AttributeConsts.FragmentOutputIsBgraBase + 12, new BuiltInAttribute($"{DefaultNames.SupportBlockIsBgraName}[3]", AggregateType.Bool) },
- { AttributeConsts.FragmentOutputIsBgraBase + 16, new BuiltInAttribute($"{DefaultNames.SupportBlockIsBgraName}[4]", AggregateType.Bool) },
- { AttributeConsts.FragmentOutputIsBgraBase + 20, new BuiltInAttribute($"{DefaultNames.SupportBlockIsBgraName}[5]", AggregateType.Bool) },
- { AttributeConsts.FragmentOutputIsBgraBase + 24, new BuiltInAttribute($"{DefaultNames.SupportBlockIsBgraName}[6]", AggregateType.Bool) },
- { AttributeConsts.FragmentOutputIsBgraBase + 28, new BuiltInAttribute($"{DefaultNames.SupportBlockIsBgraName}[7]", AggregateType.Bool) },
-
- { AttributeConsts.SupportBlockViewInverseX, new BuiltInAttribute($"{DefaultNames.SupportBlockViewportInverse}.x", AggregateType.FP32) },
- { AttributeConsts.SupportBlockViewInverseY, new BuiltInAttribute($"{DefaultNames.SupportBlockViewportInverse}.y", AggregateType.FP32) }
- };
+ private static readonly string[] _stagePrefixes = new string[] { "cp", "vp", "tcp", "tep", "gp", "fp" };
private Dictionary<AstOperand, string> _locals;
@@ -110,8 +35,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
return operand.Type switch
{
OperandType.Argument => GetArgumentName(operand.Value),
- OperandType.Attribute => GetAttributeName(context, operand.Value, perPatch: false),
- OperandType.AttributePerPatch => GetAttributeName(context, operand.Value, perPatch: true),
OperandType.Constant => NumberFormatter.FormatInt(operand.Value),
OperandType.ConstantBuffer => GetConstantBufferName(operand, context.Config),
OperandType.LocalVariable => _locals[operand],
@@ -155,177 +78,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
return GetVec4Indexed(GetUbName(stage, slotExpr) + $"[{offsetExpr} >> 2]", offsetExpr + " & 3", indexElement);
}
- public static string GetOutAttributeName(CodeGenContext context, int value, bool perPatch)
- {
- return GetAttributeName(context, value, perPatch, isOutAttr: true);
- }
-
- public static string GetAttributeName(CodeGenContext context, int value, bool perPatch, bool isOutAttr = false, string indexExpr = "0")
- {
- ShaderConfig config = context.Config;
-
- if ((value & AttributeConsts.LoadOutputMask) != 0)
- {
- isOutAttr = true;
- }
-
- value &= AttributeConsts.Mask & ~3;
- char swzMask = GetSwizzleMask((value >> 2) & 3);
-
- if (perPatch)
- {
- if (value >= AttributeConsts.UserAttributePerPatchBase && value < AttributeConsts.UserAttributePerPatchEnd)
- {
- value -= AttributeConsts.UserAttributePerPatchBase;
-
- return $"{DefaultNames.PerPatchAttributePrefix}{(value >> 4)}.{swzMask}";
- }
- else if (value < AttributeConsts.UserAttributePerPatchBase)
- {
- return value switch
- {
- AttributeConsts.TessLevelOuter0 => "gl_TessLevelOuter[0]",
- AttributeConsts.TessLevelOuter1 => "gl_TessLevelOuter[1]",
- AttributeConsts.TessLevelOuter2 => "gl_TessLevelOuter[2]",
- AttributeConsts.TessLevelOuter3 => "gl_TessLevelOuter[3]",
- AttributeConsts.TessLevelInner0 => "gl_TessLevelInner[0]",
- AttributeConsts.TessLevelInner1 => "gl_TessLevelInner[1]",
- _ => null
- };
- }
- }
- else if (value >= AttributeConsts.UserAttributeBase && value < AttributeConsts.UserAttributeEnd)
- {
- int attrOffset = value;
- value -= AttributeConsts.UserAttributeBase;
-
- string prefix = isOutAttr
- ? DefaultNames.OAttributePrefix
- : DefaultNames.IAttributePrefix;
-
- bool indexable = config.UsedFeatures.HasFlag(isOutAttr ? FeatureFlags.OaIndexing : FeatureFlags.IaIndexing);
-
- if (indexable)
- {
- string name = prefix;
-
- if (config.Stage == ShaderStage.Geometry && !isOutAttr)
- {
- name += $"[{indexExpr}]";
- }
-
- return name + $"[{(value >> 4)}]." + swzMask;
- }
- else if (config.TransformFeedbackEnabled &&
- ((config.LastInVertexPipeline && isOutAttr) ||
- (config.Stage == ShaderStage.Fragment && !isOutAttr)))
- {
- int components = context.Info.GetTransformFeedbackOutputComponents(attrOffset);
- string name = components > 1 ? $"{prefix}{(value >> 4)}" : $"{prefix}{(value >> 4)}_{swzMask}";
-
- if (AttributeInfo.IsArrayAttributeGlsl(config.Stage, isOutAttr))
- {
- name += isOutAttr ? "[gl_InvocationID]" : $"[{indexExpr}]";
- }
-
- return components > 1 ? name + '.' + swzMask : name;
- }
- else
- {
- string name = $"{prefix}{(value >> 4)}";
-
- if (AttributeInfo.IsArrayAttributeGlsl(config.Stage, isOutAttr))
- {
- name += isOutAttr ? "[gl_InvocationID]" : $"[{indexExpr}]";
- }
-
- return name + '.' + swzMask;
- }
- }
- else
- {
- if (value >= AttributeConsts.FragmentOutputColorBase && value < AttributeConsts.FragmentOutputColorEnd)
- {
- value -= AttributeConsts.FragmentOutputColorBase;
-
- return $"{DefaultNames.OAttributePrefix}{(value >> 4)}.{swzMask}";
- }
- else if (_builtInAttributes.TryGetValue(value, out BuiltInAttribute builtInAttr))
- {
- string subgroupMask = value switch
- {
- AttributeConsts.EqMask => "Eq",
- AttributeConsts.GeMask => "Ge",
- AttributeConsts.GtMask => "Gt",
- AttributeConsts.LeMask => "Le",
- AttributeConsts.LtMask => "Lt",
- _ => null
- };
-
- if (subgroupMask != null)
- {
- return config.GpuAccessor.QueryHostSupportsShaderBallot()
- ? $"unpackUint2x32(gl_SubGroup{subgroupMask}MaskARB).x"
- : $"gl_Subgroup{subgroupMask}Mask.x";
- }
- else if (value == AttributeConsts.LaneId)
- {
- return config.GpuAccessor.QueryHostSupportsShaderBallot()
- ? "gl_SubGroupInvocationARB"
- : "gl_SubgroupInvocationID";
- }
-
- if (config.Stage == ShaderStage.Fragment)
- {
- // TODO: There must be a better way to handle this...
- switch (value)
- {
- case AttributeConsts.PositionX: return $"(gl_FragCoord.x / {DefaultNames.SupportBlockRenderScaleName}[0])";
- case AttributeConsts.PositionY: return $"(gl_FragCoord.y / {DefaultNames.SupportBlockRenderScaleName}[0])";
- case AttributeConsts.PositionZ: return "gl_FragCoord.z";
- case AttributeConsts.PositionW: return "gl_FragCoord.w";
-
- case AttributeConsts.FrontFacing:
- if (config.GpuAccessor.QueryHostHasFrontFacingBug())
- {
- // This is required for Intel on Windows, gl_FrontFacing sometimes returns incorrect
- // (flipped) values. Doing this seems to fix it.
- return "(-floatBitsToInt(float(gl_FrontFacing)) < 0)";
- }
- break;
- }
- }
-
- string name = builtInAttr.Name;
-
- if (AttributeInfo.IsArrayAttributeGlsl(config.Stage, isOutAttr) && AttributeInfo.IsArrayBuiltIn(value))
- {
- name = isOutAttr ? $"gl_out[gl_InvocationID].{name}" : $"gl_in[{indexExpr}].{name}";
- }
-
- return name;
- }
- }
-
- // TODO: Warn about unknown built-in attribute.
-
- return isOutAttr ? "// bad_attr0x" + value.ToString("X") : "0.0";
- }
-
- public static string GetAttributeName(string attrExpr, ShaderConfig config, bool isOutAttr = false, string indexExpr = "0")
- {
- string name = isOutAttr
- ? DefaultNames.OAttributePrefix
- : DefaultNames.IAttributePrefix;
-
- if (config.Stage == ShaderStage.Geometry && !isOutAttr)
- {
- name += $"[{indexExpr}]";
- }
-
- return $"{name}[{attrExpr} >> 2][{attrExpr} & 3]";
- }
-
public static string GetUbName(ShaderStage stage, int slot, bool cbIndexable)
{
if (cbIndexable)
@@ -387,12 +139,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
{
int index = (int)stage;
- if ((uint)index >= StagePrefixes.Length)
+ if ((uint)index >= _stagePrefixes.Length)
{
return "invalid";
}
- return StagePrefixes[index];
+ return _stagePrefixes[index];
}
private static char GetSwizzleMask(int value)
@@ -405,24 +157,54 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
return $"{DefaultNames.ArgumentNamePrefix}{argIndex}";
}
- public static AggregateType GetNodeDestType(CodeGenContext context, IAstNode node, bool isAsgDest = false)
+ public static AggregateType GetNodeDestType(CodeGenContext context, IAstNode node)
{
+ // TODO: Get rid of that function entirely and return the type from the operation generation
+ // functions directly, like SPIR-V does.
+
if (node is AstOperation operation)
{
- if (operation.Inst == Instruction.LoadAttribute)
+ if (operation.Inst == Instruction.Load)
{
- // Load attribute basically just returns the attribute value.
- // Some built-in attributes may have different types, so we need
- // to return the type based on the attribute that is being read.
- if (operation.GetSource(0) is AstOperand operand && operand.Type == OperandType.Constant)
+ switch (operation.StorageKind)
{
- if (_builtInAttributes.TryGetValue(operand.Value & ~3, out BuiltInAttribute builtInAttr))
- {
- return builtInAttr.Type;
- }
- }
+ case StorageKind.Input:
+ case StorageKind.InputPerPatch:
+ case StorageKind.Output:
+ case StorageKind.OutputPerPatch:
+ if (!(operation.GetSource(0) is AstOperand varId) || varId.Type != OperandType.Constant)
+ {
+ throw new InvalidOperationException($"First input of {operation.Inst} with {operation.StorageKind} storage must be a constant operand.");
+ }
+
+ IoVariable ioVariable = (IoVariable)varId.Value;
+ bool isOutput = operation.StorageKind == StorageKind.Output || operation.StorageKind == StorageKind.OutputPerPatch;
+ bool isPerPatch = operation.StorageKind == StorageKind.InputPerPatch || operation.StorageKind == StorageKind.OutputPerPatch;
+ int location = 0;
+ int component = 0;
+
+ if (context.Config.HasPerLocationInputOrOutput(ioVariable, isOutput))
+ {
+ if (!(operation.GetSource(1) is AstOperand vecIndex) || vecIndex.Type != OperandType.Constant)
+ {
+ throw new InvalidOperationException($"Second input of {operation.Inst} with {operation.StorageKind} storage must be a constant operand.");
+ }
+
+ location = vecIndex.Value;
+
+ if (operation.SourcesCount > 2 &&
+ operation.GetSource(2) is AstOperand elemIndex &&
+ elemIndex.Type == OperandType.Constant &&
+ context.Config.HasPerLocationInputOrOutputComponent(ioVariable, location, elemIndex.Value, isOutput))
+ {
+ component = elemIndex.Value;
+ }
+ }
- return OperandInfo.GetVarType(OperandType.Attribute);
+ (_, AggregateType varType) = IoMap.GetGlslVariable(context.Config, ioVariable, location, component, isOutput, isPerPatch);
+
+ return varType & AggregateType.ElementTypeMask;
+ }
}
else if (operation.Inst == Instruction.Call)
{
@@ -461,45 +243,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
return context.CurrentFunction.GetArgumentType(argIndex);
}
- return GetOperandVarType(context, operand, isAsgDest);
+ return OperandInfo.GetVarType(operand);
}
else
{
throw new ArgumentException($"Invalid node type \"{node?.GetType().Name ?? "null"}\".");
}
}
-
- private static AggregateType GetOperandVarType(CodeGenContext context, AstOperand operand, bool isAsgDest = false)
- {
- if (operand.Type == OperandType.Attribute)
- {
- if (_builtInAttributes.TryGetValue(operand.Value & ~3, out BuiltInAttribute builtInAttr))
- {
- return builtInAttr.Type;
- }
- else if (context.Config.Stage == ShaderStage.Vertex && !isAsgDest &&
- operand.Value >= AttributeConsts.UserAttributeBase &&
- operand.Value < AttributeConsts.UserAttributeEnd)
- {
- int location = (operand.Value - AttributeConsts.UserAttributeBase) / 16;
-
- AttributeType type = context.Config.GpuAccessor.QueryAttributeType(location);
-
- return type.ToAggregateType();
- }
- else if (context.Config.Stage == ShaderStage.Fragment && isAsgDest &&
- operand.Value >= AttributeConsts.FragmentOutputColorBase &&
- operand.Value < AttributeConsts.FragmentOutputColorEnd)
- {
- int location = (operand.Value - AttributeConsts.FragmentOutputColorBase) / 16;
-
- AttributeType type = context.Config.GpuAccessor.QueryFragmentOutputType(location);
-
- return type.ToAggregateType();
- }
- }
-
- return OperandInfo.GetVarType(operand);
- }
}
} \ No newline at end of file