mirror of
https://github.com/gfx-rs/wgpu.git
synced 2025-12-08 21:26:17 +00:00
[cts_runner] Print uncaptured errors to stderr (#8263)
This is useful when running test snippets. Update READMEs including to mention how to do that.
This commit is contained in:
parent
f935660d54
commit
cb13fbe4a7
14
Cargo.lock
generated
14
Cargo.lock
generated
@ -976,6 +976,7 @@ dependencies = [
|
||||
"deno_webgpu",
|
||||
"deno_webidl",
|
||||
"env_logger",
|
||||
"tempfile",
|
||||
"termcolor",
|
||||
"tokio",
|
||||
]
|
||||
@ -3990,6 +3991,19 @@ version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ac9aa371f599d22256307c24a9d748c041e548cbf599f35d890f9d365361790"
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.23.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16"
|
||||
dependencies = [
|
||||
"fastrand",
|
||||
"getrandom 0.3.3",
|
||||
"once_cell",
|
||||
"rustix 1.0.8",
|
||||
"windows-sys 0.61.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.4.1"
|
||||
|
||||
@ -187,6 +187,7 @@ spirv = "0.3"
|
||||
static_assertions = "1.1"
|
||||
strum = { version = "0.27.1", default-features = false, features = ["derive"] }
|
||||
syn = "2.0.98"
|
||||
tempfile = "3"
|
||||
toml = "0.9.0"
|
||||
trybuild = "1"
|
||||
tracy-client = "0.18"
|
||||
|
||||
@ -22,3 +22,6 @@ deno_webidl.workspace = true
|
||||
deno_webgpu.workspace = true
|
||||
tokio = { workspace = true, features = ["full"] }
|
||||
termcolor.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile.workspace = true
|
||||
|
||||
17
cts_runner/README.md
Normal file
17
cts_runner/README.md
Normal file
@ -0,0 +1,17 @@
|
||||
# cts_runner
|
||||
|
||||
This crate contains infrastructure for running the WebGPU conformance tests on
|
||||
Deno's `wgpu`-based implementation of WebGPU.
|
||||
|
||||
Instructions for running the tests via the CTS `xtask` are in the
|
||||
[top-level README](https://github.com/gfx-rs/wgpu/blob/trunk/README.md#webgpu-conformance-test-suite).
|
||||
The file [revision.txt](./revision.txt) specifies the version of the CTS that
|
||||
will be used by default.
|
||||
|
||||
`cts_runner` is somewhat misnamed at this point, in that it is useful for
|
||||
things other than just running the CTS:
|
||||
|
||||
- The [tests](./tests) directory contains a few directed tests for
|
||||
Deno's bindings to `wgpu`.
|
||||
- Standalone JavaScript snippets that use WebGPU can be run
|
||||
with a command like: `cargo run -p cts_runner -- test.js`.
|
||||
19
cts_runner/src/bootstrap.js
vendored
19
cts_runner/src/bootstrap.js
vendored
@ -224,6 +224,25 @@ const windowOrWorkerGlobalScope = {
|
||||
|
||||
windowOrWorkerGlobalScope.console.enumerable = false;
|
||||
|
||||
// Print uncaptured WebGPU errors to stderr. This is useful when running
|
||||
// standalone JavaScript test snippets. It isn't needed for the CTS, because the
|
||||
// CTS uses error scopes. (The CTS also installs its own error handler with
|
||||
// `addEventListener`, so having this here may result in printing duplicate
|
||||
// errors from the CTS in some cases.) Printing uncaptured errors to stderr
|
||||
// isn't desired as built-in behavior in Deno, because the console is reserved
|
||||
// for the application.
|
||||
//
|
||||
// Note that catching an error here _does not_ result in a non-zero exit status.
|
||||
const requestDevice = webgpu.GPUAdapter.prototype.requestDevice;
|
||||
webgpu.GPUAdapter.prototype.requestDevice = function(desc) {
|
||||
return requestDevice.call(this, desc).then((device) => {
|
||||
device.onuncapturederror = (event) => {
|
||||
core.print("cts_runner caught WebGPU error:" + event.error.message, true);
|
||||
};
|
||||
return device;
|
||||
})
|
||||
};
|
||||
|
||||
const mainRuntimeGlobalProperties = {
|
||||
Window: globalInterfaces.windowConstructorDescriptor,
|
||||
window: util.readOnly(globalThis),
|
||||
|
||||
@ -1,5 +0,0 @@
|
||||
const adapter = await navigator.gpu.requestAdapter();
|
||||
|
||||
if (adapter.features.has("mappable-primary-buffers")) {
|
||||
throw new TypeError("Adapter should not report support for wgpu native-only features");
|
||||
}
|
||||
@ -3,12 +3,15 @@
|
||||
// As of June 2025, these tests are not run in CI.
|
||||
|
||||
use std::{
|
||||
fmt::{self, Debug, Display},
|
||||
ffi::OsStr,
|
||||
io::Write,
|
||||
path::PathBuf,
|
||||
process::Command,
|
||||
process::{Command, Output},
|
||||
str,
|
||||
};
|
||||
|
||||
use tempfile::NamedTempFile;
|
||||
|
||||
pub fn target_dir() -> PathBuf {
|
||||
let current_exe = std::env::current_exe().unwrap();
|
||||
let target_dir = current_exe.parent().unwrap().parent().unwrap();
|
||||
@ -24,38 +27,71 @@ pub fn cts_runner_exe_path() -> PathBuf {
|
||||
p
|
||||
}
|
||||
|
||||
pub struct JsError;
|
||||
|
||||
impl Display for JsError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "JavaScript test returned an error")
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for JsError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{self}")
|
||||
}
|
||||
}
|
||||
|
||||
type JsResult = Result<(), JsError>;
|
||||
|
||||
fn exec_js_test(script: &str) -> JsResult {
|
||||
let output = Command::new(cts_runner_exe_path())
|
||||
.arg(script)
|
||||
fn exec_cts_runner(script_file: impl AsRef<OsStr>) -> Output {
|
||||
Command::new(cts_runner_exe_path())
|
||||
.arg(script_file)
|
||||
.output()
|
||||
.unwrap();
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn exec_js_file(script_file: impl AsRef<OsStr>) {
|
||||
let output = exec_cts_runner(script_file);
|
||||
println!("{}", str::from_utf8(&output.stdout).unwrap());
|
||||
eprintln!("{}", str::from_utf8(&output.stderr).unwrap());
|
||||
output.status.success().then_some(()).ok_or(JsError)
|
||||
assert!(output.status.success());
|
||||
}
|
||||
|
||||
fn check_js_stderr(script: &str, expected: &str) {
|
||||
let mut tempfile = NamedTempFile::new().unwrap();
|
||||
tempfile.write_all(script.as_bytes()).unwrap();
|
||||
tempfile.flush().unwrap();
|
||||
let output = exec_cts_runner(tempfile.path());
|
||||
assert!(
|
||||
output.stdout.is_empty(),
|
||||
"unexpected output on stdout: {}",
|
||||
str::from_utf8(&output.stdout).unwrap(),
|
||||
);
|
||||
assert_eq!(str::from_utf8(&output.stderr).unwrap(), expected);
|
||||
assert!(output.status.success());
|
||||
}
|
||||
|
||||
fn exec_js(script: &str) {
|
||||
check_js_stderr(script, "");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hello_compute_example() -> JsResult {
|
||||
exec_js_test("examples/hello-compute.js")
|
||||
fn hello_compute_example() {
|
||||
exec_js_file("examples/hello-compute.js");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn features() -> JsResult {
|
||||
exec_js_test("tests/features.js")
|
||||
fn features() {
|
||||
exec_js(
|
||||
r#"
|
||||
const adapter = await navigator.gpu.requestAdapter();
|
||||
|
||||
if (adapter.features.has("mappable-primary-buffers")) {
|
||||
throw new TypeError("Adapter should not report support for wgpu native-only features");
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn uncaptured_error() {
|
||||
check_js_stderr(
|
||||
r#"
|
||||
const code = `const val: u32 = 1.1;`;
|
||||
|
||||
const adapter = await navigator.gpu.requestAdapter();
|
||||
const device = await adapter.requestDevice();
|
||||
device.createShaderModule({ code })
|
||||
"#,
|
||||
"cts_runner caught WebGPU error:
|
||||
Shader '' parsing error: the type of `val` is expected to be `u32`, but got `{AbstractFloat}`
|
||||
┌─ wgsl:1:7
|
||||
│
|
||||
1 │ const val: u32 = 1.1;
|
||||
│ ^^^ definition of `val`\n\n",
|
||||
);
|
||||
}
|
||||
|
||||
@ -14,13 +14,15 @@ a
|
||||
[wgpu trace](https://github.com/gfx-rs/wgpu/wiki/Debugging-wgpu-Applications#tracing-infrastructure)
|
||||
to the specified directory.
|
||||
|
||||
For testing this op crate will make use of the WebGPU conformance tests suite,
|
||||
running through our WPT runner. This will be used to validate implementation
|
||||
conformance.
|
||||
This op crate is tested primarily by running the
|
||||
[WebGPU conformance test suite](https://github.com/gpuweb/cts) using `wgpu`'s
|
||||
[`cts_runner`](https://github.com/gfx-rs/wgpu/blob/trunk/README.md#webgpu-conformance-test-suite).
|
||||
`cts_runner` also has a few
|
||||
[directed tests](https://github.com/gfx-rs/wgpu/tree/trunk/cts_runner/tests)
|
||||
to fill in missing coverage.
|
||||
|
||||
GitHub CI doesn't run with GPUs, so testing relies on software like DX WARP &
|
||||
Vulkan lavapipe. Currently, only using DX WARP works, so tests are only run on
|
||||
Windows.
|
||||
GPU availability in GitHub CI is limited, so some configurations rely on
|
||||
software like DX WARP & Vulkan lavapipe.
|
||||
|
||||
## Links
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user