wgpu/tests/snapshots.rs

333 lines
9.2 KiB
Rust
Raw Normal View History

2020-12-13 06:20:39 +00:00
bitflags::bitflags! {
struct Targets: u32 {
const IR = 0x1;
const ANALYSIS = 0x2;
const SPIRV = 0x4;
const METAL = 0x8;
const GLSL = 0x10;
2021-03-02 06:28:32 +00:00
const DOT = 0x20;
2020-12-13 06:20:39 +00:00
}
}
2020-12-11 14:56:10 +00:00
#[derive(Hash, PartialEq, Eq, serde::Deserialize)]
2020-12-08 05:23:29 +00:00
enum Stage {
Vertex,
Fragment,
Compute,
}
2020-12-11 14:56:10 +00:00
#[derive(Hash, PartialEq, Eq, serde::Deserialize)]
2020-12-08 05:23:29 +00:00
struct BindSource {
stage: Stage,
group: u32,
binding: u32,
}
2020-12-11 14:56:10 +00:00
#[derive(serde::Deserialize)]
2020-12-08 05:23:29 +00:00
struct BindTarget {
#[cfg_attr(not(feature = "msl-out"), allow(dead_code))]
2020-12-08 05:23:29 +00:00
#[serde(default)]
buffer: Option<u8>,
#[cfg_attr(not(feature = "msl-out"), allow(dead_code))]
2020-12-08 05:23:29 +00:00
#[serde(default)]
texture: Option<u8>,
#[cfg_attr(not(feature = "msl-out"), allow(dead_code))]
2020-12-08 05:23:29 +00:00
#[serde(default)]
sampler: Option<u8>,
#[cfg_attr(not(feature = "msl-out"), allow(dead_code))]
2020-12-08 05:23:29 +00:00
#[serde(default)]
mutable: bool,
}
2020-12-11 14:56:10 +00:00
#[derive(Default, serde::Deserialize)]
2020-12-08 05:23:29 +00:00
struct Parameters {
#[cfg_attr(not(feature = "spv-out"), allow(dead_code))]
2021-02-14 05:37:54 +00:00
spv_version: (u8, u8),
#[cfg_attr(not(feature = "spv-out"), allow(dead_code))]
2020-12-08 05:23:29 +00:00
spv_capabilities: naga::FastHashSet<spirv::Capability>,
#[cfg_attr(not(feature = "msl-out"), allow(dead_code))]
mtl_bindings: naga::FastHashMap<BindSource, BindTarget>,
}
#[allow(dead_code)]
fn with_snapshot_settings<F: FnOnce() -> ()>(snapshot_assertion: F) {
let mut settings = insta::Settings::new();
settings.set_snapshot_path("out");
settings.set_prepend_module_to_snapshot(false);
settings.bind(|| snapshot_assertion());
}
#[allow(dead_code, unused_variables)]
fn check_targets(module: &naga::Module, name: &str, targets: Targets) {
let params = match std::fs::read_to_string(format!("tests/in/{}{}", name, ".param.ron")) {
Ok(string) => ron::de::from_str(&string).expect("Couldn't find param file"),
Err(_) => Parameters::default(),
};
let info = naga::valid::Validator::new(naga::valid::ValidationFlags::all())
2021-03-20 03:45:36 +00:00
.validate(module)
.unwrap();
#[cfg(feature = "serialize")]
{
if targets.contains(Targets::IR) {
let config = ron::ser::PrettyConfig::default().with_new_line("\n".to_string());
let output = ron::ser::to_string_pretty(module, config).unwrap();
with_snapshot_settings(|| {
insta::assert_snapshot!(format!("{}.ron", name), output);
});
}
if targets.contains(Targets::ANALYSIS) {
let config = ron::ser::PrettyConfig::default().with_new_line("\n".to_string());
let output = ron::ser::to_string_pretty(&info, config).unwrap();
with_snapshot_settings(|| {
insta::assert_snapshot!(format!("{}.info.ron", name), output);
});
}
}
#[cfg(feature = "spv-out")]
{
if targets.contains(Targets::SPIRV) {
check_output_spv(module, &info, name, &params);
}
}
#[cfg(feature = "msl-out")]
{
if targets.contains(Targets::METAL) {
check_output_msl(module, &info, name, &params);
}
}
#[cfg(feature = "glsl-out")]
{
if targets.contains(Targets::GLSL) {
2021-03-07 03:47:21 +00:00
for ep in module.entry_points.iter() {
check_output_glsl(module, &info, name, ep.stage, &ep.name);
}
}
}
2021-03-02 06:28:32 +00:00
#[cfg(feature = "dot-out")]
{
if targets.contains(Targets::DOT) {
let string = naga::back::dot::write(module, Some(&info)).unwrap();
2021-03-02 06:28:32 +00:00
with_snapshot_settings(|| {
insta::assert_snapshot!(format!("{}.dot", name), string);
});
}
}
}
#[cfg(feature = "spv-out")]
fn check_output_spv(
module: &naga::Module,
info: &naga::valid::ModuleInfo,
name: &str,
params: &Parameters,
) {
use naga::back::spv;
use rspirv::binary::Disassemble;
2021-02-14 05:37:54 +00:00
let options = spv::Options {
lang_version: params.spv_version,
flags: spv::WriterFlags::DEBUG,
capabilities: params.spv_capabilities.clone(),
};
let spv = spv::write_vec(module, info, &options).unwrap();
let dis = rspirv::dr::load_words(spv)
.expect("Produced invalid SPIR-V")
.disassemble();
with_snapshot_settings(|| {
insta::assert_snapshot!(format!("{}.spvasm", name), dis);
});
}
2020-12-08 05:23:29 +00:00
#[cfg(feature = "msl-out")]
fn check_output_msl(
module: &naga::Module,
info: &naga::valid::ModuleInfo,
name: &str,
params: &Parameters,
) {
2020-12-08 05:23:29 +00:00
use naga::back::msl;
2020-12-08 05:23:29 +00:00
let mut binding_map = msl::BindingMap::default();
for (key, value) in params.mtl_bindings.iter() {
binding_map.insert(
msl::BindSource {
stage: match key.stage {
Stage::Vertex => naga::ShaderStage::Vertex,
Stage::Fragment => naga::ShaderStage::Fragment,
Stage::Compute => naga::ShaderStage::Compute,
},
group: key.group,
binding: key.binding,
},
msl::BindTarget {
buffer: value.buffer,
texture: value.texture,
sampler: value.sampler,
mutable: value.mutable,
},
);
}
let options = msl::Options {
lang_version: (1, 0),
binding_map,
2021-02-19 22:26:49 +00:00
spirv_cross_compatibility: false,
fake_missing_bindings: false,
allow_point_size: true,
2020-12-08 05:23:29 +00:00
};
let (msl, _) = msl::write_string(module, info, &options).unwrap();
with_snapshot_settings(|| {
insta::assert_snapshot!(format!("{}.msl", name), msl);
});
2020-12-08 05:23:29 +00:00
}
#[cfg(feature = "glsl-out")]
fn check_output_glsl(
module: &naga::Module,
info: &naga::valid::ModuleInfo,
name: &str,
stage: naga::ShaderStage,
ep_name: &str,
) {
use naga::back::glsl;
let options = glsl::Options {
version: glsl::Version::Embedded(310),
shader_stage: stage,
entry_point: ep_name.to_string(),
};
let mut buffer = Vec::new();
let mut writer = glsl::Writer::new(&mut buffer, module, info, &options).unwrap();
writer.write().unwrap();
let string = String::from_utf8(buffer).unwrap();
with_snapshot_settings(|| {
insta::assert_snapshot!(format!("{}-{:?}.glsl", name, stage), string);
});
2020-12-08 05:23:29 +00:00
}
#[cfg(feature = "wgsl-in")]
fn convert_wgsl(name: &str, targets: Targets) {
2020-12-08 05:23:29 +00:00
let module = naga::front::wgsl::parse_str(
&std::fs::read_to_string(format!("tests/in/{}{}", name, ".wgsl"))
2020-12-08 05:23:29 +00:00
.expect("Couldn't find wgsl file"),
)
.unwrap();
check_targets(&module, name, targets);
2020-12-08 05:23:29 +00:00
}
#[cfg(feature = "wgsl-in")]
#[test]
2021-01-23 06:57:02 +00:00
fn convert_wgsl_quad() {
2021-03-02 06:28:32 +00:00
convert_wgsl(
"quad",
Targets::SPIRV | Targets::METAL | Targets::GLSL | Targets::DOT,
);
2020-12-08 05:23:29 +00:00
}
2020-12-09 02:49:59 +00:00
#[cfg(feature = "wgsl-in")]
#[test]
2021-01-23 06:57:02 +00:00
fn convert_wgsl_empty() {
convert_wgsl("empty", Targets::SPIRV | Targets::METAL | Targets::GLSL);
2020-12-09 02:49:59 +00:00
}
2020-12-09 04:46:23 +00:00
#[cfg(feature = "wgsl-in")]
#[test]
2021-01-23 06:57:02 +00:00
fn convert_wgsl_boids() {
convert_wgsl("boids", Targets::SPIRV | Targets::METAL);
2020-12-09 04:46:23 +00:00
}
2020-12-13 06:20:39 +00:00
#[cfg(feature = "wgsl-in")]
#[test]
2021-01-23 06:57:02 +00:00
fn convert_wgsl_skybox() {
convert_wgsl("skybox", Targets::SPIRV | Targets::METAL | Targets::GLSL);
2020-12-13 06:20:39 +00:00
}
2021-01-22 04:56:18 +00:00
#[cfg(feature = "wgsl-in")]
#[test]
2021-01-23 06:57:02 +00:00
fn convert_wgsl_collatz() {
convert_wgsl(
"collatz",
Targets::SPIRV | Targets::METAL | Targets::IR | Targets::ANALYSIS,
);
2021-01-22 04:56:18 +00:00
}
2021-01-30 05:11:23 +00:00
#[cfg(feature = "wgsl-in")]
#[test]
fn convert_wgsl_shadow() {
2021-03-10 12:53:56 +00:00
convert_wgsl("shadow", Targets::SPIRV | Targets::METAL | Targets::GLSL);
2021-01-30 05:11:23 +00:00
}
2021-02-07 02:02:49 +00:00
#[cfg(feature = "wgsl-in")]
#[test]
fn convert_wgsl_image_copy() {
//SPIR-V is blocked by https://github.com/gfx-rs/naga/issues/646
convert_wgsl("image-copy", Targets::METAL);
}
2021-02-07 02:02:49 +00:00
#[cfg(feature = "wgsl-in")]
#[test]
fn convert_wgsl_texture_array() {
convert_wgsl("texture-array", Targets::SPIRV);
2021-02-07 02:02:49 +00:00
}
2021-02-08 17:30:21 +00:00
#[cfg(feature = "spv-in")]
fn convert_spv(name: &str, targets: Targets) {
2021-02-08 17:30:21 +00:00
let module = naga::front::spv::parse_u8_slice(
&std::fs::read(format!("tests/in/{}{}", name, ".spv")).expect("Couldn't find spv file"),
&Default::default(),
)
.unwrap();
check_targets(&module, name, targets);
naga::valid::Validator::new(naga::valid::ValidationFlags::all())
2021-03-20 03:45:36 +00:00
.validate(&module)
.unwrap();
2021-02-08 17:30:21 +00:00
}
#[cfg(feature = "spv-in")]
#[test]
fn convert_spv_quad_vert() {
convert_spv("quad-vert", Targets::METAL);
}
2021-02-08 17:30:21 +00:00
#[cfg(feature = "spv-in")]
#[test]
fn convert_spv_shadow() {
convert_spv("shadow", Targets::IR | Targets::ANALYSIS);
2021-02-08 17:30:21 +00:00
}
2021-02-11 19:43:37 +00:00
#[cfg(feature = "glsl-in")]
fn convert_glsl(
name: &str,
entry_points: naga::FastHashMap<String, naga::ShaderStage>,
_targets: Targets,
) {
2021-03-02 06:28:32 +00:00
let _module = naga::front::glsl::parse_str(
2021-02-11 19:43:37 +00:00
&std::fs::read_to_string(format!("tests/in/{}{}", name, ".glsl"))
.expect("Couldn't find glsl file"),
&naga::front::glsl::Options {
entry_points,
defines: Default::default(),
},
2021-02-11 19:43:37 +00:00
)
.unwrap();
//TODO
//check_targets(&module, name, targets);
2021-02-11 19:43:37 +00:00
}
#[cfg(feature = "glsl-in")]
#[test]
fn convert_glsl_quad() {
let mut entry_points = naga::FastHashMap::default();
entry_points.insert("vert_main".to_string(), naga::ShaderStage::Vertex);
entry_points.insert("frag_main".to_string(), naga::ShaderStage::Fragment);
convert_glsl("quad-glsl", entry_points, Targets::SPIRV | Targets::IR);
2021-02-11 19:43:37 +00:00
}