use std::collections::HashMap;
use std::sync::Arc;
use vulkano::device::Device;
use vulkano::pipeline::GraphicsPipeline;
use vulkano::render_pass::RenderPass;
use crate::rendering::pipeline::create_pipeline;
use crate::shaders::{fragment::*, vertex::vs};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum ShaderType {
#[default]
Pbr,
Unlit,
Emissive,
NormalDebug,
Heavy,
}
impl ShaderType {
pub fn all() -> &'static [ShaderType] {
&[
ShaderType::Pbr,
ShaderType::Unlit,
ShaderType::Emissive,
ShaderType::NormalDebug,
ShaderType::Heavy,
]
}
pub fn sort_key(&self) -> u32 {
match self {
ShaderType::Pbr => 0,
ShaderType::Unlit => 1,
ShaderType::Emissive => 2,
ShaderType::NormalDebug => 3,
ShaderType::Heavy => 4,
}
}
}
pub struct ShaderRegistry {
pipelines: HashMap<ShaderType, Arc<GraphicsPipeline>>,
scene_shader: Option<ShaderType>,
}
impl ShaderRegistry {
pub fn new(device: &Arc<Device>, render_pass: &Arc<RenderPass>) -> Self {
let vs_module =
vs::load(device.clone()).expect("Failed to load vertex shader");
let mut pipelines = HashMap::new();
let fs_pbr = fs::load(device.clone())
.expect("Failed to load PBR fragment shader");
pipelines.insert(
ShaderType::Pbr,
create_pipeline(vs_module.clone(), fs_pbr, render_pass, device),
);
let fs_unlit_mod = fs_unlit::load(device.clone())
.expect("Failed to load Unlit fragment shader");
pipelines.insert(
ShaderType::Unlit,
create_pipeline(
vs_module.clone(),
fs_unlit_mod,
render_pass,
device,
),
);
let fs_emissive_mod = fs_emissive::load(device.clone())
.expect("Failed to load Emissive fragment shader");
pipelines.insert(
ShaderType::Emissive,
create_pipeline(
vs_module.clone(),
fs_emissive_mod,
render_pass,
device,
),
);
let fs_normal_mod = fs_normal_debug::load(device.clone())
.expect("Failed to load NormalDebug fragment shader");
pipelines.insert(
ShaderType::NormalDebug,
create_pipeline(
vs_module.clone(),
fs_normal_mod,
render_pass,
device,
),
);
let fs_heavy_mod = fs_heavy::load(device.clone())
.expect("Failed to load Heavy fragment shader");
pipelines.insert(
ShaderType::Heavy,
create_pipeline(vs_module, fs_heavy_mod, render_pass, device),
);
Self {
pipelines,
scene_shader: None,
}
}
pub fn get_pipeline(
&self,
shader_type: ShaderType,
) -> &Arc<GraphicsPipeline> {
self.pipelines
.get(&shader_type)
.expect("ShaderType pipeline not found in registry")
}
pub fn default_pipeline(&self) -> &Arc<GraphicsPipeline> {
self.get_pipeline(ShaderType::Pbr)
}
pub fn resolve_shader(&self, object_shader: ShaderType) -> ShaderType {
self.scene_shader.unwrap_or(object_shader)
}
pub fn set_scene_shader(&mut self, shader: ShaderType) {
self.scene_shader = Some(shader);
}
pub fn clear_scene_shader(&mut self) {
self.scene_shader = None;
}
pub fn scene_shader(&self) -> Option<ShaderType> {
self.scene_shader
}
}