Initial support for shader half float instructions (#507)
This commit is contained in:
parent
c81abdde4c
commit
e10ff17e2d
9 changed files with 244 additions and 65 deletions
|
@ -6,6 +6,14 @@ namespace Ryujinx.Graphics.Gal.Shader
|
|||
{
|
||||
static partial class ShaderDecode
|
||||
{
|
||||
private enum HalfOutputType
|
||||
{
|
||||
PackedFp16,
|
||||
Fp32,
|
||||
MergeH0,
|
||||
MergeH1
|
||||
}
|
||||
|
||||
public static void Bfe_C(ShaderIrBlock Block, long OpCode, int Position)
|
||||
{
|
||||
EmitBfe(Block, OpCode, ShaderOper.CR);
|
||||
|
@ -144,6 +152,16 @@ namespace Ryujinx.Graphics.Gal.Shader
|
|||
EmitFsetp(Block, OpCode, ShaderOper.RR);
|
||||
}
|
||||
|
||||
public static void Hadd2_R(ShaderIrBlock Block, long OpCode, int Position)
|
||||
{
|
||||
EmitBinaryHalfOp(Block, OpCode, ShaderIrInst.Fadd);
|
||||
}
|
||||
|
||||
public static void Hmul2_R(ShaderIrBlock Block, long OpCode, int Position)
|
||||
{
|
||||
EmitBinaryHalfOp(Block, OpCode, ShaderIrInst.Fmul);
|
||||
}
|
||||
|
||||
public static void Iadd_C(ShaderIrBlock Block, long OpCode, int Position)
|
||||
{
|
||||
EmitIadd(Block, OpCode, ShaderOper.CR);
|
||||
|
@ -1041,6 +1059,47 @@ namespace Ryujinx.Graphics.Gal.Shader
|
|||
Block.AddNode(OpCode.PredNode(new ShaderIrAsg(P0Node, Op)));
|
||||
}
|
||||
|
||||
private static void EmitBinaryHalfOp(ShaderIrBlock Block, long OpCode, ShaderIrInst Inst)
|
||||
{
|
||||
bool AbsB = OpCode.Read(30);
|
||||
bool NegB = OpCode.Read(31);
|
||||
bool Sat = OpCode.Read(32);
|
||||
bool AbsA = OpCode.Read(44);
|
||||
|
||||
ShaderIrOperGpr[] VecA = OpCode.GprHalfVec8();
|
||||
ShaderIrOperGpr[] VecB = OpCode.GprHalfVec20();
|
||||
|
||||
HalfOutputType OutputType = (HalfOutputType)OpCode.Read(49, 3);
|
||||
|
||||
int Elems = OutputType == HalfOutputType.PackedFp16 ? 2 : 1;
|
||||
int First = OutputType == HalfOutputType.MergeH1 ? 1 : 0;
|
||||
|
||||
for (int Index = First; Index < Elems; Index++)
|
||||
{
|
||||
ShaderIrNode OperA = GetAluFabs (VecA[Index], AbsA);
|
||||
ShaderIrNode OperB = GetAluFabsFneg(VecB[Index], AbsB, NegB);
|
||||
|
||||
ShaderIrNode Op = new ShaderIrOp(Inst, OperA, OperB);
|
||||
|
||||
ShaderIrOperGpr Dst = GetHalfDst(OpCode, OutputType, Index);
|
||||
|
||||
Block.AddNode(OpCode.PredNode(new ShaderIrAsg(Dst, GetAluFsat(Op, Sat))));
|
||||
}
|
||||
}
|
||||
|
||||
private static ShaderIrOperGpr GetHalfDst(long OpCode, HalfOutputType OutputType, int Index)
|
||||
{
|
||||
switch (OutputType)
|
||||
{
|
||||
case HalfOutputType.PackedFp16: return OpCode.GprHalf0(Index);
|
||||
case HalfOutputType.Fp32: return OpCode.Gpr0();
|
||||
case HalfOutputType.MergeH0: return OpCode.GprHalf0(0);
|
||||
case HalfOutputType.MergeH1: return OpCode.GprHalf0(1);
|
||||
}
|
||||
|
||||
throw new ArgumentException(nameof(OutputType));
|
||||
}
|
||||
|
||||
private static void EmitLop(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
|
||||
{
|
||||
int SubOp = OpCode.Read(41, 3);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue