From 4a4ac78373eea1d2453b077299c5afe5a3ca527d Mon Sep 17 00:00:00 2001 From: Isaac Marovitz Date: Thu, 30 May 2024 16:11:48 +0100 Subject: [PATCH] Fix modulo operator Support sample offsets Include FragmentIn as additional arg Always declare frag output struct SubgroupLaneId --- .../CodeGen/Msl/CodeGenContext.cs | 2 +- .../CodeGen/Msl/Declarations.cs | 6 +-- .../CodeGen/Msl/Instructions/InstGenCall.cs | 7 +-- .../CodeGen/Msl/Instructions/InstGenHelper.cs | 2 +- .../CodeGen/Msl/Instructions/InstGenMemory.cs | 49 ++++++++++++++++++- .../CodeGen/Msl/Instructions/IoMap.cs | 1 + .../CodeGen/Msl/MslGenerator.cs | 6 ++- 7 files changed, 61 insertions(+), 12 deletions(-) diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Msl/CodeGenContext.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Msl/CodeGenContext.cs index 0b0d598c5..79c13964c 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Msl/CodeGenContext.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Msl/CodeGenContext.cs @@ -9,7 +9,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Msl public const string Tab = " "; // The number of additional arguments that every function (except for the main one) must have (for instance support_buffer) - public const int additionalArgCount = 1; + public const int AdditionalArgCount = 2; public StructuredFunction CurrentFunction { get; set; } diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Msl/Declarations.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Msl/Declarations.cs index aa641476e..8d4a9c877 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Msl/Declarations.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Msl/Declarations.cs @@ -220,7 +220,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Msl } } - private static void DeclareOutputAttributes(CodeGenContext context, IEnumerable inputs) + private static void DeclareOutputAttributes(CodeGenContext context, IEnumerable outputs) { if (context.Definitions.IaIndexing) { @@ -228,7 +228,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Msl } else { - if (inputs.Any()) + if (outputs.Any() || context.Definitions.Stage == ShaderStage.Fragment) { string prefix = ""; @@ -247,7 +247,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Msl context.EnterScope(); - foreach (var ioDefinition in inputs.OrderBy(x => x.Location)) + foreach (var ioDefinition in outputs.OrderBy(x => x.Location)) { string type = ioDefinition.IoVariable switch { diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Msl/Instructions/InstGenCall.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Msl/Instructions/InstGenCall.cs index f233908c4..5df3aa282 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Msl/Instructions/InstGenCall.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Msl/Instructions/InstGenCall.cs @@ -13,12 +13,13 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Msl.Instructions var functon = context.GetFunction(funcId.Value); int argCount = operation.SourcesCount - 1; - string[] args = new string[argCount + CodeGenContext.additionalArgCount]; + string[] args = new string[argCount + CodeGenContext.AdditionalArgCount]; // Additional arguments - args[0] = "support_buffer"; + args[0] = "in"; + args[1] = "support_buffer"; - int argIndex = CodeGenContext.additionalArgCount; + int argIndex = CodeGenContext.AdditionalArgCount; for (int i = 0; i < argCount; i++) { args[argIndex++] = GetSourceExpr(context, operation.GetSource(i + 1), functon.GetArgumentType(i)); diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Msl/Instructions/InstGenHelper.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Msl/Instructions/InstGenHelper.cs index 8839a1fb5..406fda11a 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Msl/Instructions/InstGenHelper.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Msl/Instructions/InstGenHelper.cs @@ -98,7 +98,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Msl.Instructions Add(Instruction.MemoryBarrier, InstType.Special); Add(Instruction.Minimum, InstType.CallBinary, "min"); Add(Instruction.MinimumU32, InstType.CallBinary, "min"); - Add(Instruction.Modulo, InstType.CallBinary, "%"); + Add(Instruction.Modulo, InstType.CallBinary, "fmod"); Add(Instruction.Multiply, InstType.OpBinaryCom, "*", 1); Add(Instruction.MultiplyHighS32, InstType.CallBinary, "mulhi"); Add(Instruction.MultiplyHighU32, InstType.CallBinary, "mulhi"); diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Msl/Instructions/InstGenMemory.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Msl/Instructions/InstGenMemory.cs index 652b13ee9..28d8007cd 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Msl/Instructions/InstGenMemory.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Msl/Instructions/InstGenMemory.cs @@ -1,3 +1,4 @@ +using Ryujinx.Common.Logging; using Ryujinx.Graphics.Shader.IntermediateRepresentation; using Ryujinx.Graphics.Shader.StructuredIr; using Ryujinx.Graphics.Shader.Translation; @@ -193,11 +194,15 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Msl.Instructions AstTextureOperation texOp = (AstTextureOperation)operation; bool isGather = (texOp.Flags & TextureFlags.Gather) != 0; - bool isShadow = (texOp.Type & SamplerType.Shadow) != 0; + bool hasDerivatives = (texOp.Flags & TextureFlags.Derivatives) != 0; bool intCoords = (texOp.Flags & TextureFlags.IntCoords) != 0; + bool hasLodBias = (texOp.Flags & TextureFlags.LodBias) != 0; bool hasLodLevel = (texOp.Flags & TextureFlags.LodLevel) != 0; + bool hasOffset = (texOp.Flags & TextureFlags.Offset) != 0; + bool hasOffsets = (texOp.Flags & TextureFlags.Offsets) != 0; bool isArray = (texOp.Type & SamplerType.Array) != 0; + bool isShadow = (texOp.Type & SamplerType.Shadow) != 0; bool colorIsVector = isGather || !isShadow; @@ -291,6 +296,16 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Msl.Instructions Append(Src(AggregateType.S32)); } + if (hasDerivatives) + { + Logger.Warning?.PrintMsg(LogClass.Gpu, "Unused sampler derivatives!"); + } + + if (hasLodBias) + { + Logger.Warning?.PrintMsg(LogClass.Gpu, "Unused sample LOD bias!"); + } + if (hasLodLevel) { if (intCoords) @@ -303,7 +318,37 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Msl.Instructions } } - // TODO: Support offsets + string AssembleOffsetVector(int count) + { + if (count > 1) + { + string[] elems = new string[count]; + + for (int index = 0; index < count; index++) + { + elems[index] = Src(AggregateType.S32); + } + + return "int" + count + "(" + string.Join(", ", elems) + ")"; + } + else + { + return Src(AggregateType.S32); + } + } + + // TODO: Support reads with offsets + if (!intCoords) + { + if (hasOffset) + { + Append(AssembleOffsetVector(coordsCount)); + } + else if (hasOffsets) + { + Logger.Warning?.PrintMsg(LogClass.Gpu, "Multiple offsets on gathers are not yet supported!"); + } + } texCall += ")" + (colorIsVector ? GetMaskMultiDest(texOp.Index) : ""); diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Msl/Instructions/IoMap.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Msl/Instructions/IoMap.cs index 6c11b70dc..2e93310aa 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Msl/Instructions/IoMap.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Msl/Instructions/IoMap.cs @@ -33,6 +33,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Msl.Instructions IoVariable.PrimitiveId => ("primitive_id", AggregateType.S32), IoVariable.UserDefined => GetUserDefinedVariableName(definitions, location, component, isOutput, isPerPatch), IoVariable.ThreadId => ("thread_position_in_threadgroup", AggregateType.Vector3 | AggregateType.U32), + IoVariable.SubgroupLaneId => ("thread_index_in_simdgroup", AggregateType.U32), IoVariable.VertexId => ("vertex_id", AggregateType.S32), // gl_VertexIndex does not have a direct equivalent in MSL IoVariable.VertexIndex => ("vertex_id", AggregateType.U32), diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Msl/MslGenerator.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Msl/MslGenerator.cs index 2866574eb..87512a961 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Msl/MslGenerator.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Msl/MslGenerator.cs @@ -63,14 +63,15 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Msl ShaderStage stage, bool isMainFunc = false) { - int additionalArgCount = isMainFunc ? 0 : CodeGenContext.additionalArgCount; + int additionalArgCount = isMainFunc ? 0 : CodeGenContext.AdditionalArgCount; string[] args = new string[additionalArgCount + function.InArguments.Length + function.OutArguments.Length]; // All non-main functions need to be able to access the support_buffer as well if (!isMainFunc) { - args[0] = "constant Struct_support_buffer* support_buffer"; + args[0] = "FragmentIn in"; + args[1] = "constant Struct_support_buffer* support_buffer"; } int argIndex = additionalArgCount; @@ -135,6 +136,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Msl args = args.Append("uint3 threadgroup_position_in_grid [[threadgroup_position_in_grid]]").ToArray(); args = args.Append("uint3 thread_position_in_grid [[thread_position_in_grid]]").ToArray(); args = args.Append("uint3 thread_position_in_threadgroup [[thread_position_in_threadgroup]]").ToArray(); + args = args.Append("uint thread_index_in_simdgroup [[thread_index_in_simdgroup]]").ToArray(); } foreach (var constantBuffer in context.Properties.ConstantBuffers.Values)