aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics/Shader/Translation
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/Translation
parentf617fb542a0e3d36012d77a4b5acbde7b08902f2 (diff)
Initial work
Diffstat (limited to 'Ryujinx.Graphics/Shader/Translation')
-rw-r--r--Ryujinx.Graphics/Shader/Translation/AttributeConsts.cs38
-rw-r--r--Ryujinx.Graphics/Shader/Translation/ControlFlowGraph.cs108
-rw-r--r--Ryujinx.Graphics/Shader/Translation/Dominance.cs127
-rw-r--r--Ryujinx.Graphics/Shader/Translation/EmitterContext.cs105
-rw-r--r--Ryujinx.Graphics/Shader/Translation/EmitterContextInsts.cs420
-rw-r--r--Ryujinx.Graphics/Shader/Translation/Optimizations/BranchElimination.cs64
-rw-r--r--Ryujinx.Graphics/Shader/Translation/Optimizations/ConstantFolding.cs323
-rw-r--r--Ryujinx.Graphics/Shader/Translation/Optimizations/HalfConversion.cs47
-rw-r--r--Ryujinx.Graphics/Shader/Translation/Optimizations/Optimizer.cs172
-rw-r--r--Ryujinx.Graphics/Shader/Translation/Optimizations/Simplification.cs147
-rw-r--r--Ryujinx.Graphics/Shader/Translation/Ssa.cs330
-rw-r--r--Ryujinx.Graphics/Shader/Translation/Translator.cs219
12 files changed, 0 insertions, 2100 deletions
diff --git a/Ryujinx.Graphics/Shader/Translation/AttributeConsts.cs b/Ryujinx.Graphics/Shader/Translation/AttributeConsts.cs
deleted file mode 100644
index f21a6252..00000000
--- a/Ryujinx.Graphics/Shader/Translation/AttributeConsts.cs
+++ /dev/null
@@ -1,38 +0,0 @@
-namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
-{
- static class AttributeConsts
- {
- public const int Layer = 0x064;
- public const int PointSize = 0x06c;
- public const int PositionX = 0x070;
- public const int PositionY = 0x074;
- public const int PositionZ = 0x078;
- public const int PositionW = 0x07c;
- public const int ClipDistance0 = 0x2c0;
- public const int ClipDistance1 = 0x2c4;
- public const int ClipDistance2 = 0x2c8;
- public const int ClipDistance3 = 0x2cc;
- public const int ClipDistance4 = 0x2d0;
- public const int ClipDistance5 = 0x2d4;
- public const int ClipDistance6 = 0x2d8;
- public const int ClipDistance7 = 0x2dc;
- public const int PointCoordX = 0x2e0;
- public const int PointCoordY = 0x2e4;
- public const int TessCoordX = 0x2f0;
- public const int TessCoordY = 0x2f4;
- public const int InstanceId = 0x2f8;
- public const int VertexId = 0x2fc;
- public const int FrontFacing = 0x3fc;
-
- public const int UserAttributesCount = 32;
- public const int UserAttributeBase = 0x80;
- public const int UserAttributeEnd = UserAttributeBase + UserAttributesCount * 16;
-
-
- // Note: Those attributes are used internally by the translator
- // only, they don't exist on Maxwell.
- public const int FragmentOutputDepth = 0x1000000;
- public const int FragmentOutputColorBase = 0x1000010;
- public const int FragmentOutputColorEnd = FragmentOutputColorBase + 8 * 16;
- }
-} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Shader/Translation/ControlFlowGraph.cs b/Ryujinx.Graphics/Shader/Translation/ControlFlowGraph.cs
deleted file mode 100644
index e2ca74a4..00000000
--- a/Ryujinx.Graphics/Shader/Translation/ControlFlowGraph.cs
+++ /dev/null
@@ -1,108 +0,0 @@
-using Ryujinx.Graphics.Shader.IntermediateRepresentation;
-using System.Collections.Generic;
-
-namespace Ryujinx.Graphics.Shader.Translation
-{
- static class ControlFlowGraph
- {
- public static BasicBlock[] MakeCfg(Operation[] operations)
- {
- Dictionary<Operand, BasicBlock> labels = new Dictionary<Operand, BasicBlock>();
-
- List<BasicBlock> blocks = new List<BasicBlock>();
-
- BasicBlock currentBlock = null;
-
- void NextBlock(BasicBlock nextBlock)
- {
- if (currentBlock != null && !EndsWithUnconditionalInst(currentBlock.GetLastOp()))
- {
- currentBlock.Next = nextBlock;
- }
-
- currentBlock = nextBlock;
- }
-
- void NewNextBlock()
- {
- BasicBlock block = new BasicBlock(blocks.Count);
-
- blocks.Add(block);
-
- NextBlock(block);
- }
-
- bool needsNewBlock = true;
-
- for (int index = 0; index < operations.Length; index++)
- {
- Operation operation = operations[index];
-
- if (operation.Inst == Instruction.MarkLabel)
- {
- Operand label = operation.Dest;
-
- if (labels.TryGetValue(label, out BasicBlock nextBlock))
- {
- nextBlock.Index = blocks.Count;
-
- blocks.Add(nextBlock);
-
- NextBlock(nextBlock);
- }
- else
- {
- NewNextBlock();
-
- labels.Add(label, currentBlock);
- }
- }
- else
- {
- if (needsNewBlock)
- {
- NewNextBlock();
- }
-
- currentBlock.Operations.AddLast(operation);
- }
-
- needsNewBlock = operation.Inst == Instruction.Branch ||
- operation.Inst == Instruction.BranchIfTrue ||
- operation.Inst == Instruction.BranchIfFalse;
-
- if (needsNewBlock)
- {
- Operand label = operation.Dest;
-
- if (!labels.TryGetValue(label, out BasicBlock branchBlock))
- {
- branchBlock = new BasicBlock();
-
- labels.Add(label, branchBlock);
- }
-
- currentBlock.Branch = branchBlock;
- }
- }
-
- return blocks.ToArray();
- }
-
- private static bool EndsWithUnconditionalInst(INode node)
- {
- if (node is Operation operation)
- {
- switch (operation.Inst)
- {
- case Instruction.Branch:
- case Instruction.Discard:
- case Instruction.Return:
- return true;
- }
- }
-
- return false;
- }
- }
-} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Shader/Translation/Dominance.cs b/Ryujinx.Graphics/Shader/Translation/Dominance.cs
deleted file mode 100644
index 6a3ff35f..00000000
--- a/Ryujinx.Graphics/Shader/Translation/Dominance.cs
+++ /dev/null
@@ -1,127 +0,0 @@
-using Ryujinx.Graphics.Shader.IntermediateRepresentation;
-using System.Collections.Generic;
-
-namespace Ryujinx.Graphics.Shader.Translation
-{
- static class Dominance
- {
- // Those methods are an implementation of the algorithms on "A Simple, Fast Dominance Algorithm".
- // https://www.cs.rice.edu/~keith/EMBED/dom.pdf
- public static void FindDominators(BasicBlock entry, int blocksCount)
- {
- HashSet<BasicBlock> visited = new HashSet<BasicBlock>();
-
- Stack<BasicBlock> blockStack = new Stack<BasicBlock>();
-
- List<BasicBlock> postOrderBlocks = new List<BasicBlock>(blocksCount);
-
- int[] postOrderMap = new int[blocksCount];
-
- visited.Add(entry);
-
- blockStack.Push(entry);
-
- while (blockStack.TryPop(out BasicBlock block))
- {
- if (block.Next != null && visited.Add(block.Next))
- {
- blockStack.Push(block);
- blockStack.Push(block.Next);
- }
- else if (block.Branch != null && visited.Add(block.Branch))
- {
- blockStack.Push(block);
- blockStack.Push(block.Branch);
- }
- else
- {
- postOrderMap[block.Index] = postOrderBlocks.Count;
-
- postOrderBlocks.Add(block);
- }
- }
-
- BasicBlock Intersect(BasicBlock block1, BasicBlock block2)
- {
- while (block1 != block2)
- {
- while (postOrderMap[block1.Index] < postOrderMap[block2.Index])
- {
- block1 = block1.ImmediateDominator;
- }
-
- while (postOrderMap[block2.Index] < postOrderMap[block1.Index])
- {
- block2 = block2.ImmediateDominator;
- }
- }
-
- return block1;
- }
-
- entry.ImmediateDominator = entry;
-
- bool modified;
-
- do
- {
- modified = false;
-
- for (int blkIndex = postOrderBlocks.Count - 2; blkIndex >= 0; blkIndex--)
- {
- BasicBlock block = postOrderBlocks[blkIndex];
-
- BasicBlock newIDom = null;
-
- foreach (BasicBlock predecessor in block.Predecessors)
- {
- if (predecessor.ImmediateDominator != null)
- {
- if (newIDom != null)
- {
- newIDom = Intersect(predecessor, newIDom);
- }
- else
- {
- newIDom = predecessor;
- }
- }
- }
-
- if (block.ImmediateDominator != newIDom)
- {
- block.ImmediateDominator = newIDom;
-
- modified = true;
- }
- }
- }
- while (modified);
- }
-
- public static void FindDominanceFrontiers(BasicBlock[] blocks)
- {
- for (int blkIndex = 0; blkIndex < blocks.Length; blkIndex++)
- {
- BasicBlock block = blocks[blkIndex];
-
- if (block.Predecessors.Count < 2)
- {
- continue;
- }
-
- for (int pBlkIndex = 0; pBlkIndex < block.Predecessors.Count; pBlkIndex++)
- {
- BasicBlock current = block.Predecessors[pBlkIndex];
-
- while (current != block.ImmediateDominator)
- {
- current.DominanceFrontiers.Add(block);
-
- current = current.ImmediateDominator;
- }
- }
- }
- }
- }
-} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Shader/Translation/EmitterContext.cs b/Ryujinx.Graphics/Shader/Translation/EmitterContext.cs
deleted file mode 100644
index 6c2bf6e4..00000000
--- a/Ryujinx.Graphics/Shader/Translation/EmitterContext.cs
+++ /dev/null
@@ -1,105 +0,0 @@
-using Ryujinx.Graphics.Gal;
-using Ryujinx.Graphics.Shader.Decoders;
-using Ryujinx.Graphics.Shader.IntermediateRepresentation;
-using System.Collections.Generic;
-
-using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
-
-namespace Ryujinx.Graphics.Shader.Translation
-{
- class EmitterContext
- {
- public Block CurrBlock { get; set; }
- public OpCode CurrOp { get; set; }
-
- private GalShaderType _shaderType;
-
- private ShaderHeader _header;
-
- private List<Operation> _operations;
-
- private Dictionary<ulong, Operand> _labels;
-
- public EmitterContext(GalShaderType shaderType, ShaderHeader header)
- {
- _shaderType = shaderType;
- _header = header;
-
- _operations = new List<Operation>();
-
- _labels = new Dictionary<ulong, Operand>();
- }
-
- public Operand Add(Instruction inst, Operand dest = null, params Operand[] sources)
- {
- Operation operation = new Operation(inst, dest, sources);
-
- Add(operation);
-
- return dest;
- }
-
- public void Add(Operation operation)
- {
- _operations.Add(operation);
- }
-
- public void MarkLabel(Operand label)
- {
- Add(Instruction.MarkLabel, label);
- }
-
- public Operand GetLabel(ulong address)
- {
- if (!_labels.TryGetValue(address, out Operand label))
- {
- label = Label();
-
- _labels.Add(address, label);
- }
-
- return label;
- }
-
- public void PrepareForReturn()
- {
- if (_shaderType == GalShaderType.Fragment)
- {
- if (_header.OmapDepth)
- {
- Operand dest = Attribute(AttributeConsts.FragmentOutputDepth);
-
- Operand src = Register(_header.DepthRegister, RegisterType.Gpr);
-
- this.Copy(dest, src);
- }
-
- int regIndex = 0;
-
- for (int attachment = 0; attachment < 8; attachment++)
- {
- OutputMapTarget target = _header.OmapTargets[attachment];
-
- for (int component = 0; component < 4; component++)
- {
- if (target.ComponentEnabled(component))
- {
- Operand dest = Attribute(AttributeConsts.FragmentOutputColorBase + regIndex * 4);
-
- Operand src = Register(regIndex, RegisterType.Gpr);
-
- this.Copy(dest, src);
-
- regIndex++;
- }
- }
- }
- }
- }
-
- public Operation[] GetOperations()
- {
- return _operations.ToArray();
- }
- }
-} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Shader/Translation/EmitterContextInsts.cs b/Ryujinx.Graphics/Shader/Translation/EmitterContextInsts.cs
deleted file mode 100644
index 604aa67d..00000000
--- a/Ryujinx.Graphics/Shader/Translation/EmitterContextInsts.cs
+++ /dev/null
@@ -1,420 +0,0 @@
-using Ryujinx.Graphics.Shader.IntermediateRepresentation;
-
-using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
-
-namespace Ryujinx.Graphics.Shader.Translation
-{
- static class EmitterContextInsts
- {
- public static Operand BitfieldExtractS32(this EmitterContext context, Operand a, Operand b, Operand c)
- {
- return context.Add(Instruction.BitfieldExtractS32, Local(), a, b, c);
- }
-
- public static Operand BitfieldExtractU32(this EmitterContext context, Operand a, Operand b, Operand c)
- {
- return context.Add(Instruction.BitfieldExtractU32, Local(), a, b, c);
- }
-
- public static Operand BitfieldInsert(this EmitterContext context, Operand a, Operand b, Operand c, Operand d)
- {
- return context.Add(Instruction.BitfieldInsert, Local(), a, b, c, d);
- }
-
- public static Operand BitfieldReverse(this EmitterContext context, Operand a)
- {
- return context.Add(Instruction.BitfieldReverse, Local(), a);
- }
-
- public static Operand BitwiseAnd(this EmitterContext context, Operand a, Operand b)
- {
- return context.Add(Instruction.BitwiseAnd, Local(), a, b);
- }
-
- public static Operand BitwiseExclusiveOr(this EmitterContext context, Operand a, Operand b)
- {
- return context.Add(Instruction.BitwiseExclusiveOr, Local(), a, b);
- }
-
- public static Operand BitwiseNot(this EmitterContext context, Operand a, bool invert)
- {
- if (invert)
- {
- a = context.BitwiseNot(a);
- }
-
- return a;
- }
-
- public static Operand BitwiseNot(this EmitterContext context, Operand a)
- {
- return context.Add(Instruction.BitwiseNot, Local(), a);
- }
-
- public static Operand BitwiseOr(this EmitterContext context, Operand a, Operand b)
- {
- return context.Add(Instruction.BitwiseOr, Local(), a, b);
- }
-
- public static Operand Branch(this EmitterContext context, Operand d)
- {
- return context.Add(Instruction.Branch, d);
- }
-
- public static Operand BranchIfFalse(this EmitterContext context, Operand d, Operand a)
- {
- return context.Add(Instruction.BranchIfFalse, d, a);
- }
-
- public static Operand BranchIfTrue(this EmitterContext context, Operand d, Operand a)
- {
- return context.Add(Instruction.BranchIfTrue, d, a);
- }
-
- public static Operand ConditionalSelect(this EmitterContext context, Operand a, Operand b, Operand c)
- {
- return context.Add(Instruction.ConditionalSelect, Local(), a, b, c);
- }
-
- public static Operand Copy(this EmitterContext context, Operand a)
- {
- return context.Add(Instruction.Copy, Local(), a);
- }
-
- public static void Copy(this EmitterContext context, Operand d, Operand a)
- {
- if (d.Type == OperandType.Constant)
- {
- return;
- }
-
- context.Add(Instruction.Copy, d, a);
- }
-
- public static Operand Discard(this EmitterContext context)
- {
- return context.Add(Instruction.Discard);
- }
-
- public static Operand EmitVertex(this EmitterContext context)
- {
- return context.Add(Instruction.EmitVertex);
- }
-
- public static Operand EndPrimitive(this EmitterContext context)
- {
- return context.Add(Instruction.EndPrimitive);
- }
-
- public static Operand FPAbsNeg(this EmitterContext context, Operand a, bool abs, bool neg)
- {
- return context.FPNegate(context.FPAbsolute(a, abs), neg);
- }
-
- public static Operand FPAbsolute(this EmitterContext context, Operand a, bool abs)
- {
- if (abs)
- {
- a = context.FPAbsolute(a);
- }
-
- return a;
- }
-
- public static Operand FPAbsolute(this EmitterContext context, Operand a)
- {
- return context.Add(Instruction.FP | Instruction.Absolute, Local(), a);
- }
-
- public static Operand FPAdd(this EmitterContext context, Operand a, Operand b)
- {
- return context.Add(Instruction.FP | Instruction.Add, Local(), a, b);
- }
-
- public static Operand FPCeiling(this EmitterContext context, Operand a)
- {
- return context.Add(Instruction.FP | Instruction.Ceiling, Local(), a);
- }
-
- public static Operand FPCompareEqual(this EmitterContext context, Operand a, Operand b)
- {
- return context.Add(Instruction.FP | Instruction.CompareEqual, Local(), a, b);
- }
-
- public static Operand FPCompareLess(this EmitterContext context, Operand a, Operand b)
- {
- return context.Add(Instruction.FP | Instruction.CompareLess, Local(), a, b);
- }
-
- public static Operand FPConvertToS32(this EmitterContext context, Operand a)
- {
- return context.Add(Instruction.ConvertFPToS32, Local(), a);
- }
-
- public static Operand FPCosine(this EmitterContext context, Operand a)
- {
- return context.Add(Instruction.FP | Instruction.Cosine, Local(), a);
- }
-
- public static Operand FPDivide(this EmitterContext context, Operand a, Operand b)
- {
- return context.Add(Instruction.FP | Instruction.Divide, Local(), a, b);
- }
-
- public static Operand FPExponentB2(this EmitterContext context, Operand a)
- {
- return context.Add(Instruction.FP | Instruction.ExponentB2, Local(), a);
- }
-
- public static Operand FPFloor(this EmitterContext context, Operand a)
- {
- return context.Add(Instruction.FP | Instruction.Floor, Local(), a);
- }
-
- public static Operand FPLogarithmB2(this EmitterContext context, Operand a)
- {
- return context.Add(Instruction.FP | Instruction.LogarithmB2, Local(), a);
- }
-
- public static Operand FPMaximum(this EmitterContext context, Operand a, Operand b)
- {
- return context.Add(Instruction.FP | Instruction.Maximum, Local(), a, b);
- }
-
- public static Operand FPMinimum(this EmitterContext context, Operand a, Operand b)
- {
- return context.Add(Instruction.FP | Instruction.Minimum, Local(), a, b);
- }
-
- public static Operand FPMultiply(this EmitterContext context, Operand a, Operand b)
- {
- return context.Add(Instruction.FP | Instruction.Multiply, Local(), a, b);
- }
-
- public static Operand FPFusedMultiplyAdd(this EmitterContext context, Operand a, Operand b, Operand c)
- {
- return context.Add(Instruction.FusedMultiplyAdd, Local(), a, b, c);
- }
-
- public static Operand FPNegate(this EmitterContext context, Operand a, bool neg)
- {
- if (neg)
- {
- a = context.FPNegate(a);
- }
-
- return a;
- }
-
- public static Operand FPNegate(this EmitterContext context, Operand a)
- {
- return context.Add(Instruction.FP | Instruction.Negate, Local(), a);
- }
-
- public static Operand FPReciprocal(this EmitterContext context, Operand a)
- {
- return context.FPDivide(ConstF(1), a);
- }
-
- public static Operand FPReciprocalSquareRoot(this EmitterContext context, Operand a)
- {
- return context.Add(Instruction.FP | Instruction.ReciprocalSquareRoot, Local(), a);
- }
-
- public static Operand FPSaturate(this EmitterContext context, Operand a, bool sat)
- {
- if (sat)
- {
- a = context.FPSaturate(a);
- }
-
- return a;
- }
-
- public static Operand FPSaturate(this EmitterContext context, Operand a)
- {
- return context.Add(Instruction.FP | Instruction.Clamp, Local(), a, ConstF(0), ConstF(1));
- }
-
- public static Operand FPSine(this EmitterContext context, Operand a)
- {
- return context.Add(Instruction.FP | Instruction.Sine, Local(), a);
- }
-
- public static Operand FPSquareRoot(this EmitterContext context, Operand a)
- {
- return context.Add(Instruction.FP | Instruction.SquareRoot, Local(), a);
- }
-
- public static Operand FPTruncate(this EmitterContext context, Operand a)
- {
- return context.Add(Instruction.Truncate, Local(), a);
- }
-
- public static Operand IAbsNeg(this EmitterContext context, Operand a, bool abs, bool neg)
- {
- return context.INegate(context.IAbsolute(a, abs), neg);
- }
-
- public static Operand IAbsolute(this EmitterContext context, Operand a, bool abs)
- {
- if (abs)
- {
- a = context.IAbsolute(a);
- }
-
- return a;
- }
-
- public static Operand IAbsolute(this EmitterContext context, Operand a)
- {
- return context.Add(Instruction.Absolute, Local(), a);
- }
-
- public static Operand IAdd(this EmitterContext context, Operand a, Operand b)
- {
- return context.Add(Instruction.Add, Local(), a, b);
- }
-
- public static Operand IClampS32(this EmitterContext context, Operand a, Operand b, Operand c)
- {
- return context.Add(Instruction.Clamp, Local(), a, b, c);
- }
-
- public static Operand IClampU32(this EmitterContext context, Operand a, Operand b, Operand c)
- {
- return context.Add(Instruction.ClampU32, Local(), a, b, c);
- }
-
- public static Operand ICompareEqual(this EmitterContext context, Operand a, Operand b)
- {
- return context.Add(Instruction.CompareEqual, Local(), a, b);
- }
-
- public static Operand ICompareLess(this EmitterContext context, Operand a, Operand b)
- {
- return context.Add(Instruction.CompareLess, Local(), a, b);
- }
-
- public static Operand ICompareLessUnsigned(this EmitterContext context, Operand a, Operand b)
- {
- return context.Add(Instruction.CompareLessU32, Local(), a, b);
- }
-
- public static Operand ICompareNotEqual(this EmitterContext context, Operand a, Operand b)
- {
- return context.Add(Instruction.CompareNotEqual, Local(), a, b);
- }
-
- public static Operand IConvertS32ToFP(this EmitterContext context, Operand a)
- {
- return context.Add(Instruction.ConvertS32ToFP, Local(), a);
- }
-
- public static Operand IConvertU32ToFP(this EmitterContext context, Operand a)
- {
- return context.Add(Instruction.ConvertU32ToFP, Local(), a);
- }
-
- public static Operand IMaximumS32(this EmitterContext context, Operand a, Operand b)
- {
- return context.Add(Instruction.Maximum, Local(), a, b);
- }
-
- public static Operand IMaximumU32(this EmitterContext context, Operand a, Operand b)
- {
- return context.Add(Instruction.MaximumU32, Local(), a, b);
- }
-
- public static Operand IMinimumS32(this EmitterContext context, Operand a, Operand b)
- {
- return context.Add(Instruction.Minimum, Local(), a, b);
- }
-
- public static Operand IMinimumU32(this EmitterContext context, Operand a, Operand b)
- {
- return context.Add(Instruction.MinimumU32, Local(), a, b);
- }
-
- public static Operand IMultiply(this EmitterContext context, Operand a, Operand b)
- {
- return context.Add(Instruction.Multiply, Local(), a, b);
- }
-
- public static Operand INegate(this EmitterContext context, Operand a, bool neg)
- {
- if (neg)
- {
- a = context.INegate(a);
- }
-
- return a;
- }
-
- public static Operand INegate(this EmitterContext context, Operand a)
- {
- return context.Add(Instruction.Negate, Local(), a);
- }
-
- public static Operand ISubtract(this EmitterContext context, Operand a, Operand b)
- {
- return context.Add(Instruction.Subtract, Local(), a, b);
- }
-
- public static Operand IsNan(this EmitterContext context, Operand a)
- {
- return context.Add(Instruction.IsNan, Local(), a);
- }
-
- public static Operand LoadConstant(this EmitterContext context, Operand a, Operand b)
- {
- return context.Add(Instruction.LoadConstant, Local(), a, b);
- }
-
- public static Operand PackHalf2x16(this EmitterContext context, Operand a, Operand b)
- {
- return context.Add(Instruction.PackHalf2x16, Local(), a, b);
- }
-
- public static Operand Return(this EmitterContext context)
- {
- context.PrepareForReturn();
-
- return context.Add(Instruction.Return);
- }
-
- public static Operand ShiftLeft(this EmitterContext context, Operand a, Operand b)
- {
- return context.Add(Instruction.ShiftLeft, Local(), a, b);
- }
-
- public static Operand ShiftRightS32(this EmitterContext context, Operand a, Operand b)
- {
- return context.Add(Instruction.ShiftRightS32, Local(), a, b);
- }
-
- public static Operand ShiftRightU32(this EmitterContext context, Operand a, Operand b)
- {
- return context.Add(Instruction.ShiftRightU32, Local(), a, b);
- }
-
- public static Operand UnpackHalf2x16High(this EmitterContext context, Operand a)
- {
- return UnpackHalf2x16(context, a, 1);
- }
-
- public static Operand UnpackHalf2x16Low(this EmitterContext context, Operand a)
- {
- return UnpackHalf2x16(context, a, 0);
- }
-
- private static Operand UnpackHalf2x16(this EmitterContext context, Operand a, int index)
- {
- Operand dest = Local();
-
- context.Add(new Operation(Instruction.UnpackHalf2x16, index, dest, a));
-
- return dest;
- }
- }
-} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Shader/Translation/Optimizations/BranchElimination.cs b/Ryujinx.Graphics/Shader/Translation/Optimizations/BranchElimination.cs
deleted file mode 100644
index 070f07a4..00000000
--- a/Ryujinx.Graphics/Shader/Translation/Optimizations/BranchElimination.cs
+++ /dev/null
@@ -1,64 +0,0 @@
-using Ryujinx.Graphics.Shader.IntermediateRepresentation;
-using System;
-
-namespace Ryujinx.Graphics.Shader.Translation.Optimizations
-{
- static class BranchElimination
- {
- public static bool Eliminate(BasicBlock block)
- {
- if (block.HasBranch && IsRedundantBranch((Operation)block.GetLastOp(), Next(block)))
- {
- block.Branch = null;
-
- return true;
- }
-
- return false;
- }
-
- private static bool IsRedundantBranch(Operation current, BasicBlock nextBlock)
- {
- // Here we check that:
- // - The current block ends with a branch.
- // - The next block only contains a branch.
- // - The branch on the next block is unconditional.
- // - Both branches are jumping to the same location.
- // In this case, the branch on the current block can be removed,
- // as the next block is going to jump to the same place anyway.
- if (nextBlock == null)
- {
- return false;
- }
-
- if (!(nextBlock.Operations.First?.Value is Operation next))
- {
- return false;
- }
-
- if (next.Inst != Instruction.Branch)
- {
- return false;
- }
-
- return current.Dest == next.Dest;
- }
-
- private static BasicBlock Next(BasicBlock block)
- {
- block = block.Next;
-
- while (block != null && block.Operations.Count == 0)
- {
- if (block.HasBranch)
- {
- throw new InvalidOperationException("Found a bogus empty block that \"ends with a branch\".");
- }
-
- block = block.Next;
- }
-
- return block;
- }
- }
-} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Shader/Translation/Optimizations/ConstantFolding.cs b/Ryujinx.Graphics/Shader/Translation/Optimizations/ConstantFolding.cs
deleted file mode 100644
index a2e05ef1..00000000
--- a/Ryujinx.Graphics/Shader/Translation/Optimizations/ConstantFolding.cs
+++ /dev/null
@@ -1,323 +0,0 @@
-using Ryujinx.Graphics.Shader.Decoders;
-using Ryujinx.Graphics.Shader.IntermediateRepresentation;
-using System;
-
-using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
-
-namespace Ryujinx.Graphics.Shader.Translation.Optimizations
-{
- static class ConstantFolding
- {
- public static void Fold(Operation operation)
- {
- if (!AreAllSourcesConstant(operation))
- {
- return;
- }
-
- switch (operation.Inst)
- {
- case Instruction.Add:
- EvaluateBinary(operation, (x, y) => x + y);
- break;
-
- case Instruction.BitwiseAnd:
- EvaluateBinary(operation, (x, y) => x & y);
- break;
-
- case Instruction.BitwiseExclusiveOr:
- EvaluateBinary(operation, (x, y) => x ^ y);
- break;
-
- case Instruction.BitwiseNot:
- EvaluateUnary(operation, (x) => ~x);
- break;
-
- case Instruction.BitwiseOr:
- EvaluateBinary(operation, (x, y) => x | y);
- break;
-
- case Instruction.BitfieldExtractS32:
- BitfieldExtractS32(operation);
- break;
-
- case Instruction.BitfieldExtractU32:
- BitfieldExtractU32(operation);
- break;
-
- case Instruction.Clamp:
- EvaluateTernary(operation, (x, y, z) => Math.Clamp(x, y, z));
- break;
-
- case Instruction.ClampU32:
- EvaluateTernary(operation, (x, y, z) => (int)Math.Clamp((uint)x, (uint)y, (uint)z));
- break;
-
- case Instruction.CompareEqual:
- EvaluateBinary(operation, (x, y) => x == y);
- break;
-
- case Instruction.CompareGreater:
- EvaluateBinary(operation, (x, y) => x > y);
- break;
-
- case Instruction.CompareGreaterOrEqual:
- EvaluateBinary(operation, (x, y) => x >= y);
- break;
-
- case Instruction.CompareGreaterOrEqualU32:
- EvaluateBinary(operation, (x, y) => (uint)x >= (uint)y);
- break;
-
- case Instruction.CompareGreaterU32:
- EvaluateBinary(operation, (x, y) => (uint)x > (uint)y);
- break;
-
- case Instruction.CompareLess:
- EvaluateBinary(operation, (x, y) => x < y);
- break;
-
- case Instruction.CompareLessOrEqual:
- EvaluateBinary(operation, (x, y) => x <= y);
- break;
-
- case Instruction.CompareLessOrEqualU32:
- EvaluateBinary(operation, (x, y) => (uint)x <= (uint)y);
- break;
-
- case Instruction.CompareLessU32:
- EvaluateBinary(operation, (x, y) => (uint)x < (uint)y);
- break;
-
- case Instruction.CompareNotEqual:
- EvaluateBinary(operation, (x, y) => x != y);
- break;
-
- case Instruction.Divide:
- EvaluateBinary(operation, (x, y) => y != 0 ? x / y : 0);
- break;
-
- case Instruction.FP | Instruction.Add:
- EvaluateFPBinary(operation, (x, y) => x + y);
- break;
-
- case Instruction.FP | Instruction.Clamp:
- EvaluateFPTernary(operation, (x, y, z) => Math.Clamp(x, y, z));
- break;
-
- case Instruction.FP | Instruction.CompareEqual:
- EvaluateFPBinary(operation, (x, y) => x == y);
- break;
-
- case Instruction.FP | Instruction.CompareGreater:
- EvaluateFPBinary(operation, (x, y) => x > y);
- break;
-
- case Instruction.FP | Instruction.CompareGreaterOrEqual:
- EvaluateFPBinary(operation, (x, y) => x >= y);
- break;
-
- case Instruction.FP | Instruction.CompareLess:
- EvaluateFPBinary(operation, (x, y) => x < y);
- break;
-
- case Instruction.FP | Instruction.CompareLessOrEqual:
- EvaluateFPBinary(operation, (x, y) => x <= y);
- break;
-
- case Instruction.FP | Instruction.CompareNotEqual:
- EvaluateFPBinary(operation, (x, y) => x != y);
- break;
-
- case Instruction.FP | Instruction.Divide:
- EvaluateFPBinary(operation, (x, y) => x / y);
- break;
-
- case Instruction.FP | Instruction.Multiply:
- EvaluateFPBinary(operation, (x, y) => x * y);
- break;
-
- case Instruction.FP | Instruction.Negate:
- EvaluateFPUnary(operation, (x) => -x);
- break;
-
- case Instruction.FP | Instruction.Subtract:
- EvaluateFPBinary(operation, (x, y) => x - y);
- break;
-
- case Instruction.IsNan:
- EvaluateFPUnary(operation, (x) => float.IsNaN(x));
- break;
-
- case Instruction.Maximum:
- EvaluateBinary(operation, (x, y) => Math.Max(x, y));
- break;
-
- case Instruction.MaximumU32:
- EvaluateBinary(operation, (x, y) => (int)Math.Max((uint)x, (uint)y));
- break;
-
- case Instruction.Minimum:
- EvaluateBinary(operation, (x, y) => Math.Min(x, y));
- break;
-
- case Instruction.MinimumU32:
- EvaluateBinary(operation, (x, y) => (int)Math.Min((uint)x, (uint)y));
- break;
-
- case Instruction.Multiply:
- EvaluateBinary(operation, (x, y) => x * y);
- break;
-
- case Instruction.Negate:
- EvaluateUnary(operation, (x) => -x);
- break;
-
- case Instruction.ShiftLeft:
- EvaluateBinary(operation, (x, y) => x << y);
- break;
-
- case Instruction.ShiftRightS32:
- EvaluateBinary(operation, (x, y) => x >> y);
- break;
-
- case Instruction.ShiftRightU32:
- EvaluateBinary(operation, (x, y) => (int)((uint)x >> y));
- break;
-
- case Instruction.Subtract:
- EvaluateBinary(operation, (x, y) => x - y);
- break;
-
- case Instruction.UnpackHalf2x16:
- UnpackHalf2x16(operation);
- break;
- }
- }
-
- private static bool AreAllSourcesConstant(Operation operation)
- {
- for (int index = 0; index < operation.SourcesCount; index++)
- {
- if (operation.GetSource(index).Type != OperandType.Constant)
- {
- return false;
- }
- }
-
- return true;
- }
-
- private static void BitfieldExtractS32(Operation operation)
- {
- int value = GetBitfieldExtractValue(operation);
-
- int shift = 32 - operation.GetSource(2).Value;
-
- value = (value << shift) >> shift;
-
- operation.TurnIntoCopy(Const(value));
- }
-
- private static void BitfieldExtractU32(Operation operation)
- {
- operation.TurnIntoCopy(Const(GetBitfieldExtractValue(operation)));
- }
-
- private static int GetBitfieldExtractValue(Operation operation)
- {
- int value = operation.GetSource(0).Value;
- int lsb = operation.GetSource(1).Value;
- int length = operation.GetSource(2).Value;
-
- return value.Extract(lsb, length);
- }
-
- private static void UnpackHalf2x16(Operation operation)
- {
- int value = operation.GetSource(0).Value;
-
- value = (value >> operation.ComponentIndex * 16) & 0xffff;
-
- operation.TurnIntoCopy(ConstF(HalfConversion.HalfToSingle(value)));
- }
-
- private static void FPNegate(Operation operation)
- {
- float value = operation.GetSource(0).AsFloat();
-
- operation.TurnIntoCopy(ConstF(-value));
- }
-
- private static void EvaluateUnary(Operation operation, Func<int, int> op)
- {
- int x = operation.GetSource(0).Value;
-
- operation.TurnIntoCopy(Const(op(x)));
- }
-
- private static void EvaluateFPUnary(Operation operation, Func<float, float> op)
- {
- float x = operation.GetSource(0).AsFloat();
-
- operation.TurnIntoCopy(ConstF(op(x)));
- }
-
- private static void EvaluateFPUnary(Operation operation, Func<float, bool> op)
- {
- float x = operation.GetSource(0).AsFloat();
-
- operation.TurnIntoCopy(Const(op(x) ? IrConsts.True : IrConsts.False));
- }
-
- private static void EvaluateBinary(Operation operation, Func<int, int, int> op)
- {
- int x = operation.GetSource(0).Value;
- int y = operation.GetSource(1).Value;
-
- operation.TurnIntoCopy(Const(op(x, y)));
- }
-
- private static void EvaluateBinary(Operation operation, Func<int, int, bool> op)
- {
- int x = operation.GetSource(0).Value;
- int y = operation.GetSource(1).Value;
-
- operation.TurnIntoCopy(Const(op(x, y) ? IrConsts.True : IrConsts.False));
- }
-
- private static void EvaluateFPBinary(Operation operation, Func<float, float, float> op)
- {
- float x = operation.GetSource(0).AsFloat();
- float y = operation.GetSource(1).AsFloat();
-
- operation.TurnIntoCopy(ConstF(op(x, y)));
- }
-
- private static void EvaluateFPBinary(Operation operation, Func<float, float, bool> op)
- {
- float x = operation.GetSource(0).AsFloat();
- float y = operation.GetSource(1).AsFloat();
-
- operation.TurnIntoCopy(Const(op(x, y) ? IrConsts.True : IrConsts.False));
- }
-
- private static void EvaluateTernary(Operation operation, Func<int, int, int, int> op)
- {
- int x = operation.GetSource(0).Value;
- int y = operation.GetSource(1).Value;
- int z = operation.GetSource(2).Value;
-
- operation.TurnIntoCopy(Const(op(x, y, z)));
- }
-
- private static void EvaluateFPTernary(Operation operation, Func<float, float, float, float> op)
- {
- float x = operation.GetSource(0).AsFloat();
- float y = operation.GetSource(1).AsFloat();
- float z = operation.GetSource(2).AsFloat();
-
- operation.TurnIntoCopy(ConstF(op(x, y, z)));
- }
- }
-} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Shader/Translation/Optimizations/HalfConversion.cs b/Ryujinx.Graphics/Shader/Translation/Optimizations/HalfConversion.cs
deleted file mode 100644
index 96060272..00000000
--- a/Ryujinx.Graphics/Shader/Translation/Optimizations/HalfConversion.cs
+++ /dev/null
@@ -1,47 +0,0 @@
-using System;
-
-namespace Ryujinx.Graphics.Shader.Translation.Optimizations
-{
- static class HalfConversion
- {
- public static float HalfToSingle(int value)
- {
- int mantissa = (value >> 0) & 0x3ff;
- int exponent = (value >> 10) & 0x1f;
- int sign = (value >> 15) & 0x1;
-
- if (exponent == 0x1f)
- {
- // NaN or Infinity.
- mantissa <<= 13;
- exponent = 0xff;
- }
- else if (exponent != 0 || mantissa != 0 )
- {
- if (exponent == 0)
- {
- // Denormal.
- int e = -1;
- int m = mantissa;
-
- do
- {
- e++;
- m <<= 1;
- }
- while ((m & 0x400) == 0);
-
- mantissa = m & 0x3ff;
- exponent = e;
- }
-
- mantissa <<= 13;
- exponent = 127 - 15 + exponent;
- }
-
- int output = (sign << 31) | (exponent << 23) | mantissa;
-
- return BitConverter.Int32BitsToSingle(output);
- }
- }
-} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Shader/Translation/Optimizations/Optimizer.cs b/Ryujinx.Graphics/Shader/Translation/Optimizations/Optimizer.cs
deleted file mode 100644
index 8cce0e74..00000000
--- a/Ryujinx.Graphics/Shader/Translation/Optimizations/Optimizer.cs
+++ /dev/null
@@ -1,172 +0,0 @@
-using Ryujinx.Graphics.Shader.IntermediateRepresentation;
-using System.Collections.Generic;
-using System.Linq;
-
-namespace Ryujinx.Graphics.Shader.Translation.Optimizations
-{
- static class Optimizer
- {
- public static void Optimize(BasicBlock[] blocks)
- {
- bool modified;
-
- do
- {
- modified = false;
-
- 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;
-
- bool isUnused = IsUnused(node.Value);
-
- if (!(node.Value is Operation operation) || isUnused)
- {
- if (isUnused)
- {
- RemoveNode(block, node);
-
- modified = true;
- }
-
- node = nextNode;
-
- continue;
- }
-
- ConstantFolding.Fold(operation);
-
- Simplification.Simplify(operation);
-
- if (DestIsLocalVar(operation))
- {
- if (operation.Inst == Instruction.Copy)
- {
- PropagateCopy(operation);
-
- RemoveNode(block, node);
-
- modified = true;
- }
- else if (operation.Inst == Instruction.PackHalf2x16 && PropagatePack(operation))
- {
- if (operation.Dest.UseOps.Count == 0)
- {
- RemoveNode(block, node);
- }
-
- modified = true;
- }
- }
-
- node = nextNode;
- }
-
- if (BranchElimination.Eliminate(block))
- {
- RemoveNode(block, block.Operations.Last);
-
- modified = true;
- }
- }
- }
- while (modified);
- }
-
- private static void PropagateCopy(Operation copyOp)
- {
- // Propagate copy source operand to all uses of
- // the destination operand.
- Operand dest = copyOp.Dest;
- Operand src = copyOp.GetSource(0);
-
- INode[] uses = dest.UseOps.ToArray();
-
- foreach (INode useNode in uses)
- {
- for (int index = 0; index < useNode.SourcesCount; index++)
- {
- if (useNode.GetSource(index) == dest)
- {
- useNode.SetSource(index, src);
- }
- }
- }
- }
-
- private static bool PropagatePack(Operation packOp)
- {
- // Propagate pack source operands to uses by unpack
- // instruction. The source depends on the unpack instruction.
- bool modified = false;
-
- Operand dest = packOp.Dest;
- Operand src0 = packOp.GetSource(0);
- Operand src1 = packOp.GetSource(1);
-
- INode[] uses = dest.UseOps.ToArray();
-
- foreach (INode useNode in uses)
- {
- if (!(useNode is Operation operation) || operation.Inst != Instruction.UnpackHalf2x16)
- {
- continue;
- }
-
- if (operation.GetSource(0) == dest)
- {
- operation.TurnIntoCopy(operation.ComponentIndex == 1 ? src1 : src0);
-
- modified = true;
- }
- }
-
- return modified;
- }
-
- private static void RemoveNode(BasicBlock block, LinkedListNode<INode> llNode)
- {
- // Remove a node from the nodes list, and also remove itself
- // from all the use lists on the operands that this node uses.
- block.Operations.Remove(llNode);
-
- Queue<INode> nodes = new Queue<INode>();
-
- nodes.Enqueue(llNode.Value);
-
- while (nodes.TryDequeue(out INode node))
- {
- for (int index = 0; index < node.SourcesCount; index++)
- {
- Operand src = node.GetSource(index);
-
- if (src.Type != OperandType.LocalVariable)
- {
- continue;
- }
-
- if (src.UseOps.Remove(node) && src.UseOps.Count == 0)
- {
- nodes.Enqueue(src.AsgOp);
- }
- }
- }
- }
-
- private static bool IsUnused(INode node)
- {
- return DestIsLocalVar(node) && node.Dest.UseOps.Count == 0;
- }
-
- private static bool DestIsLocalVar(INode node)
- {
- return node.Dest != null && node.Dest.Type == OperandType.LocalVariable;
- }
- }
-} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Shader/Translation/Optimizations/Simplification.cs b/Ryujinx.Graphics/Shader/Translation/Optimizations/Simplification.cs
deleted file mode 100644
index d6366dfe..00000000
--- a/Ryujinx.Graphics/Shader/Translation/Optimizations/Simplification.cs
+++ /dev/null
@@ -1,147 +0,0 @@
-using Ryujinx.Graphics.Shader.IntermediateRepresentation;
-
-using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
-
-namespace Ryujinx.Graphics.Shader.Translation.Optimizations
-{
- static class Simplification
- {
- private const int AllOnes = ~0;
-
- public static void Simplify(Operation operation)
- {
- switch (operation.Inst)
- {
- case Instruction.Add:
- case Instruction.BitwiseExclusiveOr:
- TryEliminateBinaryOpCommutative(operation, 0);
- break;
-
- case Instruction.BitwiseAnd:
- TryEliminateBitwiseAnd(operation);
- break;
-
- case Instruction.BitwiseOr:
- TryEliminateBitwiseOr(operation);
- break;
-
- case Instruction.ConditionalSelect:
- TryEliminateConditionalSelect(operation);
- break;
-
- case Instruction.Divide:
- TryEliminateBinaryOpY(operation, 1);
- break;
-
- case Instruction.Multiply:
- TryEliminateBinaryOpCommutative(operation, 1);
- break;
-
- case Instruction.ShiftLeft:
- case Instruction.ShiftRightS32:
- case Instruction.ShiftRightU32:
- case Instruction.Subtract:
- TryEliminateBinaryOpY(operation, 0);
- break;
- }
- }
-
- private static void TryEliminateBitwiseAnd(Operation operation)
- {
- // Try to recognize and optimize those 3 patterns (in order):
- // x & 0xFFFFFFFF == x, 0xFFFFFFFF & y == y,
- // x & 0x00000000 == 0x00000000, 0x00000000 & y == 0x00000000
- Operand x = operation.GetSource(0);
- Operand y = operation.GetSource(1);
-
- if (IsConstEqual(x, AllOnes))
- {
- operation.TurnIntoCopy(y);
- }
- else if (IsConstEqual(y, AllOnes))
- {
- operation.TurnIntoCopy(x);
- }
- else if (IsConstEqual(x, 0) || IsConstEqual(y, 0))
- {
- operation.TurnIntoCopy(Const(0));
- }
- }
-
- private static void TryEliminateBitwiseOr(Operation operation)
- {
- // Try to recognize and optimize those 3 patterns (in order):
- // x | 0x00000000 == x, 0x00000000 | y == y,
- // x | 0xFFFFFFFF == 0xFFFFFFFF, 0xFFFFFFFF | y == 0xFFFFFFFF
- Operand x = operation.GetSource(0);
- Operand y = operation.GetSource(1);
-
- if (IsConstEqual(x, 0))
- {
- operation.TurnIntoCopy(y);
- }
- else if (IsConstEqual(y, 0))
- {
- operation.TurnIntoCopy(x);
- }
- else if (IsConstEqual(x, AllOnes) || IsConstEqual(y, AllOnes))
- {
- operation.TurnIntoCopy(Const(AllOnes));
- }
- }
-
- private static void TryEliminateBinaryOpY(Operation operation, int comparand)
- {
- Operand x = operation.GetSource(0);
- Operand y = operation.GetSource(1);
-
- if (IsConstEqual(y, comparand))
- {
- operation.TurnIntoCopy(x);
- }
- }
-
- private static void TryEliminateBinaryOpCommutative(Operation operation, int comparand)
- {
- Operand x = operation.GetSource(0);
- Operand y = operation.GetSource(1);
-
- if (IsConstEqual(x, comparand))
- {
- operation.TurnIntoCopy(y);
- }
- else if (IsConstEqual(y, comparand))
- {
- operation.TurnIntoCopy(x);
- }
- }
-
- private static void TryEliminateConditionalSelect(Operation operation)
- {
- Operand cond = operation.GetSource(0);
-
- if (cond.Type != OperandType.Constant)
- {
- return;
- }
-
- // The condition is constant, we can turn it into a copy, and select
- // the source based on the condition value.
- int srcIndex = cond.Value != 0 ? 1 : 2;
-
- Operand source = operation.GetSource(srcIndex);
-
- operation.TurnIntoCopy(source);
- }
-
- private static bool IsConstEqual(Operand operand, int comparand)
- {
- if (operand.Type != OperandType.Constant)
- {
- return false;
- }
-
- return operand.Value == comparand;
- }
- }
-} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Shader/Translation/Ssa.cs b/Ryujinx.Graphics/Shader/Translation/Ssa.cs
deleted file mode 100644
index a4d763be..00000000
--- a/Ryujinx.Graphics/Shader/Translation/Ssa.cs
+++ /dev/null
@@ -1,330 +0,0 @@
-using Ryujinx.Graphics.Shader.Decoders;
-using Ryujinx.Graphics.Shader.IntermediateRepresentation;
-using System.Collections.Generic;
-
-using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
-
-namespace Ryujinx.Graphics.Shader.Translation
-{
- static class Ssa
- {
- private const int GprsAndPredsCount = RegisterConsts.GprsCount + RegisterConsts.PredsCount;
-
- private class DefMap
- {
- private Dictionary<Register, Operand> _map;
-
- private long[] _phiMasks;
-
- public DefMap()
- {
- _map = new Dictionary<Register, Operand>();
-
- _phiMasks = new long[(RegisterConsts.TotalCount + 63) / 64];
- }
-
- public bool TryAddOperand(Register reg, Operand operand)
- {
- return _map.TryAdd(reg, operand);
- }
-
- public bool TryGetOperand(Register reg, out Operand operand)
- {
- return _map.TryGetValue(reg, out operand);
- }
-
- public bool AddPhi(Register reg)
- {
- int key = GetKeyFromRegister(reg);
-
- int index = key / 64;
- int bit = key & 63;
-
- long mask = 1L << bit;
-
- if ((_phiMasks[index] & mask) != 0)
- {
- return false;
- }
-
- _phiMasks[index] |= mask;
-
- return true;
- }
-
- public bool HasPhi(Register reg)
- {
- int key = GetKeyFromRegister(reg);
-
- int index = key / 64;
- int bit = key & 63;
-
- return (_phiMasks[index] & (1L << bit)) != 0;
- }
- }
-
- private struct Definition
- {
- public BasicBlock Block { get; }
- public Operand Local { get; }
-
- public Definition(BasicBlock block, Operand local)
- {
- Block = block;
- Local = local;
- }
- }
-
- public static void Rename(BasicBlock[] blocks)
- {
- DefMap[] globalDefs = new DefMap[blocks.Length];
-
- for (int blkIndex = 0; blkIndex < blocks.Length; blkIndex++)
- {
- globalDefs[blkIndex] = new DefMap();
- }
-
- Queue<BasicBlock> dfPhiBlocks = new Queue<BasicBlock>();
-
- // First pass, get all defs and locals uses.
- for (int blkIndex = 0; blkIndex < blocks.Length; blkIndex++)
- {
- Operand[] localDefs = new Operand[RegisterConsts.TotalCount];
-
- Operand RenameLocal(Operand operand)
- {
- if (operand != null && operand.Type == OperandType.Register)
- {
- Operand local = localDefs[GetKeyFromRegister(operand.GetRegister())];
-
- operand = local ?? operand;
- }
-
- return operand;
- }
-
- BasicBlock block = blocks[blkIndex];
-
- LinkedListNode<INode> node = block.Operations.First;
-
- while (node != null)
- {
- if (node.Value is Operation operation)
- {
- for (int index = 0; index < operation.SourcesCount; index++)
- {
- operation.SetSource(index, RenameLocal(operation.GetSource(index)));
- }
-
- if (operation.Dest != null && operation.Dest.Type == OperandType.Register)
- {
- Operand local = Local();
-
- localDefs[GetKeyFromRegister(operation.Dest.GetRegister())] = local;
-
- operation.Dest = local;
- }
- }
-
- node = node.Next;
- }
-
- for (int index = 0; index < RegisterConsts.TotalCount; index++)
- {
- Operand local = localDefs[index];
-
- if (local == null)
- {
- continue;
- }
-
- Register reg = GetRegisterFromKey(index);
-
- globalDefs[block.Index].TryAddOperand(reg, local);
-
- dfPhiBlocks.Enqueue(block);
-
- while (dfPhiBlocks.TryDequeue(out BasicBlock dfPhiBlock))
- {
- foreach (BasicBlock domFrontier in dfPhiBlock.DominanceFrontiers)
- {
- if (globalDefs[domFrontier.Index].AddPhi(reg))
- {
- dfPhiBlocks.Enqueue(domFrontier);
- }
- }
- }
- }
- }
-
- // Second pass, rename variables with definitions on different blocks.
- for (int blkIndex = 0; blkIndex < blocks.Length; blkIndex++)
- {
- Operand[] localDefs = new Operand[RegisterConsts.TotalCount];
-
- BasicBlock block = blocks[blkIndex];
-
- Operand RenameGlobal(Operand operand)
- {
- if (operand != null && operand.Type == OperandType.Register)
- {
- int key = GetKeyFromRegister(operand.GetRegister());
-
- Operand local = localDefs[key];
-
- if (local != null)
- {
- return local;
- }
-
- operand = FindDefinitionForCurr(globalDefs, block, operand.GetRegister());
-
- localDefs[key] = operand;
- }
-
- return operand;
- }
-
- LinkedListNode<INode> node = block.Operations.First;
-
- while (node != null)
- {
- if (node.Value is Operation operation)
- {
- for (int index = 0; index < operation.SourcesCount; index++)
- {
- operation.SetSource(index, RenameGlobal(operation.GetSource(index)));
- }
- }
-
- node = node.Next;
- }
- }
- }
-
- private static Operand FindDefinitionForCurr(DefMap[] globalDefs, BasicBlock current, Register reg)
- {
- if (globalDefs[current.Index].HasPhi(reg))
- {
- return InsertPhi(globalDefs, current, reg);
- }
-
- if (current != current.ImmediateDominator)
- {
- return FindDefinition(globalDefs, current.ImmediateDominator, reg).Local;
- }
-
- return Undef();
- }
-
- private static Definition FindDefinition(DefMap[] globalDefs, BasicBlock current, Register reg)
- {
- foreach (BasicBlock block in SelfAndImmediateDominators(current))
- {
- DefMap defMap = globalDefs[block.Index];
-
- if (defMap.TryGetOperand(reg, out Operand lastDef))
- {
- return new Definition(block, lastDef);
- }
-
- if (defMap.HasPhi(reg))
- {
- return new Definition(block, InsertPhi(globalDefs, block, reg));
- }
- }
-
- return new Definition(current, Undef());
- }
-
- private static IEnumerable<BasicBlock> SelfAndImmediateDominators(BasicBlock block)
- {
- while (block != block.ImmediateDominator)
- {
- yield return block;
-
- block = block.ImmediateDominator;
- }
-
- yield return block;
- }
-
- private static Operand InsertPhi(DefMap[] globalDefs, BasicBlock block, Register reg)
- {
- // This block has a Phi that has not been materialized yet, but that
- // would define a new version of the variable we're looking for. We need
- // to materialize the Phi, add all the block/operand pairs into the Phi, and
- // then use the definition from that Phi.
- Operand local = Local();
-
- PhiNode phi = new PhiNode(local);
-
- AddPhi(block, phi);
-
- globalDefs[block.Index].TryAddOperand(reg, local);
-
- foreach (BasicBlock predecessor in block.Predecessors)
- {
- Definition def = FindDefinition(globalDefs, predecessor, reg);
-
- phi.AddSource(def.Block, def.Local);
- }
-
- return local;
- }
-
- private static void AddPhi(BasicBlock block, PhiNode phi)
- {
- LinkedListNode<INode> node = block.Operations.First;
-
- if (node != null)
- {
- while (node.Next?.Value is PhiNode)
- {
- node = node.Next;
- }
- }
-
- if (node?.Value is PhiNode)
- {
- block.Operations.AddAfter(node, phi);
- }
- else
- {
- block.Operations.AddFirst(phi);
- }
- }
-
- private static int GetKeyFromRegister(Register reg)
- {
- if (reg.Type == RegisterType.Gpr)
- {
- return reg.Index;
- }
- else if (reg.Type == RegisterType.Predicate)
- {
- return RegisterConsts.GprsCount + reg.Index;
- }
- else /* if (reg.Type == RegisterType.Flag) */
- {
- return GprsAndPredsCount + reg.Index;
- }
- }
-
- private static Register GetRegisterFromKey(int key)
- {
- if (key < RegisterConsts.GprsCount)
- {
- return new Register(key, RegisterType.Gpr);
- }
- else if (key < GprsAndPredsCount)
- {
- return new Register(key - RegisterConsts.GprsCount, RegisterType.Predicate);
- }
- else /* if (key < RegisterConsts.TotalCount) */
- {
- return new Register(key - GprsAndPredsCount, RegisterType.Flag);
- }
- }
- }
-} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Shader/Translation/Translator.cs b/Ryujinx.Graphics/Shader/Translation/Translator.cs
deleted file mode 100644
index fcebe913..00000000
--- a/Ryujinx.Graphics/Shader/Translation/Translator.cs
+++ /dev/null
@@ -1,219 +0,0 @@
-using Ryujinx.Graphics.Gal;
-using Ryujinx.Graphics.Shader.CodeGen.Glsl;
-using Ryujinx.Graphics.Shader.Decoders;
-using Ryujinx.Graphics.Shader.Instructions;
-using Ryujinx.Graphics.Shader.IntermediateRepresentation;
-using Ryujinx.Graphics.Shader.StructuredIr;
-using Ryujinx.Graphics.Shader.Translation.Optimizations;
-using System.Collections.Generic;
-
-using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
-
-namespace Ryujinx.Graphics.Shader.Translation
-{
- public static class Translator
- {
- public static ShaderProgram Translate(IGalMemory memory, ulong address, ShaderConfig config)
- {
- return Translate(memory, address, 0, config);
- }
-
- public static ShaderProgram Translate(
- IGalMemory memory,
- ulong address,
- ulong addressB,
- ShaderConfig config)
- {
- Operation[] shaderOps = DecodeShader(memory, address, config.Type);
-
- if (addressB != 0)
- {
- // Dual vertex shader.
- Operation[] shaderOpsB = DecodeShader(memory, addressB, config.Type);
-
- shaderOps = Combine(shaderOps, shaderOpsB);
- }
-
- BasicBlock[] irBlocks = ControlFlowGraph.MakeCfg(shaderOps);
-
- Dominance.FindDominators(irBlocks[0], irBlocks.Length);
-
- Dominance.FindDominanceFrontiers(irBlocks);
-
- Ssa.Rename(irBlocks);
-
- Optimizer.Optimize(irBlocks);
-
- StructuredProgramInfo sInfo = StructuredProgram.MakeStructuredProgram(irBlocks);
-
- GlslProgram program = GlslGenerator.Generate(sInfo, config);
-
- ShaderProgramInfo spInfo = new ShaderProgramInfo(
- program.CBufferDescriptors,
- program.TextureDescriptors);
-
- return new ShaderProgram(spInfo, program.Code);
- }
-
- private static Operation[] DecodeShader(IGalMemory memory, ulong address, GalShaderType shaderType)
- {
- ShaderHeader header = new ShaderHeader(memory, address);
-
- Block[] cfg = Decoder.Decode(memory, address);
-
- EmitterContext context = new EmitterContext(shaderType, header);
-
- for (int blkIndex = 0; blkIndex < cfg.Length; blkIndex++)
- {
- Block block = cfg[blkIndex];
-
- context.CurrBlock = block;
-
- context.MarkLabel(context.GetLabel(block.Address));
-
- for (int opIndex = 0; opIndex < block.OpCodes.Count; opIndex++)
- {
- OpCode op = block.OpCodes[opIndex];
-
- if (op.NeverExecute)
- {
- continue;
- }
-
- Operand predSkipLbl = null;
-
- bool skipPredicateCheck = op.Emitter == InstEmit.Bra;
-
- if (op is OpCodeSync opSync)
- {
- // If the instruction is a SYNC instruction with only one
- // possible target address, then the instruction is basically
- // just a simple branch, we can generate code similar to branch
- // instructions, with the condition check on the branch itself.
- skipPredicateCheck |= opSync.Targets.Count < 2;
- }
-
- if (!(op.Predicate.IsPT || skipPredicateCheck))
- {
- Operand label;
-
- if (opIndex == block.OpCodes.Count - 1 && block.Next != null)
- {
- label = context.GetLabel(block.Next.Address);
- }
- else
- {
- label = Label();
-
- predSkipLbl = label;
- }
-
- Operand pred = Register(op.Predicate);
-
- if (op.InvertPredicate)
- {
- context.BranchIfTrue(label, pred);
- }
- else
- {
- context.BranchIfFalse(label, pred);
- }
- }
-
- context.CurrOp = op;
-
- op.Emitter(context);
-
- if (predSkipLbl != null)
- {
- context.MarkLabel(predSkipLbl);
- }
- }
- }
-
- return context.GetOperations();
- }
-
- private static Operation[] Combine(Operation[] a, Operation[] b)
- {
- // Here we combine two shaders.
- // For shader A:
- // - All user attribute stores on shader A are turned into copies to a
- // temporary variable. It's assumed that shader B will consume them.
- // - All return instructions are turned into branch instructions, the
- // branch target being the start of the shader B code.
- // For shader B:
- // - All user attribute loads on shader B are turned into copies from a
- // temporary variable, as long that attribute is written by shader A.
- List<Operation> output = new List<Operation>(a.Length + b.Length);
-
- Operand[] temps = new Operand[AttributeConsts.UserAttributesCount * 4];
-
- Operand lblB = Label();
-
- for (int index = 0; index < a.Length; index++)
- {
- Operation operation = a[index];
-
- if (IsUserAttribute(operation.Dest))
- {
- int tIndex = (operation.Dest.Value - AttributeConsts.UserAttributeBase) / 4;
-
- Operand temp = temps[tIndex];
-
- if (temp == null)
- {
- temp = Local();
-
- temps[tIndex] = temp;
- }
-
- operation.Dest = temp;
- }
-
- if (operation.Inst == Instruction.Return)
- {
- output.Add(new Operation(Instruction.Branch, lblB));
- }
- else
- {
- output.Add(operation);
- }
- }
-
- output.Add(new Operation(Instruction.MarkLabel, lblB));
-
- for (int index = 0; index < b.Length; index++)
- {
- Operation operation = b[index];
-
- for (int srcIndex = 0; srcIndex < operation.SourcesCount; srcIndex++)
- {
- Operand src = operation.GetSource(srcIndex);
-
- if (IsUserAttribute(src))
- {
- Operand temp = temps[(src.Value - AttributeConsts.UserAttributeBase) / 4];
-
- if (temp != null)
- {
- operation.SetSource(srcIndex, temp);
- }
- }
- }
-
- output.Add(operation);
- }
-
- return output.ToArray();
- }
-
- private static bool IsUserAttribute(Operand operand)
- {
- return operand != null &&
- operand.Type == OperandType.Attribute &&
- operand.Value >= AttributeConsts.UserAttributeBase &&
- operand.Value < AttributeConsts.UserAttributeEnd;
- }
- }
-} \ No newline at end of file