Ejemplo n.º 1
0
        public static void Mov_C(ShaderIrBlock Block, long OpCode)
        {
            ShaderIrOperCbuf Cbuf = GetOperCbuf34(OpCode);

            Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Cbuf), OpCode));
        }
Ejemplo n.º 2
0
 public static void Fsetp_R(ShaderIrBlock Block, long OpCode, int Position)
 {
     EmitFsetp(Block, OpCode, ShaderOper.RR);
 }
Ejemplo n.º 3
0
 public static void Bfe_C(ShaderIrBlock Block, long OpCode, int Position)
 {
     EmitBfe(Block, OpCode, ShaderOper.CR);
 }
Ejemplo n.º 4
0
        private static void EmitSetp(ShaderIrBlock Block, long OpCode, bool IsFloat, ShaderOper Oper)
        {
            bool AbsA = OpCode.Read(7);
            bool NegP = OpCode.Read(42);
            bool NegA = OpCode.Read(43);
            bool AbsB = OpCode.Read(44);

            ShaderIrNode OperA = OpCode.Gpr8(), OperB;

            switch (Oper)
            {
            case ShaderOper.CR:   OperB = OpCode.Cbuf34();    break;

            case ShaderOper.Imm:  OperB = OpCode.Imm19_20();  break;

            case ShaderOper.Immf: OperB = OpCode.Immf19_20(); break;

            case ShaderOper.RR:   OperB = OpCode.Gpr20();     break;

            default: throw new ArgumentException(nameof(Oper));
            }

            ShaderIrInst CmpInst;

            if (IsFloat)
            {
                OperA = GetAluFabsFneg(OperA, AbsA, NegA);
                OperB = GetAluFabs(OperB, AbsB);

                CmpInst = OpCode.CmpF();
            }
            else
            {
                CmpInst = OpCode.Cmp();
            }

            ShaderIrOp Op = new ShaderIrOp(CmpInst, OperA, OperB);

            ShaderIrOperPred P0Node = OpCode.Pred3();
            ShaderIrOperPred P1Node = OpCode.Pred0();
            ShaderIrOperPred P2Node = OpCode.Pred39();

            Block.AddNode(OpCode.PredNode(new ShaderIrAsg(P0Node, Op)));

            ShaderIrInst LopInst = OpCode.BLop45();

            if (LopInst == ShaderIrInst.Band && P1Node.IsConst && P2Node.IsConst)
            {
                return;
            }

            ShaderIrNode P2NNode = P2Node;

            if (NegP)
            {
                P2NNode = new ShaderIrOp(ShaderIrInst.Bnot, P2NNode);
            }

            Op = new ShaderIrOp(ShaderIrInst.Bnot, P0Node);

            Op = new ShaderIrOp(LopInst, Op, P2NNode);

            Block.AddNode(OpCode.PredNode(new ShaderIrAsg(P1Node, Op)));

            Op = new ShaderIrOp(LopInst, P0Node, P2NNode);

            Block.AddNode(OpCode.PredNode(new ShaderIrAsg(P0Node, Op)));
        }
