Extend bindless elimination to see through Phis with the same results (#5957)

* Extend bindless elimination to see through Phis with the same results

* Shader cache version bump
This commit is contained in:
gdkchan 2023-11-19 15:10:44 -03:00 committed by GitHub
parent aa96dcb1be
commit 0b58f46266
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 58 additions and 2 deletions

View file

@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
private const ushort FileFormatVersionMajor = 1; private const ushort FileFormatVersionMajor = 1;
private const ushort FileFormatVersionMinor = 2; private const ushort FileFormatVersionMinor = 2;
private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor; private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor;
private const uint CodeGenVersion = 5791; private const uint CodeGenVersion = 5957;
private const string SharedTocFileName = "shared.toc"; private const string SharedTocFileName = "shared.toc";
private const string SharedDataFileName = "shared.data"; private const string SharedDataFileName = "shared.data";

View file

@ -55,7 +55,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
continue; continue;
} }
if (bindlessHandle.AsgOp is not Operation handleCombineOp) if (!TryGetOperation(bindlessHandle.AsgOp, out Operation handleCombineOp))
{ {
continue; continue;
} }
@ -199,9 +199,64 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
} }
} }
private static bool TryGetOperation(INode asgOp, out Operation outOperation)
{
if (asgOp is PhiNode phi)
{
// If we have a phi, let's check if all inputs are effectively the same value.
// If so, we can "see through" the phi and pick any of the inputs (since they are all the same).
Operand firstSrc = phi.GetSource(0);
for (int index = 1; index < phi.SourcesCount; index++)
{
if (!IsSameOperand(firstSrc, phi.GetSource(index)))
{
outOperation = null;
return false;
}
}
asgOp = firstSrc.AsgOp;
}
if (asgOp is Operation operation)
{
outOperation = operation;
return true;
}
outOperation = null;
return false;
}
private static bool IsSameOperand(Operand x, Operand y)
{
if (x.Type == y.Type && x.Type == OperandType.LocalVariable)
{
return x.AsgOp is Operation xOp &&
y.AsgOp is Operation yOp &&
xOp.Inst == Instruction.BitwiseOr &&
yOp.Inst == Instruction.BitwiseOr &&
AreBothEqualConstantBuffers(xOp.GetSource(0), yOp.GetSource(0)) &&
AreBothEqualConstantBuffers(xOp.GetSource(1), yOp.GetSource(1));
}
return false;
}
private static bool AreBothEqualConstantBuffers(Operand x, Operand y)
{
return x.Type == y.Type && x.Value == y.Value && x.Type == OperandType.ConstantBuffer;
}
private static Operand GetSourceForMaskedHandle(Operation asgOp, uint mask) private static Operand GetSourceForMaskedHandle(Operation asgOp, uint mask)
{ {
// Assume it was already checked that the operation is bitwise AND. // Assume it was already checked that the operation is bitwise AND.
Operand src0 = asgOp.GetSource(0); Operand src0 = asgOp.GetSource(0);
Operand src1 = asgOp.GetSource(1); Operand src1 = asgOp.GetSource(1);
@ -210,6 +265,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
// We can't check if the mask matches here as both operands are from a constant buffer. // We can't check if the mask matches here as both operands are from a constant buffer.
// Be optimistic and assume it matches. Avoid constant buffer 1 as official drivers // Be optimistic and assume it matches. Avoid constant buffer 1 as official drivers
// uses this one to store compiler constants. // uses this one to store compiler constants.
return src0.GetCbufSlot() == 1 ? src1 : src0; return src0.GetCbufSlot() == 1 ? src1 : src0;
} }
else if (src0.Type == OperandType.ConstantBuffer && src1.Type == OperandType.Constant) else if (src0.Type == OperandType.ConstantBuffer && src1.Type == OperandType.Constant)