Skip to main content

fyrox_impl/renderer/cache/
mod.rs

1// Copyright (c) 2019-present Dmitry Stepanov and Fyrox Engine contributors.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in all
11// copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19// SOFTWARE.
20
21#![allow(missing_docs)] // TODO
22
23use crate::{
24    asset::entry::DEFAULT_RESOURCE_LIFETIME,
25    core::sparse::{AtomicIndex, SparseBuffer},
26    scene::mesh::{
27        buffer::{BytesStorage, TriangleBuffer, VertexAttributeDescriptor, VertexBuffer},
28        surface::{SurfaceData, SurfaceResource},
29    },
30};
31use fxhash::FxHashMap;
32use fyrox_resource::untyped::ResourceKind;
33use std::{
34    ops::{Deref, DerefMut},
35    sync::Arc,
36};
37use uuid::Uuid;
38
39pub mod geometry;
40pub mod shader;
41pub mod texture;
42pub mod uniform;
43
44#[derive(Copy, Clone, PartialEq)]
45pub struct TimeToLive(pub f32);
46
47impl Default for TimeToLive {
48    fn default() -> Self {
49        Self(DEFAULT_RESOURCE_LIFETIME)
50    }
51}
52
53impl Deref for TimeToLive {
54    type Target = f32;
55
56    fn deref(&self) -> &Self::Target {
57        &self.0
58    }
59}
60
61impl DerefMut for TimeToLive {
62    fn deref_mut(&mut self) -> &mut Self::Target {
63        &mut self.0
64    }
65}
66
67pub struct CacheEntry<T> {
68    pub value: T,
69    pub time_to_live: TimeToLive,
70    pub self_index: Arc<AtomicIndex>,
71}
72
73impl<T> Drop for CacheEntry<T> {
74    fn drop(&mut self) {
75        // Reset self index to unassigned. This is needed, because there could be the following
76        // situation:
77        // 1) Cache entry was removed
78        // 2) Its index was stored somewhere else.
79        // 3) The index can then be used to access some entry on the index, but the cache cannot
80        // guarantee, that the data of the entry is the same.
81        self.self_index.set(AtomicIndex::UNASSIGNED_INDEX)
82    }
83}
84
85impl<T> Deref for CacheEntry<T> {
86    type Target = T;
87
88    fn deref(&self) -> &Self::Target {
89        &self.value
90    }
91}
92
93impl<T> DerefMut for CacheEntry<T> {
94    fn deref_mut(&mut self) -> &mut Self::Target {
95        &mut self.value
96    }
97}
98
99pub struct TemporaryCache<T> {
100    pub buffer: SparseBuffer<CacheEntry<T>>,
101}
102
103impl<T> Default for TemporaryCache<T> {
104    fn default() -> Self {
105        Self {
106            buffer: Default::default(),
107        }
108    }
109}
110
111impl<T> TemporaryCache<T> {
112    pub fn spawn(
113        &mut self,
114        value: T,
115        self_index: Arc<AtomicIndex>,
116        time_to_live: TimeToLive,
117    ) -> AtomicIndex {
118        let index = self.buffer.spawn(CacheEntry {
119            value,
120            time_to_live,
121            self_index,
122        });
123
124        self.buffer
125            .get_mut(&index)
126            .unwrap()
127            .self_index
128            .set(index.get());
129
130        index
131    }
132
133    pub fn get_mut(&mut self, index: &AtomicIndex) -> Option<&mut CacheEntry<T>> {
134        if let Some(entry) = self.buffer.get_mut(index) {
135            entry.time_to_live = TimeToLive::default();
136            Some(entry)
137        } else {
138            None
139        }
140    }
141
142    pub fn get_entry_mut_or_insert_with<F, E>(
143        &mut self,
144        index: &Arc<AtomicIndex>,
145        time_to_live: TimeToLive,
146        func: F,
147    ) -> Result<&mut CacheEntry<T>, E>
148    where
149        F: FnOnce() -> Result<T, E>,
150    {
151        if let Some(entry) = self.buffer.get_mut(index) {
152            entry.time_to_live = time_to_live;
153            Ok(self.buffer.get_mut(index).unwrap())
154        } else {
155            let value = func()?;
156            let index = self.buffer.spawn(CacheEntry {
157                value,
158                time_to_live,
159                self_index: index.clone(),
160            });
161            let entry = self.buffer.get_mut(&index).unwrap();
162            entry.self_index.set(index.get());
163            Ok(entry)
164        }
165    }
166
167    pub fn get_mut_or_insert_with<F, E>(
168        &mut self,
169        index: &Arc<AtomicIndex>,
170        time_to_live: TimeToLive,
171        func: F,
172    ) -> Result<&mut T, E>
173    where
174        F: FnOnce() -> Result<T, E>,
175    {
176        self.get_entry_mut_or_insert_with(index, time_to_live, func)
177            .map(|entry| &mut entry.value)
178    }
179
180    pub fn get_or_insert_with<F, E>(
181        &mut self,
182        index: &Arc<AtomicIndex>,
183        time_to_live: TimeToLive,
184        func: F,
185    ) -> Result<&T, E>
186    where
187        F: FnOnce() -> Result<T, E>,
188    {
189        self.get_entry_mut_or_insert_with(index, time_to_live, func)
190            .map(|entry| &entry.value)
191    }
192
193    pub fn update(&mut self, dt: f32) {
194        for entry in self.buffer.iter_mut() {
195            *entry.time_to_live -= dt;
196        }
197
198        for i in 0..self.buffer.len() {
199            if let Some(entry) = self.buffer.get_raw(i) {
200                if *entry.time_to_live <= 0.0 {
201                    self.buffer.free_raw(i);
202                }
203            }
204        }
205    }
206
207    pub fn clear(&mut self) {
208        self.buffer.clear();
209    }
210
211    pub fn alive_count(&self) -> usize {
212        self.buffer.filled()
213    }
214
215    pub fn remove(&mut self, index: &AtomicIndex) {
216        self.buffer.free(index);
217    }
218}
219
220/// A cache for dynamic surfaces, the content of which changes every frame. The main purpose of this
221/// cache is to keep associated GPU buffers alive a long as the surfaces in the cache and thus prevent
222/// redundant resource reallocation on every frame. This is very important for dynamic drawing, such
223/// as 2D sprites, tile maps, etc.
224#[derive(Default)]
225pub struct DynamicSurfaceCache {
226    cache: FxHashMap<u64, SurfaceResource>,
227}
228
229impl DynamicSurfaceCache {
230    /// Creates a new empty cache.
231    pub fn new() -> Self {
232        Self::default()
233    }
234
235    /// Tries to get an existing surface from the cache using its unique id or creates a new one and
236    /// returns it.
237    pub fn get_or_create(
238        &mut self,
239        unique_id: u64,
240        layout: &[VertexAttributeDescriptor],
241    ) -> SurfaceResource {
242        if let Some(surface) = self.cache.get(&unique_id) {
243            surface.clone()
244        } else {
245            let default_capacity = 4096;
246
247            // Initialize empty vertex buffer.
248            let vertex_buffer = VertexBuffer::new_with_layout(
249                layout,
250                0,
251                BytesStorage::with_capacity(default_capacity),
252            )
253            .unwrap();
254
255            // Initialize empty triangle buffer.
256            let triangle_buffer = TriangleBuffer::new(Vec::with_capacity(default_capacity * 3));
257
258            let surface = SurfaceResource::new_ok(
259                Uuid::new_v4(),
260                ResourceKind::Embedded,
261                SurfaceData::new(vertex_buffer, triangle_buffer),
262            );
263
264            self.cache.insert(unique_id, surface.clone());
265
266            surface
267        }
268    }
269
270    /// Clears the surfaces in the cache, does **not** clear the cache itself.
271    pub fn clear(&mut self) {
272        for surface in self.cache.values_mut() {
273            let mut surface_data = surface.data_ref();
274            surface_data.vertex_buffer.modify().clear();
275            surface_data.geometry_buffer.modify().clear();
276        }
277    }
278}