diff options
author | gdkchan <gab.dark.100@gmail.com> | 2023-04-25 19:51:07 -0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-04-25 19:51:07 -0300 |
commit | 9f12e50a546b15533778ed0d8290202af91c10a2 (patch) | |
tree | f0e77a7b7c605face5ef29270b4248af2682301a /Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs | |
parent | 097562bc6c227c42f803ce1078fcb4adf06cd20c (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.cs | 345 |
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 |