1#![allow(dead_code)]
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9#[allow(dead_code)]
10pub enum SortStrategy {
11 FrontToBack,
13 BackToFront,
15 ByMaterial,
17 ByPipeline,
19 None,
21}
22
23#[derive(Debug, Clone, PartialEq)]
25#[allow(dead_code)]
26pub struct DrawSortKey {
27 pub depth: f32,
29 pub material_id: u32,
31 pub pipeline_id: u32,
33 pub layer: u8,
35}
36
37impl DrawSortKey {
38 #[allow(dead_code)]
40 pub fn new(depth: f32, material_id: u32, pipeline_id: u32, layer: u8) -> Self {
41 Self {
42 depth,
43 material_id,
44 pipeline_id,
45 layer,
46 }
47 }
48}
49
50#[derive(Debug, Clone)]
52#[allow(dead_code)]
53pub struct SortedDraw {
54 pub key: DrawSortKey,
55 pub handle: usize,
56}
57
58#[allow(dead_code)]
60pub fn sort_draws(draws: &mut [SortedDraw], strategy: SortStrategy) {
61 match strategy {
62 SortStrategy::FrontToBack => draws.sort_by(|a, b| {
63 a.key
64 .depth
65 .partial_cmp(&b.key.depth)
66 .unwrap_or(std::cmp::Ordering::Equal)
67 }),
68 SortStrategy::BackToFront => draws.sort_by(|a, b| {
69 b.key
70 .depth
71 .partial_cmp(&a.key.depth)
72 .unwrap_or(std::cmp::Ordering::Equal)
73 }),
74 SortStrategy::ByMaterial => draws.sort_by_key(|d| (d.key.layer, d.key.material_id)),
75 SortStrategy::ByPipeline => draws.sort_by_key(|d| (d.key.layer, d.key.pipeline_id)),
76 SortStrategy::None => {}
77 }
78}
79
80#[allow(dead_code)]
82pub fn opaque_key(depth: f32, material_id: u32, pipeline_id: u32) -> DrawSortKey {
83 DrawSortKey::new(depth, material_id, pipeline_id, 0)
84}
85
86#[allow(dead_code)]
88pub fn transparent_key(depth: f32, material_id: u32, pipeline_id: u32) -> DrawSortKey {
89 DrawSortKey::new(depth, material_id, pipeline_id, 128)
90}
91
92#[allow(dead_code)]
94pub fn is_sorted_front_to_back(draws: &[SortedDraw]) -> bool {
95 draws.windows(2).all(|w| w[0].key.depth <= w[1].key.depth)
96}
97
98#[allow(dead_code)]
100pub fn is_sorted_back_to_front(draws: &[SortedDraw]) -> bool {
101 draws.windows(2).all(|w| w[0].key.depth >= w[1].key.depth)
102}
103
104#[cfg(test)]
105mod tests {
106 use super::*;
107
108 fn make_draw(depth: f32, mat: u32, pipe: u32, layer: u8, handle: usize) -> SortedDraw {
109 SortedDraw {
110 key: DrawSortKey::new(depth, mat, pipe, layer),
111 handle,
112 }
113 }
114
115 #[test]
116 fn front_to_back_sorts_ascending() {
117 let mut draws = vec![
118 make_draw(3.0, 0, 0, 0, 0),
119 make_draw(1.0, 0, 0, 0, 1),
120 make_draw(2.0, 0, 0, 0, 2),
121 ];
122 sort_draws(&mut draws, SortStrategy::FrontToBack);
123 assert!(is_sorted_front_to_back(&draws));
124 }
125
126 #[test]
127 fn back_to_front_sorts_descending() {
128 let mut draws = vec![
129 make_draw(1.0, 0, 0, 0, 0),
130 make_draw(3.0, 0, 0, 0, 1),
131 make_draw(2.0, 0, 0, 0, 2),
132 ];
133 sort_draws(&mut draws, SortStrategy::BackToFront);
134 assert!(is_sorted_back_to_front(&draws));
135 }
136
137 #[test]
138 fn by_material_groups() {
139 let mut draws = vec![
140 make_draw(1.0, 2, 0, 0, 0),
141 make_draw(2.0, 1, 0, 0, 1),
142 make_draw(3.0, 2, 0, 0, 2),
143 ];
144 sort_draws(&mut draws, SortStrategy::ByMaterial);
145 assert!(draws[0].key.material_id <= draws[1].key.material_id);
146 }
147
148 #[test]
149 fn by_pipeline_groups() {
150 let mut draws = vec![make_draw(1.0, 0, 3, 0, 0), make_draw(2.0, 0, 1, 0, 1)];
151 sort_draws(&mut draws, SortStrategy::ByPipeline);
152 assert!(draws[0].key.pipeline_id <= draws[1].key.pipeline_id);
153 }
154
155 #[test]
156 fn none_preserves_order() {
157 let mut draws = vec![make_draw(5.0, 0, 0, 0, 0), make_draw(1.0, 0, 0, 0, 1)];
158 sort_draws(&mut draws, SortStrategy::None);
159 assert_eq!(draws[0].handle, 0);
160 assert_eq!(draws[1].handle, 1);
161 }
162
163 #[test]
164 fn opaque_key_layer_zero() {
165 let k = opaque_key(1.0, 0, 0);
166 assert_eq!(k.layer, 0);
167 }
168
169 #[test]
170 fn transparent_key_layer_nonzero() {
171 let k = transparent_key(1.0, 0, 0);
172 assert!(k.layer > 0);
173 }
174
175 #[test]
176 fn empty_slice_sorts_cleanly() {
177 let mut draws: Vec<SortedDraw> = vec![];
178 sort_draws(&mut draws, SortStrategy::FrontToBack);
179 assert!(draws.is_empty());
180 }
181
182 #[test]
183 fn is_sorted_single_element() {
184 let draws = vec![make_draw(1.0, 0, 0, 0, 0)];
185 assert!(is_sorted_front_to_back(&draws));
186 assert!(is_sorted_back_to_front(&draws));
187 }
188}