Skip to main content

pebble/assets/
asset_plugin.rs

1use crate::{
2    app::SystemStage,
3    assets::{
4        storage::{Assets, GPUAssets},
5        upload::DeviceUpload,
6    },
7    plugin::Plugin,
8    rendering::backend::Backend,
9    system::{Res, ResMut},
10};
11
12pub struct DeviceAssetPlugin<B: Backend, T: DeviceUpload<B>> {
13    _marker: std::marker::PhantomData<(B, T)>,
14}
15
16impl<B: Backend, T: DeviceUpload<B>> DeviceAssetPlugin<B, T> {
17    pub fn new() -> Self {
18        Self {
19            _marker: std::marker::PhantomData,
20        }
21    }
22}
23
24impl<B, T> Plugin for DeviceAssetPlugin<B, T>
25where
26    B: Backend,
27    T: DeviceUpload<B>,
28{
29    fn build(&self, app: &mut crate::prelude::App) {
30        app.try_insert_resource(Assets::<T::Source>::new());
31        app.try_insert_resource(GPUAssets::<T>::new());
32        app.add_system(SystemStage::AssetSync, sync_device_assets::<B, T>);
33    }
34}
35
36fn sync_device_assets<B, T>(
37    mut cpu: ResMut<Assets<T::Source>>,
38    mut gpu: ResMut<GPUAssets<T>>,
39    backend: Option<Res<B>>,
40) where
41    B: Backend,
42    T: DeviceUpload<B>,
43{
44    let Some(device) = backend else { return };
45    for handle in cpu.take_dirty() {
46        if let Some(source) = cpu.get(handle) {
47            gpu.insert(handle, T::upload(source, &device));
48        } else {
49            tracing::warn!("Dirty asset handle removed before GPU sync");
50        }
51    }
52}