use crate::error::{SarektError, SarektResult};
use log::warn;
use slotmap::{DefaultKey, SlotMap};
use std::{
fmt::Debug,
sync::{Arc, RwLock},
};
#[derive(Clone)]
pub struct ShaderHandle<SL>
where
SL: ShaderLoader,
SL::SBH: ShaderBackendHandleTrait + Copy + Debug,
{
inner_key: DefaultKey,
shader_store: Arc<RwLock<ShaderStore<SL>>>,
}
impl<SL> Drop for ShaderHandle<SL>
where
SL: ShaderLoader,
SL::SBH: ShaderBackendHandleTrait + Copy + Debug,
{
fn drop(&mut self) {
let mut shader_store_guard = self
.shader_store
.write()
.expect("Could not unlock ShaderStore due to previous panic");
match shader_store_guard.destroy_shader(self.inner_key) {
Err(SarektError::UnknownShader) => {}
Err(e) => warn!("shader not destroyed, maybe it was already? Error: {:?}", e),
Ok(()) => {}
}
}
}
pub enum ShaderCode<'a> {
Spirv(&'a [u32]),
Glsl(&'a str), }
#[derive(Copy, Clone, Debug)]
pub enum ShaderType {
Vertex,
Fragment,
Geometry,
Tesselation,
Compute,
}
pub unsafe trait ShaderBackendHandleTrait: Copy {}
pub unsafe trait ShaderLoader {
type SBH;
fn load_shader(&self, code: &ShaderCode) -> SarektResult<Self::SBH>;
fn delete_shader(&self, shader: Self::SBH) -> SarektResult<()>;
}
pub struct ShaderStore<SL>
where
SL: ShaderLoader,
SL::SBH: ShaderBackendHandleTrait + Copy + Debug,
{
loaded_shaders: SlotMap<DefaultKey, Shader<SL::SBH>>,
shader_loader: SL,
}
impl<SL> ShaderStore<SL>
where
SL: ShaderLoader,
SL::SBH: ShaderBackendHandleTrait + Copy + Debug,
{
pub(crate) fn new(shader_loader: SL) -> Self {
Self {
loaded_shaders: SlotMap::new(),
shader_loader,
}
}
pub(crate) fn load_shader(
this: &Arc<RwLock<Self>>, code: &ShaderCode, shader_type: ShaderType,
) -> SarektResult<ShaderHandle<SL>> {
let mut shader_store = this
.write()
.expect("Could not unlock ShaderStore due to previous panic");
let shader_backend_handle = shader_store.shader_loader.load_shader(code)?;
let inner_key = shader_store
.loaded_shaders
.insert(Shader::new(shader_backend_handle, shader_type));
Ok(ShaderHandle {
inner_key,
shader_store: this.clone(),
})
}
fn destroy_shader(&mut self, inner_key: DefaultKey) -> SarektResult<()> {
let shader = self.loaded_shaders.remove(inner_key);
if shader.is_none() {
return Err(SarektError::UnknownShader);
}
self
.shader_loader
.delete_shader(shader.unwrap().shader_handle)?;
Ok(())
}
pub(crate) unsafe fn destroy_all_shaders(&mut self) {
for shader in self.loaded_shaders.iter() {
if let Err(err) = self.shader_loader.delete_shader(shader.1.shader_handle) {
warn!(
"Shader not destroyed, maybe it was already? Error: {:?}",
err
);
}
}
self.loaded_shaders.clear();
}
pub(crate) fn get_shader(&self, handle: &ShaderHandle<SL>) -> SarektResult<&Shader<SL::SBH>> {
let shader = self.loaded_shaders.get(handle.inner_key);
if let Some(shader) = shader {
return Ok(shader);
}
Err(SarektError::UnknownShader)
}
}
#[derive(Copy, Clone, Debug)]
pub(crate) struct Shader<SBH: ShaderBackendHandleTrait + Copy> {
pub shader_handle: SBH,
pub shader_type: ShaderType,
}
impl<SBH> Shader<SBH>
where
SBH: ShaderBackendHandleTrait + Copy,
{
fn new(shader_module: SBH, shader_type: ShaderType) -> Self {
Self {
shader_handle: shader_module,
shader_type,
}
}
}