Skip to content

Allow overriding Instance::new#9606

Open
inner-daemons wants to merge 2 commits into
gfx-rs:trunkfrom
inner-daemons:custom-backend-override
Open

Allow overriding Instance::new#9606
inner-daemons wants to merge 2 commits into
gfx-rs:trunkfrom
inner-daemons:custom-backend-override

Conversation

@inner-daemons
Copy link
Copy Markdown
Collaborator

Connections
Closes #9595
Split out from #9570.

Description
This is mainly useful for experimentation. It lets you change the behavior of Instance::new, though users of Instance::new can still opt-out of this change.

It lets you override the behavior of Instance::new to return a custom instance (one that doesn't necessarily use webgpu or wgpu-core).

My use case is for running wgpu's tests on an external backend (see gfx-rs/wgpu-native#594) but it can also be used to force other libraries or apps to use your own backend, if there isn't a more convenient way.

This shouldn't be a security issue because A. it only affects wgpu, so deno and Firefox are unaffected, and B. it requires a specific function to be called before the instance is created.

Testing
Tested in gfx-rs/wgpu-native#594. That PR has a test which ensures that the custom instance is actually used.

Squash or Rebase?
Squash

Checklist

  • I self-reviewed and fully understand this PR.
  • WebGPU implementations built with wgpu may be affected behaviorally.
  • Validation and feature gates are in place to confine behavioral changes.
  • Tests demonstrate the validation and altered logic works.
  • CHANGELOG.md entries for the user-facing effects of this change are present.
  • The PR is minimal, and doesn't make sense to land as multiple PRs.
  • Commits are logically scoped and individually reviewable.
  • The PR description has enough context to understand the motivation and solution implemented.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an opt-in mechanism (gated on the custom cfg) to override Instance::new with a user-registered factory function, primarily so a custom backend (e.g. wgpu-native) can intercept instance creation in third-party code and the wgpu test suite. A new BackendOptions::skip_custom_backend_library flag lets a specific call site bypass the override, and wgpu-info gains a regression test that compares a custom-backend report against the wgpu-core report.

Changes:

  • New global set_instance_factory + INSTANCE_FACTORY atomic in wgpu/src/api/instance.rs, consulted from Instance::new unless skip_custom_backend_library is set.
  • New BackendOptions::skip_custom_backend_library field plus WGPU_NO_CUSTOM_BACKEND env var handling in wgpu-types, with knock-on updates in deno_webgpu, tests/src/init.rs, and wgpu-info.
  • New custom_backend_matches_wgpu_core test in wgpu-info/src/tests.rs and small robustness changes in tests/tests/wgpu-gpu/{device,mem_leaks}.rs so generate_report returning None doesn't fail.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
wgpu/src/api/instance.rs Adds set_instance_factory and dispatch through it from Instance::new.
wgpu-types/src/backend.rs Adds skip_custom_backend_library field with env-var handling in from_env_or_default (but not with_env).
wgpu-info/src/report.rs GpuReport::generate now takes a skip_custom flag.
wgpu-info/src/cli.rs Updates CLI caller to pass false.
wgpu-info/src/tests.rs New test comparing custom-backend vs wgpu-core reports.
tests/src/init.rs Explicitly initializes the new field to false.
tests/tests/wgpu-gpu/device.rs Tolerates generate_report returning None for custom backends.
tests/tests/wgpu-gpu/mem_leaks.rs Same: early-return when no report is available.
deno_webgpu/lib.rs Sets skip_custom_backend_library: true (deno does not want overrides).
CHANGELOG.md Documents the new feature.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread wgpu-types/src/backend.rs Outdated
Comment thread wgpu-types/src/backend.rs
Comment on lines +218 to +222
/// If false and the `custom` feature is enabled for wgpu, and if an override
/// instance factory was setup, wgpu will return a custom instance created from
/// that factory.
///
/// Noop on wgpu-core.
Comment thread wgpu/src/api/instance.rs
Comment on lines +7 to +26
static INSTANCE_FACTORY: core::sync::atomic::AtomicUsize = core::sync::atomic::AtomicUsize::new(0);

/// Register a factory that can intercept [`Instance::new`] for custom backends.
///
/// The factory receives the [`InstanceDescriptor`] and returns `Ok(Instance)` to
/// take ownership of the request, or `Err(desc)` to fall through to the built-in backend.
///
/// Only the first call takes effect; subsequent calls are ignored.
///
/// This can be safely called from a constructor.
#[cfg(custom)]
pub fn set_instance_factory(f: fn(InstanceDescriptor) -> Result<Instance, InstanceDescriptor>) {
// 0 is the sentinel for "not set"; fn pointers are never null.
let _ = INSTANCE_FACTORY.compare_exchange(
0,
f as usize,
core::sync::atomic::Ordering::Release,
core::sync::atomic::Ordering::Relaxed,
);
}
Comment thread wgpu/src/api/instance.rs Outdated
Comment thread wgpu-info/src/tests.rs
Comment on lines +6 to +16
let dir = std::env::temp_dir();
let a_path = dir.join(format!("wgpu-info-{label}-custom.json"));
let b_path = dir.join(format!("wgpu-info-{label}-core.json"));
fs::write(&a_path, a).unwrap();
fs::write(&b_path, b).unwrap();
let out = Command::new("diff")
.args(["-u", "--label", "with-custom", "--label", "without-custom"])
.args([&a_path, &b_path])
.output()
.unwrap();
String::from_utf8(out.stdout).unwrap()
Comment thread wgpu-types/src/backend.rs Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Ability to override instance factory

2 participants