Implement SSY/SYNC shader instructions (#382)

* Use a program counter to control shaders' flow

* Cleanup

* Implement SSY/SYNC

* Address feedback

* Fixup commentary

* Fixup Ssy instruction
This commit is contained in:
ReinUsesLisp 2018-08-31 13:14:04 -03:00 committed by gdkchan
parent 7cb6fd8090
commit 42dc925c3d
11 changed files with 313 additions and 268 deletions

View file

@ -43,9 +43,13 @@ namespace Ryujinx.Graphics.Gal.Shader
public const string FlipUniformName = "flip"; public const string FlipUniformName = "flip";
public const string InstanceUniformName = "instance"; public const string InstanceUniformName = "instance";
public const string ProgramName = "program"; public const string BasicBlockName = "bb";
public const string ProgramAName = ProgramName + "_a"; public const string BasicBlockAName = BasicBlockName + "_a";
public const string ProgramBName = ProgramName + "_b"; public const string BasicBlockBName = BasicBlockName + "_b";
public const int SsyStackSize = 16;
public const string SsyStackName = "ssy_stack";
public const string SsyCursorName = "ssy_cursor";
private string[] StagePrefixes = new string[] { "vp", "tcp", "tep", "gp", "fp" }; private string[] StagePrefixes = new string[] { "vp", "tcp", "tep", "gp", "fp" };

View file

@ -155,18 +155,19 @@ namespace Ryujinx.Graphics.Gal.Shader
PrintDeclOutAttributes(); PrintDeclOutAttributes();
PrintDeclGprs(); PrintDeclGprs();
PrintDeclPreds(); PrintDeclPreds();
PrintDeclSsy();
if (BlocksB != null) if (BlocksB != null)
{ {
PrintBlockScope(Blocks[0], null, null, "void " + GlslDecl.ProgramAName + "()", IdentationStr); PrintBlockScope(Blocks, GlslDecl.BasicBlockAName);
SB.AppendLine(); SB.AppendLine();
PrintBlockScope(BlocksB[0], null, null, "void " + GlslDecl.ProgramBName + "()", IdentationStr); PrintBlockScope(BlocksB, GlslDecl.BasicBlockBName);
} }
else else
{ {
PrintBlockScope(Blocks[0], null, null, "void " + GlslDecl.ProgramName + "()", IdentationStr); PrintBlockScope(Blocks, GlslDecl.BasicBlockName);
} }
SB.AppendLine(); SB.AppendLine();
@ -357,6 +358,13 @@ namespace Ryujinx.Graphics.Gal.Shader
PrintDecls(Decl.Preds, "bool"); PrintDecls(Decl.Preds, "bool");
} }
private void PrintDeclSsy()
{
SB.AppendLine("uint " + GlslDecl.SsyCursorName + ";");
SB.AppendLine("uint " + GlslDecl.SsyStackName + "[" + GlslDecl.SsyStackSize + "];" + Environment.NewLine);
}
private void PrintDecls(IReadOnlyDictionary<int, ShaderDeclInfo> Dict, string CustomType = null, string Suffix = "") private void PrintDecls(IReadOnlyDictionary<int, ShaderDeclInfo> Dict, string CustomType = null, string Suffix = "")
{ {
foreach (ShaderDeclInfo DeclInfo in Dict.Values.OrderBy(DeclKeySelector)) foreach (ShaderDeclInfo DeclInfo in Dict.Values.OrderBy(DeclKeySelector))
@ -432,14 +440,16 @@ namespace Ryujinx.Graphics.Gal.Shader
} }
} }
SB.AppendLine(IdentationStr + "uint pc;");
if (BlocksB != null) if (BlocksB != null)
{ {
SB.AppendLine(IdentationStr + GlslDecl.ProgramAName + "();"); PrintProgram(Blocks, GlslDecl.BasicBlockAName);
SB.AppendLine(IdentationStr + GlslDecl.ProgramBName + "();"); PrintProgram(BlocksB, GlslDecl.BasicBlockBName);
} }
else else
{ {
SB.AppendLine(IdentationStr + GlslDecl.ProgramName + "();"); PrintProgram(Blocks, GlslDecl.BasicBlockName);
} }
if (Decl.ShaderType != GalShaderType.Geometry) if (Decl.ShaderType != GalShaderType.Geometry)
@ -477,6 +487,32 @@ namespace Ryujinx.Graphics.Gal.Shader
SB.AppendLine("}"); SB.AppendLine("}");
} }
private void PrintProgram(ShaderIrBlock[] Blocks, string Name)
{
const string Ident1 = IdentationStr;
const string Ident2 = Ident1 + IdentationStr;
const string Ident3 = Ident2 + IdentationStr;
const string Ident4 = Ident3 + IdentationStr;
SB.AppendLine(Ident1 + "pc = " + GetBlockPosition(Blocks[0]) + ";");
SB.AppendLine(Ident1 + "do {");
SB.AppendLine(Ident2 + "switch (pc) {");
foreach (ShaderIrBlock Block in Blocks)
{
string FunctionName = Block.Position.ToString("x8");
SB.AppendLine(Ident3 + "case 0x" + FunctionName + ": pc = " + Name + "_" + FunctionName + "(); break;");
}
SB.AppendLine(Ident3 + "default:");
SB.AppendLine(Ident4 + "pc = 0;");
SB.AppendLine(Ident4 + "break;");
SB.AppendLine(Ident2 + "}");
SB.AppendLine(Ident1 + "} while (pc != 0);");
}
private void PrintAttrToOutput(string Identation = IdentationStr) private void PrintAttrToOutput(string Identation = IdentationStr)
{ {
foreach (KeyValuePair<int, ShaderDeclInfo> KV in Decl.OutAttributes) foreach (KeyValuePair<int, ShaderDeclInfo> KV in Decl.OutAttributes)
@ -510,193 +546,145 @@ namespace Ryujinx.Graphics.Gal.Shader
} }
} }
private void PrintBlockScope( private void PrintBlockScope(ShaderIrBlock[] Blocks, string Name)
ShaderIrBlock Block,
ShaderIrBlock EndBlock,
ShaderIrBlock LoopBlock,
string ScopeName,
string Identation,
bool IsDoWhile = false)
{ {
string UpIdent = Identation.Substring(0, Identation.Length - IdentationStr.Length); foreach (ShaderIrBlock Block in Blocks)
{
SB.AppendLine("uint " + Name + "_" + Block.Position.ToString("x8") + "() {");
if (IsDoWhile) PrintNodes(Block, Block.GetNodes());
{
SB.AppendLine(UpIdent + "do {");
}
else
{
SB.AppendLine(UpIdent + ScopeName + " {");
}
while (Block != null && Block != EndBlock) SB.AppendLine("}" + Environment.NewLine);
{
ShaderIrNode[] Nodes = Block.GetNodes();
Block = PrintNodes(Block, EndBlock, LoopBlock, Identation, Nodes);
}
if (IsDoWhile)
{
SB.AppendLine(UpIdent + "} " + ScopeName + ";");
}
else
{
SB.AppendLine(UpIdent + "}");
} }
} }
private ShaderIrBlock PrintNodes( private void PrintNode(ShaderIrBlock Block, ShaderIrNode Node, string Identation)
ShaderIrBlock Block,
ShaderIrBlock EndBlock,
ShaderIrBlock LoopBlock,
string Identation,
params ShaderIrNode[] Nodes)
{ {
/* if (Node is ShaderIrCond Cond)
* Notes about control flow and if-else/loop generation:
* The code assumes that the program has sane control flow,
* that is, there's no jumps to a location after another jump or
* jump target (except for the end of an if-else block), and backwards
* jumps to a location before the last loop dominator.
* Such cases needs to be transformed on a step before the GLSL code
* generation to ensure that we have sane graphs to work with.
* TODO: Such transformation is not yet implemented.
*/
string NewIdent = Identation + IdentationStr;
ShaderIrBlock LoopTail = GetLoopTailBlock(Block);
if (LoopTail != null && LoopBlock != Block)
{ {
//Shoock! kuma shock! We have a loop here! string IfExpr = GetSrcExpr(Cond.Pred, true);
//The entire sequence needs to be inside a do-while block.
ShaderIrBlock LoopEnd = GetDownBlock(LoopTail);
PrintBlockScope(Block, LoopEnd, Block, "while (false)", NewIdent, IsDoWhile: true); if (Cond.Not)
{
IfExpr = "!(" + IfExpr + ")";
}
return LoopEnd; SB.AppendLine(Identation + "if (" + IfExpr + ") {");
if (Cond.Child is ShaderIrOp Op && Op.Inst == ShaderIrInst.Bra)
{
SB.AppendLine(Identation + IdentationStr + "return " + GetBlockPosition(Block.Branch) + ";");
}
else
{
PrintNode(Block, Cond.Child, Identation + IdentationStr);
}
SB.AppendLine(Identation + "}");
} }
else if (Node is ShaderIrAsg Asg)
foreach (ShaderIrNode Node in Nodes)
{ {
if (Node is ShaderIrCond Cond) if (IsValidOutOper(Asg.Dst))
{ {
string IfExpr = GetSrcExpr(Cond.Pred, true); string Expr = GetSrcExpr(Asg.Src, true);
if (Cond.Not) Expr = GetExprWithCast(Asg.Dst, Asg.Src, Expr);
{
IfExpr = "!(" + IfExpr + ")";
}
if (Cond.Child is ShaderIrOp Op && Op.Inst == ShaderIrInst.Bra) SB.AppendLine(Identation + GetDstOperName(Asg.Dst) + " = " + Expr + ";");
{
//Branch is a loop branch and would result in infinite recursion.
if (Block.Branch.Position <= Block.Position)
{
SB.AppendLine(Identation + "if (" + IfExpr + ") {");
SB.AppendLine(Identation + IdentationStr + "continue;");
SB.AppendLine(Identation + "}");
continue;
}
string SubScopeName = "if (!" + IfExpr + ")";
PrintBlockScope(Block.Next, Block.Branch, LoopBlock, SubScopeName, NewIdent);
ShaderIrBlock IfElseEnd = GetUpBlock(Block.Branch).Branch;
if (IfElseEnd?.Position > Block.Branch.Position)
{
PrintBlockScope(Block.Branch, IfElseEnd, LoopBlock, "else", NewIdent);
return IfElseEnd;
}
return Block.Branch;
}
else
{
SB.AppendLine(Identation + "if (" + IfExpr + ") {");
PrintNodes(Block, EndBlock, LoopBlock, NewIdent, Cond.Child);
SB.AppendLine(Identation + "}");
}
} }
else if (Node is ShaderIrAsg Asg) }
else if (Node is ShaderIrOp Op)
{
switch (Op.Inst)
{ {
if (IsValidOutOper(Asg.Dst)) case ShaderIrInst.Bra:
{ {
string Expr = GetSrcExpr(Asg.Src, true); SB.AppendLine(Identation + "return " + GetBlockPosition(Block.Branch) + ";");
Expr = GetExprWithCast(Asg.Dst, Asg.Src, Expr); break;
}
SB.AppendLine(Identation + GetDstOperName(Asg.Dst) + " = " + Expr + ";"); case ShaderIrInst.Emit:
}
}
else if (Node is ShaderIrOp Op)
{
if (Op.Inst == ShaderIrInst.Bra)
{
if (Block.Branch.Position <= Block.Position)
{
SB.AppendLine(Identation + "continue;");
}
}
else if (Op.Inst == ShaderIrInst.Emit)
{ {
PrintAttrToOutput(Identation); PrintAttrToOutput(Identation);
SB.AppendLine(Identation + "EmitVertex();"); SB.AppendLine(Identation + "EmitVertex();");
break;
} }
else
case ShaderIrInst.Ssy:
{ {
string StackIndex = GlslDecl.SsyStackName + "[" + GlslDecl.SsyCursorName + "]";
int TargetPosition = (Op.OperandA as ShaderIrOperImm).Value;
string Target = "0x" + TargetPosition.ToString("x8") + "u";
SB.AppendLine(Identation + StackIndex + " = " + Target + ";");
SB.AppendLine(Identation + GlslDecl.SsyCursorName + "++;");
break;
}
case ShaderIrInst.Sync:
{
SB.AppendLine(Identation + GlslDecl.SsyCursorName + "--;");
string Target = GlslDecl.SsyStackName + "[" + GlslDecl.SsyCursorName + "]";
SB.AppendLine(Identation + "return " + Target + ";");
break;
}
default:
SB.AppendLine(Identation + GetSrcExpr(Op, true) + ";"); SB.AppendLine(Identation + GetSrcExpr(Op, true) + ";");
} break;
}
else if (Node is ShaderIrCmnt Cmnt)
{
SB.AppendLine(Identation + "// " + Cmnt.Comment);
}
else
{
throw new InvalidOperationException();
} }
} }
else if (Node is ShaderIrCmnt Cmnt)
return Block.Next;
}
private ShaderIrBlock GetUpBlock(ShaderIrBlock Block)
{
return Blocks.FirstOrDefault(x => x.EndPosition == Block.Position);
}
private ShaderIrBlock GetDownBlock(ShaderIrBlock Block)
{
return Blocks.FirstOrDefault(x => x.Position == Block.EndPosition);
}
private ShaderIrBlock GetLoopTailBlock(ShaderIrBlock LoopHead)
{
ShaderIrBlock Tail = null;
foreach (ShaderIrBlock Block in LoopHead.Sources)
{ {
if (Block.Position >= LoopHead.Position) SB.AppendLine(Identation + "// " + Cmnt.Comment);
{ }
if (Tail == null || Tail.Position < Block.Position) else
{ {
Tail = Block; throw new InvalidOperationException();
} }
} }
private void PrintNodes(ShaderIrBlock Block, ShaderIrNode[] Nodes)
{
foreach (ShaderIrNode Node in Nodes)
{
PrintNode(Block, Node, IdentationStr);
} }
return Tail; if (Nodes.Length > 0)
{
ShaderIrNode Last = Nodes[Nodes.Length - 1];
bool UnconditionalFlowChange = false;
if (Last is ShaderIrOp Op)
{
switch (Op.Inst)
{
case ShaderIrInst.Bra:
case ShaderIrInst.Exit:
case ShaderIrInst.Kil:
case ShaderIrInst.Sync:
UnconditionalFlowChange = true;
break;
}
}
if (!UnconditionalFlowChange)
{
SB.AppendLine(IdentationStr + "return " + GetBlockPosition(Block.Next) + ";");
}
}
} }
private bool IsValidOutOper(ShaderIrNode Node) private bool IsValidOutOper(ShaderIrNode Node)
@ -1006,7 +994,7 @@ namespace Ryujinx.Graphics.Gal.Shader
private string GetCnumExpr(ShaderIrOp Op) => GetUnaryCall(Op, "!isnan"); private string GetCnumExpr(ShaderIrOp Op) => GetUnaryCall(Op, "!isnan");
private string GetExitExpr(ShaderIrOp Op) => "return"; private string GetExitExpr(ShaderIrOp Op) => "return 0u";
private string GetFcosExpr(ShaderIrOp Op) => GetUnaryCall(Op, "cos"); private string GetFcosExpr(ShaderIrOp Op) => GetUnaryCall(Op, "cos");
@ -1351,5 +1339,17 @@ namespace Ryujinx.Graphics.Gal.Shader
throw new ArgumentException(nameof(Node)); throw new ArgumentException(nameof(Node));
} }
private static string GetBlockPosition(ShaderIrBlock Block)
{
if (Block != null)
{
return "0x" + Block.Position.ToString("x8") + "u";
}
else
{
return "0u";
}
}
} }
} }

