Chad Capeland wrote:Hendrik Proosa wrote:Chad Capeland wrote:Are you asking how it should work or how it does work?
How it does work in Fusion.
Using hashes for associating caches seems like a nice idea, but that's a LOT of calculation to do to generate those enormous hashes and to compare them to the cached set, and you have to eat up that much extra memory to store the hashes. The likelihood of it being useful is not great since it only ever benefits you when the inputs are cycled back and forth AND there is room for the caching of the images AND there is room for the hashes AND the hash calculation and search is faster than re-rendering. Those combination of conditions may rarely exist.
Yet this is exactly how it works in Nuke, which is the motivation of my question too, to understand how Fusion does it. In Nuke, every node adds its relevant knobs (that affect its output) to its own hash. This hash and knob values of next node are again hashed together and so on. Hash itself is standard UUID value which is 128 bits, this is very tiny in memory. Hash values for 1000 nodes over a frame range of 1000 frames takes about the same amount of mem as 720p RGBA image, this is irrelevantly small. Hashing itself is also light operation because hash is not calculated on image data but from state that produces image data (I think this is why you thought it would be very slow). This state contains, in addition to knob values, current frame, view, scanline and proxy context. When certain node does not allow animation at all for example (rare but possible), it does not add frame context to its hash, thus engine knows that the output of that node does not change unless its input hashes change which will in turn change its own hash and invalidate cache.
Cache is tied to node hashing through these same uuid values. In cache dir, every cache file is named after its tied hash. And lookup for existing cache works by simply looking up the file in that dir. To prevent slow directory searches Nuke keeps a hash list in mem together with some metadata which is used for weighting stuff against each other. Stuff that takes longer to regenerate is kept longer in cache, what is used more frequently is kept longer and so on.
Lets say I have a node structure A->B->C->D->E where C is a merge and its second input is A2->B2->C. If I attach viewer to node E, hashes are calculated from top down for all nodes, their current state is stored in disk cache and node E is also stored in viewer ram cache. If I make a change in node E, only node E is recalculated because none of the hashes upstream changed. If I change it back, hash will be the same as previous state and it is retrieved (if it has not been purged). If I change some knob in node A, everything downstream it will be recalculated because their hash changed due to their input being changed. A2 and B2 are kept as is though, node C retrieves the cache for node B2 from disk. I can do all kinds of changes in the meantime, if I happen to hit the same combination (state) I had in the beginning and that cache still exists on disk it will be retrieved again, possibly hours or days later (depends on size of disk cache).