1use crate::util::Span;
38use alloc::vec;
39use alloc::vec::Vec;
40use core::ops::Range;
41use vello_common::tile::Tile;
42
43pub(crate) const DEPTH_BUCKET_WIDTH: u16 = 128;
44const DEPTH_BUCKET_TILE_WIDTH: u16 = DEPTH_BUCKET_WIDTH / Tile::WIDTH;
45const _: () = assert!(
46 DEPTH_BUCKET_WIDTH.is_multiple_of(Tile::WIDTH),
47 "depth bucket width must be a multiple of tile width"
48);
49
50#[derive(Debug, Clone, Copy, PartialEq, Eq)]
52pub(crate) struct BucketRange {
53 pub(crate) start: u16,
54 pub(crate) end: u16,
55}
56
57impl BucketRange {
58 pub(crate) fn new(start: u16, end: u16) -> Self {
59 Self { start, end }
60 }
61
62 pub(crate) fn span(self) -> Span {
63 let x = self.start * DEPTH_BUCKET_WIDTH;
64 Span::new(x, (self.end - self.start) * DEPTH_BUCKET_WIDTH)
65 }
66}
67
68#[derive(Debug, Clone, Copy, PartialEq, Eq)]
69pub(crate) enum DepthSegment {
70 Regular(Span),
73 Opaque(BucketRange),
76}
77
78pub(crate) fn split_opaque_span(span: Span, mut segment: impl FnMut(DepthSegment)) {
81 debug_assert!(
82 span.pixel_x().is_multiple_of(Tile::WIDTH) && span.pixel_end().is_multiple_of(Tile::WIDTH),
83 "`split_opaque_span` requires a tile-aligned span"
84 );
85
86 let x = span.tile_x();
87 let end = span.tile_end();
88 let aligned_x = x.next_multiple_of(DEPTH_BUCKET_TILE_WIDTH);
89 let aligned_end = (end / DEPTH_BUCKET_TILE_WIDTH) * DEPTH_BUCKET_TILE_WIDTH;
90
91 if aligned_x >= aligned_end {
92 segment(DepthSegment::Regular(span));
93
94 return;
95 }
96
97 if x < aligned_x {
98 segment(DepthSegment::Regular(Span::new_tile(x, aligned_x - x)));
99 }
100
101 if aligned_x < aligned_end {
102 segment(DepthSegment::Opaque(BucketRange::new(
103 aligned_x / DEPTH_BUCKET_TILE_WIDTH,
104 aligned_end / DEPTH_BUCKET_TILE_WIDTH,
105 )));
106 }
107
108 if aligned_end < end {
109 segment(DepthSegment::Regular(Span::new_tile(
110 aligned_end,
111 end - aligned_end,
112 )));
113 }
114}
115
116#[derive(Debug, Clone, Copy, Default)]
118pub(crate) struct DepthState {
119 bounds: Option<Span>,
121 max_draw_id: u32,
125}
126
127impl DepthState {
128 pub(crate) fn reset(&mut self) {
129 *self = Self::default();
130 }
131
132 pub(crate) fn include_span(&mut self, span: Span, draw_id: u32) {
133 if let Some(bounds) = &mut self.bounds {
134 bounds.extend(span);
135 } else {
136 self.bounds = Some(span);
137 }
138
139 self.max_draw_id = self.max_draw_id.max(draw_id);
140 }
141
142 pub(crate) fn can_skip(self, span: Span, draw_id: u32) -> bool {
147 if draw_id >= self.max_draw_id {
148 return true;
149 }
150
151 let Some(opaque_bounds) = self.bounds else {
152 return true;
153 };
154
155 let opaque_start = opaque_bounds.tile_x();
156 let opaque_end = opaque_bounds.tile_end();
157 let x = span.tile_x();
158 let end = span.tile_end();
159
160 x >= opaque_end || end <= opaque_start
161 }
162}
163
164#[derive(Debug)]
165pub(crate) struct DepthBuffer {
166 data: Vec<u32>,
168}
169
170impl DepthBuffer {
171 pub(crate) fn new(buffer_width: u16) -> Self {
172 Self {
173 data: vec![0; usize::from(buffer_width.div_ceil(DEPTH_BUCKET_WIDTH))],
174 }
175 }
176
177 pub(crate) fn for_each_unset_run(&self, span: Span, mut f: impl FnMut(Span)) {
180 let (mut idx, depth_end) = self.range(span);
181 while let Some((span, _)) = self.next_unset_run(&mut idx, depth_end, span) {
182 f(span);
183 }
184 }
185
186 pub(crate) fn for_each_unset_run_and_write(
190 &mut self,
191 bucket_range: BucketRange,
192 draw_id: u32,
193 mut f: impl FnMut(BucketRange),
194 ) {
195 let bounds = bucket_range.span();
196 let mut idx = usize::from(bucket_range.start);
197 let depth_end = usize::from(bucket_range.end);
198
199 while let Some((_, depth_range)) = self.next_unset_run(&mut idx, depth_end, bounds) {
200 let bucket_start =
201 u16::try_from(depth_range.start).expect("depth bucket range start overflow");
202 let bucket_end =
203 u16::try_from(depth_range.end).expect("depth bucket range end overflow");
204 f(BucketRange::new(bucket_start, bucket_end));
205 self.mark(depth_range, draw_id);
206 }
207 }
208
209 pub(crate) fn for_each_visible_run(&self, span: Span, draw_id: u32, mut f: impl FnMut(Span)) {
212 let (mut idx, depth_end) = self.range(span);
213
214 while let Some(span) = self.next_visible_run(&mut idx, depth_end, draw_id, span) {
215 f(span);
216 }
217 }
218
219 fn range(&self, span: Span) -> (usize, usize) {
221 (
222 usize::from(span.pixel_x() / DEPTH_BUCKET_WIDTH),
223 usize::from(span.pixel_end().div_ceil(DEPTH_BUCKET_WIDTH)).min(self.data.len()),
224 )
225 }
226
227 pub(crate) fn clear(&mut self) {
228 self.data.fill(0);
229 }
230
231 fn mark(&mut self, range: Range<usize>, draw_id: u32) {
232 self.data[range].fill(draw_id);
233 }
234
235 fn next_unset_run(
237 &self,
238 idx: &mut usize,
239 end: usize,
240 bounds: Span,
241 ) -> Option<(Span, Range<usize>)> {
242 while *idx < end && self.data[*idx] != 0 {
243 *idx += 1;
244 }
245
246 let run_start = *idx;
247 while *idx < end && self.data[*idx] == 0 {
248 *idx += 1;
249 }
250
251 if run_start == *idx {
252 return None;
253 }
254
255 Some((
256 bucket_span(run_start, *idx).intersect(bounds)?,
257 run_start..*idx,
258 ))
259 }
260
261 fn next_visible_run(
263 &self,
264 idx: &mut usize,
265 end: usize,
266 draw_id: u32,
267 bounds: Span,
268 ) -> Option<Span> {
269 while *idx < end && self.data[*idx] > draw_id {
270 *idx += 1;
271 }
272
273 let run_start = *idx;
274 while *idx < end && self.data[*idx] <= draw_id {
275 *idx += 1;
276 }
277
278 if run_start == *idx {
279 return None;
280 }
281
282 bucket_span(run_start, *idx).intersect(bounds)
283 }
284}
285
286fn bucket_span(start: usize, end: usize) -> Span {
287 let x = start as u16 * DEPTH_BUCKET_WIDTH;
288 Span::new(x, (end - start) as u16 * DEPTH_BUCKET_WIDTH)
289}
290
291#[cfg(test)]
292mod tests {
293 use super::*;
294 use alloc::vec::Vec;
295 use core::ops::Range;
296
297 fn buffer(bucket_count: usize) -> DepthBuffer {
298 DepthBuffer::new(bucket_count as u16 * DEPTH_BUCKET_WIDTH)
299 }
300
301 fn buckets(start: usize, end: usize) -> Span {
302 bucket_span(start, end)
303 }
304
305 fn bucket_range(span: Span) -> (usize, usize) {
306 (
307 usize::from(span.pixel_x() / DEPTH_BUCKET_WIDTH),
308 usize::from(span.pixel_end() / DEPTH_BUCKET_WIDTH),
309 )
310 }
311
312 fn visible_runs(buffer: &DepthBuffer, span: Span, draw_id: u32) -> Vec<(usize, usize)> {
313 let mut runs = Vec::new();
314 buffer.for_each_visible_run(span, draw_id, |span| {
315 runs.push(bucket_range(span));
316 });
317 runs
318 }
319
320 fn unset_runs(buffer: &DepthBuffer, span: Span) -> Vec<(usize, usize)> {
321 let mut runs = Vec::new();
322 buffer.for_each_unset_run(span, |span| {
323 runs.push(bucket_range(span));
324 });
325 runs
326 }
327
328 fn write_buckets(buffer: &mut DepthBuffer, range: Range<usize>, draw_id: u32) {
329 buffer.for_each_unset_run_and_write(
330 BucketRange::new(range.start as u16, range.end as u16),
331 draw_id,
332 |_| {},
333 );
334 }
335
336 fn assert_depth(buffer: &DepthBuffer, ranges: &[(Range<usize>, u32)]) {
337 let mut expected = vec![0; buffer.data.len()];
338 for (range, draw_id) in ranges {
339 expected[range.clone()].fill(*draw_id);
340 }
341
342 assert_eq!(buffer.data, expected);
343 }
344
345 #[test]
346 fn split_opaque_span_extracts_aligned_middle() {
347 let mut segments = Vec::new();
348 split_opaque_span(Span::new(4, DEPTH_BUCKET_WIDTH * 3), |segment| {
349 segments.push(segment);
350 });
351
352 assert_eq!(
353 segments,
354 [
355 DepthSegment::Regular(Span::new(4, DEPTH_BUCKET_WIDTH - 4)),
356 DepthSegment::Opaque(BucketRange::new(1, 3)),
357 DepthSegment::Regular(Span::new(DEPTH_BUCKET_WIDTH * 3, 4)),
358 ]
359 );
360 }
361
362 #[test]
363 fn depth_state_skips_when_no_later_overlapping_opaque_draw_exists() {
364 let mut state = DepthState::default();
365 let opaque = buckets(1, 2);
366 state.include_span(opaque, 7);
367
368 assert!(state.can_skip(buckets(0, 1), 1));
369 assert!(state.can_skip(opaque, 7));
370 assert!(!state.can_skip(opaque, 6));
371
372 state.reset();
373 assert!(state.can_skip(opaque, 1));
374 }
375
376 #[test]
377 fn visible_runs_skip_interleaved_later_draws() {
378 let mut buffer = buffer(5);
379 write_buckets(&mut buffer, 1..2, 10);
380 write_buckets(&mut buffer, 3..4, 10);
381
382 assert_eq!(
383 visible_runs(&buffer, buckets(0, 5), 9),
384 [(0, 1), (2, 3), (4, 5)]
385 );
386 assert_eq!(visible_runs(&buffer, buckets(0, 5), 10), [(0, 5)]);
387 }
388
389 #[test]
390 fn unset_runs_and_writes_fill_interleaved_gaps() {
391 let mut buffer = buffer(5);
392 write_buckets(&mut buffer, 1..2, 10);
393 write_buckets(&mut buffer, 3..4, 10);
394
395 assert_eq!(unset_runs(&buffer, buckets(0, 5)), [(0, 1), (2, 3), (4, 5)]);
396
397 let mut written_runs = Vec::new();
398 buffer.for_each_unset_run_and_write(BucketRange::new(0, 5), 7, |range| {
399 written_runs.push((usize::from(range.start), usize::from(range.end)));
400 });
401 assert_eq!(written_runs, [(0, 1), (2, 3), (4, 5)]);
402 assert_depth(
403 &buffer,
404 [(0..1, 7), (1..2, 10), (2..3, 7), (3..4, 10), (4..5, 7)].as_slice(),
405 );
406 }
407
408 #[test]
409 fn visible_and_unset_runs_are_limited_to_the_requested_span() {
410 let mut buffer = buffer(6);
411 write_buckets(&mut buffer, 1..2, 10);
412 write_buckets(&mut buffer, 4..5, 10);
413
414 assert_eq!(visible_runs(&buffer, buckets(2, 5), 9), [(2, 4)]);
415 assert_eq!(unset_runs(&buffer, buckets(2, 5)), [(2, 4)]);
416 }
417
418 #[test]
419 fn unset_runs_clip_to_unaligned_requested_span() {
420 let buffer = buffer(3);
421 let span = Span::new(7, DEPTH_BUCKET_WIDTH + 13);
422 let mut runs = Vec::new();
423
424 buffer.for_each_unset_run(span, |span| {
425 runs.push((span.pixel_x(), span.pixel_end()));
426 });
427
428 assert_eq!(runs, [(7, DEPTH_BUCKET_WIDTH + 20)]);
429 }
430
431 #[test]
432 fn visible_runs_only_skip_buckets_with_later_draw_ids() {
433 let mut buffer = buffer(6);
434 write_buckets(&mut buffer, 0..1, 4);
435 write_buckets(&mut buffer, 1..2, 9);
436 write_buckets(&mut buffer, 2..3, 6);
437 write_buckets(&mut buffer, 3..4, 12);
438 write_buckets(&mut buffer, 5..6, 2);
439
440 assert_eq!(
441 visible_runs(&buffer, buckets(0, 6), 6),
442 [(0, 1), (2, 3), (4, 6)]
443 );
444 }
445
446 #[test]
447 fn clear_resets_all_buckets() {
448 let mut buffer = buffer(3);
449 write_buckets(&mut buffer, 0..3, 10);
450
451 buffer.clear();
452
453 assert_depth(&buffer, &[]);
454 }
455}