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};
27use std::{
28    ops::{Deref, DerefMut},
29    sync::Arc,
30};
31
32pub mod geometry;
33pub mod shader;
34pub mod texture;
35pub mod uniform;
36
37#[derive(Copy, Clone, PartialEq)]
38pub struct TimeToLive(pub f32);
39
40impl Default for TimeToLive {
41    fn default() -> Self {
42        Self(DEFAULT_RESOURCE_LIFETIME)
43    }
44}
45
46impl Deref for TimeToLive {
47    type Target = f32;
48
49    fn deref(&self) -> &Self::Target {
50        &self.0
51    }
52}
53
54impl DerefMut for TimeToLive {
55    fn deref_mut(&mut self) -> &mut Self::Target {
56        &mut self.0
57    }
58}
59
60pub struct CacheEntry<T> {
61    pub value: T,
62    pub time_to_live: TimeToLive,
63    pub self_index: Arc<AtomicIndex>,
64}
65
66impl<T> Drop for CacheEntry<T> {
67    fn drop(&mut self) {
68        // Reset self index to unassigned. This is needed, because there could be the following
69        // situation:
70        // 1) Cache entry was removed
71        // 2) Its index was stored somewhere else.
72        // 3) The index can then be used to access some entry on the index, but the cache cannot
73        // guarantee, that the data of the entry is the same.
74        self.self_index.set(AtomicIndex::UNASSIGNED_INDEX)
75    }
76}
77
78impl<T> Deref for CacheEntry<T> {
79    type Target = T;
80
81    fn deref(&self) -> &Self::Target {
82        &self.value
83    }
84}
85
86impl<T> DerefMut for CacheEntry<T> {
87    fn deref_mut(&mut self) -> &mut Self::Target {
88        &mut self.value
89    }
90}
91
92pub struct TemporaryCache<T> {
93    pub buffer: SparseBuffer<CacheEntry<T>>,
94}
95
96impl<T> Default for TemporaryCache<T> {
97    fn default() -> Self {
98        Self {
99            buffer: Default::default(),
100        }
101    }
102}
103
104impl<T> TemporaryCache<T> {
105    pub fn spawn(
106        &mut self,
107        value: T,
108        self_index: Arc<AtomicIndex>,
109        time_to_live: TimeToLive,
110    ) -> AtomicIndex {
111        let index = self.buffer.spawn(CacheEntry {
112            value,
113            time_to_live,
114            self_index,
115        });
116
117        self.buffer
118            .get_mut(&index)
119            .unwrap()
120            .self_index
121            .set(index.get());
122
123        index
124    }
125
126    pub fn get_mut(&mut self, index: &AtomicIndex) -> Option<&mut CacheEntry<T>> {
127        if let Some(entry) = self.buffer.get_mut(index) {
128            entry.time_to_live = TimeToLive::default();
129            Some(entry)
130        } else {
131            None
132        }
133    }
134
135    pub fn get_entry_mut_or_insert_with<F, E>(
136        &mut self,
137        index: &Arc<AtomicIndex>,
138        time_to_live: TimeToLive,
139        func: F,
140    ) -> Result<&mut CacheEntry<T>, E>
141    where
142        F: FnOnce() -> Result<T, E>,
143    {
144        if let Some(entry) = self.buffer.get_mut(index) {
145            entry.time_to_live = time_to_live;
146            Ok(self.buffer.get_mut(index).unwrap())
147        } else {
148            let value = func()?;
149            let index = self.buffer.spawn(CacheEntry {
150                value,
151                time_to_live,
152                self_index: index.clone(),
153            });
154            let entry = self.buffer.get_mut(&index).unwrap();
155            entry.self_index.set(index.get());
156            Ok(entry)
157        }
158    }
159
160    pub fn get_mut_or_insert_with<F, E>(
161        &mut self,
162        index: &Arc<AtomicIndex>,
163        time_to_live: TimeToLive,
164        func: F,
165    ) -> Result<&mut T, E>
166    where
167        F: FnOnce() -> Result<T, E>,
168    {
169        self.get_entry_mut_or_insert_with(index, time_to_live, func)
170            .map(|entry| &mut entry.value)
171    }
172
173    pub fn get_or_insert_with<F, E>(
174        &mut self,
175        index: &Arc<AtomicIndex>,
176        time_to_live: TimeToLive,
177        func: F,
178    ) -> Result<&T, E>
179    where
180        F: FnOnce() -> Result<T, E>,
181    {
182        self.get_entry_mut_or_insert_with(index, time_to_live, func)
183            .map(|entry| &entry.value)
184    }
185
186    pub fn update(&mut self, dt: f32) {
187        for entry in self.buffer.iter_mut() {
188            *entry.time_to_live -= dt;
189        }
190
191        for i in 0..self.buffer.len() {
192            if let Some(entry) = self.buffer.get_raw(i) {
193                if *entry.time_to_live <= 0.0 {
194                    self.buffer.free_raw(i);
195                }
196            }
197        }
198    }
199
200    pub fn clear(&mut self) {
201        self.buffer.clear();
202    }
203
204    pub fn alive_count(&self) -> usize {
205        self.buffer.filled()
206    }
207
208    pub fn remove(&mut self, index: &AtomicIndex) {
209        self.buffer.free(index);
210    }
211}