use std::collections::HashMap;
use std::sync::Arc;
use parking_lot::Mutex;
use crate::RenderContext;
use crate::allocator::DataTextureSource;
use crate::renderer::DrawableCollectionViewInfo;
use crate::wgpu_resources::{GpuBindGroup, GpuTexture};
#[derive(Clone, Default, re_byte_size::SizeBytes)]
pub struct SortOrderCache {
sort_orders: Arc<Mutex<HashMap<crate::ViewBuilderId, Vec<u32>>>>,
}
#[derive(Clone)]
pub struct TransparentSort {
pub object_positions: Arc<Vec<glam::Vec3>>,
pub object_from_world: glam::Affine3A,
pub sort_order_cache: Option<SortOrderCache>,
}
pub fn build_back_to_front_lookup_texture(
ctx: &RenderContext,
sort: &TransparentSort,
view_info: &DrawableCollectionViewInfo,
) -> Option<GpuTexture> {
re_tracing::profile_function!();
let object_positions = &sort.object_positions;
let num_primitives = object_positions.len();
if num_primitives == 0 {
return None;
}
let mut order = sort
.sort_order_cache
.as_ref()
.and_then(|cache| cache.sort_orders.lock().remove(&view_info.view_id))
.filter(|order| order.len() == num_primitives)
.unwrap_or_else(|| (0..num_primitives as u32).collect());
let eye_object_position = sort
.object_from_world
.transform_point3(view_info.camera_world_position.into());
{
re_tracing::profile_scope!("sort");
order.sort_by_cached_key(|&i| {
let distance_squared =
object_positions[i as usize].distance_squared(eye_object_position);
std::cmp::Reverse(distance_squared.to_bits())
});
}
if let Some(cache) = &sort.sort_order_cache {
cache
.sort_orders
.lock()
.insert(view_info.view_id, order.clone());
}
let mut lookup_texture = DataTextureSource::new(ctx);
if let Err(err) = lookup_texture.extend_from_slice(&order) {
re_log::error_once!("Failed to upload index lookup texture: {err}");
return None;
}
match lookup_texture.finish(wgpu::TextureFormat::R32Uint, "back_to_front_lookup_texture") {
Ok(texture) => Some(texture),
Err(err) => {
re_log::error_once!("Failed to upload index lookup texture: {err}");
None
}
}
}
pub struct SortedDrawable {
pub batch_index: usize,
pub lookup_bind_group: Option<GpuBindGroup>,
}
#[derive(Default)]
pub struct SortedDrawables {
frame_index: u64,
entries: Vec<SortedDrawable>,
}
impl SortedDrawables {
pub fn push_for_frame(&mut self, frame_index: u64, drawable: SortedDrawable) -> usize {
if self.frame_index != frame_index {
self.frame_index = frame_index;
self.entries.clear();
}
self.entries.push(drawable);
self.entries.len() - 1
}
pub fn get(&self, index: usize) -> &SortedDrawable {
&self.entries[index]
}
}