aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Graphics.Shader/Translation/EmitterContext.cs')
-rw-r--r--Ryujinx.Graphics.Shader/Translation/EmitterContext.cs63
1 files changed, 57 insertions, 6 deletions
diff --git a/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs b/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs
index 3e50ce2f..ef5d7b96 100644
--- a/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs
+++ b/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs
@@ -21,8 +21,33 @@ namespace Ryujinx.Graphics.Shader.Translation
public int OperationsCount => _operations.Count;
+ private struct BrxTarget
+ {
+ public readonly Operand Selector;
+ public readonly int ExpectedValue;
+ public readonly ulong NextTargetAddress;
+
+ public BrxTarget(Operand selector, int expectedValue, ulong nextTargetAddress)
+ {
+ Selector = selector;
+ ExpectedValue = expectedValue;
+ NextTargetAddress = nextTargetAddress;
+ }
+ }
+
+ private class BlockLabel
+ {
+ public readonly Operand Label;
+ public BrxTarget BrxTarget;
+
+ public BlockLabel(Operand label)
+ {
+ Label = label;
+ }
+ }
+
private readonly List<Operation> _operations;
- private readonly Dictionary<ulong, Operand> _labels;
+ private readonly Dictionary<ulong, BlockLabel> _labels;
public EmitterContext(DecodedProgram program, ShaderConfig config, bool isNonMain)
{
@@ -30,7 +55,7 @@ namespace Ryujinx.Graphics.Shader.Translation
Config = config;
IsNonMain = isNonMain;
_operations = new List<Operation>();
- _labels = new Dictionary<ulong, Operand>();
+ _labels = new Dictionary<ulong, BlockLabel>();
EmitStart();
}
@@ -158,14 +183,40 @@ namespace Ryujinx.Graphics.Shader.Translation
public Operand GetLabel(ulong address)
{
- if (!_labels.TryGetValue(address, out Operand label))
+ return EnsureBlockLabel(address).Label;
+ }
+
+ public void SetBrxTarget(ulong address, Operand selector, int targetValue, ulong nextTargetAddress)
+ {
+ BlockLabel blockLabel = EnsureBlockLabel(address);
+ Debug.Assert(blockLabel.BrxTarget.Selector == null);
+ blockLabel.BrxTarget = new BrxTarget(selector, targetValue, nextTargetAddress);
+ }
+
+ public void EnterBlock(ulong address)
+ {
+ BlockLabel blockLabel = EnsureBlockLabel(address);
+
+ MarkLabel(blockLabel.Label);
+
+ BrxTarget brxTarget = blockLabel.BrxTarget;
+
+ if (brxTarget.Selector != null)
+ {
+ this.BranchIfFalse(GetLabel(brxTarget.NextTargetAddress), this.ICompareEqual(brxTarget.Selector, Const(brxTarget.ExpectedValue)));
+ }
+ }
+
+ private BlockLabel EnsureBlockLabel(ulong address)
+ {
+ if (!_labels.TryGetValue(address, out BlockLabel blockLabel))
{
- label = Label();
+ blockLabel = new BlockLabel(Label());
- _labels.Add(address, label);
+ _labels.Add(address, blockLabel);
}
- return label;
+ return blockLabel;
}
public void PrepareForVertexReturn()