Wgpu: Feature-less adapter selection

Created on 21 Jul 2019  路  3Comments  路  Source: gfx-rs/wgpu

Instead of exposing the compile time features, we could figure out at run-time which API's are available and provide the adapters to the users that represent different APIs. This would make it easier for users to select the API, also simplify the configuration and launching the apps.

enhancement

Most helpful comment

I've been investing quite a bit in reworking the implementation in such a way that the structures of different backend types can be used together in the same instance, i.e. moving the backend-specific portions outside, wrapping them into enum over backends, then matching where they meet each other ,etc. That allows a single WGPU instance to work with multiple different logical devices.

Reading up on GetProcAddress PR I got a different idea, an insight perhaps into what Google is doing. Instead of trying to match within each function, they probably just have a separate function per backend. Then, each "regular" entry point (of the C API) just extracts the info about the backend from one of the arguments (first argument always?):

fn foo<B: hal::Backend>(...) {...}
pub extern "C"  fn foo(device: DeviceId) {
  match device.get_backend() {
    Vulkan => foo<VulkanBackend>(device),
    Metal => foo<MetalBackend>(device),
    ...
  }
}

if we go this path, we could even encode the backend type in the ID itself! (just 3-4 bits)

So this is where their GetProcAddress comes handy: if the user provides the device, we can return the address of the specialized function for this backend. This means sparing a match on execution.


Let's try to evaluate the pros and cons of this approach. Pros:

  1. It's been very hard to write the code paths agnostic over an enum in Rust, since there are no HKT and this is basically HKT we are trying to implement with the minimal use of macros and other magic. Going the whole-function path means simply that most of the code only cares about a single backend.
  2. Potentially faster execution given the GetProcAddress resolving the backend.

What about the cons:

  1. I have to throw away days of focused effort... :sob:
  2. Potentially bigger binary size?

All 3 comments

Working on this now. This is going to be a long and wild ride...

I've been investing quite a bit in reworking the implementation in such a way that the structures of different backend types can be used together in the same instance, i.e. moving the backend-specific portions outside, wrapping them into enum over backends, then matching where they meet each other ,etc. That allows a single WGPU instance to work with multiple different logical devices.

Reading up on GetProcAddress PR I got a different idea, an insight perhaps into what Google is doing. Instead of trying to match within each function, they probably just have a separate function per backend. Then, each "regular" entry point (of the C API) just extracts the info about the backend from one of the arguments (first argument always?):

fn foo<B: hal::Backend>(...) {...}
pub extern "C"  fn foo(device: DeviceId) {
  match device.get_backend() {
    Vulkan => foo<VulkanBackend>(device),
    Metal => foo<MetalBackend>(device),
    ...
  }
}

if we go this path, we could even encode the backend type in the ID itself! (just 3-4 bits)

So this is where their GetProcAddress comes handy: if the user provides the device, we can return the address of the specialized function for this backend. This means sparing a match on execution.


Let's try to evaluate the pros and cons of this approach. Pros:

  1. It's been very hard to write the code paths agnostic over an enum in Rust, since there are no HKT and this is basically HKT we are trying to implement with the minimal use of macros and other magic. Going the whole-function path means simply that most of the code only cares about a single backend.
  2. Potentially faster execution given the GetProcAddress resolving the backend.

What about the cons:

  1. I have to throw away days of focused effort... :sob:
  2. Potentially bigger binary size?

Reading up on GetProcAddress PR I got a different idea, an insight perhaps into what Google is doing.

Actually for now and the foreseeable future all of WebGPU's calls will first go through the Dawn frontend and then dynamic dispatch to the correct backend (using a C++ vtable). The extra cost of dynamic dispatch is probably insignificant because hot functions used in command recording are pure frontend in our implementation (since we replay command buffers at submit time).

This is way we don't care as much for about the WGPUDevice argument for WGPUGetProcAddress. WGPUGetProcAddress will still be needed for extensions a la Vulkan or OpenGL though.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

zicklag picture zicklag  路  84Comments

cwfitzgerald picture cwfitzgerald  路  20Comments

FlorianUekermann picture FlorianUekermann  路  18Comments

z2oh picture z2oh  路  13Comments

m4b picture m4b  路  14Comments