using System; namespace Ryujinx.Graphics.Gal.Shader { public class ShaderDecompiler { protected enum OperType { Bool, F32, I32 } protected static bool IsValidOutOper(ShaderIrNode Node) { if (Node is ShaderIrOperGpr Gpr && Gpr.IsConst) { return false; } else if (Node is ShaderIrOperPred Pred && Pred.IsConst) { return false; } return true; } protected static OperType GetDstNodeType(ShaderIrNode Node) { //Special case instructions with the result type different //from the input types (like integer <-> float conversion) here. if (Node is ShaderIrOp Op) { switch (Op.Inst) { case ShaderIrInst.Stof: case ShaderIrInst.Txlf: case ShaderIrInst.Utof: return OperType.F32; case ShaderIrInst.Ftos: case ShaderIrInst.Ftou: return OperType.I32; } } return GetSrcNodeType(Node); } protected static OperType GetSrcNodeType(ShaderIrNode Node) { switch (Node) { case ShaderIrOperAbuf Abuf: return Abuf.Offs == GlslDecl.VertexIdAttr || Abuf.Offs == GlslDecl.InstanceIdAttr ? OperType.I32 : OperType.F32; case ShaderIrOperCbuf Cbuf: return OperType.F32; case ShaderIrOperGpr Gpr: return OperType.F32; case ShaderIrOperImm Imm: return OperType.I32; case ShaderIrOperImmf Immf: return OperType.F32; case ShaderIrOperPred Pred: return OperType.Bool; case ShaderIrOp Op: if (Op.Inst > ShaderIrInst.B_Start && Op.Inst < ShaderIrInst.B_End) { return OperType.Bool; } else if (Op.Inst > ShaderIrInst.F_Start && Op.Inst < ShaderIrInst.F_End) { return OperType.F32; } else if (Op.Inst > ShaderIrInst.I_Start && Op.Inst < ShaderIrInst.I_End) { return OperType.I32; } break; } throw new ArgumentException(nameof(Node)); } protected static int DeclKeySelector(ShaderDeclInfo DeclInfo) { return DeclInfo.Cbuf << 24 | DeclInfo.Index; } } }