Optimize pack/unpack sequences, some fixes related to half float instructions
This commit is contained in:
parent
3980043cf2
commit
ce71abeec9
3 changed files with 103 additions and 20 deletions
|
@ -2,7 +2,7 @@ using Ryujinx.Graphics.Shader.Instructions;
|
|||
|
||||
namespace Ryujinx.Graphics.Shader.Decoders
|
||||
{
|
||||
class OpCodeAluImm2x10 : OpCode, IOpCodeImm
|
||||
class OpCodeAluImm2x10 : OpCodeAlu, IOpCodeImm
|
||||
{
|
||||
public int Immediate { get; }
|
||||
|
||||
|
|
|
@ -292,7 +292,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||
|
||||
FPHalfSwizzle swizzle = FPHalfSwizzle.FP16;
|
||||
|
||||
if (!(op is OpCodeAluImm32))
|
||||
if (!(op is IOpCodeImm))
|
||||
{
|
||||
swizzle = (FPHalfSwizzle)op.RawOpCode.Extract(28, 2);
|
||||
}
|
||||
|
@ -314,16 +314,6 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||
return FPAbsNeg(context, operands, absoluteB, negateB);
|
||||
}
|
||||
|
||||
private static Operand[] FPAbsNeg(EmitterContext context, Operand[] operands, bool abs, bool neg)
|
||||
{
|
||||
for (int index = 0; index < operands.Length; index++)
|
||||
{
|
||||
operands[index] = context.FPAbsNeg(operands[index], abs, neg);
|
||||
}
|
||||
|
||||
return operands;
|
||||
}
|
||||
|
||||
private static Operand[] GetHalfSources(EmitterContext context, Operand src, FPHalfSwizzle swizzle)
|
||||
{
|
||||
switch (swizzle)
|
||||
|
@ -355,6 +345,16 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||
throw new ArgumentException($"Invalid swizzle \"{swizzle}\".");
|
||||
}
|
||||
|
||||
private static Operand[] FPAbsNeg(EmitterContext context, Operand[] operands, bool abs, bool neg)
|
||||
{
|
||||
for (int index = 0; index < operands.Length; index++)
|
||||
{
|
||||
operands[index] = context.FPAbsNeg(operands[index], abs, neg);
|
||||
}
|
||||
|
||||
return operands;
|
||||
}
|
||||
|
||||
private static Operand GetHalfPacked(EmitterContext context, Operand[] results)
|
||||
{
|
||||
OpCode op = context.CurrOp;
|
||||
|
@ -368,15 +368,40 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||
|
||||
switch (swizzle)
|
||||
{
|
||||
case FPHalfSwizzle.FP16: return context.PackHalf2x16(results[0], results[1]);
|
||||
case FPHalfSwizzle.FP32: return results[0];
|
||||
case FPHalfSwizzle.DupH0: return context.PackHalf2x16(results[0], results[0]);
|
||||
case FPHalfSwizzle.DupH1: return context.PackHalf2x16(results[1], results[1]);
|
||||
case FPHalfSwizzle.FP16: return context.PackHalf2x16(results[0], results[1]);
|
||||
|
||||
case FPHalfSwizzle.FP32: return results[0];
|
||||
|
||||
case FPHalfSwizzle.DupH0:
|
||||
{
|
||||
Operand h1 = GetHalfDest(context, isHigh: true);
|
||||
|
||||
return context.PackHalf2x16(results[0], h1);
|
||||
}
|
||||
|
||||
case FPHalfSwizzle.DupH1:
|
||||
{
|
||||
Operand h0 = GetHalfDest(context, isHigh: false);
|
||||
|
||||
return context.PackHalf2x16(h0, results[1]);
|
||||
}
|
||||
}
|
||||
|
||||
throw new ArgumentException($"Invalid swizzle \"{swizzle}\".");
|
||||
}
|
||||
|
||||
private static Operand GetHalfDest(EmitterContext context, bool isHigh)
|
||||
{
|
||||
if (isHigh)
|
||||
{
|
||||
return context.UnpackHalf2x16High(GetDest(context));
|
||||
}
|
||||
else
|
||||
{
|
||||
return context.UnpackHalf2x16Low(GetDest(context));
|
||||
}
|
||||
}
|
||||
|
||||
private static Operand GetFPComparison(
|
||||
EmitterContext context,
|
||||
Condition cond,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Ryujinx.Graphics.Shader.Translation.Optimizations
|
||||
{
|
||||
|
@ -43,13 +44,25 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
|
|||
|
||||
Simplification.Simplify(operation);
|
||||
|
||||
if (operation.Inst == Instruction.Copy && DestIsLocalVar(operation))
|
||||
if (DestIsLocalVar(operation))
|
||||
{
|
||||
PropagateCopy(operation);
|
||||
if (operation.Inst == Instruction.Copy)
|
||||
{
|
||||
PropagateCopy(operation);
|
||||
|
||||
RemoveNode(block, node);
|
||||
RemoveNode(block, node);
|
||||
|
||||
modified = true;
|
||||
modified = true;
|
||||
}
|
||||
else if (operation.Inst == Instruction.PackHalf2x16 && PropagatePack(operation))
|
||||
{
|
||||
if (operation.Dest.UseOps.Count == 0)
|
||||
{
|
||||
RemoveNode(block, node);
|
||||
}
|
||||
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
|
||||
node = nextNode;
|
||||
|
@ -85,6 +98,51 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
|
|||
}
|
||||
}
|
||||
|
||||
private static bool PropagatePack(Operation packOp)
|
||||
{
|
||||
//Propagate pack source operands to uses by unpack
|
||||
//instruction. The source depends on the unpack instruction.
|
||||
bool modified = false;
|
||||
|
||||
Operand dest = packOp.Dest;
|
||||
Operand src0 = packOp.GetSource(0);
|
||||
Operand src1 = packOp.GetSource(1);
|
||||
|
||||
INode[] uses = dest.UseOps.ToArray();
|
||||
|
||||
foreach (INode useNode in uses)
|
||||
{
|
||||
if (!(useNode is Operation operation))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Operand src;
|
||||
|
||||
if (operation.Inst == Instruction.UnpackHalf2x16High)
|
||||
{
|
||||
src = src1;
|
||||
}
|
||||
else if (operation.Inst == Instruction.UnpackHalf2x16Low)
|
||||
{
|
||||
src = src0;
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (operation.GetSource(0) == dest)
|
||||
{
|
||||
operation.TurnIntoCopy(src);
|
||||
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
|
||||
return modified;
|
||||
}
|
||||
|
||||
private static void RemoveNode(BasicBlock block, LinkedListNode<INode> llNode)
|
||||
{
|
||||
//Remove a node from the nodes list, and also remove itself
|
||||
|
|
Loading…
Add table
Reference in a new issue