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

API to enumerate adapters #233

Open
kainino0x opened this issue Oct 13, 2023 · 3 comments
Open

API to enumerate adapters #233

kainino0x opened this issue Oct 13, 2023 · 3 comments
Labels
non-breaking Does not require a breaking change (that would block V1.0)

Comments

@kainino0x
Copy link
Collaborator

kainino0x commented Oct 13, 2023

Raised by @rajveermalviya.
In WASM this can always return 0 or 1 adapters. In native this could return more.

meeting notes:

  • AE: We have something called EnumerateAdapters on the instance that returns a std::vector
  • RM: Interested in having an API for this
  • CF: We also have something but it's not supported in web because it’s sync and can’t be implemented over requestAdapter (in webgpu backend. webgl backend supports it)
  • (...)
  • CF: On D3D12 do you have to create a device to create an adapter?
  • AE: Yes, and it’s a problem. Wanted to do some metrics collection about whether the system supports WebGPU. But turns out if I try to EnumerateAdapters then sometimes I get hangs because it gets stuck loading the device driver somewhere.
  • (...)
  • LK: Lazily initialize those adapters? Pretend there’s an adapter and then lazily initialize it when you try to look at it.
  • CF: Possible but GetLimits or GetFeatures would initialize it. GetInfo might work but that’s probably too limiting. Mainly thinking about this in the context of tests where you want to use the same adapter every time, or the same one ANGLE is using, etc.
  • AE: Same problem in our tests.
@kainino0x kainino0x added the non-breaking Does not require a breaking change (that would block V1.0) label Oct 13, 2023
@austinEng
Copy link
Collaborator

austinEng commented Oct 23, 2023

Some ideas which could be combined or used separately

One-by-one enumeration

EnumerateStatus EnumerateAdapters(const wgpu::RequestAdapterOptions& options, uint32_t index, wgpu::Adapter* adapterOut)

Returns EnumerateStatus::NoMoreAdapters if there are no more.

This lets the application enumerate things one-by-one so it could stop enumerating when it finds an adapter it is happy with. This way you don't need to make ALL the adapters on ALL the GPUs.

One interesting bit here is that the implementation needs to maintain some kind of stable ordering of the adapters to use indices in this way.
An alternative may be to return a sort of iterator-like object.

Add some intermediate object

Add an intermediate object that you get before the adapter. It will only tell you more limited information like vendorId/deviceId. But not things like driver description or name (because we want to avoid loading the driver). Maybe we can expose everything that the Adapter has here, but it would be behind methods like RequestSupportedLimits or RequestSupportedFeatures so it's more clear this could be expensive-ish. The implementation would request lazily.
From this intermediate object, you can get a real wgpu::Adapter.
The main benefit of an intermediate is that you can find the vendorId / backend that you want, and then call Enumerate/RequestAdapter with options for just that vendor / backedType.

Make all the adapter information a "request"

RequestLimits instead of GetLimits, RequestFeatures instead of EnumerateFeatures, RequestProperties instead of GetProperties, etc.
The implementation requests these things lazily and its more clear to the application that's what's happening.
May need to split wgpu::Adapter properties into the cheap-to-get stuff, and the more-expensive-to-get stuff.

@austinEng austinEng removed the non-breaking Does not require a breaking change (that would block V1.0) label Oct 23, 2023
@austinEng
Copy link
Collaborator

Removing non-breaking label because some of these things would be breaking changes.

@kainino0x kainino0x added the !discuss Needs discussion (at meeting or online) label Oct 24, 2023
@kainino0x kainino0x added non-breaking Does not require a breaking change (that would block V1.0) and removed !discuss Needs discussion (at meeting or online) labels Nov 2, 2023
@kainino0x
Copy link
Collaborator Author

webgpu.h meeting (nov 2):

  • AE: Main problem is it’s expensive to enumerate all the adapters. Have to go make a device to check the capabilities. Options I thought of:
    • 1. Make enumerate give you one adapter at a time. Need to make indices stable.
    • 2. Yet another object which is “Adapter but with less information on it”
    • 3. Make GetProperties/GetFeatures/etc to “Request*” to make it clearer that it’s expensive/lazy
      • CF: Prefer not this
  • CF: In tests we need to select particular adapters for things like benchmarks. A benchmark of my system (which has 7 adapters - 3 D3D12, 3 Vulkan, 1 OpenGL), was 0.8 seconds. Faster than expected. Slower if tests run in parallel (1.6s). Interestingly Vulkan was the slowest. But decided not to do anything here.
  • CF: Most transparent option would be 2. Similar to what D3D12 allows. For Vulkan we have to enumerate anyway. Same for Metal.
  • CF: Another different solution: if you know which adapter you want, e.g. Chrome or Firefox to match D3D11. If we pass that to requestAdapter then we can internally try to find that adapter.
    • AE: We do have that in Dawn. RequestAdapterOptionsLUID
  • AE: We try to enumerate adapters to determine if a system has WebGPU support for telemetry. Sometimes it takes so long it hits the GPU process watchdog timer (~30s).
    • Rafael said this will load every driver DLL and page faults + loading from disk probably cause this slowness.
  • CF: Know person who works on Vulkan loader so will ask them if there’s a way to do this more efficiently
  • CF: Games for example want to select the same adapter you used before, then if it’s not available, choose something else, based on whether it’s integrated or not? Which requires creating the device?
  • AE: DXCore provides it without creating the device
  • We can do this non-breakingly later. Keep considering how to do this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
non-breaking Does not require a breaking change (that would block V1.0)
Projects
None yet
Development

No branches or pull requests

2 participants