use crate::prelude::*;
use anyhow::{Context, Result};
use core::panic;
use once_cell::sync::Lazy;
use parking_lot::Mutex;
use std::sync::Arc;
use vulkano::buffer::BufferContents;
use vulkano::descriptor_set::WriteDescriptorSet;
use vulkano::pipeline::cache::{PipelineCache, PipelineCacheCreateInfo};
mod loader;
pub(crate) mod vulkan;
pub(crate) use loader::Loader;
use vulkan::Vulkan;
pub mod textures;
pub mod data;
pub mod materials;
mod model;
#[cfg(feature = "audio")]
pub mod sounds;
pub use model::*;
pub(crate) static RESOURCES: Lazy<Resources> = Lazy::new(|| {
let vulkan = Vulkan::init().unwrap_or_else(|e| panic!("{e}"));
Resources::new(vulkan).unwrap_or_else(|e| panic!("{e}"))
});
#[cfg(feature = "labels")]
pub(crate) static LABELIFIER: Lazy<Mutex<Labelifier>> =
Lazy::new(|| Mutex::new(Labelifier::new().unwrap_or_else(|e| panic!("{e}"))));
#[derive(Clone)]
pub(crate) struct Resources {
pub vulkan: Vulkan,
pub loader: Arc<Mutex<Loader>>,
pub shapes: BasicShapes,
#[cfg(feature = "audio")]
pub audio_server: crossbeam::channel::Sender<AudioUpdate>,
}
impl Resources {
pub(crate) fn new(vulkan: Vulkan) -> Result<Self> {
let loader = Arc::new(Mutex::new(Loader::init(&vulkan).context(
"Failed to create the graphics loading environment for the game engine.",
)?));
let shapes = BasicShapes::new(&loader)
.context("Failed to load default shapes into the GPU memory.")?;
#[cfg(feature = "audio")]
let audio_server = sounds::audio_server();
Ok(Self {
vulkan,
loader,
shapes,
#[cfg(feature = "audio")]
audio_server,
})
}
pub(crate) fn vulkan(&self) -> &Vulkan {
&self.vulkan
}
pub(crate) fn loader(&self) -> &Arc<Mutex<Loader>> {
&self.loader
}
pub(crate) fn shapes(&self) -> &BasicShapes {
&self.shapes
}
}
pub unsafe fn load_pipeline_cache(data: &[u8]) -> Result<()> {
let cache = PipelineCache::new(
RESOURCES.vulkan().device.clone(),
PipelineCacheCreateInfo {
initial_data: data.to_vec(),
..Default::default()
},
)?;
RESOURCES
.loader()
.lock()
.pipeline_cache
.merge([cache.as_ref()])?;
Ok(())
}
pub fn pipeline_binary() -> Result<Vec<u8>> {
Ok(RESOURCES.loader().lock().pipeline_cache.get_data()?)
}
pub fn new_descriptor_write<T: BufferContents>(buf: T, set: u32) -> Result<WriteDescriptorSet> {
let loader = RESOURCES.loader().lock();
loader.write_descriptor(buf, set)
}