aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics/Shader/StructuredIr
diff options
context:
space:
mode:
authorgdk <gab.dark.100@gmail.com>2019-10-13 03:02:07 -0300
committerThog <thog@protonmail.com>2020-01-09 02:13:00 +0100
commit1876b346fea647e8284a66bb6d62c38801035cff (patch)
tree6eeff094298cda84d1613dc5ec0691e51d7b35f1 /Ryujinx.Graphics/Shader/StructuredIr
parentf617fb542a0e3d36012d77a4b5acbde7b08902f2 (diff)
Initial work
Diffstat (limited to 'Ryujinx.Graphics/Shader/StructuredIr')
-rw-r--r--Ryujinx.Graphics/Shader/StructuredIr/AstAssignment.cs35
-rw-r--r--Ryujinx.Graphics/Shader/StructuredIr/AstBlock.cs116
-rw-r--r--Ryujinx.Graphics/Shader/StructuredIr/AstBlockType.cs12
-rw-r--r--Ryujinx.Graphics/Shader/StructuredIr/AstBlockVisitor.cs68
-rw-r--r--Ryujinx.Graphics/Shader/StructuredIr/AstHelper.cs73
-rw-r--r--Ryujinx.Graphics/Shader/StructuredIr/AstNode.cs11
-rw-r--r--Ryujinx.Graphics/Shader/StructuredIr/AstOperand.cs49
-rw-r--r--Ryujinx.Graphics/Shader/StructuredIr/AstOperation.cs49
-rw-r--r--Ryujinx.Graphics/Shader/StructuredIr/AstOptimizer.cs149
-rw-r--r--Ryujinx.Graphics/Shader/StructuredIr/AstTextureOperation.cs25
-rw-r--r--Ryujinx.Graphics/Shader/StructuredIr/GotoElimination.cs459
-rw-r--r--Ryujinx.Graphics/Shader/StructuredIr/GotoStatement.cs23
-rw-r--r--Ryujinx.Graphics/Shader/StructuredIr/IAstNode.cs11
-rw-r--r--Ryujinx.Graphics/Shader/StructuredIr/InstructionInfo.cs142
-rw-r--r--Ryujinx.Graphics/Shader/StructuredIr/OperandInfo.cs34
-rw-r--r--Ryujinx.Graphics/Shader/StructuredIr/PhiFunctions.cs74
-rw-r--r--Ryujinx.Graphics/Shader/StructuredIr/StructuredProgram.cs254
-rw-r--r--Ryujinx.Graphics/Shader/StructuredIr/StructuredProgramContext.cs292
-rw-r--r--Ryujinx.Graphics/Shader/StructuredIr/StructuredProgramInfo.cs32
-rw-r--r--Ryujinx.Graphics/Shader/StructuredIr/VariableType.cs13
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