bevy_render/texture/
texture_cache.rs1use crate::{
2 render_resource::{Texture, TextureView},
3 renderer::RenderDevice,
4};
5use bevy_ecs::{prelude::ResMut, system::Resource};
6use bevy_utils::{Entry, HashMap};
7use wgpu::{TextureDescriptor, TextureViewDescriptor};
8
9struct CachedTextureMeta {
12 texture: Texture,
13 default_view: TextureView,
14 taken: bool,
15 frames_since_last_use: usize,
16}
17
18#[derive(Clone)]
23pub struct CachedTexture {
24 pub texture: Texture,
25 pub default_view: TextureView,
26}
27
28#[derive(Resource, Default)]
31pub struct TextureCache {
32 textures: HashMap<TextureDescriptor<'static>, Vec<CachedTextureMeta>>,
33}
34
35impl TextureCache {
36 pub fn get(
39 &mut self,
40 render_device: &RenderDevice,
41 descriptor: TextureDescriptor<'static>,
42 ) -> CachedTexture {
43 match self.textures.entry(descriptor) {
44 Entry::Occupied(mut entry) => {
45 for texture in entry.get_mut().iter_mut() {
46 if !texture.taken {
47 texture.frames_since_last_use = 0;
48 texture.taken = true;
49 return CachedTexture {
50 texture: texture.texture.clone(),
51 default_view: texture.default_view.clone(),
52 };
53 }
54 }
55
56 let texture = render_device.create_texture(&entry.key().clone());
57 let default_view = texture.create_view(&TextureViewDescriptor::default());
58 entry.get_mut().push(CachedTextureMeta {
59 texture: texture.clone(),
60 default_view: default_view.clone(),
61 frames_since_last_use: 0,
62 taken: true,
63 });
64 CachedTexture {
65 texture,
66 default_view,
67 }
68 }
69 Entry::Vacant(entry) => {
70 let texture = render_device.create_texture(entry.key());
71 let default_view = texture.create_view(&TextureViewDescriptor::default());
72 entry.insert(vec![CachedTextureMeta {
73 texture: texture.clone(),
74 default_view: default_view.clone(),
75 taken: true,
76 frames_since_last_use: 0,
77 }]);
78 CachedTexture {
79 texture,
80 default_view,
81 }
82 }
83 }
84 }
85
86 pub fn is_empty(&self) -> bool {
88 self.textures.is_empty()
89 }
90
91 pub fn update(&mut self) {
93 self.textures.retain(|_, textures| {
94 for texture in textures.iter_mut() {
95 texture.frames_since_last_use += 1;
96 texture.taken = false;
97 }
98
99 textures.retain(|texture| texture.frames_since_last_use < 3);
100 !textures.is_empty()
101 });
102 }
103}
104
105pub fn update_texture_cache_system(mut texture_cache: ResMut<TextureCache>) {
107 texture_cache.update();
108}