Started to implement shader decoding support on the GPU
This commit is contained in:
parent
eaca9a3d5d
commit
e4aeb93be8
13 changed files with 339 additions and 0 deletions
4
Ryujinx.Graphics/Gal/Shader/ShaderDecode.cs
Normal file
4
Ryujinx.Graphics/Gal/Shader/ShaderDecode.cs
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
namespace Ryujinx.Graphics.Gal.Shader
|
||||||
|
{
|
||||||
|
delegate void ShaderDecodeFunc(ShaderIrBlock Block, long OpCode);
|
||||||
|
}
|
83
Ryujinx.Graphics/Gal/Shader/ShaderDecodeAlu.cs
Normal file
83
Ryujinx.Graphics/Gal/Shader/ShaderDecodeAlu.cs
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
namespace Ryujinx.Graphics.Gal.Shader
|
||||||
|
{
|
||||||
|
static partial class ShaderDecode
|
||||||
|
{
|
||||||
|
public static void Fadd(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;
|
||||||
|
|
||||||
|
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));
|
||||||
|
|
||||||
|
if (Aa)
|
||||||
|
{
|
||||||
|
Block.AddNode(new ShaderIrNode(ShaderIrInst.Fabs));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Na)
|
||||||
|
{
|
||||||
|
Block.AddNode(new ShaderIrNode(ShaderIrInst.Fneg));
|
||||||
|
}
|
||||||
|
|
||||||
|
Block.AddNode(new ShaderIrNodeLdb(Cb, Ob));
|
||||||
|
|
||||||
|
if (Ab)
|
||||||
|
{
|
||||||
|
Block.AddNode(new ShaderIrNode(ShaderIrInst.Fabs));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Nb)
|
||||||
|
{
|
||||||
|
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 Nc = ((OpCode >> 49) & 1) != 0;
|
||||||
|
|
||||||
|
Block.AddNode(new ShaderIrNodeLdr(Ra));
|
||||||
|
Block.AddNode(new ShaderIrNodeLdb(Cb, Ob));
|
||||||
|
|
||||||
|
if (Nb)
|
||||||
|
{
|
||||||
|
Block.AddNode(new ShaderIrNode(ShaderIrInst.Fneg));
|
||||||
|
}
|
||||||
|
|
||||||
|
Block.AddNode(new ShaderIrNode(ShaderIrInst.Fmul));
|
||||||
|
Block.AddNode(new ShaderIrNodeLdr(Rc));
|
||||||
|
|
||||||
|
if (Nc)
|
||||||
|
{
|
||||||
|
Block.AddNode(new ShaderIrNode(ShaderIrInst.Fneg));
|
||||||
|
}
|
||||||
|
|
||||||
|
Block.AddNode(new ShaderIrNode(ShaderIrInst.Fadd));
|
||||||
|
Block.AddNode(new ShaderIrNodeStr(Rd));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
29
Ryujinx.Graphics/Gal/Shader/ShaderDecoder.cs
Normal file
29
Ryujinx.Graphics/Gal/Shader/ShaderDecoder.cs
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
namespace Ryujinx.Graphics.Gal.Shader
|
||||||
|
{
|
||||||
|
static class ShaderDecoder
|
||||||
|
{
|
||||||
|
public static ShaderIrBlock DecodeBasicBlock(int[] Code, int Offset)
|
||||||
|
{
|
||||||
|
ShaderIrBlock Block = new ShaderIrBlock();
|
||||||
|
|
||||||
|
while (Offset + 2 <= Code.Length)
|
||||||
|
{
|
||||||
|
uint Word0 = (uint)Code[Offset++];
|
||||||
|
uint Word1 = (uint)Code[Offset++];
|
||||||
|
|
||||||
|
long OpCode = Word0 | (long)Word1 << 32;
|
||||||
|
|
||||||
|
ShaderDecodeFunc Decode = ShaderOpCodeTable.GetDecoder(OpCode);
|
||||||
|
|
||||||
|
if (Decode == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Decode(Block, OpCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
24
Ryujinx.Graphics/Gal/Shader/ShaderIrBlock.cs
Normal file
24
Ryujinx.Graphics/Gal/Shader/ShaderIrBlock.cs
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Gal.Shader
|
||||||
|
{
|
||||||
|
class ShaderIrBlock
|
||||||
|
{
|
||||||
|
private List<ShaderIrNode> Nodes;
|
||||||
|
|
||||||
|
public ShaderIrBlock()
|
||||||
|
{
|
||||||
|
Nodes = new List<ShaderIrNode>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddNode(ShaderIrNode Node)
|
||||||
|
{
|
||||||
|
Nodes.Add(Node);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShaderIrNode[] GetNodes()
|
||||||
|
{
|
||||||
|
return Nodes.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
12
Ryujinx.Graphics/Gal/Shader/ShaderIrInst.cs
Normal file
12
Ryujinx.Graphics/Gal/Shader/ShaderIrInst.cs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
namespace Ryujinx.Graphics.Gal.Shader
|
||||||
|
{
|
||||||
|
enum ShaderIrInst
|
||||||
|
{
|
||||||
|
Fabs,
|
||||||
|
Fadd,
|
||||||
|
Fmul,
|
||||||
|
Fneg,
|
||||||
|
Ld,
|
||||||
|
St
|
||||||
|
}
|
||||||
|
}
|
12
Ryujinx.Graphics/Gal/Shader/ShaderIrNode.cs
Normal file
12
Ryujinx.Graphics/Gal/Shader/ShaderIrNode.cs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
namespace Ryujinx.Graphics.Gal.Shader
|
||||||
|
{
|
||||||
|
class ShaderIrNode
|
||||||
|
{
|
||||||
|
public ShaderIrInst Inst;
|
||||||
|
|
||||||
|
public ShaderIrNode(ShaderIrInst Inst)
|
||||||
|
{
|
||||||
|
this.Inst = Inst;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
14
Ryujinx.Graphics/Gal/Shader/ShaderIrNodeLdb.cs
Normal file
14
Ryujinx.Graphics/Gal/Shader/ShaderIrNodeLdb.cs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
namespace Ryujinx.Graphics.Gal.Shader
|
||||||
|
{
|
||||||
|
class ShaderIrNodeLdb : ShaderIrNode
|
||||||
|
{
|
||||||
|
public int Cbuf { get; private set; }
|
||||||
|
public int Offs { get; private set; }
|
||||||
|
|
||||||
|
public ShaderIrNodeLdb(int Cbuf, int Offs) : base(ShaderIrInst.Ld)
|
||||||
|
{
|
||||||
|
this.Cbuf = Cbuf;
|
||||||
|
this.Offs = Offs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
12
Ryujinx.Graphics/Gal/Shader/ShaderIrNodeLdr.cs
Normal file
12
Ryujinx.Graphics/Gal/Shader/ShaderIrNodeLdr.cs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
namespace Ryujinx.Graphics.Gal.Shader
|
||||||
|
{
|
||||||
|
class ShaderIrNodeLdr : ShaderIrNode
|
||||||
|
{
|
||||||
|
public int GprIndex { get; private set; }
|
||||||
|
|
||||||
|
public ShaderIrNodeLdr(int GprIndex) : base(ShaderIrInst.Ld)
|
||||||
|
{
|
||||||
|
this.GprIndex = GprIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
12
Ryujinx.Graphics/Gal/Shader/ShaderIrNodeStr.cs
Normal file
12
Ryujinx.Graphics/Gal/Shader/ShaderIrNodeStr.cs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
namespace Ryujinx.Graphics.Gal.Shader
|
||||||
|
{
|
||||||
|
class ShaderIrNodeStr : ShaderIrNode
|
||||||
|
{
|
||||||
|
public int GprIndex { get; private set; }
|
||||||
|
|
||||||
|
public ShaderIrNodeStr(int GprIndex) : base(ShaderIrInst.St)
|
||||||
|
{
|
||||||
|
this.GprIndex = GprIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
4
Ryujinx.Graphics/Gal/Shader/ShaderIrOper.cs
Normal file
4
Ryujinx.Graphics/Gal/Shader/ShaderIrOper.cs
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
namespace Ryujinx.Graphics.Gal.Shader
|
||||||
|
{
|
||||||
|
class ShaderIrOper { }
|
||||||
|
}
|
12
Ryujinx.Graphics/Gal/Shader/ShaderIrOperReg.cs
Normal file
12
Ryujinx.Graphics/Gal/Shader/ShaderIrOperReg.cs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
namespace Ryujinx.Graphics.Gal.Shader
|
||||||
|
{
|
||||||
|
class ShaderIrOperReg : ShaderIrOper
|
||||||
|
{
|
||||||
|
public int GprIndex { get; private set; }
|
||||||
|
|
||||||
|
public ShaderIrOperReg(int GprIndex)
|
||||||
|
{
|
||||||
|
this.GprIndex = GprIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
71
Ryujinx.Graphics/Gal/Shader/ShaderOpCodeTable.cs
Normal file
71
Ryujinx.Graphics/Gal/Shader/ShaderOpCodeTable.cs
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Gal.Shader
|
||||||
|
{
|
||||||
|
static class ShaderOpCodeTable
|
||||||
|
{
|
||||||
|
private const int EncodingBits = 14;
|
||||||
|
|
||||||
|
private static ShaderDecodeFunc[] OpCodes;
|
||||||
|
|
||||||
|
static ShaderOpCodeTable()
|
||||||
|
{
|
||||||
|
OpCodes = new ShaderDecodeFunc[1 << EncodingBits];
|
||||||
|
|
||||||
|
#region Instructions
|
||||||
|
Set("0100110001011x", ShaderDecode.Fadd);
|
||||||
|
Set("010010011xxxxx", ShaderDecode.Ffma);
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void Set(string Encoding, ShaderDecodeFunc Func)
|
||||||
|
{
|
||||||
|
if (Encoding.Length != EncodingBits)
|
||||||
|
{
|
||||||
|
throw new ArgumentException(nameof(Encoding));
|
||||||
|
}
|
||||||
|
|
||||||
|
int Bit = Encoding.Length - 1;
|
||||||
|
int Value = 0;
|
||||||
|
int XMask = 0;
|
||||||
|
int XBits = 0;
|
||||||
|
|
||||||
|
int[] XPos = new int[Encoding.Length];
|
||||||
|
|
||||||
|
for (int Index = 0; Index < Encoding.Length; Index++, Bit--)
|
||||||
|
{
|
||||||
|
char Chr = Encoding[Index];
|
||||||
|
|
||||||
|
if (Chr == '1')
|
||||||
|
{
|
||||||
|
Value |= 1 << Bit;
|
||||||
|
}
|
||||||
|
else if (Chr == 'x')
|
||||||
|
{
|
||||||
|
XMask |= 1 << Bit;
|
||||||
|
|
||||||
|
XPos[XBits++] = Bit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
XMask = ~XMask;
|
||||||
|
|
||||||
|
for (int Index = 0; Index < (1 << XBits); Index++)
|
||||||
|
{
|
||||||
|
Value &= XMask;
|
||||||
|
|
||||||
|
for (int X = 0; X < XBits; X++)
|
||||||
|
{
|
||||||
|
Value |= ((Index >> X) & 1) << XPos[X];
|
||||||
|
}
|
||||||
|
|
||||||
|
OpCodes[Value] = Func;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ShaderDecodeFunc GetDecoder(long OpCode)
|
||||||
|
{
|
||||||
|
return OpCodes[(ulong)OpCode >> (64 - EncodingBits)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
50
Ryujinx.Graphics/Gal/Shader/ShaderTest.cs
Normal file
50
Ryujinx.Graphics/Gal/Shader/ShaderTest.cs
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
namespace Ryujinx.Graphics.Gal.Shader
|
||||||
|
{
|
||||||
|
public static class ShaderTest
|
||||||
|
{
|
||||||
|
public static void Test()
|
||||||
|
{
|
||||||
|
System.Console.WriteLine("Starting test code...");
|
||||||
|
|
||||||
|
System.Collections.Generic.List<int> CodeList = new System.Collections.Generic.List<int>();
|
||||||
|
|
||||||
|
using (System.IO.FileStream FS = new System.IO.FileStream("D:\\puyo_vsh.bin", System.IO.FileMode.Open))
|
||||||
|
{
|
||||||
|
System.IO.BinaryReader Reader = new System.IO.BinaryReader(FS);
|
||||||
|
|
||||||
|
while (FS.Position + 8 <= FS.Length)
|
||||||
|
{
|
||||||
|
CodeList.Add(Reader.ReadInt32());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int[] Code = CodeList.ToArray();
|
||||||
|
|
||||||
|
ShaderIrBlock Block = ShaderDecoder.DecodeBasicBlock(Code, 0);
|
||||||
|
|
||||||
|
ShaderIrNode[] Nodes = Block.GetNodes();
|
||||||
|
|
||||||
|
foreach (ShaderIrNode Node in Nodes)
|
||||||
|
{
|
||||||
|
System.Console.Write(Node.Inst);
|
||||||
|
|
||||||
|
if (Node is ShaderIrNodeLdr LdrNode)
|
||||||
|
{
|
||||||
|
System.Console.Write($" r{LdrNode.GprIndex}");
|
||||||
|
}
|
||||||
|
else if (Node is ShaderIrNodeStr StrNode)
|
||||||
|
{
|
||||||
|
System.Console.Write($" r{StrNode.GprIndex}");
|
||||||
|
}
|
||||||
|
else if (Node is ShaderIrNodeLdb LdbNode)
|
||||||
|
{
|
||||||
|
System.Console.Write($" c{LdbNode.Cbuf}[0x{LdbNode.Offs.ToString("x")}]");
|
||||||
|
}
|
||||||
|
|
||||||
|
System.Console.WriteLine(string.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
System.Console.WriteLine("Test code finished!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue