use askama::Template;
use crate::{
render_passes::cluster_lod::shader::cache_key::{
ShaderCacheKeyClusterCompaction, ShaderCacheKeyClusterCut,
},
shaders::{AwsmShaderError, Result},
};
#[derive(Template, Debug, Default)]
#[template(path = "cluster_lod_wgsl/cluster_cut.wgsl", whitespace = "minimize")]
pub struct ShaderTemplateClusterCut {
pub paging: bool,
}
impl TryFrom<&ShaderCacheKeyClusterCut> for ShaderTemplateClusterCut {
type Error = AwsmShaderError;
fn try_from(value: &ShaderCacheKeyClusterCut) -> Result<Self> {
Ok(Self {
paging: value.paging,
})
}
}
impl ShaderTemplateClusterCut {
pub fn into_source(self) -> Result<String> {
self.render().map_err(AwsmShaderError::from)
}
pub fn debug_label(&self) -> Option<&str> {
Some("Cluster Cut")
}
}
#[derive(Template, Debug, Default)]
#[template(
path = "cluster_lod_wgsl/cluster_compaction.wgsl",
whitespace = "minimize"
)]
pub struct ShaderTemplateClusterCompaction;
impl TryFrom<&ShaderCacheKeyClusterCompaction> for ShaderTemplateClusterCompaction {
type Error = AwsmShaderError;
fn try_from(_value: &ShaderCacheKeyClusterCompaction) -> Result<Self> {
Ok(Self)
}
}
impl ShaderTemplateClusterCompaction {
pub fn into_source(self) -> Result<String> {
self.render().map_err(AwsmShaderError::from)
}
pub fn debug_label(&self) -> Option<&str> {
Some("Cluster Compaction")
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn renders_cut_shader_source() {
let src = ShaderTemplateClusterCut::default()
.into_source()
.expect("render");
assert!(src.contains("@compute"));
assert!(src.contains("fn cs_main"));
assert!(src.contains("ClusterCutParams"));
}
#[test]
fn paging_variant_gates_resident_binding() {
let off = ShaderTemplateClusterCut { paging: false }
.into_source()
.expect("render off");
let on = ShaderTemplateClusterCut { paging: true }
.into_source()
.expect("render on");
assert!(
!off.contains("resident"),
"non-paging cut must not bind/read resident (byte-identical to shipped)"
);
assert!(on.contains("@binding(3)"), "paging cut binds resident at 3");
assert!(on.contains("resident"), "paging cut reads resident");
assert!(
on.contains("selected[i] = 0u") || on.contains("selected[i]=0u"),
"paging cut culls absent (resident<0) clusters"
);
assert!(on.contains("@compute") && on.contains("fn cs_main"));
}
}