Inheritance: Instruction
Beispiel #1
0
        public void Visit(TernaryOp ins)
        {
            Vector4f a = ctx.ReadValue (ins.Source1);
            Vector4f b = ctx.ReadValue (ins.Source2);
            Vector4f c = ctx.ReadValue (ins.Source3);
            Vector4f res = new Vector4f ();
            switch (ins.Operation) {
            case TernaryOpKind.Cmp: {// a >= 0 ? b : c
                //m = a < [0,0,0,0]
                Vector4f mask = a.CompareLessThan (new Vector4f ()); //we change to a <b
                //res = (m & C) | (~m & B) -- this could be replaced by a blendps
                res = (mask & c) | mask.AndNot (b);
                break;
            }
            case TernaryOpKind.Mad: {// a *  b + c
                res = (a * b) + c;
                break;
            }
            case TernaryOpKind.SinCos: { // sin(a) , cos(a)
                //XXX maybe we should use the macro expansion provided in the driver docs for HLSL
                res.X = (float)Math.Cos (a.X);
                res.Y = (float)Math.Sin (a.X);
                break;
            }
            case TernaryOpKind.Lrp: //c + a * (b - c)
                //res = c + (a * (b - c));
                res = a * b + (Vector4f.One - a) * c;
                break;
            case TernaryOpKind.Dp2Add: //res = a.r * b.r + a.g * b.g + c.swizzle
             	res = a * b;
                //XX we could use Hadd here
                res = res + res.Shuffle (ShuffleSel.XFromY) + c;
                res = res.Shuffle (ShuffleSel.ExpandX);
                break;
            default:
                throw new Exception ("Cant handle " + ins.Operation);
            }

            if (Tracing.Enabled) Console.WriteLine ("{0} {1} {2} {3} => {4}/{5}/{6} == {7}", ins.Source1, ins.Operation, ins.Source2, ins.Source3, a, b, c, res);
            ctx.StoreValue (ins.Dest, res);
        }
Beispiel #2
0
 public void Visit(TernaryOp ins)
 {
     VisitSrcReg (ins.Source1);
     VisitSrcReg (ins.Source2);
     VisitSrcReg (ins.Source3);
     VisitDestReg (ins.Dest);
 }
Beispiel #3
0
 public void Visit(TernaryOp ins)
 {
     ctx.EmitTernary (ins);
 }
Beispiel #4
0
 public void Visit(TernaryOp ins)
 {
 }
Beispiel #5
0
        internal void EmitTernary(TernaryOp ins)
        {
            //FIXME it might be an issue if arguments are not of type Vector4f
            switch (ins.Operation) {
            case TernaryOpKind.Cmp: {
                var mask = DeclareTmp (typeof (Vector4f));
                //mask = 0
                ilgen.Emit (OpCodes.Ldloca, mask);
                ilgen.Emit (OpCodes.Initobj, typeof (Vector4f));

                //a < tmp
                LoadValue (ins.Source1);
                ilgen.Emit (OpCodes.Ldloc, mask);
                ilgen.Emit (OpCodes.Call, typeof (VectorOperations).GetMethod ("CompareLessThan", new Type[] { typeof (Vector4f), typeof (Vector4f)}));
                ilgen.Emit (OpCodes.Stloc, mask);

                //mask & c
                ilgen.Emit (OpCodes.Ldloc, mask);
                LoadValue (ins.Source3);
                ilgen.Emit (OpCodes.Call, typeof (Vector4f).GetMethod ("op_BitwiseAnd"));

                //mask.AndNot (b);
                ilgen.Emit (OpCodes.Ldloc, mask);
                LoadValue (ins.Source2);
                ilgen.Emit (OpCodes.Call, typeof (VectorOperations).GetMethod ("AndNot", new Type[] { typeof (Vector4f), typeof (Vector4f)}));

                //res = (mask & c) | mask.AndNot (b);
                ilgen.Emit (OpCodes.Call, typeof (Vector4f).GetMethod ("op_BitwiseOr"));
                StoreValue (ins.Dest);
                break;
            }

            case TernaryOpKind.Mad: //a * b + c
                LoadValue (ins.Source1);
                LoadValue (ins.Source2);
                ilgen.Emit (OpCodes.Call, typeof (Vector4f).GetMethod ("op_Multiply"));
                LoadValue (ins.Source3);
                ilgen.Emit (OpCodes.Call, typeof (Vector4f).GetMethod ("op_Addition"));
                StoreValue (ins.Dest);
                break;

            case TernaryOpKind.SinCos: //.x = cos (a.X) .y = cos (a.X)
                //XXX maybe we should use the macro expansion provided in the driver docs for HLSL
                switch (ins.Dest.WriteMask) {
                case 1: //R cos
                    ApplyMathScalarUnaryToElement (ins.Dest, ins.Source1, "Cos", "X");
                    break;
                case 2: //G Sin
                    ApplyMathScalarUnaryToElement (ins.Dest, ins.Source1, "Sin", "Y");
                    break;
                case 3: //RG
                    ApplyMathScalarUnaryToElement (ins.Dest, ins.Source1, "Cos", "X");
                    ApplyMathScalarUnaryToElement (ins.Dest, ins.Source1, "Sin", "Y");
                    break;
                default:
                    throw new Exception ("Invalid writeMask for sincos " + ins.Dest.WriteMask.ToString ("X"));
                }
                break;
            case TernaryOpKind.Lrp:  //a * b + (1 - a) * c;
                //a * b
                LoadValue (ins.Source1);
                LoadValue (ins.Source2);
                ilgen.Emit (OpCodes.Call, typeof (Vector4f).GetMethod ("op_Multiply"));
                //1 - a
                EmitTempVector4f (1);
                LoadValue (ins.Source1);
                ilgen.Emit (OpCodes.Call, typeof (Vector4f).GetMethod ("op_Subtraction"));
                // (1 - a) * c
                LoadValue (ins.Source3);
                ilgen.Emit (OpCodes.Call, typeof (Vector4f).GetMethod ("op_Multiply"));

                ilgen.Emit (OpCodes.Call, typeof (Vector4f).GetMethod ("op_Addition"));
                StoreValue (ins.Dest);
                break;
            case TernaryOpKind.Dp2Add: {//res = a.r * b.r + a.g * b.g + c.swizzle
                LoadValue (ins.Source1);
                LoadValue (ins.Source2);
                LoadValue (ins.Source3);
                ilgen.Emit (OpCodes.Call, typeof (SimdExtras).GetMethod ("Dp2Add"));
                StoreValue (ins.Dest);
                break;

                //a * b
                LoadValue (ins.Source1);
                LoadValue (ins.Source2);
                ilgen.Emit (OpCodes.Call, typeof (Vector4f).GetMethod ("op_Multiply"));
                ilgen.Emit (OpCodes.Dup);

                //FIXME we could use HorizontalAdd here
                EmitShuffle (ShuffleSel.XFromY); //[x,y,_,_] [y,y,_,_]
                ilgen.Emit (OpCodes.Call, typeof (Vector4f).GetMethod ("op_Addition")); //[x + y,_,_,_]

                //+c.swizzle
                LoadValue (ins.Source3);
                ilgen.Emit (OpCodes.Call, typeof (Vector4f).GetMethod ("op_Addition"));
                EmitShuffle (ShuffleSel.ExpandX);
                StoreValue (ins.Dest);
                break;
            }
            default:
                throw new Exception ("can't handle ternop " + ins.Operation);
            }
        }