diff options
Diffstat (limited to 'Ryujinx.Graphics.Shader/CodeGen')
5 files changed, 162 insertions, 48 deletions
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs index e29ff486..3e2e51b0 100644 --- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs +++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs @@ -136,6 +136,22 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl context.AppendLine(); } + else if (context.Config.Stage == ShaderStage.TessellationControl) + { + int threadsPerInputPrimitive = context.Config.ThreadsPerInputPrimitive; + + context.AppendLine($"layout (vertices = {threadsPerInputPrimitive}) out;"); + context.AppendLine(); + } + else if (context.Config.Stage == ShaderStage.TessellationEvaluation) + { + string patchType = context.Config.GpuAccessor.QueryTessPatchType().ToGlsl(); + string spacing = context.Config.GpuAccessor.QueryTessSpacing().ToGlsl(); + string windingOrder = context.Config.GpuAccessor.QueryTessCw() ? "cw" : "ccw"; + + context.AppendLine($"layout ({patchType}, {spacing}, {windingOrder}) in;"); + context.AppendLine(); + } if (context.Config.UsedInputAttributes != 0 || context.Config.GpPassthrough) { @@ -150,6 +166,20 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl context.AppendLine(); } + + if (context.Config.UsedInputAttributesPerPatch != 0) + { + DeclareInputAttributesPerPatch(context, context.Config.UsedInputAttributesPerPatch); + + context.AppendLine(); + } + + if (context.Config.UsedOutputAttributesPerPatch != 0) + { + DeclareUsedOutputAttributesPerPatch(context, context.Config.UsedOutputAttributesPerPatch); + + context.AppendLine(); + } } else { @@ -424,17 +454,25 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl while (usedAttributes != 0) { int index = BitOperations.TrailingZeroCount(usedAttributes); - DeclareInputAttribute(context, info, index); - usedAttributes &= ~(1 << index); } } } + private static void DeclareInputAttributesPerPatch(CodeGenContext context, int usedAttributes) + { + while (usedAttributes != 0) + { + int index = BitOperations.TrailingZeroCount(usedAttributes); + DeclareInputAttributePerPatch(context, index); + usedAttributes &= ~(1 << index); + } + } + private static void DeclareInputAttribute(CodeGenContext context, StructuredProgramInfo info, int attr) { - string suffix = context.Config.Stage == ShaderStage.Geometry ? "[]" : string.Empty; + string suffix = OperandManager.IsArrayAttribute(context.Config.Stage, isOutAttr: false) ? "[]" : string.Empty; string iq = string.Empty; if (context.Config.Stage == ShaderStage.Fragment) @@ -465,6 +503,13 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl } } + private static void DeclareInputAttributePerPatch(CodeGenContext context, int attr) + { + string name = $"{DefaultNames.PerPatchAttributePrefix}{attr}"; + + context.AppendLine($"patch in vec4 {name};"); + } + private static void DeclareOutputAttributes(CodeGenContext context, StructuredProgramInfo info) { if (context.Config.UsedFeatures.HasFlag(FeatureFlags.OaIndexing)) @@ -477,9 +522,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl while (usedAttributes != 0) { int index = BitOperations.TrailingZeroCount(usedAttributes); - DeclareOutputAttribute(context, index); - usedAttributes &= ~(1 << index); } } @@ -487,7 +530,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl private static void DeclareOutputAttribute(CodeGenContext context, int attr) { - string name = $"{DefaultNames.OAttributePrefix}{attr}"; + 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) { @@ -504,6 +548,23 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl } } + private static void DeclareUsedOutputAttributesPerPatch(CodeGenContext context, int usedAttributes) + { + while (usedAttributes != 0) + { + int index = BitOperations.TrailingZeroCount(usedAttributes); + DeclareOutputAttributePerPatch(context, index); + usedAttributes &= ~(1 << index); + } + } + + private static void DeclareOutputAttributePerPatch(CodeGenContext context, int attr) + { + string name = $"{DefaultNames.PerPatchAttributePrefix}{attr}"; + + context.AppendLine($"patch out vec4 {name};"); + } + private static void DeclareSupportUniformBlock(CodeGenContext context, bool isFragment, int scaleElements) { if (!isFragment && scaleElements == 0) diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/DefaultNames.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/DefaultNames.cs index eaf1050c..47350408 100644 --- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/DefaultNames.cs +++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/DefaultNames.cs @@ -7,6 +7,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl public const string SamplerNamePrefix = "tex"; public const string ImageNamePrefix = "img"; + public const string PerPatchAttributePrefix = "patch_attr_"; public const string IAttributePrefix = "in_attr"; public const string OAttributePrefix = "out_attr"; diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/GlslGenerator.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/GlslGenerator.cs index 2d6ede0a..077737c8 100644 --- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/GlslGenerator.cs +++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/GlslGenerator.cs @@ -126,9 +126,10 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl string dest; - if (assignment.Destination is AstOperand operand && operand.Type == OperandType.Attribute) + if (assignment.Destination is AstOperand operand && operand.Type.IsAttribute()) { - dest = OperandManager.GetOutAttributeName(operand.Value, context.Config); + bool perPatch = operand.Type == OperandType.AttributePerPatch; + dest = OperandManager.GetOutAttributeName(operand.Value, context.Config, perPatch); } else { diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs index edaacd3e..5e46bb46 100644 --- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs +++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs @@ -200,7 +200,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions if (src2 is AstOperand operand && operand.Type == OperandType.Constant) { - return OperandManager.GetAttributeName(baseAttr.Value + (operand.Value << 2), context.Config, isOutAttr: false, indexExpr); + int attrOffset = baseAttr.Value + (operand.Value << 2); + return OperandManager.GetAttributeName(attrOffset, context.Config, perPatch: false, isOutAttr: false, indexExpr); } else { @@ -326,7 +327,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions if (src2 is AstOperand operand && operand.Type == OperandType.Constant) { - attrName = OperandManager.GetAttributeName(baseAttr.Value + (operand.Value << 2), context.Config, isOutAttr: true); + int attrOffset = baseAttr.Value + (operand.Value << 2); + attrName = OperandManager.GetAttributeName(attrOffset, context.Config, perPatch: false, isOutAttr: true); } else { diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs index d35525f9..9680df27 100644 --- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs +++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs @@ -29,27 +29,33 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl private static Dictionary<int, BuiltInAttribute> _builtInAttributes = new Dictionary<int, BuiltInAttribute>() { - { AttributeConsts.Layer, new BuiltInAttribute("gl_Layer", VariableType.S32) }, - { AttributeConsts.PointSize, new BuiltInAttribute("gl_PointSize", VariableType.F32) }, - { AttributeConsts.PositionX, new BuiltInAttribute("gl_Position.x", VariableType.F32) }, - { AttributeConsts.PositionY, new BuiltInAttribute("gl_Position.y", VariableType.F32) }, - { AttributeConsts.PositionZ, new BuiltInAttribute("gl_Position.z", VariableType.F32) }, - { AttributeConsts.PositionW, new BuiltInAttribute("gl_Position.w", VariableType.F32) }, - { AttributeConsts.ClipDistance0, new BuiltInAttribute("gl_ClipDistance[0]", VariableType.F32) }, - { AttributeConsts.ClipDistance1, new BuiltInAttribute("gl_ClipDistance[1]", VariableType.F32) }, - { AttributeConsts.ClipDistance2, new BuiltInAttribute("gl_ClipDistance[2]", VariableType.F32) }, - { AttributeConsts.ClipDistance3, new BuiltInAttribute("gl_ClipDistance[3]", VariableType.F32) }, - { AttributeConsts.ClipDistance4, new BuiltInAttribute("gl_ClipDistance[4]", VariableType.F32) }, - { AttributeConsts.ClipDistance5, new BuiltInAttribute("gl_ClipDistance[5]", VariableType.F32) }, - { AttributeConsts.ClipDistance6, new BuiltInAttribute("gl_ClipDistance[6]", VariableType.F32) }, - { AttributeConsts.ClipDistance7, new BuiltInAttribute("gl_ClipDistance[7]", VariableType.F32) }, - { AttributeConsts.PointCoordX, new BuiltInAttribute("gl_PointCoord.x", VariableType.F32) }, - { AttributeConsts.PointCoordY, new BuiltInAttribute("gl_PointCoord.y", VariableType.F32) }, - { AttributeConsts.TessCoordX, new BuiltInAttribute("gl_TessCoord.x", VariableType.F32) }, - { AttributeConsts.TessCoordY, new BuiltInAttribute("gl_TessCoord.y", VariableType.F32) }, - { AttributeConsts.InstanceId, new BuiltInAttribute("gl_InstanceID", VariableType.S32) }, - { AttributeConsts.VertexId, new BuiltInAttribute("gl_VertexID", VariableType.S32) }, - { AttributeConsts.FrontFacing, new BuiltInAttribute("gl_FrontFacing", VariableType.Bool) }, + { AttributeConsts.TessLevelOuter0, new BuiltInAttribute("gl_TessLevelOuter[0]", VariableType.F32) }, + { AttributeConsts.TessLevelOuter1, new BuiltInAttribute("gl_TessLevelOuter[1]", VariableType.F32) }, + { AttributeConsts.TessLevelOuter2, new BuiltInAttribute("gl_TessLevelOuter[2]", VariableType.F32) }, + { AttributeConsts.TessLevelOuter3, new BuiltInAttribute("gl_TessLevelOuter[3]", VariableType.F32) }, + { AttributeConsts.TessLevelInner0, new BuiltInAttribute("gl_TessLevelInner[0]", VariableType.F32) }, + { AttributeConsts.TessLevelInner1, new BuiltInAttribute("gl_TessLevelInner[1]", VariableType.F32) }, + { AttributeConsts.Layer, new BuiltInAttribute("gl_Layer", VariableType.S32) }, + { AttributeConsts.PointSize, new BuiltInAttribute("gl_PointSize", VariableType.F32) }, + { AttributeConsts.PositionX, new BuiltInAttribute("gl_Position.x", VariableType.F32) }, + { AttributeConsts.PositionY, new BuiltInAttribute("gl_Position.y", VariableType.F32) }, + { AttributeConsts.PositionZ, new BuiltInAttribute("gl_Position.z", VariableType.F32) }, + { AttributeConsts.PositionW, new BuiltInAttribute("gl_Position.w", VariableType.F32) }, + { AttributeConsts.ClipDistance0, new BuiltInAttribute("gl_ClipDistance[0]", VariableType.F32) }, + { AttributeConsts.ClipDistance1, new BuiltInAttribute("gl_ClipDistance[1]", VariableType.F32) }, + { AttributeConsts.ClipDistance2, new BuiltInAttribute("gl_ClipDistance[2]", VariableType.F32) }, + { AttributeConsts.ClipDistance3, new BuiltInAttribute("gl_ClipDistance[3]", VariableType.F32) }, + { AttributeConsts.ClipDistance4, new BuiltInAttribute("gl_ClipDistance[4]", VariableType.F32) }, + { AttributeConsts.ClipDistance5, new BuiltInAttribute("gl_ClipDistance[5]", VariableType.F32) }, + { AttributeConsts.ClipDistance6, new BuiltInAttribute("gl_ClipDistance[6]", VariableType.F32) }, + { AttributeConsts.ClipDistance7, new BuiltInAttribute("gl_ClipDistance[7]", VariableType.F32) }, + { AttributeConsts.PointCoordX, new BuiltInAttribute("gl_PointCoord.x", VariableType.F32) }, + { AttributeConsts.PointCoordY, new BuiltInAttribute("gl_PointCoord.y", VariableType.F32) }, + { AttributeConsts.TessCoordX, new BuiltInAttribute("gl_TessCoord.x", VariableType.F32) }, + { AttributeConsts.TessCoordY, new BuiltInAttribute("gl_TessCoord.y", VariableType.F32) }, + { AttributeConsts.InstanceId, new BuiltInAttribute("gl_InstanceID", VariableType.S32) }, + { AttributeConsts.VertexId, new BuiltInAttribute("gl_VertexID", VariableType.S32) }, + { AttributeConsts.FrontFacing, new BuiltInAttribute("gl_FrontFacing", VariableType.Bool) }, // Special. { AttributeConsts.FragmentOutputDepth, new BuiltInAttribute("gl_FragDepth", VariableType.F32) }, @@ -61,6 +67,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl { AttributeConsts.CtaIdY, new BuiltInAttribute("gl_WorkGroupID.y", VariableType.U32) }, { AttributeConsts.CtaIdZ, new BuiltInAttribute("gl_WorkGroupID.z", VariableType.U32) }, { AttributeConsts.LaneId, new BuiltInAttribute(null, VariableType.U32) }, + { AttributeConsts.InvocationId, new BuiltInAttribute("gl_InvocationID", VariableType.S32) }, + { AttributeConsts.PrimitiveId, new BuiltInAttribute("gl_PrimitiveID", VariableType.S32) }, + { AttributeConsts.PatchVerticesIn, new BuiltInAttribute("gl_PatchVerticesIn", VariableType.S32) }, { AttributeConsts.EqMask, new BuiltInAttribute(null, VariableType.U32) }, { AttributeConsts.GeMask, new BuiltInAttribute(null, VariableType.U32) }, { AttributeConsts.GtMask, new BuiltInAttribute(null, VariableType.U32) }, @@ -99,19 +108,21 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl return operand.Type switch { OperandType.Argument => GetArgumentName(operand.Value), - OperandType.Attribute => GetAttributeName(operand.Value, config), + OperandType.Attribute => GetAttributeName(operand.Value, config, perPatch: false), + OperandType.AttributePerPatch => GetAttributeName(operand.Value, config, perPatch: true), OperandType.Constant => NumberFormatter.FormatInt(operand.Value), - OperandType.ConstantBuffer => GetConstantBufferName( - operand.CbufSlot, - operand.CbufOffset, - config.Stage, - config.UsedFeatures.HasFlag(FeatureFlags.CbIndexing)), + OperandType.ConstantBuffer => GetConstantBufferName(operand, config), OperandType.LocalVariable => _locals[operand], OperandType.Undefined => DefaultNames.UndefinedName, _ => throw new ArgumentException($"Invalid operand type \"{operand.Type}\".") }; } + private static string GetConstantBufferName(AstOperand operand, ShaderConfig config) + { + return GetConstantBufferName(operand.CbufSlot, operand.CbufOffset, config.Stage, config.UsedFeatures.HasFlag(FeatureFlags.CbIndexing)); + } + public static string GetConstantBufferName(int slot, int offset, ShaderStage stage, bool cbIndexable) { return $"{GetUbName(stage, slot, cbIndexable)}[{offset >> 2}].{GetSwizzleMask(offset & 3)}"; @@ -142,14 +153,19 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl return GetVec4Indexed(GetUbName(stage, slotExpr) + $"[{offsetExpr} >> 2]", offsetExpr + " & 3", indexElement); } - public static string GetOutAttributeName(int value, ShaderConfig config) + public static string GetOutAttributeName(int value, ShaderConfig config, bool perPatch) { - return GetAttributeName(value, config, isOutAttr: true); + return GetAttributeName(value, config, perPatch, isOutAttr: true); } - public static string GetAttributeName(int value, ShaderConfig config, bool isOutAttr = false, string indexExpr = "0") + public static string GetAttributeName(int value, ShaderConfig config, bool perPatch, bool isOutAttr = false, string indexExpr = "0") { - value &= ~3; + if ((value & AttributeConsts.LoadOutputMask) != 0) + { + isOutAttr = true; + } + + value &= AttributeConsts.Mask & ~3; char swzMask = GetSwizzleMask((value >> 2) & 3); if (value >= AttributeConsts.UserAttributeBase && value < AttributeConsts.UserAttributeEnd) @@ -160,7 +176,14 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl ? DefaultNames.OAttributePrefix : DefaultNames.IAttributePrefix; - if (config.UsedFeatures.HasFlag(isOutAttr ? FeatureFlags.OaIndexing : FeatureFlags.IaIndexing)) + bool indexable = config.UsedFeatures.HasFlag(isOutAttr ? FeatureFlags.OaIndexing : FeatureFlags.IaIndexing); + + if (!indexable && perPatch) + { + prefix = DefaultNames.PerPatchAttributePrefix; + } + + if (indexable) { string name = prefix; @@ -175,9 +198,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl { string name = $"{prefix}{(value >> 4)}_{swzMask}"; - if (config.Stage == ShaderStage.Geometry && !isOutAttr) + if (!perPatch && IsArrayAttribute(config.Stage, isOutAttr)) { - name += $"[{indexExpr}]"; + name += isOutAttr ? "[gl_InvocationID]" : $"[{indexExpr}]"; } return name; @@ -186,9 +209,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl { string name = $"{prefix}{(value >> 4)}"; - if (config.Stage == ShaderStage.Geometry && !isOutAttr) + if (!perPatch && IsArrayAttribute(config.Stage, isOutAttr)) { - name += $"[{indexExpr}]"; + name += isOutAttr ? "[gl_InvocationID]" : $"[{indexExpr}]"; } return name + '.' + swzMask; @@ -250,9 +273,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl string name = builtInAttr.Name; - if (config.Stage == ShaderStage.Geometry && (value & AttributeConsts.SpecialMask) == 0 && !isOutAttr) + if (!perPatch && IsArrayAttribute(config.Stage, isOutAttr) && IsArrayBuiltIn(value)) { - name = $"gl_in[{indexExpr}].{name}"; + name = isOutAttr ? $"gl_out[gl_InvocationID].{name}" : $"gl_in[{indexExpr}].{name}"; } return name; @@ -278,6 +301,32 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl return $"{name}[{attrExpr} >> 2][{attrExpr} & 3]"; } + public static bool IsArrayAttribute(ShaderStage stage, bool isOutAttr) + { + if (isOutAttr) + { + return stage == ShaderStage.TessellationControl; + } + else + { + return stage == ShaderStage.TessellationControl || + stage == ShaderStage.TessellationEvaluation || + stage == ShaderStage.Geometry; + } + } + + private static bool IsArrayBuiltIn(int attr) + { + if (attr <= AttributeConsts.TessLevelInner1 || + attr == AttributeConsts.TessCoordX || + attr == AttributeConsts.TessCoordY) + { + return false; + } + + return (attr & AttributeConsts.SpecialMask) == 0; + } + public static string GetUbName(ShaderStage stage, int slot, bool cbIndexable) { if (cbIndexable) |
