176 lines
5.5 KiB
Markdown
176 lines
5.5 KiB
Markdown
# RenderCadenceCompositor
|
|
|
|
This app is the modular version of the working DeckLink render-cadence probe.
|
|
|
|
Its job is to prove the production-facing foundation before the current compositor's shader/runtime/control features are ported over.
|
|
|
|
## Architecture
|
|
|
|
```text
|
|
RenderThread
|
|
owns a hidden OpenGL context
|
|
renders simple BGRA8 motion at selected cadence
|
|
queues async PBO readback
|
|
publishes completed frames into SystemFrameExchange
|
|
|
|
SystemFrameExchange
|
|
owns Free / Rendering / Completed / Scheduled slots
|
|
drops old completed unscheduled frames when render needs space
|
|
protects scheduled frames until DeckLink completion
|
|
|
|
DeckLinkOutputThread
|
|
consumes completed system-memory frames
|
|
schedules them into DeckLink up to target depth
|
|
never renders
|
|
```
|
|
|
|
Startup warms up real rendered frames before DeckLink scheduled playback starts.
|
|
|
|
## Current Scope
|
|
|
|
Included now:
|
|
|
|
- output-only DeckLink
|
|
- hidden render-thread-owned OpenGL context
|
|
- simple smooth-motion renderer
|
|
- BGRA8-only output
|
|
- async PBO readback
|
|
- latest-N system-memory frame exchange
|
|
- rendered-frame warmup
|
|
- background Slang compile of `shaders/happy-accident`
|
|
- render-thread-only GL commit once compiled shader source is ready
|
|
- compact telemetry
|
|
- non-GL frame-exchange tests
|
|
|
|
Intentionally not included yet:
|
|
|
|
- DeckLink input
|
|
- shader package rendering
|
|
- runtime state
|
|
- OSC/API control
|
|
- preview
|
|
- screenshots
|
|
- persistence
|
|
|
|
Those features should be ported only after the cadence spine is stable.
|
|
|
|
## Build
|
|
|
|
```powershell
|
|
cmake --build --preset build-debug --target RenderCadenceCompositor -- /m:1
|
|
```
|
|
|
|
The executable is:
|
|
|
|
```text
|
|
build\vs2022-x64-debug\Debug\RenderCadenceCompositor.exe
|
|
```
|
|
|
|
## Run
|
|
|
|
Run from VS Code with:
|
|
|
|
```text
|
|
Debug RenderCadenceCompositor
|
|
```
|
|
|
|
Or from a terminal:
|
|
|
|
```powershell
|
|
build\vs2022-x64-debug\Debug\RenderCadenceCompositor.exe
|
|
```
|
|
|
|
Press Enter to stop.
|
|
|
|
## Expected Telemetry
|
|
|
|
The app prints one line per second:
|
|
|
|
```text
|
|
renderFps=59.9 scheduleFps=59.9 free=7 completed=1 scheduled=4 completedPollMisses=0 scheduleFailures=0 completions=119 late=0 dropped=0 shaderCommitted=1 shaderFailures=0 decklinkBuffered=4 scheduleCallMs=0.0
|
|
```
|
|
|
|
Healthy first-run signs:
|
|
|
|
- visible DeckLink output is smooth
|
|
- `renderFps` is close to the selected cadence
|
|
- `scheduleFps` is close to the selected cadence after warmup
|
|
- `scheduled` stays near 4
|
|
- `decklinkBuffered` stays near 4 when available
|
|
- `late` and `dropped` do not increase continuously
|
|
- `scheduleFailures` does not increase
|
|
- `shaderCommitted` becomes `1` after the background Happy Accident compile completes
|
|
- `shaderFailures` remains `0`
|
|
|
|
`completedPollMisses` means the DeckLink scheduling thread woke up before a completed frame was available. It is not a DeckLink playout underrun by itself. Treat it as healthy polling noise when `scheduled`, `decklinkBuffered`, `late`, `dropped`, and `scheduleFailures` remain stable.
|
|
|
|
## Runtime Slang Shader Test
|
|
|
|
On startup the app begins compiling `shaders/happy-accident` on a background thread.
|
|
|
|
The render thread keeps drawing the simple motion renderer while Slang compiles. It only attempts the OpenGL shader compile/link once a complete GLSL fragment shader is ready. If either the Slang build or GL commit fails, the app keeps rendering the simple motion fallback.
|
|
|
|
Successful handoff signs:
|
|
|
|
- console prints `Runtime shader committed: happy-accident`
|
|
- telemetry shows `shaderCommitted=1`
|
|
- output changes from the simple motion pattern to the Happy Accident shader
|
|
- render/schedule cadence remains near 60 fps during and after the handoff
|
|
- DeckLink buffer remains stable
|
|
|
|
## Baseline Result
|
|
|
|
Date: 2026-05-12
|
|
|
|
User-visible result:
|
|
|
|
- output was smooth
|
|
- DeckLink held a 4-frame buffer
|
|
|
|
Representative telemetry:
|
|
|
|
```text
|
|
renderFps=59.9 scheduleFps=59.9 free=8 completed=0 scheduled=4 completedPollMisses=30 scheduleFailures=0 completions=720 late=0 dropped=0 decklinkBuffered=4 scheduleCallMs=1.2
|
|
renderFps=59.8 scheduleFps=59.8 free=7 completed=1 scheduled=4 completedPollMisses=36 scheduleFailures=0 completions=1080 late=0 dropped=0 decklinkBuffered=4 scheduleCallMs=4.7
|
|
renderFps=59.9 scheduleFps=59.9 free=7 completed=1 scheduled=4 completedPollMisses=86 scheduleFailures=0 completions=1381 late=0 dropped=0 decklinkBuffered=4 scheduleCallMs=2.1
|
|
```
|
|
|
|
Read:
|
|
|
|
- render cadence and DeckLink schedule cadence both held roughly 60 fps
|
|
- app scheduled depth stayed at 4
|
|
- actual DeckLink buffered depth stayed at 4
|
|
- no late frames, dropped frames, or schedule failures were observed
|
|
- completed poll misses were benign because playout remained fully fed
|
|
|
|
## Tests
|
|
|
|
```powershell
|
|
cmake --build --preset build-debug --target RenderCadenceCompositorFrameExchangeTests -- /m:1
|
|
ctest --test-dir build\vs2022-x64-debug -C Debug -R RenderCadenceCompositorFrameExchangeTests --output-on-failure
|
|
```
|
|
|
|
## Relationship To The Probe
|
|
|
|
`apps/DeckLinkRenderCadenceProbe` proved the timing model in one compact file.
|
|
|
|
This app keeps the same core behavior but splits it into modules that can grow:
|
|
|
|
- `frames/`: system-memory handoff
|
|
- `platform/`: COM/Win32/hidden GL context support
|
|
- `render/`: cadence, simple rendering, PBO readback
|
|
- `video/`: DeckLink output wrapper and scheduling thread
|
|
- `telemetry/`: cadence telemetry
|
|
- `app/`: startup/shutdown orchestration
|
|
|
|
## Next Porting Steps
|
|
|
|
Only after this app matches the probe's smooth output:
|
|
|
|
1. replace `SimpleMotionRenderer` with a render-scene interface
|
|
2. port shader package rendering
|
|
3. port runtime snapshots/live state
|
|
4. add control services
|
|
5. add preview/screenshot from system-memory frames
|
|
6. add DeckLink input as a CPU latest-frame mailbox
|