aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Shader
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2020-05-05 22:02:28 -0300
committerGitHub <noreply@github.com>2020-05-06 11:02:28 +1000
commitb8eb6abeccbd4a468214a4d2ad3a9b6e5e06973c (patch)
treecd3d71ebde0f4f32eb674778adae89c0efcb75df /Ryujinx.Graphics.Shader
parent7f500e7cae940958289abe1a3461e52684742053 (diff)
Refactor shader GPU state and memory access (#1203)
* Refactor shader GPU state and memory access * Fix NVDEC project build * Address PR feedback and add missing XML comments
Diffstat (limited to 'Ryujinx.Graphics.Shader')
-rw-r--r--Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs12
-rw-r--r--Ryujinx.Graphics.Shader/Decoders/Decoder.cs34
-rw-r--r--Ryujinx.Graphics.Shader/IGpuAccessor.cs67
-rw-r--r--Ryujinx.Graphics.Shader/Instructions/InstEmitConversion.cs4
-rw-r--r--Ryujinx.Graphics.Shader/Instructions/InstEmitFArith.cs2
-rw-r--r--Ryujinx.Graphics.Shader/Instructions/InstEmitMemory.cs22
-rw-r--r--Ryujinx.Graphics.Shader/Instructions/InstEmitMove.cs2
-rw-r--r--Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs16
-rw-r--r--Ryujinx.Graphics.Shader/Instructions/InstEmitVote.cs2
-rw-r--r--Ryujinx.Graphics.Shader/QueryInfoName.cs17
-rw-r--r--Ryujinx.Graphics.Shader/ShaderProgram.cs4
-rw-r--r--Ryujinx.Graphics.Shader/Translation/Lowering.cs6
-rw-r--r--Ryujinx.Graphics.Shader/Translation/Optimizations/GlobalToStorage.cs4
-rw-r--r--Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs58
-rw-r--r--Ryujinx.Graphics.Shader/Translation/ShaderHeader.cs38
-rw-r--r--Ryujinx.Graphics.Shader/Translation/Translator.cs62
-rw-r--r--Ryujinx.Graphics.Shader/Translation/TranslatorCallbacks.cs17
17 files changed, 155 insertions, 212 deletions
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs
index 36aff3fc..da902aa3 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs
@@ -34,7 +34,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
if (context.Config.Stage == ShaderStage.Geometry)
{
- string inPrimitive = ((InputTopology)context.Config.QueryInfo(QueryInfoName.PrimitiveTopology)).ToGlslString();
+ string inPrimitive = context.Config.GpuAccessor.QueryPrimitiveTopology().ToGlslString();
context.AppendLine($"layout ({inPrimitive}) in;");
@@ -48,7 +48,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
if (context.Config.Stage == ShaderStage.Compute)
{
- int localMemorySize = BitUtils.DivRoundUp(context.Config.QueryInfo(QueryInfoName.ComputeLocalMemorySize), 4);
+ int localMemorySize = BitUtils.DivRoundUp(context.Config.GpuAccessor.QueryComputeLocalMemorySize(), 4);
if (localMemorySize != 0)
{
@@ -58,7 +58,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
context.AppendLine();
}
- int sharedMemorySize = BitUtils.DivRoundUp(context.Config.QueryInfo(QueryInfoName.ComputeSharedMemorySize), 4);
+ int sharedMemorySize = BitUtils.DivRoundUp(context.Config.GpuAccessor.QueryComputeSharedMemorySize(), 4);
if (sharedMemorySize != 0)
{
@@ -124,9 +124,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
}
else
{
- string localSizeX = NumberFormatter.FormatInt(context.Config.QueryInfo(QueryInfoName.ComputeLocalSizeX));
- string localSizeY = NumberFormatter.FormatInt(context.Config.QueryInfo(QueryInfoName.ComputeLocalSizeY));
- string localSizeZ = NumberFormatter.FormatInt(context.Config.QueryInfo(QueryInfoName.ComputeLocalSizeZ));
+ string localSizeX = NumberFormatter.FormatInt(context.Config.GpuAccessor.QueryComputeLocalSizeX());
+ string localSizeY = NumberFormatter.FormatInt(context.Config.GpuAccessor.QueryComputeLocalSizeY());
+ string localSizeZ = NumberFormatter.FormatInt(context.Config.GpuAccessor.QueryComputeLocalSizeZ());
context.AppendLine(
"layout (" +
diff --git a/Ryujinx.Graphics.Shader/Decoders/Decoder.cs b/Ryujinx.Graphics.Shader/Decoders/Decoder.cs
index 3e322e45..e2c9212b 100644
--- a/Ryujinx.Graphics.Shader/Decoders/Decoder.cs
+++ b/Ryujinx.Graphics.Shader/Decoders/Decoder.cs
@@ -1,6 +1,5 @@
using Ryujinx.Graphics.Shader.Instructions;
using System;
-using System.Buffers.Binary;
using System.Collections.Generic;
using System.Linq;
@@ -10,7 +9,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
{
static class Decoder
{
- public static Block[] Decode(ReadOnlySpan<byte> code, ulong headerSize)
+ public static Block[] Decode(IGpuAccessor gpuAccessor, ulong startAddress)
{
List<Block> blocks = new List<Block>();
@@ -18,8 +17,6 @@ namespace Ryujinx.Graphics.Shader.Decoders
Dictionary<ulong, Block> visited = new Dictionary<ulong, Block>();
- ulong maxAddress = (ulong)code.Length - headerSize;
-
Block GetBlock(ulong blkAddress)
{
if (!visited.TryGetValue(blkAddress, out Block block))
@@ -56,7 +53,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
}
// If we have a block after the current one, set the limit address.
- ulong limitAddress = maxAddress;
+ ulong limitAddress = ulong.MaxValue;
if (nBlkIndex != blocks.Count)
{
@@ -74,7 +71,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
}
}
- FillBlock(code, currBlock, limitAddress, headerSize);
+ FillBlock(gpuAccessor, currBlock, limitAddress, startAddress);
if (currBlock.OpCodes.Count != 0)
{
@@ -82,11 +79,6 @@ namespace Ryujinx.Graphics.Shader.Decoders
// including those from SSY/PBK instructions.
foreach (OpCodePush pushOp in currBlock.PushOpCodes)
{
- if (pushOp.GetAbsoluteAddress() >= maxAddress)
- {
- return null;
- }
-
GetBlock(pushOp.GetAbsoluteAddress());
}
@@ -98,11 +90,6 @@ namespace Ryujinx.Graphics.Shader.Decoders
if (lastOp is OpCodeBranch opBr)
{
- if (opBr.GetAbsoluteAddress() >= maxAddress)
- {
- return null;
- }
-
currBlock.Branch = GetBlock(opBr.GetAbsoluteAddress());
}
else if (lastOp is OpCodeBranchIndir opBrIndir)
@@ -141,7 +128,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
}
// Do we have a block after the current one?
- if (!IsExit(currBlock.GetLastOp()) && currBlock.BrIndir != null && currBlock.EndAddress < maxAddress)
+ if (!IsExit(currBlock.GetLastOp()) && currBlock.BrIndir != null)
{
bool targetVisited = visited.ContainsKey(currBlock.EndAddress);
@@ -203,10 +190,10 @@ namespace Ryujinx.Graphics.Shader.Decoders
}
private static void FillBlock(
- ReadOnlySpan<byte> code,
- Block block,
- ulong limitAddress,
- ulong startAddress)
+ IGpuAccessor gpuAccessor,
+ Block block,
+ ulong limitAddress,
+ ulong startAddress)
{
ulong address = block.Address;
@@ -225,14 +212,11 @@ namespace Ryujinx.Graphics.Shader.Decoders
continue;
}
- uint word0 = BinaryPrimitives.ReadUInt32LittleEndian(code.Slice((int)(startAddress + address)));
- uint word1 = BinaryPrimitives.ReadUInt32LittleEndian(code.Slice((int)(startAddress + address + 4)));
-
ulong opAddress = address;
address += 8;
- long opCode = word0 | (long)word1 << 32;
+ long opCode = gpuAccessor.MemoryRead<long>(startAddress + opAddress);
(InstEmitter emitter, OpCodeTable.OpActivator opActivator) = OpCodeTable.GetEmitter(opCode);
diff --git a/Ryujinx.Graphics.Shader/IGpuAccessor.cs b/Ryujinx.Graphics.Shader/IGpuAccessor.cs
new file mode 100644
index 00000000..13281bf0
--- /dev/null
+++ b/Ryujinx.Graphics.Shader/IGpuAccessor.cs
@@ -0,0 +1,67 @@
+namespace Ryujinx.Graphics.Shader
+{
+ public interface IGpuAccessor
+ {
+ public void Log(string message)
+ {
+ // No default log output.
+ }
+
+ T MemoryRead<T>(ulong address) where T : unmanaged;
+
+ public int QueryComputeLocalSizeX()
+ {
+ return 1;
+ }
+
+ public int QueryComputeLocalSizeY()
+ {
+ return 1;
+ }
+
+ public int QueryComputeLocalSizeZ()
+ {
+ return 1;
+ }
+
+ public int QueryComputeLocalMemorySize()
+ {
+ return 0x1000;
+ }
+
+ public int QueryComputeSharedMemorySize()
+ {
+ return 0xc000;
+ }
+
+ public bool QueryIsTextureBuffer(int handle)
+ {
+ return false;
+ }
+
+ public bool QueryIsTextureRectangle(int handle)
+ {
+ return false;
+ }
+
+ public InputTopology QueryPrimitiveTopology()
+ {
+ return InputTopology.Points;
+ }
+
+ public int QueryStorageBufferOffsetAlignment()
+ {
+ return 16;
+ }
+
+ public bool QuerySupportsNonConstantTextureOffset()
+ {
+ return true;
+ }
+
+ public TextureFormat QueryTextureFormat(int handle)
+ {
+ return TextureFormat.R8G8B8A8Unorm;
+ }
+ }
+}
diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitConversion.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitConversion.cs
index 8716d4e7..c4c6c55b 100644
--- a/Ryujinx.Graphics.Shader/Instructions/InstEmitConversion.cs
+++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitConversion.cs
@@ -72,7 +72,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
if (intType == IntegerType.U64)
{
- context.Config.PrintLog("Unimplemented 64-bits F2I.");
+ context.Config.GpuAccessor.Log("Unimplemented 64-bits F2I.");
return;
}
@@ -184,7 +184,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
if (srcType == IntegerType.U64 || dstType == IntegerType.U64)
{
- context.Config.PrintLog("Invalid I2I encoding.");
+ context.Config.GpuAccessor.Log("Invalid I2I encoding.");
return;
}
diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitFArith.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitFArith.cs
index 1da5158f..6dc4c093 100644
--- a/Ryujinx.Graphics.Shader/Instructions/InstEmitFArith.cs
+++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitFArith.cs
@@ -431,7 +431,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
if (scale.AsFloat() == 1)
{
- context.Config.PrintLog($"Invalid FP multiply scale \"{op.Scale}\".");
+ context.Config.GpuAccessor.Log($"Invalid FP multiply scale \"{op.Scale}\".");
}
if (isFP64)
diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitMemory.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitMemory.cs
index 7eb88883..2418293d 100644
--- a/Ryujinx.Graphics.Shader/Instructions/InstEmitMemory.cs
+++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitMemory.cs
@@ -88,7 +88,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
}
else
{
- context.Config.PrintLog($"Invalid barrier mode: {op.Mode}.");
+ context.Config.GpuAccessor.Log($"Invalid barrier mode: {op.Mode}.");
}
}
@@ -141,7 +141,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
if (op.Size > IntegerSize.B64)
{
- context.Config.PrintLog($"Invalid LDC size: {op.Size}.");
+ context.Config.GpuAccessor.Log($"Invalid LDC size: {op.Size}.");
}
bool isSmallInt = op.Size < IntegerSize.B32;
@@ -209,7 +209,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
if (!(emit || cut))
{
- context.Config.PrintLog("Invalid OUT encoding.");
+ context.Config.GpuAccessor.Log("Invalid OUT encoding.");
}
if (emit)
@@ -274,7 +274,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
}
else
{
- context.Config.PrintLog($"Invalid reduction type: {type}.");
+ context.Config.GpuAccessor.Log($"Invalid reduction type: {type}.");
}
break;
case AtomicOp.BitwiseAnd:
@@ -284,7 +284,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
}
else
{
- context.Config.PrintLog($"Invalid reduction type: {type}.");
+ context.Config.GpuAccessor.Log($"Invalid reduction type: {type}.");
}
break;
case AtomicOp.BitwiseExclusiveOr:
@@ -294,7 +294,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
}
else
{
- context.Config.PrintLog($"Invalid reduction type: {type}.");
+ context.Config.GpuAccessor.Log($"Invalid reduction type: {type}.");
}
break;
case AtomicOp.BitwiseOr:
@@ -304,7 +304,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
}
else
{
- context.Config.PrintLog($"Invalid reduction type: {type}.");
+ context.Config.GpuAccessor.Log($"Invalid reduction type: {type}.");
}
break;
case AtomicOp.Maximum:
@@ -318,7 +318,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
}
else
{
- context.Config.PrintLog($"Invalid reduction type: {type}.");
+ context.Config.GpuAccessor.Log($"Invalid reduction type: {type}.");
}
break;
case AtomicOp.Minimum:
@@ -332,7 +332,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
}
else
{
- context.Config.PrintLog($"Invalid reduction type: {type}.");
+ context.Config.GpuAccessor.Log($"Invalid reduction type: {type}.");
}
break;
}
@@ -346,7 +346,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
if (op.Size > IntegerSize.B128)
{
- context.Config.PrintLog($"Invalid load size: {op.Size}.");
+ context.Config.GpuAccessor.Log($"Invalid load size: {op.Size}.");
}
bool isSmallInt = op.Size < IntegerSize.B32;
@@ -432,7 +432,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
if (op.Size > IntegerSize.B128)
{
- context.Config.PrintLog($"Invalid store size: {op.Size}.");
+ context.Config.GpuAccessor.Log($"Invalid store size: {op.Size}.");
}
bool isSmallInt = op.Size < IntegerSize.B32;
diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitMove.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitMove.cs
index efc80b0c..264c732d 100644
--- a/Ryujinx.Graphics.Shader/Instructions/InstEmitMove.cs
+++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitMove.cs
@@ -32,7 +32,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
if (isCC)
{
// TODO: Support Register to condition code flags copy.
- context.Config.PrintLog("R2P.CC not implemented.");
+ context.Config.GpuAccessor.Log("R2P.CC not implemented.");
}
else
{
diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs
index 18552d0a..7f7a48a6 100644
--- a/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs
+++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs
@@ -19,7 +19,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
if (type == SamplerType.None)
{
- context.Config.PrintLog("Invalid image store sampler type.");
+ context.Config.GpuAccessor.Log("Invalid image store sampler type.");
return;
}
@@ -158,7 +158,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
if (type == SamplerType.None)
{
- context.Config.PrintLog("Invalid image store sampler type.");
+ context.Config.GpuAccessor.Log("Invalid image store sampler type.");
return;
}
@@ -344,7 +344,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
if (type == SamplerType.None)
{
- context.Config.PrintLog("Invalid texture sampler type.");
+ context.Config.GpuAccessor.Log("Invalid texture sampler type.");
return;
}
@@ -423,14 +423,14 @@ namespace Ryujinx.Graphics.Shader.Instructions
if (type == SamplerType.None)
{
- context.Config.PrintLog("Invalid texel fetch sampler type.");
+ context.Config.GpuAccessor.Log("Invalid texel fetch sampler type.");
return;
}
flags = ConvertTextureFlags(tldsOp.Target) | TextureFlags.IntCoords;
- if (tldsOp.Target == TexelLoadTarget.Texture1DLodZero && context.Config.QueryInfoBool(QueryInfoName.IsTextureBuffer, tldsOp.Immediate))
+ if (tldsOp.Target == TexelLoadTarget.Texture1DLodZero && context.Config.GpuAccessor.QueryIsTextureBuffer(tldsOp.Immediate))
{
type = SamplerType.TextureBuffer;
flags &= ~TextureFlags.LodLevel;
@@ -1020,7 +1020,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
if (type == SamplerType.Texture1D && flags == TextureFlags.IntCoords && !isBindless)
{
- bool isTypeBuffer = context.Config.QueryInfoBool(QueryInfoName.IsTextureBuffer, op.Immediate);
+ bool isTypeBuffer = context.Config.GpuAccessor.QueryIsTextureBuffer(op.Immediate);
if (isTypeBuffer)
{
@@ -1093,11 +1093,11 @@ namespace Ryujinx.Graphics.Shader.Instructions
private static TextureFormat GetTextureFormat(EmitterContext context, int handle)
{
- var format = (TextureFormat)context.Config.QueryInfo(QueryInfoName.TextureFormat, handle);
+ var format = context.Config.GpuAccessor.QueryTextureFormat(handle);
if (format == TextureFormat.Unknown)
{
- context.Config.PrintLog($"Unknown format for texture {handle}.");
+ context.Config.GpuAccessor.Log($"Unknown format for texture {handle}.");
format = TextureFormat.R8G8B8A8Unorm;
}
diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitVote.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitVote.cs
index 8f81ecb4..5c16770a 100644
--- a/Ryujinx.Graphics.Shader/Instructions/InstEmitVote.cs
+++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitVote.cs
@@ -36,7 +36,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
}
else
{
- context.Config.PrintLog($"Invalid vote operation: {op.VoteOp}.");
+ context.Config.GpuAccessor.Log($"Invalid vote operation: {op.VoteOp}.");
}
if (!op.Rd.IsRZ)
diff --git a/Ryujinx.Graphics.Shader/QueryInfoName.cs b/Ryujinx.Graphics.Shader/QueryInfoName.cs
deleted file mode 100644
index 41f42cbd..00000000
--- a/Ryujinx.Graphics.Shader/QueryInfoName.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-namespace Ryujinx.Graphics.Shader
-{
- public enum QueryInfoName
- {
- ComputeLocalSizeX,
- ComputeLocalSizeY,
- ComputeLocalSizeZ,
- ComputeLocalMemorySize,
- ComputeSharedMemorySize,
- IsTextureBuffer,
- IsTextureRectangle,
- PrimitiveTopology,
- StorageBufferOffsetAlignment,
- SupportsNonConstantTextureOffset,
- TextureFormat
- }
-} \ No newline at end of file
diff --git a/Ryujinx.Graphics.Shader/ShaderProgram.cs b/Ryujinx.Graphics.Shader/ShaderProgram.cs
index 7a800d8c..30f40175 100644
--- a/Ryujinx.Graphics.Shader/ShaderProgram.cs
+++ b/Ryujinx.Graphics.Shader/ShaderProgram.cs
@@ -10,13 +10,15 @@ namespace Ryujinx.Graphics.Shader
public string Code { get; private set; }
+ public int SizeA { get; }
public int Size { get; }
- internal ShaderProgram(ShaderProgramInfo info, ShaderStage stage, string code, int size)
+ internal ShaderProgram(ShaderProgramInfo info, ShaderStage stage, string code, int size, int sizeA)
{
Info = info;
Stage = stage;
Code = code;
+ SizeA = sizeA;
Size = size;
}
diff --git a/Ryujinx.Graphics.Shader/Translation/Lowering.cs b/Ryujinx.Graphics.Shader/Translation/Lowering.cs
index 0b5ec592..6f52ce96 100644
--- a/Ryujinx.Graphics.Shader/Translation/Lowering.cs
+++ b/Ryujinx.Graphics.Shader/Translation/Lowering.cs
@@ -79,7 +79,7 @@ namespace Ryujinx.Graphics.Shader.Translation
sbSlot = PrependOperation(Instruction.ConditionalSelect, inRange, Const(slot), sbSlot);
}
- Operand alignMask = Const(-config.QueryInfo(QueryInfoName.StorageBufferOffsetAlignment));
+ Operand alignMask = Const(-config.GpuAccessor.QueryStorageBufferOffsetAlignment());
Operand baseAddrTrunc = PrependOperation(Instruction.BitwiseAnd, sbBaseAddrLow, alignMask);
Operand byteOffset = PrependOperation(Instruction.Subtract, addrLow, baseAddrTrunc);
@@ -131,9 +131,9 @@ namespace Ryujinx.Graphics.Shader.Translation
bool hasOffset = (texOp.Flags & TextureFlags.Offset) != 0;
bool hasOffsets = (texOp.Flags & TextureFlags.Offsets) != 0;
- bool hasInvalidOffset = (hasOffset || hasOffsets) && !config.QueryInfoBool(QueryInfoName.SupportsNonConstantTextureOffset);
+ bool hasInvalidOffset = (hasOffset || hasOffsets) && !config.GpuAccessor.QuerySupportsNonConstantTextureOffset();
- bool isRect = config.QueryInfoBool(QueryInfoName.IsTextureRectangle, texOp.Handle);
+ bool isRect = config.GpuAccessor.QueryIsTextureRectangle(texOp.Handle);
if (!(hasInvalidOffset || isRect))
{
diff --git a/Ryujinx.Graphics.Shader/Translation/Optimizations/GlobalToStorage.cs b/Ryujinx.Graphics.Shader/Translation/Optimizations/GlobalToStorage.cs
index 7988ef6c..254bd0b3 100644
--- a/Ryujinx.Graphics.Shader/Translation/Optimizations/GlobalToStorage.cs
+++ b/Ryujinx.Graphics.Shader/Translation/Optimizations/GlobalToStorage.cs
@@ -69,7 +69,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
Operand baseAddrTrunc = Local();
- Operand alignMask = Const(-config.QueryInfo(QueryInfoName.StorageBufferOffsetAlignment));
+ Operand alignMask = Const(-config.GpuAccessor.QueryStorageBufferOffsetAlignment());
Operation andOp = new Operation(Instruction.BitwiseAnd, baseAddrTrunc, baseAddrLow, alignMask);
@@ -140,7 +140,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
Operand baseAddrTrunc = Local();
- Operand alignMask = Const(-config.QueryInfo(QueryInfoName.StorageBufferOffsetAlignment));
+ Operand alignMask = Const(-config.GpuAccessor.QueryStorageBufferOffsetAlignment());
Operation andOp = new Operation(Instruction.BitwiseAnd, baseAddrTrunc, baseAddrLow, alignMask);
diff --git a/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs b/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs
index 3035ebf6..9e8329de 100644
--- a/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs
+++ b/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs
@@ -18,11 +18,11 @@ namespace Ryujinx.Graphics.Shader.Translation
public bool OmapSampleMask { get; }
public bool OmapDepth { get; }
- public TranslationFlags Flags { get; }
+ public IGpuAccessor GpuAccessor { get; }
- private TranslatorCallbacks _callbacks;
+ public TranslationFlags Flags { get; }
- public ShaderConfig(TranslationFlags flags, TranslatorCallbacks callbacks)
+ public ShaderConfig(IGpuAccessor gpuAccessor, TranslationFlags flags)
{
Stage = ShaderStage.Compute;
OutputTopology = OutputTopology.PointList;
@@ -32,11 +32,11 @@ namespace Ryujinx.Graphics.Shader.Translation
OmapTargets = null;
OmapSampleMask = false;
OmapDepth = false;
+ GpuAccessor = gpuAccessor;
Flags = flags;
- _callbacks = callbacks;
}
- public ShaderConfig(ShaderHeader header, TranslationFlags flags, TranslatorCallbacks callbacks)
+ public ShaderConfig(ShaderHeader header, IGpuAccessor gpuAccessor, TranslationFlags flags)
{
Stage = header.Stage;
OutputTopology = header.OutputTopology;
@@ -46,8 +46,8 @@ namespace Ryujinx.Graphics.Shader.Translation
OmapTargets = header.OmapTargets;
OmapSampleMask = header.OmapSampleMask;
OmapDepth = header.OmapDepth;
+ GpuAccessor = gpuAccessor;
Flags = flags;
- _callbacks = callbacks;
}
public int GetDepthRegister()
@@ -68,51 +68,5 @@ namespace Ryujinx.Graphics.Shader.Translation
// The depth register is always two registers after the last color output.
return count + 1;
}
-
- public bool QueryInfoBool(QueryInfoName info, int index = 0)
- {
- return Convert.ToBoolean(QueryInfo(info, index));
- }
-
- public int QueryInfo(QueryInfoName info, int index = 0)
- {
- if (_callbacks.QueryInfo != null)
- {
- return _callbacks.QueryInfo(info, index);
- }
- else
- {
- switch (info)
- {
- case QueryInfoName.ComputeLocalSizeX:
- case QueryInfoName.ComputeLocalSizeY:
- case QueryInfoName.ComputeLocalSizeZ:
- return 1;
- case QueryInfoName.ComputeLocalMemorySize:
- return 0x1000;
- case QueryInfoName.ComputeSharedMemorySize:
- return 0xc000;
- case QueryInfoName.IsTextureBuffer:
- return Convert.ToInt32(false);
- case QueryInfoName.IsTextureRectangle:
- return Convert.ToInt32(false);
- case QueryInfoName.PrimitiveTopology:
- return (int)InputTopology.Points;
- case QueryInfoName.StorageBufferOffsetAlignment:
- return 16;
- case QueryInfoName.SupportsNonConstantTextureOffset:
- return Convert.ToInt32(true);
- case QueryInfoName.TextureFormat:
- return (int)TextureFormat.R8G8B8A8Unorm;
- }
- }
-
- return 0;
- }
-
- public void PrintLog(string message)
- {
- _callbacks.PrintLog?.Invoke(message);
- }
}
} \ No newline at end of file
diff --git a/Ryujinx.Graphics.Shader/Translation/ShaderHeader.cs b/Ryujinx.Graphics.Shader/Translation/ShaderHeader.cs
index a3b861c9..1218d591 100644
--- a/Ryujinx.Graphics.Shader/Translation/ShaderHeader.cs
+++ b/Ryujinx.Graphics.Shader/Translation/ShaderHeader.cs
@@ -1,6 +1,5 @@
using Ryujinx.Graphics.Shader.Decoders;
using System;
-using System.Runtime.InteropServices;
namespace Ryujinx.Graphics.Shader.Translation
{
@@ -110,15 +109,13 @@ namespace Ryujinx.Graphics.Shader.Translation
public bool OmapSampleMask { get; }
public bool OmapDepth { get; }
- public ShaderHeader(ReadOnlySpan<byte> code)
+ public ShaderHeader(IGpuAccessor gpuAccessor, ulong address)
{
- ReadOnlySpan<int> header = MemoryMarshal.Cast<byte, int>(code);
-
- int commonWord0 = header[0];
- int commonWord1 = header[1];
- int commonWord2 = header[2];
- int commonWord3 = header[3];
- int commonWord4 = header[4];
+ 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);
SphType = commonWord0.Extract(0, 5);
Version = commonWord0.Extract(5, 5);
@@ -163,22 +160,19 @@ namespace Ryujinx.Graphics.Shader.Translation
ImapTypes = new ImapPixelType[32];
- for (int i = 0; i < 8; i++)
+ for (ulong i = 0; i < 32; i++)
{
- for (int j = 0; j < 4; j++)
- {
- byte imap = (byte)(header[6 + i] >> (j * 8));
-
- ImapTypes[i * 4 + j] = new ImapPixelType(
- (PixelImap)((imap >> 0) & 3),
- (PixelImap)((imap >> 2) & 3),
- (PixelImap)((imap >> 4) & 3),
- (PixelImap)((imap >> 6) & 3));
- }
+ byte imap = gpuAccessor.MemoryRead<byte>(address + 0x18 + i);
+
+ ImapTypes[i] = new ImapPixelType(
+ (PixelImap)((imap >> 0) & 3),
+ (PixelImap)((imap >> 2) & 3),
+ (PixelImap)((imap >> 4) & 3),
+ (PixelImap)((imap >> 6) & 3));
}
- int type2OmapTarget = header[18];
- int type2Omap = header[19];
+ int type2OmapTarget = gpuAccessor.MemoryRead<int>(address + 0x48);
+ int type2Omap = gpuAccessor.MemoryRead<int>(address + 0x4c);
OmapTargets = new OmapTarget[8];
diff --git a/Ryujinx.Graphics.Shader/Translation/Translator.cs b/Ryujinx.Graphics.Shader/Translation/Translator.cs
index 164e10a7..fb6935af 100644
--- a/Ryujinx.Graphics.Shader/Translation/Translator.cs
+++ b/Ryujinx.Graphics.Shader/Translation/Translator.cs
@@ -14,46 +14,22 @@ namespace Ryujinx.Graphics.Shader.Translation
{
private const int HeaderSize = 0x50;
- public static ReadOnlySpan<byte> ExtractCode(ReadOnlySpan<byte> code, bool compute, out int headerSize)
+ public static ShaderProgram Translate(ulong address, IGpuAccessor gpuAccessor, TranslationFlags flags)
{
- headerSize = compute ? 0 : HeaderSize;
-
- Block[] cfg = Decoder.Decode(code, (ulong)headerSize);
-
- if (cfg == null)
- {
- return code;
- }
-
- 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(ReadOnlySpan<byte> code, TranslatorCallbacks callbacks, TranslationFlags flags)
- {
- Operation[] ops = DecodeShader(code, callbacks, flags, out ShaderConfig config, out int size);
+ Operation[] ops = DecodeShader(address, gpuAccessor, flags, out ShaderConfig config, out int size);
return Translate(ops, config, size);
}
- public static ShaderProgram Translate(ReadOnlySpan<byte> vpACode, ReadOnlySpan<byte> vpBCode, TranslatorCallbacks callbacks, TranslationFlags flags)
+ public static ShaderProgram Translate(ulong addressA, ulong addressB, IGpuAccessor gpuAccessor, TranslationFlags flags)
{
- Operation[] vpAOps = DecodeShader(vpACode, callbacks, flags, out _, out _);
- Operation[] vpBOps = DecodeShader(vpBCode, callbacks, flags, out ShaderConfig config, out int sizeB);
+ Operation[] opsA = DecodeShader(addressA, gpuAccessor, flags, out _, out int sizeA);
+ Operation[] opsB = DecodeShader(addressB, gpuAccessor, flags, out ShaderConfig config, out int sizeB);
- return Translate(Combine(vpAOps, vpBOps), config, sizeB);
+ return Translate(Combine(opsA, opsB), config, sizeB, sizeA);
}
- private static ShaderProgram Translate(Operation[] ops, ShaderConfig config, int size)
+ private static ShaderProgram Translate(Operation[] ops, ShaderConfig config, int size, int sizeA = 0)
{
BasicBlock[] blocks = ControlFlowGraph.MakeCfg(ops);
@@ -83,34 +59,34 @@ namespace Ryujinx.Graphics.Shader.Translation
string glslCode = program.Code;
- return new ShaderProgram(spInfo, config.Stage, glslCode, size);
+ return new ShaderProgram(spInfo, config.Stage, glslCode, size, sizeA);
}
private static Operation[] DecodeShader(
- ReadOnlySpan<byte> code,
- TranslatorCallbacks callbacks,
- TranslationFlags flags,
- out ShaderConfig config,
- out int size)
+ ulong address,
+ IGpuAccessor gpuAccessor,
+ TranslationFlags flags,
+ out ShaderConfig config,
+ out int size)
{
Block[] cfg;
if ((flags & TranslationFlags.Compute) != 0)
{
- config = new ShaderConfig(flags, callbacks);
+ config = new ShaderConfig(gpuAccessor, flags);
- cfg = Decoder.Decode(code, 0);
+ cfg = Decoder.Decode(gpuAccessor, address);
}
else
{
- config = new ShaderConfig(new ShaderHeader(code), flags, callbacks);
+ config = new ShaderConfig(new ShaderHeader(gpuAccessor, address), gpuAccessor, flags);
- cfg = Decoder.Decode(code, HeaderSize);
+ cfg = Decoder.Decode(gpuAccessor, address + HeaderSize);
}
if (cfg == null)
{
- config.PrintLog("Invalid branch detected, failed to build CFG.");
+ gpuAccessor.Log("Invalid branch detected, failed to build CFG.");
size = 0;
@@ -150,7 +126,7 @@ namespace Ryujinx.Graphics.Shader.Translation
{
instName = "???";
- config.PrintLog($"Invalid instruction at 0x{op.Address:X6} (0x{op.RawOpCode:X16}).");
+ gpuAccessor.Log($"Invalid instruction at 0x{op.Address:X6} (0x{op.RawOpCode:X16}).");
}
string dbgComment = $"0x{op.Address:X6}: 0x{op.RawOpCode:X16} {instName}";
diff --git a/Ryujinx.Graphics.Shader/Translation/TranslatorCallbacks.cs b/Ryujinx.Graphics.Shader/Translation/TranslatorCallbacks.cs
deleted file mode 100644
index e0e9852f..00000000
--- a/Ryujinx.Graphics.Shader/Translation/TranslatorCallbacks.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using System;
-
-namespace Ryujinx.Graphics.Shader.Translation
-{
- public struct TranslatorCallbacks
- {
- internal Func<QueryInfoName, int, int> QueryInfo { get; }
-
- internal Action<string> PrintLog { get; }
-
- public TranslatorCallbacks(Func<QueryInfoName, int, int> queryInfoCallback, Action<string> printLogCallback)
- {
- QueryInfo = queryInfoCallback;
- PrintLog = printLogCallback;
- }
- }
-}