use crate::render_features::render_features_prelude::*;
use crate::visibility::VisibilityObjectId;
use fnv::{FnvHashMap, FnvHasher};
use std::hash::{BuildHasherDefault, Hash};
pub trait FramePacketData {
type PerFrameData: Sync + Send;
type RenderObjectInstanceData: Sync + Send;
type PerViewData: Sync + Send;
type RenderObjectInstancePerViewData: Sync + Send;
}
pub struct FramePacket<FramePacketDataT: FramePacketData> {
feature_index: RenderFeatureIndex,
render_object_instance_ids: FnvHashMap<RenderObjectInstance, RenderObjectInstanceId>,
pub(crate) per_frame_data: AtomicOnceCell<FramePacketDataT::PerFrameData>,
pub(crate) render_object_instances: Vec<RenderObjectInstance>,
pub(crate) render_object_instances_data:
AtomicOnceCellArray<FramePacketDataT::RenderObjectInstanceData>,
views: Vec<ViewPacket<FramePacketDataT>>,
}
impl<FramePacketDataT: FramePacketData> FramePacket<FramePacketDataT> {
pub fn new(
feature_index: RenderFeatureIndex,
frame_packet_size: &FramePacketSize,
) -> Self {
let mut views = Vec::with_capacity(frame_packet_size.view_packet_sizes.len());
for view_packet_size in frame_packet_size.view_packet_sizes.iter() {
let view_frame_index = views.len() as u32;
view_packet_size
.view
.set_view_frame_index(feature_index, view_frame_index);
views.push(ViewPacket::new(view_packet_size, view_frame_index));
}
Self {
feature_index,
per_frame_data: AtomicOnceCell::new(),
render_object_instances: Vec::with_capacity(
frame_packet_size.num_render_object_instances,
),
render_object_instances_data: AtomicOnceCellArray::with_capacity(
frame_packet_size.num_render_object_instances,
),
render_object_instance_ids: FnvHashMap::with_capacity_and_hasher(
frame_packet_size.num_render_object_instances,
BuildHasherDefault::<FnvHasher>::default(),
),
views,
}
}
pub fn view_packets(&self) -> &Vec<ViewPacket<FramePacketDataT>> {
&self.views
}
pub fn view_packet(
&self,
view_index: ViewFrameIndex,
) -> &ViewPacket<FramePacketDataT> {
self.views.get(view_index as usize).unwrap_or_else(|| {
panic!(
"ViewPacket with ViewFrameIndex {} was not found in {}.",
view_index,
std::any::type_name::<FramePacketDataT>()
)
})
}
pub fn view_packet_mut(
&mut self,
view_index: ViewFrameIndex,
) -> &mut ViewPacket<FramePacketDataT> {
self.views.get_mut(view_index as usize).unwrap_or_else(|| {
panic!(
"ViewPacket with ViewFrameIndex {} was not found in {}.",
view_index,
std::any::type_name::<FramePacketDataT>()
)
})
}
pub fn render_object_instances(&self) -> &Vec<RenderObjectInstance> {
&self.render_object_instances
}
pub fn render_object_instances_data(
&self
) -> &AtomicOnceCellArray<FramePacketDataT::RenderObjectInstanceData> {
&self.render_object_instances_data
}
pub fn per_frame_data(&self) -> &AtomicOnceCell<FramePacketDataT::PerFrameData> {
&self.per_frame_data
}
}
impl<FramePacketDataT: 'static + Sync + Send + FramePacketData> RenderFeatureFramePacket
for FramePacket<FramePacketDataT>
{
fn get_or_push_render_object_instance(
&mut self,
render_object_instance: RenderObjectInstance,
) -> RenderObjectInstanceId {
return if let Some(render_object_instance_id) =
self.render_object_instance_ids.get(&render_object_instance)
{
*render_object_instance_id
} else {
let render_object_instance_id =
self.render_object_instances.len() as RenderObjectInstanceId;
self.render_object_instances.push(render_object_instance);
self.render_object_instance_ids
.insert(render_object_instance, render_object_instance_id);
render_object_instance_id
};
}
fn render_feature_view_packet(
&self,
view_index: ViewFrameIndex,
) -> &dyn RenderFeatureViewPacket {
self.view_packet(view_index)
}
fn render_feature_view_packet_mut(
&mut self,
view_index: u32,
) -> &mut dyn RenderFeatureViewPacket {
self.view_packet_mut(view_index)
}
fn feature_index(&self) -> RenderFeatureIndex {
self.feature_index
}
}
#[derive(Copy, Eq, PartialEq, Hash, Clone, Debug)]
pub struct RenderObjectInstance {
pub object_id: ObjectId,
pub render_object_id: RenderObjectId,
pub visibility_object_id: VisibilityObjectId,
}
impl RenderObjectInstance {
pub fn new(
object_id: ObjectId,
render_object_id: RenderObjectId,
visibility_object_id: VisibilityObjectId,
) -> Self {
Self {
object_id,
render_object_id,
visibility_object_id,
}
}
}