vfpga-runner
vfpgaRunner · sourcesA HOST module that runs a loaded `.vfpga` declarative effect spec — a "virtual FPGA bitstream" swapped into one reconfigurable card (inspired by, not a clone of, classic video-synth hardware). The module declares the full I/O SUPERSET it can wire — 4 video inputs (vin1..vin4), 4 CV inputs (cv1..cv4), 4 gate inputs (g1..g4), 2 video outputs (vout1 canonical / vout2 via read('outputTexture:vout2')), and an 8-slot generic param bank (p1..p8) — and a loaded VfpgaSpec (node.data.vfpga, picked from the "load preset…" menu) selects which subset is ACTIVE and what GL render-graph runs. The card is manifest-driven: it renders the full port superset as handles (inactive ones dimmed) and shows only the loaded spec's active CV inputs (each with a bipolar SCALE attenuverter + OFFSET + always-on scope), gate inputs (with an activity LED), and its mapped param knobs (p1..pN, labelled + ranged by the spec, MIDI-learnable). CV inputs are linear-scaled into named role uniforms; gate inputs raw-pass into synthetic gN_evt params that the factory hysteresis edge-detects (DOOM/backdraft convention) so a spec's shader can read a held level / rising-edge count. Specs are IN-REPO bundled TypeScript (no user-uploaded code in v1) collected by import.meta.glob; the render runs on the MAIN thread (#1811 — the render worker has no cross-thread input textures for vin1..vin4, its return protocol carries one picture per node so vout2 could not be served, and the card polls read('gateState') every frame). Preset change hot-swaps the GL pipeline. This foundation ships ONE VFPGA: smpte-bars, a pure SMPTE-style colour-bar generator (0 video in → 1 video out, one CV SHIFT role + BRIGHT/SAT params) — a deterministic always-on reference source for bringing up downstream effects.
Full guide: VFPGA runner guide The video-FPGA effect runner — the tile model, the catalog, and how to wire it.the faceplate
outputs
| id | cable | what it does |
|---|---|---|
vout1 | video | Primary video output — the canonical surface texture. The loaded spec's vout1 FBO (the final pass writing 'output'); always present, and what downstream modules and OUTPUT sample. RGB video stream |
vout2 | video | Secondary video output. Exposed only when the loaded spec declares a vout2 FBO (read('outputTexture:vout2')); otherwise null/inactive. Lets a multi-output effect tap a second buffer. RGB video stream |
controls
| control | what it does |
|---|---|
| Cv1 val | Synthetic CV param for the cv1 jack (no knob). Carries the raw CV sample written by the cv1 input; read as the loaded spec's CV-role-1 modulation uniform after the card's SCALE attenuverter + OFFSET. |
| Cv2 val | Synthetic CV param for the cv2 jack (no knob). Holds the raw cv2 sample, surfaced to the loaded spec's CV-role-2 uniform post SCALE + OFFSET. |
| Cv3 val | Synthetic CV param for the cv3 jack (no knob). Holds the raw cv3 sample, read by the loaded spec's CV-role-3 uniform after SCALE + OFFSET. |
| Cv4 val | Synthetic CV param for the cv4 jack (no knob). Holds the raw cv4 sample, read by the loaded spec's CV-role-4 uniform after SCALE + OFFSET. |
| G1 evt | Synthetic gate param for the g1 jack (no knob). The factory hysteresis edge-detector turns this raw sample into the held-level and rising-edge-count uniforms the loaded spec's gate-role-1 reads. |
| G2 evt | Synthetic gate param for the g2 jack (no knob). Edge-detected into the held-level and rising-edge-count uniforms consumed by the loaded spec's gate-role-2. |
| G3 evt | Synthetic gate param for the g3 jack (no knob). Edge-detected into the held-level / rising-edge-count uniforms the loaded spec's gate-role-3 reads. |
| G4 evt | Synthetic gate param for the g4 jack (no knob). Edge-detected into the held-level / rising-edge-count uniforms the loaded spec's gate-role-4 reads. |
| P1 | Generic param slot 1 (host 0..1). A loaded VFPGA maps and labels one of its params onto this slot; the card renders a knob in the spec's [min,max] range only when the loaded spec uses the slot. The mapped value drives the bound shader uniform. |
| P2 | Generic param slot 2. Surfaced as a labeled knob (in the spec's mapped range) only if the loaded VFPGA maps a param onto it; otherwise hidden. CV patched to the same uniform adds on top of this base. |
| P3 | Generic param slot 3. A labeled knob appears only when the loaded spec maps a param here; the host slot is generic 0..1, shown to the user in the spec's [min,max] range. |
| P4 | Generic param slot 4. Mapped + labeled by the loaded VFPGA when used; renders a knob in the spec's range, otherwise inactive. |
| P5 | Generic param slot 5. Labeled and ranged by whichever spec param the loaded VFPGA maps onto it; no knob when the slot is unused by the loaded spec. |
| P6 | Generic param slot 6. Surfaced as a knob (spec label + range) only when the loaded VFPGA uses the slot; the underlying host value is a 0..1 generic slot. |
| P7 | Generic param slot 7. Mapped + labeled per the loaded spec; renders a knob in the mapped range when active, otherwise dimmed/hidden. |
| P8 | Generic param slot 8 — the last of the p1..p8 bank. Labeled and ranged by the loaded VFPGA's mapped param when used; no knob otherwise. |
| Vfpga cv {n} | Modulation rack - one strip per CV role the LOADED VFPGA declares, each carrying a SCALE attenuverter (-1..+1, so it inverts), an OFFSET (0..1), and an always-on trace of the value that actually reaches the shader uniform; then an activity lamp per active gate role. SCALE and OFFSET are applied to the raw cv1..cv4 sample before the spec's cvRole adds it onto its uniform, so they set how far and in which direction a patched cable swings that role. They live in node.data.cvInputs (never per-frame Y.Doc writes) and are the same values the legacy card's per-CV SCALE/OFFSET knobs write. The lamps read the factory's held gate state, the same read('gateState') seam the card polls. A spec that declares neither CV nor gate roles renders an empty rack. |
| Vfpga preset {n} | VFPGA picker - the dropdown listing every bundled .vfpga bitstream by name (smpte-bars, chroma-rot, databend-cvbs, framestore-howl, macroblock-mosh, scaler-glitch, sync-bender, tmds-sparkle). Picking one writes node.data.vfpga and hot-swaps the running effect: the old GL pipeline is disposed, the new spec's passes are compiled, and its param-slot defaults are seeded into p1..p8 so the loaded program renders with its intended bend amounts immediately. It is the module's identity control - every other control here means something different depending on what this one says. On the legacy card the same action is the "load preset..." menu. |
source
vfpga-runner.ts on GitHub.