[Host] Multi-thread suite and host internal state

68 views
Skip to first unread message

Alexandre Gauthier

unread,
Oct 8, 2014, 8:20:45 AM10/8/14
to ofx-dis...@googlegroups.com
Hey,

Seems we're reaching a dead-end here in Natron when trying to maintain the internal state expected by the plug-in when calling suite functions if they are called by a thread of the multi-thread suite or any other thread that wasn't spawned by the Host.

Here's the detailed issue:

 Since a plug-in can have multiple renders (or any other action) called at the same time (if it supports it), the host needs to provide a way to correctly keep the arguments of an action local to a render call, so that when the plug-in calls fetchImage on the source clip, the host will feed it with an appropriate image respecting the arguments that were given to the render action in the first place.

We thought of 2 possible solutions to maintain such an internal state:

1) Have small objects, local to an action call, containing an image effect handle (different for each action) and all the per-action local data associated to it. This object would then also contain a pointer to the *real* host image effect to which it would just serve as a proxy, filling out the missing arguments.
This approach seems cool at first glance, but seems impossible because on the plug-in side, (at least on the Support C++ layer as proposed by ofxa) an ImageEffect is associated to the same image effect handle. So if we were to create a local image effect handle for each action, we'd have to first call the createInstanceAction which can then become expensive and inappropriate.

2) Thread-local storage: Each thread calling out an action is tagged with "action-local" data, so that when the plug-in calls a function of a suite, we can just inspect the local data for the current thread and retrieve the internal state. This works great (and is the solution we adopted currently for Natron), but has the following downside(s):

- This is expensive and hard to maintain 
- This does not port well to the threads spawned by the multi-thread suite: We cannot copy the local state of the thread calling the multiThread() function of the multi-thread suite to the actual spawned threads because there's no handle to the image effect. Likewise, if a plug-in launches its own threads and calls suite functions, it will be unable to access any internal state.

So...2 questions:

A) I see 2 solutions to make the thread-storage solution work:
-  either pass an image effect handle to the multiThread suite function of the plug-in calling the function so that we can duplicate the thread-storage: This will not translate to plug-in spawned threads as we have no way to duplicate thread-storage on them

- Forbid completely in the official spec the usage of any suite function because the host is unable to guarantee the internal state when called in such manner. For me this is the solution that makes much sense because the threads spawned by the multi-thread suite are supposed to be workers that will run a short amount of time and shouldn't call suite functions in the middle "EXCEPT" the abort() function!

B) Do you have any advice on how we could store the arguments of an action so that they are local to an action AND thread-safe ? Maybe our knowledge is limited in possible implementations too;)

Alex

PierreJasmin_REVisionEffects

unread,
Oct 13, 2014, 11:38:59 PM10/13/14
to ofx-dis...@googlegroups.com


On Wednesday, October 8, 2014 8:20:45 PM UTC+8, Alexandre Gauthier wrote:
Hey,

Seems we're reaching a dead-end here in Natron when trying to maintain the internal state expected by the plug-in when calling suite functions if they are called by a thread of the multi-thread suite or any other thread that wasn't spawned by the Host.





Alexandre

I don't fully understand your question, normally when multi-threading you would fetch image on main thread then access it with worker threads. One still needs to read param values...

If the Multi-thread suite causes you issues, you can not support it.

Pierre
 

Alexandre

unread,
Oct 14, 2014, 5:04:36 AM10/14/14
to ofx-dis...@googlegroups.com
Maybe a clearer example:

In the render action, issued by a thread controlled by the host, you call

srcClip->fetchImage(args.time)  (which calls clipGetImage) 

The host needs to fill the missing parameters to the call of this function to return an appropriate image, namely : 
- The render window
- The render scale
- The optional view if support for the Sony Vegas multi view suite is enabled
- more ...
Which where parameters that were passed to the render action in the first place!

The only solution we found to recover those parameters in a thread-safe manner and that are local to the action is to use Thread-local storage.

This has the down-side that the thread-storage has to be explicitly set before calling the render Action, and that the thread calling the clipGetImage function must be a thread that had it’s local storage set in the first place.

If the thread-local storage wasn’t set for the thread then…
- You don’t know what is the current render window, you can only allocate an image which has the size of the region of definition…
- You don’t know the current render scale at which the call was made, you can only support 1:1 images
- You cannot know the current optional view for the Sony Vegas multi view suite
- etc…

The multi-thread suite is the only suite not passing an OfxImageEffectHandle when calling multiThread. This makes it hard then to duplicate the thread-local storage of the thread calling the multiThread() function to the newly spawned threads, because we don’t have access to the effect using the multi-thread suite!

That’s why we’re unable to set the thread-local storage for the multi-thread suite spawned threads, and that if one of those threads call a suite function which requires an “implicit state maintained by the host", e.g: clipGetImage, then the returned image will NOT be appropriate.

Question is: why not pass to all actions and suite functions an optional void* hostExtraData 
so that the host can easily maintain its own local per-action state easily ?

Was it designed this way because the one designing it had in mind an easy way to recover these parameters that we didn’t think of ?

Alex

--
You received this message because you are subscribed to a topic in the Google Groups "ofx-discussion" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/ofx-discussion/V6F_5pdubWo/unsubscribe.
To unsubscribe from this group and all its topics, send an email to ofx-discussio...@googlegroups.com.
To post to this group, send email to ofx-dis...@googlegroups.com.
Visit this group at http://groups.google.com/group/ofx-discussion.
For more options, visit https://groups.google.com/d/optout.

PierreJasmin_REVisionEffects

unread,
Oct 23, 2014, 7:14:24 PM10/23/14
to ofx-dis...@googlegroups.com


Alexandre,

1. I am not familiar with the C++ wrapper. I am only aware of Nuke using it for their own OFX plugins.
2. Initially the MP suite was more thought like a support convenience to shield people from OS specifics. Maybe it was not a good idea and maybe we might need a different suite here. I added this to the list of issues I maintain.

Pierre

Alexandre

unread,
Oct 24, 2014, 2:09:11 AM10/24/14
to ofx-dis...@googlegroups.com
Pierre, 
It’s not much about the C++ wrapper but about the design of the actions/Image effect suite:

The host calls an action with many arguments and the plug-ins call functions of a suite with less arguments that were provided to the action, typically:

The Render Action

	#include "ofxImageEffect.h"
	#define kOfxImageEffectActionRender                "OfxImageEffectActionRender"
Arguments


OfxStatus(*clipGetImage)(OfxImageClipHandleclip, 
 OfxTime  time, 
 OfxRectD *region, 
 OfxPropertySetHandle *imageHandle);
 


We’ve lost quite a bit of infos here!;) And this is sometimes not possible for the host to recover all parameters correctly in a thread-safe manner, plus this is expensive.

Why not pass to all actions in the InArgs a void* hostExtraData and to all suite functions that same parameter so the host is no longer bothered with maintaining its own datas ? ;)

I do not know how they do this in other hosts, but to us the only viable solution to work-around that issue was to use thread-local storage.

I would really suggest that you think about adding that blind handle to all actions/suite functions, just for safety. This might be a handle to a property set (like done for all inArgs/outArgs) and the host could even add/remove properties in it without harm.

I mean we could safely add parameters to, e.g: the render action and the old plug-ins would still be compatible with the same signature of the function, but wouldn’t use all the properties. Just an idea here but to me which allows a bit more space to the host to do more complex things.

best,

Alex
 


Gary Oberbrunner

unread,
Oct 24, 2014, 8:36:28 AM10/24/14
to ofx-dis...@googlegroups.com

On Fri, Oct 24, 2014 at 2:09 AM, Alexandre <immar...@gmail.com> wrote:
OfxStatus(*clipGetImage)(OfxImageClipHandleclip, 
 OfxTime  time, 
 OfxRectD *region, 
 OfxPropertySetHandle *imageHandle);
 


We’ve lost quite a bit of infos here!;) And this is sometimes not possible for the host to recover all parameters correctly

HI Alexandre; what additional information does the host need at this point to retrieve the clip image?  Unless your host is going to give a different image to each effect instance (?!) I don't see what else you need.  The clip is stored somewhere in the host, and the host data structure pointed to by the clip handle should have all the info the host needs to retrieve it.

--
Gary

Alexandre

unread,
Oct 24, 2014, 2:28:48 PM10/24/14
to ofx-dis...@googlegroups.com
Hello Gary,

In a true multi-threaded environment, the host needs to be able to send multiple render action on the same image effect instance and they can all be at different time, for a different render window at a different scale, etc…
Also for certain suites we also need the view parameter.

Then when the image effect instance calls get clipGetImage suite function on the source clip, our data structure internally has to return an image which is appropriate to the arguments that were passed to the render action in the first place.

To do so, we need to know what was the render window and the render scale passed to the render action in the first place, and optionally the view parameter when supporting multi-view effects.
Well the list can go on, the point being the plug-in doesn’t pass all the arguments needed by the host in the clipGetImage suite function which leads to the need of a way to maintain a state associated to each call to the render action.
This also has to be thread-safe and this information can be different for all threads that are currently running the render action.

So on the host side, there’s one data structure that should do the following:

 Retain the arguments passed to the render action in such a way that each call to the render action has a different set of arguments. When calling clipGetImage, then the host should have some sort of “ID” to fetch the arguments that were passed to the render action of the thread currently calling clipGetImage.
If you still follow me, the only way to perform this is thread-local storage. This is really annoying to maintain and not cheap, plus it doesn’t work for threads that didn’t have their local-storage set in the first place (i.e: threads launched by the plug-in).

It would way easier if there was a blind extra data handle passed to all actions and all suite functions.
The same thing can be achieved by passing-back the InArgs property set given to all actions as a parameter of all suite functions, as proposed in this standard change planned for 1.4 : http://openeffects.org/standard_changes/236

I really hope that the standard pushes it to 1.4 soon as I’m sure this would improve all hosts across the board both. It would reduce complexity (less bugs) and improve efficiency (dereferencing a pointer is way faster than finding an object in a huge map)


Alex




HI Alexandre; what additional information does the host need at this point to retrieve the clip image?  Unless your host is going to give a different image to each effect instance (?!) I don't see what else you need.  The clip is stored somewhere in the host, and the host data structure pointed to by the clip handle should have all the info the host needs to retrieve it.

--
Gary

Gary Oberbrunner

unread,
Oct 24, 2014, 2:39:24 PM10/24/14
to ofx-dis...@googlegroups.com
On Fri, Oct 24, 2014 at 2:28 PM, Alexandre <immar...@gmail.com> wrote:
> Then when the image effect instance calls get clipGetImage suite function on
> the source clip, our data structure internally has to return an image which
> is appropriate to the arguments that were passed to the render action in the
> first place.
>
> To do so, we need to know what was the render window and the render scale
> passed to the render action in the first place, and optionally the view
> parameter when supporting multi-view effects.

I don't think so. You should return the raw un-scaled pixels from the
source always. You should not need to account for render window,
render scale, etc. You _should_ only need clip ID and frame. I'm not
sure what the "view parameter" is. There has been some talk of a
multi-view extension to OFX, but as far as I know there is no standard
for that.

--
Gary

Alexandre

unread,
Oct 24, 2014, 2:55:29 PM10/24/14
to ofx-dis...@googlegroups.com
Sorry, I didn’t mean render window but regions of interest, which are computed using the render window. 

Here are the following steps of what a host do: 

- Host needs to render a certain render window
- Host computes regions of interest over that render window (via the getRegionsOfInterest action)
- Host computes frames (via the getFramesNeeded action)
- Host pre-renders the regions of interests over the frames needed from the input clips 
- Host calls the render action

Now here’s the follow up:

- plug-in calls clipGetImage on the source clip with for parameters time and optional bounds (which may be NULL)
- The host have to return an image of the source clip where at least the previous region of interest specified as been rendered
- The host then fetches from its internal structure what was the last result of getRegionsOfInterest action for the current thread. What happens next is up to the host, but generally it will most likely try to find an image in a cache matching the current parameters and check whether all the region of interest is already rendered. If there is no cache or the image could not be found then it will be rendered for the given region of interest. 
Same thing applies to the renderScale: the host can explicitly have image of different scales, and when clipGetImage is called, it needs to know what is the current render scale otherwise it will only be able to return 1:1 images.
- The host can now return to the plug-in the image and life goes on

Without thread-local storage you can’t deal with it properly: 

- The host could not recover the region of interest for that particular clip
- The host could not recover the render scale

It would have to give you an image of the size of the region of definition (in pixel coordinates) and at render scale 1:1

On 24 Oct 2014, at 20:39, Gary Oberbrunner <ga...@oberbrunner.com> wrote:

 

Ruben Galvao

unread,
Oct 24, 2014, 3:03:24 PM10/24/14
to ofx-dis...@googlegroups.com

Hi, I've also experienced the same problem.
And it's not only with texture requests, for example the getParamValue function can be called by the plugin without the time set; or the plugin could call the getTime function.
If you called the plugin to render two frames from two separate threads, it becomes difficult for the host to know what time to return to the plugin.

--
You received this message because you are subscribed to the Google Groups "ofx-discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ofx-discussio...@googlegroups.com.

Gary Oberbrunner

unread,
Oct 24, 2014, 3:34:44 PM10/24/14
to ofx-dis...@googlegroups.com
On Fri, Oct 24, 2014 at 2:55 PM, Alexandre <immar...@gmail.com> wrote:
...
> It would have to give you an image of the size of the region of definition
> (in pixel coordinates) and at render scale 1:1

According to the spec, that is exactly what I would expect. I'm not
sure what this render scale is. What in the spec makes you think it
should do something different?

And if you need to map from instance back to clip (if you have to
store per-instance state with each clip for whatever reason, or you
just need to know which instance called clipGetImage), can't you just
give a different clip handle to each instance? The host will get that
handle back as the first arg to clipGetImage.

--
Gary

Gary Oberbrunner

unread,
Oct 24, 2014, 3:40:12 PM10/24/14
to ofx-dis...@googlegroups.com
On Fri, Oct 24, 2014 at 3:03 PM, Ruben Galvao <rdsg...@gmail.com> wrote:
> Hi, I've also experienced the same problem.
> And it's not only with texture requests, for example the getParamValue
> function can be called by the plugin without the time set; or the plugin
> could call the getTime function.
> If you called the plugin to render two frames from two separate threads, it
> becomes difficult for the host to know what time to return to the plugin.

If different effect instances have different "current times", then you
should store that in the instance data structure somewhere and make
sure all the handles you pass to the effect (paramHandle etc.) have
pointers back to your instance data. As long as you have an instance
pointer in your paramHandle, then when the plug-in calls
paramGetValue(paramHandle, ...) you'll get that instance pointer back
and can find its current time.

No?

--
Gary

Ruben Galvao

unread,
Oct 24, 2014, 3:50:53 PM10/24/14
to ofx-dis...@googlegroups.com

Yes that is a possible work around. But that means you end up with multiple copies of instances which must be initialised and synchronised.
This makes something that should be simple, overly complicated.
You're basically designing around the limitations of the API instead of having an API that makes the simple things simple.

Gary Oberbrunner

unread,
Oct 24, 2014, 3:56:10 PM10/24/14
to ofx-dis...@googlegroups.com
On Fri, Oct 24, 2014 at 3:50 PM, Ruben Galvao <rdsg...@gmail.com> wrote:
> Yes that is a possible work around. But that means you end up with multiple
> copies of instances which must be initialised and synchronised.
> This makes something that should be simple, overly complicated.
> You're basically designing around the limitations of the API instead of
> having an API that makes the simple things simple.

Perhaps so, but it's been in use for 10 years by many companies and it
would be painful to introduce the changes you're suggesting.

I also don't see how it multiplies instances beyond what you already
have. Many hosts already keep a "UI instance" and one or more "render
instances", and synchronize them as needed. I'm a plug-in guy, not a
host guy, but I don't think the host guys will tell you it's overly
complicated. The spec already tries to be clear about when plug-ins
are allowed to alter their state, partly to make this synchronization
easy.

--
Gary

Alexandre

unread,
Oct 24, 2014, 4:21:28 PM10/24/14
to ofx-dis...@googlegroups.com

Yes that is a possible work around. But that means you end up with multiple copies of instances which must be initialised and synchronised.
This makes something that should be simple, overly complicated.
You're basically designing around the limitations of the API instead of having an API that makes the simple things simple.

This is exactly my point.
The API is tailored in a way that some parameters are hidden. This is great for plug-in developers but not so great for hosts.

I already told you one possible way to handle it for a host: thread-local storage: This is currently the best solution available, to the extent of my knowledge.

There are also 2 other options:

1)- Pass-back the InArgs of the action to all suite functions (the easiest solution on both sides and it would end all problems)
2)- The host tries to have multiple copies of an image effect instance (one OfxImageEffectHandle per thread): While this “could” be possible, I can tell you that I doubt that Bruno Nicoletti (and other authors) thought that API that way when tailoring it: Take a look at the C++ plug-in Support Layer: it wraps one OfxImageEffectHandle by a OFX::ImageEffect.
So if we were to create one image effect for each render we would then to have to initialise each OfxImageEffectHandle, that is:

- Call createInstanceAction which can be expensive on plug-in side (the host needs to re-create all parameters & clips)
Take a plug-in like Genarts ParticleIllusion which has over 500 parameters, this can then become a real bottleneck/

Clearly this solution is not the one meant by the specification. 

Maybe there’re other options which I’m unaware of, but the problem looks so simple that I believe it’s either:

- Something we didn’t think about which makes it trivial to solve the problem 
- A mistake in the API, but it sounds weird that in 10 years no one reported anything wrong about it.

While I’m all for the “keep what already works”, I hope we really exposed to you the limitations of the API regarding  multi-threading (multiple concurrent frames rendering) and optimisations that the Host can do.

Again: applying the standard changed mentioned in my previous mail would both increase performance of all hosts across the board and make the life easier for the hosts . This should probably also could remove some bugs in Host implementations because the current solution of “copying” many image effect instances or “maintaining” a thread-local storage are really cumbersome.

...
It would have to give you an image of the size of the region of definition

(in pixel coordinates) and at render scale 1:1
According to the spec, that is exactly what I would expect.  I'm not

sure what this render scale is.  What in the spec makes you think it
should do something different?


If the host should really render only the region of definition and at scale 1:1 then there’s no point in having different properties to define an image, see : http://openfx.sourceforge.net/Documentation/1.3/ofxProgrammingReference.html#kOfxImagePropBounds
For less than full frame images, the pixel bounds will be contained by the kOfxImagePropRegionOfDefinition bounds.

What matters is that the host rendered the region of interest the plug-in supplied beforehand, not that it rendered the whole image.


And if you need to map from instance back to clip (if you have to
store per-instance state with each clip for whatever reason, or you
just need to know which instance called clipGetImage), can't you just
give a different clip handle to each instance?  The host will get that
handle back as the first arg to clipGetImage.

Please refer to the beginning of my mail, having multiple copies of an image effect is not a solution, this is a huge limitation for the host and alters efficiency and clarity. This is at most a workaround.


You received this message because you are subscribed to a topic in the Google Groups "ofx-discussion" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/ofx-discussion/V6F_5pdubWo/unsubscribe.
To unsubscribe from this group and all its topics, send an email to ofx-discussio...@googlegroups.com.

Gary Oberbrunner

unread,
Oct 24, 2014, 4:47:53 PM10/24/14
to ofx-dis...@googlegroups.com
On Fri, Oct 24, 2014 at 4:21 PM, Alexandre <immar...@gmail.com> wrote:
...
> So if we were to create one image effect for each render we would then to
> have to initialise each OfxImageEffectHandle, that is:
>
> - Call createInstanceAction which can be expensive on plug-in side (the host
> needs to re-create all parameters & clips)
> Take a plug-in like Genarts ParticleIllusion which has over 500 parameters,
> this can then become a real bottleneck/

Yes, I know it well. :-) If your host is slow on this, just wait.
It'll get worse in the future.

But you don't have to do it once per render, just once per instance
per thread. You can keep those instances around.

But actually I think it's simpler than that. You clearly have some
concept in your host of two "instances" of the plug-in, one of which
you want to render at time t1, in thread 1, with a certain RoI, and
the other at t2 in thread 2 and its own RoI. I think you can still
have only one real plug-in instance (only call createInstanceAction
once), but the struct pointed to by your clip handle can have a
pointer to the "real" plug-in instance and also whatever per-call data
you're maintaining (the RoIs and whatever else you care about). The
plugin will pass that back to you in clipGetImage. Now at this point
I'm out of my depth, but perhaps it'll help.

--
Gary

Alexandre

unread,
Oct 24, 2014, 5:02:19 PM10/24/14
to ofx-dis...@googlegroups.com
>
> Yes, I know it well. :-) If your host is slow on this, just wait.
> It'll get worse in the future.
>
> But you don't have to do it once per render, just once per instance
> per thread. You can keep those instances around.

Even if the host has a thread-pool, having to clone and synchronise parameters/clips around before rendering anything is really a performance drop whereas we could just pass a pointer to an InArgs in parameter!

>
> But actually I think it's simpler than that. You clearly have some
> concept in your host of two "instances" of the plug-in, one of which
> you want to render at time t1, in thread 1, with a certain RoI, and
> the other at t2 in thread 2 and its own RoI. I think you can still
> have only one real plug-in instance (only call createInstanceAction
> once), but the struct pointed to by your clip handle can have a
> pointer to the "real" plug-in instance and also whatever per-call data
> you're maintaining (the RoIs and whatever else you care about). The
> plugin will pass that back to you in clipGetImage. Now at this point
> I'm out of my depth, but perhaps it'll help.
>

Yes we tried that solution, unfortunately the C++ Support layer as proposed by the ofx official repository ( and our Support layer is based on that https://github.com/devernay/openfx ) does not allow having different clips instances/parameters instances for a single image effect instance.
It’s either you clone the whole thing or not, that’s why I wrote previously that I don’t think the API was meant to end-up to be used the way you describe.

In the end our thread-storage solution we currently have in Natron is way more efficient than cloning/copying the state of all clips/parameters before calling a single render, but is limited in the situation where the plug-in make calls to suite functions on a thread that do not have thread-storage set.

For example if a plug-in starts a new thread and in this thread calls clipGetImage, well in Natron we will be unable to recover the state (but we have some fallback option: we call getRegionsOfInterests again and try to recover the render scale )

> --
> Gary
>
> --

Paul Miller

unread,
Oct 24, 2014, 5:13:23 PM10/24/14
to ofx-dis...@googlegroups.com

> For example if a plug-in starts a new thread and in this thread calls clipGetImage, well in Natron we will be unable to recover the state (but we have some fallback option: we call getRegionsOfInterests again and try to recover the render scale )

But surely know what the render scale is? I don't think it was intended
for a plugin to ask for a render scale that was different than defined
by the host?

I'll stop calling you surely now.

Gary Oberbrunner

unread,
Oct 24, 2014, 5:18:52 PM10/24/14
to ofx-dis...@googlegroups.com
On Fri, Oct 24, 2014 at 5:02 PM, Alexandre <immar...@gmail.com> wrote:
>>
>> Yes, I know it well. :-) If your host is slow on this, just wait.
>> It'll get worse in the future.
>>
>> But you don't have to do it once per render, just once per instance
>> per thread. You can keep those instances around.
>
> Even if the host has a thread-pool, having to clone and synchronise parameters/clips around before rendering anything is really a performance drop whereas we could just pass a pointer to an InArgs in parameter!

I see you would like this. But it's not a backward-compatible change,
and getting all the hosts and plug-ins to change would not be easy and
would take years. You will have to choose between performance and
compatibility, unless you can make changes in your architecture that
allow both.

>> But actually I think it's simpler than that. You clearly have some
>> concept in your host of two "instances" of the plug-in, one of which
>> you want to render at time t1, in thread 1, with a certain RoI, and
>> the other at t2 in thread 2 and its own RoI. I think you can still
>> have only one real plug-in instance (only call createInstanceAction
>> once), but the struct pointed to by your clip handle can have a
>> pointer to the "real" plug-in instance and also whatever per-call data
>> you're maintaining (the RoIs and whatever else you care about). The
>> plugin will pass that back to you in clipGetImage. Now at this point
>> I'm out of my depth, but perhaps it'll help.
>
> Yes we tried that solution, unfortunately the C++ Support layer as proposed by the ofx official repository ( and our Support layer is based on that https://github.com/devernay/openfx ) does not allow having different clips instances/parameters instances for a single image effect instance.
> It’s either you clone the whole thing or not, that’s why I wrote previously that I don’t think the API was meant to end-up to be used the way you describe.

The C++ support layer is very basic and mostly unmaintained (except
for devernay, who is working on it). I don't think anyone commercial
uses it. Tuttle does, but Tuttle is also quite simple in many ways.

If you're writing a serious host, you're probably better off with the
C interface. Perhaps that is the architectural change I referred to
above, that could gain you high performance _and_ good compatibility.

Good luck!

--
Gary

Alexandre

unread,
Oct 24, 2014, 6:46:06 PM10/24/14
to ofx-dis...@googlegroups.com, Frédéric Devernay
>
> But surely know what the render scale is? I don't think it was intended for a plugin to ask for a render scale that was different than defined by the host?
>
> I'll stop calling you surely now.
>

Render scale = scale at which the host wants the plug-in to render the image.
In Nuke for example this corresponds to the drop-down on top of the Viewer. It corresponds to downscale power of 2s
When it is set for instance to 4 the render scale will be set actually to 0.25

This way all images are downscaled and the rendering much faster. This is also commonly used by hosts when images are zoomed out and possibly when the user is actively seeking the timeline while still maintaining the left button pressed.

Of course the plug-in is never asking for any render scale… it is just receiving in parameters from the host! But when calling clipGetImage the host has to provide an image which is relevant regarding the parameters given to the previous call to the render action.

@Gary:

> I see you would like this. But it's not a backward-compatible change,
> and getting all the hosts and plug-ins to change would not be easy and
> would take years. You will have to choose between performance and
> compatibility, unless you can make changes in your architecture that
> allow both.


This is actually quite simple to add: You introduce ImageEffectSuiteV2 PropertySuiteV2, etc… with all suite functions passing back a handle to the PropertySet of the InArgs passed to the corresponding action.

The hosts that do not want to change their code will still have compatibility with plug-ins of ImageEffectSuiteV1, PropertySuiteV1 (that is all ofx plug-ins on earth) and the host that do want to support the V2 can just implement it and it will then be compatible with V1 and V2… well thats pretty much like every change the standard has made so far: it maintains backward compatibility
on host side...

> The C++ support layer is very basic and mostly unmaintained (except
> for devernay, who is working on it). I don't think anyone commercial
> uses it. Tuttle does, but Tuttle is also quite simple in many ways.
>

I’m working with devernay and I’m a maintainer of that layer too.
I would tend to think that Nuke do use that layer too (though in a more evolved version that what’s on the ofxa repo)

I do not think that the layer is very basic, it certainly had bugs in the version on the ofxa repo but it allows to develop everything as per the standard.

> If you're writing a serious host, you're probably better off with the
> C interface. Perhaps that is the architectural change I referred to
> above, that could gain you high performance _and_ good compatibility.

Allow me to disagree on this, the cloning and copying of all those information is - to my own experience as a host developer - way more expensive than the other options I enunciated in my previous mail.

You get good compatibility when introducing new suites versions too, you just let a chance for hosts to evolve on a less error-prone base and everyone benefit of it. If some host do not want to support new versions - fine, nothing changes.

I’m not sure that I can report more on the issue now, if other host developers want to contribute to the discussion it would be much appreciated.

Alex
Reply all
Reply to author
Forward
0 new messages