mirror of
https://github.com/FyroxEngine/Fyrox.git
synced 2026-10-11 22:50:08 +00:00
fixed incorrect usage of dynamic surface cache
- generate a bundle per material and a surface per vertex buffer layout - add any number of instances to the bundle, but leave the number of surfaces the same - fixes uncontrollable growth of dynamic surface cache (especially when moving camera)
This commit is contained in:
@@ -1181,27 +1181,24 @@ impl RenderDataBundleStorageTrait for RenderDataBundleStorage {
|
||||
node_handle: Handle<Node>,
|
||||
func: &mut dyn FnMut(VertexBufferRefMut, TriangleBufferRefMut),
|
||||
) {
|
||||
let mut layout_hasher = FxHasher::default();
|
||||
layout.hash(&mut layout_hasher);
|
||||
let layout_id = layout_hasher.finish();
|
||||
|
||||
let mut hasher = FxHasher::default();
|
||||
hasher.write_u64(material.key());
|
||||
layout.hash(&mut hasher);
|
||||
hasher.write_u64(sort_index);
|
||||
hasher.write_u32(render_path as u32);
|
||||
let key = hasher.finish();
|
||||
let bundle_id = hasher.finish();
|
||||
|
||||
let bundle = if let Some(&bundle_index) = self.bundle_map.get(&key) {
|
||||
let bundle = if let Some(&bundle_index) = self.bundle_map.get(&bundle_id) {
|
||||
self.bundles.get_mut(bundle_index).unwrap()
|
||||
} else {
|
||||
self.bundle_map.insert(key, self.bundles.len());
|
||||
self.bundle_map.insert(bundle_id, self.bundles.len());
|
||||
self.bundles.push(RenderDataBundle {
|
||||
data: dynamic_surface_cache.get_or_create(key, layout),
|
||||
data: dynamic_surface_cache.get_or_create(layout_id, layout),
|
||||
sort_index,
|
||||
instances: vec![
|
||||
// Each bundle must have at least one instance to be rendered.
|
||||
SurfaceInstanceData {
|
||||
node_handle,
|
||||
..Default::default()
|
||||
},
|
||||
],
|
||||
instances: Vec::default(),
|
||||
material: material.clone(),
|
||||
render_path,
|
||||
time_to_live: Default::default(),
|
||||
@@ -1215,7 +1212,20 @@ impl RenderDataBundleStorageTrait for RenderDataBundleStorage {
|
||||
let vertex_buffer = data.vertex_buffer.modify();
|
||||
let triangle_buffer = data.geometry_buffer.modify();
|
||||
|
||||
let offset = triangle_buffer.len();
|
||||
|
||||
func(vertex_buffer, triangle_buffer);
|
||||
|
||||
let instance = SurfaceInstanceData {
|
||||
node_handle,
|
||||
element_range: ElementRange::Specific {
|
||||
offset,
|
||||
count: data.geometry_buffer.len() - offset,
|
||||
},
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
bundle.instances.push(instance);
|
||||
}
|
||||
|
||||
/// Adds a new surface instance to the storage. The method will automatically put the instance in the appropriate
|
||||
|
||||
Vendored
+3
-21
@@ -29,7 +29,6 @@ use crate::{
|
||||
},
|
||||
};
|
||||
use fxhash::FxHashMap;
|
||||
use fyrox_resource::entry::TimedEntry;
|
||||
use fyrox_resource::untyped::ResourceKind;
|
||||
use std::{
|
||||
ops::{Deref, DerefMut},
|
||||
@@ -224,12 +223,10 @@ impl<T> TemporaryCache<T> {
|
||||
/// as 2D sprites, tile maps, etc.
|
||||
#[derive(Default)]
|
||||
pub struct DynamicSurfaceCache {
|
||||
cache: FxHashMap<u64, TimedEntry<SurfaceResource>>,
|
||||
cache: FxHashMap<u64, SurfaceResource>,
|
||||
}
|
||||
|
||||
impl DynamicSurfaceCache {
|
||||
const TTL: f32 = 1.0;
|
||||
|
||||
/// Creates a new empty cache.
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
@@ -243,8 +240,7 @@ impl DynamicSurfaceCache {
|
||||
layout: &[VertexAttributeDescriptor],
|
||||
) -> SurfaceResource {
|
||||
if let Some(surface) = self.cache.get_mut(&unique_id) {
|
||||
surface.time_to_live = Self::TTL;
|
||||
surface.value.clone()
|
||||
surface.clone()
|
||||
} else {
|
||||
let default_capacity = 4096;
|
||||
|
||||
@@ -265,13 +261,7 @@ impl DynamicSurfaceCache {
|
||||
SurfaceData::new(vertex_buffer, triangle_buffer),
|
||||
);
|
||||
|
||||
self.cache.insert(
|
||||
unique_id,
|
||||
TimedEntry {
|
||||
value: surface.clone(),
|
||||
time_to_live: Self::TTL,
|
||||
},
|
||||
);
|
||||
self.cache.insert(unique_id, surface.clone());
|
||||
|
||||
surface
|
||||
}
|
||||
@@ -289,12 +279,4 @@ impl DynamicSurfaceCache {
|
||||
surface_data.geometry_buffer.modify().clear();
|
||||
}
|
||||
}
|
||||
|
||||
/// Updates the cache entries and removes ones that wasn't used for some time.
|
||||
pub fn update(&mut self, dt: f32) {
|
||||
self.cache.retain(|_, entry| {
|
||||
entry.time_to_live -= dt;
|
||||
entry.time_to_live > 0.0
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -924,7 +924,6 @@ impl Renderer {
|
||||
self.update_texture_cache(resource_manager, dt);
|
||||
self.update_shader_cache(dt);
|
||||
self.geometry_cache.update(dt);
|
||||
self.dynamic_surface_cache.update(dt);
|
||||
}
|
||||
|
||||
fn render_scene_observer(
|
||||
|
||||
Reference in New Issue
Block a user