(sept 23, 2016) - this is to be simultaneously addressed with caching and multi-processing.
Currently only one kind of plug-in instance is recognised, this is used for everything, interface, caching state, rendering etc… Many host applications have severe problems with this model, as they typically have separate render objects that are either lightweight special purpose render objects, or cloned on demand copies of the effect.
To deal with the current API, they either have multiple instances of a plug-in around, continually syncing data from the persistant/UI version to the render version, or they do this on demand. This often leads to sub-optimal performance and a great deal of complexity.
Plug-ins also find this difficult, as they often cache data in an instance, expecting to be able to re-use that data on the next render (eg: motion vectors from a retimer). In a clone on demand host, as the instance is continually being re-created, this cached data is always being destroyed once the temporary render instance is released.
A good way to manage this would be to have the API support a special purpose lightweight render instance object. The full effect instance is asked to populate one of these with any data it needs for the render action (and related actions such as RoD/RoI?), this object is then called to do the actual pixel pushing. This decouples object persistence and interface from processing, and allows for better multi threaded behaviour.
This is a major and complex change to the API and needs to be thoroughly discussed between host devs and plug-in devs.
As plug-ins are currently caching data between renders within the persistent instance (as in our retimer example), we still need to allow a plug-in to cache data in some manner. A better way all round would be for an explicit caching API, which a render object or persistent object could both commit and retrieve data to a host managed cache in a thread safe manner.
In Natron 3 we clone all effects in the render tree for each time and view (as in the multiview extension) passed to the render action.
All actions that are typically called on a render threads are instead called on each of these clones.
Each clone gets a set of cloned parameters where their value is cloned from the main instance parameters for the requested time and view. These means that we can guarantee that a value will not change between 2 actions called for a single same render.
In case of an animated parameter, if the plug-in calls getValue instead of getValueAtTime, we are able to recover the current time of the current action of the plug-in because each ImageEffect clone was created to render a specific time.
Cloning effects allows to partially resolve the "loss of context" of the host when calling suite functions. In our case, we found out that it almost completely removes the need to use thread local storage on the host side, except for the multi-thread suite and strings storage.
In order for this to work nicely, it is important that the render clone does not perform expensive operations in the create instance action: it should only fetch its parameters.
A possible way to do it would be to have an action similar to the create instance action, but that would be specific to create an ImageEffect render instance, where the plug-in is expected not to do more than fetching parameters. This action should also get a pointer to the main-thread instance so that the render instance can nicely cache data in a convenient way.
handlehandle to the plug-in instance, cast to an
inArgs: Contains the following property:
/** @brief Pointer property x1 pointing to the main-thread OfxImageEffectHandle
#define kOfxImageEffectMainInstanceHandle "OfxImageEffectMainInstanceHandle"
outArgsis redundant and is set to NULL.
This action is similar to the kOfxActionCreateInstance action except that the ImageEffect is only to be used for render actions. This should be the first action called on a render thread so that the ImageEffect instance can have a consistent state throughout all actions of the render threads.
It is expected that this action only fetches its parameters.
The kOfxImageEffectMainInstanceHandle can be used to cache or retrieved cached data on the main-thread instance.
#define kOfxActionCreateRenderInstance "OfxActionCreateRenderInstance"