diff options
| author | gdk <gab.dark.100@gmail.com> | 2019-11-08 17:29:41 -0300 |
|---|---|---|
| committer | Thog <thog@protonmail.com> | 2020-01-09 02:13:00 +0100 |
| commit | 769c02235f489f02b1791e6e76dc8b3ab18028ee (patch) | |
| tree | ef0a2ffc5030360d5cef78e7c67e131e44348d50 /Ryujinx.Graphics.Shader/Translation | |
| parent | 1e8bc29f32cde08616175f8f87405dfa7b8c4025 (diff) | |
Add ATOMS, LDS, POPC, RED, STS and VOTE shader instructions, start changing the way how global memory is handled
Diffstat (limited to 'Ryujinx.Graphics.Shader/Translation')
6 files changed, 187 insertions, 29 deletions
diff --git a/Ryujinx.Graphics.Shader/Translation/AttributeConsts.cs b/Ryujinx.Graphics.Shader/Translation/AttributeConsts.cs index 08aac1ca..8ff37429 100644 --- a/Ryujinx.Graphics.Shader/Translation/AttributeConsts.cs +++ b/Ryujinx.Graphics.Shader/Translation/AttributeConsts.cs @@ -42,5 +42,13 @@ namespace Ryujinx.Graphics.Shader.Translation public const int CtaIdX = 0x2000010; public const int CtaIdY = 0x2000014; public const int CtaIdZ = 0x2000018; + + public const int LaneId = 0x2000020; + + public const int EqMask = 0x2000024; + public const int GeMask = 0x2000028; + public const int GtMask = 0x200002c; + public const int LeMask = 0x2000030; + public const int LtMask = 0x2000034; } }
\ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Translation/EmitterContextInsts.cs b/Ryujinx.Graphics.Shader/Translation/EmitterContextInsts.cs index 58a37b52..e94d4d2d 100644 --- a/Ryujinx.Graphics.Shader/Translation/EmitterContextInsts.cs +++ b/Ryujinx.Graphics.Shader/Translation/EmitterContextInsts.cs @@ -6,6 +6,61 @@ namespace Ryujinx.Graphics.Shader.Translation { static class EmitterContextInsts { + public static Operand AtomicAdd(this EmitterContext context, Instruction mr, Operand a, Operand b) + { + return context.Add(Instruction.AtomicAdd | mr, Local(), a, b); + } + + public static Operand AtomicAnd(this EmitterContext context, Instruction mr, Operand a, Operand b) + { + return context.Add(Instruction.AtomicAnd | mr, Local(), a, b); + } + + public static Operand AtomicCompareAndSwap(this EmitterContext context, Instruction mr, Operand a, Operand b, Operand c) + { + return context.Add(Instruction.AtomicCompareAndSwap | mr, Local(), a, b, c); + } + + public static Operand AtomicMaxS32(this EmitterContext context, Instruction mr, Operand a, Operand b) + { + return context.Add(Instruction.AtomicMaxS32 | mr, Local(), a, b); + } + + public static Operand AtomicMaxU32(this EmitterContext context, Instruction mr, Operand a, Operand b) + { + return context.Add(Instruction.AtomicMaxU32 | mr, Local(), a, b); + } + + public static Operand AtomicMinS32(this EmitterContext context, Instruction mr, Operand a, Operand b) + { + return context.Add(Instruction.AtomicMinS32 | mr, Local(), a, b); + } + + public static Operand AtomicMinU32(this EmitterContext context, Instruction mr, Operand a, Operand b) + { + return context.Add(Instruction.AtomicMinU32 | mr, Local(), a, b); + } + + public static Operand AtomicOr(this EmitterContext context, Instruction mr, Operand a, Operand b) + { + return context.Add(Instruction.AtomicOr | mr, Local(), a, b); + } + + public static Operand AtomicSwap(this EmitterContext context, Instruction mr, Operand a, Operand b) + { + return context.Add(Instruction.AtomicSwap | mr, Local(), a, b); + } + + public static Operand AtomicXor(this EmitterContext context, Instruction mr, Operand a, Operand b) + { + return context.Add(Instruction.AtomicXor | mr, Local(), a, b); + } + + public static Operand Ballot(this EmitterContext context, Operand a) + { + return context.Add(Instruction.Ballot, Local(), a); + } + public static Operand BitCount(this EmitterContext context, Operand a) { return context.Add(Instruction.BitCount, Local(), a); @@ -411,6 +466,11 @@ namespace Ryujinx.Graphics.Shader.Translation return context.Add(Instruction.LoadLocal, Local(), a); } + public static Operand LoadShared(this EmitterContext context, Operand a) + { + return context.Add(Instruction.LoadShared, Local(), a); + } + public static Operand PackHalf2x16(this EmitterContext context, Operand a, Operand b) { return context.Add(Instruction.PackHalf2x16, Local(), a, b); @@ -468,6 +528,11 @@ namespace Ryujinx.Graphics.Shader.Translation return context.Add(Instruction.StoreLocal, null, a, b); } + public static Operand StoreShared(this EmitterContext context, Operand a, Operand b) + { + return context.Add(Instruction.StoreShared, null, a, b); + } + public static Operand UnpackHalf2x16High(this EmitterContext context, Operand a) { return UnpackHalf2x16(context, a, 1); @@ -486,5 +551,20 @@ namespace Ryujinx.Graphics.Shader.Translation return dest; } + + public static Operand VoteAll(this EmitterContext context, Operand a) + { + return context.Add(Instruction.VoteAll, Local(), a); + } + + public static Operand VoteAllEqual(this EmitterContext context, Operand a) + { + return context.Add(Instruction.VoteAllEqual, Local(), a); + } + + public static Operand VoteAny(this EmitterContext context, Operand a) + { + return context.Add(Instruction.VoteAny, Local(), a); + } } }
\ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Translation/Optimizations/ConstantFolding.cs b/Ryujinx.Graphics.Shader/Translation/Optimizations/ConstantFolding.cs index 97852ac1..b6958929 100644 --- a/Ryujinx.Graphics.Shader/Translation/Optimizations/ConstantFolding.cs +++ b/Ryujinx.Graphics.Shader/Translation/Optimizations/ConstantFolding.cs @@ -256,7 +256,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations { int value = operation.GetSource(0).Value; - value = (value >> operation.ComponentIndex * 16) & 0xffff; + value = (value >> operation.Index * 16) & 0xffff; operation.TurnIntoCopy(ConstF(HalfConversion.HalfToSingle(value))); } diff --git a/Ryujinx.Graphics.Shader/Translation/Optimizations/GlobalToStorage.cs b/Ryujinx.Graphics.Shader/Translation/Optimizations/GlobalToStorage.cs index 3d89faf6..2fafa5ad 100644 --- a/Ryujinx.Graphics.Shader/Translation/Optimizations/GlobalToStorage.cs +++ b/Ryujinx.Graphics.Shader/Translation/Optimizations/GlobalToStorage.cs @@ -1,8 +1,6 @@ using Ryujinx.Graphics.Shader.IntermediateRepresentation; using System.Collections.Generic; -using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; - namespace Ryujinx.Graphics.Shader.Translation.Optimizations { static class GlobalToStorage @@ -27,7 +25,8 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations continue; } - if (operation.Inst == Instruction.LoadGlobal || + if (operation.Inst.IsAtomic() || + operation.Inst == Instruction.LoadGlobal || operation.Inst == Instruction.StoreGlobal) { Operand source = operation.GetSource(0); @@ -51,18 +50,31 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations Operation storageOp; - if (operation.Inst == Instruction.LoadGlobal) + if (operation.Inst.IsAtomic()) + { + Operand[] sources = new Operand[operation.SourcesCount]; + + for (int index = 0; index < operation.SourcesCount; index++) + { + sources[index] = operation.GetSource(index); + } + + Instruction inst = (operation.Inst & ~Instruction.MrMask) | Instruction.MrStorage; + + storageOp = new Operation(inst, storageIndex, operation.Dest, sources); + } + else if (operation.Inst == Instruction.LoadGlobal) { Operand source = operation.GetSource(0); - storageOp = new Operation(Instruction.LoadStorage, operation.Dest, Const(storageIndex), source); + storageOp = new Operation(Instruction.LoadStorage, storageIndex, operation.Dest, source); } else { Operand src1 = operation.GetSource(0); Operand src2 = operation.GetSource(1); - storageOp = new Operation(Instruction.StoreStorage, null, Const(storageIndex), src1, src2); + storageOp = new Operation(Instruction.StoreStorage, storageIndex, null, src1, src2); } for (int index = 0; index < operation.SourcesCount; index++) @@ -114,6 +126,11 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations return -1; } + public static int GetStorageCbOffset(ShaderStage stage, int slot) + { + return GetStorageBaseCbOffset(stage) + slot * StorageDescSize; + } + private static int GetStorageBaseCbOffset(ShaderStage stage) { switch (stage) diff --git a/Ryujinx.Graphics.Shader/Translation/Optimizations/Optimizer.cs b/Ryujinx.Graphics.Shader/Translation/Optimizations/Optimizer.cs index 6ee27884..93d86541 100644 --- a/Ryujinx.Graphics.Shader/Translation/Optimizations/Optimizer.cs +++ b/Ryujinx.Graphics.Shader/Translation/Optimizations/Optimizer.cs @@ -133,7 +133,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations if (operation.GetSource(0) == dest) { - operation.TurnIntoCopy(operation.ComponentIndex == 1 ? src1 : src0); + operation.TurnIntoCopy(operation.Index == 1 ? src1 : src0); modified = true; } @@ -251,7 +251,30 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations private static bool IsUnused(INode node) { - return DestIsLocalVar(node) && node.Dest.UseOps.Count == 0; + return !HasSideEffects(node) && DestIsLocalVar(node) && node.Dest.UseOps.Count == 0; + } + + private static bool HasSideEffects(INode node) + { + if (node is Operation operation) + { + switch (operation.Inst & Instruction.Mask) + { + case Instruction.AtomicAdd: + case Instruction.AtomicAnd: + case Instruction.AtomicCompareAndSwap: + case Instruction.AtomicMaxS32: + case Instruction.AtomicMaxU32: + case Instruction.AtomicMinS32: + case Instruction.AtomicMinU32: + case Instruction.AtomicOr: + case Instruction.AtomicSwap: + case Instruction.AtomicXor: + return true; + } + } + + return false; } private static bool DestIsLocalVar(INode node) diff --git a/Ryujinx.Graphics.Shader/Translation/Translator.cs b/Ryujinx.Graphics.Shader/Translation/Translator.cs index aaf618e9..b7a5bffa 100644 --- a/Ryujinx.Graphics.Shader/Translation/Translator.cs +++ b/Ryujinx.Graphics.Shader/Translation/Translator.cs @@ -15,25 +15,38 @@ namespace Ryujinx.Graphics.Shader.Translation { private const int HeaderSize = 0x50; - public static ShaderProgram Translate(Span<byte> code, TranslationConfig translationConfig) + public static Span<byte> ExtractCode(Span<byte> code, bool compute, out int headerSize) { - return Translate(code, Span<byte>.Empty, translationConfig); + if (compute) + { + headerSize = 0; + } + else + { + headerSize = HeaderSize; + } + + Block[] cfg = Decoder.Decode(code, (ulong)headerSize); + + ulong endAddress = 0; + + foreach (Block block in cfg) + { + if (endAddress < block.EndAddress) + { + endAddress = block.EndAddress; + } + } + + return code.Slice(0, headerSize + (int)endAddress); } - public static ShaderProgram Translate(Span<byte> code, Span<byte> code2, TranslationConfig translationConfig) + public static ShaderProgram Translate(Span<byte> code, TranslationConfig translationConfig) { bool compute = (translationConfig.Flags & TranslationFlags.Compute) != 0; bool debugMode = (translationConfig.Flags & TranslationFlags.DebugMode) != 0; - Operation[] shaderOps = DecodeShader(code, compute, debugMode, out ShaderHeader header); - - if (code2 != Span<byte>.Empty) - { - // Dual vertex shader. - Operation[] shaderOpsB = DecodeShader(code2, compute, debugMode, out header); - - shaderOps = Combine(shaderOps, shaderOpsB); - } + Operation[] ops = DecodeShader(code, compute, debugMode, out ShaderHeader header); ShaderStage stage; @@ -63,7 +76,29 @@ namespace Ryujinx.Graphics.Shader.Translation maxOutputVertexCount, outputTopology); - BasicBlock[] irBlocks = ControlFlowGraph.MakeCfg(shaderOps); + return Translate(ops, config); + } + + public static ShaderProgram Translate(Span<byte> vpACode, Span<byte> vpBCode, TranslationConfig translationConfig) + { + bool debugMode = (translationConfig.Flags & TranslationFlags.DebugMode) != 0; + + Operation[] vpAOps = DecodeShader(vpACode, compute: false, debugMode, out _); + Operation[] vpBOps = DecodeShader(vpBCode, compute: false, debugMode, out ShaderHeader header); + + ShaderConfig config = new ShaderConfig( + header.Stage, + translationConfig.Flags, + translationConfig.MaxCBufferSize, + header.MaxOutputVertexCount, + header.OutputTopology); + + return Translate(Combine(vpAOps, vpBOps), config); + } + + private static ShaderProgram Translate(Operation[] ops, ShaderConfig config) + { + BasicBlock[] irBlocks = ControlFlowGraph.MakeCfg(ops); Dominance.FindDominators(irBlocks[0], irBlocks.Length); @@ -71,7 +106,7 @@ namespace Ryujinx.Graphics.Shader.Translation Ssa.Rename(irBlocks); - Optimizer.Optimize(irBlocks, stage); + Optimizer.Optimize(irBlocks, config.Stage); StructuredProgramInfo sInfo = StructuredProgram.MakeStructuredProgram(irBlocks, config); @@ -87,12 +122,7 @@ namespace Ryujinx.Graphics.Shader.Translation string glslCode = program.Code; - if (translationConfig.Version != 0) - { - glslCode = "// " + translationConfig.Version + Environment.NewLine + glslCode; - } - - return new ShaderProgram(spInfo, stage, glslCode); + return new ShaderProgram(spInfo, config.Stage, glslCode); } private static Operation[] DecodeShader(Span<byte> code, bool compute, bool debugMode, out ShaderHeader header) |
