aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Shader/CodeGen/Glsl
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
parent097562bc6c227c42f803ce1078fcb4adf06cd20c (diff)
Refactor attribute handling on the shader generator (#4565)
* 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')
-rw-r--r--Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs35
-rw-r--r--Ryujinx.Graphics.Shader/CodeGen/Glsl/GlslGenerator.cs16
-rw-r--r--Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs20
-rw-r--r--Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs4
-rw-r--r--Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs158
-rw-r--r--Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/IoMap.cs145
-rw-r--r--Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs345
7 files changed, 340 insertions, 383 deletions
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs
index 5e53d62a..81b79ec4 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs
@@ -59,6 +59,11 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
context.AppendLine("#extension GL_NV_geometry_shader_passthrough : enable");
}
+ if (context.Config.GpuAccessor.QueryHostSupportsViewportMask())
+ {
+ context.AppendLine("#extension GL_NV_viewport_array2 : enable");
+ }
+
context.AppendLine("#pragma optionNV(fastmath off)");
context.AppendLine();
@@ -215,7 +220,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
if (context.Config.TransformFeedbackEnabled && context.Config.LastInVertexPipeline)
{
- var tfOutput = context.Info.GetTransformFeedbackOutput(AttributeConsts.PositionX);
+ var tfOutput = context.Config.GetTransformFeedbackOutput(AttributeConsts.PositionX);
if (tfOutput.Valid)
{
context.AppendLine($"layout (xfb_buffer = {tfOutput.Buffer}, xfb_offset = {tfOutput.Offset}, xfb_stride = {tfOutput.Stride}) out gl_PerVertex");
@@ -552,7 +557,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
private static void DeclareInputAttribute(CodeGenContext context, StructuredProgramInfo info, int attr)
{
- string suffix = AttributeInfo.IsArrayAttributeGlsl(context.Config.Stage, isOutAttr: false) ? "[]" : string.Empty;
+ string suffix = IsArrayAttributeGlsl(context.Config.Stage, isOutAttr: false) ? "[]" : string.Empty;
string iq = string.Empty;
if (context.Config.Stage == ShaderStage.Fragment)
@@ -569,8 +574,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
if (context.Config.TransformFeedbackEnabled && context.Config.Stage == ShaderStage.Fragment)
{
- int attrOffset = AttributeConsts.UserAttributeBase + attr * 16;
- int components = context.Info.GetTransformFeedbackOutputComponents(attrOffset);
+ int components = context.Config.GetTransformFeedbackOutputComponents(attr, 0);
if (components > 1)
{
@@ -652,13 +656,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
private static void DeclareOutputAttribute(CodeGenContext context, int attr)
{
- string suffix = AttributeInfo.IsArrayAttributeGlsl(context.Config.Stage, isOutAttr: true) ? "[]" : string.Empty;
+ string suffix = IsArrayAttributeGlsl(context.Config.Stage, isOutAttr: true) ? "[]" : string.Empty;
string name = $"{DefaultNames.OAttributePrefix}{attr}{suffix}";
if (context.Config.TransformFeedbackEnabled && context.Config.LastInVertexPipeline)
{
- int attrOffset = AttributeConsts.UserAttributeBase + attr * 16;
- int components = context.Info.GetTransformFeedbackOutputComponents(attrOffset);
+ int components = context.Config.GetTransformFeedbackOutputComponents(attr, 0);
if (components > 1)
{
@@ -672,7 +675,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
string xfb = string.Empty;
- var tfOutput = context.Info.GetTransformFeedbackOutput(attrOffset);
+ var tfOutput = context.Config.GetTransformFeedbackOutput(attr, 0);
if (tfOutput.Valid)
{
xfb = $", xfb_buffer = {tfOutput.Buffer}, xfb_offset = {tfOutput.Offset}, xfb_stride = {tfOutput.Stride}";
@@ -687,7 +690,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
string xfb = string.Empty;
- var tfOutput = context.Info.GetTransformFeedbackOutput(attrOffset + c * 4);
+ var tfOutput = context.Config.GetTransformFeedbackOutput(attr, c);
if (tfOutput.Valid)
{
xfb = $", xfb_buffer = {tfOutput.Buffer}, xfb_offset = {tfOutput.Offset}, xfb_stride = {tfOutput.Stride}";
@@ -726,6 +729,20 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
context.AppendLine($"layout (location = {attr}, index = 1) out vec4 {name2};");
}
+ private static bool IsArrayAttributeGlsl(ShaderStage stage, bool isOutAttr)
+ {
+ if (isOutAttr)
+ {
+ return stage == ShaderStage.TessellationControl;
+ }
+ else
+ {
+ return stage == ShaderStage.TessellationControl ||
+ stage == ShaderStage.TessellationEvaluation ||
+ stage == ShaderStage.Geometry;
+ }
+ }
+
private static void DeclareUsedOutputAttributesPerPatch(CodeGenContext context, HashSet<int> attrs)
{
foreach (int attr in attrs.Order())
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/GlslGenerator.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/GlslGenerator.cs
index 90727558..751d0350 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/GlslGenerator.cs
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/GlslGenerator.cs
@@ -1,5 +1,4 @@
using Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions;
-using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using Ryujinx.Graphics.Shader.StructuredIr;
using Ryujinx.Graphics.Shader.Translation;
using System;
@@ -126,21 +125,10 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
}
else if (node is AstAssignment assignment)
{
+ AggregateType dstType = OperandManager.GetNodeDestType(context, assignment.Destination);
AggregateType srcType = OperandManager.GetNodeDestType(context, assignment.Source);
- AggregateType dstType = OperandManager.GetNodeDestType(context, assignment.Destination, isAsgDest: true);
-
- string dest;
-
- if (assignment.Destination is AstOperand operand && operand.Type.IsAttribute())
- {
- bool perPatch = operand.Type == OperandType.AttributePerPatch;
- dest = OperandManager.GetOutAttributeName(context, operand.Value, perPatch);
- }
- else
- {
- dest = InstGen.GetExpression(context, assignment.Destination);
- }
+ string dest = InstGen.GetExpression(context, assignment.Destination);
string src = ReinterpretCast(context, assignment.Source, srcType, dstType);
context.AppendLine(dest + " = " + src + ";");
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs
index 9ca4618d..01bd11e5 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs
@@ -73,7 +73,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
// For shared memory access, the second argument is unused and should be ignored.
// It is there to make both storage and shared access have the same number of arguments.
// For storage, both inputs are consumed when the argument index is 0, so we should skip it here.
- if (argIndex == 1 && (atomic || (inst & Instruction.MrMask) == Instruction.MrShared))
+ if (argIndex == 1 && (atomic || operation.StorageKind == StorageKind.SharedMemory))
{
continue;
}
@@ -85,14 +85,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
if (argIndex == 0 && atomic)
{
- Instruction memRegion = inst & Instruction.MrMask;
-
- switch (memRegion)
+ switch (operation.StorageKind)
{
- case Instruction.MrShared: args += LoadShared(context, operation); break;
- case Instruction.MrStorage: args += LoadStorage(context, operation); break;
+ case StorageKind.SharedMemory: args += LoadShared(context, operation); break;
+ case StorageKind.StorageBuffer: args += LoadStorage(context, operation); break;
- default: throw new InvalidOperationException($"Invalid memory region \"{memRegion}\".");
+ default: throw new InvalidOperationException($"Invalid storage kind \"{operation.StorageKind}\".");
}
}
else
@@ -166,8 +164,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
case Instruction.ImageAtomic:
return ImageLoadOrStore(context, operation);
- case Instruction.LoadAttribute:
- return LoadAttribute(context, operation);
+ case Instruction.Load:
+ return Load(context, operation);
case Instruction.LoadConstant:
return LoadConstant(context, operation);
@@ -193,8 +191,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
case Instruction.PackHalf2x16:
return PackHalf2x16(context, operation);
- case Instruction.StoreAttribute:
- return StoreAttribute(context, operation);
+ case Instruction.Store:
+ return Store(context, operation);
case Instruction.StoreLocal:
return StoreLocal(context, operation);
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs
index 743b695c..00478f6a 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs
@@ -82,7 +82,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
Add(Instruction.ImageStore, InstType.Special);
Add(Instruction.ImageAtomic, InstType.Special);
Add(Instruction.IsNan, InstType.CallUnary, "isnan");
- Add(Instruction.LoadAttribute, InstType.Special);
+ Add(Instruction.Load, InstType.Special);
Add(Instruction.LoadConstant, InstType.Special);
Add(Instruction.LoadLocal, InstType.Special);
Add(Instruction.LoadShared, InstType.Special);
@@ -118,7 +118,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
Add(Instruction.ShuffleXor, InstType.CallQuaternary, HelperFunctionNames.ShuffleXor);
Add(Instruction.Sine, InstType.CallUnary, "sin");
Add(Instruction.SquareRoot, InstType.CallUnary, "sqrt");
- Add(Instruction.StoreAttribute, InstType.Special);
+ Add(Instruction.Store, InstType.Special);
Add(Instruction.StoreLocal, InstType.Special);
Add(Instruction.StoreShared, InstType.Special);
Add(Instruction.StoreShared16, InstType.Special);
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs
index a5d2632c..99519837 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs
@@ -210,30 +210,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
return texCallBuilder.ToString();
}
- public static string LoadAttribute(CodeGenContext context, AstOperation operation)
+ public static string Load(CodeGenContext context, AstOperation operation)
{
- IAstNode src1 = operation.GetSource(0);
- IAstNode src2 = operation.GetSource(1);
- IAstNode src3 = operation.GetSource(2);
-
- if (!(src1 is AstOperand baseAttr) || baseAttr.Type != OperandType.Constant)
- {
- throw new InvalidOperationException($"First input of {nameof(Instruction.LoadAttribute)} must be a constant operand.");
- }
-
- string indexExpr = GetSoureExpr(context, src3, GetSrcVarType(operation.Inst, 2));
-
- if (src2 is AstOperand operand && operand.Type == OperandType.Constant)
- {
- int attrOffset = baseAttr.Value + (operand.Value << 2);
- return OperandManager.GetAttributeName(context, attrOffset, perPatch: false, isOutAttr: false, indexExpr);
- }
- else
- {
- string attrExpr = GetSoureExpr(context, src2, GetSrcVarType(operation.Inst, 1));
- attrExpr = Enclose(attrExpr, src2, Instruction.ShiftRightS32, isLhs: true);
- return OperandManager.GetAttributeName(attrExpr, context.Config, isOutAttr: false, indexExpr);
- }
+ return GenerateLoadOrStore(context, operation, isStore: false);
}
public static string LoadConstant(CodeGenContext context, AstOperation operation)
@@ -337,33 +316,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
return $"textureQueryLod({samplerName}, {coordsExpr}){GetMask(texOp.Index)}";
}
- public static string StoreAttribute(CodeGenContext context, AstOperation operation)
+ public static string Store(CodeGenContext context, AstOperation operation)
{
- IAstNode src1 = operation.GetSource(0);
- IAstNode src2 = operation.GetSource(1);
- IAstNode src3 = operation.GetSource(2);
-
- if (!(src1 is AstOperand baseAttr) || baseAttr.Type != OperandType.Constant)
- {
- throw new InvalidOperationException($"First input of {nameof(Instruction.StoreAttribute)} must be a constant operand.");
- }
-
- string attrName;
-
- if (src2 is AstOperand operand && operand.Type == OperandType.Constant)
- {
- int attrOffset = baseAttr.Value + (operand.Value << 2);
- attrName = OperandManager.GetAttributeName(context, attrOffset, perPatch: false, isOutAttr: true);
- }
- else
- {
- string attrExpr = GetSoureExpr(context, src2, GetSrcVarType(operation.Inst, 1));
- attrExpr = Enclose(attrExpr, src2, Instruction.ShiftRightS32, isLhs: true);
- attrName = OperandManager.GetAttributeName(attrExpr, context.Config, isOutAttr: true);
- }
-
- string value = GetSoureExpr(context, src3, GetSrcVarType(operation.Inst, 2));
- return $"{attrName} = {value}";
+ return GenerateLoadOrStore(context, operation, isStore: true);
}
public static string StoreLocal(CodeGenContext context, AstOperation operation)
@@ -847,6 +802,111 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
}
}
+ private static string GenerateLoadOrStore(CodeGenContext context, AstOperation operation, bool isStore)
+ {
+ StorageKind storageKind = operation.StorageKind;
+
+ string varName;
+ AggregateType varType;
+ int srcIndex = 0;
+
+ switch (storageKind)
+ {
+ case StorageKind.Input:
+ case StorageKind.InputPerPatch:
+ case StorageKind.Output:
+ case StorageKind.OutputPerPatch:
+ if (!(operation.GetSource(srcIndex++) is AstOperand varId) || varId.Type != OperandType.Constant)
+ {
+ throw new InvalidOperationException($"First input of {operation.Inst} with {storageKind} storage must be a constant operand.");
+ }
+
+ IoVariable ioVariable = (IoVariable)varId.Value;
+ bool isOutput = storageKind.IsOutput();
+ bool isPerPatch = storageKind.IsPerPatch();
+ int location = -1;
+ int component = 0;
+
+ if (context.Config.HasPerLocationInputOrOutput(ioVariable, isOutput))
+ {
+ if (!(operation.GetSource(srcIndex++) is AstOperand vecIndex) || vecIndex.Type != OperandType.Constant)
+ {
+ throw new InvalidOperationException($"Second input of {operation.Inst} with {storageKind} storage must be a constant operand.");
+ }
+
+ location = vecIndex.Value;
+
+ if (operation.SourcesCount > srcIndex &&
+ operation.GetSource(srcIndex) is AstOperand elemIndex &&
+ elemIndex.Type == OperandType.Constant &&
+ context.Config.HasPerLocationInputOrOutputComponent(ioVariable, location, elemIndex.Value, isOutput))
+ {
+ component = elemIndex.Value;
+ srcIndex++;
+ }
+ }
+
+ (varName, varType) = IoMap.GetGlslVariable(context.Config, ioVariable, location, component, isOutput, isPerPatch);
+
+ if (IoMap.IsPerVertexBuiltIn(context.Config.Stage, ioVariable, isOutput))
+ {
+ // Since those exist both as input and output on geometry and tessellation shaders,
+ // we need the gl_in and gl_out prefixes to disambiguate.
+
+ if (storageKind == StorageKind.Input)
+ {
+ string expr = GetSoureExpr(context, operation.GetSource(srcIndex++), AggregateType.S32);
+ varName = $"gl_in[{expr}].{varName}";
+ }
+ else if (storageKind == StorageKind.Output)
+ {
+ string expr = GetSoureExpr(context, operation.GetSource(srcIndex++), AggregateType.S32);
+ varName = $"gl_out[{expr}].{varName}";
+ }
+ }
+
+ int firstSrcIndex = srcIndex;
+ int inputsCount = isStore ? operation.SourcesCount - 1 : operation.SourcesCount;
+
+ for (; srcIndex < inputsCount; srcIndex++)
+ {
+ IAstNode src = operation.GetSource(srcIndex);
+
+ if ((varType & AggregateType.ElementCountMask) != 0 &&
+ srcIndex == inputsCount - 1 &&
+ src is AstOperand elementIndex &&
+ elementIndex.Type == OperandType.Constant)
+ {
+ varName += "." + "xyzw"[elementIndex.Value & 3];
+ }
+ else if (srcIndex == firstSrcIndex && context.Config.Stage == ShaderStage.TessellationControl && storageKind == StorageKind.Output)
+ {
+ // GLSL requires that for tessellation control shader outputs,
+ // that the index expression must be *exactly* "gl_InvocationID",
+ // otherwise the compilation fails.
+ // TODO: Get rid of this and use expression propagation to make sure we generate the correct code from IR.
+ varName += "[gl_InvocationID]";
+ }
+ else
+ {
+ varName += $"[{GetSoureExpr(context, src, AggregateType.S32)}]";
+ }
+ }
+ break;
+
+ default:
+ throw new InvalidOperationException($"Invalid storage kind {storageKind}.");
+ }
+
+ if (isStore)
+ {
+ varType &= AggregateType.ElementTypeMask;
+ varName = $"{varName} = {GetSoureExpr(context, operation.GetSource(srcIndex), varType)}";
+ }
+
+ return varName;
+ }
+
private static string GetStorageBufferAccessor(string slotExpr, string offsetExpr, ShaderStage stage)
{
string sbName = OperandManager.GetShaderStagePrefix(stage);
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/IoMap.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/IoMap.cs
new file mode 100644
index 00000000..093ee232
--- /dev/null
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/IoMap.cs
@@ -0,0 +1,145 @@
+using Ryujinx.Graphics.Shader.IntermediateRepresentation;
+using Ryujinx.Graphics.Shader.Translation;
+using System.Globalization;
+
+namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
+{
+ static class IoMap
+ {
+ public static (string, AggregateType) GetGlslVariable(
+ ShaderConfig config,
+ IoVariable ioVariable,
+ int location,
+ int component,
+ bool isOutput,
+ bool isPerPatch)
+ {
+ return ioVariable switch
+ {
+ IoVariable.BackColorDiffuse => ("gl_BackColor", AggregateType.Vector4 | AggregateType.FP32), // Deprecated.
+ IoVariable.BackColorSpecular => ("gl_BackSecondaryColor", AggregateType.Vector4 | AggregateType.FP32), // Deprecated.
+ IoVariable.BaseInstance => ("gl_BaseInstanceARB", AggregateType.S32),
+ IoVariable.BaseVertex => ("gl_BaseVertexARB", AggregateType.S32),
+ IoVariable.ClipDistance => ("gl_ClipDistance", AggregateType.Array | AggregateType.FP32),
+ IoVariable.CtaId => ("gl_WorkGroupID", AggregateType.Vector3 | AggregateType.U32),
+ IoVariable.DrawIndex => ("gl_DrawIDARB", AggregateType.S32),
+ IoVariable.FogCoord => ("gl_FogFragCoord", AggregateType.FP32), // Deprecated.
+ IoVariable.FragmentCoord => ("gl_FragCoord", AggregateType.Vector4 | AggregateType.FP32),
+ IoVariable.FragmentOutputColor => GetFragmentOutputColorVariableName(config, location),
+ IoVariable.FragmentOutputDepth => ("gl_FragDepth", AggregateType.FP32),
+ IoVariable.FragmentOutputIsBgra => (DefaultNames.SupportBlockIsBgraName, AggregateType.Array | AggregateType.Bool),
+ IoVariable.FrontColorDiffuse => ("gl_FrontColor", AggregateType.Vector4 | AggregateType.FP32), // Deprecated.
+ IoVariable.FrontColorSpecular => ("gl_FrontSecondaryColor", AggregateType.Vector4 | AggregateType.FP32), // Deprecated.
+ IoVariable.FrontFacing => ("gl_FrontFacing", AggregateType.Bool),
+ IoVariable.InstanceId => ("gl_InstanceID", AggregateType.S32),
+ IoVariable.InstanceIndex => ("gl_InstanceIndex", AggregateType.S32),
+ IoVariable.InvocationId => ("gl_InvocationID", AggregateType.S32),
+ IoVariable.Layer => ("gl_Layer", AggregateType.S32),
+ IoVariable.PatchVertices => ("gl_PatchVerticesIn", AggregateType.S32),
+ IoVariable.PointCoord => ("gl_PointCoord", AggregateType.Vector2 | AggregateType.FP32),
+ IoVariable.PointSize => ("gl_PointSize", AggregateType.FP32),
+ IoVariable.Position => ("gl_Position", AggregateType.Vector4 | AggregateType.FP32),
+ IoVariable.PrimitiveId => GetPrimitiveIdVariableName(config.Stage, isOutput),
+ IoVariable.SubgroupEqMask => GetSubgroupMaskVariableName(config, "Eq"),
+ IoVariable.SubgroupGeMask => GetSubgroupMaskVariableName(config, "Ge"),
+ IoVariable.SubgroupGtMask => GetSubgroupMaskVariableName(config, "Gt"),
+ IoVariable.SubgroupLaneId => GetSubgroupInvocationIdVariableName(config),
+ IoVariable.SubgroupLeMask => GetSubgroupMaskVariableName(config, "Le"),
+ IoVariable.SubgroupLtMask => GetSubgroupMaskVariableName(config, "Lt"),
+ IoVariable.SupportBlockRenderScale => (DefaultNames.SupportBlockRenderScaleName, AggregateType.Array | AggregateType.FP32),
+ IoVariable.SupportBlockViewInverse => (DefaultNames.SupportBlockViewportInverse, AggregateType.Vector2 | AggregateType.FP32),
+ IoVariable.TessellationCoord => ("gl_TessCoord", AggregateType.Vector3 | AggregateType.FP32),
+ IoVariable.TessellationLevelInner => ("gl_TessLevelInner", AggregateType.Array | AggregateType.FP32),
+ IoVariable.TessellationLevelOuter => ("gl_TessLevelOuter", AggregateType.Array | AggregateType.FP32),
+ IoVariable.TextureCoord => ("gl_TexCoord", AggregateType.Array | AggregateType.Vector4 | AggregateType.FP32), // Deprecated.
+ IoVariable.ThreadId => ("gl_LocalInvocationID", AggregateType.Vector3 | AggregateType.U32),
+ IoVariable.ThreadKill => ("gl_HelperInvocation", AggregateType.Bool),
+ IoVariable.UserDefined => GetUserDefinedVariableName(config, location, component, isOutput, isPerPatch),
+ IoVariable.VertexId => ("gl_VertexID", AggregateType.S32),
+ IoVariable.VertexIndex => ("gl_VertexIndex", AggregateType.S32),
+ IoVariable.ViewportIndex => ("gl_ViewportIndex", AggregateType.S32),
+ IoVariable.ViewportMask => ("gl_ViewportMask", AggregateType.Array | AggregateType.S32),
+ _ => (null, AggregateType.Invalid)
+ };
+ }
+
+ public static bool IsPerVertexBuiltIn(ShaderStage stage, IoVariable ioVariable, bool isOutput)
+ {
+ switch (ioVariable)
+ {
+ case IoVariable.Layer:
+ case IoVariable.ViewportIndex:
+ case IoVariable.PointSize:
+ case IoVariable.Position:
+ case IoVariable.ClipDistance:
+ case IoVariable.PointCoord:
+ case IoVariable.ViewportMask:
+ if (isOutput)
+ {
+ return stage == ShaderStage.TessellationControl;
+ }
+ else
+ {
+ return stage == ShaderStage.TessellationControl ||
+ stage == ShaderStage.TessellationEvaluation ||
+ stage == ShaderStage.Geometry;
+ }
+ }
+
+ return false;
+ }
+
+ private static (string, AggregateType) GetFragmentOutputColorVariableName(ShaderConfig config, int location)
+ {
+ if (location < 0)
+ {
+ return (DefaultNames.OAttributePrefix, config.GetFragmentOutputColorType(0));
+ }
+
+ string name = DefaultNames.OAttributePrefix + location.ToString(CultureInfo.InvariantCulture);
+
+ return (name, config.GetFragmentOutputColorType(location));
+ }
+
+ private static (string, AggregateType) GetPrimitiveIdVariableName(ShaderStage stage, bool isOutput)
+ {
+ // The geometry stage has an additional gl_PrimitiveIDIn variable.
+ return (isOutput || stage != ShaderStage.Geometry ? "gl_PrimitiveID" : "gl_PrimitiveIDIn", AggregateType.S32);
+ }
+
+ private static (string, AggregateType) GetSubgroupMaskVariableName(ShaderConfig config, string cc)
+ {
+ return config.GpuAccessor.QueryHostSupportsShaderBallot()
+ ? ($"unpackUint2x32(gl_SubGroup{cc}MaskARB)", AggregateType.Vector2 | AggregateType.U32)
+ : ($"gl_Subgroup{cc}Mask", AggregateType.Vector4 | AggregateType.U32);
+ }
+
+ private static (string, AggregateType) GetSubgroupInvocationIdVariableName(ShaderConfig config)
+ {
+ return config.GpuAccessor.QueryHostSupportsShaderBallot()
+ ? ("gl_SubGroupInvocationARB", AggregateType.U32)
+ : ("gl_SubgroupInvocationID", AggregateType.U32);
+ }
+
+ private static (string, AggregateType) GetUserDefinedVariableName(ShaderConfig config, int location, int component, bool isOutput, bool isPerPatch)
+ {
+ string name = isPerPatch
+ ? DefaultNames.PerPatchAttributePrefix
+ : (isOutput ? DefaultNames.OAttributePrefix : DefaultNames.IAttributePrefix);
+
+ if (location < 0)
+ {
+ return (name, config.GetUserDefinedType(0, isOutput));
+ }
+
+ name += location.ToString(CultureInfo.InvariantCulture);
+
+ if (config.HasPerLocationInputOrOutputComponent(IoVariable.UserDefined, location, component, isOutput))
+ {
+ name += "_" + "xyzw"[component & 3];
+ }
+
+ return (name, config.GetUserDefinedType(location, isOutput));
+ }
+ }
+} \ No newline at end of file
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