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
This commit is contained in:
gdkchan 2023-10-04 19:46:11 -03:00 committed by GitHub
parent f61b7818c3
commit a0af6e4d07
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 33 additions and 49 deletions

View file

@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
private const ushort FileFormatVersionMajor = 1;
private const ushort FileFormatVersionMinor = 2;
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 SharedDataFileName = "shared.data";

View file

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

View file

@ -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)
{
DeclareConstantBuffers(context, context.Properties.ConstantBuffers.Values);

View file

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

View file

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

View file

@ -8,11 +8,15 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
{
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(
IReadOnlyList<Function> functions,
AttributeUsage attributeUsage,
ShaderDefinitions definitions,
ResourceManager resourceManager,
TargetLanguage targetLanguage,
bool debugMode)
{
StructuredProgramContext context = new(attributeUsage, definitions, resourceManager, debugMode);
@ -23,19 +27,19 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
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[] outArguments = new AggregateType[function.OutArgumentsCount];
for (int i = 0; i < inArguments.Length; i++)
{
inArguments[i] = AggregateType.S32;
inArguments[i] = FuncParameterType;
}
for (int i = 0; i < outArguments.Length; i++)
{
outArguments[i] = AggregateType.S32;
outArguments[i] = FuncParameterType;
}
context.EnterFunction(blocks.Length, function.Name, returnType, inArguments, outArguments);
@ -58,7 +62,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
}
else
{
AddOperation(context, operation);
AddOperation(context, operation, targetLanguage);
}
}
}
@ -73,7 +77,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
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;
StorageKind storageKind = operation.StorageKind;
@ -114,10 +118,29 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
IAstNode[] sources = new IAstNode[sourcesCount + outDestsCount];
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
{
for (int index = 0; index < operation.SourcesCount; index++)
{
sources[index] = context.GetOperandOrCbLoad(operation.GetSource(index));
}
}
for (int index = 0; index < outDestsCount; index++)
{

View file

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