mod byte_offsets;
mod mirror;
mod mirrors;
mod programs;
mod reflect;
use mirror::Case;
use programs::{Program, Target};
const _: () = assert!(concinnity_render::uniforms::MAX_PROBES == 8);
fn check(program: &Program, cases: &[Case]) {
if !crate::slangc_gate::slangc_available() {
return;
}
let mut drift = Vec::new();
for target in Target::ALL {
if !cases.iter().any(|case| case.targets.contains(&target)) {
continue;
}
let layouts = match programs::layouts(program, target) {
Ok(layouts) => layouts,
Err(e) => {
drift.push(e);
continue;
}
};
for case in cases.iter().filter(|c| c.targets.contains(&target)) {
let name = case.mirror.shader_name;
let Some(shader) = layouts.get(name) else {
drift.push(format!(
"{} ({}): the reflection of {} declares no `{name}`; the mirror names a \
struct this variant does not compile",
case.mirror.rust_name,
target.label(),
program.entry,
));
continue;
};
drift.extend(
mirror::drift(&case.mirror, shader)
.into_iter()
.map(|line| format!("[{}] {line}", target.label())),
);
}
}
assert!(
drift.is_empty(),
"{} layouts drifted from the shader:\n {}",
program.entry,
drift.join("\n "),
);
}
#[test]
fn main_bindless_layouts_match_the_shader() {
check(
&programs::MAIN_BINDLESS_VERT,
&mirrors::forward::main_bindless(),
);
}
#[test]
fn light_cull_layouts_match_the_shader() {
check(
&programs::LIGHT_CULL_KERNEL,
&mirrors::forward::light_cull(),
);
}
#[test]
fn rt_skin_layouts_match_the_shader() {
check(&programs::RT_SKIN_KERNEL, &mirrors::geometry::rt_skin());
}
#[test]
fn gbuffer_prepass_vertex_layouts_match_the_shader() {
check(
&programs::GBUFFER_PREPASS_VERT,
&mirrors::geometry::gbuffer_vertex(),
);
}
#[test]
fn gbuffer_prepass_fragment_layouts_match_the_shader() {
check(
&programs::GBUFFER_PREPASS_FRAG,
&mirrors::geometry::gbuffer_fragment(),
);
}
#[test]
fn shadow_layouts_match_the_shader() {
check(&programs::SHADOW_VERT, &mirrors::geometry::shadow());
}
#[test]
fn decal_layouts_match_the_shader() {
check(&programs::DECAL_VERT, &mirrors::geometry::decal());
}
#[test]
fn line_layouts_match_the_shader() {
check(&programs::LINE_VERT, &mirrors::geometry::line());
}
#[test]
fn particle_layouts_match_the_shader() {
check(&programs::PARTICLE_VERT, &mirrors::geometry::particle());
}
#[test]
fn text_layouts_match_the_shader() {
check(&programs::TEXT_VERT, &mirrors::geometry::text());
}
#[test]
fn glass_layouts_match_the_shader() {
check(&programs::GLASS_VERT, &mirrors::transparent::glass());
}
#[test]
fn glass_mesh_layouts_match_the_shader() {
check(
&programs::GLASS_MESH_VERT,
&mirrors::transparent::glass_mesh(),
);
}
#[test]
fn water_layouts_match_the_shader() {
check(&programs::WATER_VERT, &mirrors::transparent::water());
}
#[test]
fn rt_reflections_layouts_match_the_shader() {
check(
&programs::RT_REFLECTIONS_FRAG,
&mirrors::transparent::rt_reflections(),
);
}
#[test]
fn fog_layouts_match_the_shader() {
check(&programs::FOG_FROXEL, &mirrors::transparent::fog());
}
#[test]
fn taa_layouts_match_the_shader() {
check(&programs::TAA_FRAG, &mirrors::post::taa());
}
#[test]
fn bloom_layouts_match_the_shader() {
check(&programs::BLOOM_PREFILTER, &mirrors::post::bloom());
}
#[test]
fn composite_layouts_match_the_shader() {
check(&programs::COMPOSITE_FRAG, &mirrors::post::composite());
}
#[test]
fn ssao_layouts_match_the_shader() {
check(&programs::SSAO_KERNEL, &mirrors::post::ssao());
}
#[test]
fn ssr_layouts_match_the_shader() {
check(&programs::SSR_RESOLVE, &mirrors::post::ssr());
}
#[test]
fn ssgi_layouts_match_the_shader() {
check(&programs::SSGI_GATHER, &mirrors::post::ssgi());
}
#[test]
fn auto_exposure_layouts_match_the_shader() {
check(
&programs::AUTO_EXPOSURE_BUILD,
&mirrors::post::auto_exposure(),
);
}
#[test]
fn hiz_layouts_match_the_shader() {
check(&programs::HIZ_INIT_SINGLE, &mirrors::post::hiz());
}