Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
graph_runtime_buffer_assignment.hpp
Go to the documentation of this file.
1#pragma once
2
4
5#include <cstdint>
6#include <vector>
7
8namespace pulp::graph {
9
10// Off-RT buffer assignment for the canonical graph executor's routing path.
11//
12// A "slot" is one mono scratch channel buffer (sized max_frames by the pool
13// that backs it). Each node gets a contiguous input region (one slot per input
14// port) and output region (one slot per output port); a node's own two regions
15// are always disjoint so a binding can read inputs while writing outputs.
16//
17// Scratch is REUSED across non-overlapping lifetimes (liveness allocation): a
18// region is recycled only by strictly-later nodes in topological order, after
19// its last reader this block, so it never aliases a value still in use. Reuse is
20// size-bucketed to keep regions contiguous, so the executor keeps addressing
21// slots as `slots.input_base + p` / `slots.output_base + p` — reuse only shrinks
22// slot_count, the consumption contract is unchanged. A feedback source's output
23// region is pinned live to end-of-block (the feedback capture reads it), and the
24// per-edge feedback previous-block slots are never recycled (cross-block state).
25//
26// The executor reads inter-node routing straight from the plan's connection
27// table (inbound_connection_indices + connections), so the assignment only
28// needs to publish where each node's port regions live and how many slots the
29// pool must hold.
30
31inline constexpr std::uint32_t kGraphRuntimeNoSlot = 0xFFFFFFFFu;
32
34 // Base scratch-slot index of this node's input region; the input port p
35 // occupies slot (input_base + p). Meaningful only when input_ports > 0.
36 std::uint32_t input_base = 0;
37 // Base scratch-slot index of this node's output region; the output port p
38 // occupies slot (output_base + p). Meaningful only when output_ports > 0.
39 std::uint32_t output_base = 0;
40};
41
43 std::uint32_t slot_count = 0;
44 // Indexed by dense node index (matches GraphRuntimePlan::nodes order).
45 std::vector<GraphRuntimeNodeSlots> nodes;
46 // Indexed by connection index (matches GraphRuntimePlan::connections). For a
47 // feedback connection, the dedicated previous-block storage slot (one mono
48 // slot per feedback edge, appended after the node port regions and persisted
49 // across blocks); kGraphRuntimeNoSlot for every non-feedback connection.
50 // The executor gathers feedback as dst += prev_slot (last block) and copies
51 // the source's output slot into prev_slot after the block — a one-block
52 // delay matching host::SignalGraph's feedback_prev.
53 std::vector<std::uint32_t> feedback_prev_slot;
54 // True if the plan has any feedback connection.
55 bool has_feedback = false;
56 // Indexed by connection index (matches GraphRuntimePlan::connections). For a
57 // feedforward audio connection, the number of samples its source output must
58 // be delayed so it time-aligns with the destination's most-latent input —
59 // plug-in delay compensation. Derived by propagating per-node
60 // latency_samples through the topology (input_latency = max upstream
61 // output_latency; output_latency = input_latency + this node's
62 // latency_samples) and taking dst.input_latency - src.output_latency. 0 for
63 // connections that need no delay and for every feedback/event connection.
64 // The backing delay ring (sized delay + max_frames, with a persisted write
65 // position) lives in the GraphRuntimeBufferPool, which knows max_frames; the
66 // assignment carries only the per-connection sample counts.
67 std::vector<std::uint32_t> connection_delay_samples;
68 // True if any connection needs a non-zero delay.
69 bool has_delay = false;
70 bool ok = false;
71 // Maximum latency arriving at any AudioOutput node after topology
72 // propagation. This is the graph's externally reported latency. Derived in
73 // the same propagation pass as connection PDC, so host-visible latency and
74 // delay rings cannot drift, and keeping it beside the per-connection delays
75 // makes this assignment the single owner of latency analysis instead of
76 // requiring each host path to repeat the graph walk. Appended for
77 // aggregate-initializer compatibility.
78 std::uint32_t total_latency_samples = 0;
79 // Indexed by connection index. 1 when the destination may read this edge's
80 // samples in place, without a private copy: the edge is the only reader of
81 // its source port (no fan-out, no feedback capture of it, no automation tap
82 // on it), and the source's output region is not persistent across blocks.
83 // A consumer that wrote through its input view (a hosted plug-in, a native
84 // core that casts constness away) can then change only bytes nobody else
85 // reads. A feedback edge's previous-block slot is its own, so it is always
86 // 1. Empty (or 0) means copy. Appended for aggregate-initializer
87 // compatibility.
88 std::vector<std::uint8_t> reads_in_place;
89};
90
91// Compute the slot layout for `plan`. Returns ok=false (and slot_count=0) only
92// on allocation failure; an empty plan yields ok=true with slot_count=0.
93//
94// `allow_reuse` (default true) is the serial layout: a scratch region is recycled
95// by strictly-later nodes once its last reader has run, minimizing slot_count.
96// Pass false for the PARALLEL executor: reuse keys on serial topological order,
97// but same-level nodes run concurrently, so a recycled slot would alias and race
98// two live values. With allow_reuse=false every node gets fresh, never-recycled
99// input/output regions (larger slot_count, but no inter-node aliasing); feedback-
100// prev and delay-ring slots are unaffected (already never recycled).
102 const GraphRuntimePlan& plan, bool allow_reuse = true);
103
104} // namespace pulp::graph
Definition graph_runtime_buffer_assignment.hpp:8
GraphRuntimeBufferAssignment build_graph_runtime_buffer_assignment(const GraphRuntimePlan &plan, bool allow_reuse=true)
constexpr std::uint32_t kGraphRuntimeNoSlot
Definition graph_runtime_buffer_assignment.hpp:31
Definition graph_runtime_buffer_assignment.hpp:42
std::vector< GraphRuntimeNodeSlots > nodes
Definition graph_runtime_buffer_assignment.hpp:45
std::uint32_t total_latency_samples
Definition graph_runtime_buffer_assignment.hpp:78
std::vector< std::uint32_t > connection_delay_samples
Definition graph_runtime_buffer_assignment.hpp:67
std::vector< std::uint8_t > reads_in_place
Definition graph_runtime_buffer_assignment.hpp:88
bool ok
Definition graph_runtime_buffer_assignment.hpp:70
bool has_feedback
Definition graph_runtime_buffer_assignment.hpp:55
std::vector< std::uint32_t > feedback_prev_slot
Definition graph_runtime_buffer_assignment.hpp:53
std::uint32_t slot_count
Definition graph_runtime_buffer_assignment.hpp:43
bool has_delay
Definition graph_runtime_buffer_assignment.hpp:69
Definition graph_runtime_buffer_assignment.hpp:33
std::uint32_t input_base
Definition graph_runtime_buffer_assignment.hpp:36
std::uint32_t output_base
Definition graph_runtime_buffer_assignment.hpp:39
Definition graph_runtime_plan.hpp:169