Some work on shader decoding

This commit is contained in:
gdkchan 2018-03-22 00:38:07 -03:00
commit 1220d24a3f
2 changed files with 161 additions and 45 deletions

View file

@ -1,83 +1,191 @@
using System;
namespace Ryujinx.Graphics.Gal.Shader namespace Ryujinx.Graphics.Gal.Shader
{ {
static partial class ShaderDecode static partial class ShaderDecode
{ {
public static void Fadd(ShaderIrBlock Block, long OpCode) private enum ShaderOper
{ {
int Rd = (int)(OpCode >> 0) & 0xff; RR,
int Ra = (int)(OpCode >> 8) & 0xff; RC,
int Ob = (int)(OpCode >> 20) & 0x3fff; CR,
int Cb = (int)(OpCode >> 34) & 0x1f; Imm
}
public static void Fadd_R(ShaderIrBlock Block, long OpCode)
{
EmitAluBinary(Block, OpCode, ShaderOper.RR, ShaderIrInst.Fadd);
}
public static void Fadd_C(ShaderIrBlock Block, long OpCode)
{
EmitAluBinary(Block, OpCode, ShaderOper.CR, ShaderIrInst.Fadd);
}
public static void Fadd_Imm(ShaderIrBlock Block, long OpCode)
{
EmitAluBinary(Block, OpCode, ShaderOper.Imm, ShaderIrInst.Fadd);
}
public static void Ffma_RR(ShaderIrBlock Block, long OpCode)
{
EmitAluFfma(Block, OpCode, ShaderOper.RR);
}
public static void Ffma_CR(ShaderIrBlock Block, long OpCode)
{
EmitAluFfma(Block, OpCode, ShaderOper.CR);
}
public static void Ffma_RC(ShaderIrBlock Block, long OpCode)
{
EmitAluFfma(Block, OpCode, ShaderOper.RC);
}
public static void Ffma_Imm(ShaderIrBlock Block, long OpCode)
{
EmitAluFfma(Block, OpCode, ShaderOper.Imm);
}
public static void Fmul_R(ShaderIrBlock Block, long OpCode)
{
EmitAluBinary(Block, OpCode, ShaderOper.RR, ShaderIrInst.Fmul);
}
public static void Fmul_C(ShaderIrBlock Block, long OpCode)
{
EmitAluBinary(Block, OpCode, ShaderOper.CR, ShaderIrInst.Fmul);
}
public static void Fmul_Imm(ShaderIrBlock Block, long OpCode)
{
EmitAluBinary(Block, OpCode, ShaderOper.Imm, ShaderIrInst.Fmul);
}
private static void EmitAluBinary(
ShaderIrBlock Block,
long OpCode,
ShaderOper Oper,
ShaderIrInst Inst)
{
bool Nb = ((OpCode >> 45) & 1) != 0; bool Nb = ((OpCode >> 45) & 1) != 0;
bool Aa = ((OpCode >> 46) & 1) != 0; bool Aa = ((OpCode >> 46) & 1) != 0;
bool Na = ((OpCode >> 48) & 1) != 0; bool Na = ((OpCode >> 48) & 1) != 0;
bool Ab = ((OpCode >> 49) & 1) != 0; bool Ab = ((OpCode >> 49) & 1) != 0;
bool Ad = ((OpCode >> 50) & 1) != 0; bool Ad = ((OpCode >> 50) & 1) != 0;
Block.AddNode(new ShaderIrNodeLdr(Ra)); EmitAluOperANode(Block, OpCode);
if (Aa) if (Inst == ShaderIrInst.Fadd)
{ {
Block.AddNode(new ShaderIrNode(ShaderIrInst.Fabs)); EmitAluAbsNeg(Block, Aa, Na);
} }
if (Na) switch (Oper)
{ {
Block.AddNode(new ShaderIrNode(ShaderIrInst.Fneg)); case ShaderOper.RR: EmitAluOperBNode_RR (Block, OpCode); break;
case ShaderOper.CR: EmitAluOperBCNode_C (Block, OpCode); break;
case ShaderOper.Imm: EmitAluOperBNode_Imm(Block, OpCode); break;
default: throw new ArgumentException(nameof(Oper));
} }
Block.AddNode(new ShaderIrNodeLdb(Cb, Ob)); EmitAluAbsNeg(Block, Ab, Nb);
if (Ab) Block.AddNode(new ShaderIrNode(Inst));
{
Block.AddNode(new ShaderIrNode(ShaderIrInst.Fabs)); EmitAluAbs(Block, Ad);
EmitAluStrResult(Block, OpCode);
} }
if (Nb) private static void EmitAluFfma(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
{ {
Block.AddNode(new ShaderIrNode(ShaderIrInst.Fneg));
}
Block.AddNode(new ShaderIrNode(ShaderIrInst.Fadd));
if (Ad)
{
Block.AddNode(new ShaderIrNode(ShaderIrInst.Fabs));
}
Block.AddNode(new ShaderIrNodeStr(Rd));
}
public static void Ffma(ShaderIrBlock Block, long OpCode)
{
int Rd = (int)(OpCode >> 0) & 0xff;
int Ra = (int)(OpCode >> 8) & 0xff;
int Ob = (int)(OpCode >> 20) & 0x3fff;
int Cb = (int)(OpCode >> 34) & 0x1f;
int Rc = (int)(OpCode >> 39) & 0xff;
bool Nb = ((OpCode >> 48) & 1) != 0; bool Nb = ((OpCode >> 48) & 1) != 0;
bool Nc = ((OpCode >> 49) & 1) != 0; bool Nc = ((OpCode >> 49) & 1) != 0;
Block.AddNode(new ShaderIrNodeLdr(Ra)); EmitAluOperANode(Block, OpCode);
Block.AddNode(new ShaderIrNodeLdb(Cb, Ob));
if (Nb) switch (Oper)
{ {
Block.AddNode(new ShaderIrNode(ShaderIrInst.Fneg)); case ShaderOper.RR: EmitAluOperBNode_RR (Block, OpCode); break;
case ShaderOper.CR: EmitAluOperBCNode_C (Block, OpCode); break;
case ShaderOper.RC: EmitAluOperBCNode_R (Block, OpCode); break;
case ShaderOper.Imm: EmitAluOperBNode_Imm(Block, OpCode); break;
} }
EmitAluNeg(Block, Nb);
Block.AddNode(new ShaderIrNode(ShaderIrInst.Fmul)); Block.AddNode(new ShaderIrNode(ShaderIrInst.Fmul));
Block.AddNode(new ShaderIrNodeLdr(Rc));
if (Nc) if (Oper == ShaderOper.RC)
{
EmitAluOperBCNode_C(Block, OpCode);
}
else
{
EmitAluOperBCNode_R(Block, OpCode);
}
EmitAluNeg(Block, Nc);
Block.AddNode(new ShaderIrNode(ShaderIrInst.Fadd));
EmitAluStrResult(Block, OpCode);
}
private static void EmitAluAbsNeg(ShaderIrBlock Block, bool Abs, bool Neg)
{
EmitAluAbs(Block, Abs);
EmitAluNeg(Block, Neg);
}
private static void EmitAluAbs(ShaderIrBlock Block, bool Abs)
{
if (Abs)
{
Block.AddNode(new ShaderIrNode(ShaderIrInst.Fabs));
}
}
private static void EmitAluNeg(ShaderIrBlock Block, bool Neg)
{
if (Neg)
{ {
Block.AddNode(new ShaderIrNode(ShaderIrInst.Fneg)); Block.AddNode(new ShaderIrNode(ShaderIrInst.Fneg));
} }
}
Block.AddNode(new ShaderIrNode(ShaderIrInst.Fadd)); private static void EmitAluOperANode(ShaderIrBlock Block, long OpCode)
Block.AddNode(new ShaderIrNodeStr(Rd)); {
Block.AddNode(new ShaderIrNodeLdr((int)(OpCode >> 8) & 0xff));
}
private static void EmitAluOperBNode_RR(ShaderIrBlock Block, long OpCode)
{
Block.AddNode(new ShaderIrNodeLdr((int)(OpCode >> 20) & 0xff));
}
private static void EmitAluOperBCNode_R(ShaderIrBlock Block, long OpCode)
{
Block.AddNode(new ShaderIrNodeLdr((int)(OpCode >> 39) & 0xff));
}
private static void EmitAluOperBCNode_C(ShaderIrBlock Block, long OpCode)
{
Block.AddNode(new ShaderIrNodeLdb(
(int)(OpCode >> 34) & 0x1f,
(int)(OpCode >> 20) & 0x3fff));
}
private static void EmitAluOperBNode_Imm(ShaderIrBlock Block, long OpCode)
{
//TODO
}
private static void EmitAluStrResult(ShaderIrBlock Block, long OpCode)
{
Block.AddNode(new ShaderIrNodeStr((int)(OpCode >> 0) & 0xff));
} }
} }
} }

View file

@ -13,8 +13,16 @@ namespace Ryujinx.Graphics.Gal.Shader
OpCodes = new ShaderDecodeFunc[1 << EncodingBits]; OpCodes = new ShaderDecodeFunc[1 << EncodingBits];
#region Instructions #region Instructions
Set("0100110001011x", ShaderDecode.Fadd); Set("0101110001011x", ShaderDecode.Fadd_R);
Set("010010011xxxxx", ShaderDecode.Ffma); Set("0100110001011x", ShaderDecode.Fadd_C);
Set("0011100x01011x", ShaderDecode.Fadd_Imm);
Set("010110011xxxxx", ShaderDecode.Ffma_RR);
Set("010100011xxxxx", ShaderDecode.Ffma_RC);
Set("010010011xxxxx", ShaderDecode.Ffma_CR);
Set("001100101xxxxx", ShaderDecode.Ffma_Imm);
Set("0101110001101x", ShaderDecode.Fmul_R);
Set("0100110001101x", ShaderDecode.Fmul_C);
Set("0011100x01101x", ShaderDecode.Fmul_Imm);
#endregion #endregion
} }