const COMMON: &str = include_str!("../shaders/common.wgsl");
fn with_common(base: &str) -> String {
let mut out = String::with_capacity(COMMON.len() + 1 + base.len());
out.push_str(COMMON);
out.push('\n');
out.push_str(base);
out
}
pub(crate) fn sprite_shader_source(capable: bool) -> String {
let base = include_str!("../shaders/sprite_model_dda.wgsl");
if !capable {
return with_common(base);
}
let snippet = include_str!("../shaders/sprite_terrain_shadow.wgsl");
const BEGIN: &str = "//XS4_STUB_BEGIN";
const END: &str = "//XS4_STUB_END";
let (Some(b), Some(e)) = (base.find(BEGIN), base.find(END)) else {
panic!("sprite_model_dda.wgsl: XS4 stub markers not found");
};
let e_end = e + END.len();
let mut out = String::with_capacity(base.len() + snippet.len());
out.push_str(&base[..b]);
out.push_str(snippet);
out.push_str(&base[e_end..]);
with_common(&out)
}
pub(crate) fn scene_shader_source(capable: bool) -> String {
let base = include_str!("../shaders/scene_dda.wgsl");
if !capable {
return with_common(base);
}
let snippet = include_str!("../shaders/scene_sprite_shadow.wgsl");
const BEGIN: &str = "//XS4C_STUB_BEGIN";
const END: &str = "//XS4C_STUB_END";
let (Some(b), Some(e)) = (base.find(BEGIN), base.find(END)) else {
panic!("scene_dda.wgsl: XS4C stub markers not found");
};
let e_end = e + END.len();
let mut out = String::with_capacity(base.len() + snippet.len());
out.push_str(&base[..b]);
out.push_str(snippet);
out.push_str(&base[e_end..]);
with_common(&out)
}
#[cfg(test)]
mod tests {
#[test]
fn wgsl_shaders_validate() {
let sprite_stub = super::sprite_shader_source(false);
let scene_stub = super::scene_shader_source(false);
let shaders: &[(&str, &str)] = &[
("sprite_model_dda.wgsl (stub)", &sprite_stub),
("scene_dda.wgsl (stub)", &scene_stub),
("blit.wgsl", include_str!("../shaders/blit.wgsl")),
(
"scene_blit.wgsl",
include_str!("../shaders/scene_blit.wgsl"),
),
(
"scene_resolve.wgsl",
include_str!("../shaders/scene_resolve.wgsl"),
),
("line.wgsl", include_str!("../shaders/line.wgsl")),
("image.wgsl", include_str!("../shaders/image.wgsl")),
];
let mut validator = naga::valid::Validator::new(
naga::valid::ValidationFlags::all(),
naga::valid::Capabilities::all(),
);
for (name, src) in shaders {
let module = naga::front::wgsl::parse_str(src).unwrap_or_else(|e| {
panic!("{name}: WGSL parse failed:\n{}", e.emit_to_string(src))
});
validator
.validate(&module)
.unwrap_or_else(|e| panic!("{name}: WGSL validation failed: {e:?}"));
}
let capable = super::sprite_shader_source(true);
let module = naga::front::wgsl::parse_str(&capable).unwrap_or_else(|e| {
panic!(
"sprite_model_dda.wgsl (capable): parse failed:\n{}",
e.emit_to_string(&capable)
)
});
validator.validate(&module).unwrap_or_else(|e| {
panic!("sprite_model_dda.wgsl (capable): validation failed: {e:?}")
});
let scene_cap = super::scene_shader_source(true);
let module = naga::front::wgsl::parse_str(&scene_cap).unwrap_or_else(|e| {
panic!(
"scene_dda.wgsl (capable): parse failed:\n{}",
e.emit_to_string(&scene_cap)
)
});
validator
.validate(&module)
.unwrap_or_else(|e| panic!("scene_dda.wgsl (capable): validation failed: {e:?}"));
}
}