#![allow(dead_code)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[allow(dead_code)]
pub enum SortStrategy {
FrontToBack,
BackToFront,
ByMaterial,
ByPipeline,
None,
}
#[derive(Debug, Clone, PartialEq)]
#[allow(dead_code)]
pub struct DrawSortKey {
pub depth: f32,
pub material_id: u32,
pub pipeline_id: u32,
pub layer: u8,
}
impl DrawSortKey {
#[allow(dead_code)]
pub fn new(depth: f32, material_id: u32, pipeline_id: u32, layer: u8) -> Self {
Self {
depth,
material_id,
pipeline_id,
layer,
}
}
}
#[derive(Debug, Clone)]
#[allow(dead_code)]
pub struct SortedDraw {
pub key: DrawSortKey,
pub handle: usize,
}
#[allow(dead_code)]
pub fn sort_draws(draws: &mut [SortedDraw], strategy: SortStrategy) {
match strategy {
SortStrategy::FrontToBack => draws.sort_by(|a, b| {
a.key
.depth
.partial_cmp(&b.key.depth)
.unwrap_or(std::cmp::Ordering::Equal)
}),
SortStrategy::BackToFront => draws.sort_by(|a, b| {
b.key
.depth
.partial_cmp(&a.key.depth)
.unwrap_or(std::cmp::Ordering::Equal)
}),
SortStrategy::ByMaterial => draws.sort_by_key(|d| (d.key.layer, d.key.material_id)),
SortStrategy::ByPipeline => draws.sort_by_key(|d| (d.key.layer, d.key.pipeline_id)),
SortStrategy::None => {}
}
}
#[allow(dead_code)]
pub fn opaque_key(depth: f32, material_id: u32, pipeline_id: u32) -> DrawSortKey {
DrawSortKey::new(depth, material_id, pipeline_id, 0)
}
#[allow(dead_code)]
pub fn transparent_key(depth: f32, material_id: u32, pipeline_id: u32) -> DrawSortKey {
DrawSortKey::new(depth, material_id, pipeline_id, 128)
}
#[allow(dead_code)]
pub fn is_sorted_front_to_back(draws: &[SortedDraw]) -> bool {
draws.windows(2).all(|w| w[0].key.depth <= w[1].key.depth)
}
#[allow(dead_code)]
pub fn is_sorted_back_to_front(draws: &[SortedDraw]) -> bool {
draws.windows(2).all(|w| w[0].key.depth >= w[1].key.depth)
}
#[cfg(test)]
mod tests {
use super::*;
fn make_draw(depth: f32, mat: u32, pipe: u32, layer: u8, handle: usize) -> SortedDraw {
SortedDraw {
key: DrawSortKey::new(depth, mat, pipe, layer),
handle,
}
}
#[test]
fn front_to_back_sorts_ascending() {
let mut draws = vec![
make_draw(3.0, 0, 0, 0, 0),
make_draw(1.0, 0, 0, 0, 1),
make_draw(2.0, 0, 0, 0, 2),
];
sort_draws(&mut draws, SortStrategy::FrontToBack);
assert!(is_sorted_front_to_back(&draws));
}
#[test]
fn back_to_front_sorts_descending() {
let mut draws = vec![
make_draw(1.0, 0, 0, 0, 0),
make_draw(3.0, 0, 0, 0, 1),
make_draw(2.0, 0, 0, 0, 2),
];
sort_draws(&mut draws, SortStrategy::BackToFront);
assert!(is_sorted_back_to_front(&draws));
}
#[test]
fn by_material_groups() {
let mut draws = vec![
make_draw(1.0, 2, 0, 0, 0),
make_draw(2.0, 1, 0, 0, 1),
make_draw(3.0, 2, 0, 0, 2),
];
sort_draws(&mut draws, SortStrategy::ByMaterial);
assert!(draws[0].key.material_id <= draws[1].key.material_id);
}
#[test]
fn by_pipeline_groups() {
let mut draws = vec![make_draw(1.0, 0, 3, 0, 0), make_draw(2.0, 0, 1, 0, 1)];
sort_draws(&mut draws, SortStrategy::ByPipeline);
assert!(draws[0].key.pipeline_id <= draws[1].key.pipeline_id);
}
#[test]
fn none_preserves_order() {
let mut draws = vec![make_draw(5.0, 0, 0, 0, 0), make_draw(1.0, 0, 0, 0, 1)];
sort_draws(&mut draws, SortStrategy::None);
assert_eq!(draws[0].handle, 0);
assert_eq!(draws[1].handle, 1);
}
#[test]
fn opaque_key_layer_zero() {
let k = opaque_key(1.0, 0, 0);
assert_eq!(k.layer, 0);
}
#[test]
fn transparent_key_layer_nonzero() {
let k = transparent_key(1.0, 0, 0);
assert!(k.layer > 0);
}
#[test]
fn empty_slice_sorts_cleanly() {
let mut draws: Vec<SortedDraw> = vec![];
sort_draws(&mut draws, SortStrategy::FrontToBack);
assert!(draws.is_empty());
}
#[test]
fn is_sorted_single_element() {
let draws = vec![make_draw(1.0, 0, 0, 0, 0)];
assert!(is_sorted_front_to_back(&draws));
assert!(is_sorted_back_to_front(&draws));
}
}