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)]
22pub struct CachedTexture {
23 pub texture: Texture,
24 pub default_view: TextureView,
25}
26
27#[derive(Resource, Default)]
30pub struct TextureCache {
31 textures: HashMap<TextureDescriptor<'static>, Vec<CachedTextureMeta>>,
32}
33
34impl TextureCache {
35 pub fn get(
38 &mut self,
39 render_device: &RenderDevice,
40 descriptor: TextureDescriptor<'static>,
41 ) -> CachedTexture {
42 match self.textures.entry(descriptor) {
43 Entry::Occupied(mut entry) => {
44 for texture in entry.get_mut().iter_mut() {
45 if !texture.taken {
46 texture.frames_since_last_use = 0;
47 texture.taken = true;
48 return CachedTexture {
49 texture: texture.texture.clone(),
50 default_view: texture.default_view.clone(),
51 };
52 }
53 }
54
55 let texture = render_device.create_texture(&entry.key().clone());
56 let default_view = texture.create_view(&TextureViewDescriptor::default());
57 entry.get_mut().push(CachedTextureMeta {
58 texture: texture.clone(),
59 default_view: default_view.clone(),
60 frames_since_last_use: 0,
61 taken: true,
62 });
63 CachedTexture {
64 texture,
65 default_view,
66 }
67 }
68 Entry::Vacant(entry) => {
69 let texture = render_device.create_texture(entry.key());
70 let default_view = texture.create_view(&TextureViewDescriptor::default());
71 entry.insert(vec![CachedTextureMeta {
72 texture: texture.clone(),
73 default_view: default_view.clone(),
74 taken: true,
75 frames_since_last_use: 0,
76 }]);
77 CachedTexture {
78 texture,
79 default_view,
80 }
81 }
82 }
83 }
84
85 pub fn is_empty(&self) -> bool {
87 self.textures.is_empty()
88 }
89
90 pub fn update(&mut self) {
92 self.textures.retain(|_, textures| {
93 for texture in textures.iter_mut() {
94 texture.frames_since_last_use += 1;
95 texture.taken = false;
96 }
97
98 textures.retain(|texture| texture.frames_since_last_use < 3);
99 !textures.is_empty()
100 });
101 }
102}
103
104pub fn update_texture_cache_system(mut texture_cache: ResMut<TextureCache>) {
106 texture_cache.update();
107}