View file

@ -1,4 +1,4 @@
namespace Ryujinx.Graphics.Gal.Shader namespace Ryujinx.Graphics.Gal.Shader
{ {
delegate void ShaderDecodeFunc(ShaderIrBlock Block, long OpCode); delegate void ShaderDecodeFunc(ShaderIrBlock Block, long OpCode, long Position);
} }

View file

@ -6,32 +6,32 @@ namespace Ryujinx.Graphics.Gal.Shader
{ {
static partial class ShaderDecode static partial class ShaderDecode
{ {
public static void Bfe_C(ShaderIrBlock Block, long OpCode) public static void Bfe_C(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitBfe(Block, OpCode, ShaderOper.CR); EmitBfe(Block, OpCode, ShaderOper.CR);
} }
public static void Bfe_I(ShaderIrBlock Block, long OpCode) public static void Bfe_I(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitBfe(Block, OpCode, ShaderOper.Imm); EmitBfe(Block, OpCode, ShaderOper.Imm);
} }
public static void Bfe_R(ShaderIrBlock Block, long OpCode) public static void Bfe_R(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitBfe(Block, OpCode, ShaderOper.RR); EmitBfe(Block, OpCode, ShaderOper.RR);
} }
public static void Fadd_C(ShaderIrBlock Block, long OpCode) public static void Fadd_C(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitFadd(Block, OpCode, ShaderOper.CR); EmitFadd(Block, OpCode, ShaderOper.CR);
} }
public static void Fadd_I(ShaderIrBlock Block, long OpCode) public static void Fadd_I(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitFadd(Block, OpCode, ShaderOper.Immf); EmitFadd(Block, OpCode, ShaderOper.Immf);
} }
public static void Fadd_I32(ShaderIrBlock Block, long OpCode) public static void Fadd_I32(ShaderIrBlock Block, long OpCode, long Position)
{ {
ShaderIrNode OperA = GetOperGpr8 (OpCode); ShaderIrNode OperA = GetOperGpr8 (OpCode);
ShaderIrNode OperB = GetOperImmf32_20(OpCode); ShaderIrNode OperB = GetOperImmf32_20(OpCode);
@ -49,47 +49,47 @@ namespace Ryujinx.Graphics.Gal.Shader
Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Op), OpCode)); Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Op), OpCode));
} }
public static void Fadd_R(ShaderIrBlock Block, long OpCode) public static void Fadd_R(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitFadd(Block, OpCode, ShaderOper.RR); EmitFadd(Block, OpCode, ShaderOper.RR);
} }
public static void Ffma_CR(ShaderIrBlock Block, long OpCode) public static void Ffma_CR(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitFfma(Block, OpCode, ShaderOper.CR); EmitFfma(Block, OpCode, ShaderOper.CR);
} }
public static void Ffma_I(ShaderIrBlock Block, long OpCode) public static void Ffma_I(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitFfma(Block, OpCode, ShaderOper.Immf); EmitFfma(Block, OpCode, ShaderOper.Immf);
} }
public static void Ffma_RC(ShaderIrBlock Block, long OpCode) public static void Ffma_RC(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitFfma(Block, OpCode, ShaderOper.RC); EmitFfma(Block, OpCode, ShaderOper.RC);
} }
public static void Ffma_RR(ShaderIrBlock Block, long OpCode) public static void Ffma_RR(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitFfma(Block, OpCode, ShaderOper.RR); EmitFfma(Block, OpCode, ShaderOper.RR);
} }
public static void Fmnmx_C(ShaderIrBlock Block, long OpCode) public static void Fmnmx_C(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitFmnmx(Block, OpCode, ShaderOper.CR); EmitFmnmx(Block, OpCode, ShaderOper.CR);
} }
public static void Fmnmx_I(ShaderIrBlock Block, long OpCode) public static void Fmnmx_I(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitFmnmx(Block, OpCode, ShaderOper.Immf); EmitFmnmx(Block, OpCode, ShaderOper.Immf);
} }
public static void Fmnmx_R(ShaderIrBlock Block, long OpCode) public static void Fmnmx_R(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitFmnmx(Block, OpCode, ShaderOper.RR); EmitFmnmx(Block, OpCode, ShaderOper.RR);
} }
public static void Fmul_I32(ShaderIrBlock Block, long OpCode) public static void Fmul_I32(ShaderIrBlock Block, long OpCode, long Position)
{ {
ShaderIrNode OperA = GetOperGpr8 (OpCode); ShaderIrNode OperA = GetOperGpr8 (OpCode);
ShaderIrNode OperB = GetOperImmf32_20(OpCode); ShaderIrNode OperB = GetOperImmf32_20(OpCode);
@ -99,62 +99,62 @@ namespace Ryujinx.Graphics.Gal.Shader
Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Op), OpCode)); Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Op), OpCode));
} }
public static void Fmul_C(ShaderIrBlock Block, long OpCode) public static void Fmul_C(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitFmul(Block, OpCode, ShaderOper.CR); EmitFmul(Block, OpCode, ShaderOper.CR);
} }
public static void Fmul_I(ShaderIrBlock Block, long OpCode) public static void Fmul_I(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitFmul(Block, OpCode, ShaderOper.Immf); EmitFmul(Block, OpCode, ShaderOper.Immf);
} }
public static void Fmul_R(ShaderIrBlock Block, long OpCode) public static void Fmul_R(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitFmul(Block, OpCode, ShaderOper.RR); EmitFmul(Block, OpCode, ShaderOper.RR);
} }
public static void Fset_C(ShaderIrBlock Block, long OpCode) public static void Fset_C(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitFset(Block, OpCode, ShaderOper.CR); EmitFset(Block, OpCode, ShaderOper.CR);
} }
public static void Fset_I(ShaderIrBlock Block, long OpCode) public static void Fset_I(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitFset(Block, OpCode, ShaderOper.Immf); EmitFset(Block, OpCode, ShaderOper.Immf);
} }
public static void Fset_R(ShaderIrBlock Block, long OpCode) public static void Fset_R(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitFset(Block, OpCode, ShaderOper.RR); EmitFset(Block, OpCode, ShaderOper.RR);
} }
public static void Fsetp_C(ShaderIrBlock Block, long OpCode) public static void Fsetp_C(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitFsetp(Block, OpCode, ShaderOper.CR); EmitFsetp(Block, OpCode, ShaderOper.CR);
} }
public static void Fsetp_I(ShaderIrBlock Block, long OpCode) public static void Fsetp_I(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitFsetp(Block, OpCode, ShaderOper.Immf); EmitFsetp(Block, OpCode, ShaderOper.Immf);
} }
public static void Fsetp_R(ShaderIrBlock Block, long OpCode) public static void Fsetp_R(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitFsetp(Block, OpCode, ShaderOper.RR); EmitFsetp(Block, OpCode, ShaderOper.RR);
} }
public static void Iadd_C(ShaderIrBlock Block, long OpCode) public static void Iadd_C(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitIadd(Block, OpCode, ShaderOper.CR); EmitIadd(Block, OpCode, ShaderOper.CR);
} }
public static void Iadd_I(ShaderIrBlock Block, long OpCode) public static void Iadd_I(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitIadd(Block, OpCode, ShaderOper.Imm); EmitIadd(Block, OpCode, ShaderOper.Imm);
} }
public static void Iadd_I32(ShaderIrBlock Block, long OpCode) public static void Iadd_I32(ShaderIrBlock Block, long OpCode, long Position)
{ {
ShaderIrNode OperA = GetOperGpr8 (OpCode); ShaderIrNode OperA = GetOperGpr8 (OpCode);
ShaderIrNode OperB = GetOperImm32_20(OpCode); ShaderIrNode OperB = GetOperImm32_20(OpCode);
@ -168,42 +168,42 @@ namespace Ryujinx.Graphics.Gal.Shader
Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Op), OpCode)); Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Op), OpCode));
} }
public static void Iadd_R(ShaderIrBlock Block, long OpCode) public static void Iadd_R(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitIadd(Block, OpCode, ShaderOper.RR); EmitIadd(Block, OpCode, ShaderOper.RR);
} }
public static void Iadd3_C(ShaderIrBlock Block, long OpCode) public static void Iadd3_C(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitIadd3(Block, OpCode, ShaderOper.CR); EmitIadd3(Block, OpCode, ShaderOper.CR);
} }
public static void Iadd3_I(ShaderIrBlock Block, long OpCode) public static void Iadd3_I(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitIadd3(Block, OpCode, ShaderOper.Imm); EmitIadd3(Block, OpCode, ShaderOper.Imm);
} }
public static void Iadd3_R(ShaderIrBlock Block, long OpCode) public static void Iadd3_R(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitIadd3(Block, OpCode, ShaderOper.RR); EmitIadd3(Block, OpCode, ShaderOper.RR);
} }
public static void Imnmx_C(ShaderIrBlock Block, long OpCode) public static void Imnmx_C(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitImnmx(Block, OpCode, ShaderOper.CR); EmitImnmx(Block, OpCode, ShaderOper.CR);
} }
public static void Imnmx_I(ShaderIrBlock Block, long OpCode) public static void Imnmx_I(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitImnmx(Block, OpCode, ShaderOper.Imm); EmitImnmx(Block, OpCode, ShaderOper.Imm);
} }
public static void Imnmx_R(ShaderIrBlock Block, long OpCode) public static void Imnmx_R(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitImnmx(Block, OpCode, ShaderOper.RR); EmitImnmx(Block, OpCode, ShaderOper.RR);
} }
public static void Ipa(ShaderIrBlock Block, long OpCode) public static void Ipa(ShaderIrBlock Block, long OpCode, long Position)
{ {
ShaderIrNode OperA = GetOperAbuf28(OpCode); ShaderIrNode OperA = GetOperAbuf28(OpCode);
ShaderIrNode OperB = GetOperGpr20 (OpCode); ShaderIrNode OperB = GetOperGpr20 (OpCode);
@ -213,52 +213,52 @@ namespace Ryujinx.Graphics.Gal.Shader
Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Op), OpCode)); Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Op), OpCode));
} }
public static void Iscadd_C(ShaderIrBlock Block, long OpCode) public static void Iscadd_C(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitIscadd(Block, OpCode, ShaderOper.CR); EmitIscadd(Block, OpCode, ShaderOper.CR);
} }
public static void Iscadd_I(ShaderIrBlock Block, long OpCode) public static void Iscadd_I(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitIscadd(Block, OpCode, ShaderOper.Imm); EmitIscadd(Block, OpCode, ShaderOper.Imm);
} }
public static void Iscadd_R(ShaderIrBlock Block, long OpCode) public static void Iscadd_R(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitIscadd(Block, OpCode, ShaderOper.RR); EmitIscadd(Block, OpCode, ShaderOper.RR);
} }
public static void Iset_C(ShaderIrBlock Block, long OpCode) public static void Iset_C(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitIset(Block, OpCode, ShaderOper.CR); EmitIset(Block, OpCode, ShaderOper.CR);
} }
public static void Iset_I(ShaderIrBlock Block, long OpCode) public static void Iset_I(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitIset(Block, OpCode, ShaderOper.Imm); EmitIset(Block, OpCode, ShaderOper.Imm);
} }
public static void Iset_R(ShaderIrBlock Block, long OpCode) public static void Iset_R(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitIset(Block, OpCode, ShaderOper.RR); EmitIset(Block, OpCode, ShaderOper.RR);
} }
public static void Isetp_C(ShaderIrBlock Block, long OpCode) public static void Isetp_C(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitIsetp(Block, OpCode, ShaderOper.CR); EmitIsetp(Block, OpCode, ShaderOper.CR);
} }
public static void Isetp_I(ShaderIrBlock Block, long OpCode) public static void Isetp_I(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitIsetp(Block, OpCode, ShaderOper.Imm); EmitIsetp(Block, OpCode, ShaderOper.Imm);
} }
public static void Isetp_R(ShaderIrBlock Block, long OpCode) public static void Isetp_R(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitIsetp(Block, OpCode, ShaderOper.RR); EmitIsetp(Block, OpCode, ShaderOper.RR);
} }
public static void Lop_I32(ShaderIrBlock Block, long OpCode) public static void Lop_I32(ShaderIrBlock Block, long OpCode, long Position)
{ {
int SubOp = (int)(OpCode >> 53) & 3; int SubOp = (int)(OpCode >> 53) & 3;
@ -292,22 +292,22 @@ namespace Ryujinx.Graphics.Gal.Shader
} }
} }
public static void Lop_C(ShaderIrBlock Block, long OpCode) public static void Lop_C(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitLop(Block, OpCode, ShaderOper.CR); EmitLop(Block, OpCode, ShaderOper.CR);
} }
public static void Lop_I(ShaderIrBlock Block, long OpCode) public static void Lop_I(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitLop(Block, OpCode, ShaderOper.Imm); EmitLop(Block, OpCode, ShaderOper.Imm);
} }
public static void Lop_R(ShaderIrBlock Block, long OpCode) public static void Lop_R(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitLop(Block, OpCode, ShaderOper.RR); EmitLop(Block, OpCode, ShaderOper.RR);
} }
public static void Mufu(ShaderIrBlock Block, long OpCode) public static void Mufu(ShaderIrBlock Block, long OpCode, long Position)
{ {
int SubOp = (int)(OpCode >> 20) & 0xf; int SubOp = (int)(OpCode >> 20) & 0xf;
@ -336,7 +336,7 @@ namespace Ryujinx.Graphics.Gal.Shader
Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Op), OpCode)); Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Op), OpCode));
} }
public static void Psetp(ShaderIrBlock Block, long OpCode) public static void Psetp(ShaderIrBlock Block, long OpCode, long Position)
{ {
bool NegA = ((OpCode >> 15) & 1) != 0; bool NegA = ((OpCode >> 15) & 1) != 0;
bool NegB = ((OpCode >> 32) & 1) != 0; bool NegB = ((OpCode >> 32) & 1) != 0;
@ -390,47 +390,47 @@ namespace Ryujinx.Graphics.Gal.Shader
Block.AddNode(GetPredNode(new ShaderIrAsg(P0Node, Op), OpCode)); Block.AddNode(GetPredNode(new ShaderIrAsg(P0Node, Op), OpCode));
} }
public static void Rro_C(ShaderIrBlock Block, long OpCode) public static void Rro_C(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitRro(Block, OpCode, ShaderOper.CR); EmitRro(Block, OpCode, ShaderOper.CR);
} }
public static void Rro_I(ShaderIrBlock Block, long OpCode) public static void Rro_I(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitRro(Block, OpCode, ShaderOper.Immf); EmitRro(Block, OpCode, ShaderOper.Immf);
} }
public static void Rro_R(ShaderIrBlock Block, long OpCode) public static void Rro_R(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitRro(Block, OpCode, ShaderOper.RR); EmitRro(Block, OpCode, ShaderOper.RR);
} }
public static void Shl_C(ShaderIrBlock Block, long OpCode) public static void Shl_C(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitAluBinary(Block, OpCode, ShaderOper.CR, ShaderIrInst.Lsl); EmitAluBinary(Block, OpCode, ShaderOper.CR, ShaderIrInst.Lsl);
} }
public static void Shl_I(ShaderIrBlock Block, long OpCode) public static void Shl_I(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitAluBinary(Block, OpCode, ShaderOper.Imm, ShaderIrInst.Lsl); EmitAluBinary(Block, OpCode, ShaderOper.Imm, ShaderIrInst.Lsl);
} }
public static void Shl_R(ShaderIrBlock Block, long OpCode) public static void Shl_R(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitAluBinary(Block, OpCode, ShaderOper.RR, ShaderIrInst.Lsl); EmitAluBinary(Block, OpCode, ShaderOper.RR, ShaderIrInst.Lsl);
} }
public static void Shr_C(ShaderIrBlock Block, long OpCode) public static void Shr_C(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitAluBinary(Block, OpCode, ShaderOper.CR, GetShrInst(OpCode)); EmitAluBinary(Block, OpCode, ShaderOper.CR, GetShrInst(OpCode));
} }
public static void Shr_I(ShaderIrBlock Block, long OpCode) public static void Shr_I(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitAluBinary(Block, OpCode, ShaderOper.Imm, GetShrInst(OpCode)); EmitAluBinary(Block, OpCode, ShaderOper.Imm, GetShrInst(OpCode));
} }
public static void Shr_R(ShaderIrBlock Block, long OpCode) public static void Shr_R(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitAluBinary(Block, OpCode, ShaderOper.RR, GetShrInst(OpCode)); EmitAluBinary(Block, OpCode, ShaderOper.RR, GetShrInst(OpCode));
} }
@ -442,7 +442,7 @@ namespace Ryujinx.Graphics.Gal.Shader
return Signed ? ShaderIrInst.Asr : ShaderIrInst.Lsr; return Signed ? ShaderIrInst.Asr : ShaderIrInst.Lsr;
} }
public static void Vmad(ShaderIrBlock Block, long OpCode) public static void Vmad(ShaderIrBlock Block, long OpCode, long Position)
{ {
ShaderIrNode OperA = GetOperGpr8(OpCode); ShaderIrNode OperA = GetOperGpr8(OpCode);
@ -477,22 +477,22 @@ namespace Ryujinx.Graphics.Gal.Shader
Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Final), OpCode)); Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Final), OpCode));
} }
public static void Xmad_CR(ShaderIrBlock Block, long OpCode) public static void Xmad_CR(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitXmad(Block, OpCode, ShaderOper.CR); EmitXmad(Block, OpCode, ShaderOper.CR);
} }
public static void Xmad_I(ShaderIrBlock Block, long OpCode) public static void Xmad_I(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitXmad(Block, OpCode, ShaderOper.Imm); EmitXmad(Block, OpCode, ShaderOper.Imm);
} }
public static void Xmad_RC(ShaderIrBlock Block, long OpCode) public static void Xmad_RC(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitXmad(Block, OpCode, ShaderOper.RC); EmitXmad(Block, OpCode, ShaderOper.RC);
} }
public static void Xmad_RR(ShaderIrBlock Block, long OpCode) public static void Xmad_RR(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitXmad(Block, OpCode, ShaderOper.RR); EmitXmad(Block, OpCode, ShaderOper.RR);
} }

