Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make wgpu_hal::api::Empty into a usable Noop backend for testing. #7063

Merged
merged 4 commits into from
Feb 13, 2025

Conversation

kpreid
Copy link
Contributor

@kpreid kpreid commented Feb 6, 2025

Connections
Prototype implementation of #5236.

Description
This allows users to create a nonfunctional wgpu instance by setting options to use the Noop backend (formerly Empty), which allows creating resources and issuing commands (that will never run) without having any actual GPU or other device available. This is intended to be used in unit tests for code which manages wgpuresources. It does so by exposing a safe means to createwgpu_hal::api::Empty, and by tweaking the behavior of Empty` slightly so that it allows more things to succeed.

Resolved questions: This is a draft because I am unsure about many elements and want to get feedback before I put more work into it. Particularly:

  • It seems to me not ideal that this depends on wgpu-core — but Empty was already there. I was originally planning to write a wgpu backend instead, but this seemed like a simpler place to start. If we like the direction this goes, then perhaps it would be even better to have a wgpu backend so there is no need for a feature and no need to build wgpu-core (e.g. for an application which uses WebGPU only).
  • To get it to run, I had to add a Backends bit for Empty, which means that Backends::all() includes Empty. But applications which ask for Backends::all() will then (semantically if not in practice) be saying they will accept a nonfunctional implementation. It is now necessary to specify a special option.
  • Are there any caveats to using Empty this way?
    • It seems to be only used for some tests, so perhaps exposing it is incorrect/unsound in some way.
    • Will making more of its operations succeed rather than fail break any of its existing usage? No.
  • I named the public feature “noop” instead of “empty”, but probably there should be consistent naming — I just don't think Empty is a good public name. Renamed all to Noop.
  • Ideally the noop device would accept all commands, but become “lost” immediately upon any action that would be able to view the output (i.e. mapping a buffer for read). I don’t yet know how to do this precisely. The noop device now allows buffer manipulation but nothing else.

Testing
Added a test function demonstrating minimum functionality. No manual testing or specific hardware required to test! That's the whole point!

Checklist

  • Run cargo fmt.
  • Run taplo format.
  • Run cargo clippy. If applicable, add:
    • --target wasm32-unknown-unknown
  • Run cargo xtask test to run tests.
  • Add change to CHANGELOG.md. See simple instructions inside file.

@sagudev
Copy link
Contributor

sagudev commented Feb 6, 2025

  • It seems to me not ideal that this depends on wgpu-core — but Empty was already there. I was originally planning to write a wgpu backend instead, but this seemed like a simpler place to start. If we like the direction this goes, then perhaps it would be even better to have a wgpu backend so there is no need for a feature and no need to build wgpu-core (e.g. for an application which uses WebGPU only).

Most of validation is in wgpu-core anyway, so I am not sure how much useful would empty wgpu backend be.

@kpreid
Copy link
Contributor Author

kpreid commented Feb 6, 2025

Most of validation is in wgpu-core anyway, so I am not sure how much useful would empty wgpu backend be.

Thank you for that clarification; I wasn’t sure if that was true, and it is quite important for some testing purposes that validation is performed.

Copy link
Member

@cwfitzgerald cwfitzgerald left a comment

Choose a reason for hiding this comment

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

This is so cool and I've been wanting to have this for a very long time!

I think we can handle the Backends bitflag like this:

  • We include the Empty backend as in this PR.
  • We add a EmptyBackendOptions which has a single boolean enable, which defaults false.

This way the empty backend is "enabled", but doesn't actually return any adapter until the enable boolean is set.

Though now thinking about it, if this is feature gated anyway, does it matter? Maybe it does because of feature unification?

wgpu-hal/src/empty.rs Outdated Show resolved Hide resolved
wgpu-types/src/lib.rs Outdated Show resolved Hide resolved
wgpu/Cargo.toml Outdated Show resolved Hide resolved
wgpu/Cargo.toml Outdated Show resolved Hide resolved
@cwfitzgerald
Copy link
Member

cwfitzgerald commented Feb 11, 2025

It seems to be only used for some tests, so perhaps exposing it is incorrect/unsound in some way.

We just never wired it up properly.

Will making more of its operations succeed rather than fail break any of its existing usage?

I'm unaware of any, and if it's there, we can break it, this wasn't a feature we advertised.

I named the public feature “noop” instead of “empty”, but probably there should be consistent naming — I just don't think Empty is a good public name.

Noop backend is a pretty good name, I think changing is is a-okay

Ideally the noop device would accept all commands, but become “lost” immediately upon any action that would be able to view the output (i.e. mapping a buffer for read). I don’t yet know how to do this precisely.

I wouldn't worry about it, I think just always returning zeros (or whatever data you wrote it) for mappings is okay.

@kpreid kpreid force-pushed the noop-via-hal branch 3 times, most recently from d9e803d to 22572ce Compare February 12, 2025 01:04
@kpreid
Copy link
Contributor Author

kpreid commented Feb 12, 2025

Though now thinking about it, if this is feature gated anyway, does it matter? Maybe it does because of feature unification?

Indeed, we need to not return a noop backend just because some other package, which is either uncareful about minimal features or has a non-test-only use case for it, has enabled the feature.

Noop backend is a pretty good name, I think changing is is a-okay

Done.

I wouldn't worry about it, I think just always returning zeros (or whatever data you wrote it) for mappings is okay.

I've now added support for copying and reading buffers, because that seemed likely to be valuable — it will allow full testing of any module/middleware whose job is “put things in a buffer in the proper layout” — and because having it helps prove that the buffer mapping code I need anyway is actually correct; the previous iteration of this PR was actually unsound.

Texture support would also be very useful, but significantly harder and so I didn't include it in this PR.

@kpreid kpreid marked this pull request as ready for review February 12, 2025 01:42
@kpreid kpreid requested review from crowlKats and a team as code owners February 12, 2025 01:42
@kpreid kpreid changed the title Add Instance::noop() to create a guaranteed nonfunctional instance for testing. Make wgpu_hal::api::Empty into a usable Noop backend for testing. Feb 12, 2025
Copy link
Member

@cwfitzgerald cwfitzgerald left a comment

Choose a reason for hiding this comment

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

Incredible work as always!

Some comments, but all minor.

tests/Cargo.toml Show resolved Hide resolved
tests/src/init.rs Outdated Show resolved Hide resolved
wgpu-core/Cargo.toml Outdated Show resolved Hide resolved
wgpu-hal/src/noop/buffer.rs Outdated Show resolved Hide resolved
wgpu-hal/src/noop/mod.rs Outdated Show resolved Hide resolved
@cwfitzgerald
Copy link
Member

This just needs conflicts fixed then we're good to go.

@cwfitzgerald cwfitzgerald enabled auto-merge (squash) February 13, 2025 02:21
This is in preparation for making it a more substantial test stub,
able to execute nontrivial code, and usable from the safe `wgpu` API.
This will allow using it in tests of wgpu resource management code
that does not actually require a backend.

* `enumerate_adapters()` returns an adapter instead of failing.
* `open()` returns a device instead of failing.
* `create_buffer()` allocates actual memory.
* `map_buffer()` actually provides access to that memory.
* `clear_buffer()` actually clears the buffer.
* `copy_buffer_to_buffer()` actually copies data.
* Fences actually work (trivially, because all operations are
  synchronous).

Future work could include implementing texture copies,
timestamp queries, and the clearing part of render passes.
auto-merge was automatically disabled February 13, 2025 02:37

Head branch was pushed to by a user without write access

@kpreid
Copy link
Contributor Author

kpreid commented Feb 13, 2025

Whoops, I rebased but without having fetched today. Should be good to merge now.

@kpreid
Copy link
Contributor Author

kpreid commented Feb 13, 2025

@cwfitzgerald My pushing disabled auto-merge so you're going to have to hit the button again.

…also I see you're planning to squash this, so I had better pre-squash it so the commit messages aren't lost. Grumble grumble.

@cwfitzgerald
Copy link
Member

I can rebase, I just wasn't sure if they were standalone

@kpreid
Copy link
Contributor Author

kpreid commented Feb 13, 2025

All the commits I previously pushed were self-contained and (should) pass tests. Shall I restore them? Right now I have squashed to one commit, but I don't prefer that.

@kpreid
Copy link
Contributor Author

kpreid commented Feb 13, 2025

I have now re-pushed the version with incremental, informative commits.

@cwfitzgerald
Copy link
Member

Yeah just let us know when we can rebase and merge, and we will. We're going to add this to the pull request template shortly.

@cwfitzgerald cwfitzgerald merged commit 0f111cb into gfx-rs:trunk Feb 13, 2025
65 checks passed
@kpreid kpreid deleted the noop-via-hal branch February 13, 2025 03:47
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.

3 participants