pebble/assets/
asset_plugin.rs1use crate::{
2 app::SystemStage,
3 assets::{
4 dependent_asset_plugin::Dependencies,
5 storage::{Assets, GPUAssets},
6 upload::DeviceUpload,
7 },
8 plugin::Plugin,
9 rendering::backend::Backend,
10 resources::Resources,
11 system::{Res, ResMut},
12};
13
14pub struct DeviceAssetPlugin<B: Backend, T: DeviceUpload<B>> {
15 _marker: std::marker::PhantomData<(B, T)>,
16}
17
18impl<B: Backend, T: DeviceUpload<B>> DeviceAssetPlugin<B, T> {
19 pub fn new() -> Self {
20 Self {
21 _marker: std::marker::PhantomData,
22 }
23 }
24}
25
26impl<B, T> Plugin for DeviceAssetPlugin<B, T>
27where
28 B: Backend,
29 T: DeviceUpload<B>,
30{
31 fn build(&self, app: &mut crate::prelude::App) {
32 app.try_insert_resource(Assets::<T::Source>::new());
33 app.try_insert_resource(GPUAssets::<T>::new());
34 app.add_system(SystemStage::AssetSync, sync_device_assets::<B, T>);
35 }
36}
37
38fn sync_device_assets<B, T>(
39 mut cpu: ResMut<Assets<T::Source>>,
40 mut gpu: ResMut<GPUAssets<T>>,
41 backend: Option<Res<B>>,
42 world: &hecs::World,
43 resources: &Resources,
44) where
45 B: Backend,
46 T: DeviceUpload<B>,
47{
48 let Some(device) = backend else {
49 log_waiting::<B, T>(&cpu, "backend");
50 return;
51 };
52
53 let Some(deps) = T::Deps::try_gather(world, resources) else {
54 log_waiting::<B, T>(&cpu, "dependencies");
55 return;
56 };
57
58 for handle in cpu.take_dirty() {
59 if let Some(source) = cpu.get(handle) {
60 gpu.insert(handle, T::upload(source, &device, &deps));
61 }
62 }
63}
64
65fn log_waiting<B, T>(cpu: &Assets<T::Source>, what: &str)
66where
67 B: Backend,
68 T: DeviceUpload<B>,
69{
70 if !cpu.dirty_is_empty() {
71 tracing::trace!(
72 "{}: waiting on {what}, {} pending",
73 std::any::type_name::<T>(),
74 cpu.dirty_len()
75 );
76 }
77}