View file

@ -6,7 +6,7 @@ namespace Ryujinx.Graphics.Gal.Shader
{ {
static partial class ShaderDecode static partial class ShaderDecode
{ {
public static void Bra(ShaderIrBlock Block, long OpCode) public static void Bra(ShaderIrBlock Block, long OpCode, long Position)
{ {
if ((OpCode & 0x20) != 0) if ((OpCode & 0x20) != 0)
{ {
@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Gal.Shader
Block.AddNode(GetPredNode(new ShaderIrOp(ShaderIrInst.Bra, Imm), OpCode)); Block.AddNode(GetPredNode(new ShaderIrOp(ShaderIrInst.Bra, Imm), OpCode));
} }
public static void Exit(ShaderIrBlock Block, long OpCode) public static void Exit(ShaderIrBlock Block, long OpCode, long Position)
{ {
int CCode = (int)OpCode & 0x1f; int CCode = (int)OpCode & 0x1f;
@ -34,9 +34,34 @@ namespace Ryujinx.Graphics.Gal.Shader
} }
public static void Kil(ShaderIrBlock Block, long OpCode) public static void Kil(ShaderIrBlock Block, long OpCode, long Position)
{ {
Block.AddNode(GetPredNode(new ShaderIrOp(ShaderIrInst.Kil), OpCode)); Block.AddNode(GetPredNode(new ShaderIrOp(ShaderIrInst.Kil), OpCode));
} }
public static void Ssy(ShaderIrBlock Block, long OpCode, long Position)
{
if ((OpCode & 0x20) != 0)
{
//This reads the target offset from the constant buffer.
//Almost impossible to support with GLSL.
throw new NotImplementedException();
}
int Offset = ((int)(OpCode >> 20) << 8) >> 8;
int Target = (int)(Position + Offset);
ShaderIrOperImm Imm = new ShaderIrOperImm(Target);
Block.AddNode(new ShaderIrOp(ShaderIrInst.Ssy, Imm));
}
public static void Sync(ShaderIrBlock Block, long OpCode, long Position)
{
//TODO: Implement Sync condition codes
Block.AddNode(GetPredNode(new ShaderIrOp(ShaderIrInst.Sync), OpCode));
}
} }
} }

View file

@ -31,7 +31,7 @@ namespace Ryujinx.Graphics.Gal.Shader
{ RGB_, RG_A, R_BA, _GBA, RGBA, ____, ____, ____ } { RGB_, RG_A, R_BA, _GBA, RGBA, ____, ____, ____ }
}; };
public static void Ld_A(ShaderIrBlock Block, long OpCode) public static void Ld_A(ShaderIrBlock Block, long OpCode, long Position)
{ {
ShaderIrNode[] Opers = GetOperAbuf20(OpCode); ShaderIrNode[] Opers = GetOperAbuf20(OpCode);
@ -50,7 +50,7 @@ namespace Ryujinx.Graphics.Gal.Shader
} }
} }
public static void Ld_C(ShaderIrBlock Block, long OpCode) public static void Ld_C(ShaderIrBlock Block, long OpCode, long Position)
{ {
int CbufPos = (int)(OpCode >> 22) & 0x3fff; int CbufPos = (int)(OpCode >> 22) & 0x3fff;
int CbufIndex = (int)(OpCode >> 36) & 0x1f; int CbufIndex = (int)(OpCode >> 36) & 0x1f;
@ -97,7 +97,7 @@ namespace Ryujinx.Graphics.Gal.Shader
} }
} }
public static void St_A(ShaderIrBlock Block, long OpCode) public static void St_A(ShaderIrBlock Block, long OpCode, long Position)
{ {
ShaderIrNode[] Opers = GetOperAbuf20(OpCode); ShaderIrNode[] Opers = GetOperAbuf20(OpCode);
@ -113,7 +113,7 @@ namespace Ryujinx.Graphics.Gal.Shader
} }
} }
public static void Texq(ShaderIrBlock Block, long OpCode) public static void Texq(ShaderIrBlock Block, long OpCode, long Position)
{ {
ShaderIrNode OperD = GetOperGpr0(OpCode); ShaderIrNode OperD = GetOperGpr0(OpCode);
ShaderIrNode OperA = GetOperGpr8(OpCode); ShaderIrNode OperA = GetOperGpr8(OpCode);
@ -132,12 +132,12 @@ namespace Ryujinx.Graphics.Gal.Shader
Block.AddNode(GetPredNode(new ShaderIrAsg(OperA, Op1), OpCode)); //Is this right? Block.AddNode(GetPredNode(new ShaderIrAsg(OperA, Op1), OpCode)); //Is this right?
} }
public static void Tex(ShaderIrBlock Block, long OpCode) public static void Tex(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitTex(Block, OpCode, GprHandle: false); EmitTex(Block, OpCode, GprHandle: false);
} }
public static void Tex_B(ShaderIrBlock Block, long OpCode) public static void Tex_B(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitTex(Block, OpCode, GprHandle: true); EmitTex(Block, OpCode, GprHandle: true);
} }
@ -202,12 +202,12 @@ namespace Ryujinx.Graphics.Gal.Shader
} }
} }
public static void Texs(ShaderIrBlock Block, long OpCode) public static void Texs(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitTexs(Block, OpCode, ShaderIrInst.Texs); EmitTexs(Block, OpCode, ShaderIrInst.Texs);
} }
public static void Tlds(ShaderIrBlock Block, long OpCode) public static void Tlds(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitTexs(Block, OpCode, ShaderIrInst.Txlf); EmitTexs(Block, OpCode, ShaderIrInst.Txlf);
} }

