mirror of
https://git.743378673.xyz/MeloNX/MeloNX.git
synced 2025-07-23 15:07:11 +02:00
Replace constant buffer access on shader with new Load instruction (#4646)
This commit is contained in:
parent
fb27042e01
commit
402f05b8ef
42 changed files with 788 additions and 625 deletions
|
@ -32,25 +32,49 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
|
|||
continue;
|
||||
}
|
||||
|
||||
if (handleAsgOp.Inst != Instruction.LoadConstant)
|
||||
if (handleAsgOp.Inst != Instruction.Load ||
|
||||
handleAsgOp.StorageKind != StorageKind.ConstantBuffer ||
|
||||
handleAsgOp.SourcesCount != 4)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Operand ldcSrc0 = handleAsgOp.GetSource(0);
|
||||
|
||||
if (ldcSrc0.Type != OperandType.Constant ||
|
||||
!config.ResourceManager.TryGetConstantBufferSlot(ldcSrc0.Value, out int src0CbufSlot) ||
|
||||
src0CbufSlot != 2)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Operand ldcSrc1 = handleAsgOp.GetSource(1);
|
||||
|
||||
if (ldcSrc0.Type != OperandType.Constant || ldcSrc0.Value != 2)
|
||||
// We expect field index 0 to be accessed.
|
||||
if (ldcSrc1.Type != OperandType.Constant || ldcSrc1.Value != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(ldcSrc1.AsgOp is Operation shrOp) || shrOp.Inst != Instruction.ShiftRightU32)
|
||||
Operand ldcSrc2 = handleAsgOp.GetSource(2);
|
||||
|
||||
// FIXME: This is missing some checks, for example, a check to ensure that the shift value is 2.
|
||||
// Might be not worth fixing since if that doesn't kick in, the result will be no texture
|
||||
// to access anyway which is also wrong.
|
||||
// Plus this whole transform is fundamentally flawed as-is since we have no way to know the array size.
|
||||
// Eventually, this should be entirely removed in favor of a implementation that supports true bindless
|
||||
// texture access.
|
||||
if (!(ldcSrc2.AsgOp is Operation shrOp) || shrOp.Inst != Instruction.ShiftRightU32)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(shrOp.GetSource(0).AsgOp is Operation addOp) || addOp.Inst != Instruction.Add)
|
||||
if (!(shrOp.GetSource(0).AsgOp is Operation shrOp2) || shrOp2.Inst != Instruction.ShiftRightU32)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(shrOp2.GetSource(0).AsgOp is Operation addOp) || addOp.Inst != Instruction.Add)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
|
|||
{
|
||||
static class ConstantFolding
|
||||
{
|
||||
public static void RunPass(Operation operation)
|
||||
public static void RunPass(ShaderConfig config, Operation operation)
|
||||
{
|
||||
if (!AreAllSourcesConstant(operation))
|
||||
{
|
||||
|
@ -153,8 +153,21 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
|
|||
EvaluateFPUnary(operation, (x) => float.IsNaN(x));
|
||||
break;
|
||||
|
||||
case Instruction.LoadConstant:
|
||||
operation.TurnIntoCopy(Cbuf(operation.GetSource(0).Value, operation.GetSource(1).Value));
|
||||
case Instruction.Load:
|
||||
if (operation.StorageKind == StorageKind.ConstantBuffer && operation.SourcesCount == 4)
|
||||
{
|
||||
int binding = operation.GetSource(0).Value;
|
||||
int fieldIndex = operation.GetSource(1).Value;
|
||||
|
||||
if (config.ResourceManager.TryGetConstantBufferSlot(binding, out int cbufSlot) && fieldIndex == 0)
|
||||
{
|
||||
int vecIndex = operation.GetSource(2).Value;
|
||||
int elemIndex = operation.GetSource(3).Value;
|
||||
int cbufOffset = vecIndex * 4 + elemIndex;
|
||||
|
||||
operation.TurnIntoCopy(Cbuf(cbufSlot, cbufOffset));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Instruction.Maximum:
|
||||
|
|
|
@ -347,21 +347,23 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
|
|||
return wordOffset;
|
||||
}
|
||||
|
||||
Operand[] sources = new Operand[operation.SourcesCount];
|
||||
Operand cbufOffset = GetCbufOffset();
|
||||
Operand vecIndex = Local();
|
||||
Operand elemIndex = Local();
|
||||
|
||||
node.List.AddBefore(node, new Operation(Instruction.ShiftRightU32, 0, vecIndex, cbufOffset, Const(2)));
|
||||
node.List.AddBefore(node, new Operation(Instruction.BitwiseAnd, 0, elemIndex, cbufOffset, Const(3)));
|
||||
|
||||
Operand[] sources = new Operand[4];
|
||||
|
||||
int cbSlot = UbeFirstCbuf + storageIndex;
|
||||
|
||||
sources[0] = Const(cbSlot);
|
||||
sources[1] = GetCbufOffset();
|
||||
sources[0] = Const(config.ResourceManager.GetConstantBufferBinding(cbSlot));
|
||||
sources[1] = Const(0);
|
||||
sources[2] = vecIndex;
|
||||
sources[3] = elemIndex;
|
||||
|
||||
config.SetUsedConstantBuffer(cbSlot);
|
||||
|
||||
for (int index = 2; index < operation.SourcesCount; index++)
|
||||
{
|
||||
sources[index] = operation.GetSource(index);
|
||||
}
|
||||
|
||||
Operation ldcOp = new Operation(Instruction.LoadConstant, operation.Dest, sources);
|
||||
Operation ldcOp = new Operation(Instruction.Load, StorageKind.ConstantBuffer, operation.Dest, sources);
|
||||
|
||||
for (int index = 0; index < operation.SourcesCount; index++)
|
||||
{
|
||||
|
|
|
@ -9,7 +9,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
|
|||
{
|
||||
public static void RunPass(BasicBlock[] blocks, ShaderConfig config)
|
||||
{
|
||||
RunOptimizationPasses(blocks);
|
||||
RunOptimizationPasses(blocks, config);
|
||||
|
||||
int sbUseMask = 0;
|
||||
int ubeUseMask = 0;
|
||||
|
@ -31,10 +31,10 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
|
|||
config.SetAccessibleBufferMasks(sbUseMask, ubeUseMask);
|
||||
|
||||
// Run optimizations one last time to remove any code that is now optimizable after above passes.
|
||||
RunOptimizationPasses(blocks);
|
||||
RunOptimizationPasses(blocks, config);
|
||||
}
|
||||
|
||||
private static void RunOptimizationPasses(BasicBlock[] blocks)
|
||||
private static void RunOptimizationPasses(BasicBlock[] blocks, ShaderConfig config)
|
||||
{
|
||||
bool modified;
|
||||
|
||||
|
@ -73,7 +73,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
|
|||
continue;
|
||||
}
|
||||
|
||||
ConstantFolding.RunPass(operation);
|
||||
ConstantFolding.RunPass(config, operation);
|
||||
Simplification.RunPass(operation);
|
||||
|
||||
if (DestIsLocalVar(operation))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue