diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2020-05-05 22:02:28 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-05-06 11:02:28 +1000 |
| commit | b8eb6abeccbd4a468214a4d2ad3a9b6e5e06973c (patch) | |
| tree | cd3d71ebde0f4f32eb674778adae89c0efcb75df /Ryujinx.Graphics.Shader | |
| parent | 7f500e7cae940958289abe1a3461e52684742053 (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')
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; - } - } -} |
