Skip to content

Commit fd671d4

Browse files
authored
Use test to generate .gpuinfo file to reduce recompilations (#8660)
1 parent 889055f commit fd671d4

File tree

4 files changed

+73
-45
lines changed

4 files changed

+73
-45
lines changed

.github/workflows/ci.yml

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ env:
3737
RUSTFLAGS: -D warnings
3838
RUSTDOCFLAGS: -D warnings
3939
WASM_BINDGEN_TEST_TIMEOUT: 300 # 5 minutes
40-
CACHE_SUFFIX: d # cache busting
40+
CACHE_SUFFIX: e # cache busting
4141
WGPU_CI: true
4242

4343
# Every time a PR is pushed to, cancel any previous jobs. This
@@ -588,16 +588,6 @@ jobs:
588588
# Delete snapshots so we can ensure there aren't any excess output files.
589589
rm -r naga/tests/out
590590
591-
- name: Run `wgpu-info`
592-
shell: bash
593-
run: |
594-
echo "$PATH"
595-
596-
export RUST_LOG=trace
597-
598-
# This needs to match the command in xtask/tests.rs
599-
cargo --locked llvm-cov --no-cfg-coverage --no-report run --bin wgpu-info -- -vv
600-
601591
- name: Run tests
602592
shell: bash
603593
run: |
@@ -610,13 +600,23 @@ jobs:
610600
run: git add . && git diff --exit-code HEAD naga/tests/out
611601

612602
- uses: actions/upload-artifact@v5
603+
name: Upload comparison images
613604
if: always() # We want artifacts even if the tests fail.
614605
with:
615606
name: comparison-images-${{ matrix.os }}
616607
path: |
617608
**/*-actual.png
618609
**/*-difference.png
619610
611+
# Print GPU configuration so we can see what features were available during the test.
612+
- name: Print GPU configurations
613+
if: always() # We want this information even if the tests fail.
614+
shell: bash
615+
run: |
616+
set -e
617+
618+
cat .gpuconfig
619+
620620
- name: Generate coverage report
621621
id: coverage
622622
shell: bash

wgpu-info/src/main.rs

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,13 @@
1-
#[cfg(not(target_arch = "wasm32"))]
1+
#![cfg_attr(target_arch = "wasm32", no_main)]
2+
#![cfg(not(target_arch = "wasm32"))]
3+
24
mod cli;
3-
#[cfg(not(target_arch = "wasm32"))]
45
mod human;
5-
#[cfg(not(target_arch = "wasm32"))]
66
mod report;
7-
#[cfg(not(target_arch = "wasm32"))]
7+
#[cfg(test)]
8+
mod tests;
89
mod texture;
910

1011
fn main() -> anyhow::Result<()> {
11-
#[cfg(not(target_arch = "wasm32"))]
12-
{
13-
cli::main()?;
14-
}
15-
Ok(())
12+
cli::main()
1613
}

wgpu-info/src/tests.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
use std::{fs::File, io::BufWriter};
2+
3+
const ENV_VAR_SAVE: &str = "WGPU_INFO_SAVE_GPUCONFIG_REPORT";
4+
5+
// We use a test to generate the .gpuconfig file instead of using the cli directly
6+
// as `cargo run --bin wgpu-info` would build a different set of dependencies, causing
7+
// incremental changes to need to rebuild the wgpu stack twice, one for the tests
8+
// and once for the cli binary.
9+
//
10+
// Needs to be kept in sync with the test in xtask/src/test.rs
11+
#[test]
12+
fn generate_gpuconfig_report() {
13+
let report = crate::report::GpuReport::generate();
14+
15+
// If we don't get the env var, just test that we can generate the report, but don't save it
16+
// to avoid a race condition when other tests are reading the file.
17+
if std::env::var(ENV_VAR_SAVE).is_err() {
18+
println!("Set {ENV_VAR_SAVE} to generate a .gpuconfig report using this test");
19+
return;
20+
}
21+
22+
let file = File::create(concat!(env!("CARGO_MANIFEST_DIR"), "/../.gpuconfig")).unwrap();
23+
let buf = BufWriter::new(file);
24+
report.into_json(buf).unwrap();
25+
}

xtask/src/test.rs

Lines changed: 31 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,17 @@ pub fn run_tests(
3131
let mut cargo_args = flatten_args(args, passthrough_args);
3232

3333
// Re-add profile flags that were consumed during argument parsing
34-
if is_release {
35-
cargo_args.insert(0, OsString::from("--release"));
34+
#[expect(clippy::manual_map)] // This is much clearer than using map()
35+
let profile_arg = if is_release {
36+
Some(OsString::from("--release"))
3637
} else if let Some(ref p) = custom_profile {
37-
cargo_args.insert(0, OsString::from(format!("--cargo-profile={p}")));
38+
Some(OsString::from(format!("--cargo-profile={p}")))
39+
} else {
40+
None
41+
};
42+
43+
if let Some(ref profile_arg) = profile_arg {
44+
cargo_args.insert(0, profile_arg.clone());
3845
}
3946

4047
// Retries handled by cargo nextest natively
@@ -50,37 +57,36 @@ pub fn run_tests(
5057
install_warp::install_warp(&shell, &target_dir)?;
5158
}
5259

53-
// These needs to match the command in "run wgpu-info" in `.github/workflows/ci.yml`
54-
let llvm_cov_flags: &[_] = if llvm_cov {
55-
&["llvm-cov", "--no-cfg-coverage", "--no-report"]
56-
} else {
57-
&[]
58-
};
59-
let llvm_cov_nextest_flags: &[_] = if llvm_cov {
60+
let test_suite_run_flags: &[_] = if llvm_cov {
6061
&["llvm-cov", "--no-cfg-coverage", "--no-report", "nextest"]
61-
} else if list {
62-
&["nextest", "list"]
6362
} else {
6463
&["nextest", "run"]
6564
};
6665

6766
log::info!("Generating .gpuconfig file based on gpus on the system");
6867

68+
// We use a test to generate the .gpuconfig file instead of using the cli directly
69+
// as `cargo run --bin wgpu-info` would build a different set of dependencies, causing
70+
// incremental changes to need to rebuild the wgpu stack twice, one for the tests
71+
// and once for the cli binary.
72+
//
73+
// Needs to be kept in sync with the test in wgpu-info/src/tests.rs
6974
shell
7075
.cmd("cargo")
71-
.args(llvm_cov_flags)
72-
.args([
73-
"run",
74-
"--bin",
75-
"wgpu-info",
76-
"--",
77-
"--json",
78-
"-o",
79-
".gpuconfig",
80-
])
76+
.args(test_suite_run_flags)
77+
// Use the same build configuration as the main tests, so that we only build once.
78+
.args(["--benches", "--tests", "--all-features"])
79+
// Use the same cargo profile as the main tests.
80+
.args(profile_arg)
81+
// We need to tell nextest to filter by binary too, so it doesn't try to enumerate
82+
// tests on any of the gpu enabled test binaries, as that will fail due to
83+
// old or missing .gpuconfig files.
84+
.args(["-E", "binary(wgpu-info)", "generate_gpuconfig_report"])
85+
// Turn on the env var for saving the .gpuconfig files
86+
.env("WGPU_INFO_SAVE_GPUCONFIG_REPORT", "1")
8187
.quiet()
8288
.run()
83-
.context("Failed to run wgpu-info to generate .gpuconfig")?;
89+
.context("Failed to run tests to generate .gpuconfig")?;
8490

8591
let gpu_count = shell
8692
.read_file(".gpuconfig")
@@ -99,7 +105,7 @@ pub fn run_tests(
99105
log::info!("Listing tests");
100106
shell
101107
.cmd("cargo")
102-
.args(llvm_cov_nextest_flags)
108+
.args(["nextest", "list"])
103109
.args(["-v", "--benches", "--tests", "--all-features"])
104110
.args(cargo_args)
105111
.run()
@@ -110,7 +116,7 @@ pub fn run_tests(
110116

111117
shell
112118
.cmd("cargo")
113-
.args(llvm_cov_nextest_flags)
119+
.args(test_suite_run_flags)
114120
.args(["--benches", "--tests", "--all-features"])
115121
.args(cargo_args)
116122
.quiet()

0 commit comments

Comments
 (0)