def testDefaultExpressionForSupportedPlugs( self ) : s = Gaffer.ScriptNode() s["n"] = Gaffer.Node() s["n"]["user"].addChild( Gaffer.IntPlug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) ) s["n"]["user"].addChild( Gaffer.FloatPlug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) ) s["n"]["user"].addChild( Gaffer.StringPlug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) ) s["n"]["user"].addChild( Gaffer.BoolPlug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) ) s["n"]["user"].addChild( Gaffer.V2fPlug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) ) s["n"]["user"].addChild( Gaffer.V2iPlug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) ) s["n"]["user"].addChild( Gaffer.V3fPlug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) ) s["n"]["user"].addChild( Gaffer.V3iPlug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) ) s["n"]["user"].addChild( Gaffer.Color3fPlug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) ) s["n"]["user"].addChild( Gaffer.Color4fPlug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) ) s["n"]["user"].addChild( Gaffer.Box2fPlug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) ) s["n"]["user"].addChild( Gaffer.Box2iPlug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) ) s["n"]["user"].addChild( Gaffer.Box3fPlug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) ) s["n"]["user"].addChild( Gaffer.Box3iPlug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) ) s["n"]["user"].addChild( Gaffer.IntVectorDataPlug( defaultValue = IECore.IntVectorData( [ 0, 1 ] ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) ) s["n"]["user"].addChild( Gaffer.FloatVectorDataPlug( defaultValue = IECore.FloatVectorData( [ 0, 1 ] ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) ) s["n"]["user"].addChild( Gaffer.StringVectorDataPlug( defaultValue = IECore.StringVectorData( [ "a", "b" ] ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) ) s["n"]["user"].addChild( Gaffer.V3fVectorDataPlug( defaultValue = IECore.V3fVectorData( [ IECore.V3f( 1 ) ] ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) ) s["n"]["user"].addChild( Gaffer.Color3fVectorDataPlug( defaultValue = IECore.Color3fVectorData( [ IECore.Color3f( 1 ) ] ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) ) s["n"]["user"].addChild( Gaffer.M44fVectorDataPlug( defaultValue = IECore.M44fVectorData( [ IECore.M44f() ] ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) ) s["n"]["user"].addChild( Gaffer.V2iVectorDataPlug( defaultValue = IECore.V2iVectorData( [ IECore.V2i() ] ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) ) s["e"] = Gaffer.Expression() for plug in s["n"]["user"] : value = plug.getValue() s["e"].setExpression( s["e"].defaultExpression( plug, "python" ) ) self.assertTrue( plug.getInput().node().isSame( s["e"] ) ) self.assertEqual( plug.getValue(), value )
def __init__( self, name = "Wedge" ) : GafferDispatch.TaskContextProcessor.__init__( self, name ) self["variable"] = Gaffer.StringPlug( defaultValue = "wedge:value" ) self["indexVariable"] = Gaffer.StringPlug( defaultValue = "wedge:index" ) self["mode"] = Gaffer.IntPlug( defaultValue = int( self.Mode.FloatRange ), minValue = int( self.Mode.FloatRange ), maxValue = int( self.Mode.StringList ), ) # float range self["floatMin"] = Gaffer.FloatPlug( defaultValue = 0 ) self["floatMax"] = Gaffer.FloatPlug( defaultValue = 1 ) self["floatSteps"] = Gaffer.IntPlug( minValue = 2, defaultValue = 11 ) # int range self["intMin"] = Gaffer.IntPlug( defaultValue = 0 ) self["intMax"] = Gaffer.IntPlug( defaultValue = 5 ) self["intStep"] = Gaffer.IntPlug( minValue = 1, defaultValue = 1 ) # color range self["ramp"] = Gaffer.SplinefColor3fPlug( defaultValue = IECore.SplinefColor3f( IECore.CubicBasisf.catmullRom(), ( ( 0, imath.Color3f( 0 ) ), ( 0, imath.Color3f( 0 ) ), ( 1, imath.Color3f( 1 ) ), ( 1, imath.Color3f( 1 ) ), ) ) ) self["colorSteps"] = Gaffer.IntPlug( defaultValue = 5, minValue = 2 ) # lists self["floats"] = Gaffer.FloatVectorDataPlug( defaultValue = IECore.FloatVectorData() ) self["ints"] = Gaffer.IntVectorDataPlug( defaultValue = IECore.IntVectorData() ) self["strings"] = Gaffer.StringVectorDataPlug( defaultValue = IECore.StringVectorData() )
def testBadCachePolicyHang(self): # Using the legacy cache policy for OSLImage.shadingPlug creates a hang due to tbb task stealing, # though it's a bit hard to actually demonstrate constant = GafferImage.Constant() constant["format"].setValue(GafferImage.Format(128, 128, 1.000)) # Need a slow to compute OSL code in order to trigger hang mandelbrotCode = self.mandelbrotNode() # In order to trigger the hang, we need to mix threads which are stuck waiting for an expression which # uses the Standard policy with threads that are actually finishing, so that tbb tries to start up new # threads while we're waiting for the expression result. To do this, we use the "var" context variable # to create two versions of this OSLCode mandelbrotCode["varExpression"] = Gaffer.Expression() mandelbrotCode["varExpression"].setExpression( 'parent.parameters.iterations = 100000 + context( "var", 0 );', "OSL") oslImage = GafferOSL.OSLImage() oslImage["channels"].addChild( Gaffer.NameValuePlug( "", Gaffer.Color3fPlug( "value", defaultValue=imath.Color3f(1, 1, 1), flags=Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ), True, "channel", Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic)) oslImage["in"].setInput(constant["out"]) oslImage["channels"]["channel"]["value"][0].setInput( mandelbrotCode["out"]["outFloat"]) oslImage["channels"]["channel"]["value"][1].setInput( mandelbrotCode["out"]["outFloat"]) oslImage["channels"]["channel"]["value"][2].setInput( mandelbrotCode["out"]["outFloat"]) # This imageStats is use to create non-blocking slow calculations imageStats = GafferImage.ImageStats() imageStats["in"].setInput(oslImage["out"]) imageStats["area"].setValue( imath.Box2i(imath.V2i(0, 0), imath.V2i(64, 64))) # This box does the non-blocking slow calculation, followed by a blocking slow calculation. # This ensures that tasks which do just the non-block calculation will start finishing while # the blocking slow calculation is still running, allowing tbb to try running more threads # on the blocking calcluation, realizing they can't run, and stealing tasks onto those threads # which can hit the Standard policy lock on the expression upstream and deadlock, unless the # OSLImage isolates its threads correctly expressionBox = Gaffer.Box() expressionBox.addChild( Gaffer.FloatVectorDataPlug("inChannelData", defaultValue=IECore.FloatVectorData( []))) expressionBox.addChild(Gaffer.FloatPlug("inStat")) expressionBox.addChild( Gaffer.FloatPlug("out", direction=Gaffer.Plug.Direction.Out)) expressionBox["inChannelData"].setInput(oslImage["out"]["channelData"]) expressionBox["inStat"].setInput(imageStats["average"]["r"]) expressionBox["contextVariables"] = Gaffer.ContextVariables() expressionBox["contextVariables"].setup( Gaffer.FloatVectorDataPlug("in", defaultValue=IECore.FloatVectorData( []))) expressionBox["contextVariables"]["variables"].addChild( Gaffer.NameValuePlug("image:tileOrigin", Gaffer.V2iPlug("value"), True, "member1")) expressionBox["contextVariables"]["variables"].addChild( Gaffer.NameValuePlug("image:channelName", Gaffer.StringPlug("value", defaultValue='R'), True, "member2")) expressionBox["contextVariables"]["variables"].addChild( Gaffer.NameValuePlug("var", Gaffer.IntPlug("value", defaultValue=1), True, "member3")) expressionBox["contextVariables"]["in"].setInput( expressionBox["inChannelData"]) expressionBox["expression"] = Gaffer.Expression() expressionBox["expression"].setExpression( inspect.cleandoc(""" d = parent["contextVariables"]["out"] parent["out"] = d[0] + parent["inStat"] """)) # Create a switch to mix which tasks perform the non-blocking or blocking calculation - we need a mixture # to trigger the hang switch = Gaffer.Switch() switch.setup(Gaffer.IntPlug( "in", defaultValue=0, )) switch["in"][0].setInput(expressionBox["out"]) switch["in"][1].setInput(imageStats["average"]["r"]) switch["switchExpression"] = Gaffer.Expression() switch["switchExpression"].setExpression( 'parent.index = ( stoi( context( "testContext", "0" ) ) % 10 ) > 5;', "OSL") # In order to evaluate this expression a bunch of times at once with different values of "testContext", # we set up a simple scene that can be evaluated with GafferSceneTest.traversScene. # In theory, we could use a simple function that used a parallel_for to evaluate switch["out"], but for # some reason we don't entirely understand, this does not trigger the hang import GafferSceneTest import GafferScene sphere = GafferScene.Sphere() pathFilter = GafferScene.PathFilter() pathFilter["paths"].setValue(IECore.StringVectorData(['/sphere'])) customAttributes = GafferScene.CustomAttributes() customAttributes["attributes"].addChild( Gaffer.NameValuePlug("foo", Gaffer.FloatPlug("value"), True, "member1")) customAttributes["attributes"]["member1"]["value"].setInput( switch["out"]) customAttributes["in"].setInput(sphere["out"]) customAttributes["filter"].setInput(pathFilter["out"]) collectScenes = GafferScene.CollectScenes() collectScenes["in"].setInput(customAttributes["out"]) collectScenes["rootNames"].setValue( IECore.StringVectorData([str(i) for i in range(1000)])) collectScenes["rootNameVariable"].setValue('testContext') # When OSLImage.shadingPlug is not correctly isolated, and grain size on ShadingEngine is smaller than the # image tile size, this fails about 50% of the time. Running it 5 times makes the failure pretty consistent. for i in range(5): Gaffer.ValuePlug.clearCache() Gaffer.ValuePlug.clearHashCache() GafferSceneTest.traverseScene(collectScenes["out"])