use askama::Template;
use crate::{
render_passes::material_classify::{
buffers::header_bytes, shader::cache_key::ShaderCacheKeyMaterialClassify,
},
shaders::{AwsmShaderError, Result},
};
pub struct ShaderTemplateMaterialClassify {
pub bind_groups: ShaderTemplateMaterialClassifyBindGroups,
pub compute: ShaderTemplateMaterialClassifyCompute,
}
#[derive(Template, Debug)]
#[template(
path = "material_classify_wgsl/bind_groups.wgsl",
whitespace = "minimize"
)]
pub struct ShaderTemplateMaterialClassifyBindGroups {
pub multisampled_geometry: bool,
pub bucket_count: u32,
pub pad_words_iter: Vec<u32>,
pub emit_edge_data: bool,
}
#[derive(Template, Debug)]
#[template(path = "material_classify_wgsl/compute.wgsl", whitespace = "minimize")]
pub struct ShaderTemplateMaterialClassifyCompute {
pub multisampled_geometry: bool,
pub emit_edge_data: bool,
pub n_words: u32,
pub words_iter: Vec<u32>,
pub edge_slot_bits: u32,
}
pub fn pad_words_count(bucket_count: u32) -> u32 {
let unpadded = bucket_count * 16 + bucket_count * 4 + 4; let padded = header_bytes(bucket_count);
(padded - unpadded) / 4
}
impl TryFrom<&ShaderCacheKeyMaterialClassify> for ShaderTemplateMaterialClassify {
type Error = AwsmShaderError;
fn try_from(key: &ShaderCacheKeyMaterialClassify) -> Result<Self> {
let multisampled_geometry = key.msaa_sample_count.is_some();
let bucket_count = key.bucket_count();
let pad_words_iter = (0..pad_words_count(bucket_count)).collect();
let mask_words = crate::dynamic_materials::classify_mask_words(bucket_count);
Ok(ShaderTemplateMaterialClassify {
bind_groups: ShaderTemplateMaterialClassifyBindGroups {
multisampled_geometry,
bucket_count,
pad_words_iter,
emit_edge_data: key.emit_edge_data,
},
compute: ShaderTemplateMaterialClassifyCompute {
multisampled_geometry,
emit_edge_data: key.emit_edge_data,
n_words: mask_words,
words_iter: (0..mask_words).collect(),
edge_slot_bits: crate::dynamic_materials::edge_slot_bits(bucket_count) as u32,
},
})
}
}
impl ShaderTemplateMaterialClassify {
pub fn into_source(self) -> Result<String> {
let bind_groups_source = self.bind_groups.render()?;
let compute_source = self.compute.render()?;
Ok(format!("{}\n{}", bind_groups_source, compute_source))
}
pub fn debug_label(&self) -> Option<&str> {
Some("Material Classify")
}
}