# DeckLink Render Cadence Probe

This is a deliberately small architecture probe for the Phase 7.7 playout model.

It is not the main app and does not use the main runtime, shader stack, preview path, input upload path, or render engine.

## What It Tests

The probe validates the clean playout spine:

```text
single OpenGL render thread
  owns its own hidden GL context
  renders a simple moving BGRA8 pattern at output cadence
  queues GPU readback through a PBO ring
  copies completed readbacks into latest-N system-memory slots

system-memory frame store
  owns free / rendering / completed / scheduled slots
  drops old completed unscheduled frames when render cadence needs space
  protects scheduled frames until DeckLink completion

DeckLink playout thread
  consumes completed system-memory frames
  keeps a small scheduled buffer filled
  does not render
```

Startup warms up rendered frames before starting DeckLink scheduled playback.

## How To Build

```powershell
cmake --build --preset build-debug --target DeckLinkRenderCadenceProbe -- /m:1
```

The executable is:

```text
build\vs2022-x64-debug\Debug\DeckLinkRenderCadenceProbe.exe
```

## How To Run

Run it from a terminal so you can see the telemetry:

```powershell
build\vs2022-x64-debug\Debug\DeckLinkRenderCadenceProbe.exe
```

Press Enter to stop.

The first version assumes `1080p59.94` / `1920x1080` output and BGRA8 system-memory frames.

## What To Watch

The probe prints one line per second:

- `renderFps`: cadence render throughput
- `scheduleFps`: DeckLink scheduling throughput
- `free`: free system-memory slots
- `completed`: rendered, unscheduled slots
- `scheduled`: slots currently owned by DeckLink
- `drops`: old completed unscheduled frames recycled by the latest-N cache
- `pboMiss`: PBO ring was full when trying to queue readback
- `late`: DeckLink displayed-late completions
- `dropped`: DeckLink dropped completions
- `decklinkBuffered`: actual DeckLink buffered-frame count when available

For a healthy architecture proof, expect:

- `renderFps` close to the selected output cadence
- `scheduleFps` close to the selected output cadence after warmup
- `scheduled` hovering near the target buffer depth
- `late` and `dropped` not increasing continuously
- visible motion that is smooth on the DeckLink output

## Interpretation

If this probe is smooth at 59.94/60, the broad architecture is viable and the main app's remaining stutters are likely caused by integration details such as input upload, shared render-thread work, preview/screenshot work, or runtime/render-state coupling.

If this probe is not smooth, the problem is lower level: DeckLink scheduling, OpenGL readback, Windows scheduling, or hardware/driver behavior.

## Initial Result

Date: 2026-05-12

User-visible result:

- output looked smooth

Representative telemetry:

```text
renderFps=59.9 scheduleFps=59.9 free=7 completed=1 scheduled=4 drops=0 pboMiss=0 completions=119 late=0 dropped=0 decklinkBuffered=4
renderFps=59.9 scheduleFps=59.9 free=7 completed=1 scheduled=4 drops=0 pboMiss=0 completions=179 late=0 dropped=0 decklinkBuffered=4
renderFps=59.8 scheduleFps=59.8 free=7 completed=1 scheduled=4 drops=0 pboMiss=0 completions=239 late=0 dropped=0 decklinkBuffered=4
renderFps=60.8 scheduleFps=59.8 free=7 completed=1 scheduled=4 drops=0 pboMiss=0 completions=299 late=0 dropped=0 decklinkBuffered=4
renderFps=59.9 scheduleFps=59.9 free=7 completed=1 scheduled=4 drops=0 pboMiss=0 completions=360 late=0 dropped=0 decklinkBuffered=4
renderFps=59.8 scheduleFps=60.8 free=8 completed=0 scheduled=4 drops=0 pboMiss=0 completions=420 late=0 dropped=0 decklinkBuffered=4
```

Read:

- the clean architecture can sustain the selected output cadence on the test machine
- BGRA8 PBO readback is viable when isolated from the main app's other render-thread work
- latest-N system-memory buffering stayed stable
- DeckLink actual buffered depth stayed at 4
- there were no late frames, dropped frames, completed-frame drops, or PBO misses in the sampled output

Implication:

The main app's remaining stutters are likely integration/ownership issues rather than a fundamental DeckLink/OpenGL/BGRA8 readback limit. The highest-value suspects are input upload before output render, shared render-thread queue contention, preview/screenshot work, and runtime/render-state work on the output path.
