- Pass through input texture when the LUT processor is not ready yet,
preventing black frames while the processor is being generated.
- Serialize processor generation with a single in-flight task to avoid
concurrent OCIO lock contention that could freeze the UI.
- Invalidate cached frames after the async processor is set so the viewer
refreshes automatically without requiring the playhead to be moved.
- Add OAK_DISABLE_HWACCEL environment variable to force software decoding.
- Add FFmpegDecoderHW regression test for H.264 4:2:2 10-bit decoding.
- Add shared UBO layout across vertex + fragment stages so vertex
uniforms like ove_mvpmat compile and bind correctly.
- Rewrite uniform extraction/injection to avoid corrupting the UBO
block and to keep explicit sampler bindings stable.
- Make the UBO and sampler descriptor bindings visible to both vertex
and fragment stages.
- Add layout locations for vertex varyings (ove_texcoord) and fragment
inputs so SPIR-V generation succeeds.
- Extend TransitionImageLayout() to cover all layout pairs used by
upload/download/clear/blit.
- Add subpass dependencies to the cached render pass and leave
destinations in SHADER_READ_ONLY_OPTIMAL after Blit().
- Move descriptor allocation before command recording and abort cleanly
if allocation fails; switch Blit() to the persistent linear sampler.
- Add a gtest that creates a Vulkan backend, uploads a red U8 RGBA
texture, blits through the default pass-through shader, and verifies
the downloaded pixel is red. This test passes on the current system.
ctest passes 4/4; DynamicRenderBackend.* passes 3/1 (Vulkan fallback
skipped because Vulkan is available).
- Add PickRenderableFormat / IsColorAttachmentSupported so 3-channel
Vulkan formats fall back to 4-channel when unsupported.
- Make oakvulkan target and C ABI check conditional on Vulkan_FOUND;
skip liboakvulkan build/dependencies when Vulkan headers/libs are
absent.
- Update Preferences tooltip to reflect Vulkan is an experimental
prototype that may fall back to OpenGL.
- Revise dynamic backend plan doc: phase 3/4/5 described as prototype
frameworks with runtime validation pending, and list recent Vulkan
fixes (init idempotency, descriptor/sampler lifetime, dynamic
viewport/scissor, render pass clear, format probing).
Both OAK_ENABLE_DYNAMIC_RENDER_BACKEND=ON and OFF configurations
build and pass ctest (4/4).
- Extract libolive-rendercore static library to minimize backend link boundary.
- Add DynamicRenderer adapter with C ABI (oakgl/oakvulkan shared libs).
- Make OAK_ENABLE_DYNAMIC_RENDER_BACKEND default ON with OpenGL fallback.
- Implement VulkanRenderer prototype (textures, shaders, UBO blit, readback).
- Add backend-neutral viewer readback path (offscreen -> QImage -> QPainter).
- Refactor PluginRenderer to be renderer-agnostic; OFX plugins fall back to CPU
path on non-OpenGL backends while preserving OpenGL render path.
- Add Renderer::AttachOutputTexture/DetachOutputTexture and C ABI forwards.
- Update docs/zh/render-backend-dynamic-plan.md for Phase 3/4/5.
This commit removes redundant readbacks and uploads in the OpenFX
plugin pipeline, achieving zero-copy rendering for GL-capable
plugins and reducing CPU path overhead.
PluginRenderer (OpenGL path):
- Skip ReadbackTextureToFrame + ConvertFrameIfNeeded + Upload after
plugin render. The destination texture is already valid on GPU.
- Pass readback_cpu=false to setInputTexture() so input textures are
provided via loadTexture() (GL texture IDs) instead of being
downloaded to CPU Image buffers.
- Remove duplicate ReadbackTextureToFrame block between
getClipPreferences and the second setInputTexture call.
OliveClipInstance:
- Add optional bool readback_cpu=true to setInputTexture(). When
false, only params and input_textures_ are updated; CPU readback
and memcpy into Image are skipped.
- Add pruneImagesCache() to prevent unbounded growth of images_.
Input clips are limited to 8 cached frames; output clips are
left untouched.
Micro-optimizations:
- Replace per-row memcpy loops with single block memcpy when
src/dst strides are contiguous (common case in Olive pipeline).
- Remove dead GL_PREAMBLE macro definition.
fix(viewer): resolve playback head lag, frozen frames, and pause delay
Three playback pipeline behavioral issues are fixed:
1. Prequeue blocked playhead start:
Reduce kVideoPlaybackInterval from 0.5s to 0.1s. This lowers
prequeue length from 15–30 frames to 3–6 frames, so the
playback timer starts much sooner after pressing Play.
2. Frozen display during playback:
Relax the hard frame-drop logic in RendererGeneratedFrameForQueue.
When the queue has fewer than 2 frames, keep late frames instead
of dropping them, preventing the viewer from freezing entirely
when rendering cannot keep up with playback speed.
3. Delayed frame update after pause:
Cancel in-flight render tickets in PauseInternal() before
deleting queue watchers. Previously the render thread continued
processing stale playback frames, blocking the single-frame
render requested by UpdateTextureFromNode().
This commit resolves several categories of OFX plugin failures that
manifested as magenta (pink) render output or crashes:
1. Param default-value initialization
- IntegerInstance, DoubleInstance, BooleanInstance, ChoiceInstance,
and StringInstance now read kOfxParamPropDefault from the descriptor
at construction time. Previously, when no PluginNode was attached
(integration-test mode), get() returned 0/0.0/false, causing
generator plugins to receive invalid extent/format/PAR values and
crash in coordinate assertions.
- IntegerInstance also fixed uninitialized `id` that caused
kOfxStatErrBadHandle in CImg plugins.
2. Clip property initialization
- newClipInstance() now seeds pixelDepth and components from the
host VideoParams instead of leaving them as None. This prevents
Transform3x3Plugin and similar plugins from asserting on
getPixelComponentCount() during fetchClip inside createInstance.
- getAspectRatio() and getProjectPixelAspectRatio() now fall back
to 1.0 when the project's PAR is not yet set, avoiding division-
by-zero in coordinate conversion.
3. Frame-rate and time-base preservation
- setInputTexture() no longer overwrites the clip's frame_rate or
time_base with the input texture's values. Multi-input plugins
were crashing because setupClipPreferencesArgs throws when inputs
have mismatched rates.
4. Render loop hardening
- getClipPreferences() is now wrapped in try/catch so that frame-
rate mismatch exceptions mark render failure instead of aborting
the render thread.
- getRegionOfInterestAction() treats kOfxStatErrBadHandle as non-
fatal and falls back to default RoI.
- RenderPlugin syncs all clip instances after setVideoParam so that
getAspectRatio/getFrameRate return valid values before
createInstanceAction queries them.
5. Test suite updates
- All PluginMisc tests now use F32 input to match the host pipeline
default.
- CreateGradientTexture fixed to support F32 pixel format.
- Added CImgBilateral and CImgGuided_MultiInput tests.
- Secret parameters are now registered as hidden Node inputs so that
getClipPreferences can read them (fixes generator pink screen).
6. Debug logging in HostSupport
- clipGetImage and clipGetRegionOfDefinition now catch exceptions
and log the failing clip name for easier debugging.
- Fix SIGSEGV in PluginMisc.Keyer by linking Param::SetInstance to instances.
Olive's custom param instances (IntegerInstance, DoubleInstance, etc.) were
not passing the SetInstance pointer to the OpenFX HostSupport base class,
leaving _paramSetInstance as nullptr. When Keyer called paramSetValue during
createInstanceAction, the suite function dereferenced the null pointer in
paramChangedByPlugin(). Now newParam() passes 'this' to every constructor.
- Fix render-thread crash when OFX plugins set params during rendering.
MinOFX calls paramSetValue inside createInstanceAction from the render
thread. SubmitUndoCommand() used to push undo commands directly to
UndoStack, which modifies QAction state (GUI-only). Added IsGuiThread()
check: non-GUI threads execute redo_now() and discard the command without
touching the undo stack.
- Enable PluginMisc.MergeOver and PluginMisc.Keyer integration tests.
MergeOver now supplies both Source and Bg textures; Keyer uses U16 format.
Both pass in the full test suite.
- Make ViewerQueue thread-safe with QMutex around AppendTimewise/PurgeBefore.
Adds copy ctor and assignment to support mutex-per-instance semantics.