blade_render/
asset_hub.rs

1use blade_asset::AssetManager;
2use std::{path::Path, sync::Arc};
3
4/// A single hub to manage all assets.
5pub struct AssetHub {
6    pub textures: Arc<AssetManager<crate::texture::Baker>>,
7    pub models: AssetManager<crate::model::Baker>,
8    pub shaders: AssetManager<crate::shader::Baker>,
9}
10
11pub struct LoadContext<'a> {
12    asset_hub: &'a AssetHub,
13    base_path: &'a Path,
14    finish_task: choir::IdleTask,
15}
16
17impl AssetHub {
18    /// Create a new hub.
19    pub fn new(
20        target: &Path,
21        choir: &Arc<choir::Choir>,
22        gpu_context: &Arc<blade_graphics::Context>,
23    ) -> Self {
24        let _ = std::fs::create_dir_all(target);
25        let textures = Arc::new(AssetManager::new(
26            target,
27            choir,
28            crate::texture::Baker::new(gpu_context),
29        ));
30        let models = AssetManager::new(
31            target,
32            choir,
33            crate::model::Baker::new(gpu_context, &textures),
34        );
35
36        let mut sh_baker = crate::shader::Baker::new(gpu_context);
37        sh_baker.register_bool("DEBUG_MODE", cfg!(debug_assertions));
38        sh_baker.register_enum::<crate::render::DebugMode>();
39        sh_baker.register_bitflags::<crate::render::DebugDrawFlags>();
40        sh_baker.register_bitflags::<crate::render::DebugTextureFlags>();
41        let shaders = AssetManager::new(target, choir, sh_baker);
42
43        Self {
44            textures,
45            models,
46            shaders,
47        }
48    }
49
50    /// Flush the GPU state updates into the specified command encoder.
51    ///
52    /// Populates the list of temporary buffers that can be freed when the
53    /// relevant submission is completely retired.
54    #[profiling::function]
55    pub fn flush(
56        &self,
57        command_encoder: &mut blade_graphics::CommandEncoder,
58        temp_buffers: &mut Vec<blade_graphics::Buffer>,
59    ) {
60        self.textures.baker.flush(command_encoder, temp_buffers);
61        self.models.baker.flush(command_encoder, temp_buffers);
62    }
63
64    /// Destroy the hub contents.
65    pub fn destroy(&mut self) {
66        self.textures.clear();
67        self.models.clear();
68        self.shaders.clear();
69    }
70
71    pub fn open_context<'a, N: Into<choir::Name>>(
72        &'a self,
73        base_path: &'a Path,
74        name: N,
75    ) -> LoadContext {
76        LoadContext {
77            asset_hub: self,
78            base_path,
79            finish_task: self.shaders.choir.spawn(name).init_dummy(),
80        }
81    }
82
83    #[profiling::function]
84    pub fn list_running_tasks(&self) -> Vec<choir::RunningTask> {
85        let mut list = Vec::new();
86        self.textures.list_running_tasks(&mut list);
87        self.models.list_running_tasks(&mut list);
88        self.shaders.list_running_tasks(&mut list);
89        list
90    }
91}
92
93impl LoadContext<'_> {
94    pub fn load_shader(&mut self, path: &str) -> blade_asset::Handle<crate::Shader> {
95        let (handle, task) = self
96            .asset_hub
97            .shaders
98            .load(self.base_path.join(path), crate::shader::Meta);
99        self.finish_task.depend_on(task);
100        handle
101    }
102
103    pub fn close(self) -> choir::RunningTask {
104        self.finish_task.run()
105    }
106}