aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Shader/StructuredIr
diff options
context:
space:
mode:
authorTSR Berry <20988865+TSRBerry@users.noreply.github.com>2023-04-08 01:22:00 +0200
committerMary <thog@protonmail.com>2023-04-27 23:51:14 +0200
commitcee712105850ac3385cd0091a923438167433f9f (patch)
tree4a5274b21d8b7f938c0d0ce18736d3f2993b11b1 /Ryujinx.Graphics.Shader/StructuredIr
parentcd124bda587ef09668a971fa1cac1c3f0cfc9f21 (diff)
Move solution and projects to src
Diffstat (limited to 'Ryujinx.Graphics.Shader/StructuredIr')
-rw-r--r--Ryujinx.Graphics.Shader/StructuredIr/AstAssignment.cs35
-rw-r--r--Ryujinx.Graphics.Shader/StructuredIr/AstBlock.cs117
-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/AstComment.cs12
-rw-r--r--Ryujinx.Graphics.Shader/StructuredIr/AstHelper.cs74
-rw-r--r--Ryujinx.Graphics.Shader/StructuredIr/AstNode.cs11
-rw-r--r--Ryujinx.Graphics.Shader/StructuredIr/AstOperand.cs50
-rw-r--r--Ryujinx.Graphics.Shader/StructuredIr/AstOperation.cs80
-rw-r--r--Ryujinx.Graphics.Shader/StructuredIr/AstOptimizer.cs155
-rw-r--r--Ryujinx.Graphics.Shader/StructuredIr/AstTextureOperation.cs36
-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/HelperFunctionsMask.cs21
-rw-r--r--Ryujinx.Graphics.Shader/StructuredIr/IAstNode.cs11
-rw-r--r--Ryujinx.Graphics.Shader/StructuredIr/InstructionInfo.cs216
-rw-r--r--Ryujinx.Graphics.Shader/StructuredIr/IoDefinition.cs44
-rw-r--r--Ryujinx.Graphics.Shader/StructuredIr/OperandInfo.cs33
-rw-r--r--Ryujinx.Graphics.Shader/StructuredIr/PhiFunctions.cs45
-rw-r--r--Ryujinx.Graphics.Shader/StructuredIr/StructuredFunction.cs42
-rw-r--r--Ryujinx.Graphics.Shader/StructuredIr/StructuredProgram.cs421
-rw-r--r--Ryujinx.Graphics.Shader/StructuredIr/StructuredProgramContext.cs330
-rw-r--r--Ryujinx.Graphics.Shader/StructuredIr/StructuredProgramInfo.cs36
23 files changed, 0 insertions, 2331 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 2f34bee8..00000000
--- a/Ryujinx.Graphics.Shader/StructuredIr/AstBlock.cs
+++ /dev/null
@@ -1,117 +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 IAstNode Last => _nodes.Last?.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/AstComment.cs b/Ryujinx.Graphics.Shader/StructuredIr/AstComment.cs
deleted file mode 100644
index dabe623f..00000000
--- a/Ryujinx.Graphics.Shader/StructuredIr/AstComment.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-namespace Ryujinx.Graphics.Shader.StructuredIr
-{
- class AstComment : AstNode
- {
- public string Comment { get; }
-
- public AstComment(string comment)
- {
- Comment = comment;
- }
- }
-} \ 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 7aa0409b..00000000
--- a/Ryujinx.Graphics.Shader/StructuredIr/AstHelper.cs
+++ /dev/null
@@ -1,74 +0,0 @@
-using Ryujinx.Graphics.Shader.IntermediateRepresentation;
-using Ryujinx.Graphics.Shader.Translation;
-
-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(AggregateType 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 1fc0035f..00000000
--- a/Ryujinx.Graphics.Shader/StructuredIr/AstOperand.cs
+++ /dev/null
@@ -1,50 +0,0 @@
-using Ryujinx.Graphics.Shader.IntermediateRepresentation;
-using Ryujinx.Graphics.Shader.Translation;
-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 AggregateType 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 = AggregateType.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 2393fd8d..00000000
--- a/Ryujinx.Graphics.Shader/StructuredIr/AstOperation.cs
+++ /dev/null
@@ -1,80 +0,0 @@
-using Ryujinx.Graphics.Shader.IntermediateRepresentation;
-using Ryujinx.Graphics.Shader.Translation;
-using System.Numerics;
-
-using static Ryujinx.Graphics.Shader.StructuredIr.AstHelper;
-
-namespace Ryujinx.Graphics.Shader.StructuredIr
-{
- class AstOperation : AstNode
- {
- public Instruction Inst { get; }
- public StorageKind StorageKind { get; }
-
- public int Index { get; }
-
- private IAstNode[] _sources;
-
- public int SourcesCount => _sources.Length;
-
- public AstOperation(Instruction inst, StorageKind storageKind, IAstNode[] sources, int sourcesCount)
- {
- Inst = inst;
- StorageKind = storageKind;
- _sources = sources;
-
- for (int index = 0; index < sources.Length; index++)
- {
- if (index < sourcesCount)
- {
- AddUse(sources[index], this);
- }
- else
- {
- AddDef(sources[index], this);
- }
- }
-
- Index = 0;
- }
-
- public AstOperation(Instruction inst, StorageKind storageKind, int index, IAstNode[] sources, int sourcesCount) : this(inst, storageKind, sources, sourcesCount)
- {
- Index = index;
- }
-
- public AstOperation(Instruction inst, params IAstNode[] sources) : this(inst, StorageKind.None, sources, sources.Length)
- {
- }
-
- 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;
- }
-
- public AggregateType GetVectorType(AggregateType scalarType)
- {
- int componentsCount = BitOperations.PopCount((uint)Index);
-
- AggregateType type = scalarType;
-
- switch (componentsCount)
- {
- case 2: type |= AggregateType.Vector2; break;
- case 3: type |= AggregateType.Vector3; break;
- case 4: type |= AggregateType.Vector4; break;
- }
-
- return type;
- }
- }
-} \ 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 b71ae2c4..00000000
--- a/Ryujinx.Graphics.Shader/StructuredIr/AstOptimizer.cs
+++ /dev/null
@@ -1,155 +0,0 @@
-using Ryujinx.Graphics.Shader.IntermediateRepresentation;
-using Ryujinx.Graphics.Shader.Translation;
-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(StructuredProgramContext context)
- {
- AstBlock mainBlock = context.CurrentFunction.MainBlock;
-
- // When debug mode is enabled, we disable expression propagation
- // (this makes comparison with the disassembly easier).
- if (!context.Config.Options.Flags.HasFlag(TranslationFlags.DebugMode))
- {
- 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);
-
- context.CurrentFunction.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 a44f13cc..00000000
--- a/Ryujinx.Graphics.Shader/StructuredIr/AstTextureOperation.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using Ryujinx.Graphics.Shader.IntermediateRepresentation;
-
-namespace Ryujinx.Graphics.Shader.StructuredIr
-{
- class AstTextureOperation : AstOperation
- {
- public SamplerType Type { get; }
- public TextureFormat Format { get; }
- public TextureFlags Flags { get; }
-
- public int CbufSlot { get; }
- public int Handle { get; }
-
- public AstTextureOperation(
- Instruction inst,
- SamplerType type,
- TextureFormat format,
- TextureFlags flags,
- int cbufSlot,
- int handle,
- int index,
- params IAstNode[] sources) : base(inst, StorageKind.None, index, sources, sources.Length)
- {
- Type = type;
- Format = format;
- Flags = flags;
- CbufSlot = cbufSlot;
- Handle = handle;
- }
-
- public AstTextureOperation WithType(SamplerType type)
- {
- return new AstTextureOperation(Inst, type, Format, Flags, CbufSlot, Handle, Index);
- }
- }
-} \ 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/HelperFunctionsMask.cs b/Ryujinx.Graphics.Shader/StructuredIr/HelperFunctionsMask.cs
deleted file mode 100644
index d45f8d4e..00000000
--- a/Ryujinx.Graphics.Shader/StructuredIr/HelperFunctionsMask.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-using System;
-
-namespace Ryujinx.Graphics.Shader.StructuredIr
-{
- [Flags]
- enum HelperFunctionsMask
- {
- AtomicMinMaxS32Shared = 1 << 0,
- AtomicMinMaxS32Storage = 1 << 1,
- MultiplyHighS32 = 1 << 2,
- MultiplyHighU32 = 1 << 3,
- Shuffle = 1 << 4,
- ShuffleDown = 1 << 5,
- ShuffleUp = 1 << 6,
- ShuffleXor = 1 << 7,
- StoreSharedSmallInt = 1 << 8,
- StoreStorageSmallInt = 1 << 9,
- SwizzleAdd = 1 << 10,
- FSI = 1 << 11
- }
-} \ 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 8eccef23..00000000
--- a/Ryujinx.Graphics.Shader/StructuredIr/InstructionInfo.cs
+++ /dev/null
@@ -1,216 +0,0 @@
-using Ryujinx.Graphics.Shader.IntermediateRepresentation;
-using Ryujinx.Graphics.Shader.Translation;
-using System;
-
-namespace Ryujinx.Graphics.Shader.StructuredIr
-{
- static class InstructionInfo
- {
- private readonly struct InstInfo
- {
- public AggregateType DestType { get; }
-
- public AggregateType[] SrcTypes { get; }
-
- public InstInfo(AggregateType destType, params AggregateType[] srcTypes)
- {
- DestType = destType;
- SrcTypes = srcTypes;
- }
- }
-
- private static InstInfo[] _infoTbl;
-
- static InstructionInfo()
- {
- _infoTbl = new InstInfo[(int)Instruction.Count];
-
- // Inst Destination type Source 1 type Source 2 type Source 3 type Source 4 type
- Add(Instruction.AtomicAdd, AggregateType.U32, AggregateType.S32, AggregateType.S32, AggregateType.U32);
- Add(Instruction.AtomicAnd, AggregateType.U32, AggregateType.S32, AggregateType.S32, AggregateType.U32);
- Add(Instruction.AtomicCompareAndSwap, AggregateType.U32, AggregateType.S32, AggregateType.S32, AggregateType.U32, AggregateType.U32);
- Add(Instruction.AtomicMaxS32, AggregateType.S32, AggregateType.S32, AggregateType.S32, AggregateType.S32);
- Add(Instruction.AtomicMaxU32, AggregateType.U32, AggregateType.S32, AggregateType.S32, AggregateType.U32);
- Add(Instruction.AtomicMinS32, AggregateType.S32, AggregateType.S32, AggregateType.S32, AggregateType.S32);
- Add(Instruction.AtomicMinU32, AggregateType.U32, AggregateType.S32, AggregateType.S32, AggregateType.U32);
- Add(Instruction.AtomicOr, AggregateType.U32, AggregateType.S32, AggregateType.S32, AggregateType.U32);
- Add(Instruction.AtomicSwap, AggregateType.U32, AggregateType.S32, AggregateType.S32, AggregateType.U32);
- Add(Instruction.AtomicXor, AggregateType.U32, AggregateType.S32, AggregateType.S32, AggregateType.U32);
- Add(Instruction.Absolute, AggregateType.Scalar, AggregateType.Scalar);
- Add(Instruction.Add, AggregateType.Scalar, AggregateType.Scalar, AggregateType.Scalar);
- Add(Instruction.Ballot, AggregateType.U32, AggregateType.Bool);
- Add(Instruction.BitCount, AggregateType.S32, AggregateType.S32);
- Add(Instruction.BitfieldExtractS32, AggregateType.S32, AggregateType.S32, AggregateType.S32, AggregateType.S32);
- Add(Instruction.BitfieldExtractU32, AggregateType.U32, AggregateType.U32, AggregateType.S32, AggregateType.S32);
- Add(Instruction.BitfieldInsert, AggregateType.S32, AggregateType.S32, AggregateType.S32, AggregateType.S32, AggregateType.S32);
- Add(Instruction.BitfieldReverse, AggregateType.S32, AggregateType.S32);
- Add(Instruction.BitwiseAnd, AggregateType.S32, AggregateType.S32, AggregateType.S32);
- Add(Instruction.BitwiseExclusiveOr, AggregateType.S32, AggregateType.S32, AggregateType.S32);
- Add(Instruction.BitwiseNot, AggregateType.S32, AggregateType.S32);
- Add(Instruction.BitwiseOr, AggregateType.S32, AggregateType.S32, AggregateType.S32);
- Add(Instruction.BranchIfTrue, AggregateType.Void, AggregateType.Bool);
- Add(Instruction.BranchIfFalse, AggregateType.Void, AggregateType.Bool);
- Add(Instruction.Call, AggregateType.Scalar);
- Add(Instruction.Ceiling, AggregateType.Scalar, AggregateType.Scalar, AggregateType.Scalar);
- Add(Instruction.Clamp, AggregateType.Scalar, AggregateType.Scalar, AggregateType.Scalar, AggregateType.Scalar);
- Add(Instruction.ClampU32, AggregateType.U32, AggregateType.U32, AggregateType.U32, AggregateType.U32);
- Add(Instruction.CompareEqual, AggregateType.Bool, AggregateType.Scalar, AggregateType.Scalar);
- Add(Instruction.CompareGreater, AggregateType.Bool, AggregateType.Scalar, AggregateType.Scalar);
- Add(Instruction.CompareGreaterOrEqual, AggregateType.Bool, AggregateType.Scalar, AggregateType.Scalar);
- Add(Instruction.CompareGreaterOrEqualU32, AggregateType.Bool, AggregateType.U32, AggregateType.U32);
- Add(Instruction.CompareGreaterU32, AggregateType.Bool, AggregateType.U32, AggregateType.U32);
- Add(Instruction.CompareLess, AggregateType.Bool, AggregateType.Scalar, AggregateType.Scalar);
- Add(Instruction.CompareLessOrEqual, AggregateType.Bool, AggregateType.Scalar, AggregateType.Scalar);
- Add(Instruction.CompareLessOrEqualU32, AggregateType.Bool, AggregateType.U32, AggregateType.U32);
- Add(Instruction.CompareLessU32, AggregateType.Bool, AggregateType.U32, AggregateType.U32);
- Add(Instruction.CompareNotEqual, AggregateType.Bool, AggregateType.Scalar, AggregateType.Scalar);
- Add(Instruction.ConditionalSelect, AggregateType.Scalar, AggregateType.Bool, AggregateType.Scalar, AggregateType.Scalar);
- Add(Instruction.ConvertFP32ToFP64, AggregateType.FP64, AggregateType.FP32);
- Add(Instruction.ConvertFP64ToFP32, AggregateType.FP32, AggregateType.FP64);
- Add(Instruction.ConvertFP32ToS32, AggregateType.S32, AggregateType.FP32);
- Add(Instruction.ConvertFP32ToU32, AggregateType.U32, AggregateType.FP32);
- Add(Instruction.ConvertFP64ToS32, AggregateType.S32, AggregateType.FP64);
- Add(Instruction.ConvertFP64ToU32, AggregateType.U32, AggregateType.FP64);
- Add(Instruction.ConvertS32ToFP32, AggregateType.FP32, AggregateType.S32);
- Add(Instruction.ConvertS32ToFP64, AggregateType.FP64, AggregateType.S32);
- Add(Instruction.ConvertU32ToFP32, AggregateType.FP32, AggregateType.U32);
- Add(Instruction.ConvertU32ToFP64, AggregateType.FP64, AggregateType.U32);
- Add(Instruction.Cosine, AggregateType.Scalar, AggregateType.Scalar);
- Add(Instruction.Ddx, AggregateType.FP32, AggregateType.FP32);
- Add(Instruction.Ddy, AggregateType.FP32, AggregateType.FP32);
- Add(Instruction.Divide, AggregateType.Scalar, AggregateType.Scalar, AggregateType.Scalar);
- Add(Instruction.ExponentB2, AggregateType.Scalar, AggregateType.Scalar);
- Add(Instruction.FindLSB, AggregateType.S32, AggregateType.S32);
- Add(Instruction.FindMSBS32, AggregateType.S32, AggregateType.S32);
- Add(Instruction.FindMSBU32, AggregateType.S32, AggregateType.U32);
- Add(Instruction.Floor, AggregateType.Scalar, AggregateType.Scalar);
- Add(Instruction.FusedMultiplyAdd, AggregateType.Scalar, AggregateType.Scalar, AggregateType.Scalar, AggregateType.Scalar);
- Add(Instruction.ImageLoad, AggregateType.FP32);
- Add(Instruction.ImageStore, AggregateType.Void);
- Add(Instruction.ImageAtomic, AggregateType.S32);
- Add(Instruction.IsNan, AggregateType.Bool, AggregateType.Scalar);
- Add(Instruction.Load, AggregateType.FP32);
- Add(Instruction.LoadConstant, AggregateType.FP32, AggregateType.S32, AggregateType.S32);
- Add(Instruction.LoadGlobal, AggregateType.U32, AggregateType.S32, AggregateType.S32);
- Add(Instruction.LoadLocal, AggregateType.U32, AggregateType.S32);
- Add(Instruction.LoadShared, AggregateType.U32, AggregateType.S32);
- Add(Instruction.LoadStorage, AggregateType.U32, AggregateType.S32, AggregateType.S32);
- Add(Instruction.Lod, AggregateType.FP32);
- Add(Instruction.LogarithmB2, AggregateType.Scalar, AggregateType.Scalar);
- Add(Instruction.LogicalAnd, AggregateType.Bool, AggregateType.Bool, AggregateType.Bool);
- Add(Instruction.LogicalExclusiveOr, AggregateType.Bool, AggregateType.Bool, AggregateType.Bool);
- Add(Instruction.LogicalNot, AggregateType.Bool, AggregateType.Bool);
- Add(Instruction.LogicalOr, AggregateType.Bool, AggregateType.Bool, AggregateType.Bool);
- Add(Instruction.Maximum, AggregateType.Scalar, AggregateType.Scalar, AggregateType.Scalar);
- Add(Instruction.MaximumU32, AggregateType.U32, AggregateType.U32, AggregateType.U32);
- Add(Instruction.Minimum, AggregateType.Scalar, AggregateType.Scalar, AggregateType.Scalar);
- Add(Instruction.MinimumU32, AggregateType.U32, AggregateType.U32, AggregateType.U32);
- Add(Instruction.Multiply, AggregateType.Scalar, AggregateType.Scalar, AggregateType.Scalar);
- Add(Instruction.MultiplyHighS32, AggregateType.S32, AggregateType.S32, AggregateType.S32);
- Add(Instruction.MultiplyHighU32, AggregateType.U32, AggregateType.U32, AggregateType.U32);
- Add(Instruction.Negate, AggregateType.Scalar, AggregateType.Scalar);
- Add(Instruction.PackDouble2x32, AggregateType.FP64, AggregateType.U32, AggregateType.U32);
- Add(Instruction.PackHalf2x16, AggregateType.U32, AggregateType.FP32, AggregateType.FP32);
- Add(Instruction.ReciprocalSquareRoot, AggregateType.Scalar, AggregateType.Scalar);
- Add(Instruction.Round, AggregateType.Scalar, AggregateType.Scalar);
- Add(Instruction.ShiftLeft, AggregateType.S32, AggregateType.S32, AggregateType.S32);
- Add(Instruction.ShiftRightS32, AggregateType.S32, AggregateType.S32, AggregateType.S32);
- Add(Instruction.ShiftRightU32, AggregateType.U32, AggregateType.U32, AggregateType.S32);
- Add(Instruction.Shuffle, AggregateType.FP32, AggregateType.FP32, AggregateType.U32, AggregateType.U32, AggregateType.Bool);
- Add(Instruction.ShuffleDown, AggregateType.FP32, AggregateType.FP32, AggregateType.U32, AggregateType.U32, AggregateType.Bool);
- Add(Instruction.ShuffleUp, AggregateType.FP32, AggregateType.FP32, AggregateType.U32, AggregateType.U32, AggregateType.Bool);
- Add(Instruction.ShuffleXor, AggregateType.FP32, AggregateType.FP32, AggregateType.U32, AggregateType.U32, AggregateType.Bool);
- Add(Instruction.Sine, AggregateType.Scalar, AggregateType.Scalar);
- Add(Instruction.SquareRoot, AggregateType.Scalar, AggregateType.Scalar);
- Add(Instruction.Store, AggregateType.Void);
- Add(Instruction.StoreGlobal, AggregateType.Void, AggregateType.S32, AggregateType.S32, AggregateType.U32);
- Add(Instruction.StoreLocal, AggregateType.Void, AggregateType.S32, AggregateType.U32);
- Add(Instruction.StoreShared, AggregateType.Void, AggregateType.S32, AggregateType.U32);
- Add(Instruction.StoreShared16, AggregateType.Void, AggregateType.S32, AggregateType.U32);
- Add(Instruction.StoreShared8, AggregateType.Void, AggregateType.S32, AggregateType.U32);
- Add(Instruction.StoreStorage, AggregateType.Void, AggregateType.S32, AggregateType.S32, AggregateType.U32);
- Add(Instruction.StoreStorage16, AggregateType.Void, AggregateType.S32, AggregateType.S32, AggregateType.U32);
- Add(Instruction.StoreStorage8, AggregateType.Void, AggregateType.S32, AggregateType.S32, AggregateType.U32);
- Add(Instruction.Subtract, AggregateType.Scalar, AggregateType.Scalar, AggregateType.Scalar);
- Add(Instruction.SwizzleAdd, AggregateType.FP32, AggregateType.FP32, AggregateType.FP32, AggregateType.S32);
- Add(Instruction.TextureSample, AggregateType.FP32);
- Add(Instruction.TextureSize, AggregateType.S32, AggregateType.S32, AggregateType.S32);
- Add(Instruction.Truncate, AggregateType.Scalar, AggregateType.Scalar);
- Add(Instruction.UnpackDouble2x32, AggregateType.U32, AggregateType.FP64);
- Add(Instruction.UnpackHalf2x16, AggregateType.FP32, AggregateType.U32);
- Add(Instruction.VectorExtract, AggregateType.Scalar, AggregateType.Vector4, AggregateType.S32);
- Add(Instruction.VoteAll, AggregateType.Bool, AggregateType.Bool);
- Add(Instruction.VoteAllEqual, AggregateType.Bool, AggregateType.Bool);
- Add(Instruction.VoteAny, AggregateType.Bool, AggregateType.Bool);
- }
-
- private static void Add(Instruction inst, AggregateType destType, params AggregateType[] srcTypes)
- {
- _infoTbl[(int)inst] = new InstInfo(destType, srcTypes);
- }
-
- public static AggregateType GetDestVarType(Instruction inst)
- {
- return GetFinalVarType(_infoTbl[(int)(inst & Instruction.Mask)].DestType, inst);
- }
-
- public static AggregateType GetSrcVarType(Instruction inst, int index)
- {
- // TODO: Return correct type depending on source index,
- // that can improve the decompiler output.
- if (inst == Instruction.ImageLoad ||
- inst == Instruction.ImageStore ||
- inst == Instruction.ImageAtomic ||
- inst == Instruction.Lod ||
- inst == Instruction.TextureSample)
- {
- return AggregateType.FP32;
- }
- else if (inst == Instruction.Call || inst == Instruction.Load || inst == Instruction.Store)
- {
- return AggregateType.S32;
- }
-
- return GetFinalVarType(_infoTbl[(int)(inst & Instruction.Mask)].SrcTypes[index], inst);
- }
-
- private static AggregateType GetFinalVarType(AggregateType type, Instruction inst)
- {
- if (type == AggregateType.Scalar)
- {
- if ((inst & Instruction.FP32) != 0)
- {
- return AggregateType.FP32;
- }
- else if ((inst & Instruction.FP64) != 0)
- {
- return AggregateType.FP64;
- }
- else
- {
- return AggregateType.S32;
- }
- }
- else if (type == AggregateType.Void)
- {
- 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/IoDefinition.cs b/Ryujinx.Graphics.Shader/StructuredIr/IoDefinition.cs
deleted file mode 100644
index 21a1b3f0..00000000
--- a/Ryujinx.Graphics.Shader/StructuredIr/IoDefinition.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-using Ryujinx.Graphics.Shader.IntermediateRepresentation;
-using System;
-
-namespace Ryujinx.Graphics.Shader.StructuredIr
-{
- readonly struct IoDefinition : IEquatable<IoDefinition>
- {
- public StorageKind StorageKind { get; }
- public IoVariable IoVariable { get; }
- public int Location { get; }
- public int Component { get; }
-
- public IoDefinition(StorageKind storageKind, IoVariable ioVariable, int location = 0, int component = 0)
- {
- StorageKind = storageKind;
- IoVariable = ioVariable;
- Location = location;
- Component = component;
- }
-
- public override bool Equals(object other)
- {
- return other is IoDefinition ioDefinition && Equals(ioDefinition);
- }
-
- public bool Equals(IoDefinition other)
- {
- return StorageKind == other.StorageKind &&
- IoVariable == other.IoVariable &&
- Location == other.Location &&
- Component == other.Component;
- }
-
- public override int GetHashCode()
- {
- return (int)StorageKind | ((int)IoVariable << 8) | (Location << 16) | (Component << 24);
- }
-
- public override string ToString()
- {
- return $"{StorageKind}.{IoVariable}.{Location}.{Component}";
- }
- }
-} \ 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 38ed1584..00000000
--- a/Ryujinx.Graphics.Shader/StructuredIr/OperandInfo.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using Ryujinx.Graphics.Shader.IntermediateRepresentation;
-using Ryujinx.Graphics.Shader.Translation;
-using System;
-
-namespace Ryujinx.Graphics.Shader.StructuredIr
-{
- static class OperandInfo
- {
- public static AggregateType GetVarType(AstOperand operand)
- {
- if (operand.Type == OperandType.LocalVariable)
- {
- return operand.VarType;
- }
- else
- {
- return GetVarType(operand.Type);
- }
- }
-
- public static AggregateType GetVarType(OperandType type)
- {
- return type switch
- {
- OperandType.Argument => AggregateType.S32,
- OperandType.Constant => AggregateType.S32,
- OperandType.ConstantBuffer => AggregateType.FP32,
- OperandType.Undefined => AggregateType.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 541ca298..00000000
--- a/Ryujinx.Graphics.Shader/StructuredIr/PhiFunctions.cs
+++ /dev/null
@@ -1,45 +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 not 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);
-
- srcBlock.Append(copyOp);
- }
-
- block.Operations.Remove(node);
-
- node = nextNode;
- }
- }
- }
- }
-} \ No newline at end of file
diff --git a/Ryujinx.Graphics.Shader/StructuredIr/StructuredFunction.cs b/Ryujinx.Graphics.Shader/StructuredIr/StructuredFunction.cs
deleted file mode 100644
index 61c4fed7..00000000
--- a/Ryujinx.Graphics.Shader/StructuredIr/StructuredFunction.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-using Ryujinx.Graphics.Shader.Translation;
-using System.Collections.Generic;
-
-namespace Ryujinx.Graphics.Shader.StructuredIr
-{
- class StructuredFunction
- {
- public AstBlock MainBlock { get; }
-
- public string Name { get; }
-
- public AggregateType ReturnType { get; }
-
- public AggregateType[] InArguments { get; }
- public AggregateType[] OutArguments { get; }
-
- public HashSet<AstOperand> Locals { get; }
-
- public StructuredFunction(
- AstBlock mainBlock,
- string name,
- AggregateType returnType,
- AggregateType[] inArguments,
- AggregateType[] outArguments)
- {
- MainBlock = mainBlock;
- Name = name;
- ReturnType = returnType;
- InArguments = inArguments;
- OutArguments = outArguments;
-
- Locals = new HashSet<AstOperand>();
- }
-
- public AggregateType GetArgumentType(int index)
- {
- return index >= InArguments.Length
- ? OutArguments[index - InArguments.Length]
- : InArguments[index];
- }
- }
-} \ 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 b4ca8ee5..00000000
--- a/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgram.cs
+++ /dev/null
@@ -1,421 +0,0 @@
-using Ryujinx.Graphics.Shader.IntermediateRepresentation;
-using Ryujinx.Graphics.Shader.Translation;
-using System;
-using System.Collections.Generic;
-using System.Numerics;
-
-namespace Ryujinx.Graphics.Shader.StructuredIr
-{
- static class StructuredProgram
- {
- public static StructuredProgramInfo MakeStructuredProgram(Function[] functions, ShaderConfig config)
- {
- StructuredProgramContext context = new StructuredProgramContext(config);
-
- for (int funcIndex = 0; funcIndex < functions.Length; funcIndex++)
- {
- Function function = functions[funcIndex];
-
- BasicBlock[] blocks = function.Blocks;
-
- AggregateType returnType = function.ReturnsValue ? AggregateType.S32 : AggregateType.Void;
-
- AggregateType[] inArguments = new AggregateType[function.InArgumentsCount];
- AggregateType[] outArguments = new AggregateType[function.OutArgumentsCount];
-
- for (int i = 0; i < inArguments.Length; i++)
- {
- inArguments[i] = AggregateType.S32;
- }
-
- for (int i = 0; i < outArguments.Length; i++)
- {
- outArguments[i] = AggregateType.S32;
- }
-
- context.EnterFunction(blocks.Length, function.Name, returnType, inArguments, outArguments);
-
- PhiFunctions.Remove(blocks);
-
- for (int blkIndex = 0; blkIndex < blocks.Length; blkIndex++)
- {
- BasicBlock block = blocks[blkIndex];
-
- context.EnterBlock(block);
-
- for (LinkedListNode<INode> opNode = block.Operations.First; opNode != null; opNode = opNode.Next)
- {
- Operation operation = (Operation)opNode.Value;
-
- if (IsBranchInst(operation.Inst))
- {
- context.LeaveBlock(block, operation);
- }
- else
- {
- AddOperation(context, operation);
- }
- }
- }
-
- GotoElimination.Eliminate(context.GetGotos());
-
- AstOptimizer.Optimize(context);
-
- context.LeaveFunction();
- }
-
- return context.Info;
- }
-
- private static void AddOperation(StructuredProgramContext context, Operation operation)
- {
- Instruction inst = operation.Inst;
- StorageKind storageKind = operation.StorageKind;
-
- if ((inst == Instruction.Load || inst == Instruction.Store) && storageKind.IsInputOrOutput())
- {
- IoVariable ioVariable = (IoVariable)operation.GetSource(0).Value;
- bool isOutput = storageKind.IsOutput();
- bool perPatch = storageKind.IsPerPatch();
- int location = 0;
- int component = 0;
-
- if (context.Config.HasPerLocationInputOrOutput(ioVariable, isOutput))
- {
- location = operation.GetSource(1).Value;
-
- if (operation.SourcesCount > 2 &&
- operation.GetSource(2).Type == OperandType.Constant &&
- context.Config.HasPerLocationInputOrOutputComponent(ioVariable, location, operation.GetSource(2).Value, isOutput))
- {
- component = operation.GetSource(2).Value;
- }
- }
-
- context.Info.IoDefinitions.Add(new IoDefinition(storageKind, ioVariable, location, component));
- }
-
- bool vectorDest = IsVectorDestInst(inst);
-
- int sourcesCount = operation.SourcesCount;
- int outDestsCount = operation.DestsCount != 0 && !vectorDest ? operation.DestsCount - 1 : 0;
-
- IAstNode[] sources = new IAstNode[sourcesCount + outDestsCount];
-
- for (int index = 0; index < operation.SourcesCount; index++)
- {
- sources[index] = context.GetOperand(operation.GetSource(index));
- }
-
- for (int index = 0; index < outDestsCount; index++)
- {
- AstOperand oper = context.GetOperand(operation.GetDest(1 + index));
-
- oper.VarType = InstructionInfo.GetSrcVarType(inst, sourcesCount + index);
-
- sources[sourcesCount + index] = oper;
- }
-
- AstTextureOperation GetAstTextureOperation(TextureOperation texOp)
- {
- return new AstTextureOperation(
- inst,
- texOp.Type,
- texOp.Format,
- texOp.Flags,
- texOp.CbufSlot,
- texOp.Handle,
- texOp.Index,
- sources);
- }
-
- int componentsCount = BitOperations.PopCount((uint)operation.Index);
-
- if (vectorDest && componentsCount > 1)
- {
- AggregateType destType = InstructionInfo.GetDestVarType(inst);
-
- IAstNode source;
-
- if (operation is TextureOperation texOp)
- {
- if (texOp.Inst == Instruction.ImageLoad)
- {
- destType = texOp.Format.GetComponentType();
- }
-
- source = GetAstTextureOperation(texOp);
- }
- else
- {
- source = new AstOperation(inst, operation.StorageKind, operation.Index, sources, operation.SourcesCount);
- }
-
- AggregateType destElemType = destType;
-
- switch (componentsCount)
- {
- case 2: destType |= AggregateType.Vector2; break;
- case 3: destType |= AggregateType.Vector3; break;
- case 4: destType |= AggregateType.Vector4; break;
- }
-
- AstOperand destVec = context.NewTemp(destType);
-
- context.AddNode(new AstAssignment(destVec, source));
-
- for (int i = 0; i < operation.DestsCount; i++)
- {
- AstOperand dest = context.GetOperand(operation.GetDest(i));
- AstOperand index = new AstOperand(OperandType.Constant, i);
-
- dest.VarType = destElemType;
-
- context.AddNode(new AstAssignment(dest, new AstOperation(Instruction.VectorExtract, StorageKind.None, new[] { destVec, index }, 2)));
- }
- }
- else if (operation.Dest != null)
- {
- AstOperand dest = context.GetOperand(operation.Dest);
-
- // 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, AggregateType.Bool))
- {
- inst = GetLogicalFromBitwiseInst(inst);
- }
-
- bool isCondSel = inst == Instruction.ConditionalSelect;
- bool isCopy = inst == Instruction.Copy;
-
- if (isCondSel || isCopy)
- {
- AggregateType type = GetVarTypeFromUses(operation.Dest);
-
- if (isCondSel && type == AggregateType.FP32)
- {
- inst |= Instruction.FP32;
- }
-
- dest.VarType = type;
- }
- else
- {
- dest.VarType = InstructionInfo.GetDestVarType(inst);
- }
-
- IAstNode source;
-
- if (operation is TextureOperation texOp)
- {
- if (texOp.Inst == Instruction.ImageLoad)
- {
- dest.VarType = texOp.Format.GetComponentType();
- }
-
- source = GetAstTextureOperation(texOp);
- }
- else if (!isCopy)
- {
- source = new AstOperation(inst, operation.StorageKind, operation.Index, sources, operation.SourcesCount);
- }
- else
- {
- source = sources[0];
- }
-
- context.AddNode(new AstAssignment(dest, source));
- }
- else if (operation.Inst == Instruction.Comment)
- {
- context.AddNode(new AstComment(((CommentNode)operation).Comment));
- }
- else if (operation is TextureOperation texOp)
- {
- AstTextureOperation astTexOp = GetAstTextureOperation(texOp);
-
- context.AddNode(astTexOp);
- }
- else
- {
- context.AddNode(new AstOperation(inst, operation.StorageKind, operation.Index, sources, operation.SourcesCount));
- }
-
- // Those instructions needs to be emulated by using helper functions,
- // because they are NVIDIA specific. Those flags helps the backend to
- // decide which helper functions are needed on the final generated code.
- switch (operation.Inst)
- {
- case Instruction.AtomicMaxS32:
- case Instruction.AtomicMinS32:
- if (operation.StorageKind == StorageKind.SharedMemory)
- {
- context.Info.HelperFunctionsMask |= HelperFunctionsMask.AtomicMinMaxS32Shared;
- }
- else if (operation.StorageKind == StorageKind.StorageBuffer)
- {
- context.Info.HelperFunctionsMask |= HelperFunctionsMask.AtomicMinMaxS32Storage;
- }
- break;
- case Instruction.MultiplyHighS32:
- context.Info.HelperFunctionsMask |= HelperFunctionsMask.MultiplyHighS32;
- break;
- case Instruction.MultiplyHighU32:
- context.Info.HelperFunctionsMask |= HelperFunctionsMask.MultiplyHighU32;
- break;
- case Instruction.Shuffle:
- context.Info.HelperFunctionsMask |= HelperFunctionsMask.Shuffle;
- break;
- case Instruction.ShuffleDown:
- context.Info.HelperFunctionsMask |= HelperFunctionsMask.ShuffleDown;
- break;
- case Instruction.ShuffleUp:
- context.Info.HelperFunctionsMask |= HelperFunctionsMask.ShuffleUp;
- break;
- case Instruction.ShuffleXor:
- context.Info.HelperFunctionsMask |= HelperFunctionsMask.ShuffleXor;
- break;
- case Instruction.StoreShared16:
- case Instruction.StoreShared8:
- context.Info.HelperFunctionsMask |= HelperFunctionsMask.StoreSharedSmallInt;
- break;
- case Instruction.StoreStorage16:
- case Instruction.StoreStorage8:
- context.Info.HelperFunctionsMask |= HelperFunctionsMask.StoreStorageSmallInt;
- break;
- case Instruction.SwizzleAdd:
- context.Info.HelperFunctionsMask |= HelperFunctionsMask.SwizzleAdd;
- break;
- case Instruction.FSIBegin:
- case Instruction.FSIEnd:
- context.Info.HelperFunctionsMask |= HelperFunctionsMask.FSI;
- break;
- }
- }
-
- private static AggregateType 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 not 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 AggregateType.S32;
- }
-
- private static bool AreAllSourceTypesEqual(IAstNode[] sources, AggregateType type)
- {
- foreach (IAstNode node in sources)
- {
- if (node is not AstOperand operand)
- {
- return false;
- }
-
- if (operand.VarType != type)
- {
- return false;
- }
- }
-
- return true;
- }
-
- private static bool IsVectorDestInst(Instruction inst)
- {
- return inst switch
- {
- Instruction.ImageLoad or
- Instruction.TextureSample => true,
- _ => false
- };
- }
-
- private static bool IsBranchInst(Instruction inst)
- {
- return inst switch
- {
- Instruction.Branch or
- Instruction.BranchIfFalse or
- Instruction.BranchIfTrue => true,
- _ => false
- };
- }
-
- private static bool IsBitwiseInst(Instruction inst)
- {
- return inst switch
- {
- Instruction.BitwiseAnd or
- Instruction.BitwiseExclusiveOr or
- Instruction.BitwiseNot or
- Instruction.BitwiseOr => true,
- _ => false
- };
- }
-
- private static Instruction GetLogicalFromBitwiseInst(Instruction inst)
- {
- return inst switch
- {
- Instruction.BitwiseAnd => Instruction.LogicalAnd,
- Instruction.BitwiseExclusiveOr => Instruction.LogicalExclusiveOr,
- Instruction.BitwiseNot => Instruction.LogicalNot,
- Instruction.BitwiseOr => 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 68bbdeb1..00000000
--- a/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgramContext.cs
+++ /dev/null
@@ -1,330 +0,0 @@
-using Ryujinx.Graphics.Shader.IntermediateRepresentation;
-using Ryujinx.Graphics.Shader.Translation;
-using System.Collections.Generic;
-using System.Linq;
-using System.Numerics;
-
-using static Ryujinx.Graphics.Shader.StructuredIr.AstHelper;
-
-namespace Ryujinx.Graphics.Shader.StructuredIr
-{
- class StructuredProgramContext
- {
- private HashSet<BasicBlock> _loopTails;
-
- private Stack<(AstBlock Block, int CurrEndIndex, int LoopEndIndex)> _blockStack;
-
- private Dictionary<Operand, AstOperand> _localsMap;
-
- private Dictionary<int, AstAssignment> _gotoTempAsgs;
-
- private List<GotoStatement> _gotos;
-
- private AstBlock _currBlock;
-
- private int _currEndIndex;
- private int _loopEndIndex;
-
- public StructuredFunction CurrentFunction { get; private set; }
-
- public StructuredProgramInfo Info { get; }
-
- public ShaderConfig Config { get; }
-
- public StructuredProgramContext(ShaderConfig config)
- {
- Info = new StructuredProgramInfo();
-
- Config = config;
-
- if (config.GpPassthrough)
- {
- int passthroughAttributes = config.PassthroughAttributes;
- while (passthroughAttributes != 0)
- {
- int index = BitOperations.TrailingZeroCount(passthroughAttributes);
-
- Info.IoDefinitions.Add(new IoDefinition(StorageKind.Input, IoVariable.UserDefined, index));
-
- passthroughAttributes &= ~(1 << index);
- }
-
- Info.IoDefinitions.Add(new IoDefinition(StorageKind.Input, IoVariable.Position));
- Info.IoDefinitions.Add(new IoDefinition(StorageKind.Input, IoVariable.PointSize));
- Info.IoDefinitions.Add(new IoDefinition(StorageKind.Input, IoVariable.ClipDistance));
- }
- else if (config.Stage == ShaderStage.Fragment)
- {
- // Potentially used for texture coordinate scaling.
- Info.IoDefinitions.Add(new IoDefinition(StorageKind.Input, IoVariable.FragmentCoord));
- }
- }
-
- public void EnterFunction(
- int blocksCount,
- string name,
- AggregateType returnType,
- AggregateType[] inArguments,
- AggregateType[] outArguments)
- {
- _loopTails = new HashSet<BasicBlock>();
-
- _blockStack = new Stack<(AstBlock, int, int)>();
-
- _localsMap = new Dictionary<Operand, AstOperand>();
-
- _gotoTempAsgs = new Dictionary<int, AstAssignment>();
-
- _gotos = new List<GotoStatement>();
-
- _currBlock = new AstBlock(AstBlockType.Main);
-
- _currEndIndex = blocksCount;
- _loopEndIndex = blocksCount;
-
- CurrentFunction = new StructuredFunction(_currBlock, name, returnType, inArguments, outArguments);
- }
-
- public void LeaveFunction()
- {
- Info.Functions.Add(CurrentFunction);
- }
-
- public void EnterBlock(BasicBlock block)
- {
- while (_currEndIndex == block.Index)
- {
- (_currBlock, _currEndIndex, _loopEndIndex) = _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 not a loop, break.
- if (predecessor.Index < block.Index)
- {
- break;
- }
-
- // Check if we can create a do-while loop here (only possible if the loop end
- // falls inside the current scope), if not add a goto instead.
- if (predecessor.Index < _currEndIndex && !done)
- {
- // Create do-while loop block. We must avoid inserting a goto at the end
- // of the loop later, when the tail block is processed. So we add the predecessor
- // to a list of loop tails to prevent it from being processed later.
- Operation branchOp = (Operation)predecessor.GetLastOp();
-
- NewBlock(AstBlockType.DoWhile, branchOp, predecessor.Index + 1);
-
- _loopTails.Add(predecessor);
-
- done = true;
- }
- else
- {
- // Failed to create loop. Since this block is the loop head, we reset the
- // goto condition variable here. The variable is always reset on the jump
- // target, and this block is the jump target for some loop.
- AddGotoTempReset(block, GetGotoTempAsg(block.Index));
-
- break;
- }
- }
- }
-
- private void LookForIfStatements(BasicBlock block, Operation branchOp)
- {
- if (block.Branch == null)
- {
- return;
- }
-
- // We can only enclose the "if" when the branch lands before
- // the end of the current block. If the current enclosing block
- // is not a loop, then we can also do so if the branch lands
- // right at the end of the current block. When it is a loop,
- // this is not valid as the loop condition would be evaluated,
- // and it could erroneously jump back to the start of the loop.
- bool inRange =
- block.Branch.Index < _currEndIndex ||
- (block.Branch.Index == _currEndIndex && block.Branch.Index < _loopEndIndex);
-
- bool isLoop = block.Branch.Index <= block.Index;
-
- if (inRange && !isLoop)
- {
- NewBlock(AstBlockType.If, branchOp, block.Branch.Index);
- }
- else if (!_loopTails.Contains(block))
- {
- AstAssignment gotoTempAsg = GetGotoTempAsg(block.Branch.Index);
-
- // We use DoWhile type here, as the condition should be true for
- // unconditional branches, or it should jump if the condition is true otherwise.
- 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(AggregateType.Bool);
-
- gotoTempAsg = Assign(gotoTemp, Const(IrConsts.False));
-
- _gotoTempAsgs.Add(index, gotoTempAsg);
-
- return gotoTempAsg;
- }
-
- private void AddGotoTempReset(BasicBlock block, AstAssignment gotoTempAsg)
- {
- // If it was already added, we don't need to add it again.
- if (gotoTempAsg.Parent != null)
- {
- return;
- }
-
- 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)
- {
- CurrentFunction.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, _loopEndIndex));
-
- _currBlock = childBlock;
- _currEndIndex = endIndex;
-
- if (type == AstBlockType.DoWhile)
- {
- _loopEndIndex = endIndex;
- }
- }
-
- private IAstNode GetBranchCond(AstBlockType type, Operation branchOp)
- {
- IAstNode cond;
-
- if (branchOp.Inst == Instruction.Branch)
- {
- // If the branch is not conditional, the condition is a constant.
- // For if it's false (always jump over, if block never executed).
- // For loops it's always true (always loop).
- cond = Const(type == AstBlockType.If ? IrConsts.False : IrConsts.True);
- }
- else
- {
- cond = GetOperand(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();
- }
-
- public AstOperand NewTemp(AggregateType type)
- {
- AstOperand newTemp = Local(type);
-
- CurrentFunction.Locals.Add(newTemp);
-
- return newTemp;
- }
-
- public AstOperand GetOperand(Operand operand)
- {
- if (operand == null)
- {
- return null;
- }
-
- if (operand.Type != OperandType.LocalVariable)
- {
- if (operand.Type == OperandType.ConstantBuffer)
- {
- Config.SetUsedConstantBuffer(operand.GetCbufSlot());
- }
-
- return new AstOperand(operand);
- }
-
- if (!_localsMap.TryGetValue(operand, out AstOperand astOperand))
- {
- astOperand = new AstOperand(operand);
-
- _localsMap.Add(operand, astOperand);
-
- CurrentFunction.Locals.Add(astOperand);
- }
-
- return astOperand;
- }
- }
-} \ 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 c5104146..00000000
--- a/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgramInfo.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using System.Collections.Generic;
-
-namespace Ryujinx.Graphics.Shader.StructuredIr
-{
- readonly struct TransformFeedbackOutput
- {
- public readonly bool Valid;
- public readonly int Buffer;
- public readonly int Offset;
- public readonly int Stride;
-
- public TransformFeedbackOutput(int buffer, int offset, int stride)
- {
- Valid = true;
- Buffer = buffer;
- Offset = offset;
- Stride = stride;
- }
- }
-
- class StructuredProgramInfo
- {
- public List<StructuredFunction> Functions { get; }
-
- public HashSet<IoDefinition> IoDefinitions { get; }
-
- public HelperFunctionsMask HelperFunctionsMask { get; set; }
-
- public StructuredProgramInfo()
- {
- Functions = new List<StructuredFunction>();
-
- IoDefinitions = new HashSet<IoDefinition>();
- }
- }
-} \ No newline at end of file