Explorar el Código

Use unique temporary variables for function call parameters on SPIR-V (#5757)

* Use unique temporary variables for function call parameters on SPIR-V

* Shader cache version bump
gdkchan hace 2 años
padre
commit
a0af6e4d07

+ 1 - 1
src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs

@@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
         private const ushort FileFormatVersionMajor = 1;
         private const ushort FileFormatVersionMajor = 1;
         private const ushort FileFormatVersionMinor = 2;
         private const ushort FileFormatVersionMinor = 2;
         private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor;
         private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor;
-        private const uint CodeGenVersion = 5750;
+        private const uint CodeGenVersion = 5757;
 
 
         private const string SharedTocFileName = "shared.toc";
         private const string SharedTocFileName = "shared.toc";
         private const string SharedDataFileName = "shared.data";
         private const string SharedDataFileName = "shared.data";

+ 0 - 12
src/Ryujinx.Graphics.Shader/CodeGen/Spirv/CodeGenContext.cs

@@ -44,7 +44,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
 
 
         public StructuredFunction CurrentFunction { get; set; }
         public StructuredFunction CurrentFunction { get; set; }
         private readonly Dictionary<AstOperand, Instruction> _locals = new();
         private readonly Dictionary<AstOperand, Instruction> _locals = new();
-        private readonly Dictionary<int, Instruction[]> _localForArgs = new();
         private readonly Dictionary<int, Instruction> _funcArgs = new();
         private readonly Dictionary<int, Instruction> _funcArgs = new();
         private readonly Dictionary<int, (StructuredFunction, Instruction)> _functions = new();
         private readonly Dictionary<int, (StructuredFunction, Instruction)> _functions = new();
 
 
@@ -112,7 +111,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
             IsMainFunction = isMainFunction;
             IsMainFunction = isMainFunction;
             MayHaveReturned = false;
             MayHaveReturned = false;
             _locals.Clear();
             _locals.Clear();
-            _localForArgs.Clear();
             _funcArgs.Clear();
             _funcArgs.Clear();
         }
         }
 
 
@@ -169,11 +167,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
             _locals.Add(local, spvLocal);
             _locals.Add(local, spvLocal);
         }
         }
 
 
-        public void DeclareLocalForArgs(int funcIndex, Instruction[] spvLocals)
-        {
-            _localForArgs.Add(funcIndex, spvLocals);
-        }
-
         public void DeclareArgument(int argIndex, Instruction spvLocal)
         public void DeclareArgument(int argIndex, Instruction spvLocal)
         {
         {
             _funcArgs.Add(argIndex, spvLocal);
             _funcArgs.Add(argIndex, spvLocal);
@@ -278,11 +271,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
             return _locals[local];
             return _locals[local];
         }
         }
 
 
-        public Instruction[] GetLocalForArgsPointers(int funcIndex)
-        {
-            return _localForArgs[funcIndex];
-        }
-
         public Instruction GetArgumentPointer(AstOperand funcArg)
         public Instruction GetArgumentPointer(AstOperand funcArg)
         {
         {
             return _funcArgs[funcArg.Value];
             return _funcArgs[funcArg.Value];

+ 0 - 22
src/Ryujinx.Graphics.Shader/CodeGen/Spirv/Declarations.cs

@@ -41,28 +41,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
             }
             }
         }
         }
 
 
