aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Shader/Translation
diff options
context:
space:
mode:
authorgdk <gab.dark.100@gmail.com>2019-11-08 17:29:41 -0300
committerThog <thog@protonmail.com>2020-01-09 02:13:00 +0100
commit769c02235f489f02b1791e6e76dc8b3ab18028ee (patch)
treeef0a2ffc5030360d5cef78e7c67e131e44348d50 /Ryujinx.Graphics.Shader/Translation
parent1e8bc29f32cde08616175f8f87405dfa7b8c4025 (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')
-rw-r--r--Ryujinx.Graphics.Shader/Translation/AttributeConsts.cs8
-rw-r--r--Ryujinx.Graphics.Shader/Translation/EmitterContextInsts.cs80
-rw-r--r--Ryujinx.Graphics.Shader/Translation/Optimizations/ConstantFolding.cs2
-rw-r--r--Ryujinx.Graphics.Shader/Translation/Optimizations/GlobalToStorage.cs29
-rw-r--r--Ryujinx.Graphics.Shader/Translation/Optimizations/Optimizer.cs27
-rw-r--r--Ryujinx.Graphics.Shader/Translation/Translator.cs70
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)