mirror of
https://github.com/storytold/spark.git
synced 2026-10-13 23:52:44 +00:00
68 lines
1.9 KiB
Rust
68 lines
1.9 KiB
Rust
use anyhow::anyhow;
|
|
|
|
const DEPTH_INFINITY: u32 = 0x7c00;
|
|
const DEPTH_SIZE: usize = DEPTH_INFINITY as usize + 1;
|
|
|
|
#[derive(Default)]
|
|
pub struct SortBuffers {
|
|
pub readback: Vec<u16>,
|
|
pub ordering: Vec<u32>,
|
|
pub buckets: Vec<u32>,
|
|
}
|
|
|
|
impl SortBuffers {
|
|
pub fn ensure_size(&mut self, max_splats: usize) {
|
|
if self.readback.len() < max_splats {
|
|
self.readback.resize(max_splats, 0);
|
|
}
|
|
if self.ordering.len() < max_splats {
|
|
self.ordering.resize(max_splats, 0);
|
|
}
|
|
if self.buckets.len() < DEPTH_SIZE {
|
|
self.buckets.resize(DEPTH_SIZE, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn sort_internal(buffers: &mut SortBuffers, num_splats: usize) -> anyhow::Result<u32> {
|
|
let SortBuffers { readback, ordering, buckets } = buffers;
|
|
let readback = &readback[..num_splats];
|
|
|
|
// Set the bucket counts to zero
|
|
buckets.clear();
|
|
buckets.resize(DEPTH_SIZE, 0);
|
|
|
|
// Count the number of splats in each bucket
|
|
for &metric in readback.iter() {
|
|
if (metric as u32) < DEPTH_INFINITY {
|
|
buckets[metric as usize] += 1;
|
|
}
|
|
}
|
|
|
|
// Compute bucket starting offset
|
|
let mut active_splats = 0;
|
|
for count in buckets.iter_mut().rev().skip(1) {
|
|
let new_total = active_splats + *count;
|
|
*count = active_splats;
|
|
active_splats = new_total;
|
|
}
|
|
|
|
// Write out splat indices at the right location using bucket offsets
|
|
for (index, &metric) in readback.iter().enumerate() {
|
|
if (metric as u32) < DEPTH_INFINITY {
|
|
ordering[buckets[metric as usize] as usize] = index as u32;
|
|
buckets[metric as usize] += 1;
|
|
}
|
|
}
|
|
|
|
// Sanity check
|
|
if buckets[0] != active_splats {
|
|
return Err(anyhow!(
|
|
"Expected {} active splats but got {}",
|
|
active_splats,
|
|
buckets[0]
|
|
));
|
|
}
|
|
Ok(active_splats)
|
|
}
|