Replace constant buffer access on shader with new Load instruction (#4646)

This commit is contained in:
gdkchan 2023-05-20 16:19:26 -03:00 committed by GitHub
parent fb27042e01
commit 402f05b8ef
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
42 changed files with 788 additions and 625 deletions

View file

@ -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;
}

View file

@ -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:

View file

@ -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++)
{

View file

@ -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))