Ejemplo n.º 5
0
        private static void EmitXmad(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
        {
            //TODO: Confirm SignAB/C, it is just a guess.
            //TODO: Implement Mode 3 (CSFU), what it does?
            bool SignAB = OpCode.Read(48);
            bool SignC  = OpCode.Read(49);
            bool HighB  = OpCode.Read(52);
            bool HighA  = OpCode.Read(53);

            int Mode = OpCode.Read(50, 7);

            ShaderIrNode OperA = OpCode.Gpr8(), OperB, OperC;

            ShaderIrOperImm Imm16  = new ShaderIrOperImm(16);
            ShaderIrOperImm ImmMsk = new ShaderIrOperImm(0xffff);

            ShaderIrInst ShiftAB = SignAB ? ShaderIrInst.Asr : ShaderIrInst.Lsr;
            ShaderIrInst ShiftC  = SignC  ? ShaderIrInst.Asr : ShaderIrInst.Lsr;

            if (HighA)
            {
                OperA = new ShaderIrOp(ShiftAB, OperA, Imm16);
            }

            switch (Oper)
            {
            case ShaderOper.CR:  OperB = OpCode.Cbuf34();   break;

            case ShaderOper.Imm: OperB = OpCode.Imm19_20(); break;

            case ShaderOper.RC:  OperB = OpCode.Gpr39();    break;

            case ShaderOper.RR:  OperB = OpCode.Gpr20();    break;

            default: throw new ArgumentException(nameof(Oper));
            }

            bool ProductShiftLeft = false, Merge = false;

            if (Oper == ShaderOper.RC)
            {
                OperC = OpCode.Cbuf34();
            }
            else
            {
                OperC = OpCode.Gpr39();

                ProductShiftLeft = OpCode.Read(36);
                Merge            = OpCode.Read(37);
            }

            switch (Mode)
            {
            //CLO.
            case 1: OperC = ExtendTo32(OperC, SignC, 16); break;

            //CHI.
            case 2: OperC = new ShaderIrOp(ShiftC, OperC, Imm16); break;
            }

            ShaderIrNode OperBH = OperB;

            if (HighB)
            {
                OperBH = new ShaderIrOp(ShiftAB, OperBH, Imm16);
            }

            ShaderIrOp MulOp = new ShaderIrOp(ShaderIrInst.Mul, OperA, OperBH);

            if (ProductShiftLeft)
            {
                MulOp = new ShaderIrOp(ShaderIrInst.Lsl, MulOp, Imm16);
            }

            ShaderIrOp AddOp = new ShaderIrOp(ShaderIrInst.Add, MulOp, OperC);

            if (Merge)
            {
                AddOp = new ShaderIrOp(ShaderIrInst.And, AddOp, ImmMsk);
                OperB = new ShaderIrOp(ShaderIrInst.Lsl, OperB, Imm16);
                AddOp = new ShaderIrOp(ShaderIrInst.Or, AddOp, OperB);
            }

            if (Mode == 4)
            {
                OperB = new ShaderIrOp(ShaderIrInst.Lsl, OperB, Imm16);
                AddOp = new ShaderIrOp(ShaderIrInst.Or, AddOp, OperB);
            }

            Block.AddNode(OpCode.PredNode(new ShaderIrAsg(OpCode.Gpr0(), AddOp)));
        }
Ejemplo n.º 6
0
        private static void EmitTexs(ShaderIrBlock block,
                                     long opCode,
                                     ShaderIrInst inst,
                                     GalTextureTarget textureTarget,
                                     TextureInstructionSuffix textureInstructionSuffix)
        {
            if (inst == ShaderIrInst.Txlf && textureTarget == GalTextureTarget.CubeArray)
            {
                throw new InvalidOperationException("TLDS instructions cannot use CUBE modifier!");
            }

            bool isArray = ImageUtils.IsArray(textureTarget);

            ShaderIrOperGpr[] coords = new ShaderIrOperGpr[ImageUtils.GetCoordsCountTextureTarget(textureTarget)];

            ShaderIrOperGpr operA = opCode.Gpr8();
            ShaderIrOperGpr operB = opCode.Gpr20();

            ShaderIrOperGpr suffixExtra = opCode.Gpr20();

            suffixExtra.Index += 1;

            int coordStartIndex = 0;

            if (isArray)
            {
                coordStartIndex++;
                coords[coords.Length - 1] = opCode.Gpr8();
            }

            switch (coords.Length - coordStartIndex)
            {
            case 1:
                coords[0] = opCode.Gpr8();

                break;

            case 2:
                coords[0]        = opCode.Gpr8();
                coords[0].Index += coordStartIndex;

                break;

            case 3:
                coords[0]        = opCode.Gpr8();
                coords[0].Index += coordStartIndex;

                coords[1]        = opCode.Gpr8();
                coords[1].Index += 1 + coordStartIndex;

                break;

            default:
                throw new NotSupportedException($"{coords.Length - coordStartIndex} coords textures aren't supported in TEXS");
            }

            int operBIndex = 0;

            ShaderIrOperGpr levelOfDetail = null;
            ShaderIrOperGpr offset        = null;
            ShaderIrOperGpr depthCompare  = null;

            // OperB is always the last value
            // Not applicable to 1d textures
            if (coords.Length - coordStartIndex != 1)
            {
                coords[coords.Length - coordStartIndex - 1] = operB;
                operBIndex++;
            }

            // Encoding of TEXS/TLDS is a bit special and change for 2d textures
            // NOTE: OperA seems to hold at best two args.
            // On 2D textures, if no suffix need an additional values, Y is stored in OperB, otherwise coords are in OperA and the additional values is in OperB.
            if (textureInstructionSuffix != TextureInstructionSuffix.None && textureInstructionSuffix != TextureInstructionSuffix.Lz && textureTarget == GalTextureTarget.TwoD)
            {
                coords[coords.Length - coordStartIndex - 1]        = opCode.Gpr8();
                coords[coords.Length - coordStartIndex - 1].Index += coords.Length - coordStartIndex - 1;
                operBIndex--;
            }

            // TODO: Find what MZ does and what changes about the encoding (Maybe Multisample?)
            if ((textureInstructionSuffix & TextureInstructionSuffix.Ll) != 0)
            {
                levelOfDetail        = opCode.Gpr20();
                levelOfDetail.Index += operBIndex;
                operBIndex++;
            }

            if ((textureInstructionSuffix & TextureInstructionSuffix.AOffI) != 0)
            {
                offset        = opCode.Gpr20();
                offset.Index += operBIndex;
                operBIndex++;
            }

            if ((textureInstructionSuffix & TextureInstructionSuffix.Dc) != 0)
            {
                depthCompare        = opCode.Gpr20();
                depthCompare.Index += operBIndex;
                operBIndex++;
            }

            int lutIndex;

            lutIndex  = !opCode.Gpr0().IsConst  ? 1 : 0;
            lutIndex |= !opCode.Gpr28().IsConst ? 2 : 0;

            if (lutIndex == 0)
            {
                //Both destination registers are RZ, do nothing.
                return;
            }

            bool fp16 = !opCode.Read(59);

            int dstIncrement = 0;

            ShaderIrOperGpr GetDst()
            {
                ShaderIrOperGpr dst;

                if (fp16)
                {
                    //FP16 mode, two components are packed on the two
                    //halfs of a 32-bits register, as two half-float values.
                    int halfPart = dstIncrement & 1;

                    switch (lutIndex)
                    {
                    case 1: dst = opCode.GprHalf0(halfPart);  break;

                    case 2: dst = opCode.GprHalf28(halfPart); break;

                    case 3: dst = (dstIncrement >> 1) != 0
                            ? opCode.GprHalf28(halfPart)
                            : opCode.GprHalf0(halfPart); break;

                    default: throw new InvalidOperationException();
                    }
                }
                else
                {
                    //32-bits mode, each component uses one register.
                    //Two components uses two consecutive registers.
                    switch (lutIndex)
                    {
                    case 1: dst = opCode.Gpr0();  break;

                    case 2: dst = opCode.Gpr28(); break;

                    case 3: dst = (dstIncrement >> 1) != 0
                            ? opCode.Gpr28()
                            : opCode.Gpr0(); break;

                    default: throw new InvalidOperationException();
                    }

                    dst.Index += dstIncrement & 1;
                }

                dstIncrement++;

                return(dst);
            }

            int chMask = _maskLut[lutIndex, opCode.Read(50, 7)];

            if (chMask == 0)
            {
                //All channels are disabled, do nothing.
                return;
            }

            ShaderIrNode operC = opCode.Imm13_36();

            coords = CoordsRegistersToTempRegisters(block, coords);

            for (int ch = 0; ch < 4; ch++)
            {
                if (!IsChannelUsed(chMask, ch))
                {
                    continue;
                }

                ShaderIrMetaTex meta = new ShaderIrMetaTex(ch, textureTarget, textureInstructionSuffix, coords)
                {
                    LevelOfDetail = levelOfDetail,
                    Offset        = offset,
                    DepthCompare  = depthCompare
                };
                ShaderIrOp op = new ShaderIrOp(inst, operA, operB, operC, meta);

                ShaderIrOperGpr dst = GetDst();

                if (dst.IsValidRegister && !dst.IsConst)
                {
                    block.AddNode(opCode.PredNode(new ShaderIrAsg(dst, op)));
                }
            }
        }
Ejemplo n.º 7
0
        private ShaderIrBlock PrintNodes(
            ShaderIrBlock Block,
            ShaderIrBlock EndBlock,
            ShaderIrBlock LoopBlock,
            string Identation,
            params ShaderIrNode[] Nodes)
        {
            /*
             * 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!
                //The entire sequence needs to be inside a do-while block.
                ShaderIrBlock LoopEnd = GetDownBlock(LoopTail);

                PrintBlockScope(Block, LoopEnd, Block, "while (false)", NewIdent, IsDoWhile: true);

                return(LoopEnd);
            }

            foreach (ShaderIrNode Node in Nodes)
            {
                if (Node is ShaderIrCond Cond)
                {
                    string IfExpr = GetSrcExpr(Cond.Pred, true);

                    if (Cond.Not)
                    {
                        IfExpr = "!(" + IfExpr + ")";
                    }

                    if (Cond.Child is ShaderIrOp Op && Op.Inst == ShaderIrInst.Bra)
                    {
                        //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 + "}");
                    }
                }
Ejemplo n.º 8
0
 public static void Ffma_RR(ShaderIrBlock Block, long OpCode)
 {
     EmitAluFfma(Block, OpCode, ShaderOper.RR);
 }
Ejemplo n.º 9
0
 public static void Fmul_R(ShaderIrBlock Block, long OpCode)
 {
     EmitAluBinaryF(Block, OpCode, ShaderOper.RR, ShaderIrInst.Fmul);
 }
Ejemplo n.º 10
0
 public static void Shr_R(ShaderIrBlock Block, long OpCode)
 {
     EmitAluBinary(Block, OpCode, ShaderOper.RR, GetShrInst(OpCode));
 }
Ejemplo n.º 11
0
        private static void EmitSetp(ShaderIrBlock Block, long OpCode, bool IsFloat, ShaderOper Oper)
        {
            bool Aa = ((OpCode >> 7) & 1) != 0;
            bool Np = ((OpCode >> 42) & 1) != 0;
            bool Na = ((OpCode >> 43) & 1) != 0;
            bool Ab = ((OpCode >> 44) & 1) != 0;

            ShaderIrNode OperA = GetOperGpr8(OpCode), OperB;

            switch (Oper)
            {
            case ShaderOper.CR:   OperB = GetOperCbuf34(OpCode); break;

            case ShaderOper.Imm:  OperB = GetOperImm19_20(OpCode); break;

            case ShaderOper.Immf: OperB = GetOperImmf19_20(OpCode); break;

            case ShaderOper.RR:   OperB = GetOperGpr20(OpCode); break;

            default: throw new ArgumentException(nameof(Oper));
            }

            ShaderIrInst CmpInst;

            if (IsFloat)
            {
                OperA = GetAluAbsNeg(OperA, Aa, Na);
                OperB = GetAluAbs(OperB, Ab);

                CmpInst = GetCmpF(OpCode);
            }
            else
            {
                CmpInst = GetCmp(OpCode);
            }

            ShaderIrOp Op = new ShaderIrOp(CmpInst, OperA, OperB);

            ShaderIrOperPred P0Node = GetOperPred3(OpCode);
            ShaderIrOperPred P1Node = GetOperPred0(OpCode);
            ShaderIrOperPred P2Node = GetOperPred39(OpCode);

            Block.AddNode(GetPredNode(new ShaderIrAsg(P0Node, Op), OpCode));

            ShaderIrInst LopInst = GetBLop(OpCode);

            if (LopInst == ShaderIrInst.Band && P1Node.IsConst && P2Node.IsConst)
            {
                return;
            }

            ShaderIrNode P2NNode = P2Node;

            if (Np)
            {
                P2NNode = new ShaderIrOp(ShaderIrInst.Bnot, P2NNode);
            }

            Op = new ShaderIrOp(ShaderIrInst.Bnot, P0Node);

            Op = new ShaderIrOp(LopInst, Op, P2NNode);

            Block.AddNode(GetPredNode(new ShaderIrAsg(P1Node, Op), OpCode));

            Op = new ShaderIrOp(LopInst, P0Node, P2NNode);

            Block.AddNode(GetPredNode(new ShaderIrAsg(P0Node, Op), OpCode));
        }
Ejemplo n.º 12
0
 public static void Texs(ShaderIrBlock Block, long OpCode)
 {
     EmitTexs(Block, OpCode, ShaderIrInst.Texs);
 }
Ejemplo n.º 13
0
 public static void Tex(ShaderIrBlock Block, long OpCode)
 {
     EmitTex(Block, OpCode, GprHandle: false);
 }
Ejemplo n.º 14
0
        public static void Mov_I(ShaderIrBlock Block, long OpCode)
        {
            ShaderIrOperImm Imm = GetOperImm19_20(OpCode);

            Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Imm), OpCode));
        }
Ejemplo n.º 15
0
        private static void EmitTexs(ShaderIrBlock Block, long OpCode, ShaderIrInst Inst)
        {
            //TODO: Support other formats.
            ShaderIrNode OperA = OpCode.Gpr8();
            ShaderIrNode OperB = OpCode.Gpr20();
            ShaderIrNode OperC = OpCode.Imm13_36();

            int LutIndex;

            LutIndex  = OpCode.Gpr0().Index != ShaderIrOperGpr.ZRIndex ? 1 : 0;
            LutIndex |= OpCode.Gpr28().Index != ShaderIrOperGpr.ZRIndex ? 2 : 0;

            if (LutIndex == 0)
            {
                //Both registers are RZ, color is not written anywhere.
                //So, the intruction is basically a no-op.
                return;
            }

            int ChMask = MaskLut[LutIndex, OpCode.Read(50, 7)];

            for (int Ch = 0; Ch < 4; Ch++)
            {
                ShaderIrOperGpr Dst = new ShaderIrOperGpr(TempRegStart + Ch);

                ShaderIrMetaTex Meta = new ShaderIrMetaTex(Ch);

                ShaderIrOp Op = new ShaderIrOp(Inst, OperA, OperB, OperC, Meta);

                Block.AddNode(OpCode.PredNode(new ShaderIrAsg(Dst, Op)));
            }

            int RegInc = 0;

            ShaderIrOperGpr GetDst()
            {
                ShaderIrOperGpr Dst;

                switch (LutIndex)
                {
                case 1: Dst = OpCode.Gpr0();  break;

                case 2: Dst = OpCode.Gpr28(); break;

                case 3: Dst = (RegInc >> 1) != 0
                        ? OpCode.Gpr28()
                        : OpCode.Gpr0(); break;

                default: throw new InvalidOperationException();
                }

                Dst.Index += RegInc++ & 1;

                return(Dst);
            }

            for (int Ch = 0; Ch < 4; Ch++)
            {
                if (!IsChannelUsed(ChMask, Ch))
                {
                    continue;
                }

                ShaderIrOperGpr Src = new ShaderIrOperGpr(TempRegStart + Ch);

                ShaderIrOperGpr Dst = GetDst();

                if (Dst.Index != ShaderIrOperGpr.ZRIndex)
                {
                    Block.AddNode(OpCode.PredNode(new ShaderIrAsg(Dst, Src)));
                }
            }
        }
Ejemplo n.º 16
0
 public static void Fsetp_C(ShaderIrBlock Block, long OpCode)
 {
     EmitFsetp(Block, OpCode, ShaderOper.CR);
 }
Ejemplo n.º 17
0
        private static void EmitTex(ShaderIrBlock block, long opCode, TextureInstructionSuffix textureInstructionSuffix, bool gprHandle)
        {
            bool isArray = opCode.HasArray();

            GalTextureTarget textureTarget = TexToTextureTarget(opCode.Read(28, 6), isArray);

            bool hasDepthCompare = opCode.Read(0x32);

            if (hasDepthCompare)
            {
                textureInstructionSuffix |= TextureInstructionSuffix.Dc;
            }

            ShaderIrOperGpr[] coords = new ShaderIrOperGpr[ImageUtils.GetCoordsCountTextureTarget(textureTarget)];

            int indexExtraCoord = 0;

            if (isArray)
            {
                indexExtraCoord++;

                coords[coords.Length - 1] = opCode.Gpr8();
            }


            for (int index = 0; index < coords.Length - indexExtraCoord; index++)
            {
                ShaderIrOperGpr coordReg = opCode.Gpr8();

                coordReg.Index += index;

                coordReg.Index += indexExtraCoord;

                if (!coordReg.IsValidRegister)
                {
                    coordReg.Index = ShaderIrOperGpr.ZrIndex;
                }

                coords[index] = coordReg;
            }

            int chMask = opCode.Read(31, 0xf);

            ShaderIrOperGpr levelOfDetail = null;
            ShaderIrOperGpr offset        = null;
            ShaderIrOperGpr depthCompare  = null;

            // TODO: determine first argument when TEX.B is used
            int operBIndex = gprHandle ? 1 : 0;

            if ((textureInstructionSuffix & TextureInstructionSuffix.Ll) != 0 ||
                (textureInstructionSuffix & TextureInstructionSuffix.Lb) != 0 ||
                (textureInstructionSuffix & TextureInstructionSuffix.Lba) != 0 ||
                (textureInstructionSuffix & TextureInstructionSuffix.Lla) != 0)
            {
                levelOfDetail        = opCode.Gpr20();
                levelOfDetail.Index += operBIndex;

                operBIndex++;
            }

            if ((textureInstructionSuffix & TextureInstructionSuffix.AOffI) != 0)
            {
                offset        = opCode.Gpr20();
                offset.Index += operBIndex;

                operBIndex++;
            }

            if ((textureInstructionSuffix & TextureInstructionSuffix.Dc) != 0)
            {
                depthCompare        = opCode.Gpr20();
                depthCompare.Index += operBIndex;

                operBIndex++;
            }

            // ???
            ShaderIrNode operC = gprHandle
                ? (ShaderIrNode)opCode.Gpr20()
                : (ShaderIrNode)opCode.Imm13_36();

            ShaderIrInst inst = gprHandle ? ShaderIrInst.Texb : ShaderIrInst.Texs;

            coords = CoordsRegistersToTempRegisters(block, coords);

            int regInc = 0;

            for (int ch = 0; ch < 4; ch++)
            {
                if (!IsChannelUsed(chMask, ch))
                {
                    continue;
                }

                ShaderIrOperGpr dst = opCode.Gpr0();

                dst.Index += regInc++;

                if (!dst.IsValidRegister || dst.IsConst)
                {
                    continue;
                }

                ShaderIrMetaTex meta = new ShaderIrMetaTex(ch, textureTarget, textureInstructionSuffix, coords)
                {
                    LevelOfDetail = levelOfDetail,
                    Offset        = offset,
                    DepthCompare  = depthCompare
                };

                ShaderIrOp op = new ShaderIrOp(inst, coords[0], coords.Length > 1 ? coords[1] : null, operC, meta);

                block.AddNode(opCode.PredNode(new ShaderIrAsg(dst, op)));
            }
        }
Ejemplo n.º 18
0
 public static void Fadd_C(ShaderIrBlock Block, long OpCode)
 {
     EmitAluBinaryF(Block, OpCode, ShaderOper.CR, ShaderIrInst.Fadd);
 }
Ejemplo n.º 19
0
        private static void EmitTld4(ShaderIrBlock block, long opCode, GalTextureTarget textureType, TextureInstructionSuffix textureInstructionSuffix, int chMask, int component, bool scalar)
        {
            ShaderIrOperGpr operA = opCode.Gpr8();
            ShaderIrOperGpr operB = opCode.Gpr20();
            ShaderIrOperImm operC = opCode.Imm13_36();

            ShaderIrOperGpr[] coords = new ShaderIrOperGpr[ImageUtils.GetCoordsCountTextureTarget(textureType)];

            ShaderIrOperGpr offset       = null;
            ShaderIrOperGpr depthCompare = null;

            bool isArray = ImageUtils.IsArray(textureType);

            int operBIndex = 0;

            if (scalar)
            {
                int coordStartIndex = 0;

                if (isArray)
                {
                    coordStartIndex++;
                    coords[coords.Length - 1] = operB;
                }

                switch (coords.Length - coordStartIndex)
                {
                case 1:
                    coords[0] = opCode.Gpr8();

                    break;

                case 2:
                    coords[0]        = opCode.Gpr8();
                    coords[0].Index += coordStartIndex;

                    break;

                case 3:
                    coords[0]        = opCode.Gpr8();
                    coords[0].Index += coordStartIndex;

                    coords[1]        = opCode.Gpr8();
                    coords[1].Index += 1 + coordStartIndex;

                    break;

                default:
                    throw new NotSupportedException($"{coords.Length - coordStartIndex} coords textures aren't supported in TLD4S");
                }

                if (coords.Length - coordStartIndex != 1)
                {
                    coords[coords.Length - coordStartIndex - 1] = operB;
                    operBIndex++;
                }

                if (textureInstructionSuffix != TextureInstructionSuffix.None && textureType == GalTextureTarget.TwoD)
                {
                    coords[coords.Length - coordStartIndex - 1]        = opCode.Gpr8();
                    coords[coords.Length - coordStartIndex - 1].Index += coords.Length - coordStartIndex - 1;
                    operBIndex--;
                }
            }
            else
            {
                int indexExtraCoord = 0;

                if (isArray)
                {
                    indexExtraCoord++;

                    coords[coords.Length - 1] = opCode.Gpr8();
                }

                for (int index = 0; index < coords.Length - indexExtraCoord; index++)
                {
                    coords[index] = opCode.Gpr8();

                    coords[index].Index += index;

                    coords[index].Index += indexExtraCoord;

                    if (coords[index].Index > ShaderIrOperGpr.ZrIndex)
                    {
                        coords[index].Index = ShaderIrOperGpr.ZrIndex;
                    }
                }
            }

            if ((textureInstructionSuffix & TextureInstructionSuffix.AOffI) != 0)
            {
                offset        = opCode.Gpr20();
                offset.Index += operBIndex;
                operBIndex++;
            }

            if ((textureInstructionSuffix & TextureInstructionSuffix.Dc) != 0)
            {
                depthCompare        = opCode.Gpr20();
                depthCompare.Index += operBIndex;
                operBIndex++;
            }

            coords = CoordsRegistersToTempRegisters(block, coords);

            int regInc = 0;

            for (int ch = 0; ch < 4; ch++)
            {
                if (!IsChannelUsed(chMask, ch))
                {
                    continue;
                }

                ShaderIrOperGpr dst = opCode.Gpr0();

                dst.Index += regInc++;

                if (!dst.IsValidRegister || dst.IsConst)
                {
                    continue;
                }

                ShaderIrMetaTex meta = new ShaderIrMetaTex(ch, textureType, textureInstructionSuffix, coords)
                {
                    Component    = component,
                    Offset       = offset,
                    DepthCompare = depthCompare
                };

                ShaderIrOp op = new ShaderIrOp(ShaderIrInst.Tld4, operA, operB, operC, meta);

                block.AddNode(opCode.PredNode(new ShaderIrAsg(dst, op)));
            }
        }
Ejemplo n.º 20
0
 public static void Isetp_I(ShaderIrBlock Block, long OpCode)
 {
     EmitIsetp(Block, OpCode, ShaderOper.Imm);
 }
Ejemplo n.º 21
0
 private static void EmitIsetp(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
 {
     EmitSetp(Block, OpCode, false, Oper);
 }
Ejemplo n.º 22
0
        private void PrintNode(ShaderIrBlock Block, ShaderIrNode Node, string Identation)
        {
            if (Node is ShaderIrCond Cond)
            {
                string IfExpr = GetSrcExpr(Cond.Pred, true);

                if (Cond.Not)
                {
                    IfExpr = "!(" + IfExpr + ")";
                }

                SB.AppendLine(Identation + "if (" + IfExpr + ") {");

                PrintNode(Block, Cond.Child, Identation + IdentationStr);

                SB.AppendLine(Identation + "}");
            }
            else if (Node is ShaderIrAsg Asg)
            {
                if (IsValidOutOper(Asg.Dst))
                {
                    string Expr = GetSrcExpr(Asg.Src, true);

                    Expr = GetExprWithCast(Asg.Dst, Asg.Src, Expr);

                    SB.AppendLine(Identation + GetDstOperName(Asg.Dst) + " = " + Expr + ";");
                }
            }
            else if (Node is ShaderIrOp Op)
            {
                switch (Op.Inst)
                {
                case ShaderIrInst.Bra:
                {
                    SB.AppendLine(Identation + "return " + GetBlockPosition(Block.Branch) + ";");

                    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)
            {
                SB.AppendLine(Identation + "// " + Cmnt.Comment);
            }
            else
            {
                throw new InvalidOperationException();
            }
        }
Ejemplo n.º 23
0
 public static void Fmul_C(ShaderIrBlock Block, long OpCode, int Position)
 {
     EmitFmul(Block, OpCode, ShaderOper.CR);
 }
Ejemplo n.º 24
0
 public static void Exit(ShaderIrBlock Block, long OpCode)
 {
     Block.AddNode(GetPredNode(new ShaderIrOp(ShaderIrInst.Exit), OpCode));
 }
Ejemplo n.º 25
0
 public static void Fset_I(ShaderIrBlock Block, long OpCode, int Position)
 {
     EmitFset(Block, OpCode, ShaderOper.Immf);
 }
Ejemplo n.º 26
0
 public static void Tex_B(ShaderIrBlock Block, long OpCode, int Position)
 {
     EmitTex(Block, OpCode, GprHandle: true);
 }
Ejemplo n.º 27
0
 public static void Hmul2_R(ShaderIrBlock Block, long OpCode, int Position)
 {
     EmitBinaryHalfOp(Block, OpCode, ShaderIrInst.Fmul);
 }
Ejemplo n.º 28
0
 public static void Tlds(ShaderIrBlock Block, long OpCode, int Position)
 {
     EmitTexs(Block, OpCode, ShaderIrInst.Txlf);
 }
Ejemplo n.º 29
0
 public static void Iadd_C(ShaderIrBlock Block, long OpCode, int Position)
 {
     EmitIadd(Block, OpCode, ShaderOper.CR);
 }
Ejemplo n.º 30
0
 public static void I2i_R(ShaderIrBlock Block, long OpCode)
 {
     EmitI2i(Block, OpCode, ShaderOper.RR);
 }