1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
use super::daemon::AssetDaemonOpt;
use super::{daemon, Renderer};
use super::{RenderFeaturePlugin, RenderGraphGenerator};
use crate::renderer_thread_pool_none::RendererThreadPoolNone;
use crate::{RendererAssetPlugin, RendererThreadPool};
use rafx_api::{RafxApi, RafxQueueType, RafxResult};
use rafx_assets::distill_impl::AssetResource;
use rafx_assets::{AssetManager, UploadQueueConfig};
use rafx_framework::render_features::{ExtractResources, RenderRegistryBuilder};
use std::sync::Arc;

pub enum AssetSource {
    Packfile(std::path::PathBuf),
    Daemon {
        external_daemon: bool,
        daemon_args: AssetDaemonOpt,
    },
}

pub struct RendererBuilderResult {
    pub asset_resource: AssetResource,
    pub asset_manager: AssetManager,
    pub renderer: Renderer,
}

#[derive(Default)]
pub struct RendererBuilder {
    feature_plugins: Vec<Arc<dyn RenderFeaturePlugin>>,
    asset_plugins: Vec<Arc<dyn RendererAssetPlugin>>,
}

impl RendererBuilder {
    pub fn add_render_feature(
        mut self,
        plugin: Arc<dyn RenderFeaturePlugin>,
    ) -> Self {
        self.feature_plugins.push(plugin);
        self
    }

    pub fn add_asset(
        mut self,
        plugin: Arc<dyn RendererAssetPlugin>,
    ) -> Self {
        self.asset_plugins.push(plugin);
        self
    }

    pub fn build(
        self,
        extract_resources: ExtractResources,
        rafx_api: &RafxApi,
        asset_source: AssetSource,
        render_graph_generator: Box<dyn RenderGraphGenerator>,
        renderer_thread_pool: Option<Box<dyn RendererThreadPool>>, // TODO(dvd): Change to threading type enum with options None, RenderThread, or ThreadPool.
    ) -> RafxResult<RendererBuilderResult> {
        let mut asset_resource = match asset_source {
            AssetSource::Packfile(packfile) => {
                log::info!("Reading from packfile {:?}", packfile);

                // Initialize the packfile loader with the packfile path
                daemon::init_distill_packfile(&packfile)
            }
            AssetSource::Daemon {
                external_daemon,
                daemon_args,
            } => {
                if !external_daemon {
                    log::info!("Hosting local daemon at {:?}", daemon_args.address);

                    let mut asset_daemon = rafx_assets::distill_impl::default_daemon()
                        .with_db_path(daemon_args.db_dir)
                        .with_address(daemon_args.address)
                        .with_asset_dirs(daemon_args.asset_dirs);

                    for plugin in &self.asset_plugins {
                        asset_daemon = plugin.configure_asset_daemon(asset_daemon);
                    }

                    // Spawn the daemon in a background thread.
                    std::thread::spawn(move || {
                        asset_daemon.run();
                    });
                } else {
                    log::info!("Connecting to daemon at {:?}", daemon_args.address);
                }

                // Connect to the daemon we just launched
                daemon::init_distill_daemon(daemon_args.address.to_string())
            }
        };

        let mut render_registry_builder = RenderRegistryBuilder::default();
        for plugin in &self.feature_plugins {
            render_registry_builder = plugin.configure_render_registry(render_registry_builder);
        }
        for plugin in &self.asset_plugins {
            render_registry_builder = plugin.configure_render_registry(render_registry_builder);
        }

        let render_registry = render_registry_builder.build();

        let device_context = rafx_api.device_context();

        let graphics_queue = device_context.create_queue(RafxQueueType::Graphics)?;
        let transfer_queue = device_context.create_queue(RafxQueueType::Transfer)?;

        let mut asset_manager = AssetManager::new(
            &device_context,
            &render_registry,
            UploadQueueConfig {
                max_concurrent_uploads: 4,
                max_new_uploads_in_single_frame: 4,
                max_bytes_per_upload: 64 * 1024 * 1024,
            },
            &graphics_queue,
            &transfer_queue,
        );

        asset_manager.register_default_asset_types(&mut asset_resource);

        for plugin in &self.asset_plugins {
            plugin.register_asset_types(&mut asset_manager, &mut asset_resource);
        }

        let renderer = Renderer::new(
            extract_resources,
            &mut asset_resource,
            &mut asset_manager,
            &graphics_queue,
            &transfer_queue,
            self.feature_plugins,
            self.asset_plugins,
            render_graph_generator,
            renderer_thread_pool
                .or_else(|| Some(Box::new(RendererThreadPoolNone::new())))
                .unwrap(),
        );

        match renderer {
            Ok(renderer) => Ok(RendererBuilderResult {
                asset_resource,
                asset_manager,
                renderer,
            }),
            Err(e) => {
                std::mem::drop(asset_resource);
                std::mem::drop(asset_manager);
                Err(e)
            }
        }
    }
}