Some work on shader decoding

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

View file

@ -1,83 +1,191 @@
using System;
namespace Ryujinx.Graphics.Gal.Shader
{
static partial class ShaderDecode
{
public static void Fadd(ShaderIrBlock Block, long OpCode)
private enum ShaderOper
{
int Rd = (int)(OpCode >> 0) & 0xff;
int Ra = (int)(OpCode >> 8) & 0xff;
int Ob = (int)(OpCode >> 20) & 0x3fff;
int Cb = (int)(OpCode >> 34) & 0x1f;
RR,
RC,
CR,
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 Aa = ((OpCode >> 46) & 1) != 0;
bool Na = ((OpCode >> 48) & 1) != 0;
bool Ab = ((OpCode >> 49) & 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(ShaderIrInst.Fabs));
}
Block.AddNode(new ShaderIrNode(Inst));
if (Nb)
{
Block.AddNode(new ShaderIrNode(ShaderIrInst.Fneg));
}
EmitAluAbs(Block, Ad);
Block.AddNode(new ShaderIrNode(ShaderIrInst.Fadd));
if (Ad)
{
Block.AddNode(new ShaderIrNode(ShaderIrInst.Fabs));
}
Block.AddNode(new ShaderIrNodeStr(Rd));
EmitAluStrResult(Block, OpCode);
}
public static void Ffma(ShaderIrBlock Block, long OpCode)
private static void EmitAluFfma(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
{
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 Nc = ((OpCode >> 49) & 1) != 0;
Block.AddNode(new ShaderIrNodeLdr(Ra));
Block.AddNode(new ShaderIrNodeLdb(Cb, Ob));
EmitAluOperANode(Block, OpCode);
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 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.Fadd));
Block.AddNode(new ShaderIrNodeStr(Rd));
private static void EmitAluOperANode(ShaderIrBlock Block, long OpCode)
{
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,9 +13,17 @@ namespace Ryujinx.Graphics.Gal.Shader
OpCodes = new ShaderDecodeFunc[1 << EncodingBits];
#region Instructions
Set("0100110001011x", ShaderDecode.Fadd);
Set("010010011xxxxx", ShaderDecode.Ffma);
#endregion
Set("0101110001011x", ShaderDecode.Fadd_R);
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
}
private static void Set(string Encoding, ShaderDecodeFunc Func)