View file

@ -25,67 +25,67 @@ namespace Ryujinx.Graphics.Gal.Shader
F64 = 3 F64 = 3
} }
public static void F2f_C(ShaderIrBlock Block, long OpCode) public static void F2f_C(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitF2f(Block, OpCode, ShaderOper.CR); EmitF2f(Block, OpCode, ShaderOper.CR);
} }
public static void F2f_I(ShaderIrBlock Block, long OpCode) public static void F2f_I(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitF2f(Block, OpCode, ShaderOper.Immf); EmitF2f(Block, OpCode, ShaderOper.Immf);
} }
public static void F2f_R(ShaderIrBlock Block, long OpCode) public static void F2f_R(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitF2f(Block, OpCode, ShaderOper.RR); EmitF2f(Block, OpCode, ShaderOper.RR);
} }
public static void F2i_C(ShaderIrBlock Block, long OpCode) public static void F2i_C(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitF2i(Block, OpCode, ShaderOper.CR); EmitF2i(Block, OpCode, ShaderOper.CR);
} }
public static void F2i_I(ShaderIrBlock Block, long OpCode) public static void F2i_I(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitF2i(Block, OpCode, ShaderOper.Immf); EmitF2i(Block, OpCode, ShaderOper.Immf);
} }
public static void F2i_R(ShaderIrBlock Block, long OpCode) public static void F2i_R(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitF2i(Block, OpCode, ShaderOper.RR); EmitF2i(Block, OpCode, ShaderOper.RR);
} }
public static void I2f_C(ShaderIrBlock Block, long OpCode) public static void I2f_C(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitI2f(Block, OpCode, ShaderOper.CR); EmitI2f(Block, OpCode, ShaderOper.CR);
} }
public static void I2f_I(ShaderIrBlock Block, long OpCode) public static void I2f_I(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitI2f(Block, OpCode, ShaderOper.Imm); EmitI2f(Block, OpCode, ShaderOper.Imm);
} }
public static void I2f_R(ShaderIrBlock Block, long OpCode) public static void I2f_R(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitI2f(Block, OpCode, ShaderOper.RR); EmitI2f(Block, OpCode, ShaderOper.RR);
} }
public static void I2i_C(ShaderIrBlock Block, long OpCode) public static void I2i_C(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitI2i(Block, OpCode, ShaderOper.CR); EmitI2i(Block, OpCode, ShaderOper.CR);
} }
public static void I2i_I(ShaderIrBlock Block, long OpCode) public static void I2i_I(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitI2i(Block, OpCode, ShaderOper.Imm); EmitI2i(Block, OpCode, ShaderOper.Imm);
} }
public static void I2i_R(ShaderIrBlock Block, long OpCode) public static void I2i_R(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitI2i(Block, OpCode, ShaderOper.RR); EmitI2i(Block, OpCode, ShaderOper.RR);
} }
public static void Isberd(ShaderIrBlock Block, long OpCode) public static void Isberd(ShaderIrBlock Block, long OpCode, long Position)
{ {
//This instruction seems to be used to translate from an address to a vertex index in a GS //This instruction seems to be used to translate from an address to a vertex index in a GS
//Stub it as such //Stub it as such
@ -95,50 +95,50 @@ namespace Ryujinx.Graphics.Gal.Shader
Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), GetOperGpr8(OpCode)), OpCode)); Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), GetOperGpr8(OpCode)), OpCode));
} }
public static void Mov_C(ShaderIrBlock Block, long OpCode) public static void Mov_C(ShaderIrBlock Block, long OpCode, long Position)
{ {
ShaderIrOperCbuf Cbuf = GetOperCbuf34(OpCode); ShaderIrOperCbuf Cbuf = GetOperCbuf34(OpCode);
Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Cbuf), OpCode)); Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Cbuf), OpCode));
} }
public static void Mov_I(ShaderIrBlock Block, long OpCode) public static void Mov_I(ShaderIrBlock Block, long OpCode, long Position)
{ {
ShaderIrOperImm Imm = GetOperImm19_20(OpCode); ShaderIrOperImm Imm = GetOperImm19_20(OpCode);
Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Imm), OpCode)); Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Imm), OpCode));
} }
public static void Mov_I32(ShaderIrBlock Block, long OpCode) public static void Mov_I32(ShaderIrBlock Block, long OpCode, long Position)
{ {
ShaderIrOperImm Imm = GetOperImm32_20(OpCode); ShaderIrOperImm Imm = GetOperImm32_20(OpCode);
Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Imm), OpCode)); Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Imm), OpCode));
} }
public static void Mov_R(ShaderIrBlock Block, long OpCode) public static void Mov_R(ShaderIrBlock Block, long OpCode, long Position)
{ {
ShaderIrOperGpr Gpr = GetOperGpr20(OpCode); ShaderIrOperGpr Gpr = GetOperGpr20(OpCode);
Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Gpr), OpCode)); Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Gpr), OpCode));
} }
public static void Sel_C(ShaderIrBlock Block, long OpCode) public static void Sel_C(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitSel(Block, OpCode, ShaderOper.CR); EmitSel(Block, OpCode, ShaderOper.CR);
} }
public static void Sel_I(ShaderIrBlock Block, long OpCode) public static void Sel_I(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitSel(Block, OpCode, ShaderOper.Imm); EmitSel(Block, OpCode, ShaderOper.Imm);
} }
public static void Sel_R(ShaderIrBlock Block, long OpCode) public static void Sel_R(ShaderIrBlock Block, long OpCode, long Position)
{ {
EmitSel(Block, OpCode, ShaderOper.RR); EmitSel(Block, OpCode, ShaderOper.RR);
} }
public static void Mov_S(ShaderIrBlock Block, long OpCode) public static void Mov_S(ShaderIrBlock Block, long OpCode, long Position)
{ {
Block.AddNode(new ShaderIrCmnt("Stubbed.")); Block.AddNode(new ShaderIrCmnt("Stubbed."));

View file

@ -4,7 +4,7 @@ namespace Ryujinx.Graphics.Gal.Shader
{ {
static partial class ShaderDecode static partial class ShaderDecode
{ {
public static void Out_R(ShaderIrBlock Block, long OpCode) public static void Out_R(ShaderIrBlock Block, long OpCode, long Position)
{ {
//TODO: Those registers have to be used for something //TODO: Those registers have to be used for something
ShaderIrOperGpr Gpr0 = GetOperGpr0(OpCode); ShaderIrOperGpr Gpr0 = GetOperGpr0(OpCode);

View file

@ -50,17 +50,29 @@ namespace Ryujinx.Graphics.Gal.Shader
{ {
ShaderIrNode LastNode = Current.GetLastNode(); ShaderIrNode LastNode = Current.GetLastNode();
ShaderIrOp Op = GetInnermostOp(LastNode); ShaderIrOp InnerOp = GetInnermostOp(LastNode);
if (Op?.Inst == ShaderIrInst.Bra) if (InnerOp?.Inst == ShaderIrInst.Bra)
{ {
int Offset = ((ShaderIrOperImm)Op.OperandA).Value; int Offset = ((ShaderIrOperImm)InnerOp.OperandA).Value;
long Target = Current.EndPosition + Offset; long Target = Current.EndPosition + Offset;
Current.Branch = Enqueue(Target, Current); Current.Branch = Enqueue(Target, Current);
} }
foreach (ShaderIrNode Node in Current.Nodes)
{
if (Node is ShaderIrOp CurrOp && CurrOp.Inst == ShaderIrInst.Ssy)
{
int Offset = ((ShaderIrOperImm)CurrOp.OperandA).Value;
long Target = Offset;
Current.Branch = Enqueue(Target, Current);
}
}
if (NodeHasNext(LastNode)) if (NodeHasNext(LastNode))
{ {
Current.Next = Enqueue(Current.EndPosition); Current.Next = Enqueue(Current.EndPosition);
@ -157,7 +169,7 @@ namespace Ryujinx.Graphics.Gal.Shader
{ {
int Offset = ((int)(OpCode >> 20) << 8) >> 8; int Offset = ((int)(OpCode >> 20) << 8) >> 8;
long Target = Position + Offset; long Target = Position + Offset - Beginning;
DbgOpCode += " (0x" + Target.ToString("x16") + ")"; DbgOpCode += " (0x" + Target.ToString("x16") + ")";
} }
@ -170,7 +182,7 @@ namespace Ryujinx.Graphics.Gal.Shader
continue; continue;
} }
Decode(Block, OpCode); Decode(Block, OpCode, Position);
} }
while (!IsFlowChange(Block.GetLastNode())); while (!IsFlowChange(Block.GetLastNode()));

View file

@ -84,6 +84,8 @@ namespace Ryujinx.Graphics.Gal.Shader
Bra, Bra,
Exit, Exit,
Kil, Kil,
Ssy,
Sync,
Emit, Emit,
Cut Cut

View file

@ -112,7 +112,9 @@ namespace Ryujinx.Graphics.Gal.Shader
Set("0100110000101x", ShaderDecode.Shr_C); Set("0100110000101x", ShaderDecode.Shr_C);
Set("0011100x00101x", ShaderDecode.Shr_I); Set("0011100x00101x", ShaderDecode.Shr_I);
Set("0101110000101x", ShaderDecode.Shr_R); Set("0101110000101x", ShaderDecode.Shr_R);
Set("1110001010010x", ShaderDecode.Ssy);
Set("1110111111110x", ShaderDecode.St_A); Set("1110111111110x", ShaderDecode.St_A);
Set("1111000011111x", ShaderDecode.Sync);
Set("110000xxxx111x", ShaderDecode.Tex); Set("110000xxxx111x", ShaderDecode.Tex);
Set("1101111010111x", ShaderDecode.Tex_B); Set("1101111010111x", ShaderDecode.Tex_B);
Set("1101111101001x", ShaderDecode.Texq); Set("1101111101001x", ShaderDecode.Texq);