Add ld/st (attribute variant) instruction decoding, initial implementation of expression propagation, changes to the IR
This commit is contained in:
parent
1220d24a3f
commit
06a19248cd
18 changed files with 472 additions and 128 deletions
|
@ -1,5 +1,7 @@
|
|||
using System;
|
||||
|
||||
using static Ryujinx.Graphics.Gal.Shader.ShaderDecodeHelper;
|
||||
|
||||
namespace Ryujinx.Graphics.Gal.Shader
|
||||
{
|
||||
static partial class ShaderDecode
|
||||
|
@ -74,29 +76,28 @@ namespace Ryujinx.Graphics.Gal.Shader
|
|||
bool Ab = ((OpCode >> 49) & 1) != 0;
|
||||
bool Ad = ((OpCode >> 50) & 1) != 0;
|
||||
|
||||
EmitAluOperANode(Block, OpCode);
|
||||
ShaderIrOper OperA = GetAluOperANode_R(OpCode);
|
||||
ShaderIrOper OperB;
|
||||
|
||||
if (Inst == ShaderIrInst.Fadd)
|
||||
{
|
||||
EmitAluAbsNeg(Block, Aa, Na);
|
||||
OperA = GetAluAbsNeg(OperA, Aa, Na);
|
||||
}
|
||||
|
||||
switch (Oper)
|
||||
{
|
||||
case ShaderOper.RR: EmitAluOperBNode_RR (Block, OpCode); break;
|
||||
case ShaderOper.CR: EmitAluOperBCNode_C (Block, OpCode); break;
|
||||
case ShaderOper.Imm: EmitAluOperBNode_Imm(Block, OpCode); break;
|
||||
case ShaderOper.RR: OperB = GetAluOperBNode_RR (OpCode); break;
|
||||
case ShaderOper.CR: OperB = GetAluOperBCNode_C (OpCode); break;
|
||||
case ShaderOper.Imm: OperB = GetAluOperBNode_Imm(OpCode); break;
|
||||
|
||||
default: throw new ArgumentException(nameof(Oper));
|
||||
}
|
||||
|
||||
EmitAluAbsNeg(Block, Ab, Nb);
|
||||
OperB = GetAluAbsNeg(OperB, Ab, Nb);
|
||||
|
||||
Block.AddNode(new ShaderIrNode(Inst));
|
||||
ShaderIrOper Op = GetAluAbs(new ShaderIrOperOp(Inst, OperA, OperB), Ad);
|
||||
|
||||
EmitAluAbs(Block, Ad);
|
||||
|
||||
EmitAluStrResult(Block, OpCode);
|
||||
Block.AddNode(new ShaderIrNode(GetAluOperDNode(OpCode), Op));
|
||||
}
|
||||
|
||||
private static void EmitAluFfma(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
|
||||
|
@ -104,88 +105,49 @@ namespace Ryujinx.Graphics.Gal.Shader
|
|||
bool Nb = ((OpCode >> 48) & 1) != 0;
|
||||
bool Nc = ((OpCode >> 49) & 1) != 0;
|
||||
|
||||
EmitAluOperANode(Block, OpCode);
|
||||
ShaderIrOper OperA = GetAluOperANode_R(OpCode);
|
||||
ShaderIrOper OperB;
|
||||
ShaderIrOper OperC;
|
||||
|
||||
switch (Oper)
|
||||
{
|
||||
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;
|
||||
case ShaderOper.RR: OperB = GetAluOperBNode_RR (OpCode); break;
|
||||
case ShaderOper.CR: OperB = GetAluOperBCNode_C (OpCode); break;
|
||||
case ShaderOper.RC: OperB = GetAluOperBCNode_R (OpCode); break;
|
||||
case ShaderOper.Imm: OperB = GetAluOperBNode_Imm(OpCode); break;
|
||||
|
||||
default: throw new ArgumentException(nameof(Oper));
|
||||
}
|
||||
|
||||
EmitAluNeg(Block, Nb);
|
||||
|
||||
Block.AddNode(new ShaderIrNode(ShaderIrInst.Fmul));
|
||||
OperB = GetAluNeg(OperB, Nb);
|
||||
|
||||
if (Oper == ShaderOper.RC)
|
||||
{
|
||||
EmitAluOperBCNode_C(Block, OpCode);
|
||||
OperC = GetAluNeg(GetAluOperBCNode_C(OpCode), Nc);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitAluOperBCNode_R(Block, OpCode);
|
||||
OperC = GetAluNeg(GetAluOperBCNode_R(OpCode), Nc);
|
||||
}
|
||||
|
||||
EmitAluNeg(Block, Nc);
|
||||
ShaderIrOper Op = new ShaderIrOperOp(ShaderIrInst.Ffma, OperA, OperB, OperC);
|
||||
|
||||
Block.AddNode(new ShaderIrNode(ShaderIrInst.Fadd));
|
||||
|
||||
EmitAluStrResult(Block, OpCode);
|
||||
Block.AddNode(new ShaderIrNode(GetAluOperDNode(OpCode), Op));
|
||||
}
|
||||
|
||||
private static void EmitAluAbsNeg(ShaderIrBlock Block, bool Abs, bool Neg)
|
||||
private static ShaderIrOper GetAluAbsNeg(ShaderIrOper Node, bool Abs, bool Neg)
|
||||
{
|
||||
EmitAluAbs(Block, Abs);
|
||||
EmitAluNeg(Block, Neg);
|
||||
return GetAluNeg(GetAluAbs(Node, Abs), Neg);
|
||||
}
|
||||
|
||||
private static void EmitAluAbs(ShaderIrBlock Block, bool Abs)
|
||||
private static ShaderIrOper GetAluAbs(ShaderIrOper Node, bool Abs)
|
||||
{
|
||||
if (Abs)
|
||||
{
|
||||
Block.AddNode(new ShaderIrNode(ShaderIrInst.Fabs));
|
||||
}
|
||||
return Abs ? new ShaderIrOperOp(ShaderIrInst.Fabs, Node) : Node;
|
||||
}
|
||||
|
||||
private static void EmitAluNeg(ShaderIrBlock Block, bool Neg)
|
||||
private static ShaderIrOper GetAluNeg(ShaderIrOper Node, bool Neg)
|
||||
{
|
||||
if (Neg)
|
||||
{
|
||||
Block.AddNode(new ShaderIrNode(ShaderIrInst.Fneg));
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
return Neg ? new ShaderIrOperOp(ShaderIrInst.Fneg, Node) : Node;
|
||||
}
|
||||
}
|
||||
}
|
54
Ryujinx.Graphics/Gal/Shader/ShaderDecodeHelper.cs
Normal file
54
Ryujinx.Graphics/Gal/Shader/ShaderDecodeHelper.cs
Normal file
|
@ -0,0 +1,54 @@
|
|||
namespace Ryujinx.Graphics.Gal.Shader
|
||||
{
|
||||
static class ShaderDecodeHelper
|
||||
{
|
||||
public static ShaderIrOper[] GetAluOperANode_A(long OpCode)
|
||||
{
|
||||
int Abuf = (int)(OpCode >> 20) & 0x3ff;
|
||||
int Reg = (int)(OpCode >> 39) & 0xff;
|
||||
int Size = (int)(OpCode >> 47) & 3;
|
||||
|
||||
ShaderIrOper[] Opers = new ShaderIrOper[Size + 1];
|
||||
|
||||
for (int Index = 0; Index <= Size; Index++)
|
||||
{
|
||||
Opers[Index] = new ShaderIrOperAbuf(Abuf, (Reg + Index) & 0xff);
|
||||
}
|
||||
|
||||
return Opers;
|
||||
}
|
||||
|
||||
public static ShaderIrOper GetAluOperANode_R(long OpCode)
|
||||
{
|
||||
return new ShaderIrOperReg((int)(OpCode >> 8) & 0xff);
|
||||
}
|
||||
|
||||
public static ShaderIrOper GetAluOperBNode_RR(long OpCode)
|
||||
{
|
||||
return new ShaderIrOperReg((int)(OpCode >> 20) & 0xff);
|
||||
}
|
||||
|
||||
public static ShaderIrOper GetAluOperBCNode_R(long OpCode)
|
||||
{
|
||||
return new ShaderIrOperReg((int)(OpCode >> 39) & 0xff);
|
||||
}
|
||||
|
||||
public static ShaderIrOper GetAluOperBCNode_C(long OpCode)
|
||||
{
|
||||
return new ShaderIrOperCbuf(
|
||||
(int)(OpCode >> 34) & 0x1f,
|
||||
(int)(OpCode >> 20) & 0x3fff);
|
||||
}
|
||||
|
||||
public static ShaderIrOper GetAluOperDNode(long OpCode)
|
||||
{
|
||||
return new ShaderIrOperReg((int)(OpCode >> 0) & 0xff);
|
||||
}
|
||||
|
||||
public static ShaderIrOper GetAluOperBNode_Imm(long OpCode)
|
||||
{
|
||||
//TODO
|
||||
return new ShaderIrOper();
|
||||
}
|
||||
}
|
||||
}
|
29
Ryujinx.Graphics/Gal/Shader/ShaderDecodeMem.cs
Normal file
29
Ryujinx.Graphics/Gal/Shader/ShaderDecodeMem.cs
Normal file
|
@ -0,0 +1,29 @@
|
|||
using static Ryujinx.Graphics.Gal.Shader.ShaderDecodeHelper;
|
||||
|
||||
namespace Ryujinx.Graphics.Gal.Shader
|
||||
{
|
||||
static partial class ShaderDecode
|
||||
{
|
||||
public static void Ld_A(ShaderIrBlock Block, long OpCode)
|
||||
{
|
||||
ShaderIrOper[] Opers = GetAluOperANode_A(OpCode);
|
||||
ShaderIrOper OperD = GetAluOperDNode(OpCode);
|
||||
|
||||
foreach (ShaderIrOper OperA in Opers)
|
||||
{
|
||||
Block.AddNode(new ShaderIrNode(OperD, OperA));
|
||||
}
|
||||
}
|
||||
|
||||
public static void St_A(ShaderIrBlock Block, long OpCode)
|
||||
{
|
||||
ShaderIrOper[] Opers = GetAluOperANode_A(OpCode);
|
||||
ShaderIrOper OperD = GetAluOperDNode(OpCode);
|
||||
|
||||
foreach (ShaderIrOper OperA in Opers)
|
||||
{
|
||||
Block.AddNode(new ShaderIrNode(OperA, OperD));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -23,6 +23,8 @@ namespace Ryujinx.Graphics.Gal.Shader
|
|||
Decode(Block, OpCode);
|
||||
}
|
||||
|
||||
Block.RunOptimizationPasses();
|
||||
|
||||
return Block;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,11 @@ namespace Ryujinx.Graphics.Gal.Shader
|
|||
Nodes.Add(Node);
|
||||
}
|
||||
|
||||
public void RunOptimizationPasses()
|
||||
{
|
||||
ShaderOptExprProp.Optimize(Nodes);
|
||||
}
|
||||
|
||||
public ShaderIrNode[] GetNodes()
|
||||
{
|
||||
return Nodes.ToArray();
|
||||
|
|
|
@ -4,9 +4,8 @@ namespace Ryujinx.Graphics.Gal.Shader
|
|||
{
|
||||
Fabs,
|
||||
Fadd,
|
||||
Ffma,
|
||||
Fmul,
|
||||
Fneg,
|
||||
Ld,
|
||||
St
|
||||
}
|
||||
}
|
|
@ -2,11 +2,13 @@ namespace Ryujinx.Graphics.Gal.Shader
|
|||
{
|
||||
class ShaderIrNode
|
||||
{
|
||||
public ShaderIrInst Inst;
|
||||
public ShaderIrOper Dst { get; set; }
|
||||
public ShaderIrOper Src { get; set; }
|
||||
|
||||
public ShaderIrNode(ShaderIrInst Inst)
|
||||
public ShaderIrNode(ShaderIrOper Dst, ShaderIrOper Src)
|
||||
{
|
||||
this.Inst = Inst;
|
||||
this.Dst = Dst;
|
||||
this.Src = Src;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
namespace Ryujinx.Graphics.Gal.Shader
|
||||
{
|
||||
class ShaderIrNodeLdr : ShaderIrNode
|
||||
{
|
||||
public int GprIndex { get; private set; }
|
||||
|
||||
public ShaderIrNodeLdr(int GprIndex) : base(ShaderIrInst.Ld)
|
||||
{
|
||||
this.GprIndex = GprIndex;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
namespace Ryujinx.Graphics.Gal.Shader
|
||||
{
|
||||
class ShaderIrNodeStr : ShaderIrNode
|
||||
{
|
||||
public int GprIndex { get; private set; }
|
||||
|
||||
public ShaderIrNodeStr(int GprIndex) : base(ShaderIrInst.St)
|
||||
{
|
||||
this.GprIndex = GprIndex;
|
||||
}
|
||||
}
|
||||
}
|
14
Ryujinx.Graphics/Gal/Shader/ShaderIrOperAbuf.cs
Normal file
14
Ryujinx.Graphics/Gal/Shader/ShaderIrOperAbuf.cs
Normal file
|
@ -0,0 +1,14 @@
|
|||
namespace Ryujinx.Graphics.Gal.Shader
|
||||
{
|
||||
class ShaderIrOperAbuf : ShaderIrOper
|
||||
{
|
||||
public int Offs { get; private set; }
|
||||
public int GprIndex { get; private set; }
|
||||
|
||||
public ShaderIrOperAbuf(int Offs, int GprIndex)
|
||||
{
|
||||
this.Offs = Offs;
|
||||
this.GprIndex = GprIndex;
|
||||
}
|
||||
}
|
||||
}
|
14
Ryujinx.Graphics/Gal/Shader/ShaderIrOperCbuf.cs
Normal file
14
Ryujinx.Graphics/Gal/Shader/ShaderIrOperCbuf.cs
Normal file
|
@ -0,0 +1,14 @@
|
|||
namespace Ryujinx.Graphics.Gal.Shader
|
||||
{
|
||||
class ShaderIrOperCbuf : ShaderIrOper
|
||||
{
|
||||
public int Index { get; private set; }
|
||||
public int Offs { get; private set; }
|
||||
|
||||
public ShaderIrOperCbuf(int Index, int Offs)
|
||||
{
|
||||
this.Index = Index;
|
||||
this.Offs = Offs;
|
||||
}
|
||||
}
|
||||
}
|
12
Ryujinx.Graphics/Gal/Shader/ShaderIrOperImm.cs
Normal file
12
Ryujinx.Graphics/Gal/Shader/ShaderIrOperImm.cs
Normal file
|
@ -0,0 +1,12 @@
|
|||
namespace Ryujinx.Graphics.Gal.Shader
|
||||
{
|
||||
class ShaderIrOperImm : ShaderIrOper
|
||||
{
|
||||
public int Imm { get; private set; }
|
||||
|
||||
public ShaderIrOperImm(int Imm)
|
||||
{
|
||||
this.Imm = Imm;
|
||||
}
|
||||
}
|
||||
}
|
12
Ryujinx.Graphics/Gal/Shader/ShaderIrOperImmf.cs
Normal file
12
Ryujinx.Graphics/Gal/Shader/ShaderIrOperImmf.cs
Normal file
|
@ -0,0 +1,12 @@
|
|||
namespace Ryujinx.Graphics.Gal.Shader
|
||||
{
|
||||
class ShaderIrOperImmf : ShaderIrOper
|
||||
{
|
||||
public float Imm { get; private set; }
|
||||
|
||||
public ShaderIrOperImmf(float Imm)
|
||||
{
|
||||
this.Imm = Imm;
|
||||
}
|
||||
}
|
||||
}
|
22
Ryujinx.Graphics/Gal/Shader/ShaderIrOperOp.cs
Normal file
22
Ryujinx.Graphics/Gal/Shader/ShaderIrOperOp.cs
Normal file
|
@ -0,0 +1,22 @@
|
|||
namespace Ryujinx.Graphics.Gal.Shader
|
||||
{
|
||||
class ShaderIrOperOp : ShaderIrOper
|
||||
{
|
||||
public ShaderIrInst Inst { get; private set; }
|
||||
public ShaderIrOper OperandA { get; set; }
|
||||
public ShaderIrOper OperandB { get; set; }
|
||||
public ShaderIrOper OperandC { get; set; }
|
||||
|
||||
public ShaderIrOperOp(
|
||||
ShaderIrInst Inst,
|
||||
ShaderIrOper OperandA = null,
|
||||
ShaderIrOper OperandB = null,
|
||||
ShaderIrOper OperandC = null)
|
||||
{
|
||||
this.Inst = Inst;
|
||||
this.OperandA = OperandA;
|
||||
this.OperandB = OperandB;
|
||||
this.OperandC = OperandC;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -23,6 +23,8 @@ namespace Ryujinx.Graphics.Gal.Shader
|
|||
Set("0101110001101x", ShaderDecode.Fmul_R);
|
||||
Set("0100110001101x", ShaderDecode.Fmul_C);
|
||||
Set("0011100x01101x", ShaderDecode.Fmul_Imm);
|
||||
Set("1110111111011x", ShaderDecode.Ld_A);
|
||||
Set("1110111111110x", ShaderDecode.St_A);
|
||||
#endregion
|
||||
}
|
||||
|
||||
|
|
152
Ryujinx.Graphics/Gal/Shader/ShaderOptExprProp.cs
Normal file
152
Ryujinx.Graphics/Gal/Shader/ShaderOptExprProp.cs
Normal file
|
@ -0,0 +1,152 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ryujinx.Graphics.Gal.Shader
|
||||
{
|
||||
static class ShaderOptExprProp
|
||||
{
|
||||
private struct UseSite
|
||||
{
|
||||
public object Parent;
|
||||
|
||||
public int OperIndex;
|
||||
|
||||
public UseSite(object Parent, int OperIndex)
|
||||
{
|
||||
this.Parent = Parent;
|
||||
this.OperIndex = OperIndex;
|
||||
}
|
||||
}
|
||||
|
||||
private class RegUse
|
||||
{
|
||||
public ShaderIrNode Node { get; private set; }
|
||||
|
||||
private List<UseSite> Sites;
|
||||
|
||||
public RegUse()
|
||||
{
|
||||
Sites = new List<UseSite>();
|
||||
}
|
||||
|
||||
public void AddUseSite(UseSite Site)
|
||||
{
|
||||
Sites.Add(Site);
|
||||
}
|
||||
|
||||
public bool TryPropagate()
|
||||
{
|
||||
//If the use count of the register is more than 1,
|
||||
//then propagating the expression is not worth it,
|
||||
//because the code will be larger, harder to read,
|
||||
//and less efficient due to the common sub-expression being
|
||||
//propagated.
|
||||
if (Sites.Count == 1 || !(Node.Src is ShaderIrOperOp))
|
||||
{
|
||||
foreach (UseSite Site in Sites)
|
||||
{
|
||||
if (Site.Parent is ShaderIrOperOp Op)
|
||||
{
|
||||
switch (Site.OperIndex)
|
||||
{
|
||||
case 0: Op.OperandA = Node.Src; break;
|
||||
case 1: Op.OperandB = Node.Src; break;
|
||||
case 2: Op.OperandC = Node.Src; break;
|
||||
|
||||
default: throw new InvalidOperationException();
|
||||
}
|
||||
}
|
||||
else if (Site.Parent is ShaderIrNode SiteNode)
|
||||
{
|
||||
SiteNode.Src = Node.Src;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return Sites.Count == 0;
|
||||
}
|
||||
|
||||
public void SetNewAsg(ShaderIrNode Node)
|
||||
{
|
||||
this.Node = Node;
|
||||
|
||||
Sites.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public static void Optimize(List<ShaderIrNode> Nodes)
|
||||
{
|
||||
Dictionary<int, RegUse> Uses = new Dictionary<int, RegUse>();
|
||||
|
||||
RegUse GetRegUse(int GprIndex)
|
||||
{
|
||||
RegUse Use;
|
||||
|
||||
if (!Uses.TryGetValue(GprIndex, out Use))
|
||||
{
|
||||
Use = new RegUse();
|
||||
|
||||
Uses.Add(GprIndex, Use);
|
||||
}
|
||||
|
||||
return Use;
|
||||
}
|
||||
|
||||
void TryAddRegUse(object Parent, ShaderIrOper Oper, int OperIndex = 0)
|
||||
{
|
||||
if (Oper is ShaderIrOperOp Op)
|
||||
{
|
||||
TryAddRegUse(Op, Op.OperandA, 0);
|
||||
TryAddRegUse(Op, Op.OperandB, 1);
|
||||
TryAddRegUse(Op, Op.OperandC, 2);
|
||||
}
|
||||
else if (Oper is ShaderIrOperReg Reg && Reg.GprIndex != 0xff)
|
||||
{
|
||||
GetRegUse(Reg.GprIndex).AddUseSite(new UseSite(Parent, OperIndex));
|
||||
}
|
||||
}
|
||||
|
||||
for (int Index = 0; Index < Nodes.Count; Index++)
|
||||
{
|
||||
ShaderIrNode Node = Nodes[Index];
|
||||
|
||||
if (Node.Src is ShaderIrOperOp Op)
|
||||
{
|
||||
TryAddRegUse(Node, Op);
|
||||
}
|
||||
else if (Node.Src is ShaderIrOperReg)
|
||||
{
|
||||
TryAddRegUse(Node, Node.Src);
|
||||
}
|
||||
|
||||
if (Node.Dst is ShaderIrOperReg Reg && Reg.GprIndex != 0xff)
|
||||
{
|
||||
RegUse Use = GetRegUse(Reg.GprIndex);
|
||||
|
||||
if (Use.Node != null && Use.TryPropagate())
|
||||
{
|
||||
Nodes.Remove(Use.Node);
|
||||
|
||||
Index--;
|
||||
}
|
||||
|
||||
Use.SetNewAsg(Node);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (RegUse Use in Uses.Values)
|
||||
{
|
||||
if (Use.TryPropagate())
|
||||
{
|
||||
Nodes.Remove(Use.Node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,3 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ryujinx.Graphics.Gal.Shader
|
||||
{
|
||||
public static class ShaderTest
|
||||
|
@ -26,25 +29,123 @@ namespace Ryujinx.Graphics.Gal.Shader
|
|||
|
||||
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($"{GetOutOperName(Node.Dst)} = {GetInOperName(Node.Src, true)}");
|
||||
}
|
||||
|
||||
System.Console.WriteLine("Test code finished!");
|
||||
}
|
||||
|
||||
private static string GetOutOperName(ShaderIrOper Oper)
|
||||
{
|
||||
switch (Oper)
|
||||
{
|
||||
case ShaderIrOperAbuf Abuf: return GetOAbufName(Abuf);
|
||||
case ShaderIrOperReg Reg: return GetRegName(Reg);
|
||||
|
||||
default: throw new ArgumentException(nameof(Oper));
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetInOperName(ShaderIrOper Oper, bool Entry = false)
|
||||
{
|
||||
switch (Oper)
|
||||
{
|
||||
case ShaderIrOperAbuf Abuf: return GetIAbufName(Abuf);
|
||||
case ShaderIrOperCbuf Cbuf: return GetCbufName(Cbuf);
|
||||
case ShaderIrOperReg Reg: return GetRegName(Reg);
|
||||
case ShaderIrOperOp Op:
|
||||
string Expr;
|
||||
|
||||
if (InstsExpr.TryGetValue(Op.Inst, out GetInstExpr GetExpr))
|
||||
{
|
||||
Expr = GetExpr(Op);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotImplementedException(Op.Inst.ToString());
|
||||
}
|
||||
|
||||
if (!(Entry || IsUnary(Op.Inst)))
|
||||
{
|
||||
Expr = $"({Expr})";
|
||||
}
|
||||
|
||||
return Expr;
|
||||
|
||||
default: throw new ArgumentException(nameof(Oper));
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsUnary(ShaderIrInst Inst)
|
||||
{
|
||||
return Inst == ShaderIrInst.Fabs ||
|
||||
Inst == ShaderIrInst.Fneg;
|
||||
}
|
||||
|
||||
private static string GetOAbufName(ShaderIrOperAbuf Abuf)
|
||||
{
|
||||
return $"a_out[0x{Abuf.Offs:x} + {GetRegName(Abuf.GprIndex)}]";
|
||||
}
|
||||
|
||||
private static string GetIAbufName(ShaderIrOperAbuf Abuf)
|
||||
{
|
||||
return $"a_in[0x{Abuf.Offs:x} + {GetRegName(Abuf.GprIndex)}]";
|
||||
}
|
||||
|
||||
private static string GetCbufName(ShaderIrOperCbuf Cbuf)
|
||||
{
|
||||
return $"c{Cbuf.Index}[{Cbuf.Offs}]";
|
||||
}
|
||||
|
||||
private static string GetRegName(ShaderIrOperReg Reg)
|
||||
{
|
||||
return GetRegName(Reg.GprIndex);
|
||||
}
|
||||
|
||||
private static string GetRegName(int GprIndex)
|
||||
{
|
||||
return GprIndex == 0xff ? "0" : $"r{GprIndex}";
|
||||
}
|
||||
|
||||
private delegate string GetInstExpr(ShaderIrOperOp Op);
|
||||
|
||||
private static Dictionary<ShaderIrInst, GetInstExpr> InstsExpr = new
|
||||
Dictionary<ShaderIrInst, GetInstExpr>()
|
||||
{
|
||||
{ ShaderIrInst.Fabs, GetFabsExpr },
|
||||
{ ShaderIrInst.Fadd, GetFaddExpr },
|
||||
{ ShaderIrInst.Ffma, GetFfmaExpr },
|
||||
{ ShaderIrInst.Fmul, GetFmulExpr },
|
||||
{ ShaderIrInst.Fneg, GetFnegExpr },
|
||||
};
|
||||
|
||||
private static string GetFabsExpr(ShaderIrOperOp Op)
|
||||
{
|
||||
return $"abs({GetInOperName(Op.OperandA)})";
|
||||
}
|
||||
|
||||
private static string GetFaddExpr(ShaderIrOperOp Op)
|
||||
{
|
||||
return $"{GetInOperName(Op.OperandA)} + " +
|
||||
$"{GetInOperName(Op.OperandB)}";
|
||||
}
|
||||
|
||||
private static string GetFfmaExpr(ShaderIrOperOp Op)
|
||||
{
|
||||
return $"{GetInOperName(Op.OperandA)} * " +
|
||||
$"{GetInOperName(Op.OperandB)} + " +
|
||||
$"{GetInOperName(Op.OperandC)}";
|
||||
}
|
||||
|
||||
private static string GetFmulExpr(ShaderIrOperOp Op)
|
||||
{
|
||||
return $"{GetInOperName(Op.OperandA)} * " +
|
||||
$"{GetInOperName(Op.OperandB)}";
|
||||
}
|
||||
|
||||
private static string GetFnegExpr(ShaderIrOperOp Op)
|
||||
{
|
||||
return $"-{GetInOperName(Op.OperandA)}";
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue