Started to implement shader decoding support on the GPU
This commit is contained in:
parent
d4a3e8267b
commit
b1a84555bd
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
Reference in a new issue