Product: Fusion (standalone)
Category: OFX host compliance — image buffer allocation
Severity: High — produces permanently incorrect renders that survive in the frame cache
Summary
When two instances of the same OFX plugin are both rendered for the first time in the same playback burst (e.g., dragging a frame to the viewer while both nodes are active in the timeline), Fusion provides the same host image buffer address to both instances for their source clip and their destination clip across approximately 13–14 frames.
This violates the OFX 1.4 specification requirement that each distinct effect node must receive a unique writable output image. The result is that both instances write their output to the same memory address sequentially — the first writer's result is destroyed by the second — and Fusion's frame cache then permanently serves the corrupted output for those frames until the composition is closed and reopened.
How to Reproduce
Setup
- Create a Fusion composition with two instances of the same OFX plugin placed on independent, parallel branches — each connected to its own distinct upstream node (e.g., two separate MediaIn nodes). The instances must not be chained (the output of one must not feed the other).
- Configure each instance with clearly different parameter values so their outputs are visually distinct.
- The plugin must write to its OFX output image (i.e., not a passthrough effect). A GPU-accelerated plugin that renders to the full frame is ideal for making the bug visually apparent.
Steps
- Close and reopen the composition to clear all caches.
- Navigate to a frame where both instances are simultaneously active in the timeline.
- Drag that frame into the Fusion viewer to trigger the initial render burst.
- Observe incorrect / mixed output on approximately 13–14 frames starting from the first rendered frame.
- Scrub back to those frames — the incorrect output persists. It is never re-evaluated; closing the composition is required to reset.
Evidence: Buffer Address Log
The following addresses were captured by logging OFX::Image::getPixelData() for both the source clip (fetchImage on the connected input) and the destination clip (fetchImage on the output) inside the plugin's render() implementation, for each instance, for each frame.
Code: Select all
// Frames 1105–1118: both instances receive identical buffer addresses
// despite being connected to independent upstream nodes
Instance A frame=1105 src=0000001B50200000 dst=0000001B48200000
Instance B frame=1105 src=0000001B50200000 dst=0000001B48200000 ← aliased
Instance A frame=1106 src=0000001B50200000 dst=0000001B48200000
Instance B frame=1106 src=0000001B50200000 dst=0000001B48200000 ← aliased
// ... identical for every frame through 1118 ...
// Frame 1119 onward: unique buffers per instance — correct behaviour resumes
Instance A frame=1119 src=0000001DF5000000 dst=0000001B48200000
Instance B frame=1119 src=0000001E05000000 dst=0000001DFD000000 ← correctKey observations:
- Source buffers are aliased across both instances for frames 1105–1118, despite each instance being connected to a completely independent upstream node.
- Destination buffers are aliased across both instances for the same frame range. Instance A writes its result; Instance B then overwrites the same address. Fusion caches the final state of that address as the authoritative output for both nodes.
- From frame 1119 onward, Fusion allocates unique buffers per instance and all output is correct.
- Both instances execute sequentially on the same render thread — there is no concurrency involved.
Expected Behaviour
Per the OFX 1.4 Image Effect specification:
Each call to
clipGetImagefor a distinct clip/instance/time must return an image whose pixel storage is not aliased to any other live image returned to any other instance.
Two effect instances on independent branches with independent upstream nodes must each receive:
- A source image whose pixel data reflects their own connected upstream node's output for that frame.
- A destination image whose pixel storage is not aliased to any other effect's destination for the same frame.