diff options
Diffstat (limited to 'Ryujinx.Graphics.Shader/Translation')
3 files changed, 52 insertions, 16 deletions
diff --git a/Ryujinx.Graphics.Shader/Translation/Optimizations/BindlessElimination.cs b/Ryujinx.Graphics.Shader/Translation/Optimizations/BindlessElimination.cs index 9515c349..a26c81c9 100644 --- a/Ryujinx.Graphics.Shader/Translation/Optimizations/BindlessElimination.cs +++ b/Ryujinx.Graphics.Shader/Translation/Optimizations/BindlessElimination.cs @@ -5,7 +5,9 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations { class BindlessElimination { - public static void RunPass(BasicBlock block) + private const int NvnTextureBufferSlot = 2; + + public static void RunPass(BasicBlock block, ShaderConfig config) { // We can turn a bindless into regular access by recognizing the pattern // produced by the compiler for separate texture and sampler. @@ -24,26 +26,39 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations continue; } - if (!(texOp.GetSource(0).AsgOp is Operation handleCombineOp)) + if (texOp.Inst == Instruction.TextureSample) { - continue; - } + if (!(texOp.GetSource(0).AsgOp is Operation handleCombineOp)) + { + continue; + } - if (handleCombineOp.Inst != Instruction.BitwiseOr) - { - continue; - } + if (handleCombineOp.Inst != Instruction.BitwiseOr) + { + continue; + } - Operand src0 = handleCombineOp.GetSource(0); - Operand src1 = handleCombineOp.GetSource(1); + Operand src0 = handleCombineOp.GetSource(0); + Operand src1 = handleCombineOp.GetSource(1); - if (src0.Type != OperandType.ConstantBuffer || src0.GetCbufSlot() != 2 || - src1.Type != OperandType.ConstantBuffer || src1.GetCbufSlot() != 2) - { - continue; + if (src0.Type != OperandType.ConstantBuffer || src0.GetCbufSlot() != NvnTextureBufferSlot || + src1.Type != OperandType.ConstantBuffer || src1.GetCbufSlot() != NvnTextureBufferSlot) + { + continue; + } + + texOp.SetHandle(src0.GetCbufOffset() | (src1.GetCbufOffset() << 16)); } + else if (texOp.Inst == Instruction.ImageLoad || texOp.Inst == Instruction.ImageStore) + { + Operand src0 = texOp.GetSource(0); - texOp.SetHandle(src0.GetCbufOffset() | (src1.GetCbufOffset() << 16)); + if (src0.Type == OperandType.ConstantBuffer && src0.GetCbufSlot() == NvnTextureBufferSlot) + { + texOp.SetHandle(src0.GetCbufOffset()); + texOp.Format = config.GetTextureFormat(texOp.Handle); + } + } } } } diff --git a/Ryujinx.Graphics.Shader/Translation/Optimizations/Optimizer.cs b/Ryujinx.Graphics.Shader/Translation/Optimizations/Optimizer.cs index 10a0e780..286574cf 100644 --- a/Ryujinx.Graphics.Shader/Translation/Optimizations/Optimizer.cs +++ b/Ryujinx.Graphics.Shader/Translation/Optimizations/Optimizer.cs @@ -89,7 +89,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations for (int blkIndex = 0; blkIndex < blocks.Length; blkIndex++) { BindlessToIndexed.RunPass(blocks[blkIndex]); - BindlessElimination.RunPass(blocks[blkIndex]); + BindlessElimination.RunPass(blocks[blkIndex], config); // Try to eliminate any operations that are now unused. LinkedListNode<INode> node = blocks[blkIndex].Operations.First; diff --git a/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs b/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs index 9e8329de..8b38afb9 100644 --- a/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs +++ b/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs @@ -68,5 +68,26 @@ namespace Ryujinx.Graphics.Shader.Translation // The depth register is always two registers after the last color output. return count + 1; } + + public TextureFormat GetTextureFormat(int handle) + { + // When the formatted load extension is supported, we don't need to + // specify a format, we can just declare it without a format and the GPU will handle it. + if (GpuAccessor.QuerySupportsImageLoadFormatted()) + { + return TextureFormat.Unknown; + } + + var format = GpuAccessor.QueryTextureFormat(handle); + + if (format == TextureFormat.Unknown) + { + GpuAccessor.Log($"Unknown format for texture {handle}."); + + format = TextureFormat.R8G8B8A8Unorm; + } + + return format; + } } }
\ No newline at end of file |
