Friday, July 22, 2011

GSoC11 - Depsgraph Hacking - Driver Updates

This week I'd set aside some time to get through some of the bug reports on the tracker. And it happens that there are some related to the depsgraph and drivers, so I thought I'd go in and give this stuff another crack to try and push the frontiers of our current depsgraph's limitations before the inevitable big recode project ;)

So the problem I set out to investigate was whether it would still be possible in the current architecture to hack the depsgraph to at least tag + flush updates for object data id-blocks (e.g. lamp data in this particular case). In particular, trying to drive the location of a cube using the distance setting of a lamp.

Admittedly, up till today, I hadn't really taken a good look under the hood of the depsgraph, having mainly only dealt with a few parts as necessary when things broke. From previous dealings with this system from outward/overall aspects, the following points applied:
1) Only Object and Object-data (but only when associated directly with an Object) are able to be handled by the system
2) The Depsgraph merely kept track of relationships between Objects
3) If one object changes and the Depsgraph is told to tag it as needing updates, other Objects which depend on it will be tagged as needing either Object-level or Data-level updates
4) object_handle_update() is responsible for processing whatever tags depsgraph has set on objects in the scene

Despite these limitations, I figured that perhaps for such object data it might still be possible to somehow hook up the dependencies correctly.

Indeed, just adding a relevant relationship to the dependency graph "seemed" relatively straightforward, using a method similar to how constraints are usually handled. However, when this didn't seem to immediately provide any visible results, I started to have to dig deep inside the guts of this system, tracing what updates (if any) were going on.

After several hours of wading through this code, uncommenting and/or adding new debugging prints, I finally came across the point where all the problems were coming from. flush_update_node() was never doing any dependency flushing for the lamp because it never registered as having any child dependencies at all!

Checking back at how the depsgraph was being built, I found that it had some code that wasn't being used, which would have added object<-->object-data as a relationship in the depsgraph, but which would never really happen because the building function was called in a way which explicitly excludes this. After enabling this, I quickly saw why: Blender would crash on startup, as the object-data nodes would start getting treated as objects, leading to some rather "interesting" consequences...

Indeed, there were some rather questionable things in there, such as an obtuse "type" arg which seems to take everything including the kitchen sink, various types of data being shoehorned into a typeless setting named "ob" and then extracted again by checking for global settings called "i_am_an_evil_hack" (or words to that effect)... But perhaps more disturbing was how much of the potential power of a dependency graph, for discovering and/or affecting entities using the relationships between them in a simplified overview is made almost non-existent. There are quite a few things in Blender which could have been much simpler if this was done in a different way!

Having thought over the consequences of various hacks which may have allowed all this to work, it's fair to say that unfortunately, any further work here will really have to wait till a decent refactor project, perhaps one which tackles related thread-safety, duplicators, proxies, and noodle magic... But then, this is still very much crystal-ball gazing + feature drooling still, though on the other hand, it'd be less risky if were were able to just evolve whatever code we have towards a better design. Then again, after today, I think it's safe to say that in several regards, a start-over would be better.


  1. Man that would be sweet to have! Drive anything with anything, way to go. Are there such plans as a "inevitable big recode project" or what is the current outlook on this feature set?

  2. Hi,
    Facing same problem with custom function as expression in alpha slot of a material i've found a simple workaround to force update by creating a dumb variable in driver with a link to (parent/any) node.
    This way, the graph dependency condition is met and the driver suddenly works as expected.