diff --git a/.gitignore b/.gitignore index aefc86aec..65edd583c 100644 --- a/.gitignore +++ b/.gitignore @@ -17,4 +17,4 @@ wgpu/red.png # Output from invalid comparison tests -**/screenshot-difference.png +**/*-difference.png diff --git a/wgpu/Cargo.toml b/wgpu/Cargo.toml index b607b699d..382d4f46c 100644 --- a/wgpu/Cargo.toml +++ b/wgpu/Cargo.toml @@ -87,6 +87,26 @@ git = "https://github.com/gfx-rs/naga" tag = "gfx-26" features = ["wgsl-in", "spv-out"] +[[example]] +name="boids" +path="examples/boids/main.rs" +test = true + +[[example]] +name="bunnymark" +path="examples/bunnymark/main.rs" +test = true + +[[example]] +name="conservative-raster" +path="examples/conservative-raster/main.rs" +test = true + +[[example]] +name="cube" +path="examples/cube/main.rs" +test = true + [[example]] name="hello-compute" test = true @@ -99,6 +119,31 @@ required-features = ["spirv"] name="mipmap" test = true +[[example]] +name="msaa-line" +path="examples/msaa-line/main.rs" +test = true + +[[example]] +name="shadow" +path="examples/shadow/main.rs" +test = true + +[[example]] +name="skybox" +path="examples/skybox/main.rs" +test = true + +[[example]] +name="texture-arrays" +path="examples/texture-arrays/main.rs" +test = true + +[[example]] +name="water" +path="examples/water/main.rs" +test = true + [target.'cfg(target_arch = "wasm32")'.dependencies] wasm-bindgen = "0.2.73" # remember to change version in wiki as well web-sys = { version = "=0.3.50", features = [ diff --git a/wgpu/examples/boids/main.rs b/wgpu/examples/boids/main.rs index 6392792d1..64c1df6a8 100644 --- a/wgpu/examples/boids/main.rs +++ b/wgpu/examples/boids/main.rs @@ -1,7 +1,10 @@ // Flocking boids example with gpu compute update pass // adapted from https://github.com/austinEng/webgpu-samples/blob/master/src/examples/computeBoids.ts -use rand::distributions::{Distribution, Uniform}; +use rand::{ + distributions::{Distribution, Uniform}, + SeedableRng, +}; use std::{borrow::Cow, mem}; use wgpu::util::DeviceExt; @@ -168,7 +171,7 @@ impl framework::Example for Example { // buffer for all particles data of type [(posx,posy,velx,vely),...] let mut initial_particle_data = vec![0.0f32; (4 * NUM_PARTICLES) as usize]; - let mut rng = rand::thread_rng(); + let mut rng = rand::rngs::StdRng::seed_from_u64(42); let unif = Uniform::new_inclusive(-1.0, 1.0); for particle_instance_chunk in initial_particle_data.chunks_mut(4) { particle_instance_chunk[0] = unif.sample(&mut rng); // posx @@ -314,3 +317,16 @@ impl framework::Example for Example { fn main() { framework::run::("boids"); } + +#[test] +fn boids() { + framework::test::( + concat!(env!("CARGO_MANIFEST_DIR"), "/examples/boids/screenshot.png"), + 1024, + 768, + wgpu::Features::default(), + framework::test_common::TestParameters::default(), + 0, + 50, + ); +} diff --git a/wgpu/examples/boids/screenshot.png b/wgpu/examples/boids/screenshot.png index e510c1c16..f3c6796b1 100644 Binary files a/wgpu/examples/boids/screenshot.png and b/wgpu/examples/boids/screenshot.png differ diff --git a/wgpu/examples/bunnymark/main.rs b/wgpu/examples/bunnymark/main.rs index 18c2efc89..57f3f4a51 100644 --- a/wgpu/examples/bunnymark/main.rs +++ b/wgpu/examples/bunnymark/main.rs @@ -349,3 +349,19 @@ impl framework::Example for Example { fn main() { framework::run::("bunnymark"); } + +#[test] +fn bunnymark() { + framework::test::( + concat!( + env!("CARGO_MANIFEST_DIR"), + "/examples/bunnymark/screenshot.png" + ), + 1024, + 768, + wgpu::Features::default(), + framework::test_common::TestParameters::default(), + 0, + 50, + ); +} diff --git a/wgpu/examples/bunnymark/screenshot.png b/wgpu/examples/bunnymark/screenshot.png new file mode 100644 index 000000000..48deda727 Binary files /dev/null and b/wgpu/examples/bunnymark/screenshot.png differ diff --git a/wgpu/examples/conservative-raster/main.rs b/wgpu/examples/conservative-raster/main.rs index 43f90b7a6..5a35ff283 100644 --- a/wgpu/examples/conservative-raster/main.rs +++ b/wgpu/examples/conservative-raster/main.rs @@ -73,7 +73,7 @@ impl framework::Example for Example { } fn init( sc_desc: &wgpu::SwapChainDescriptor, - adapter: &wgpu::Adapter, + _adapter: &wgpu::Adapter, device: &wgpu::Device, _queue: &wgpu::Queue, ) -> Self { @@ -133,7 +133,7 @@ impl framework::Example for Example { multisample: wgpu::MultisampleState::default(), }); - let pipeline_lines = if adapter + let pipeline_lines = if device .features() .contains(wgpu::Features::NON_FILL_POLYGON_MODE) { @@ -312,3 +312,19 @@ impl framework::Example for Example { fn main() { framework::run::("conservative-raster"); } + +#[test] +fn conservative_raster() { + framework::test::( + concat!( + env!("CARGO_MANIFEST_DIR"), + "/examples/conservative-raster/screenshot.png" + ), + 1024, + 768, + wgpu::Features::default(), + framework::test_common::TestParameters::default(), + 0, + 0, + ); +} diff --git a/wgpu/examples/conservative-raster/screenshot.png b/wgpu/examples/conservative-raster/screenshot.png index e227e10e6..4a4d4cd7e 100644 Binary files a/wgpu/examples/conservative-raster/screenshot.png and b/wgpu/examples/conservative-raster/screenshot.png differ diff --git a/wgpu/examples/cube/main.rs b/wgpu/examples/cube/main.rs index c890cee86..238e6f66c 100644 --- a/wgpu/examples/cube/main.rs +++ b/wgpu/examples/cube/main.rs @@ -379,3 +379,32 @@ impl framework::Example for Example { fn main() { framework::run::("cube"); } + +#[test] +fn cube() { + framework::test::( + concat!(env!("CARGO_MANIFEST_DIR"), "/examples/cube/screenshot.png"), + 1024, + 768, + wgpu::Features::default(), + framework::test_common::TestParameters::default(), + 1, + 3, + ); +} + +#[test] +fn cube_lines() { + framework::test::( + concat!( + env!("CARGO_MANIFEST_DIR"), + "/examples/cube/screenshot-lines.png" + ), + 1024, + 768, + wgpu::Features::NON_FILL_POLYGON_MODE, + framework::test_common::TestParameters::default(), + 1, + 3, + ); +} diff --git a/wgpu/examples/cube/screenshot-lines.png b/wgpu/examples/cube/screenshot-lines.png new file mode 100644 index 000000000..289a9733f Binary files /dev/null and b/wgpu/examples/cube/screenshot-lines.png differ diff --git a/wgpu/examples/cube/screenshot.png b/wgpu/examples/cube/screenshot.png index 784ffc463..bd8d0158c 100644 Binary files a/wgpu/examples/cube/screenshot.png and b/wgpu/examples/cube/screenshot.png differ diff --git a/wgpu/examples/framework.rs b/wgpu/examples/framework.rs index 79653dea2..89935cdc2 100644 --- a/wgpu/examples/framework.rs +++ b/wgpu/examples/framework.rs @@ -1,13 +1,13 @@ -use std::future::Future; #[cfg(not(target_arch = "wasm32"))] use std::time::{Duration, Instant}; +use std::{future::Future}; use winit::{ event::{self, WindowEvent}, event_loop::{ControlFlow, EventLoop}, }; #[path = "../tests/common/mod.rs"] -mod test_common; +pub mod test_common; #[rustfmt::skip] #[allow(unused)] @@ -365,20 +365,28 @@ pub fn run(title: &str) { } #[cfg(test)] -pub fn test(image_path: &str, width: u32, height: u32, tollerance: u8, max_outliers: usize) { +#[allow(dead_code)] +pub fn test( + image_path: &str, + width: u32, + height: u32, + optional_features: wgpu::Features, + base_test_parameters: test_common::TestParameters, + tollerance: u8, + max_outliers: usize, +) { use std::num::NonZeroU32; assert_eq!(width % 64, 0, "width needs to be aligned 64"); - let _optional = E::optional_features(); - let features = E::required_features(); + let features = E::required_features() | optional_features; let mut limits = E::required_limits(); if limits == wgpu::Limits::default() { limits = test_common::lowest_reasonable_limits(); } test_common::initialize_test( - test_common::TestParameters::default() + base_test_parameters .features(features) .limits(limits), |ctx| { diff --git a/wgpu/examples/mipmap/main.rs b/wgpu/examples/mipmap/main.rs index 6b7c45962..6a14d6c9a 100644 --- a/wgpu/examples/mipmap/main.rs +++ b/wgpu/examples/mipmap/main.rs @@ -484,7 +484,9 @@ fn mipmap() { ), 1024, 768, - 10, // Mipmap sampling is highly variant between impls. - 10, + wgpu::Features::default(), + framework::test_common::TestParameters::default(), + 15, // Mipmap sampling is highly variant between impls. This is currently bounded by the M1 + 40, ); } diff --git a/wgpu/examples/mipmap/screenshot.png b/wgpu/examples/mipmap/screenshot.png index 2369b8fe7..eb67ca39c 100644 Binary files a/wgpu/examples/mipmap/screenshot.png and b/wgpu/examples/mipmap/screenshot.png differ diff --git a/wgpu/examples/msaa-line/main.rs b/wgpu/examples/msaa-line/main.rs index 9f9d61973..9ada8be58 100644 --- a/wgpu/examples/msaa-line/main.rs +++ b/wgpu/examples/msaa-line/main.rs @@ -282,3 +282,19 @@ impl framework::Example for Example { fn main() { framework::run::("msaa-line"); } + +#[test] +fn msaa_line() { + framework::test::( + concat!( + env!("CARGO_MANIFEST_DIR"), + "/examples/msaa-line/screenshot.png" + ), + 1024, + 768, + wgpu::Features::default(), + framework::test_common::TestParameters::default(), + 0, + 1 << 15, // MSAA is comically different between vendors, 32k is a decent limit + ); +} diff --git a/wgpu/examples/msaa-line/screenshot.png b/wgpu/examples/msaa-line/screenshot.png index 9e4208124..332bda7a9 100644 Binary files a/wgpu/examples/msaa-line/screenshot.png and b/wgpu/examples/msaa-line/screenshot.png differ diff --git a/wgpu/examples/shadow/main.rs b/wgpu/examples/shadow/main.rs index 6fed1b54a..e7b27a7c3 100644 --- a/wgpu/examples/shadow/main.rs +++ b/wgpu/examples/shadow/main.rs @@ -821,3 +821,19 @@ impl framework::Example for Example { fn main() { framework::run::("shadow"); } + +#[test] +fn shadow() { + framework::test::( + concat!( + env!("CARGO_MANIFEST_DIR"), + "/examples/shadow/screenshot.png" + ), + 1024, + 768, + wgpu::Features::default(), + framework::test_common::TestParameters::default(), + 1, + 1, + ); +} diff --git a/wgpu/examples/shadow/screenshot.png b/wgpu/examples/shadow/screenshot.png index ae0782378..e0106800b 100644 Binary files a/wgpu/examples/shadow/screenshot.png and b/wgpu/examples/shadow/screenshot.png differ diff --git a/wgpu/examples/skybox/main.rs b/wgpu/examples/skybox/main.rs index b25844ab7..c212e3128 100644 --- a/wgpu/examples/skybox/main.rs +++ b/wgpu/examples/skybox/main.rs @@ -459,3 +459,67 @@ impl framework::Example for Skybox { fn main() { framework::run::("skybox"); } + +#[test] +fn skybox() { + framework::test::( + concat!( + env!("CARGO_MANIFEST_DIR"), + "/examples/skybox/screenshot.png" + ), + 1024, + 768, + wgpu::Features::default(), + framework::test_common::TestParameters::default(), + 2, + 3, + ); +} + +#[test] +fn skybox_bc1() { + framework::test::( + concat!( + env!("CARGO_MANIFEST_DIR"), + "/examples/skybox/screenshot-bc1.png" + ), + 1024, + 768, + wgpu::Features::TEXTURE_COMPRESSION_BC, + framework::test_common::TestParameters::default(), + 4, + 0, + ); +} + +#[test] +fn skybox_etc2() { + framework::test::( + concat!( + env!("CARGO_MANIFEST_DIR"), + "/examples/skybox/screenshot-etc2.png" + ), + 1024, + 768, + wgpu::Features::TEXTURE_COMPRESSION_ETC2, + framework::test_common::TestParameters::default(), + 1, // TODO + 1, // TODO + ); +} + +#[test] +fn skybox_astc() { + framework::test::( + concat!( + env!("CARGO_MANIFEST_DIR"), + "/examples/skybox/screenshot-astc.png" + ), + 1024, + 768, + wgpu::Features::TEXTURE_COMPRESSION_ASTC_LDR, + framework::test_common::TestParameters::default(), + 1, // TODO + 1, // TODO + ); +} diff --git a/wgpu/examples/skybox/screenshot-bc1.png b/wgpu/examples/skybox/screenshot-bc1.png new file mode 100644 index 000000000..d111bc512 Binary files /dev/null and b/wgpu/examples/skybox/screenshot-bc1.png differ diff --git a/wgpu/examples/skybox/screenshot.png b/wgpu/examples/skybox/screenshot.png index db0cb5ba3..362c921f9 100644 Binary files a/wgpu/examples/skybox/screenshot.png and b/wgpu/examples/skybox/screenshot.png differ diff --git a/wgpu/examples/skybox/shader.wgsl b/wgpu/examples/skybox/shader.wgsl index 9d211eed5..700fde930 100644 --- a/wgpu/examples/skybox/shader.wgsl +++ b/wgpu/examples/skybox/shader.wgsl @@ -73,6 +73,6 @@ fn fs_entity(in: EntityOutput) -> [[location(0)]] vec4 { let normal = normalize(in.normal); let reflected = incident - 2.0 * dot(normal, incident) * normal; - let reflected_color = textureSample(r_texture, r_sampler, reflected); - return vec4(0.1, 0.1, 0.1, 0.1) + 0.5 * reflected_color; + let reflected_color = textureSample(r_texture, r_sampler, reflected).rgb; + return vec4(vec3(0.1) + 0.5 * reflected_color, 1.0); } diff --git a/wgpu/examples/texture-arrays/main.rs b/wgpu/examples/texture-arrays/main.rs index ae452ed53..db0594867 100644 --- a/wgpu/examples/texture-arrays/main.rs +++ b/wgpu/examples/texture-arrays/main.rs @@ -100,7 +100,7 @@ impl framework::Example for Example { f if f.contains(wgpu::Features::SAMPLED_TEXTURE_ARRAY_NON_UNIFORM_INDEXING) => { wgpu::include_spirv_raw!("non-uniform.frag.spv") } - f if f.contains(wgpu::Features::SAMPLED_TEXTURE_ARRAY_DYNAMIC_INDEXING) => { + f if f.contains(wgpu::Features::SAMPLED_TEXTURE_ARRAY_DYNAMIC_INDEXING | wgpu::Features::PUSH_CONSTANTS) => { uniform_workaround = true; wgpu::include_spirv_raw!("uniform.frag.spv") } @@ -322,3 +322,73 @@ impl framework::Example for Example { fn main() { framework::run::("texture-arrays"); } + +// This fails due to an issue with naga https://github.com/gfx-rs/wgpu/issues/1532 +#[test] +fn texture_arrays_constant() { + framework::test::( + concat!( + env!("CARGO_MANIFEST_DIR"), + "/examples/texture-arrays/screenshot.png" + ), + 1024, + 768, + wgpu::Features::default(), + framework::test_common::TestParameters::default().failure(), + 0, + 0, + ); +} + +// This fails due to an issue with naga https://github.com/gfx-rs/wgpu/issues/1532 +#[test] +fn texture_arrays_uniform() { + framework::test::( + concat!( + env!("CARGO_MANIFEST_DIR"), + "/examples/texture-arrays/screenshot.png" + ), + 1024, + 768, + wgpu::Features::SAMPLED_TEXTURE_ARRAY_DYNAMIC_INDEXING | wgpu::Features::PUSH_CONSTANTS, + framework::test_common::TestParameters::default().failure(), + 0, + 0, + ); +} + + +// This fails due to an issue with naga https://github.com/gfx-rs/wgpu/issues/1532 +#[test] +fn texture_arrays_non_uniform() { + framework::test::( + concat!( + env!("CARGO_MANIFEST_DIR"), + "/examples/texture-arrays/screenshot.png" + ), + 1024, + 768, + wgpu::Features::SAMPLED_TEXTURE_ARRAY_NON_UNIFORM_INDEXING, + framework::test_common::TestParameters::default().failure(), + 0, + 0, + ); +} + + +// This fails due to an issue with naga https://github.com/gfx-rs/wgpu/issues/1532 +#[test] +fn texture_arrays_unsized_non_uniform() { + framework::test::( + concat!( + env!("CARGO_MANIFEST_DIR"), + "/examples/texture-arrays/screenshot.png" + ), + 1024, + 768, + wgpu::Features::SAMPLED_TEXTURE_ARRAY_NON_UNIFORM_INDEXING | wgpu::Features::UNSIZED_BINDING_ARRAY, + framework::test_common::TestParameters::default().failure(), + 0, + 0, + ); +} diff --git a/wgpu/examples/water/main.rs b/wgpu/examples/water/main.rs index f6290798c..05afd72ad 100644 --- a/wgpu/examples/water/main.rs +++ b/wgpu/examples/water/main.rs @@ -5,6 +5,7 @@ mod point_gen; use bytemuck::{Pod, Zeroable}; use cgmath::Point3; +use rand::SeedableRng; use std::{borrow::Cow, iter, mem}; use wgpu::util::DeviceExt; @@ -279,7 +280,7 @@ impl framework::Example for Example { let terrain_noise = noise::OpenSimplex::new(); // Random colouration - let mut terrain_random = rand::thread_rng(); + let mut terrain_random = rand::rngs::StdRng::seed_from_u64(42); // Generate terrain. The closure determines what each hexagon will look like. let terrain = @@ -788,3 +789,19 @@ impl framework::Example for Example { fn main() { framework::run::("water"); } + +#[test] +fn shadow() { + framework::test::( + concat!( + env!("CARGO_MANIFEST_DIR"), + "/examples/water/screenshot.png" + ), + 1024, + 768, + wgpu::Features::default(), + framework::test_common::TestParameters::default(), + 2, + 2, + ); +} diff --git a/wgpu/examples/water/screenshot.png b/wgpu/examples/water/screenshot.png index 434ebf3f2..7d71ae573 100644 Binary files a/wgpu/examples/water/screenshot.png and b/wgpu/examples/water/screenshot.png differ diff --git a/wgpu/tests/common/image.rs b/wgpu/tests/common/image.rs index 7e24630b0..11400650c 100644 --- a/wgpu/tests/common/image.rs +++ b/wgpu/tests/common/image.rs @@ -100,7 +100,7 @@ pub fn compare_image_output( .max() .unwrap(); - if outliers >= max_outliers { + if outliers > max_outliers { // Because the deta is mismatched, lets output the difference to a file. let old_path = Path::new(&path); let difference_path = Path::new(&path).with_file_name( diff --git a/wgpu/tests/common/mod.rs b/wgpu/tests/common/mod.rs index 7de9ba953..e202f05a9 100644 --- a/wgpu/tests/common/mod.rs +++ b/wgpu/tests/common/mod.rs @@ -46,18 +46,18 @@ pub fn lowest_reasonable_limits() -> Limits { max_texture_dimension_2d: 1024, max_texture_dimension_3d: 32, max_texture_array_layers: 32, - max_bind_groups: 1, - max_dynamic_uniform_buffers_per_pipeline_layout: 1, - max_dynamic_storage_buffers_per_pipeline_layout: 1, - max_sampled_textures_per_shader_stage: 1, - max_samplers_per_shader_stage: 1, - max_storage_buffers_per_shader_stage: 1, - max_storage_textures_per_shader_stage: 1, - max_uniform_buffers_per_shader_stage: 1, + max_bind_groups: 2, + max_dynamic_uniform_buffers_per_pipeline_layout: 2, + max_dynamic_storage_buffers_per_pipeline_layout: 2, + max_sampled_textures_per_shader_stage:2, + max_samplers_per_shader_stage: 2, + max_storage_buffers_per_shader_stage: 2, + max_storage_textures_per_shader_stage: 2, + max_uniform_buffers_per_shader_stage: 2, max_uniform_buffer_binding_size: 256, - max_storage_buffer_binding_size: 256, - max_vertex_buffers: 1, - max_vertex_attributes: 2, + max_storage_buffer_binding_size: 1 << 16, + max_vertex_buffers: 4, + max_vertex_attributes: 4, max_vertex_buffer_array_stride: 32, max_push_constant_size: 0, }