diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3434a01e7f..84bb455a53 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,6 +10,7 @@ on: env: CARGO_INCREMENTAL: false CARGO_TERM_COLOR: always + RUST_LOG: info RUST_BACKTRACE: full MSRV: 1.65 PKG_CONFIG_ALLOW_CROSS: 1 # allow android to work @@ -112,10 +113,23 @@ jobs: with: key: clippy-${{ matrix.target }}-${{ matrix.kind }}-${{ env.CACHE_SUFFIX }} + - name: install aarch64-linux-gnu g++ + if: matrix.target == 'aarch64-unknown-linux-gnu' + run: | + set -e + + sudo apt-get update -y -qq + + sudo apt-get install g++-aarch64-linux-gnu + - name: add android apk to path if: matrix.target == 'aarch64-linux-android' run: | - echo "$ANDROID_HOME/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/bin" >> $GITHUB_PATH + # clang++ will be detected correctly by CC from path + echo "$ANDROID_NDK/toolchains/llvm/prebuilt/linux-x86_64/bin" >> $GITHUB_PATH + + # the android sdk doesn't use the conventional name for ar, so explicitly set it. + echo "AR_aarch64_linux_android=llvm-ar" >> "$GITHUB_ENV" - name: check web if: matrix.kind == 'web' @@ -224,7 +238,7 @@ jobs: mkdir -p swiftshader curl -LsSf https://github.com/gfx-rs/ci-build/releases/latest/download/swiftshader-linux-x86_64.tar.xz | tar -xf - -C swiftshader - echo "LD_LIBRARY_PATH=$PWD/swiftshader" >> $GITHUB_ENV + echo "VK_ICD_FILENAMES=$PWD/swiftshader/vk_swiftshader_icd.json" >> $GITHUB_ENV - name: install llvmpipe, vulkan sdk if: matrix.os == 'ubuntu-22.04' @@ -272,6 +286,13 @@ jobs: WGPU_BACKEND=$backend cargo llvm-cov --no-cfg-coverage nextest -p wgpu -p wgpu-types -p wgpu-hal -p wgpu-core -p player --no-fail-fast --no-report done + - uses: actions/upload-artifact@v3 + with: + name: comparison-images + path: | + **/*-actual.png + **/*-difference.png + - name: generate coverage report shell: bash run: | diff --git a/Cargo.lock b/Cargo.lock index 4c8d1bcf4c..51c9270ca9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1764,6 +1764,24 @@ dependencies = [ "syn 1.0.105", ] +[[package]] +name = "nv-flip" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f87db52c5c87af428016af298dcdcb879ed7e235603de697d1d2f90ddd0d95be" +dependencies = [ + "nv-flip-sys", +] + +[[package]] +name = "nv-flip-sys" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "932e1eed40002ba70fccac6dab3b64be3301607c3ee88bd14989c4d4e1c1c993" +dependencies = [ + "cc", +] + [[package]] name = "obj" version = "0.10.2" @@ -3147,6 +3165,7 @@ dependencies = [ "naga", "nanorand", "noise", + "nv-flip", "obj", "parking_lot 0.12.1", "png", diff --git a/Cargo.toml b/Cargo.toml index 0a39aa49dd..7aaedc183f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -65,6 +65,7 @@ libloading = ">=0.7,<0.9" libc = "0.2" log = "0.4" nanorand = { version = "0.7", default-features = false } +nv-flip = "0.1" num-traits = { version = "0.2" } # Opt out of noise's "default-features" to avoid "image" feature as a dependency count optimization. # This will not be required in the next release since it has been removed from the default feature in https://github.com/Razaekel/noise-rs/commit/1af9e1522236b2c584fb9a02150c9c67a5e6bb04#diff-2e9d962a08321605940b5a657135052fbcef87b5e360662bb527c96d9a615542 @@ -149,3 +150,7 @@ wgpu-types = { path = "./wgpu-types" } #web-sys = { path = "../wasm-bindgen/crates/web-sys" } #js-sys = { path = "../wasm-bindgen/crates/js-sys" } #wasm-bindgen = { path = "../wasm-bindgen" } + +# Speed up image comparison even in debug builds +[profile.dev.package."nv-flip-sys"] +opt-level = 3 diff --git a/wgpu-types/src/lib.rs b/wgpu-types/src/lib.rs index 5025ac7ae1..63a646b5d7 100644 --- a/wgpu-types/src/lib.rs +++ b/wgpu-types/src/lib.rs @@ -111,6 +111,21 @@ pub enum Backend { BrowserWebGpu = 6, } +impl Backend { + /// Returns the string name of the backend. + pub fn to_str(self) -> &'static str { + match self { + Backend::Empty => "empty", + Backend::Vulkan => "vulkan", + Backend::Metal => "metal", + Backend::Dx12 => "dx12", + Backend::Dx11 => "dx11", + Backend::Gl => "gl", + Backend::BrowserWebGpu => "webgpu", + } + } +} + /// Power Preference when choosing a physical adapter. /// /// Corresponds to [WebGPU `GPUPowerPreference`]( diff --git a/wgpu/Cargo.toml b/wgpu/Cargo.toml index 69cdbe5a8d..e63cd19d3a 100644 --- a/wgpu/Cargo.toml +++ b/wgpu/Cargo.toml @@ -178,6 +178,7 @@ winit.workspace = true # for "halmark" example [target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] async-executor.workspace = true +nv-flip.workspace = true [dependencies.naga] workspace = true diff --git a/wgpu/examples/boids/main.rs b/wgpu/examples/boids/main.rs index a906bde3c8..80d28dc3e7 100644 --- a/wgpu/examples/boids/main.rs +++ b/wgpu/examples/boids/main.rs @@ -335,6 +335,7 @@ wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser); #[wasm_bindgen_test::wasm_bindgen_test] fn boids() { framework::test::(framework::FrameworkRefTest { + // Generated on 1080ti on Vk/Windows image_path: "/examples/boids/screenshot.png", width: 1024, height: 768, @@ -342,7 +343,6 @@ fn boids() { base_test_parameters: framework::test_common::TestParameters::default() .downlevel_flags(wgpu::DownlevelFlags::COMPUTE_SHADERS) .limits(wgpu::Limits::downlevel_defaults()), - tolerance: 0, - max_outliers: 2500, // Currently bounded by WARP + comparisons: &[framework::ComparisonType::Mean(0.005)], }); } diff --git a/wgpu/examples/bunnymark/main.rs b/wgpu/examples/bunnymark/main.rs index 2154be0d01..a4553f663f 100644 --- a/wgpu/examples/bunnymark/main.rs +++ b/wgpu/examples/bunnymark/main.rs @@ -369,7 +369,13 @@ fn bunnymark() { height: 768, optional_features: wgpu::Features::default(), base_test_parameters: framework::test_common::TestParameters::default(), - tolerance: 10, - max_outliers: 53, // Bounded by WARP + // We're looking for very small differences, so look in the high percentiles. + comparisons: &[ + framework::ComparisonType::Mean(0.05), + framework::ComparisonType::Percentile { + percentile: 0.95, + threshold: 0.05, + }, + ], }); } diff --git a/wgpu/examples/conservative-raster/main.rs b/wgpu/examples/conservative-raster/main.rs index 69336cc993..9ed305b3cc 100644 --- a/wgpu/examples/conservative-raster/main.rs +++ b/wgpu/examples/conservative-raster/main.rs @@ -326,7 +326,6 @@ fn conservative_raster() { height: 768, optional_features: wgpu::Features::default(), base_test_parameters: framework::test_common::TestParameters::default(), - tolerance: 0, - max_outliers: 0, + comparisons: &[framework::ComparisonType::Mean(0.0)], }); } diff --git a/wgpu/examples/cube/main.rs b/wgpu/examples/cube/main.rs index 2be0fba5e9..61e9019886 100644 --- a/wgpu/examples/cube/main.rs +++ b/wgpu/examples/cube/main.rs @@ -413,13 +413,15 @@ wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser); #[wasm_bindgen_test::wasm_bindgen_test] fn cube() { framework::test::(framework::FrameworkRefTest { + // Generated on 1080ti on Vk/Windows image_path: "/examples/cube/screenshot.png", width: 1024, height: 768, optional_features: wgpu::Features::default(), base_test_parameters: framework::test_common::TestParameters::default(), - tolerance: 1, - max_outliers: 1225, // Bounded by swiftshader + comparisons: &[ + framework::ComparisonType::Mean(0.04), // Bounded by Intel 630 on Vk/Windows + ], }); } @@ -427,12 +429,19 @@ fn cube() { #[wasm_bindgen_test::wasm_bindgen_test] fn cube_lines() { framework::test::(framework::FrameworkRefTest { + // Generated on 1080ti on Vk/Windows image_path: "/examples/cube/screenshot-lines.png", width: 1024, height: 768, optional_features: wgpu::Features::POLYGON_MODE_LINE, base_test_parameters: framework::test_common::TestParameters::default(), - tolerance: 2, - max_outliers: 1250, // Bounded by swiftshader + // We're looking for tiny changes here, so we focus on a spike in the 95th percentile. + comparisons: &[ + framework::ComparisonType::Mean(0.05), // Bounded by Intel 630 on Vk/Windows + framework::ComparisonType::Percentile { + percentile: 0.95, + threshold: 0.36, + }, // Bounded by 1080ti on DX12 + ], }); } diff --git a/wgpu/examples/framework.rs b/wgpu/examples/framework.rs index 2f33915ba9..cd5e07820e 100644 --- a/wgpu/examples/framework.rs +++ b/wgpu/examples/framework.rs @@ -494,6 +494,9 @@ pub fn parse_url_query_string<'a>(query: &'a str, search_key: &str) -> Option<&' None } +#[cfg(test)] +pub use test_common::image::ComparisonType; + #[cfg(test)] pub struct FrameworkRefTest { pub image_path: &'static str, @@ -501,8 +504,8 @@ pub struct FrameworkRefTest { pub height: u32, pub optional_features: wgpu::Features, pub base_test_parameters: test_common::TestParameters, - pub tolerance: u8, - pub max_outliers: usize, + /// Comparisons against FLIP statistics that determine if the test passes or fails. + pub comparisons: &'static [ComparisonType], } #[cfg(test)] @@ -616,11 +619,11 @@ pub fn test(mut params: FrameworkRefTest) { test_common::image::compare_image_output( env!("CARGO_MANIFEST_DIR").to_string() + params.image_path, + ctx.adapter_info.backend, params.width, params.height, &bytes, - params.tolerance, - params.max_outliers, + params.comparisons, ); }, ); diff --git a/wgpu/examples/mipmap/main.rs b/wgpu/examples/mipmap/main.rs index 6175685dec..c30473a47f 100644 --- a/wgpu/examples/mipmap/main.rs +++ b/wgpu/examples/mipmap/main.rs @@ -500,7 +500,6 @@ fn mipmap() { optional_features: wgpu::Features::default(), base_test_parameters: framework::test_common::TestParameters::default() .backend_failure(wgpu::Backends::GL), - tolerance: 50, - max_outliers: 5000, // Mipmap sampling is highly variant between impls. This is currently bounded by lavapipe + comparisons: &[framework::ComparisonType::Mean(0.02)], }); } diff --git a/wgpu/examples/msaa-line/main.rs b/wgpu/examples/msaa-line/main.rs index 1de7044bc3..b5321ea8c6 100644 --- a/wgpu/examples/msaa-line/main.rs +++ b/wgpu/examples/msaa-line/main.rs @@ -324,10 +324,18 @@ fn msaa_line() { image_path: "/examples/msaa-line/screenshot.png", width: 1024, height: 768, - optional_features: wgpu::Features::default() - | wgt::Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES, - base_test_parameters: framework::test_common::TestParameters::default(), - tolerance: 64, - max_outliers: 1 << 16, // MSAA is comically different between vendors, 32k is a decent limit + optional_features: wgt::Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES, + base_test_parameters: framework::test_common::TestParameters::default() + // AMD seems to render nothing on DX12 https://github.com/gfx-rs/wgpu/issues/3838 + .specific_failure(Some(wgpu::Backends::DX12), Some(0x1002), None, false), + // There's a lot of natural variance so we check the weighted median too to differentiate + // real failures from variance. + comparisons: &[ + framework::ComparisonType::Mean(0.065), + framework::ComparisonType::Percentile { + percentile: 0.5, + threshold: 0.29, + }, + ], }); } diff --git a/wgpu/examples/shadow/main.rs b/wgpu/examples/shadow/main.rs index b5acb59530..7c6f5017a7 100644 --- a/wgpu/examples/shadow/main.rs +++ b/wgpu/examples/shadow/main.rs @@ -859,7 +859,6 @@ fn shadow() { .specific_failure(Some(wgpu::Backends::VULKAN), None, Some("V3D"), false) // llvmpipe versions in CI are flaky: https://github.com/gfx-rs/wgpu/issues/2594 .specific_failure(Some(wgpu::Backends::VULKAN), None, Some("llvmpipe"), true), - tolerance: 2, - max_outliers: 1075, // bounded by swiftshader + comparisons: &[framework::ComparisonType::Mean(0.02)], }); } diff --git a/wgpu/examples/skybox/main.rs b/wgpu/examples/skybox/main.rs index d5a5652b7e..6b0637643e 100644 --- a/wgpu/examples/skybox/main.rs +++ b/wgpu/examples/skybox/main.rs @@ -482,8 +482,7 @@ fn skybox() { Some("ANGLE"), false, ), - tolerance: 3, - max_outliers: 207, // bounded by swiftshader + comparisons: &[framework::ComparisonType::Mean(0.015)], }); } @@ -496,8 +495,7 @@ fn skybox_bc1() { height: 768, optional_features: wgpu::Features::TEXTURE_COMPRESSION_BC, base_test_parameters: framework::test_common::TestParameters::default(), // https://bugs.chromium.org/p/angleproject/issues/detail?id=7056 - tolerance: 5, - max_outliers: 191, // Bounded by swiftshader + comparisons: &[framework::ComparisonType::Mean(0.02)], }); } @@ -510,8 +508,7 @@ fn skybox_etc2() { height: 768, optional_features: wgpu::Features::TEXTURE_COMPRESSION_ETC2, base_test_parameters: framework::test_common::TestParameters::default(), // https://bugs.chromium.org/p/angleproject/issues/detail?id=7056 - tolerance: 5, - max_outliers: 248, // Bounded by swiftshader + comparisons: &[framework::ComparisonType::Mean(0.015)], }); } @@ -524,7 +521,6 @@ fn skybox_astc() { height: 768, optional_features: wgpu::Features::TEXTURE_COMPRESSION_ASTC, base_test_parameters: framework::test_common::TestParameters::default(), // https://bugs.chromium.org/p/angleproject/issues/detail?id=7056 - tolerance: 5, - max_outliers: 300, // Bounded by rp4 on vk + comparisons: &[framework::ComparisonType::Mean(0.016)], }); } diff --git a/wgpu/examples/stencil-triangles/main.rs b/wgpu/examples/stencil-triangles/main.rs index aaed5c08a9..5ad46c6ac9 100644 --- a/wgpu/examples/stencil-triangles/main.rs +++ b/wgpu/examples/stencil-triangles/main.rs @@ -246,7 +246,6 @@ fn stencil_triangles() { height: 768, optional_features: wgpu::Features::default(), base_test_parameters: framework::test_common::TestParameters::default(), - tolerance: 1, - max_outliers: 0, + comparisons: &[framework::ComparisonType::Mean(0.03)], }); } diff --git a/wgpu/examples/texture-arrays/main.rs b/wgpu/examples/texture-arrays/main.rs index 1ddf681ab4..c9318673eb 100644 --- a/wgpu/examples/texture-arrays/main.rs +++ b/wgpu/examples/texture-arrays/main.rs @@ -422,8 +422,7 @@ fn texture_arrays_uniform() { height: 768, optional_features: wgpu::Features::empty(), base_test_parameters: framework::test_common::TestParameters::default(), - tolerance: 0, - max_outliers: 0, + comparisons: &[framework::ComparisonType::Mean(0.0)], }); } @@ -437,7 +436,6 @@ fn texture_arrays_non_uniform() { optional_features: wgpu::Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING, base_test_parameters: framework::test_common::TestParameters::default(), - tolerance: 0, - max_outliers: 0, + comparisons: &[framework::ComparisonType::Mean(0.0)], }); } diff --git a/wgpu/examples/water/main.rs b/wgpu/examples/water/main.rs index da7ad3aaee..9f516cd532 100644 --- a/wgpu/examples/water/main.rs +++ b/wgpu/examples/water/main.rs @@ -832,7 +832,6 @@ fn water() { optional_features: wgpu::Features::default(), base_test_parameters: framework::test_common::TestParameters::default() .downlevel_flags(wgpu::DownlevelFlags::READ_ONLY_DEPTH_STENCIL), - tolerance: 5, - max_outliers: 1693, // bounded by swiftshader + comparisons: &[framework::ComparisonType::Mean(0.01)], }); } diff --git a/wgpu/tests/common/image.rs b/wgpu/tests/common/image.rs index f3c9df6baf..9009909d68 100644 --- a/wgpu/tests/common/image.rs +++ b/wgpu/tests/common/image.rs @@ -1,10 +1,4 @@ -use std::{ - borrow::Cow, - ffi::{OsStr, OsString}, - io, - path::Path, - str::FromStr, -}; +use std::{borrow::Cow, ffi::OsStr, io, path::Path}; use wgpu::util::DeviceExt; use wgpu::*; @@ -71,80 +65,187 @@ pub fn calc_difference(lhs: u8, rhs: u8) -> u8 { (lhs as i16 - rhs as i16).unsigned_abs() as u8 } +fn add_alpha(input: &[u8]) -> Vec { + input + .chunks_exact(3) + .flat_map(|chunk| [chunk[0], chunk[1], chunk[2], 255]) + .collect() +} + +fn remove_alpha(input: &[u8]) -> Vec { + input + .chunks_exact(4) + .flat_map(|chunk| &chunk[0..3]) + .copied() + .collect() +} + +#[cfg(not(target_arch = "wasm32"))] +fn print_flip(pool: &mut nv_flip::FlipPool) { + println!("\tMean: {:.6}", pool.mean()); + println!("\tMin Value: {:.6}", pool.min_value()); + for percentile in [25, 50, 75, 95, 99] { + println!( + "\t {percentile}%: {:.6}", + pool.get_percentile(percentile as f32 / 100.0, true) + ); + } + println!("\tMax Value: {:.6}", pool.max_value()); +} + +/// The FLIP library generates a per-pixel error map where 0.0 represents "no error" +/// and 1.0 represents "maximum error" between the images. This is then put into +/// a weighted-histogram, which we query to determine if the errors between +/// the test and reference image is high enough to count as "different". +/// +/// Error thresholds will be different for every test, but good initial values +/// to look at are in the [0.01, 0.1] range. The larger the area that might have +/// inherent variance, the larger this base value is. Using a high percentile comparison +/// (e.g. 95% or 99%) is good for images that are likely to have a lot of error +/// in a small area when they fail. +#[derive(Debug, Clone, Copy)] +pub enum ComparisonType { + /// If the mean error is greater than the given value, the test will fail. + Mean(f32), + /// If the given percentile is greater than the given value, the test will fail. + /// + /// The percentile is given in the range [0, 1]. + Percentile { percentile: f32, threshold: f32 }, +} + +impl ComparisonType { + #[cfg(not(target_arch = "wasm32"))] + fn check(&self, pool: &mut nv_flip::FlipPool) -> bool { + match *self { + ComparisonType::Mean(v) => { + let mean = pool.mean(); + let within = mean <= v; + println!( + "\tExpected Mean ({:.6}) to be under expected maximum ({}): {}", + mean, + v, + if within { "PASS" } else { "FAIL" } + ); + within + } + ComparisonType::Percentile { + percentile: p, + threshold: v, + } => { + let percentile = pool.get_percentile(p, true); + let within = percentile <= v; + println!( + "\tExpected {}% ({:.6}) to be under expected maximum ({}): {}", + p * 100.0, + percentile, + v, + if within { "PASS" } else { "FAIL" } + ); + within + } + } + } +} + pub fn compare_image_output( path: impl AsRef + AsRef, + backend: wgpu::Backend, width: u32, height: u32, - data: &[u8], - tolerance: u8, - max_outliers: usize, + test_with_alpha: &[u8], + checks: &[ComparisonType], ) { - let comparison_data = read_png(&path, width, height); - - if let Some(cmp) = comparison_data { - assert_eq!(cmp.len(), data.len()); - - let difference_data: Vec<_> = cmp - .chunks_exact(4) - .zip(data.chunks_exact(4)) - .flat_map(|(cmp_chunk, data_chunk)| { - [ - calc_difference(cmp_chunk[0], data_chunk[0]), - calc_difference(cmp_chunk[1], data_chunk[1]), - calc_difference(cmp_chunk[2], data_chunk[2]), - 255, - ] - }) - .collect(); - - let outliers: usize = difference_data - .chunks_exact(4) - .map(|colors| { - (colors[0] > tolerance) as usize - + (colors[1] > tolerance) as usize - + (colors[2] > tolerance) as usize - }) - .sum(); - - let max_difference = difference_data - .chunks_exact(4) - .map(|colors| colors[0].max(colors[1]).max(colors[2])) - .max() - .unwrap(); - - if outliers > max_outliers { - // Because the data is mismatched, lets output the difference to a file. - let old_path = Path::new(&path); - let actual_path = Path::new(&path).with_file_name( - OsString::from_str( - &(old_path.file_stem().unwrap().to_string_lossy() + "-actual.png"), - ) - .unwrap(), - ); - let difference_path = Path::new(&path).with_file_name( - OsString::from_str( - &(old_path.file_stem().unwrap().to_string_lossy() + "-difference.png"), - ) - .unwrap(), - ); - - write_png(actual_path, width, height, data, png::Compression::Fast); - write_png( - difference_path, - width, - height, - &difference_data, - png::Compression::Fast, - ); + #[cfg(not(target_arch = "wasm32"))] + { + use std::{ffi::OsString, str::FromStr}; + + let reference_with_alpha = read_png(&path, width, height); + + let reference = match reference_with_alpha { + Some(v) => remove_alpha(&v), + None => { + write_png( + &path, + width, + height, + test_with_alpha, + png::Compression::Best, + ); + return; + } + }; + let test = remove_alpha(test_with_alpha); + + assert_eq!(reference.len(), test.len()); + + let reference_flip = nv_flip::FlipImageRgb8::with_data(width, height, &reference); + let test_flip = nv_flip::FlipImageRgb8::with_data(width, height, &test); + + let error_map_flip = nv_flip::flip( + reference_flip, + test_flip, + nv_flip::DEFAULT_PIXELS_PER_DEGREE, + ); + let mut pool = nv_flip::FlipPool::from_image(&error_map_flip); + + let reference_path = Path::new(&path); + println!( + "Starting image comparison test with reference image \"{}\"", + reference_path.display() + ); + + print_flip(&mut pool); + + // If there are no checks, we want to fail the test. + let mut all_passed = !checks.is_empty(); + // We always iterate all of these, as the call to check prints + for check in checks { + all_passed &= check.check(&mut pool); + } - panic!( - "Image data mismatch! Outlier count {outliers} over limit {max_outliers}. Max difference {max_difference}" - ) - } else { - println!("{outliers} outliers over max difference {max_difference}"); + let file_stem = reference_path.file_stem().unwrap().to_string_lossy(); + // Determine the paths to write out the various intermediate files + let actual_path = Path::new(&path).with_file_name( + OsString::from_str(&format!("{}-{}-actual.png", file_stem, backend.to_str(),)).unwrap(), + ); + let difference_path = Path::new(&path).with_file_name( + OsString::from_str(&format!( + "{}-{}-difference.png", + file_stem, + backend.to_str(), + )) + .unwrap(), + ); + + // Convert the error values to a false color reprensentation + let magma_image = error_map_flip + .apply_color_lut(&nv_flip::magma_lut()) + .to_vec(); + let magma_image_with_alpha = add_alpha(&magma_image); + + write_png( + actual_path, + width, + height, + test_with_alpha, + png::Compression::Fast, + ); + write_png( + difference_path, + width, + height, + &magma_image_with_alpha, + png::Compression::Fast, + ); + + if !all_passed { + panic!("Image data mismatch!") } - } else { - write_png(&path, width, height, data, png::Compression::Best); + } + + #[cfg(target_arch = "wasm32")] + { + let _ = (path, backend, width, height, test_with_alpha, checks); } } diff --git a/wgpu/tests/shader/struct_layout.rs b/wgpu/tests/shader/struct_layout.rs index a2f1f8a1ed..c62588ab1b 100644 --- a/wgpu/tests/shader/struct_layout.rs +++ b/wgpu/tests/shader/struct_layout.rs @@ -183,6 +183,8 @@ fn uniform_input() { initialize_test( TestParameters::default() .downlevel_flags(DownlevelFlags::COMPUTE_SHADERS) + // Validation errors thrown by the SPIR-V validator https://github.com/gfx-rs/naga/issues/2034 + .specific_failure(Some(wgpu::Backends::VULKAN), None, None, false) .limits(Limits::downlevel_defaults()), |ctx| { shader_input_output_test( diff --git a/wgpu/tests/shader/zero_init_workgroup_mem.rs b/wgpu/tests/shader/zero_init_workgroup_mem.rs index 1e288a08d7..c951697d51 100644 --- a/wgpu/tests/shader/zero_init_workgroup_mem.rs +++ b/wgpu/tests/shader/zero_init_workgroup_mem.rs @@ -16,14 +16,15 @@ fn zero_init_workgroup_mem() { TestParameters::default() .downlevel_flags(DownlevelFlags::COMPUTE_SHADERS) .limits(Limits::downlevel_defaults()) - // remove once we get to https://github.com/gfx-rs/wgpu/issues/3193 or + // remove both of these once we get to https://github.com/gfx-rs/wgpu/issues/3193 or // https://github.com/gfx-rs/wgpu/issues/3160 .specific_failure( Some(Backends::DX12), Some(5140), Some("Microsoft Basic Render Driver"), true, - ), + ) + .specific_failure(Some(Backends::VULKAN), None, Some("swiftshader"), true), zero_init_workgroup_mem_impl, ); }