-        public static void DeclareLocalForArgs(CodeGenContext context, List<StructuredFunction> functions)
-        {
-            for (int funcIndex = 0; funcIndex < functions.Count; funcIndex++)
-            {
-                StructuredFunction function = functions[funcIndex];
-                SpvInstruction[] locals = new SpvInstruction[function.InArguments.Length];
-
-                for (int i = 0; i < function.InArguments.Length; i++)
-                {
-                    var type = function.GetArgumentType(i);
-                    var localPointerType = context.TypePointer(StorageClass.Function, context.GetType(type));
-                    var spvLocal = context.Variable(localPointerType, StorageClass.Function);
-
-                    context.AddLocalVariable(spvLocal);
-
-                    locals[i] = spvLocal;
-                }
-
-                context.DeclareLocalForArgs(funcIndex, locals);
-            }
-        }
-
         public static void DeclareAll(CodeGenContext context, StructuredProgramInfo info)
         public static void DeclareAll(CodeGenContext context, StructuredProgramInfo info)
         {
         {
             DeclareConstantBuffers(context, context.Properties.ConstantBuffers.Values);
             DeclareConstantBuffers(context, context.Properties.ConstantBuffers.Values);

+ 1 - 6
src/Ryujinx.Graphics.Shader/CodeGen/Spirv/Instructions.cs

@@ -311,7 +311,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
             var (function, spvFunc) = context.GetFunction(funcId.Value);
             var (function, spvFunc) = context.GetFunction(funcId.Value);
 
 
             var args = new SpvInstruction[operation.SourcesCount - 1];
             var args = new SpvInstruction[operation.SourcesCount - 1];
-            var spvLocals = context.GetLocalForArgsPointers(funcId.Value);
 
 
             for (int i = 0; i < args.Length; i++)
             for (int i = 0; i < args.Length; i++)
             {
             {
@@ -324,12 +323,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
                 else
                 else
                 {
                 {
                     var type = function.GetArgumentType(i);
                     var type = function.GetArgumentType(i);
-                    var value = context.Get(type, operand);
-                    var spvLocal = spvLocals[i];
 
 
-                    context.Store(spvLocal, value);
-
-                    args[i] = spvLocal;
+                    args[i] = context.Get(type, operand);
                 }
                 }
             }
             }
 
 

+ 0 - 1
src/Ryujinx.Graphics.Shader/CodeGen/Spirv/SpirvGenerator.cs

@@ -161,7 +161,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
             context.EnterBlock(function.MainBlock);
             context.EnterBlock(function.MainBlock);
 
 
             Declarations.DeclareLocals(context, function);
             Declarations.DeclareLocals(context, function);
-            Declarations.DeclareLocalForArgs(context, info.Functions);
 
 
             Generate(context, function.MainBlock);
             Generate(context, function.MainBlock);
 
 

+ 30 - 7
src/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgram.cs

@@ -8,11 +8,15 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
 {
 {
     static class StructuredProgram
     static class StructuredProgram
     {
     {
+        // TODO: Eventually it should be possible to specify the parameter types for the function instead of using S32 for everything.
+        private const AggregateType FuncParameterType = AggregateType.S32;
+
         public static StructuredProgramInfo MakeStructuredProgram(
         public static StructuredProgramInfo MakeStructuredProgram(
             IReadOnlyList<Function> functions,
             IReadOnlyList<Function> functions,
             AttributeUsage attributeUsage,
             AttributeUsage attributeUsage,
             ShaderDefinitions definitions,
             ShaderDefinitions definitions,
             ResourceManager resourceManager,
             ResourceManager resourceManager,
+            TargetLanguage targetLanguage,
             bool debugMode)
             bool debugMode)
         {
         {
             StructuredProgramContext context = new(attributeUsage, definitions, resourceManager, debugMode);
             StructuredProgramContext context = new(attributeUsage, definitions, resourceManager, debugMode);
@@ -23,19 +27,19 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
 
 
                 BasicBlock[] blocks = function.Blocks;
                 BasicBlock[] blocks = function.Blocks;
 
 
-                AggregateType returnType = function.ReturnsValue ? AggregateType.S32 : AggregateType.Void;
+                AggregateType returnType = function.ReturnsValue ? FuncParameterType : AggregateType.Void;
 
 
                 AggregateType[] inArguments = new AggregateType[function.InArgumentsCount];
                 AggregateType[] inArguments = new AggregateType[function.InArgumentsCount];
                 AggregateType[] outArguments = new AggregateType[function.OutArgumentsCount];
                 AggregateType[] outArguments = new AggregateType[function.OutArgumentsCount];
 
 
                 for (int i = 0; i < inArguments.Length; i++)
                 for (int i = 0; i < inArguments.Length; i++)
                 {
                 {
-                    inArguments[i] = AggregateType.S32;
+                    inArguments[i] = FuncParameterType;
                 }
                 }
 
 
                 for (int i = 0; i < outArguments.Length; i++)
                 for (int i = 0; i < outArguments.Length; i++)
                 {
                 {
-                    outArguments[i] = AggregateType.S32;
+                    outArguments[i] = FuncParameterType;
                 }
                 }
 
 
                 context.EnterFunction(blocks.Length, function.Name, returnType, inArguments, outArguments);
                 context.EnterFunction(blocks.Length, function.Name, returnType, inArguments, outArguments);
@@ -58,7 +62,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
                         }
                         }
                         else
                         else
                         {
                         {
-                            AddOperation(context, operation);
+                            AddOperation(context, operation, targetLanguage);
                         }
                         }
                     }
                     }
                 }
                 }
@@ -73,7 +77,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
             return context.Info;
             return context.Info;
         }
         }
 
 
-        private static void AddOperation(StructuredProgramContext context, Operation operation)
+        private static void AddOperation(StructuredProgramContext context, Operation operation, TargetLanguage targetLanguage)
         {
         {
             Instruction inst = operation.Inst;
             Instruction inst = operation.Inst;
             StorageKind storageKind = operation.StorageKind;
             StorageKind storageKind = operation.StorageKind;
@@ -114,9 +118,28 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
 
 
             IAstNode[] sources = new IAstNode[sourcesCount + outDestsCount];
             IAstNode[] sources = new IAstNode[sourcesCount + outDestsCount];
 
 
-            for (int index = 0; index < operation.SourcesCount; index++)
+            if (inst == Instruction.Call && targetLanguage == TargetLanguage.Spirv)
+            {
+                // SPIR-V requires that all function parameters are copied to a local variable before the call
+                // (or at least that's what the Khronos compiler does).
+
+                // First one is the function index.
+                sources[0] = context.GetOperandOrCbLoad(operation.GetSource(0));
+
+                // Remaining ones are parameters, copy them to a temp local variable.
+                for (int index = 1; index < operation.SourcesCount; index++)
+                {
+                    AstOperand argTemp = context.NewTemp(FuncParameterType);
+                    context.AddNode(new AstAssignment(argTemp, context.GetOperandOrCbLoad(operation.GetSource(index))));
+                    sources[index] = argTemp;
+                }
+            }
+            else
             {
             {
-                sources[index] = context.GetOperandOrCbLoad(operation.GetSource(index));
+                for (int index = 0; index < operation.SourcesCount; index++)
+                {
+                    sources[index] = context.GetOperandOrCbLoad(operation.GetSource(index));
+                }
             }
             }
 
 
             for (int index = 0; index < outDestsCount; index++)
             for (int index = 0; index < outDestsCount; index++)

+ 1 - 0
src/Ryujinx.Graphics.Shader/Translation/TranslatorContext.cs

@@ -329,6 +329,7 @@ namespace Ryujinx.Graphics.Shader.Translation
                 attributeUsage,
                 attributeUsage,
                 definitions,
                 definitions,
                 resourceManager,
                 resourceManager,
+                Options.TargetLanguage,
                 Options.Flags.HasFlag(TranslationFlags.DebugMode));
                 Options.Flags.HasFlag(TranslationFlags.DebugMode));
 
 
             int geometryVerticesPerPrimitive = Definitions.OutputTopology switch
             int geometryVerticesPerPrimitive = Definitions.OutputTopology switch