forked from Mirror/Ryujinx
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:
parent
aa96dcb1be
commit
0b58f46266
2 changed files with 58 additions and 2 deletions
|
@ -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";
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in a new issue