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
|
namespace Ryujinx.Graphics.Shader.Decoders
|
||||||
{
|
{
|
||||||
class OpCodeAluImm2x10 : OpCode, IOpCodeImm
|
class OpCodeAluImm2x10 : OpCodeAlu, IOpCodeImm
|
||||||
{
|
{
|
||||||
public int Immediate { get; }
|
public int Immediate { get; }
|
||||||
|
|
||||||
|
|
|
@ -292,7 +292,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||||
|
|
||||||
FPHalfSwizzle swizzle = FPHalfSwizzle.FP16;
|
FPHalfSwizzle swizzle = FPHalfSwizzle.FP16;
|
||||||
|
|
||||||
if (!(op is OpCodeAluImm32))
|
if (!(op is IOpCodeImm))
|
||||||
{
|
{
|
||||||
swizzle = (FPHalfSwizzle)op.RawOpCode.Extract(28, 2);
|
swizzle = (FPHalfSwizzle)op.RawOpCode.Extract(28, 2);
|
||||||
}
|
}
|
||||||
|
@ -314,16 +314,6 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||||
return FPAbsNeg(context, operands, absoluteB, negateB);
|
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)
|
private static Operand[] GetHalfSources(EmitterContext context, Operand src, FPHalfSwizzle swizzle)
|
||||||
{
|
{
|
||||||
switch (swizzle)
|
switch (swizzle)
|
||||||
|
@ -355,6 +345,16 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||||
throw new ArgumentException($"Invalid swizzle \"{swizzle}\".");
|
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)
|
private static Operand GetHalfPacked(EmitterContext context, Operand[] results)
|
||||||
{
|
{
|
||||||
OpCode op = context.CurrOp;
|
OpCode op = context.CurrOp;
|
||||||
|
@ -368,15 +368,40 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||||
|
|
||||||
switch (swizzle)
|
switch (swizzle)
|
||||||
{
|
{
|
||||||
case FPHalfSwizzle.FP16: return context.PackHalf2x16(results[0], results[1]);
|
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.FP32: return results[0];
|
||||||
case FPHalfSwizzle.DupH1: return context.PackHalf2x16(results[1], results[1]);
|
|
||||||
|
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}\".");
|
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(
|
private static Operand GetFPComparison(
|
||||||
EmitterContext context,
|
EmitterContext context,
|
||||||
Condition cond,
|
Condition cond,
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
|
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Shader.Translation.Optimizations
|
namespace Ryujinx.Graphics.Shader.Translation.Optimizations
|
||||||
{
|
{
|
||||||
|
@ -43,13 +44,25 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
|
||||||
|
|
||||||
Simplification.Simplify(operation);
|
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;
|
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)
|
private static void RemoveNode(BasicBlock block, LinkedListNode<INode> llNode)
|
||||||
{
|
{
|
||||||
//Remove a node from the nodes list, and also remove itself
|
//Remove a node from the nodes list, and also remove itself
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue