Rendering

The kOfxImageEffectActionRender action is passed to plugins, when the host requires them to render an output frame.

All calls to the kOfxImageEffectActionRender are bracketed by a pair of kOfxImageEffectActionBeginSequenceRender and kOfxImageEffectActionEndSequenceRender actions. This is to allow plugins to prepare themselves for rendering long sequences by setting up any tables etc.. it may need.

The kOfxImageEffectActionBeginSequenceRender will indicate the frame range that is to be renderred, and whether this is purely a single frame render due to interactive feedback from a user in a GUI.

The render action is used in conjunction with the optional

Identity Effects

If an effect does nothing to its input clips (for example a blur with blur size set to ‘0’) it can indicate that it is an identity function via the kOfxImageEffectActionIsIdentity action. The plugin indicates which input the host should use for the region in question. This allows a host to short circuit the processing of an effect.

Rendering and The Get Region Actions

Many hosts attempt to minimise the areas that they render by using regions of interest and regions of definition, while some of the simpler hosts do not attempt to do so. In general the order of actions, per frame rendered, is something along the lines of….

  • ask the effect for it’s region of definition,

  • clip the render window against that

  • ask the effect for the regions of interest of each of it’s inputs against the clipped render window,

  • clip those regions of interest against the region of definition of each of those inputs,

  • render and cache each of those inputs,

  • render the effect against it’s clipped render window.

A host can ask an effect to render an arbitrary window of pixels, generally these should be clipped to an effect’s region of definition, however, depending on the host, they may not be. The actual region to render is indicated by the kOfxImageEffectPropRenderWindow render action argument. If an effect is asked to render outside of its region of definition, it should fill those pixels in with black transparent pixels.

Note thate OfxImageEffectSuiteV1::clipGetImage() function takes an optional region parameter. This is a region, in Canonical coordinates, that the effect would like on that input clip. If not used in a render action, then the image returned should be based on the previous get region of interest action. If used, then the image returned will be based on this (usually be clipped to the input’s region of definition). Generally a plugin should not use the region parameter in the render action, but should leave it to the ‘default’ region.

Multi-threaded Rendering

Multiple render actions may be passed to an effect at the same time. A plug-in states it’s level of render thread safety by setting the kOfxImageEffectPluginRenderThreadSafety string property. This can be set to one of three states….

kOfxImageEffectRenderUnsafe

String used to label render threads as un thread safe, see, kOfxImageEffectPluginRenderThreadSafety.

Indicating that only a single ‘render’ action can be made at any time among all instances

kOfxImageEffectRenderInstanceSafe

String used to label render threads as instance thread safe, kOfxImageEffectPluginRenderThreadSafety.

Indicating that any instance can have a single ‘render’ action at any one time

kOfxImageEffectRenderFullySafe

String used to label render threads as fully thread safe, kOfxImageEffectPluginRenderThreadSafety.

Indicating that any instance of a plugin can have multiple renders running simultaneously

Rendering in a Symmetric Multi Processing Environment

When rendering on computers that have more that once CPU (or this new-fangled hyperthreading), hosts and effects will want to take advantage of all that extra CPU goodness to speed up rendering. This means multi-threading of the render function in some way.

If the plugin has set kOfxImageEffectPluginRenderThreadSafety to kOfxImageEffectRenderFullySafe, the host may choose to render a single frame across multiple CPUs by having each CPU render a different window. However, the plugin may wish to remain in charge of multithreading a single frame. The plugin set property kOfxImageEffectPluginPropHostFrameThreading informs the host as to whether the host should perform SMP on the effect. It can be set to either…

  • 1, in which case the host will attempt to multithread an effect instance by calling it’s render function called simultaneously, each call will be with a different renderWindow, but be at the same frame

  • 0, in which case the host only ever calls the render function once per frame. If the effect wants to multithread it must use the OfxMultiThreadSuite API.

A host may have a render farm of computers. Depending exactly how the host works with it’s render farm, it may have multiple copies on an instance spread over the farm rendering separate frame ranges, 1-100 on station A, 101 to 200 on station B and so on…

Rendering Sequential Effects

Some plugins need the output of the previous frame to render the next, typically they cache some information about the last render and use that somehow on the next frame. Some temporally averaging degraining algorithms work that way. Such effects cannot render correctly unless they are strictly rendered in order, from first to last frame, on a single instance.

Other plugins are able to render correctly when called in an arbitrary frame order, but render much more efficiently if rendered in order. For example a particle system which maintains the state of the particle system in an instance would simply increment the simulation by a frame if rendering in-order, but would need to restart the particle system from scratch if the frame jumped backwards.

Most plug-ins do not have any sequential dependence. For example, a simple gain operation has no dependence on the previous frame.

Similarly, host applications, due to their architectures, may or may not be able to guarantee that a plugin can be rendered strictly in-order. Node based applications typically have much more difficulty in guaranteeing such behaviour.

To indicate whether a plugin needs to be rendered in a strictly sequential order, and to indicate whether a host supports such behaviour we have a property, kOfxImageEffectInstancePropSequentialRender. For plug-ins this can be one of three values…

  • 0, in which case the host can render an instance over arbitrary frame ranges on an arbitrary number of computers without any problem (default),

  • 1, in which case the host must render an instance on a single computer over it’s entire frame range, from first to last.

  • 2, in which case the effect is more efficiently rendered in frame order, but can compute the correct result regardless of render order.

For hosts, this property takes three values…

  • 0, which indicates thet the host can never guarantee sequential rendering,

  • 1, which indicates thet the host can guarantee sequential rendering for plugins that request it,

  • 2, which indicates thet the host can sometimes perform sequential rendering.

When rendering, a host will set the in args property on kOfxImageEffectPropSequentialRenderStatus to indicate whether the host is currently supporting sequential renders. This will be passed to the following actions,

  • the begin sequence render action

  • the sequence render action

  • the end sequence render action

Hosts may still render sequential effects with random frame access in interactive sessions, for example when the user scrubs the current frame on the timeline and the host asks an effect to render a preview frame. In such cases, the plugin can detect that the instance is being interactively manipulated via the kOfxImageEffectPropInteractiveRenderStatus property and hack an approximation together for UI purposes. If eventually rendering the sequence, the host must ignore all frames rendered out of order and not cache them for use in the final result.

A host may set the in args property kOfxImageEffectPropRenderQualityDraft in :c:macro:kOfxImageEffectActionRender` to ask for a render in Draft/Preview mode. This is useful for applications that must support fast scrubbing. These allow a plug-in to take short-cuts for improved performance when the situation allows and it makes sense, for example to generate thumbnails with effects applied. For example switch to a cheaper interpolation type or rendering mode. A plugin should expect frames rendered in this manner that will not be stuck in host cache unless the cache is only used in the same draft situations.

OFX : Fields and Field Rendering

Fields are evil, but until the world decides to adopt sensible video standard and casts the current ones into the same pit as 2 inch video tape, we are stuck with them.

Before we start, some nomenclature. The Y-Axis is considerred to be up, so in a fielded image,

  • even scan lines 0,2,4,6,… are collectively referred to as the lower field,

  • odd scan lines 1,3,5,7… are collective referred to as the upper field.

We don’t call them odd and even, so as to avoid confusion with video standard, which have scanline 0 at the top, and so have the opposite sense of our ‘odd’ and ‘even’.

Clips and images from those clips are flagged as to whether they are fielded or not, and if so what is the spatial/temporal ordering of the fields in that image. The kOfxImageClipPropFieldOrder clip and image instance property can be…

kOfxImageFieldNone

String used to label imagery as having no fields

The material is unfielded

kOfxImageFieldLower

String used to label the lower field (scan lines 0,2,4…) of fielded imagery

The material is fielded, with scan line 0,2,4…. occurring first in a frame

kOfxImageFieldUpper

String used to label the upper field (scan lines 1,3,5…) of fielded imagery

The material is fielded, with scan line 1,3,5…. occurring first in a frame

Images extracted from a clip flag what their fieldedness is with the property kOfxImagePropField, this can be….

kOfxImageFieldNone

String used to label imagery as having no fields

The image is an unfielded frame

kOfxImageFieldBoth

String used to label both fields of fielded imagery, indicating interlaced footage

The image is fielded and contains both interlaced fields

kOfxImageFieldLower

String used to label the lower field (scan lines 0,2,4…) of fielded imagery

The image is fielded and contains a single field, being the lower field (lines 0,2,4…)

kOfxImageFieldUpper

String used to label the upper field (scan lines 1,3,5…) of fielded imagery

The image is fielded and contains a single field, being the upper field (lines 1,3,5…)

The plugin specifies how it deals with fielded imagery by setting the kOfxImageEffectPluginPropFieldRenderTwiceAlways property. This can be,

  • 0 - the plugin is to have it’s render function called twice only if there is animation in any of it’s parameters

  • 1 - the plugin is to have it’s render function called twice always (default)

The reason for this is an optimisation. Imagine a text generator with no animation being asked to render into a fielded output clip, it can treat an interlaced fielded image as an unfielded frame. So the host can get the effect to render both fields in one hit and save on the overhead required to do the rendering in two passes.

If called twice per frame, the time passed to the render action will be frame and frame+0.5. So 0.0 0.5 1.0 1.5 etc…

When rendering unfielded footage, the host will only ever call the effect’s render action once per frame, with the time being at the integers, 0.0, 1.0, 2.0 and so on.

The render action’s argument property kOfxImageEffectPropFieldToRender tells the effect which field it should render, this can be one of…

A plugin can specify how it wishes fielded footage to be fetched from a clip via the clip descriptor property kOfxImageClipPropFieldExtraction. This can be one of…

Fetch a full frame interlaced image

Fetch a single field, making a half height image

Fetch a single field, but doubling each line and so making a full

height image (default)

If fetching a single field, the actual field fetched from the source frame is…

  • the first temporal field if the time passed to clipGetImage has a fractional part of 0.0 <= f < 0.5

  • the second temporal field otherwise,

To illustrate this last behaviour, the two examples below show an output with twice the frame rate of the input and how clipGetImage maps to the input. The .0 and .5 mean first and second temporal fields.

Behaviour with unfielded footage

output 0       1       2       3
source 0       0       1       1
Behaviour with fielded footage

output 0.0 0.5 1.0 1.5 2.0 2.5 3.0 3.5
source 0.0 0.0 0.5 0.5 1.0 1.0 1.5 1.5

NOTE

  • while some rarely used video standards can have odd number of scan-lines, under OFX, both fields always consist of the same number of lines. Pad with black where needed.

  • host developers, for single field extracted images, you don’t need to do any buffer copies, you just need to set the row bytes property of the returned image to twice the normal value, and maybe tweak the start address by a scanline.

Rendering In An Interactive Environment

Any host with an interface will most likely have an interactive thread and a rendering thread. This allows an effect to be manipulated while having renders batched off to a background thread. This will mean that some degree of locking will go on to prevent simultaneous read/writes occurring, see this section for more on thread safety.

A host may need to abort a backgrounded render, typically in response to a user changing a parameter value. An effect should occasionally poll the OfxImageEffectSuiteV1::abort() function to see if it should give up on rendering.

Rendering on GPU

This file contains an optional suite for performing GPU-accelerated
rendering of OpenFX Image Effect Plug-ins.  For details see
\ref ofxGPURender.

It allows hosts and plugins to support OpenGL, CUDA, Metal and other
GPU acceleration methods.

StatusReturnValues

OfxStatus returns indicating that a OpenGL render error has occurred:

  • If a plug-in returns kOfxStatGLRenderFailed, the host should retry the render with OpenGL rendering disabled.

  • If a plug-in returns kOfxStatGLOutOfMemory, the host may choose to free resources on the GPU and retry the OpenGL render, rather than immediately falling back to CPU rendering.

kOfxStatGPUOutOfMemory

GPU render ran out of memory.

kOfxStatGLOutOfMemory

OpenGL render ran out of memory (same as kOfxStatGPUOutOfMemory)

kOfxStatGPURenderFailed

GPU render failed in a non-memory-related way.

kOfxStatGLRenderFailed

OpenGL render failed in a non-memory-related way (same as kOfxStatGPURenderFailed)

Defines

__OFXGPURENDER_H__
kOfxOpenGLRenderSuite

The name of the OpenGL render suite, used to fetch from a host via OfxHost::fetchSuite.

kOfxImageEffectPropOpenGLRenderSupported

Indicates whether a host or plugin can support OpenGL accelerated rendering.

  • Type - C string X 1

  • Property Set - plugin descriptor (read/write), host descriptor (read only) - plugin instance change (read/write)

  • Default - “false” for a plugin

  • Valid Values - This must be one of

    • ”false” - in which case the host or plugin does not support OpenGL accelerated rendering

    • ”true” - which means a host or plugin can support OpenGL accelerated rendering, in the case of plug-ins this also means that it is capable of CPU based rendering in the absence of a GPU

    • ”needed” - only for plug-ins, this means that an effect has to have OpenGL support, without which it cannot work.

V1.4: It is now expected from host reporting v1.4 that the plugin can during instance change switch from true to false and false to true.

kOfxOpenGLPropPixelDepth

Indicates the bit depths supported by a plug-in during OpenGL renders.

This is analogous to kOfxImageEffectPropSupportedPixelDepths. When a plug-in sets this property, the host will try to provide buffers/textures in one of the supported formats. Additionally, the target buffers where the plug-in renders to will be set to one of the supported formats.

Unlike kOfxImageEffectPropSupportedPixelDepths, this property is optional. Shader-based effects might not really care about any format specifics when using OpenGL textures, so they can leave this unset and allow the host the decide the format.

kOfxImageEffectPropOpenGLEnabled

Indicates that an image effect SHOULD use OpenGL acceleration in the current action.

When a plugin and host have established they can both use OpenGL renders then when this property has been set the host expects the plugin to render its result into the buffer it has setup before calling the render. The plugin can then also safely use the ‘OfxImageEffectOpenGLRenderSuite’

v1.4: kOfxImageEffectPropOpenGLEnabled should probably be checked in Instance Changed prior to try to read image via clipLoadTexture

Note

Once this property is set, the host and plug-in have agreed to use OpenGL, so the effect SHOULD access all its images through the OpenGL suite.

kOfxImageEffectPropOpenGLTextureIndex

Indicates the texture index of an image turned into an OpenGL texture by the host.

kOfxImageEffectPropOpenGLTextureTarget

Indicates the texture target enumerator of an image turned into an OpenGL texture by the host.

The property set of the following actions should contain this property:

kOfxActionOpenGLContextAttached

Action called when an effect has just been attached to an OpenGL context.

The purpose of this action is to allow a plugin to set up any data it may need to do OpenGL rendering in an instance. For example…

  • allocate a lookup table on a GPU,

  • create an openCL or CUDA context that is bound to the host’s OpenGL context so it can share buffers.

The plugin will be responsible for deallocating any such shared resource in the kOfxActionOpenGLContextDetached action.

A host cannot call kOfxActionOpenGLContextAttached on the same instance without an intervening kOfxActionOpenGLContextDetached. A host can have a plugin swap OpenGL contexts by issuing a attach/detach for the first context then another attach for the next context.

The arguments to the action are…

  • handle handle to the plug-in instance, cast to an OfxImageEffectHandle

  • inArgs is redundant and set to NULL

  • outArgs is redundant and set to NULL

A plugin can return…
  • kOfxStatOK, the action was trapped and all was well

  • kOfxStatReplyDefault, the action was ignored, but all was well anyway

  • kOfxStatErrMemory, in which case this may be called again after a memory purge

  • kOfxStatFailed, something went wrong, but no error code appropriate, the plugin should to post a message if possible and the host should not attempt to run the plugin in OpenGL render mode.

kOfxActionOpenGLContextDetached

Action called when an effect is about to be detached from an OpenGL context.

The purpose of this action is to allow a plugin to deallocate any resource allocated in kOfxActionOpenGLContextAttached just before the host decouples a plugin from an OpenGL context. The host must call this with the same OpenGL context active as it called with the corresponding kOfxActionOpenGLContextAttached.

The arguments to the action are…

  • handle handle to the plug-in instance, cast to an OfxImageEffectHandle

  • inArgs is redundant and set to NULL

  • outArgs is redundant and set to NULL

A plugin can return…
  • kOfxStatOK, the action was trapped and all was well

  • kOfxStatReplyDefault, the action was ignored, but all was well anyway

  • kOfxStatErrMemory, in which case this may be called again after a memory purge

  • kOfxStatFailed, something went wrong, but no error code appropriate, the plugin should to post a message if possible and the host should not attempt to run the plugin in OpenGL render mode.

kOfxImageEffectPropCudaRenderSupported

Indicates whether a host or plugin can support Cuda render.

  • Type - string X 1

  • Property Set - plugin descriptor (read/write), host descriptor (read only)

  • Default - “false”

  • Valid Values - This must be one of

    • ”false” - the host or plugin does not support Cuda render

    • ”true” - the host or plugin can support Cuda render

kOfxImageEffectPropCudaEnabled

Indicates that an image effect SHOULD use Cuda render in the current action.

If a plugin and host have both set kOfxImageEffectPropCudaRenderSupported=”true” then the host MAY set this property to indicate that it is passing images as Cuda memory pointers.

  • Type - int X 1

  • Property Set - inArgs property set of the kOfxImageEffectActionRender action

  • Valid Values

    • 0 indicates that the kOfxImagePropData of each image of each clip is a CPU memory pointer.

    • 1 indicates that the kOfxImagePropData of each image of each clip is a Cuda memory pointer.

kOfxImageEffectPropCudaStreamSupported

Indicates whether a host or plugin can support Cuda streams.

  • Type - string X 1

  • Property Set - plugin descriptor (read/write), host descriptor (read only)

  • Default - “false”

  • Valid Values - This must be one of

    • ”false” - in which case the host or plugin does not support Cuda streams

    • ”true” - which means a host or plugin can support Cuda streams

kOfxImageEffectPropCudaStream

The Cuda stream to be used for rendering.

  • Type - pointer X 1

  • Property Set - inArgs property set of the kOfxImageEffectActionRender action

This property will only be set if the host and plugin both support Cuda streams.

If set:

  • this property contains a pointer to the stream of Cuda render (cudaStream_t). In order to use it, reinterpret_cast<cudaStream_t>(pointer) is needed.

  • the plugin SHOULD ensure that its render action enqueues any asynchronous Cuda operations onto the supplied queue.

  • the plugin SHOULD NOT wait for final asynchronous operations to complete before returning from the render action, and SHOULD NOT call cudaDeviceSynchronize() at any time.

If not set:

  • the plugin SHOULD ensure that any asynchronous operations it enqueues have completed before returning from the render action.

kOfxImageEffectPropMetalRenderSupported

Indicates whether a host or plugin can support Metal render.

  • Type - string X 1

  • Property Set - plugin descriptor (read/write), host descriptor (read only)

  • Default - “false”

  • Valid Values - This must be one of

    • ”false” - the host or plugin does not support Metal render

    • ”true” - the host or plugin can support Metal render

kOfxImageEffectPropMetalEnabled

Indicates that an image effect SHOULD use Metal render in the current action.

If a plugin and host have both set kOfxImageEffectPropMetalRenderSupported=”true” then the host MAY set this property to indicate that it is passing images as Metal buffers.

  • Type - int X 1

  • Property Set - inArgs property set of the kOfxImageEffectActionRender action

  • Valid Values

    • 0 indicates that the kOfxImagePropData of each image of each clip is a CPU memory pointer.

    • 1 indicates that the kOfxImagePropData of each image of each clip is a Metal id<MTLBuffer>.

kOfxImageEffectPropMetalCommandQueue

The command queue of Metal render.

  • Type - pointer X 1

  • Property Set - inArgs property set of the kOfxImageEffectActionRender action

This property contains a pointer to the command queue to be used for Metal rendering (id<MTLCommandQueue>). In order to use it, reinterpret_cast<id<MTLCommandQueue>>(pointer) is needed.

The plugin SHOULD ensure that its render action enqueues any asynchronous Metal operations onto the supplied queue.

The plugin SHOULD NOT wait for final asynchronous operations to complete before returning from the render action.

kOfxImageEffectPropOpenCLRenderSupported

Indicates whether a host or plugin can support OpenCL render.

  • Type - string X 1

  • Property Set - plugin descriptor (read/write), host descriptor (read only)

  • Default - “false”

  • Valid Values - This must be one of

    • ”false” - the host or plugin does not support OpenCL render

    • ”true” - the host or plugin can support OpenCL render

kOfxImageEffectPropOpenCLEnabled

Indicates that an image effect SHOULD use OpenCL render in the current action.

If a plugin and host have both set kOfxImageEffectPropOpenCLRenderSupported=”true” then the host MAY set this property to indicate that it is passing images as OpenCL buffers.

  • Type - int X 1

  • Property Set - inArgs property set of the kOfxImageEffectActionRender action

  • Valid Values

    • 0 indicates that the kOfxImagePropData of each image of each clip is a CPU memory pointer.

    • 1 indicates that the kOfxImagePropData of each image of each clip is a cl_mem.

kOfxImageEffectPropOpenCLCommandQueue

The command queue of OpenCL render.

  • Type - pointer X 1

  • Property Set - inArgs property set of the kOfxImageEffectActionRender action

This property contains a pointer to the command queue to be used for Metal rendering (cl_command_queue). In order to use it, reinterpret_cast<cl_command_queue>(pointer) is needed.

The plugin SHOULD ensure that its render action enqueues any asynchronous OpenCL operations onto the supplied queue.

The plugin SHOULD NOT wait for final asynchronous operations to complete before returning from the render action.

Typedefs

typedef struct OfxImageEffectOpenGLRenderSuiteV1 OfxImageEffectOpenGLRenderSuiteV1

OFX suite that provides image to texture conversion for OpenGL processing.

struct OfxImageEffectOpenGLRenderSuiteV1
#include <ofxGPURender.h>

OFX suite that provides image to texture conversion for OpenGL processing.

Public Members

OfxStatus (*clipLoadTexture)(OfxImageClipHandle clip, OfxTime time, const char *format, const OfxRectD *region, OfxPropertySetHandle *textureHandle)

loads an image from an OFX clip as a texture into OpenGL

  • clip clip to load the image from

  • time effect time to load the image from

  • format requested texture format (As in none,byte,word,half,float, etc..) When set to NULL, the host decides the format based on the plug-in’s kOfxOpenGLPropPixelDepth setting.

  • region region of the image to load (optional, set to NULL to get a ‘default’ region) this is in the CanonicalCoordinates.

  • textureHandle property set containing information about the texture

An image is fetched from a clip at the indicated time for the given region and loaded into an OpenGL texture. When a specific format is requested, the host ensures it gives the requested format. When the clip specified is the “Output” clip, the format is ignored and the host must bind the resulting texture as the current color buffer (render target). This may also be done prior to calling the kOfxImageEffectActionRender action. If the region parameter is set to non-NULL, then it will be clipped to the clip’s Region of Definition for the given time. The returned image will be at least as big as this region. If the region parameter is not set or is NULL, then the region fetched will be at least the Region of Interest the effect has previously specified, clipped to the clip’s Region of Definition. Information about the texture, including the texture index, is returned in the textureHandle argument. The properties on this handle will be…

With the exception of the OpenGL specifics, these properties are the same as the properties in an image handle returned by clipGetImage in the image effect suite.

Note

Pre:

  • clip was returned by clipGetHandle

  • Format property in the texture handle

Post:

  • texture handle to be disposed of by clipFreeTexture before the action returns

  • when the clip specified is the “Output” clip, the format is ignored and the host must bind the resulting texture as the current color buffer (render target). This may also be done prior to calling the render action.

Return:

  • kOfxStatOK - the image was successfully fetched and returned in the handle,

  • kOfxStatFailed - the image could not be fetched because it does not exist in the clip at the indicated time and/or region, the plugin should continue operation, but assume the image was black and transparent.

  • kOfxStatErrBadHandle - the clip handle was invalid,

  • kOfxStatErrMemory - not enough OpenGL memory was available for the effect to load the texture. The plugin should abort the GL render and return kOfxStatErrMemory, after which the host can decide to retry the operation with CPU based processing.

OfxStatus (*clipFreeTexture)(OfxPropertySetHandle textureHandle)

Releases the texture handle previously returned by clipLoadTexture.

For input clips, this also deletes the texture from OpenGL. This should also be called on the output clip; for the Output clip, it just releases the handle but does not delete the texture (since the host will need to read it).

Pre:

  • textureHandle was returned by clipGetImage

Post:

  • all operations on textureHandle will be invalid, and the OpenGL texture it referred to has been deleted (for source clips)

Return:

OfxStatus (*flushResources)()

Request the host to minimize its GPU resource load.

When a plugin fails to allocate GPU resources, it can call this function to request the host to flush its GPU resources if it holds any. After the function the plugin can try again to allocate resources which then might succeed if the host actually has released anything.

Pre:

Post:

  • No changes to the plugin GL state should have been made.

Return: