sva_engine/render/
drive.rs1use sva_samples::Extent;
4
5use super::RenderConfig;
6use super::table::spill::Spill;
7use super::table::{Pulled, Table};
8use super::until::{Known, Until};
9use crate::cache::Recording;
10use crate::error::EngineError;
11use crate::flops::Work;
12use crate::query::{DEFAULT_FRAME_SECS, Representation};
13
14pub(super) struct Driver {
15 pub(super) table: Table,
16 pub(super) start: i64,
17 pub(super) at: i64,
18 last: i64,
19 block: usize,
20 until: Option<Until>,
21 frame: usize,
22 stop: Option<i64>,
23 end: Option<i64>,
24 keep: i64,
26 most_bytes: usize,
27 pub(super) work: Work,
28 pub(super) recording: Recording,
29 pub(super) spill: Option<Spill>,
30}
31
32pub struct Block {
33 planes: Vec<Vec<f64>>,
34 start: i64,
35}
36
37impl Block {
38 pub fn start(&self) -> i64 {
39 self.start
40 }
41
42 pub fn len(&self) -> usize {
43 self.planes[0].len()
44 }
45
46 pub fn is_empty(&self) -> bool {
47 self.len() == 0
48 }
49
50 pub fn width(&self) -> usize {
51 self.planes.len()
52 }
53
54 pub fn plane(&self, c: usize) -> &[f64] {
55 &self.planes[c]
56 }
57}
58
59pub(super) fn frame(config: &RenderConfig, rate: u32) -> usize {
61 let secs = config
62 .asks
63 .iter()
64 .find_map(|ask| match ask.representation {
65 Representation::Envelope { frame_secs } => Some(frame_secs),
66 _ => None,
67 })
68 .flatten()
69 .unwrap_or(DEFAULT_FRAME_SECS);
70 ((secs * f64::from(rate)).round() as usize).max(1)
71}
72
73impl Driver {
74 pub(super) fn new(
75 table: Table,
76 range: Extent,
77 block: usize,
78 config: &RenderConfig,
79 recording: Recording,
80 ) -> Driver {
81 let frame = frame(config, config.rate);
82 Driver {
83 table,
84 start: range.start,
85 at: range.start,
86 last: range.end,
87 block,
88 keep: config.until.as_ref().map_or(0, |_| frame as i64),
89 until: config.until.clone(),
90 frame,
91 stop: None,
92 end: None,
93 most_bytes: 0,
94 work: Work {
95 waves: Some(0),
96 ..Work::default()
97 },
98 recording,
99 spill: None,
100 }
101 }
102
103 pub(super) fn replace(&mut self, table: Table, last: i64) {
104 self.table = table;
105 self.last = last;
106 if self.stop.is_none() {
107 self.end = None;
108 }
109 }
110
111 pub(super) fn last(&self) -> i64 {
112 self.last
113 }
114
115 pub(super) fn next_to(&self) -> i64 {
116 self.last
117 .min(self.at.saturating_add(self.block as i64))
118 .max(self.at)
119 }
120
121 pub(super) fn next_block(&mut self) -> Result<Option<Block>, EngineError> {
122 let from = self.at;
123 if !self.pull()? {
124 return Ok(None);
125 }
126 let end = self.end.map_or(self.at, |end| end.clamp(from, self.at));
127 let held = self.table.samples(self.table.root, Extent::new(from, end));
128 Ok(Some(Block {
129 planes: held.planes,
130 start: from,
131 }))
132 }
133
134 pub(super) fn pull(&mut self) -> Result<bool, EngineError> {
135 let from = self.at;
136 if self.end.is_some_and(|end| from >= end) {
137 return Ok(false);
138 }
139 let to = self.next_to();
140 self.recording.reach(from);
141 let window = Extent::new(from, to);
142 if from == self.start {
143 let history = self
144 .table
145 .history(window, self.block as i64, &mut self.recording)?;
146 self.priced(&history);
147 }
148 let asked = self.spill.as_ref().map(|_| self.table.demand(window));
149 let pulled = self.table.pull(window, &mut self.recording)?;
150 self.priced(&pulled);
151 if let (Some(spill), Some(asked)) = (&mut self.spill, asked) {
152 spill.take(&self.table, &asked);
153 }
154 self.work.samples += (to - from) as u64;
155 self.at = to;
156 self.settle(from, to);
157 let future = (to < self.last).then(|| Extent::new(to, self.last));
158 let keep = Extent::new(from.min(to.saturating_sub(self.keep)), to);
159 self.table.release(future, keep, self.start);
160 Ok(true)
161 }
162
163 fn priced(&mut self, pulled: &Pulled) {
164 self.work.priced_flops += pulled.priced;
165 self.work.waves = self.work.waves.map(|held| held + pulled.waves);
166 self.most_bytes = self.most_bytes.max(pulled.most_bytes);
167 }
168
169 pub(super) fn most_bytes(&self) -> usize {
170 self.most_bytes
171 }
172
173 fn settle(&mut self, from: i64, to: i64) {
176 if self.end.is_some() {
177 return;
178 }
179 if self.last <= to {
180 self.end = Some(to);
181 }
182 let Some(until) = &self.until else {
183 return;
184 };
185 let frame = self.frame as i64;
186 let open = self.start + (from - 1 - self.start).div_euclid(frame) * frame;
187 let base = open.max(self.start);
188 let heard = self.table.samples(self.table.root, Extent::new(base, to));
189 let planes: Vec<&[f64]> = heard.planes.iter().map(Vec::as_slice).collect();
190 let rate = self.table.values[self.table.root].grid.rate;
191 let known = Known::new(planes, base, self.start, self.frame, rate, to == self.last);
192 if let Some(at) = until.first(&known, base, to) {
193 self.stop = Some(at);
194 self.end = Some(at.max(from));
195 }
196 }
197
198 pub(super) fn end(&self) -> Option<i64> {
199 self.end
200 }
201
202 pub(super) fn stop(&self) -> Option<i64> {
203 self.stop
204 }
205}