Phase 4 complete
All checks were successful
CI / React UI Build (push) Successful in 11s
CI / Native Windows Build And Tests (push) Successful in 2m39s
CI / Windows Release Package (push) Successful in 2m45s

This commit is contained in:
Aiden
2026-05-11 18:39:02 +10:00
parent f141d20026
commit 761df3b2d0
5 changed files with 68 additions and 97 deletions

View File

@@ -49,7 +49,7 @@ That split is workable today, but it creates architectural pressure:
- render-local transient state now has clearer Phase 3 boundaries, but GL ownership is still shared through callback and UI entrypoints.
- it is difficult to test render behavior separately from app bootstrap and hardware integration.
`RenderEngine` exists to absorb that responsibility into one subsystem with one direction of ownership.
`RenderEngine` exists to absorb that responsibility into one subsystem with one direction of ownership. Phase 4 has completed the GL ownership part of this target: normal runtime GL work now enters through the `RenderEngine` render thread.
## Responsibilities
@@ -153,9 +153,9 @@ Those rules matter because the current codebase often solves timing issues by le
## GL Ownership Model
## Target Rule
## Current Rule
One subsystem owns GL. In practice that should mean one render thread becomes the long-lived GL owner in a later phase.
One subsystem owns GL. `RenderEngine` now starts a dedicated render thread, binds the existing GL context on that thread for normal runtime work, and routes input upload, output render, preview presentation, screenshot capture, shader application, and render-local reset work through render-thread requests.
The render thread should:
@@ -168,20 +168,20 @@ The render thread should:
Other threads should interact with the subsystem through queues, snapshots, and completion signals, not by borrowing the GL context.
## Current State
## Remaining Timing State
Today GL work is still shared across callback-driven and UI entrypoints:
GL ownership is no longer shared across callback-driven and UI entrypoints:
- input upload is requested through [OpenGLVideoIOBridge::UploadInputFrame()](/c:/Users/Aiden/Documents/GitHub/video-shader-toys/apps/LoopThroughWithOpenGLCompositing/gl/pipeline/OpenGLVideoIOBridge.cpp:11)
- playout-triggered render is requested through [OpenGLVideoIOBridge::RenderScheduledFrame()](/c:/Users/Aiden/Documents/GitHub/video-shader-toys/apps/LoopThroughWithOpenGLCompositing/gl/pipeline/OpenGLVideoIOBridge.cpp:18)
- render-pass execution occurs in [OpenGLRenderPipeline::RenderFrame()](/c:/Users/Aiden/Documents/GitHub/video-shader-toys/apps/LoopThroughWithOpenGLCompositing/gl/pipeline/OpenGLRenderPipeline.cpp:31)
- preview and screenshot paths still enter `RenderEngine` methods that bind the shared context
- preview and screenshot paths enter `RenderEngine` queue/request methods
The `CRITICAL_SECTION` protects correctness, but it is not the target architectural model.
The remaining timing issue is not shared GL ownership; it is the transitional synchronous output request/response path. The DeckLink completion callback still waits while the render thread produces an output frame, fills the DeckLink buffer, and then schedules the next frame.
## Migration Direction
Phase 1 should treat the current bridge lock as a temporary compatibility mechanism. The target path should be:
The next target path should be:
1. input callback enqueues frame payloads or references
2. render thread accepts the latest usable input frame
@@ -189,7 +189,7 @@ Phase 1 should treat the current bridge lock as a temporary compatibility mechan
4. render thread produces completed output frames ahead of backend demand
5. backend callbacks only dequeue and schedule pre-rendered frames
That removes the need for callback threads to ever own GL.
Phase 4 completed the part that removes callback-thread GL ownership. Phase 7 should complete the producer/consumer playout part.
## Render Loop Boundaries
@@ -407,7 +407,7 @@ inside render-owned code paths instead of putting them back into runtime storage
Introduce snapshot-facing APIs so render no longer depends on broad runtime-state access for frame production.
Current status: Phase 3 introduced `RenderFrameInput`, `RenderFrameState`, and `RenderFrameStateResolver`, so frame-state selection is named and no longer lives inside GL drawing. Phase 4 can build on that contract while moving GL ownership.
Current status: Phase 3 introduced `RenderFrameInput`, `RenderFrameState`, and `RenderFrameStateResolver`, so frame-state selection is named and no longer lives inside GL drawing. Phase 4 built on that contract and moved normal runtime GL ownership onto the render thread.
### Step 4. Move Uploads Onto Render Ownership