This native wgpu + Tauri 2 example establishes the shared frame and output-sink contract for the new Junkpile I/O series.
It does not record or stream a video file yet. Instead, it proves that one authoritative GPU frame can be routed through multiple independent sink implementations without putting output-specific behavior inside the renderer.
FrameDescriptorVideoFrame containing the GPU texture, view, frame index, and timestampFrameSink lifecycleWGSL source renderer
↓
Authoritative RGBA8 sRGB texture (1280 × 720 @ 60 fps)
↓ same VideoFrame contract
├── Recording-stage GPU mirror
├── Streaming-stage GPU mirror
├── Window preview composite
└── Bounded CPU-worker probe
The right side of the native renderer window displays the two GPU mirrors. Since each mirror is a separate texture, disabling one causes only that panel to freeze. The authoritative source and the other sinks continue.
npm install
npm run dev
35 ms or 80 ms.
0 ms.
src-tauri/src/
├── frame.rs Frame descriptor and borrowed VideoFrame
├── output.rs FrameSink contract and sink implementations
├── renderer.rs Authoritative renderer and sink routing
├── source.wgsl Animated authoritative frame
├── preview.wgsl Three-texture preview composite
└── main.rs Tauri lifecycle and commands
FrameDescriptor states the media assumptions explicitly:
FrameSink provides:
The renderer only knows that it owns a list of sinks. It does not contain recording, streaming, NDI, Syphon, or Spout logic.
The worker probe receives frame metadata and timestamps through a bounded queue. It intentionally does not perform GPU readback yet.
The next example will replace that probe with a real GPU-to-CPU readback pipeline and FFmpeg file recording.
This milestone passes when: