use concinnity_cook::compile::shader::CompiledShader;
use concinnity_core::components::{ShaderSource, ShaderStage};
use concinnity_core::render::backend::{PipelineBuilder, PreparedPipelines};
use concinnity_core::render::shader_programs::surface::Sources;
use concinnity_engine::live_edit::shader_sources::ShaderSourceEntry;
use crate::debug::hot_reload::report::ReloadFailure;
pub(in crate::debug::hot_reload) type CompileResult = Result<CompiledShader, ReloadFailure>;
#[derive(Debug, Clone, PartialEq, Eq)]
pub(in crate::debug::hot_reload) struct ShaderTexts {
pub vertex: Option<ShaderSource>,
pub fragment: ShaderSource,
}
impl ShaderTexts {
pub(in crate::debug::hot_reload) fn read(entry: &ShaderSourceEntry) -> Result<Self, String> {
let read = |stage| {
entry
.path(stage)
.map(|path| {
concinnity_cook::compile::shader::read_shader_source(path)
.map(|text| ShaderSource {
path: path.to_string(),
text,
})
.map_err(|e| e.to_string())
})
.transpose()
};
Ok(Self {
vertex: read(ShaderStage::Vertex)?,
fragment: read(ShaderStage::Fragment)?
.ok_or_else(|| "the Shader declares no fragment file".to_string())?,
})
}
pub(in crate::debug::hot_reload) fn sources(&self) -> Sources<'_> {
Sources {
vertex: self.vertex.as_ref().map(ShaderSource::as_file),
fragment: self.fragment.as_file(),
}
}
}
pub(in crate::debug::hot_reload) fn compile(name: &str, texts: &ShaderTexts) -> CompileResult {
Ok(concinnity_host::thread::jobs::pool().install(|| {
concinnity_cook::compile::shader::compile_world_shader(
name,
&texts.sources(),
crate::cook_platform(),
)
})?)
}
pub(in crate::debug::hot_reload) struct Rebuilt {
pub compiled: CompiledShader,
pub prepared: Option<PreparedPipelines>,
}
pub(in crate::debug::hot_reload) type RebuildResult = Result<Rebuilt, ReloadFailure>;
pub(in crate::debug::hot_reload) fn prepare(
compiled: CompiledShader,
builder: Option<&dyn PipelineBuilder>,
bucket: u32,
) -> RebuildResult {
let prepared = builder
.map(|b| b.world_shader(bucket, &compiled.programs))
.transpose()
.map_err(|e| ReloadFailure::Rejected(e.to_string()))?;
Ok(Rebuilt { compiled, prepared })
}