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/Translation | |
| 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/Translation')
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); } |
