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); }
public void Visit(TernaryOp ins) { VisitSrcReg (ins.Source1); VisitSrcReg (ins.Source2); VisitSrcReg (ins.Source3); VisitDestReg (ins.Dest); }
public void Visit(TernaryOp ins) { ctx.EmitTernary (ins); }
public void Visit(TernaryOp ins) { }
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); } }