wgpu/benches/criterion.rs

278 lines
9.7 KiB
Rust
Raw Normal View History

#![allow(clippy::needless_borrowed_reference)]
2022-02-16 00:23:30 +00:00
use criterion::*;
2022-02-16 01:01:12 +00:00
use std::{fs, path::PathBuf, slice};
2022-02-16 00:23:30 +00:00
2022-02-16 01:01:12 +00:00
fn gather_inputs(folder: &str, extension: &str) -> Vec<Box<[u8]>> {
2022-02-16 00:23:30 +00:00
let mut list = Vec::new();
let read_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join(folder)
.read_dir()
.unwrap();
for file_entry in read_dir {
match file_entry {
Ok(entry) => match entry.path().extension() {
Satisfy latest `clippy` lints (up to Rust 1.64) (#2081) * refactor: satisfy `clippy::borrow_deref_ref` * chore: satisfy `clippy::ptr_arg` * refactor: satisfy `clippy::needless_update` * chore: `allow(clippy::too_many_arguments)` on `write_output_glsl` test Since this is test code, I don't think there's a strong impetus to refactor types to consolidate or otherwise alter arguments here. Let's just `allow` this. * refactor: satisfy `clippy::single_match` I think it's sixes whether to keep this code as-is or to `allow(...)` as-is. 🤷🏻‍♂️ * refactor: satisfy `clippy::single_char_pattern` * refactor: satisfy `clippy::reversed_empty_ranges` The lint fires because it generally doesn't make sense to use a `Range` built this way; [upstream `Range` docs]) states: > It is empty if `start >= end`. `clippy` wants to help us from naively iterating over a `Range` like this! Thanks, `clippy`! However, we're not actually using the offending `addresses` variables for iteration. We're using them as a flat data structure with fields that happen to conceptually match. We can, therefore, sidestep this lint by "just" inlining into separate variables for start and end instead. [upstream `Range` docs]: https://doc.rust-lang.org/stable/std/ops/struct.Range.html * refactor: satisfy `clippy::pattern_type_mismatch` * chore: `allow(clippy::panic)` for `test` We definitely should let `panic!(...)` calls exist in `cfg(test)`! It's a very standard way to fail `#[test]` functions. It seems that previous test authors agree! 😅 * fixup! refactor: satisfy `clippy::pattern_type_mismatch` * fixup! refactor: satisfy `clippy::single_match`
2022-11-03 16:32:15 +00:00
Some(ostr) if ostr == extension => {
2022-02-16 01:01:12 +00:00
let input = fs::read(entry.path()).unwrap_or_default();
list.push(input.into_boxed_slice());
2022-02-16 00:23:30 +00:00
}
_ => continue,
},
Err(e) => {
log::warn!("Skipping file: {:?}", e);
continue;
}
}
}
list
}
2022-02-16 01:01:12 +00:00
fn parse_glsl(stage: naga::ShaderStage, inputs: &[Box<[u8]>]) {
let mut parser = naga::front::glsl::Frontend::default();
2022-02-16 01:01:12 +00:00
let options = naga::front::glsl::Options {
stage,
defines: Default::default(),
};
for input in inputs.iter() {
let string = std::str::from_utf8(input).unwrap();
parser.parse(&options, string).unwrap();
}
}
2022-02-16 00:23:30 +00:00
fn frontends(c: &mut Criterion) {
2022-02-16 01:01:12 +00:00
let mut group = c.benchmark_group("front");
2022-02-16 02:47:38 +00:00
#[cfg(all(feature = "wgsl-in", feature = "serialize", feature = "deserialize"))]
2022-02-16 01:01:12 +00:00
group.bench_function("bin", |b| {
let inputs_wgsl = gather_inputs("tests/in", "wgsl");
let mut frontend = naga::front::wgsl::Frontend::new();
2022-02-16 01:01:12 +00:00
let inputs_bin = inputs_wgsl
.iter()
.map(|input| {
let string = std::str::from_utf8(input).unwrap();
let module = frontend.parse(string).unwrap();
2022-02-16 01:01:12 +00:00
bincode::serialize(&module).unwrap()
})
.collect::<Vec<_>>();
b.iter(move || {
for input in inputs_bin.iter() {
bincode::deserialize::<naga::Module>(input).unwrap();
}
});
});
#[cfg(feature = "wgsl-in")]
2022-02-16 00:23:30 +00:00
group.bench_function("wgsl", |b| {
2022-02-17 14:45:45 +00:00
let inputs_wgsl = gather_inputs("tests/in", "wgsl");
let inputs = inputs_wgsl
.iter()
.map(|input| std::str::from_utf8(input).unwrap())
.collect::<Vec<_>>();
let mut frontend = naga::front::wgsl::Frontend::new();
2022-02-16 00:23:30 +00:00
b.iter(move || {
2022-02-17 14:45:45 +00:00
for &input in inputs.iter() {
frontend.parse(input).unwrap();
2022-02-16 00:23:30 +00:00
}
});
});
2022-02-16 01:01:12 +00:00
#[cfg(feature = "spv-in")]
group.bench_function("spv", |b| {
let inputs = gather_inputs("tests/in/spv", "spv");
b.iter(move || {
let options = naga::front::spv::Options::default();
for input in inputs.iter() {
let spv =
unsafe { slice::from_raw_parts(input.as_ptr() as *const u32, input.len() / 4) };
let parser = naga::front::spv::Frontend::new(spv.iter().cloned(), &options);
2022-02-16 01:01:12 +00:00
parser.parse().unwrap();
}
});
});
#[cfg(feature = "glsl-in")]
group.bench_function("glsl", |b| {
let vert = gather_inputs("tests/in/glsl", "vert");
b.iter(move || parse_glsl(naga::ShaderStage::Vertex, &vert));
let frag = gather_inputs("tests/in/glsl", "frag");
b.iter(move || parse_glsl(naga::ShaderStage::Vertex, &frag));
2022-02-16 01:21:54 +00:00
//TODO: hangs for some reason!
2022-02-16 01:01:12 +00:00
//let comp = gather_inputs("tests/in/glsl", "comp");
//b.iter(move || parse_glsl(naga::ShaderStage::Compute, &comp));
});
2022-02-16 00:23:30 +00:00
}
2022-02-16 02:47:38 +00:00
#[cfg(feature = "wgsl-in")]
fn gather_modules() -> Vec<naga::Module> {
let inputs = gather_inputs("tests/in", "wgsl");
let mut frontend = naga::front::wgsl::Frontend::new();
2022-02-16 02:47:38 +00:00
inputs
.iter()
.map(|input| {
let string = std::str::from_utf8(input).unwrap();
frontend.parse(string).unwrap()
2022-02-16 02:47:38 +00:00
})
.collect()
}
#[cfg(not(feature = "wgsl-in"))]
fn gather_modules() -> Vec<naga::Module> {
Vec::new()
}
2022-02-16 01:21:54 +00:00
2022-02-16 02:47:38 +00:00
fn validation(c: &mut Criterion) {
let inputs = gather_modules();
2022-02-16 01:21:54 +00:00
let mut group = c.benchmark_group("valid");
#[cfg(feature = "validate")]
group.bench_function("safe", |b| {
let mut validator = naga::valid::Validator::new(
naga::valid::ValidationFlags::all(),
naga::valid::Capabilities::all(),
);
b.iter(|| {
for input in inputs.iter() {
validator.validate(input).unwrap();
}
});
});
#[cfg(feature = "validate")]
group.bench_function("unsafe", |b| {
let mut validator = naga::valid::Validator::new(
naga::valid::ValidationFlags::empty(),
naga::valid::Capabilities::all(),
);
b.iter(|| {
for input in inputs.iter() {
validator.validate(input).unwrap();
}
});
});
}
2022-02-16 00:23:30 +00:00
2022-02-16 02:47:38 +00:00
fn backends(c: &mut Criterion) {
#[cfg(feature = "validate")]
let inputs = {
let mut validator = naga::valid::Validator::new(
naga::valid::ValidationFlags::empty(),
naga::valid::Capabilities::empty(),
);
let input_modules = gather_modules();
input_modules
.into_iter()
.flat_map(|module| validator.validate(&module).ok().map(|info| (module, info)))
.collect::<Vec<_>>()
};
#[cfg(not(feature = "validate"))]
let inputs = Vec::<(naga::Module, naga::valid::ModuleInfo)>::new();
let mut group = c.benchmark_group("back");
#[cfg(feature = "wgsl-out")]
group.bench_function("wgsl", |b| {
b.iter(|| {
let mut string = String::new();
let flags = naga::back::wgsl::WriterFlags::empty();
for &(ref module, ref info) in inputs.iter() {
let mut writer = naga::back::wgsl::Writer::new(&mut string, flags);
writer.write(module, info).unwrap();
string.clear();
}
});
});
#[cfg(feature = "spv-out")]
group.bench_function("spv", |b| {
b.iter(|| {
let mut data = Vec::new();
let options = naga::back::spv::Options::default();
for &(ref module, ref info) in inputs.iter() {
let mut writer = naga::back::spv::Writer::new(&options).unwrap();
writer.write(module, info, None, &mut data).unwrap();
data.clear();
}
});
});
#[cfg(feature = "spv-out")]
group.bench_function("spv-separate", |b| {
b.iter(|| {
let mut data = Vec::new();
let options = naga::back::spv::Options::default();
for &(ref module, ref info) in inputs.iter() {
let mut writer = naga::back::spv::Writer::new(&options).unwrap();
for ep in module.entry_points.iter() {
let pipeline_options = naga::back::spv::PipelineOptions {
shader_stage: ep.stage,
entry_point: ep.name.clone(),
};
writer
.write(module, info, Some(&pipeline_options), &mut data)
.unwrap();
data.clear();
}
}
});
});
#[cfg(feature = "msl-out")]
group.bench_function("msl", |b| {
b.iter(|| {
let mut string = String::new();
let options = naga::back::msl::Options::default();
for &(ref module, ref info) in inputs.iter() {
let pipeline_options = naga::back::msl::PipelineOptions::default();
let mut writer = naga::back::msl::Writer::new(&mut string);
writer
.write(module, info, &options, &pipeline_options)
.unwrap();
string.clear();
}
});
});
#[cfg(feature = "hlsl-out")]
group.bench_function("hlsl", |b| {
b.iter(|| {
let options = naga::back::hlsl::Options::default();
let mut string = String::new();
for &(ref module, ref info) in inputs.iter() {
let mut writer = naga::back::hlsl::Writer::new(&mut string, &options);
let _ = writer.write(module, info); // may fail on unimplemented things
string.clear();
}
});
});
#[cfg(feature = "glsl-out")]
group.bench_function("glsl-separate", |b| {
b.iter(|| {
let mut string = String::new();
let options = naga::back::glsl::Options {
version: naga::back::glsl::Version::new_gles(320),
2022-02-16 02:47:38 +00:00
writer_flags: naga::back::glsl::WriterFlags::empty(),
binding_map: Default::default(),
zero_initialize_workgroup_memory: true,
2022-02-16 02:47:38 +00:00
};
for &(ref module, ref info) in inputs.iter() {
for ep in module.entry_points.iter() {
let pipeline_options = naga::back::glsl::PipelineOptions {
shader_stage: ep.stage,
entry_point: ep.name.clone(),
multiview: None,
2022-02-16 02:47:38 +00:00
};
Satisfy latest `clippy` lints (up to Rust 1.64) (#2081) * refactor: satisfy `clippy::borrow_deref_ref` * chore: satisfy `clippy::ptr_arg` * refactor: satisfy `clippy::needless_update` * chore: `allow(clippy::too_many_arguments)` on `write_output_glsl` test Since this is test code, I don't think there's a strong impetus to refactor types to consolidate or otherwise alter arguments here. Let's just `allow` this. * refactor: satisfy `clippy::single_match` I think it's sixes whether to keep this code as-is or to `allow(...)` as-is. 🤷🏻‍♂️ * refactor: satisfy `clippy::single_char_pattern` * refactor: satisfy `clippy::reversed_empty_ranges` The lint fires because it generally doesn't make sense to use a `Range` built this way; [upstream `Range` docs]) states: > It is empty if `start >= end`. `clippy` wants to help us from naively iterating over a `Range` like this! Thanks, `clippy`! However, we're not actually using the offending `addresses` variables for iteration. We're using them as a flat data structure with fields that happen to conceptually match. We can, therefore, sidestep this lint by "just" inlining into separate variables for start and end instead. [upstream `Range` docs]: https://doc.rust-lang.org/stable/std/ops/struct.Range.html * refactor: satisfy `clippy::pattern_type_mismatch` * chore: `allow(clippy::panic)` for `test` We definitely should let `panic!(...)` calls exist in `cfg(test)`! It's a very standard way to fail `#[test]` functions. It seems that previous test authors agree! 😅 * fixup! refactor: satisfy `clippy::pattern_type_mismatch` * fixup! refactor: satisfy `clippy::single_match`
2022-11-03 16:32:15 +00:00
// might be `Err` if missing features
if let Ok(mut writer) = naga::back::glsl::Writer::new(
2022-02-16 02:47:38 +00:00
&mut string,
module,
info,
&options,
&pipeline_options,
naga::proc::BoundsCheckPolicies::default(),
2022-02-16 02:47:38 +00:00
) {
Satisfy latest `clippy` lints (up to Rust 1.64) (#2081) * refactor: satisfy `clippy::borrow_deref_ref` * chore: satisfy `clippy::ptr_arg` * refactor: satisfy `clippy::needless_update` * chore: `allow(clippy::too_many_arguments)` on `write_output_glsl` test Since this is test code, I don't think there's a strong impetus to refactor types to consolidate or otherwise alter arguments here. Let's just `allow` this. * refactor: satisfy `clippy::single_match` I think it's sixes whether to keep this code as-is or to `allow(...)` as-is. 🤷🏻‍♂️ * refactor: satisfy `clippy::single_char_pattern` * refactor: satisfy `clippy::reversed_empty_ranges` The lint fires because it generally doesn't make sense to use a `Range` built this way; [upstream `Range` docs]) states: > It is empty if `start >= end`. `clippy` wants to help us from naively iterating over a `Range` like this! Thanks, `clippy`! However, we're not actually using the offending `addresses` variables for iteration. We're using them as a flat data structure with fields that happen to conceptually match. We can, therefore, sidestep this lint by "just" inlining into separate variables for start and end instead. [upstream `Range` docs]: https://doc.rust-lang.org/stable/std/ops/struct.Range.html * refactor: satisfy `clippy::pattern_type_mismatch` * chore: `allow(clippy::panic)` for `test` We definitely should let `panic!(...)` calls exist in `cfg(test)`! It's a very standard way to fail `#[test]` functions. It seems that previous test authors agree! 😅 * fixup! refactor: satisfy `clippy::pattern_type_mismatch` * fixup! refactor: satisfy `clippy::single_match`
2022-11-03 16:32:15 +00:00
let _ = writer.write(); // might be `Err` if unsupported
}
2022-02-16 02:47:38 +00:00
string.clear();
}
}
});
});
}
2022-02-16 00:23:30 +00:00
criterion_group!(criterion, frontends, validation, backends,);
criterion_main!(criterion);