aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics/Gal/Shader/ShaderDecoder.cs
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2019-04-17 20:57:08 -0300
committerjduncanator <1518948+jduncanator@users.noreply.github.com>2019-04-18 09:57:08 +1000
commit6b23a2c125b9c48b5ebea92716004ef68698bb0f (patch)
tree69332df6fbbd8e2bddc522ba682fcc5c7a69e101 /Ryujinx.Graphics/Gal/Shader/ShaderDecoder.cs
parentb2e88b04a85b41cc60af3485d88c90429e84a218 (diff)
New shader translator implementation (#654)
* Start implementing a new shader translator * Fix shift instructions and a typo * Small refactoring on StructuredProgram, move RemovePhis method to a separate class * Initial geometry shader support * Implement TLD4 * Fix -- There's no negation on FMUL32I * Add constant folding and algebraic simplification optimizations, nits * Some leftovers from constant folding * Avoid cast for constant assignments * Add a branch elimination pass, and misc small fixes * Remove redundant branches, add expression propagation and other improvements on the code * Small leftovers -- add missing break and continue, remove unused properties, other improvements * Add null check to handle empty block cases on block visitor * Add HADD2 and HMUL2 half float shader instructions * Optimize pack/unpack sequences, some fixes related to half float instructions * Add TXQ, TLD, TLDS and TLD4S shader texture instructions, and some support for bindless textures, some refactoring on codegen * Fix copy paste mistake that caused RZ to be ignored on the AST instruction * Add workaround for conditional exit, and fix half float instruction with constant buffer * Add missing 0.0 source for TLDS.LZ variants * Simplify the switch for TLDS.LZ * Texture instructions related fixes * Implement the HFMA instruction, and some misc. fixes * Enable constant folding on UnpackHalf2x16 instructions * Refactor HFMA to use OpCode* for opcode decoding rather than on the helper methods * Remove the old shader translator * Remove ShaderDeclInfo and other unused things * Add dual vertex shader support * Add ShaderConfig, used to pass shader type and maximum cbuffer size * Move and rename some instruction enums * Move texture instructions into a separate file * Move operand GetExpression and locals management to OperandManager * Optimize opcode decoding using a simple list and binary search * Add missing condition for do-while on goto elimination * Misc. fixes on texture instructions * Simplify TLDS switch * Address PR feedback, and a nit
Diffstat (limited to 'Ryujinx.Graphics/Gal/Shader/ShaderDecoder.cs')
-rw-r--r--Ryujinx.Graphics/Gal/Shader/ShaderDecoder.cs218
1 files changed, 0 insertions, 218 deletions
diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecoder.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecoder.cs
deleted file mode 100644
index 4b23f8d0..00000000
--- a/Ryujinx.Graphics/Gal/Shader/ShaderDecoder.cs
+++ /dev/null
@@ -1,218 +0,0 @@
-using System.Collections.Generic;
-
-namespace Ryujinx.Graphics.Gal.Shader
-{
- static class ShaderDecoder
- {
- private const long HeaderSize = 0x50;
-
- private const bool AddDbgComments = true;
-
- public static ShaderIrBlock[] Decode(IGalMemory memory, long start)
- {
- Dictionary<int, ShaderIrBlock> visited = new Dictionary<int, ShaderIrBlock>();
- Dictionary<int, ShaderIrBlock> visitedEnd = new Dictionary<int, ShaderIrBlock>();
-
- Queue<ShaderIrBlock> blocks = new Queue<ShaderIrBlock>();
-
- long beginning = start + HeaderSize;
-
- ShaderIrBlock Enqueue(int position, ShaderIrBlock source = null)
- {
- if (!visited.TryGetValue(position, out ShaderIrBlock output))
- {
- output = new ShaderIrBlock(position);
-
- blocks.Enqueue(output);
-
- visited.Add(position, output);
- }
-
- if (source != null)
- {
- output.Sources.Add(source);
- }
-
- return output;
- }
-
- ShaderIrBlock entry = Enqueue(0);
-
- while (blocks.Count > 0)
- {
- ShaderIrBlock current = blocks.Dequeue();
-
- FillBlock(memory, current, beginning);
-
- //Set child blocks. "Branch" is the block the branch instruction
- //points to (when taken), "Next" is the block at the next address,
- //executed when the branch is not taken. For Unconditional Branches
- //or end of shader, Next is null.
- if (current.Nodes.Count > 0)
- {
- ShaderIrNode lastNode = current.GetLastNode();
-
- ShaderIrOp innerOp = GetInnermostOp(lastNode);
-
- if (innerOp?.Inst == ShaderIrInst.Bra)
- {
- int target = ((ShaderIrOperImm)innerOp.OperandA).Value;
-
- current.Branch = Enqueue(target, current);
- }
-
- foreach (ShaderIrNode node in current.Nodes)
- {
- innerOp = GetInnermostOp(node);
-
- if (innerOp is ShaderIrOp currOp && currOp.Inst == ShaderIrInst.Ssy)
- {
- int target = ((ShaderIrOperImm)currOp.OperandA).Value;
-
- Enqueue(target, current);
- }
- }
-
- if (NodeHasNext(lastNode))
- {
- current.Next = Enqueue(current.EndPosition);
- }
- }
-
- //If we have on the graph two blocks with the same end position,
- //then we need to split the bigger block and have two small blocks,
- //the end position of the bigger "Current" block should then be == to
- //the position of the "Smaller" block.
- while (visitedEnd.TryGetValue(current.EndPosition, out ShaderIrBlock smaller))
- {
- if (current.Position > smaller.Position)
- {
- ShaderIrBlock temp = smaller;
-
- smaller = current;
- current = temp;
- }
-
- current.EndPosition = smaller.Position;
- current.Next = smaller;
- current.Branch = null;
-
- current.Nodes.RemoveRange(
- current.Nodes.Count - smaller.Nodes.Count,
- smaller.Nodes.Count);
-
- visitedEnd[smaller.EndPosition] = smaller;
- }
-
- visitedEnd.Add(current.EndPosition, current);
- }
-
- //Make and sort Graph blocks array by position.
- ShaderIrBlock[] graph = new ShaderIrBlock[visited.Count];
-
- while (visited.Count > 0)
- {
- uint firstPos = uint.MaxValue;
-
- foreach (ShaderIrBlock block in visited.Values)
- {
- if (firstPos > (uint)block.Position)
- firstPos = (uint)block.Position;
- }
-
- ShaderIrBlock current = visited[(int)firstPos];
-
- do
- {
- graph[graph.Length - visited.Count] = current;
-
- visited.Remove(current.Position);
-
- current = current.Next;
- }
- while (current != null);
- }
-
- return graph;
- }
-
- private static void FillBlock(IGalMemory memory, ShaderIrBlock block, long beginning)
- {
- int position = block.Position;
-
- do
- {
- //Ignore scheduling instructions, which are written every 32 bytes.
- if ((position & 0x1f) == 0)
- {
- position += 8;
-
- continue;
- }
-
- uint word0 = (uint)memory.ReadInt32(position + beginning + 0);
- uint word1 = (uint)memory.ReadInt32(position + beginning + 4);
-
- position += 8;
-
- long opCode = word0 | (long)word1 << 32;
-
- ShaderDecodeFunc decode = ShaderOpCodeTable.GetDecoder(opCode);
-
- if (AddDbgComments)
- {
- string dbgOpCode = $"0x{(position - 8):x16}: 0x{opCode:x16} ";
-
- dbgOpCode += (decode?.Method.Name ?? "???");
-
- if (decode == ShaderDecode.Bra || decode == ShaderDecode.Ssy)
- {
- int offset = ((int)(opCode >> 20) << 8) >> 8;
-
- long target = position + offset;
-
- dbgOpCode += " (0x" + target.ToString("x16") + ")";
- }
-
- block.AddNode(new ShaderIrCmnt(dbgOpCode));
- }
-
- if (decode == null)
- {
- continue;
- }
-
- decode(block, opCode, position);
- }
- while (!IsFlowChange(block.GetLastNode()));
-
- block.EndPosition = position;
- }
-
- private static bool IsFlowChange(ShaderIrNode node)
- {
- return !NodeHasNext(GetInnermostOp(node));
- }
-
- private static ShaderIrOp GetInnermostOp(ShaderIrNode node)
- {
- if (node is ShaderIrCond cond)
- {
- node = cond.Child;
- }
-
- return node is ShaderIrOp op ? op : null;
- }
-
- private static bool NodeHasNext(ShaderIrNode node)
- {
- if (!(node is ShaderIrOp op))
- {
- return true;
- }
-
- return op.Inst != ShaderIrInst.Exit &&
- op.Inst != ShaderIrInst.Bra;
- }
- }
-} \ No newline at end of file