Optimize pack/unpack sequences, some fixes related to half float instructions

This commit is contained in:
gdkchan 2019-04-06 15:36:30 -03:00
parent 3980043cf2
commit ce71abeec9
3 changed files with 103 additions and 20 deletions

View file

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

View file

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

View file

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