diff options
author | gdkchan <gab.dark.100@gmail.com> | 2021-10-12 17:35:31 -0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-12 22:35:31 +0200 |
commit | a7109c767bdc014327b574012794156c92174495 (patch) | |
tree | d7d7db6eaa63d4e3e0396a3182d0267b6ad31dd7 /Ryujinx.Graphics.Shader/Decoders/Block.cs | |
parent | 0510fde25ae66ec0b55091746a52931248d75b89 (diff) |
Rewrite shader decoding stage (#2698)
* Rewrite shader decoding stage
* Fix P2R constant buffer encoding
* Fix PSET/PSETP
* PR feedback
* Log unimplemented shader instructions
* Implement NOP
* Remove using
* PR feedback
Diffstat (limited to 'Ryujinx.Graphics.Shader/Decoders/Block.cs')
-rw-r--r-- | Ryujinx.Graphics.Shader/Decoders/Block.cs | 135 |
1 files changed, 75 insertions, 60 deletions
diff --git a/Ryujinx.Graphics.Shader/Decoders/Block.cs b/Ryujinx.Graphics.Shader/Decoders/Block.cs index 69cb55b9..0b55c59e 100644 --- a/Ryujinx.Graphics.Shader/Decoders/Block.cs +++ b/Ryujinx.Graphics.Shader/Decoders/Block.cs @@ -1,57 +1,56 @@ +using Ryujinx.Graphics.Shader.IntermediateRepresentation; using System; using System.Collections.Generic; +using System.Linq; namespace Ryujinx.Graphics.Shader.Decoders { - class Block + class PushOpInfo { - public ulong Address { get; set; } - public ulong EndAddress { get; set; } - - private Block _next; - private Block _branch; + public InstOp Op { get; } + public Dictionary<Block, Operand> Consumers; - public Block Next + public PushOpInfo(InstOp op) { - get - { - return _next; - } - set - { - _next?.Predecessors.Remove(this); - value?.Predecessors.Add(this); - _next = value; - } + Op = op; + Consumers = new Dictionary<Block, Operand>(); } + } + + struct SyncTarget + { + public PushOpInfo PushOpInfo { get; } + public int PushOpId { get; } - public Block Branch + public SyncTarget(PushOpInfo pushOpInfo, int pushOpId) { - get - { - return _branch; - } - set - { - _branch?.Predecessors.Remove(this); - value?.Predecessors.Add(this); - _branch = value; - } + PushOpInfo = pushOpInfo; + PushOpId = pushOpId; } + } - public HashSet<Block> Predecessors { get; } + class Block + { + public ulong Address { get; set; } + public ulong EndAddress { get; set; } - public List<OpCode> OpCodes { get; } - public List<OpCodePush> PushOpCodes { get; } + public List<Block> Predecessors { get; } + public List<Block> Successors { get; } + + public List<InstOp> OpCodes { get; } + public List<PushOpInfo> PushOpCodes { get; } + public Dictionary<ulong, SyncTarget> SyncTargets { get; } public Block(ulong address) { Address = address; - Predecessors = new HashSet<Block>(); + Predecessors = new List<Block>(); + Successors = new List<Block>(); - OpCodes = new List<OpCode>(); - PushOpCodes = new List<OpCodePush>(); + OpCodes = new List<InstOp>(); + PushOpCodes = new List<PushOpInfo>(); + SyncTargets = new Dictionary<ulong, SyncTarget>(); } public void Split(Block rightBlock) @@ -64,36 +63,56 @@ namespace Ryujinx.Graphics.Shader.Decoders } int splitCount = OpCodes.Count - splitIndex; - if (splitCount <= 0) { throw new ArgumentException("Can't split at right block address."); } rightBlock.EndAddress = EndAddress; + rightBlock.Successors.AddRange(Successors); + rightBlock.Predecessors.Add(this); - rightBlock.Next = Next; - rightBlock.Branch = Branch; + EndAddress = rightBlock.Address; + + Successors.Clear(); + Successors.Add(rightBlock); + // Move ops. rightBlock.OpCodes.AddRange(OpCodes.GetRange(splitIndex, splitCount)); - rightBlock.UpdatePushOps(); + OpCodes.RemoveRange(splitIndex, splitCount); - EndAddress = rightBlock.Address; + // Update push consumers that points to this block. + foreach (SyncTarget syncTarget in SyncTargets.Values) + { + PushOpInfo pushOpInfo = syncTarget.PushOpInfo; - Next = rightBlock; - Branch = null; + Operand local = pushOpInfo.Consumers[this]; + pushOpInfo.Consumers.Remove(this); + pushOpInfo.Consumers.Add(rightBlock, local); + } - OpCodes.RemoveRange(splitIndex, splitCount); + rightBlock.SyncTargets.Union(SyncTargets); + SyncTargets.Clear(); - UpdatePushOps(); + // Move push ops. + for (int i = 0; i < PushOpCodes.Count; i++) + { + if (PushOpCodes[i].Op.Address >= rightBlock.Address) + { + int count = PushOpCodes.Count - i; + rightBlock.PushOpCodes.AddRange(PushOpCodes.Skip(i)); + PushOpCodes.RemoveRange(i, count); + break; + } + } } - private static int BinarySearch(List<OpCode> opCodes, ulong address) + private static int BinarySearch(List<InstOp> opCodes, ulong address) { - int left = 0; + int left = 0; int middle = 0; - int right = opCodes.Count - 1; + int right = opCodes.Count - 1; while (left <= right) { @@ -101,7 +120,7 @@ namespace Ryujinx.Graphics.Shader.Decoders middle = left + (size >> 1); - OpCode opCode = opCodes[middle]; + InstOp opCode = opCodes[middle]; if (address == opCode.Address) { @@ -121,29 +140,25 @@ namespace Ryujinx.Graphics.Shader.Decoders return middle; } - public OpCode GetLastOp() + public InstOp GetLastOp() { if (OpCodes.Count != 0) { return OpCodes[OpCodes.Count - 1]; } - return null; + return default; } - public void UpdatePushOps() + public bool HasNext() { - PushOpCodes.Clear(); - - for (int index = 0; index < OpCodes.Count; index++) - { - if (!(OpCodes[index] is OpCodePush op)) - { - continue; - } + InstOp lastOp = GetLastOp(); + return OpCodes.Count != 0 && !Decoder.IsUnconditionalBranch(ref lastOp); + } - PushOpCodes.Add(op); - } + public void AddPushOp(InstOp op) + { + PushOpCodes.Add(new PushOpInfo(op)); } } }
\ No newline at end of file |