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_webgpu",
|
||||||
"deno_webidl",
|
"deno_webidl",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
|
"tempfile",
|
||||||
"termcolor",
|
"termcolor",
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
@ -3990,6 +3991,19 @@ version = "0.1.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1ac9aa371f599d22256307c24a9d748c041e548cbf599f35d890f9d365361790"
|
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]]
|
[[package]]
|
||||||
name = "termcolor"
|
name = "termcolor"
|
||||||
version = "1.4.1"
|
version = "1.4.1"
|
||||||
|
|||||||
@ -187,6 +187,7 @@ spirv = "0.3"
|
|||||||
static_assertions = "1.1"
|
static_assertions = "1.1"
|
||||||
strum = { version = "0.27.1", default-features = false, features = ["derive"] }
|
strum = { version = "0.27.1", default-features = false, features = ["derive"] }
|
||||||
syn = "2.0.98"
|
syn = "2.0.98"
|
||||||
|
tempfile = "3"
|
||||||
toml = "0.9.0"
|
toml = "0.9.0"
|
||||||
trybuild = "1"
|
trybuild = "1"
|
||||||
tracy-client = "0.18"
|
tracy-client = "0.18"
|
||||||
|
|||||||
@ -22,3 +22,6 @@ deno_webidl.workspace = true
|
|||||||
deno_webgpu.workspace = true
|
deno_webgpu.workspace = true
|
||||||
tokio = { workspace = true, features = ["full"] }
|
tokio = { workspace = true, features = ["full"] }
|
||||||
termcolor.workspace = true
|
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;
|
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 = {
|
const mainRuntimeGlobalProperties = {
|
||||||
Window: globalInterfaces.windowConstructorDescriptor,
|
Window: globalInterfaces.windowConstructorDescriptor,
|
||||||
window: util.readOnly(globalThis),
|
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.
|
// As of June 2025, these tests are not run in CI.
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
fmt::{self, Debug, Display},
|
ffi::OsStr,
|
||||||
|
io::Write,
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
process::Command,
|
process::{Command, Output},
|
||||||
str,
|
str,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use tempfile::NamedTempFile;
|
||||||
|
|
||||||
pub fn target_dir() -> PathBuf {
|
pub fn target_dir() -> PathBuf {
|
||||||
let current_exe = std::env::current_exe().unwrap();
|
let current_exe = std::env::current_exe().unwrap();
|
||||||
let target_dir = current_exe.parent().unwrap().parent().unwrap();
|
let target_dir = current_exe.parent().unwrap().parent().unwrap();
|
||||||
@ -24,38 +27,71 @@ pub fn cts_runner_exe_path() -> PathBuf {
|
|||||||
p
|
p
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct JsError;
|
fn exec_cts_runner(script_file: impl AsRef<OsStr>) -> Output {
|
||||||
|
Command::new(cts_runner_exe_path())
|
||||||
impl Display for JsError {
|
.arg(script_file)
|
||||||
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)
|
|
||||||
.output()
|
.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());
|
println!("{}", str::from_utf8(&output.stdout).unwrap());
|
||||||
eprintln!("{}", str::from_utf8(&output.stderr).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]
|
#[test]
|
||||||
fn hello_compute_example() -> JsResult {
|
fn hello_compute_example() {
|
||||||
exec_js_test("examples/hello-compute.js")
|
exec_js_file("examples/hello-compute.js");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn features() -> JsResult {
|
fn features() {
|
||||||
exec_js_test("tests/features.js")
|
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)
|
[wgpu trace](https://github.com/gfx-rs/wgpu/wiki/Debugging-wgpu-Applications#tracing-infrastructure)
|
||||||
to the specified directory.
|
to the specified directory.
|
||||||
|
|
||||||
For testing this op crate will make use of the WebGPU conformance tests suite,
|
This op crate is tested primarily by running the
|
||||||
running through our WPT runner. This will be used to validate implementation
|
[WebGPU conformance test suite](https://github.com/gpuweb/cts) using `wgpu`'s
|
||||||
conformance.
|
[`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 &
|
GPU availability in GitHub CI is limited, so some configurations rely on
|
||||||
Vulkan lavapipe. Currently, only using DX WARP works, so tests are only run on
|
software like DX WARP & Vulkan lavapipe.
|
||||||
Windows.
|
|
||||||
|
|
||||||
## Links
|
## Links
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user