diff --git a/Ryujinx.Graphics/Gal/Shader/GlslDecl.cs b/Ryujinx.Graphics/Gal/Shader/GlslDecl.cs index a52c5934d2..c837632ec2 100644 --- a/Ryujinx.Graphics/Gal/Shader/GlslDecl.cs +++ b/Ryujinx.Graphics/Gal/Shader/GlslDecl.cs @@ -47,6 +47,10 @@ namespace Ryujinx.Graphics.Gal.Shader public const string BasicBlockAName = BasicBlockName + "_a"; 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 StagePrefix; diff --git a/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs b/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs index 031da8d517..104fd72354 100644 --- a/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs +++ b/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs @@ -155,6 +155,7 @@ namespace Ryujinx.Graphics.Gal.Shader PrintDeclOutAttributes(); PrintDeclGprs(); PrintDeclPreds(); + PrintDeclSsy(); if (BlocksB != null) { @@ -357,6 +358,13 @@ namespace Ryujinx.Graphics.Gal.Shader 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 Dict, string CustomType = null, string Suffix = "") { foreach (ShaderDeclInfo DeclInfo in Dict.Values.OrderBy(DeclKeySelector)) @@ -587,19 +595,53 @@ namespace Ryujinx.Graphics.Gal.Shader } else if (Node is ShaderIrOp Op) { - if (Op.Inst == ShaderIrInst.Bra) + switch (Op.Inst) { - SB.AppendLine(Identation + "return " + GetBlockPosition(Block.Branch) + ";"); - } - else if (Op.Inst == ShaderIrInst.Emit) - { - PrintAttrToOutput(Identation); + case ShaderIrInst.Bra: + { + SB.AppendLine(Identation + "return " + GetBlockPosition(Block.Branch) + ";"); - SB.AppendLine(Identation + "EmitVertex();"); - } - else - { - SB.AppendLine(Identation + GetSrcExpr(Op, true) + ";"); + break; + } + + case ShaderIrInst.Emit: + { + PrintAttrToOutput(Identation); + + SB.AppendLine(Identation + "EmitVertex();"); + + break; + } + + 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) + ";"); + break; } } else if (Node is ShaderIrCmnt Cmnt) @@ -632,6 +674,7 @@ namespace Ryujinx.Graphics.Gal.Shader case ShaderIrInst.Bra: case ShaderIrInst.Exit: case ShaderIrInst.Kil: + case ShaderIrInst.Sync: UnconditionalFlowChange = true; break; } diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecode.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecode.cs index ef0fd78bd3..73625f65fe 100644 --- a/Ryujinx.Graphics/Gal/Shader/ShaderDecode.cs +++ b/Ryujinx.Graphics/Gal/Shader/ShaderDecode.cs @@ -1,4 +1,4 @@ namespace Ryujinx.Graphics.Gal.Shader { - delegate void ShaderDecodeFunc(ShaderIrBlock Block, long OpCode); + delegate void ShaderDecodeFunc(ShaderIrBlock Block, long OpCode, long Position); } \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeAlu.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeAlu.cs index b60da7c1c3..5eb761dab6 100644 --- a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeAlu.cs +++ b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeAlu.cs @@ -6,32 +6,32 @@ namespace Ryujinx.Graphics.Gal.Shader { 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); } - 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); } - 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); } - 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); } - 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); } - 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 OperB = GetOperImmf32_20(OpCode); @@ -49,47 +49,47 @@ namespace Ryujinx.Graphics.Gal.Shader 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); } - 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); } - 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); } - 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); } - 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); } - 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); } - 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); } - 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); } - 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 OperB = GetOperImmf32_20(OpCode); @@ -99,62 +99,62 @@ namespace Ryujinx.Graphics.Gal.Shader 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); } - 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); } - 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); } - 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); } - 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); } - 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); } - 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); } - 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); } - 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); } - 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); } - 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); } - 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 OperB = GetOperImm32_20(OpCode); @@ -168,42 +168,42 @@ namespace Ryujinx.Graphics.Gal.Shader 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); } - 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); } - 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); } - 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); } - 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); } - 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); } - 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); } - public static void Ipa(ShaderIrBlock Block, long OpCode) + public static void Ipa(ShaderIrBlock Block, long OpCode, long Position) { ShaderIrNode OperA = GetOperAbuf28(OpCode); ShaderIrNode OperB = GetOperGpr20 (OpCode); @@ -213,52 +213,52 @@ namespace Ryujinx.Graphics.Gal.Shader 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); } - 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); } - 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); } - 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); } - 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); } - 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); } - 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); } - 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); } - 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); } - 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; @@ -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); } - 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); } - 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); } - public static void Mufu(ShaderIrBlock Block, long OpCode) + public static void Mufu(ShaderIrBlock Block, long OpCode, long Position) { int SubOp = (int)(OpCode >> 20) & 0xf; @@ -336,7 +336,7 @@ namespace Ryujinx.Graphics.Gal.Shader 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 NegB = ((OpCode >> 32) & 1) != 0; @@ -390,47 +390,47 @@ namespace Ryujinx.Graphics.Gal.Shader 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); } - 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); } - 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); } - 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); } - 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); } - 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); } - 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)); } - 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)); } - 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)); } @@ -442,7 +442,7 @@ namespace Ryujinx.Graphics.Gal.Shader 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); @@ -477,22 +477,22 @@ namespace Ryujinx.Graphics.Gal.Shader 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); } - 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); } - 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); } - 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); } diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeFlow.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeFlow.cs index 8d0925a321..b7e8a1bf1e 100644 --- a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeFlow.cs +++ b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeFlow.cs @@ -6,7 +6,7 @@ namespace Ryujinx.Graphics.Gal.Shader { 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) { @@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Gal.Shader 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; @@ -34,9 +34,27 @@ 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)); } + + public static void Ssy_I(ShaderIrBlock Block, long OpCode, long Position) + { + 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: Stop ignoring Sync branches + + Block.AddNode(GetPredNode(new ShaderIrOp(ShaderIrInst.Sync), OpCode)); + } } } \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMem.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMem.cs index a183b0c69a..2ae58bf89d 100644 --- a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMem.cs +++ b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMem.cs @@ -31,7 +31,7 @@ namespace Ryujinx.Graphics.Gal.Shader { 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); @@ -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 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); @@ -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 OperA = GetOperGpr8(OpCode); @@ -132,12 +132,12 @@ namespace Ryujinx.Graphics.Gal.Shader 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); } - 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); } @@ -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); } - public static void Tlds(ShaderIrBlock Block, long OpCode) + public static void Tlds(ShaderIrBlock Block, long OpCode, long Position) { EmitTexs(Block, OpCode, ShaderIrInst.Txlf); } diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMove.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMove.cs index c6b71fb01a..aef92c5a90 100644 --- a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMove.cs +++ b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMove.cs @@ -25,67 +25,67 @@ namespace Ryujinx.Graphics.Gal.Shader 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); } - 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); } - 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); } - 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); } - 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); } - 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); } - 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); } - 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); } - 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); } - 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); } - 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); } - 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); } - 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 //Stub it as such @@ -95,50 +95,50 @@ namespace Ryujinx.Graphics.Gal.Shader 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); 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); 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); 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); 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); } - 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); } - 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); } - 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.")); diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeSpecial.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeSpecial.cs index f1be005f9c..4300c32e32 100644 --- a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeSpecial.cs +++ b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeSpecial.cs @@ -4,7 +4,7 @@ namespace Ryujinx.Graphics.Gal.Shader { 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 ShaderIrOperGpr Gpr0 = GetOperGpr0(OpCode); diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecoder.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecoder.cs index 37db73478c..81d8f31268 100644 --- a/Ryujinx.Graphics/Gal/Shader/ShaderDecoder.cs +++ b/Ryujinx.Graphics/Gal/Shader/ShaderDecoder.cs @@ -50,17 +50,29 @@ namespace Ryujinx.Graphics.Gal.Shader { 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; 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)) { Current.Next = Enqueue(Current.EndPosition); @@ -170,7 +182,7 @@ namespace Ryujinx.Graphics.Gal.Shader continue; } - Decode(Block, OpCode); + Decode(Block, OpCode, Position); } while (!IsFlowChange(Block.GetLastNode())); diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderIrInst.cs b/Ryujinx.Graphics/Gal/Shader/ShaderIrInst.cs index d197835a7a..35dea61216 100644 --- a/Ryujinx.Graphics/Gal/Shader/ShaderIrInst.cs +++ b/Ryujinx.Graphics/Gal/Shader/ShaderIrInst.cs @@ -84,6 +84,8 @@ namespace Ryujinx.Graphics.Gal.Shader Bra, Exit, Kil, + Ssy, + Sync, Emit, Cut diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderOpCodeTable.cs b/Ryujinx.Graphics/Gal/Shader/ShaderOpCodeTable.cs index 95b8e467d2..7a4c5e550f 100644 --- a/Ryujinx.Graphics/Gal/Shader/ShaderOpCodeTable.cs +++ b/Ryujinx.Graphics/Gal/Shader/ShaderOpCodeTable.cs @@ -112,7 +112,9 @@ namespace Ryujinx.Graphics.Gal.Shader Set("0100110000101x", ShaderDecode.Shr_C); Set("0011100x00101x", ShaderDecode.Shr_I); Set("0101110000101x", ShaderDecode.Shr_R); + Set("1110001010010x", ShaderDecode.Ssy_I); Set("1110111111110x", ShaderDecode.St_A); + Set("1111000011111x", ShaderDecode.Sync); Set("110000xxxx111x", ShaderDecode.Tex); Set("1101111010111x", ShaderDecode.Tex_B); Set("1101111101001x", ShaderDecode.Texq);