diff options
Diffstat (limited to 'Ryujinx.Graphics/Gal/Shader/ShaderDecoder.cs')
-rw-r--r-- | Ryujinx.Graphics/Gal/Shader/ShaderDecoder.cs | 218 |
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 |