diff options
author | gdkchan <gab.dark.100@gmail.com> | 2020-10-25 17:00:44 -0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-10-25 17:00:44 -0300 |
commit | 49f970d5bd9163e2b4e26a33ef8f84529174d5de (patch) | |
tree | eceaf9c0454d27413ca77689c06a24b47467d1a0 /Ryujinx.Graphics.Shader/StructuredIr/StructuredProgram.cs | |
parent | 973a615d405a83d5fc2f6a11ad12ba63c2a76465 (diff) |
Implement CAL and RET shader instructions (#1618)
* Add support for CAL and RET shader instructions
* Remove unused stuff
* Fix a bug that could cause the wrong values to be passed to a function
* Avoid repopulating function id dictionary every time
* PR feedback
* Fix vertex shader A/B merge
Diffstat (limited to 'Ryujinx.Graphics.Shader/StructuredIr/StructuredProgram.cs')
-rw-r--r-- | Ryujinx.Graphics.Shader/StructuredIr/StructuredProgram.cs | 109 |
1 files changed, 81 insertions, 28 deletions
diff --git a/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgram.cs b/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgram.cs index 65de5218..66570dc9 100644 --- a/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgram.cs +++ b/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgram.cs @@ -8,51 +8,108 @@ namespace Ryujinx.Graphics.Shader.StructuredIr { static class StructuredProgram { - public static StructuredProgramInfo MakeStructuredProgram(BasicBlock[] blocks, ShaderConfig config) + public static StructuredProgramInfo MakeStructuredProgram(Function[] functions, ShaderConfig config) { - PhiFunctions.Remove(blocks); + StructuredProgramContext context = new StructuredProgramContext(config); - StructuredProgramContext context = new StructuredProgramContext(blocks.Length, config); - - for (int blkIndex = 0; blkIndex < blocks.Length; blkIndex++) + for (int funcIndex = 0; funcIndex < functions.Length; funcIndex++) { - BasicBlock block = blocks[blkIndex]; + Function function = functions[funcIndex]; + + BasicBlock[] blocks = function.Blocks; + + VariableType returnType = function.ReturnsValue ? VariableType.S32 : VariableType.None; - context.EnterBlock(block); + VariableType[] inArguments = new VariableType[function.InArgumentsCount]; + VariableType[] outArguments = new VariableType[function.OutArgumentsCount]; - foreach (INode node in block.Operations) + for (int i = 0; i < inArguments.Length; i++) { - Operation operation = (Operation)node; + inArguments[i] = VariableType.S32; + } - if (IsBranchInst(operation.Inst)) - { - context.LeaveBlock(block, operation); - } - else + for (int i = 0; i < outArguments.Length; i++) + { + outArguments[i] = VariableType.S32; + } + + context.EnterFunction(blocks.Length, function.Name, returnType, inArguments, outArguments); + + PhiFunctions.Remove(blocks); + + for (int blkIndex = 0; blkIndex < blocks.Length; blkIndex++) + { + BasicBlock block = blocks[blkIndex]; + + context.EnterBlock(block); + + for (LinkedListNode<INode> opNode = block.Operations.First; opNode != null; opNode = opNode.Next) { - AddOperation(context, operation); + Operation operation = (Operation)opNode.Value; + + if (IsBranchInst(operation.Inst)) + { + context.LeaveBlock(block, operation); + } + else if (operation.Inst != Instruction.CallOutArgument) + { + AddOperation(context, opNode); + } } } - } - GotoElimination.Eliminate(context.GetGotos()); + GotoElimination.Eliminate(context.GetGotos()); - AstOptimizer.Optimize(context); + AstOptimizer.Optimize(context); + + context.LeaveFunction(); + } return context.Info; } - private static void AddOperation(StructuredProgramContext context, Operation operation) + private static void AddOperation(StructuredProgramContext context, LinkedListNode<INode> opNode) { + Operation operation = (Operation)opNode.Value; + Instruction inst = operation.Inst; - IAstNode[] sources = new IAstNode[operation.SourcesCount]; + bool isCall = inst == Instruction.Call; - for (int index = 0; index < sources.Length; index++) + int sourcesCount = operation.SourcesCount; + + List<Operand> callOutOperands = new List<Operand>(); + + if (isCall) + { + LinkedListNode<INode> scan = opNode.Next; + + while (scan != null && scan.Value is Operation nextOp && nextOp.Inst == Instruction.CallOutArgument) + { + callOutOperands.Add(nextOp.Dest); + scan = scan.Next; + } + + sourcesCount += callOutOperands.Count; + } + + IAstNode[] sources = new IAstNode[sourcesCount]; + + for (int index = 0; index < operation.SourcesCount; index++) { sources[index] = context.GetOperandUse(operation.GetSource(index)); } + if (isCall) + { + for (int index = 0; index < callOutOperands.Count; index++) + { + sources[operation.SourcesCount + index] = context.GetOperandDef(callOutOperands[index]); + } + + callOutOperands.Clear(); + } + AstTextureOperation GetAstTextureOperation(TextureOperation texOp) { return new AstTextureOperation( @@ -98,8 +155,6 @@ namespace Ryujinx.Graphics.Shader.StructuredIr AddSBufferUse(context.Info.SBuffers, operation); } - AstAssignment assignment; - // If all the sources are bool, it's better to use short-circuiting // logical operations, rather than forcing a cast to int and doing // a bitwise operation with the value, as it is likely to be used as @@ -152,16 +207,14 @@ namespace Ryujinx.Graphics.Shader.StructuredIr } else if (!isCopy) { - source = new AstOperation(inst, operation.Index, sources); + source = new AstOperation(inst, operation.Index, sources, operation.SourcesCount); } else { source = sources[0]; } - assignment = new AstAssignment(dest, source); - - context.AddNode(assignment); + context.AddNode(new AstAssignment(dest, source)); } else if (operation.Inst == Instruction.Comment) { @@ -182,7 +235,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr AddSBufferUse(context.Info.SBuffers, operation); } - context.AddNode(new AstOperation(inst, operation.Index, sources)); + context.AddNode(new AstOperation(inst, operation.Index, sources, operation.SourcesCount)); } // Those instructions needs to be emulated by using helper functions, |