render: the M3 OFX host — one oak-worker --ofx-host process for every plugin job
docs/zh/plans/render-pipeline-threads.md M3 (design 3.2): OpenFX crash isolation moves from "every worker hosts plugins" to a single dedicated host process, served over NDJSON + shared memory. - oak-worker --ofx-host mode (src/ofx_host.rs): loads every plugin once, resolves jobs by the cross-process-stable OFX identifier, and renders through the same in-process executor the workers used to install. - oak-render/ofxhost.rs: the single-host client. The render manager creates and installs it for the Pipeline backend (lazy spawn on the first plugin job); eval::process_plugin_job prefers it and falls back to the in-process executor otherwise, so the process backend keeps its current behavior until M4. - Data plane: input/output FrameSlotPool pairs (the handshake's input_* fields are used for the first time). Named clips and the source frame are written to input slots after the explicit CPU readback; the plugin output returns through an output slot. Pool size/capacity grow by a host restart when a job needs more (safe: submissions are serialized and one job is in flight). - Crash loop: reader EOF fails the in-flight submit, which respawns the host and re-posts the same job (frames are read back once); after three consecutive crashes the client is permanently dead and the evaluator falls back to a purple frame. The dead child is reaped immediately, and a submit mutex enforces the one-job-in-flight contract. - Progress/cancel: the host flushes plugin_progress immediately (live progress), and reads stdin on its own thread so plugin_cancel takes effect mid-render at the plugin's next progressUpdate; the sticky flag resets at progressStart and request_plugin_cancel_all broadcasts to both the worker pool and the host. - JobSpec::Plugin / PluginJobPayload carry the plugin type_id (stable across processes); `--ofx-crash-once` / `--ofx-crash-always` are the deterministic crash hooks, matching the worker's env hooks. - Tests: wire round-trips; host unit tests (crash budget, cancel-flag reset through the factory, source mapping); oak-worker integration tests against the real host + bundled test plugin (render + progress, crash respawn and re-post, three-crash give-up, mid-render cancel on the new slow variant, concurrent submits); eval's purple fallback.
This commit is contained in:
@@ -80,6 +80,9 @@ impl PluginInstanceHandle {
|
||||
pub struct PluginJobPayload {
|
||||
/// The instance identity (oakplugin registry key).
|
||||
pub instance: PluginInstanceHandle,
|
||||
/// The OFX plugin identifier (cross-process stable; the single OFX
|
||||
/// host process resolves its own instance from it).
|
||||
pub type_id: String,
|
||||
/// The request time (C++ `globals.time().in()`).
|
||||
pub time: Rational,
|
||||
/// The effect input id the main source texture arrives on (C++
|
||||
@@ -238,6 +241,7 @@ impl NodeBehavior for PluginNode {
|
||||
if tex.is_some() && !self.instance.is_null() {
|
||||
let payload = Job::PluginJob(PluginJobPayload {
|
||||
instance: self.instance,
|
||||
type_id: self.type_id.clone(),
|
||||
time,
|
||||
effect_input_id: core.effect_input.clone(),
|
||||
values: inputs.clone(),
|
||||
|
||||
Reference in New Issue
Block a user