示例#1
0
        private static void EmitSet(ShaderIrBlock Block, long OpCode, bool IsFloat, ShaderOper Oper)
        {
            bool NegA = OpCode.Read(43);
            bool AbsB = OpCode.Read(44);
            bool NegB = OpCode.Read(53);
            bool AbsA = OpCode.Read(54);

            bool BoolFloat = OpCode.Read(IsFloat ? 52 : 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 = GetAluFabsFneg(OperB, AbsB, NegB);

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

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

            ShaderIrInst LopInst = OpCode.BLop45();

            ShaderIrOperPred PNode = OpCode.Pred39();

            ShaderIrNode Imm0, Imm1;

            if (BoolFloat)
            {
                Imm0 = new ShaderIrOperImmf(0);
                Imm1 = new ShaderIrOperImmf(1);
            }
            else
            {
                Imm0 = new ShaderIrOperImm(0);
                Imm1 = new ShaderIrOperImm(-1);
            }

            ShaderIrNode Asg0 = new ShaderIrAsg(OpCode.Gpr0(), Imm0);
            ShaderIrNode Asg1 = new ShaderIrAsg(OpCode.Gpr0(), Imm1);

            if (LopInst != ShaderIrInst.Band || !PNode.IsConst)
            {
                ShaderIrOp Op2 = new ShaderIrOp(LopInst, Op, PNode);

                Asg0 = new ShaderIrCond(Op2, Asg0, Not: true);
                Asg1 = new ShaderIrCond(Op2, Asg1, Not: false);
            }
            else
            {
                Asg0 = new ShaderIrCond(Op, Asg0, Not: true);
                Asg1 = new ShaderIrCond(Op, Asg1, Not: false);
            }

            Block.AddNode(OpCode.PredNode(Asg0));
            Block.AddNode(OpCode.PredNode(Asg1));
        }
示例#2
0
        private static void EmitF2i(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
        {
            IntType Type = GetIntType(OpCode);

            if (Type == IntType.U64 ||
                Type == IntType.S64)
            {
                //TODO: 64-bits support.
                //Note: GLSL doesn't support 64-bits integers.
                throw new NotImplementedException();
            }

            bool NegA = ((OpCode >> 45) & 1) != 0;
            bool AbsA = ((OpCode >> 49) & 1) != 0;

            ShaderIrNode OperA;

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

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

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

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

            OperA = GetAluFabsFneg(OperA, AbsA, NegA);

            ShaderIrInst RoundInst = GetRoundInst(OpCode);

            if (RoundInst != ShaderIrInst.Invalid)
            {
                OperA = new ShaderIrOp(RoundInst, OperA);
            }

            bool Signed = Type >= IntType.S8;

            int Size = 8 << ((int)Type & 3);

            if (Size < 32)
            {
                uint Mask = uint.MaxValue >> (32 - Size);

                float CMin = 0;
                float CMax = Mask;

                if (Signed)
                {
                    uint HalfMask = Mask >> 1;

                    CMin -= HalfMask + 1;
                    CMax  = HalfMask;
                }

                ShaderIrOperImmf IMin = new ShaderIrOperImmf(CMin);
                ShaderIrOperImmf IMax = new ShaderIrOperImmf(CMax);

                OperA = new ShaderIrOp(ShaderIrInst.Fclamp, OperA, IMin, IMax);
            }

            ShaderIrInst Inst = Signed
                ? ShaderIrInst.Ftos
                : ShaderIrInst.Ftou;

            ShaderIrNode Op = new ShaderIrOp(Inst, OperA);

            Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Op), OpCode));
        }
示例#3
0
        private static void EmitSet(ShaderIrBlock Block, long OpCode, bool IsFloat, ShaderOper Oper)
        {
            bool Na = ((OpCode >> 43) & 1) != 0;
            bool Ab = ((OpCode >> 44) & 1) != 0;
            bool Nb = ((OpCode >> 53) & 1) != 0;
            bool Aa = ((OpCode >> 54) & 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 = GetAluAbsNeg(OperB, Ab, Nb);

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

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

            ShaderIrInst LopInst = GetBLop(OpCode);

            ShaderIrOperPred PNode = GetOperPred39(OpCode);

            ShaderIrOperImmf Imm0 = new ShaderIrOperImmf(0);
            ShaderIrOperImmf Imm1 = new ShaderIrOperImmf(1);

            ShaderIrNode Asg0 = new ShaderIrAsg(GetOperGpr0(OpCode), Imm0);
            ShaderIrNode Asg1 = new ShaderIrAsg(GetOperGpr0(OpCode), Imm1);

            if (LopInst != ShaderIrInst.Band || !PNode.IsConst)
            {
                ShaderIrOp Op2 = new ShaderIrOp(LopInst, Op, PNode);

                Asg0 = new ShaderIrCond(Op2, Asg0, Not: true);
                Asg1 = new ShaderIrCond(Op2, Asg1, Not: false);
            }
            else
            {
                Asg0 = new ShaderIrCond(Op, Asg0, Not: true);
                Asg1 = new ShaderIrCond(Op, Asg1, Not: false);
            }

            Block.AddNode(GetPredNode(Asg0, OpCode));
            Block.AddNode(GetPredNode(Asg1, OpCode));
        }
示例#4
0
        private static void EmitF2I(ShaderIrBlock block, long opCode, ShaderOper oper)
        {
            IntType type = GetIntType(opCode);

            if (type == IntType.U64 ||
                type == IntType.S64)
            {
                //TODO: 64-bits support.
                //Note: GLSL doesn't support 64-bits integers.
                throw new NotImplementedException();
            }

            bool negA = opCode.Read(45);
            bool absA = opCode.Read(49);

            ShaderIrNode operA;

            switch (oper)
            {
            case ShaderOper.Cr:   operA = opCode.Cbuf34();    break;

            case ShaderOper.Immf: operA = opCode.Immf19_20(); break;

            case ShaderOper.Rr:   operA = opCode.Gpr20();     break;

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

            operA = GetAluFabsFneg(operA, absA, negA);

            ShaderIrInst roundInst = GetRoundInst(opCode);

            if (roundInst != ShaderIrInst.Invalid)
            {
                operA = new ShaderIrOp(roundInst, operA);
            }

            bool signed = type >= IntType.S8;

            int size = 8 << ((int)type & 3);

            if (size < 32)
            {
                uint mask = uint.MaxValue >> (32 - size);

                float cMin = 0;
                float cMax = mask;

                if (signed)
                {
                    uint halfMask = mask >> 1;

                    cMin -= halfMask + 1;
                    cMax  = halfMask;
                }

                ShaderIrOperImmf min = new ShaderIrOperImmf(cMin);
                ShaderIrOperImmf max = new ShaderIrOperImmf(cMax);

                operA = new ShaderIrOp(ShaderIrInst.Fclamp, operA, min, max);
            }

            ShaderIrInst inst = signed
                ? ShaderIrInst.Ftos
                : ShaderIrInst.Ftou;

            ShaderIrNode op = new ShaderIrOp(inst, operA);

            block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), op)));
        }
示例#5
0
        private static void EmitSet(ShaderIrBlock block, long opCode, bool isFloat, ShaderOper oper)
        {
            bool negA = opCode.Read(43);
            bool absB = opCode.Read(44);
            bool negB = opCode.Read(53);
            bool absA = opCode.Read(54);

            bool boolFloat = opCode.Read(isFloat ? 52 : 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 = GetAluFabsFneg(operB, absB, negB);

                cmpInst = opCode.CmpF();
            }
            else
            {
                cmpInst = opCode.Cmp();
            }

            ShaderIrOp op = new ShaderIrOp(cmpInst, operA, operB);

            ShaderIrInst lopInst = opCode.BLop45();

            ShaderIrOperPred pNode = opCode.Pred39();

            ShaderIrNode imm0, imm1;

            if (boolFloat)
            {
                imm0 = new ShaderIrOperImmf(0);
                imm1 = new ShaderIrOperImmf(1);
            }
            else
            {
                imm0 = new ShaderIrOperImm(0);
                imm1 = new ShaderIrOperImm(-1);
            }

            ShaderIrNode asg0 = new ShaderIrAsg(opCode.Gpr0(), imm0);
            ShaderIrNode asg1 = new ShaderIrAsg(opCode.Gpr0(), imm1);

            if (lopInst != ShaderIrInst.Band || !pNode.IsConst)
            {
                ShaderIrOp op2 = new ShaderIrOp(lopInst, op, pNode);

                asg0 = new ShaderIrCond(op2, asg0, not: true);
                asg1 = new ShaderIrCond(op2, asg1, not: false);
            }
            else
            {
                asg0 = new ShaderIrCond(op, asg0, not: true);
                asg1 = new ShaderIrCond(op, asg1, not: false);
            }

            block.AddNode(opCode.PredNode(asg0));
            block.AddNode(opCode.PredNode(asg1));
        }