aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Shader/Translation
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/Translation
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/Translation')
-rw-r--r--Ryujinx.Graphics.Shader/Translation/ControlFlowGraph.cs25
-rw-r--r--Ryujinx.Graphics.Shader/Translation/Dominance.cs1
-rw-r--r--Ryujinx.Graphics.Shader/Translation/EmitterContext.cs11
-rw-r--r--Ryujinx.Graphics.Shader/Translation/ShaderHeader.cs21
-rw-r--r--Ryujinx.Graphics.Shader/Translation/Translator.cs38
5 files changed, 70 insertions, 26 deletions
diff --git a/Ryujinx.Graphics.Shader/Translation/ControlFlowGraph.cs b/Ryujinx.Graphics.Shader/Translation/ControlFlowGraph.cs
index fb0535c8..65328fd7 100644
--- a/Ryujinx.Graphics.Shader/Translation/ControlFlowGraph.cs
+++ b/Ryujinx.Graphics.Shader/Translation/ControlFlowGraph.cs
@@ -129,6 +129,31 @@ namespace Ryujinx.Graphics.Shader.Translation
}
}
+ // Remove unreachable blocks.
+ bool hasUnreachable;
+
+ do
+ {
+ hasUnreachable = false;
+
+ for (int blkIndex = 1; blkIndex < blocks.Count; blkIndex++)
+ {
+ BasicBlock block = blocks[blkIndex];
+
+ if (block.Predecessors.Count == 0)
+ {
+ block.Next = null;
+ block.Branch = null;
+ blocks.RemoveAt(blkIndex--);
+ hasUnreachable = true;
+ }
+ else
+ {
+ block.Index = blkIndex;
+ }
+ }
+ } while (hasUnreachable);
+
return new ControlFlowGraph(blocks.ToArray());
}
diff --git a/Ryujinx.Graphics.Shader/Translation/Dominance.cs b/Ryujinx.Graphics.Shader/Translation/Dominance.cs
index da4a38da..09c2eb0f 100644
--- a/Ryujinx.Graphics.Shader/Translation/Dominance.cs
+++ b/Ryujinx.Graphics.Shader/Translation/Dominance.cs
@@ -1,5 +1,4 @@
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
-using System.Collections.Generic;
namespace Ryujinx.Graphics.Shader.Translation
{
diff --git a/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs b/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs
index c96b75a5..bdfd9626 100644
--- a/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs
+++ b/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs
@@ -1,6 +1,8 @@
using Ryujinx.Graphics.Shader.Decoders;
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using System.Collections.Generic;
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
@@ -9,7 +11,7 @@ namespace Ryujinx.Graphics.Shader.Translation
class EmitterContext
{
public Block CurrBlock { get; set; }
- public OpCode CurrOp { get; set; }
+ public InstOp CurrOp { get; set; }
public ShaderConfig Config { get; }
@@ -30,6 +32,13 @@ namespace Ryujinx.Graphics.Shader.Translation
_labels = new Dictionary<ulong, Operand>();
}
+ public T GetOp<T>() where T : unmanaged
+ {
+ Debug.Assert(Unsafe.SizeOf<T>() == sizeof(ulong));
+ ulong op = CurrOp.RawOpCode;
+ return Unsafe.As<ulong, T>(ref op);
+ }
+
public Operand Add(Instruction inst, Operand dest = null, params Operand[] sources)
{
Operation operation = new Operation(inst, dest, sources);
diff --git a/Ryujinx.Graphics.Shader/Translation/ShaderHeader.cs b/Ryujinx.Graphics.Shader/Translation/ShaderHeader.cs
index ff5932e1..0ad172da 100644
--- a/Ryujinx.Graphics.Shader/Translation/ShaderHeader.cs
+++ b/Ryujinx.Graphics.Shader/Translation/ShaderHeader.cs
@@ -1,5 +1,6 @@
using Ryujinx.Graphics.Shader.Decoders;
using System;
+using System.Runtime.InteropServices;
namespace Ryujinx.Graphics.Shader.Translation
{
@@ -113,11 +114,13 @@ namespace Ryujinx.Graphics.Shader.Translation
public ShaderHeader(IGpuAccessor gpuAccessor, ulong address)
{
- int commonWord0 = gpuAccessor.MemoryRead<int>(address + 0);
- int commonWord1 = gpuAccessor.MemoryRead<int>(address + 4);
- int commonWord2 = gpuAccessor.MemoryRead<int>(address + 8);
- int commonWord3 = gpuAccessor.MemoryRead<int>(address + 12);
- int commonWord4 = gpuAccessor.MemoryRead<int>(address + 16);
+ ReadOnlySpan<int> header = MemoryMarshal.Cast<ulong, int>(gpuAccessor.GetCode(address, 0x50));
+
+ int commonWord0 = header[0];
+ int commonWord1 = header[1];
+ int commonWord2 = header[2];
+ int commonWord3 = header[3];
+ int commonWord4 = header[4];
SphType = commonWord0.Extract(0, 5);
Version = commonWord0.Extract(5, 5);
@@ -164,9 +167,9 @@ namespace Ryujinx.Graphics.Shader.Translation
ImapTypes = new ImapPixelType[32];
- for (ulong i = 0; i < 32; i++)
+ for (int i = 0; i < 32; i++)
{
- byte imap = gpuAccessor.MemoryRead<byte>(address + 0x18 + i);
+ byte imap = (byte)(header[6 + (i >> 2)] >> ((i & 3) * 8));
ImapTypes[i] = new ImapPixelType(
(PixelImap)((imap >> 0) & 3),
@@ -175,8 +178,8 @@ namespace Ryujinx.Graphics.Shader.Translation
(PixelImap)((imap >> 6) & 3));
}
- int type2OmapTarget = gpuAccessor.MemoryRead<int>(address + 0x48);
- int type2Omap = gpuAccessor.MemoryRead<int>(address + 0x4c);
+ int type2OmapTarget = header[18];
+ int type2Omap = header[19];
OmapTargets = new OmapTarget[8];
diff --git a/Ryujinx.Graphics.Shader/Translation/Translator.cs b/Ryujinx.Graphics.Shader/Translation/Translator.cs
index 1abf19d7..0a0ee4a7 100644
--- a/Ryujinx.Graphics.Shader/Translation/Translator.cs
+++ b/Ryujinx.Graphics.Shader/Translation/Translator.cs
@@ -150,9 +150,12 @@ namespace Ryujinx.Graphics.Shader.Translation
{
for (int index = 0; index < block.OpCodes.Count; index++)
{
- if (block.OpCodes[index] is OpCodeTextureBase texture)
+ InstOp op = block.OpCodes[index];
+
+ if (op.Props.HasFlag(InstProps.Tex))
{
- config.TextureHandlesForCache.Add(texture.HandleOffset);
+ int tidB = (int)((op.RawOpCode >> 36) & 0x1fff);
+ config.TextureHandlesForCache.Add(tidB);
}
}
}
@@ -241,15 +244,15 @@ namespace Ryujinx.Graphics.Shader.Translation
{
for (int opIndex = 0; opIndex < block.OpCodes.Count; opIndex++)
{
- OpCode op = block.OpCodes[opIndex];
+ InstOp op = block.OpCodes[opIndex];
- if ((context.Config.Options.Flags & TranslationFlags.DebugMode) != 0)
+ if (context.Config.Options.Flags.HasFlag(TranslationFlags.DebugMode))
{
string instName;
if (op.Emitter != null)
{
- instName = op.Emitter.Method.Name;
+ instName = op.Name.ToString();
}
else
{
@@ -263,31 +266,36 @@ namespace Ryujinx.Graphics.Shader.Translation
context.Add(new CommentNode(dbgComment));
}
- if (op.NeverExecute)
+ InstConditional opConditional = new InstConditional(op.RawOpCode);
+
+ bool noPred = op.Props.HasFlag(InstProps.NoPred);
+ if (!noPred && opConditional.Pred == RegisterConsts.PredicateTrueIndex && opConditional.PredInv)
{
continue;
}
Operand predSkipLbl = null;
- bool skipPredicateCheck = op is OpCodeBranch opBranch && !opBranch.PushTarget;
-
- if (op is OpCodeBranchPop opBranchPop)
+ if (op.Name == InstName.Sync || op.Name == InstName.Brk)
{
// If the instruction is a SYNC or BRK instruction with only one
// possible target address, then the instruction is basically
// just a simple branch, we can generate code similar to branch
// instructions, with the condition check on the branch itself.
- skipPredicateCheck = opBranchPop.Targets.Count < 2;
+ noPred = block.SyncTargets.Count <= 1;
+ }
+ else if (op.Name == InstName.Bra)
+ {
+ noPred = true;
}
- if (!(op.Predicate.IsPT || skipPredicateCheck))
+ if (!(opConditional.Pred == RegisterConsts.PredicateTrueIndex || noPred))
{
Operand label;
- if (opIndex == block.OpCodes.Count - 1 && block.Next != null)
+ if (opIndex == block.OpCodes.Count - 1 && block.HasNext())
{
- label = context.GetLabel(block.Next.Address);
+ label = context.GetLabel(block.Successors[0].Address);
}
else
{
@@ -296,9 +304,9 @@ namespace Ryujinx.Graphics.Shader.Translation
predSkipLbl = label;
}
- Operand pred = Register(op.Predicate);
+ Operand pred = Register(opConditional.Pred, RegisterType.Predicate);
- if (op.InvertPredicate)
+ if (opConditional.PredInv)
{
context.BranchIfTrue(label, pred);
}