aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Shader/Decoders/Block.cs
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2021-10-12 17:35:31 -0300
committerGitHub <noreply@github.com>2021-10-12 22:35:31 +0200
commita7109c767bdc014327b574012794156c92174495 (patch)
treed7d7db6eaa63d4e3e0396a3182d0267b6ad31dd7 /Ryujinx.Graphics.Shader/Decoders/Block.cs
parent0510fde25ae66ec0b55091746a52931248d75b89 (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.cs135
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