Files
video-shader-toys/apps/RenderCadenceCompositor
Aiden 4ea829af85
Some checks failed
CI / React UI Build (push) Successful in 11s
CI / Native Windows Build And Tests (push) Successful in 2m52s
CI / Windows Release Package (push) Has been cancelled
Shader test past
2026-05-12 02:08:48 +10:00
..
2026-05-12 02:08:48 +10:00
2026-05-12 01:59:02 +10:00
2026-05-12 01:59:02 +10:00
2026-05-12 02:08:48 +10:00
2026-05-12 02:08:48 +10:00
2026-05-12 02:08:48 +10:00
2026-05-12 01:59:02 +10:00
2026-05-12 02:08:48 +10:00
2026-05-12 01:59:02 +10:00

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

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

cmake --build --preset build-debug --target RenderCadenceCompositor -- /m:1

The executable is:

build\vs2022-x64-debug\Debug\RenderCadenceCompositor.exe

Run

Run from VS Code with:

Debug RenderCadenceCompositor

Or from a terminal:

build\vs2022-x64-debug\Debug\RenderCadenceCompositor.exe

Press Enter to stop.

Expected Telemetry

The app prints one line per second:

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:

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

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