diff options
| author | gdk <gab.dark.100@gmail.com> | 2019-10-13 03:02:07 -0300 |
|---|---|---|
| committer | Thog <thog@protonmail.com> | 2020-01-09 02:13:00 +0100 |
| commit | 1876b346fea647e8284a66bb6d62c38801035cff (patch) | |
| tree | 6eeff094298cda84d1613dc5ec0691e51d7b35f1 /Ryujinx.Graphics/Shader/StructuredIr | |
| parent | f617fb542a0e3d36012d77a4b5acbde7b08902f2 (diff) | |
Initial work
Diffstat (limited to 'Ryujinx.Graphics/Shader/StructuredIr')
20 files changed, 0 insertions, 1921 deletions
diff --git a/Ryujinx.Graphics/Shader/StructuredIr/AstAssignment.cs b/Ryujinx.Graphics/Shader/StructuredIr/AstAssignment.cs deleted file mode 100644 index bb3fe7af..00000000 --- a/Ryujinx.Graphics/Shader/StructuredIr/AstAssignment.cs +++ /dev/null @@ -1,35 +0,0 @@ -using static Ryujinx.Graphics.Shader.StructuredIr.AstHelper; - -namespace Ryujinx.Graphics.Shader.StructuredIr -{ - class AstAssignment : AstNode - { - public IAstNode Destination { get; } - - private IAstNode _source; - - public IAstNode Source - { - get - { - return _source; - } - set - { - RemoveUse(_source, this); - - AddUse(value, this); - - _source = value; - } - } - - public AstAssignment(IAstNode destination, IAstNode source) - { - Destination = destination; - Source = source; - - AddDef(destination, this); - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Graphics/Shader/StructuredIr/AstBlock.cs b/Ryujinx.Graphics/Shader/StructuredIr/AstBlock.cs deleted file mode 100644 index fdef87de..00000000 --- a/Ryujinx.Graphics/Shader/StructuredIr/AstBlock.cs +++ /dev/null @@ -1,116 +0,0 @@ -using Ryujinx.Graphics.Shader.IntermediateRepresentation; -using System; -using System.Collections; -using System.Collections.Generic; - -using static Ryujinx.Graphics.Shader.StructuredIr.AstHelper; - -namespace Ryujinx.Graphics.Shader.StructuredIr -{ - class AstBlock : AstNode, IEnumerable<IAstNode> - { - public AstBlockType Type { get; private set; } - - private IAstNode _condition; - - public IAstNode Condition - { - get - { - return _condition; - } - set - { - RemoveUse(_condition, this); - - AddUse(value, this); - - _condition = value; - } - } - - private LinkedList<IAstNode> _nodes; - - public IAstNode First => _nodes.First?.Value; - - public int Count => _nodes.Count; - - public AstBlock(AstBlockType type, IAstNode condition = null) - { - Type = type; - Condition = condition; - - _nodes = new LinkedList<IAstNode>(); - } - - public void Add(IAstNode node) - { - Add(node, _nodes.AddLast(node)); - } - - public void AddFirst(IAstNode node) - { - Add(node, _nodes.AddFirst(node)); - } - - public void AddBefore(IAstNode next, IAstNode node) - { - Add(node, _nodes.AddBefore(next.LLNode, node)); - } - - public void AddAfter(IAstNode prev, IAstNode node) - { - Add(node, _nodes.AddAfter(prev.LLNode, node)); - } - - private void Add(IAstNode node, LinkedListNode<IAstNode> newNode) - { - if (node.Parent != null) - { - throw new ArgumentException("Node already belongs to a block."); - } - - node.Parent = this; - node.LLNode = newNode; - } - - public void Remove(IAstNode node) - { - _nodes.Remove(node.LLNode); - - node.Parent = null; - node.LLNode = null; - } - - public void AndCondition(IAstNode cond) - { - Condition = new AstOperation(Instruction.LogicalAnd, Condition, cond); - } - - public void OrCondition(IAstNode cond) - { - Condition = new AstOperation(Instruction.LogicalOr, Condition, cond); - } - public void TurnIntoIf(IAstNode cond) - { - Condition = cond; - - Type = AstBlockType.If; - } - - public void TurnIntoElseIf() - { - Type = AstBlockType.ElseIf; - } - - public IEnumerator<IAstNode> GetEnumerator() - { - return _nodes.GetEnumerator(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Graphics/Shader/StructuredIr/AstBlockType.cs b/Ryujinx.Graphics/Shader/StructuredIr/AstBlockType.cs deleted file mode 100644 index c12efda9..00000000 --- a/Ryujinx.Graphics/Shader/StructuredIr/AstBlockType.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace Ryujinx.Graphics.Shader.StructuredIr -{ - enum AstBlockType - { - DoWhile, - If, - Else, - ElseIf, - Main, - While - } -}
\ No newline at end of file diff --git a/Ryujinx.Graphics/Shader/StructuredIr/AstBlockVisitor.cs b/Ryujinx.Graphics/Shader/StructuredIr/AstBlockVisitor.cs deleted file mode 100644 index 10d5dce0..00000000 --- a/Ryujinx.Graphics/Shader/StructuredIr/AstBlockVisitor.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System; -using System.Collections.Generic; - -using static Ryujinx.Graphics.Shader.StructuredIr.AstHelper; - -namespace Ryujinx.Graphics.Shader.StructuredIr -{ - class AstBlockVisitor - { - public AstBlock Block { get; private set; } - - public class BlockVisitationEventArgs : EventArgs - { - public AstBlock Block { get; } - - public BlockVisitationEventArgs(AstBlock block) - { - Block = block; - } - } - - public event EventHandler<BlockVisitationEventArgs> BlockEntered; - public event EventHandler<BlockVisitationEventArgs> BlockLeft; - - public AstBlockVisitor(AstBlock mainBlock) - { - Block = mainBlock; - } - - public IEnumerable<IAstNode> Visit() - { - IAstNode node = Block.First; - - while (node != null) - { - // We reached a child block, visit the nodes inside. - while (node is AstBlock childBlock) - { - Block = childBlock; - - node = childBlock.First; - - BlockEntered?.Invoke(this, new BlockVisitationEventArgs(Block)); - } - - // Node may be null, if the block is empty. - if (node != null) - { - IAstNode next = Next(node); - - yield return node; - - node = next; - } - - // We reached the end of the list, go up on tree to the parent blocks. - while (node == null && Block.Type != AstBlockType.Main) - { - BlockLeft?.Invoke(this, new BlockVisitationEventArgs(Block)); - - node = Next(Block); - - Block = Block.Parent; - } - } - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Graphics/Shader/StructuredIr/AstHelper.cs b/Ryujinx.Graphics/Shader/StructuredIr/AstHelper.cs deleted file mode 100644 index 9d3148e1..00000000 --- a/Ryujinx.Graphics/Shader/StructuredIr/AstHelper.cs +++ /dev/null @@ -1,73 +0,0 @@ -using Ryujinx.Graphics.Shader.IntermediateRepresentation; - -namespace Ryujinx.Graphics.Shader.StructuredIr -{ - static class AstHelper - { - public static void AddUse(IAstNode node, IAstNode parent) - { - if (node is AstOperand operand && operand.Type == OperandType.LocalVariable) - { - operand.Uses.Add(parent); - } - } - - public static void AddDef(IAstNode node, IAstNode parent) - { - if (node is AstOperand operand && operand.Type == OperandType.LocalVariable) - { - operand.Defs.Add(parent); - } - } - - public static void RemoveUse(IAstNode node, IAstNode parent) - { - if (node is AstOperand operand && operand.Type == OperandType.LocalVariable) - { - operand.Uses.Remove(parent); - } - } - - public static void RemoveDef(IAstNode node, IAstNode parent) - { - if (node is AstOperand operand && operand.Type == OperandType.LocalVariable) - { - operand.Defs.Remove(parent); - } - } - - public static AstAssignment Assign(IAstNode destination, IAstNode source) - { - return new AstAssignment(destination, source); - } - - public static AstOperand Const(int value) - { - return new AstOperand(OperandType.Constant, value); - } - - public static AstOperand Local(VariableType type) - { - AstOperand local = new AstOperand(OperandType.LocalVariable); - - local.VarType = type; - - return local; - } - - public static IAstNode InverseCond(IAstNode cond) - { - return new AstOperation(Instruction.LogicalNot, cond); - } - - public static IAstNode Next(IAstNode node) - { - return node.LLNode.Next?.Value; - } - - public static IAstNode Previous(IAstNode node) - { - return node.LLNode.Previous?.Value; - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Graphics/Shader/StructuredIr/AstNode.cs b/Ryujinx.Graphics/Shader/StructuredIr/AstNode.cs deleted file mode 100644 index c667aac9..00000000 --- a/Ryujinx.Graphics/Shader/StructuredIr/AstNode.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System.Collections.Generic; - -namespace Ryujinx.Graphics.Shader.StructuredIr -{ - class AstNode : IAstNode - { - public AstBlock Parent { get; set; } - - public LinkedListNode<IAstNode> LLNode { get; set; } - } -}
\ No newline at end of file diff --git a/Ryujinx.Graphics/Shader/StructuredIr/AstOperand.cs b/Ryujinx.Graphics/Shader/StructuredIr/AstOperand.cs deleted file mode 100644 index 97ff3ca9..00000000 --- a/Ryujinx.Graphics/Shader/StructuredIr/AstOperand.cs +++ /dev/null @@ -1,49 +0,0 @@ -using Ryujinx.Graphics.Shader.IntermediateRepresentation; -using System.Collections.Generic; - -namespace Ryujinx.Graphics.Shader.StructuredIr -{ - class AstOperand : AstNode - { - public HashSet<IAstNode> Defs { get; } - public HashSet<IAstNode> Uses { get; } - - public OperandType Type { get; } - - public VariableType VarType { get; set; } - - public int Value { get; } - - public int CbufSlot { get; } - public int CbufOffset { get; } - - private AstOperand() - { - Defs = new HashSet<IAstNode>(); - Uses = new HashSet<IAstNode>(); - - VarType = VariableType.S32; - } - - public AstOperand(Operand operand) : this() - { - Type = operand.Type; - - if (Type == OperandType.ConstantBuffer) - { - CbufSlot = operand.GetCbufSlot(); - CbufOffset = operand.GetCbufOffset(); - } - else - { - Value = operand.Value; - } - } - - public AstOperand(OperandType type, int value = 0) : this() - { - Type = type; - Value = value; - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Graphics/Shader/StructuredIr/AstOperation.cs b/Ryujinx.Graphics/Shader/StructuredIr/AstOperation.cs deleted file mode 100644 index 1607ffec..00000000 --- a/Ryujinx.Graphics/Shader/StructuredIr/AstOperation.cs +++ /dev/null @@ -1,49 +0,0 @@ -using Ryujinx.Graphics.Shader.IntermediateRepresentation; - -using static Ryujinx.Graphics.Shader.StructuredIr.AstHelper; - -namespace Ryujinx.Graphics.Shader.StructuredIr -{ - class AstOperation : AstNode - { - public Instruction Inst { get; } - - public int ComponentMask { get; } - - private IAstNode[] _sources; - - public int SourcesCount => _sources.Length; - - public AstOperation(Instruction inst, params IAstNode[] sources) - { - Inst = inst; - _sources = sources; - - foreach (IAstNode source in sources) - { - AddUse(source, this); - } - - ComponentMask = 1; - } - - public AstOperation(Instruction inst, int compMask, params IAstNode[] sources) : this(inst, sources) - { - ComponentMask = compMask; - } - - public IAstNode GetSource(int index) - { - return _sources[index]; - } - - public void SetSource(int index, IAstNode source) - { - RemoveUse(_sources[index], this); - - AddUse(source, this); - - _sources[index] = source; - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Graphics/Shader/StructuredIr/AstOptimizer.cs b/Ryujinx.Graphics/Shader/StructuredIr/AstOptimizer.cs deleted file mode 100644 index 0f5392b7..00000000 --- a/Ryujinx.Graphics/Shader/StructuredIr/AstOptimizer.cs +++ /dev/null @@ -1,149 +0,0 @@ -using Ryujinx.Graphics.Shader.IntermediateRepresentation; -using System.Collections.Generic; -using System.Linq; - -using static Ryujinx.Graphics.Shader.StructuredIr.AstHelper; - -namespace Ryujinx.Graphics.Shader.StructuredIr -{ - static class AstOptimizer - { - public static void Optimize(StructuredProgramInfo info) - { - AstBlock mainBlock = info.MainBlock; - - AstBlockVisitor visitor = new AstBlockVisitor(mainBlock); - - foreach (IAstNode node in visitor.Visit()) - { - if (node is AstAssignment assignment && assignment.Destination is AstOperand propVar) - { - bool isWorthPropagating = propVar.Uses.Count == 1 || IsWorthPropagating(assignment.Source); - - if (propVar.Defs.Count == 1 && isWorthPropagating) - { - PropagateExpression(propVar, assignment.Source); - } - - if (propVar.Type == OperandType.LocalVariable && propVar.Uses.Count == 0) - { - visitor.Block.Remove(assignment); - - info.Locals.Remove(propVar); - } - } - } - - RemoveEmptyBlocks(mainBlock); - } - - private static bool IsWorthPropagating(IAstNode source) - { - if (!(source is AstOperation srcOp)) - { - return false; - } - - if (!InstructionInfo.IsUnary(srcOp.Inst)) - { - return false; - } - - return srcOp.GetSource(0) is AstOperand || srcOp.Inst == Instruction.Copy; - } - - private static void PropagateExpression(AstOperand propVar, IAstNode source) - { - IAstNode[] uses = propVar.Uses.ToArray(); - - foreach (IAstNode useNode in uses) - { - if (useNode is AstBlock useBlock) - { - useBlock.Condition = source; - } - else if (useNode is AstOperation useOperation) - { - for (int srcIndex = 0; srcIndex < useOperation.SourcesCount; srcIndex++) - { - if (useOperation.GetSource(srcIndex) == propVar) - { - useOperation.SetSource(srcIndex, source); - } - } - } - else if (useNode is AstAssignment useAssignment) - { - useAssignment.Source = source; - } - } - } - - private static void RemoveEmptyBlocks(AstBlock mainBlock) - { - Queue<AstBlock> pending = new Queue<AstBlock>(); - - pending.Enqueue(mainBlock); - - while (pending.TryDequeue(out AstBlock block)) - { - foreach (IAstNode node in block) - { - if (node is AstBlock childBlock) - { - pending.Enqueue(childBlock); - } - } - - AstBlock parent = block.Parent; - - if (parent == null) - { - continue; - } - - AstBlock nextBlock = Next(block) as AstBlock; - - bool hasElse = nextBlock != null && nextBlock.Type == AstBlockType.Else; - - bool isIf = block.Type == AstBlockType.If; - - if (block.Count == 0) - { - if (isIf) - { - if (hasElse) - { - nextBlock.TurnIntoIf(InverseCond(block.Condition)); - } - - parent.Remove(block); - } - else if (block.Type == AstBlockType.Else) - { - parent.Remove(block); - } - } - else if (isIf && parent.Type == AstBlockType.Else && parent.Count == (hasElse ? 2 : 1)) - { - AstBlock parentOfParent = parent.Parent; - - parent.Remove(block); - - parentOfParent.AddAfter(parent, block); - - if (hasElse) - { - parent.Remove(nextBlock); - - parentOfParent.AddAfter(block, nextBlock); - } - - parentOfParent.Remove(parent); - - block.TurnIntoElseIf(); - } - } - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Graphics/Shader/StructuredIr/AstTextureOperation.cs b/Ryujinx.Graphics/Shader/StructuredIr/AstTextureOperation.cs deleted file mode 100644 index e40f7b70..00000000 --- a/Ryujinx.Graphics/Shader/StructuredIr/AstTextureOperation.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Ryujinx.Graphics.Shader.IntermediateRepresentation; - -namespace Ryujinx.Graphics.Shader.StructuredIr -{ - class AstTextureOperation : AstOperation - { - public TextureType Type { get; } - public TextureFlags Flags { get; } - - public int Handle { get; } - - public AstTextureOperation( - Instruction inst, - TextureType type, - TextureFlags flags, - int handle, - int compMask, - params IAstNode[] sources) : base(inst, compMask, sources) - { - Type = type; - Flags = flags; - Handle = handle; - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Graphics/Shader/StructuredIr/GotoElimination.cs b/Ryujinx.Graphics/Shader/StructuredIr/GotoElimination.cs deleted file mode 100644 index 8bcf9d9c..00000000 --- a/Ryujinx.Graphics/Shader/StructuredIr/GotoElimination.cs +++ /dev/null @@ -1,459 +0,0 @@ -using Ryujinx.Graphics.Shader.IntermediateRepresentation; -using System; -using System.Collections.Generic; - -using static Ryujinx.Graphics.Shader.StructuredIr.AstHelper; - -namespace Ryujinx.Graphics.Shader.StructuredIr -{ - static class GotoElimination - { - // This is a modified version of the algorithm presented on the paper - // "Taming Control Flow: A Structured Approach to Eliminating Goto Statements". - public static void Eliminate(GotoStatement[] gotos) - { - for (int index = gotos.Length - 1; index >= 0; index--) - { - GotoStatement stmt = gotos[index]; - - AstBlock gBlock = ParentBlock(stmt.Goto); - AstBlock lBlock = ParentBlock(stmt.Label); - - int gLevel = Level(gBlock); - int lLevel = Level(lBlock); - - if (IndirectlyRelated(gBlock, lBlock, gLevel, lLevel)) - { - AstBlock drBlock = gBlock; - - int drLevel = gLevel; - - do - { - drBlock = drBlock.Parent; - - drLevel--; - } - while (!DirectlyRelated(drBlock, lBlock, drLevel, lLevel)); - - MoveOutward(stmt, gLevel, drLevel); - - gBlock = drBlock; - gLevel = drLevel; - - if (Previous(stmt.Goto) is AstBlock elseBlock && elseBlock.Type == AstBlockType.Else) - { - // It's possible that the label was enclosed inside an else block, - // in this case we need to update the block and level. - // We also need to set the IsLoop for the case when the label is - // now before the goto, due to the newly introduced else block. - lBlock = ParentBlock(stmt.Label); - - lLevel = Level(lBlock); - - if (!IndirectlyRelated(elseBlock, lBlock, gLevel + 1, lLevel)) - { - stmt.IsLoop = true; - } - } - } - - if (DirectlyRelated(gBlock, lBlock, gLevel, lLevel)) - { - if (gLevel > lLevel) - { - MoveOutward(stmt, gLevel, lLevel); - } - else - { - if (stmt.IsLoop) - { - Lift(stmt); - } - - MoveInward(stmt); - } - } - - gBlock = ParentBlock(stmt.Goto); - - if (stmt.IsLoop) - { - EncloseDoWhile(stmt, gBlock, stmt.Label); - } - else - { - Enclose(gBlock, AstBlockType.If, stmt.Condition, Next(stmt.Goto), stmt.Label); - } - - gBlock.Remove(stmt.Goto); - } - } - - private static bool IndirectlyRelated(AstBlock lBlock, AstBlock rBlock, int lLevel, int rlevel) - { - return !(lBlock == rBlock || DirectlyRelated(lBlock, rBlock, lLevel, rlevel)); - } - - private static bool DirectlyRelated(AstBlock lBlock, AstBlock rBlock, int lLevel, int rLevel) - { - // If the levels are equal, they can be either siblings or indirectly related. - if (lLevel == rLevel) - { - return false; - } - - IAstNode block; - IAstNode other; - - int blockLvl, otherLvl; - - if (lLevel > rLevel) - { - block = lBlock; - blockLvl = lLevel; - other = rBlock; - otherLvl = rLevel; - } - else /* if (rLevel > lLevel) */ - { - block = rBlock; - blockLvl = rLevel; - other = lBlock; - otherLvl = lLevel; - } - - while (blockLvl >= otherLvl) - { - if (block == other) - { - return true; - } - - block = block.Parent; - - blockLvl--; - } - - return false; - } - - private static void Lift(GotoStatement stmt) - { - AstBlock block = ParentBlock(stmt.Goto); - - AstBlock[] path = BackwardsPath(block, ParentBlock(stmt.Label)); - - AstBlock loopFirstStmt = path[path.Length - 1]; - - if (loopFirstStmt.Type == AstBlockType.Else) - { - loopFirstStmt = Previous(loopFirstStmt) as AstBlock; - - if (loopFirstStmt == null || loopFirstStmt.Type != AstBlockType.If) - { - throw new InvalidOperationException("Found an else without a matching if."); - } - } - - AstBlock newBlock = EncloseDoWhile(stmt, block, loopFirstStmt); - - block.Remove(stmt.Goto); - - newBlock.AddFirst(stmt.Goto); - - stmt.IsLoop = false; - } - - private static void MoveOutward(GotoStatement stmt, int gLevel, int lLevel) - { - AstBlock origin = ParentBlock(stmt.Goto); - - AstBlock block = origin; - - // Check if a loop is enclosing the goto, and the block that is - // directly related to the label is above the loop block. - // In that case, we need to introduce a break to get out of the loop. - AstBlock loopBlock = origin; - - int loopLevel = gLevel; - - while (loopLevel > lLevel) - { - AstBlock child = loopBlock; - - loopBlock = loopBlock.Parent; - - loopLevel--; - - if (child.Type == AstBlockType.DoWhile) - { - EncloseSingleInst(stmt, Instruction.LoopBreak); - - block.Remove(stmt.Goto); - - loopBlock.AddAfter(child, stmt.Goto); - - block = loopBlock; - gLevel = loopLevel; - } - } - - // Insert ifs to skip the parts that shouldn't be executed due to the goto. - bool tryInsertElse = stmt.IsUnconditional && origin.Type == AstBlockType.If; - - while (gLevel > lLevel) - { - Enclose(block, AstBlockType.If, stmt.Condition, Next(stmt.Goto)); - - block.Remove(stmt.Goto); - - AstBlock child = block; - - // We can't move the goto in the middle of a if and a else block, in - // this case we need to move it after the else. - // IsLoop may need to be updated if the label is inside the else, as - // introducing a loop is the only way to ensure the else will be executed. - if (Next(child) is AstBlock elseBlock && elseBlock.Type == AstBlockType.Else) - { - child = elseBlock; - } - - block = block.Parent; - - block.AddAfter(child, stmt.Goto); - - gLevel--; - - if (tryInsertElse && child == origin) - { - AstBlock lBlock = ParentBlock(stmt.Label); - - IAstNode last = block == lBlock && !stmt.IsLoop ? stmt.Label : null; - - AstBlock newBlock = Enclose(block, AstBlockType.Else, null, Next(stmt.Goto), last); - - if (newBlock != null) - { - block.Remove(stmt.Goto); - - block.AddAfter(newBlock, stmt.Goto); - } - } - } - } - - private static void MoveInward(GotoStatement stmt) - { - AstBlock block = ParentBlock(stmt.Goto); - - AstBlock[] path = BackwardsPath(block, ParentBlock(stmt.Label)); - - for (int index = path.Length - 1; index >= 0; index--) - { - AstBlock child = path[index]; - AstBlock last = child; - - if (child.Type == AstBlockType.If) - { - // Modify the if condition to allow it to be entered by the goto. - if (!ContainsCondComb(child.Condition, Instruction.LogicalOr, stmt.Condition)) - { - child.OrCondition(stmt.Condition); - } - } - else if (child.Type == AstBlockType.Else) - { - // Modify the matching if condition to force the else to be entered by the goto. - if (!(Previous(child) is AstBlock ifBlock) || ifBlock.Type != AstBlockType.If) - { - throw new InvalidOperationException("Found an else without a matching if."); - } - - IAstNode cond = InverseCond(stmt.Condition); - - if (!ContainsCondComb(ifBlock.Condition, Instruction.LogicalAnd, cond)) - { - ifBlock.AndCondition(cond); - } - - last = ifBlock; - } - - Enclose(block, AstBlockType.If, stmt.Condition, Next(stmt.Goto), last); - - block.Remove(stmt.Goto); - - child.AddFirst(stmt.Goto); - - block = child; - } - } - - private static bool ContainsCondComb(IAstNode node, Instruction inst, IAstNode newCond) - { - while (node is AstOperation operation && operation.SourcesCount == 2) - { - if (operation.Inst == inst && IsSameCond(operation.GetSource(1), newCond)) - { - return true; - } - - node = operation.GetSource(0); - } - - return false; - } - - private static AstBlock EncloseDoWhile(GotoStatement stmt, AstBlock block, IAstNode first) - { - if (block.Type == AstBlockType.DoWhile && first == block.First) - { - // We only need to insert the continue if we're not at the end of the loop, - // or if our condition is different from the loop condition. - if (Next(stmt.Goto) != null || block.Condition != stmt.Condition) - { - EncloseSingleInst(stmt, Instruction.LoopContinue); - } - - // Modify the do-while condition to allow it to continue. - if (!ContainsCondComb(block.Condition, Instruction.LogicalOr, stmt.Condition)) - { - block.OrCondition(stmt.Condition); - } - - return block; - } - - return Enclose(block, AstBlockType.DoWhile, stmt.Condition, first, stmt.Goto); - } - - private static void EncloseSingleInst(GotoStatement stmt, Instruction inst) - { - AstBlock block = ParentBlock(stmt.Goto); - - AstBlock newBlock = new AstBlock(AstBlockType.If, stmt.Condition); - - block.AddAfter(stmt.Goto, newBlock); - - newBlock.AddFirst(new AstOperation(inst)); - } - - private static AstBlock Enclose( - AstBlock block, - AstBlockType type, - IAstNode cond, - IAstNode first, - IAstNode last = null) - { - if (first == last) - { - return null; - } - - if (type == AstBlockType.If) - { - cond = InverseCond(cond); - } - - // Do a quick check, if we are enclosing a single block, - // and the block type/condition matches the one we're going - // to create, then we don't need a new block, we can just - // return the old one. - bool hasSingleNode = Next(first) == last; - - if (hasSingleNode && BlockMatches(first, type, cond)) - { - return first as AstBlock; - } - - AstBlock newBlock = new AstBlock(type, cond); - - block.AddBefore(first, newBlock); - - while (first != last) - { - IAstNode next = Next(first); - - block.Remove(first); - - newBlock.Add(first); - - first = next; - } - - return newBlock; - } - - private static bool BlockMatches(IAstNode node, AstBlockType type, IAstNode cond) - { - if (!(node is AstBlock block)) - { - return false; - } - - return block.Type == type && IsSameCond(block.Condition, cond); - } - - private static bool IsSameCond(IAstNode lCond, IAstNode rCond) - { - if (lCond is AstOperation lCondOp && lCondOp.Inst == Instruction.LogicalNot) - { - if (!(rCond is AstOperation rCondOp) || rCondOp.Inst != lCondOp.Inst) - { - return false; - } - - lCond = lCondOp.GetSource(0); - rCond = rCondOp.GetSource(0); - } - - return lCond == rCond; - } - - private static AstBlock ParentBlock(IAstNode node) - { - if (node is AstBlock block) - { - return block.Parent; - } - - while (!(node is AstBlock)) - { - node = node.Parent; - } - - return node as AstBlock; - } - - private static AstBlock[] BackwardsPath(AstBlock top, AstBlock bottom) - { - AstBlock block = bottom; - - List<AstBlock> path = new List<AstBlock>(); - - while (block != top) - { - path.Add(block); - - block = block.Parent; - } - - return path.ToArray(); - } - - private static int Level(IAstNode node) - { - int level = 0; - - while (node != null) - { - level++; - - node = node.Parent; - } - - return level; - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Graphics/Shader/StructuredIr/GotoStatement.cs b/Ryujinx.Graphics/Shader/StructuredIr/GotoStatement.cs deleted file mode 100644 index 25216e55..00000000 --- a/Ryujinx.Graphics/Shader/StructuredIr/GotoStatement.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Ryujinx.Graphics.Shader.IntermediateRepresentation; - -namespace Ryujinx.Graphics.Shader.StructuredIr -{ - class GotoStatement - { - public AstOperation Goto { get; } - public AstAssignment Label { get; } - - public IAstNode Condition => Label.Destination; - - public bool IsLoop { get; set; } - - public bool IsUnconditional => Goto.Inst == Instruction.Branch; - - public GotoStatement(AstOperation branch, AstAssignment label, bool isLoop) - { - Goto = branch; - Label = label; - IsLoop = isLoop; - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Graphics/Shader/StructuredIr/IAstNode.cs b/Ryujinx.Graphics/Shader/StructuredIr/IAstNode.cs deleted file mode 100644 index 5ececbb5..00000000 --- a/Ryujinx.Graphics/Shader/StructuredIr/IAstNode.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System.Collections.Generic; - -namespace Ryujinx.Graphics.Shader.StructuredIr -{ - interface IAstNode - { - AstBlock Parent { get; set; } - - LinkedListNode<IAstNode> LLNode { get; set; } - } -}
\ No newline at end of file diff --git a/Ryujinx.Graphics/Shader/StructuredIr/InstructionInfo.cs b/Ryujinx.Graphics/Shader/StructuredIr/InstructionInfo.cs deleted file mode 100644 index 46a61553..00000000 --- a/Ryujinx.Graphics/Shader/StructuredIr/InstructionInfo.cs +++ /dev/null @@ -1,142 +0,0 @@ -using Ryujinx.Graphics.Shader.IntermediateRepresentation; -using System; - -namespace Ryujinx.Graphics.Shader.StructuredIr -{ - static class InstructionInfo - { - private struct InstInfo - { - public VariableType DestType { get; } - - public VariableType[] SrcTypes { get; } - - public InstInfo(VariableType destType, params VariableType[] srcTypes) - { - DestType = destType; - SrcTypes = srcTypes; - } - } - - private static InstInfo[] _infoTbl; - - static InstructionInfo() - { - _infoTbl = new InstInfo[(int)Instruction.Count]; - - Add(Instruction.Absolute, VariableType.Scalar, VariableType.Scalar); - Add(Instruction.Add, VariableType.Scalar, VariableType.Scalar, VariableType.Scalar); - Add(Instruction.BitfieldExtractS32, VariableType.S32, VariableType.S32, VariableType.S32, VariableType.S32); - Add(Instruction.BitfieldExtractU32, VariableType.U32, VariableType.U32, VariableType.S32, VariableType.S32); - Add(Instruction.BitfieldInsert, VariableType.Int, VariableType.Int, VariableType.Int, VariableType.S32, VariableType.S32); - Add(Instruction.BitfieldReverse, VariableType.Int, VariableType.Int); - Add(Instruction.BitwiseAnd, VariableType.Int, VariableType.Int, VariableType.Int); - Add(Instruction.BitwiseExclusiveOr, VariableType.Int, VariableType.Int, VariableType.Int); - Add(Instruction.BitwiseNot, VariableType.Int, VariableType.Int); - Add(Instruction.BitwiseOr, VariableType.Int, VariableType.Int, VariableType.Int); - Add(Instruction.BranchIfTrue, VariableType.None, VariableType.Bool); - Add(Instruction.BranchIfFalse, VariableType.None, VariableType.Bool); - Add(Instruction.Ceiling, VariableType.F32, VariableType.F32, VariableType.F32); - Add(Instruction.Clamp, VariableType.Scalar, VariableType.Scalar, VariableType.Scalar, VariableType.Scalar); - Add(Instruction.ClampU32, VariableType.U32, VariableType.U32, VariableType.U32, VariableType.U32); - Add(Instruction.CompareEqual, VariableType.Bool, VariableType.Scalar, VariableType.Scalar); - Add(Instruction.CompareGreater, VariableType.Bool, VariableType.Scalar, VariableType.Scalar); - Add(Instruction.CompareGreaterOrEqual, VariableType.Bool, VariableType.Scalar, VariableType.Scalar); - Add(Instruction.CompareGreaterOrEqualU32, VariableType.Bool, VariableType.U32, VariableType.U32); - Add(Instruction.CompareGreaterU32, VariableType.Bool, VariableType.U32, VariableType.U32); - Add(Instruction.CompareLess, VariableType.Bool, VariableType.Scalar, VariableType.Scalar); - Add(Instruction.CompareLessOrEqual, VariableType.Bool, VariableType.Scalar, VariableType.Scalar); - Add(Instruction.CompareLessOrEqualU32, VariableType.Bool, VariableType.U32, VariableType.U32); - Add(Instruction.CompareLessU32, VariableType.Bool, VariableType.U32, VariableType.U32); - Add(Instruction.CompareNotEqual, VariableType.Bool, VariableType.Scalar, VariableType.Scalar); - Add(Instruction.ConditionalSelect, VariableType.Scalar, VariableType.Bool, VariableType.Scalar, VariableType.Scalar); - Add(Instruction.ConvertFPToS32, VariableType.S32, VariableType.F32); - Add(Instruction.ConvertS32ToFP, VariableType.F32, VariableType.S32); - Add(Instruction.ConvertU32ToFP, VariableType.F32, VariableType.U32); - Add(Instruction.Cosine, VariableType.Scalar, VariableType.Scalar); - Add(Instruction.Divide, VariableType.Scalar, VariableType.Scalar, VariableType.Scalar); - Add(Instruction.ExponentB2, VariableType.Scalar, VariableType.Scalar); - Add(Instruction.Floor, VariableType.F32, VariableType.F32); - Add(Instruction.FusedMultiplyAdd, VariableType.F32, VariableType.F32, VariableType.F32, VariableType.F32); - Add(Instruction.IsNan, VariableType.Bool, VariableType.F32); - Add(Instruction.LoadConstant, VariableType.F32, VariableType.S32, VariableType.S32); - Add(Instruction.LogarithmB2, VariableType.Scalar, VariableType.Scalar); - Add(Instruction.LogicalAnd, VariableType.Bool, VariableType.Bool, VariableType.Bool); - Add(Instruction.LogicalExclusiveOr, VariableType.Bool, VariableType.Bool, VariableType.Bool); - Add(Instruction.LogicalNot, VariableType.Bool, VariableType.Bool); - Add(Instruction.LogicalOr, VariableType.Bool, VariableType.Bool, VariableType.Bool); - Add(Instruction.ShiftLeft, VariableType.Int, VariableType.Int, VariableType.Int); - Add(Instruction.ShiftRightS32, VariableType.S32, VariableType.S32, VariableType.Int); - Add(Instruction.ShiftRightU32, VariableType.U32, VariableType.U32, VariableType.Int); - Add(Instruction.Maximum, VariableType.Scalar, VariableType.Scalar, VariableType.Scalar); - Add(Instruction.MaximumU32, VariableType.U32, VariableType.U32, VariableType.U32); - Add(Instruction.Minimum, VariableType.Scalar, VariableType.Scalar, VariableType.Scalar); - Add(Instruction.MinimumU32, VariableType.U32, VariableType.U32, VariableType.U32); - Add(Instruction.Multiply, VariableType.Scalar, VariableType.Scalar, VariableType.Scalar); - Add(Instruction.Negate, VariableType.Scalar, VariableType.Scalar); - Add(Instruction.PackHalf2x16, VariableType.U32, VariableType.F32, VariableType.F32); - Add(Instruction.ReciprocalSquareRoot, VariableType.Scalar, VariableType.Scalar); - Add(Instruction.Sine, VariableType.Scalar, VariableType.Scalar); - Add(Instruction.SquareRoot, VariableType.Scalar, VariableType.Scalar); - Add(Instruction.Subtract, VariableType.Scalar, VariableType.Scalar, VariableType.Scalar); - Add(Instruction.TextureSample, VariableType.F32); - Add(Instruction.TextureSize, VariableType.S32, VariableType.S32, VariableType.S32); - Add(Instruction.Truncate, VariableType.F32, VariableType.F32); - Add(Instruction.UnpackHalf2x16, VariableType.F32, VariableType.U32); - } - - private static void Add(Instruction inst, VariableType destType, params VariableType[] srcTypes) - { - _infoTbl[(int)inst] = new InstInfo(destType, srcTypes); - } - - public static VariableType GetDestVarType(Instruction inst) - { - return GetFinalVarType(_infoTbl[(int)(inst & Instruction.Mask)].DestType, inst); - } - - public static VariableType GetSrcVarType(Instruction inst, int index) - { - if (inst == Instruction.TextureSample) - { - return VariableType.F32; - } - - return GetFinalVarType(_infoTbl[(int)(inst & Instruction.Mask)].SrcTypes[index], inst); - } - - private static VariableType GetFinalVarType(VariableType type, Instruction inst) - { - if (type == VariableType.Scalar) - { - return (inst & Instruction.FP) != 0 - ? VariableType.F32 - : VariableType.S32; - } - else if (type == VariableType.Int) - { - return VariableType.S32; - } - else if (type == VariableType.None) - { - throw new ArgumentException($"Invalid operand for instruction \"{inst}\"."); - } - - return type; - } - - public static bool IsUnary(Instruction inst) - { - if (inst == Instruction.Copy) - { - return true; - } - else if (inst == Instruction.TextureSample) - { - return false; - } - - return _infoTbl[(int)(inst & Instruction.Mask)].SrcTypes.Length == 1; - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Graphics/Shader/StructuredIr/OperandInfo.cs b/Ryujinx.Graphics/Shader/StructuredIr/OperandInfo.cs deleted file mode 100644 index a3a8d138..00000000 --- a/Ryujinx.Graphics/Shader/StructuredIr/OperandInfo.cs +++ /dev/null @@ -1,34 +0,0 @@ -using Ryujinx.Graphics.Shader.IntermediateRepresentation; -using System; - -namespace Ryujinx.Graphics.Shader.StructuredIr -{ - static class OperandInfo - { - public static VariableType GetVarType(AstOperand operand) - { - if (operand.Type == OperandType.LocalVariable) - { - return operand.VarType; - } - else - { - return GetVarType(operand.Type); - } - } - - public static VariableType GetVarType(OperandType type) - { - switch (type) - { - case OperandType.Attribute: return VariableType.F32; - case OperandType.Constant: return VariableType.S32; - case OperandType.ConstantBuffer: return VariableType.F32; - case OperandType.GlobalMemory: return VariableType.F32; - case OperandType.Undefined: return VariableType.S32; - } - - throw new ArgumentException($"Invalid operand type \"{type}\"."); - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Graphics/Shader/StructuredIr/PhiFunctions.cs b/Ryujinx.Graphics/Shader/StructuredIr/PhiFunctions.cs deleted file mode 100644 index 53391b62..00000000 --- a/Ryujinx.Graphics/Shader/StructuredIr/PhiFunctions.cs +++ /dev/null @@ -1,74 +0,0 @@ -using Ryujinx.Graphics.Shader.IntermediateRepresentation; -using System.Collections.Generic; - -namespace Ryujinx.Graphics.Shader.StructuredIr -{ - static class PhiFunctions - { - public static void Remove(BasicBlock[] blocks) - { - for (int blkIndex = 0; blkIndex < blocks.Length; blkIndex++) - { - BasicBlock block = blocks[blkIndex]; - - LinkedListNode<INode> node = block.Operations.First; - - while (node != null) - { - LinkedListNode<INode> nextNode = node.Next; - - if (!(node.Value is PhiNode phi)) - { - node = nextNode; - - continue; - } - - for (int index = 0; index < phi.SourcesCount; index++) - { - Operand src = phi.GetSource(index); - - BasicBlock srcBlock = phi.GetBlock(index); - - Operation copyOp = new Operation(Instruction.Copy, phi.Dest, src); - - AddBeforeBranch(srcBlock, copyOp); - } - - block.Operations.Remove(node); - - node = nextNode; - } - } - } - - private static void AddBeforeBranch(BasicBlock block, INode node) - { - INode lastOp = block.GetLastOp(); - - if (lastOp is Operation operation && IsControlFlowInst(operation.Inst)) - { - block.Operations.AddBefore(block.Operations.Last, node); - } - else - { - block.Operations.AddLast(node); - } - } - - private static bool IsControlFlowInst(Instruction inst) - { - switch (inst) - { - case Instruction.Branch: - case Instruction.BranchIfFalse: - case Instruction.BranchIfTrue: - case Instruction.Discard: - case Instruction.Return: - return true; - } - - return false; - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Graphics/Shader/StructuredIr/StructuredProgram.cs b/Ryujinx.Graphics/Shader/StructuredIr/StructuredProgram.cs deleted file mode 100644 index 26faaf36..00000000 --- a/Ryujinx.Graphics/Shader/StructuredIr/StructuredProgram.cs +++ /dev/null @@ -1,254 +0,0 @@ -using Ryujinx.Graphics.Shader.IntermediateRepresentation; -using System; -using System.Collections.Generic; - -namespace Ryujinx.Graphics.Shader.StructuredIr -{ - static class StructuredProgram - { - public static StructuredProgramInfo MakeStructuredProgram(BasicBlock[] blocks) - { - PhiFunctions.Remove(blocks); - - StructuredProgramContext context = new StructuredProgramContext(blocks.Length); - - for (int blkIndex = 0; blkIndex < blocks.Length; blkIndex++) - { - BasicBlock block = blocks[blkIndex]; - - context.EnterBlock(block); - - foreach (INode node in block.Operations) - { - Operation operation = (Operation)node; - - if (IsBranchInst(operation.Inst)) - { - context.LeaveBlock(block, operation); - } - else - { - AddOperation(context, operation); - } - } - } - - GotoElimination.Eliminate(context.GetGotos()); - - AstOptimizer.Optimize(context.Info); - - return context.Info; - } - - private static void AddOperation(StructuredProgramContext context, Operation operation) - { - Instruction inst = operation.Inst; - - IAstNode[] sources = new IAstNode[operation.SourcesCount]; - - for (int index = 0; index < sources.Length; index++) - { - sources[index] = context.GetOperandUse(operation.GetSource(index)); - } - - if (operation.Dest != null) - { - AstOperand dest = context.GetOperandDef(operation.Dest); - - if (inst == Instruction.LoadConstant) - { - Operand ldcSource = operation.GetSource(0); - - if (ldcSource.Type != OperandType.Constant) - { - throw new InvalidOperationException("Found LDC with non-constant constant buffer slot."); - } - - context.Info.CBuffers.Add(ldcSource.Value); - } - - 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 - // a bool in the end. - if (IsBitwiseInst(inst) && AreAllSourceTypesEqual(sources, VariableType.Bool)) - { - inst = GetLogicalFromBitwiseInst(inst); - } - - bool isCondSel = inst == Instruction.ConditionalSelect; - bool isCopy = inst == Instruction.Copy; - - if (isCondSel || isCopy) - { - VariableType type = GetVarTypeFromUses(operation.Dest); - - if (isCondSel && type == VariableType.F32) - { - inst |= Instruction.FP; - } - - dest.VarType = type; - } - else - { - dest.VarType = InstructionInfo.GetDestVarType(inst); - } - - int componentMask = 1 << operation.ComponentIndex; - - IAstNode source; - - if (operation is TextureOperation texOp) - { - AstTextureOperation astTexOp = new AstTextureOperation( - inst, - texOp.Type, - texOp.Flags, - texOp.Handle, - componentMask, - sources); - - context.Info.Samplers.Add(astTexOp); - - source = astTexOp; - } - else if (!isCopy) - { - source = new AstOperation(inst, componentMask, sources); - } - else - { - source = sources[0]; - } - - assignment = new AstAssignment(dest, source); - - context.AddNode(assignment); - } - else - { - context.AddNode(new AstOperation(inst, sources)); - } - } - - private static VariableType GetVarTypeFromUses(Operand dest) - { - HashSet<Operand> visited = new HashSet<Operand>(); - - Queue<Operand> pending = new Queue<Operand>(); - - bool Enqueue(Operand operand) - { - if (visited.Add(operand)) - { - pending.Enqueue(operand); - - return true; - } - - return false; - } - - Enqueue(dest); - - while (pending.TryDequeue(out Operand operand)) - { - foreach (INode useNode in operand.UseOps) - { - if (!(useNode is Operation operation)) - { - continue; - } - - if (operation.Inst == Instruction.Copy) - { - if (operation.Dest.Type == OperandType.LocalVariable) - { - if (Enqueue(operation.Dest)) - { - break; - } - } - else - { - return OperandInfo.GetVarType(operation.Dest.Type); - } - } - else - { - for (int index = 0; index < operation.SourcesCount; index++) - { - if (operation.GetSource(index) == operand) - { - return InstructionInfo.GetSrcVarType(operation.Inst, index); - } - } - } - } - } - - return VariableType.S32; - } - - private static bool AreAllSourceTypesEqual(IAstNode[] sources, VariableType type) - { - foreach (IAstNode node in sources) - { - if (!(node is AstOperand operand)) - { - return false; - } - - if (operand.VarType != type) - { - return false; - } - } - - return true; - } - - private static bool IsBranchInst(Instruction inst) - { - switch (inst) - { - case Instruction.Branch: - case Instruction.BranchIfFalse: - case Instruction.BranchIfTrue: - return true; - } - - return false; - } - - private static bool IsBitwiseInst(Instruction inst) - { - switch (inst) - { - case Instruction.BitwiseAnd: - case Instruction.BitwiseExclusiveOr: - case Instruction.BitwiseNot: - case Instruction.BitwiseOr: - return true; - } - - return false; - } - - private static Instruction GetLogicalFromBitwiseInst(Instruction inst) - { - switch (inst) - { - case Instruction.BitwiseAnd: return Instruction.LogicalAnd; - case Instruction.BitwiseExclusiveOr: return Instruction.LogicalExclusiveOr; - case Instruction.BitwiseNot: return Instruction.LogicalNot; - case Instruction.BitwiseOr: return Instruction.LogicalOr; - } - - throw new ArgumentException($"Unexpected instruction \"{inst}\"."); - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Graphics/Shader/StructuredIr/StructuredProgramContext.cs b/Ryujinx.Graphics/Shader/StructuredIr/StructuredProgramContext.cs deleted file mode 100644 index 5d6ff890..00000000 --- a/Ryujinx.Graphics/Shader/StructuredIr/StructuredProgramContext.cs +++ /dev/null @@ -1,292 +0,0 @@ -using Ryujinx.Graphics.Shader.IntermediateRepresentation; -using System.Collections.Generic; -using System.Linq; - -using static Ryujinx.Graphics.Shader.StructuredIr.AstHelper; - -namespace Ryujinx.Graphics.Shader.StructuredIr -{ - class StructuredProgramContext - { - private HashSet<BasicBlock> _loopTails; - - private Stack<(AstBlock Block, int EndIndex)> _blockStack; - - private Dictionary<Operand, AstOperand> _localsMap; - - private Dictionary<int, AstAssignment> _gotoTempAsgs; - - private List<GotoStatement> _gotos; - - private AstBlock _currBlock; - - private int _currEndIndex; - - public StructuredProgramInfo Info { get; } - - public StructuredProgramContext(int blocksCount) - { - _loopTails = new HashSet<BasicBlock>(); - - _blockStack = new Stack<(AstBlock, int)>(); - - _localsMap = new Dictionary<Operand, AstOperand>(); - - _gotoTempAsgs = new Dictionary<int, AstAssignment>(); - - _gotos = new List<GotoStatement>(); - - _currBlock = new AstBlock(AstBlockType.Main); - - _currEndIndex = blocksCount; - - Info = new StructuredProgramInfo(_currBlock); - } - - public void EnterBlock(BasicBlock block) - { - while (_currEndIndex == block.Index) - { - (_currBlock, _currEndIndex) = _blockStack.Pop(); - } - - if (_gotoTempAsgs.TryGetValue(block.Index, out AstAssignment gotoTempAsg)) - { - AddGotoTempReset(block, gotoTempAsg); - } - - LookForDoWhileStatements(block); - } - - public void LeaveBlock(BasicBlock block, Operation branchOp) - { - LookForIfStatements(block, branchOp); - } - - private void LookForDoWhileStatements(BasicBlock block) - { - // Check if we have any predecessor whose index is greater than the - // current block, this indicates a loop. - bool done = false; - - foreach (BasicBlock predecessor in block.Predecessors.OrderByDescending(x => x.Index)) - { - if (predecessor.Index < block.Index) - { - break; - } - - if (predecessor.Index < _currEndIndex && !done) - { - Operation branchOp = (Operation)predecessor.GetLastOp(); - - NewBlock(AstBlockType.DoWhile, branchOp, predecessor.Index + 1); - - _loopTails.Add(predecessor); - - done = true; - } - else - { - AddGotoTempReset(block, GetGotoTempAsg(block.Index)); - - break; - } - } - } - - private void LookForIfStatements(BasicBlock block, Operation branchOp) - { - if (block.Branch == null) - { - return; - } - - bool isLoop = block.Branch.Index <= block.Index; - - if (block.Branch.Index <= _currEndIndex && !isLoop) - { - NewBlock(AstBlockType.If, branchOp, block.Branch.Index); - } - else if (!_loopTails.Contains(block)) - { - AstAssignment gotoTempAsg = GetGotoTempAsg(block.Branch.Index); - - IAstNode cond = GetBranchCond(AstBlockType.DoWhile, branchOp); - - AddNode(Assign(gotoTempAsg.Destination, cond)); - - AstOperation branch = new AstOperation(branchOp.Inst); - - AddNode(branch); - - GotoStatement gotoStmt = new GotoStatement(branch, gotoTempAsg, isLoop); - - _gotos.Add(gotoStmt); - } - } - - private AstAssignment GetGotoTempAsg(int index) - { - if (_gotoTempAsgs.TryGetValue(index, out AstAssignment gotoTempAsg)) - { - return gotoTempAsg; - } - - AstOperand gotoTemp = NewTemp(VariableType.Bool); - - gotoTempAsg = Assign(gotoTemp, Const(IrConsts.False)); - - _gotoTempAsgs.Add(index, gotoTempAsg); - - return gotoTempAsg; - } - - private void AddGotoTempReset(BasicBlock block, AstAssignment gotoTempAsg) - { - AddNode(gotoTempAsg); - - // For block 0, we don't need to add the extra "reset" at the beginning, - // because it is already the first node to be executed on the shader, - // so it is reset to false by the "local" assignment anyway. - if (block.Index != 0) - { - Info.MainBlock.AddFirst(Assign(gotoTempAsg.Destination, Const(IrConsts.False))); - } - } - - private void NewBlock(AstBlockType type, Operation branchOp, int endIndex) - { - NewBlock(type, GetBranchCond(type, branchOp), endIndex); - } - - private void NewBlock(AstBlockType type, IAstNode cond, int endIndex) - { - AstBlock childBlock = new AstBlock(type, cond); - - AddNode(childBlock); - - _blockStack.Push((_currBlock, _currEndIndex)); - - _currBlock = childBlock; - _currEndIndex = endIndex; - } - - private IAstNode GetBranchCond(AstBlockType type, Operation branchOp) - { - IAstNode cond; - - if (branchOp.Inst == Instruction.Branch) - { - cond = Const(type == AstBlockType.If ? IrConsts.False : IrConsts.True); - } - else - { - cond = GetOperandUse(branchOp.GetSource(0)); - - Instruction invInst = type == AstBlockType.If - ? Instruction.BranchIfTrue - : Instruction.BranchIfFalse; - - if (branchOp.Inst == invInst) - { - cond = new AstOperation(Instruction.LogicalNot, cond); - } - } - - return cond; - } - - public void AddNode(IAstNode node) - { - _currBlock.Add(node); - } - - public GotoStatement[] GetGotos() - { - return _gotos.ToArray(); - } - - private AstOperand NewTemp(VariableType type) - { - AstOperand newTemp = Local(type); - - Info.Locals.Add(newTemp); - - return newTemp; - } - - public AstOperand GetOperandDef(Operand operand) - { - if (TryGetUserAttributeIndex(operand, out int attrIndex)) - { - Info.OAttributes.Add(attrIndex); - } - - return GetOperand(operand); - } - - public AstOperand GetOperandUse(Operand operand) - { - if (TryGetUserAttributeIndex(operand, out int attrIndex)) - { - Info.IAttributes.Add(attrIndex); - } - else if (operand.Type == OperandType.ConstantBuffer) - { - Info.CBuffers.Add(operand.GetCbufSlot()); - } - - return GetOperand(operand); - } - - private AstOperand GetOperand(Operand operand) - { - if (operand == null) - { - return null; - } - - if (operand.Type != OperandType.LocalVariable) - { - return new AstOperand(operand); - } - - if (!_localsMap.TryGetValue(operand, out AstOperand astOperand)) - { - astOperand = new AstOperand(operand); - - _localsMap.Add(operand, astOperand); - - Info.Locals.Add(astOperand); - } - - return astOperand; - } - - private static bool TryGetUserAttributeIndex(Operand operand, out int attrIndex) - { - if (operand.Type == OperandType.Attribute) - { - if (operand.Value >= AttributeConsts.UserAttributeBase && - operand.Value < AttributeConsts.UserAttributeEnd) - { - attrIndex = (operand.Value - AttributeConsts.UserAttributeBase) >> 4; - - return true; - } - else if (operand.Value >= AttributeConsts.FragmentOutputColorBase && - operand.Value < AttributeConsts.FragmentOutputColorEnd) - { - attrIndex = (operand.Value - AttributeConsts.FragmentOutputColorBase) >> 4; - - return true; - } - } - - attrIndex = 0; - - return false; - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Graphics/Shader/StructuredIr/StructuredProgramInfo.cs b/Ryujinx.Graphics/Shader/StructuredIr/StructuredProgramInfo.cs deleted file mode 100644 index d368ef00..00000000 --- a/Ryujinx.Graphics/Shader/StructuredIr/StructuredProgramInfo.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System.Collections.Generic; - -namespace Ryujinx.Graphics.Shader.StructuredIr -{ - class StructuredProgramInfo - { - public AstBlock MainBlock { get; } - - public HashSet<AstOperand> Locals { get; } - - public HashSet<int> CBuffers { get; } - - public HashSet<int> IAttributes { get; } - public HashSet<int> OAttributes { get; } - - public HashSet<AstTextureOperation> Samplers { get; } - - public StructuredProgramInfo(AstBlock mainBlock) - { - MainBlock = mainBlock; - - Locals = new HashSet<AstOperand>(); - - CBuffers = new HashSet<int>(); - - IAttributes = new HashSet<int>(); - OAttributes = new HashSet<int>(); - - Samplers = new HashSet<AstTextureOperation>(); - } - } -}
\ No newline at end of file diff --git a/Ryujinx.Graphics/Shader/StructuredIr/VariableType.cs b/Ryujinx.Graphics/Shader/StructuredIr/VariableType.cs deleted file mode 100644 index 4c7f3849..00000000 --- a/Ryujinx.Graphics/Shader/StructuredIr/VariableType.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Ryujinx.Graphics.Shader.StructuredIr -{ - enum VariableType - { - None, - Bool, - Scalar, - Int, - F32, - S32, - U32 - } -}
\ No newline at end of file |
