Skip to content

Commit ae64e3a

Browse files
bors[bot]grovesNL
andauthored
Merge #375
375: Use callback for `request_adapter` r=kvark a=grovesNL For now this is mostly a signature change which allows us to start using a callback for `request_adapter`. Once we have an event loop, the callback could be scheduled to make this asynchronous. At that point the examples and server would have to be updated, because they currently rely on the callback running immediately (inline). The reason for this change is that `request_adapter` is supposed to return a `Promise` in JS, so we can represent it with callbacks at the C API, and `Future` in Rust (though we'll probably keep using callbacks initially). I also changed `request_adapter` to provide an adapter with `AdapterId::ERROR` when no adapters are available, so we can add basic error handling to wgpu-rs (gfx-rs/wgpu-rs#117). Co-authored-by: Joshua Groves <[email protected]>
2 parents 951641d + 7f25b8c commit ae64e3a

File tree

6 files changed

+96
-33
lines changed

6 files changed

+96
-33
lines changed

examples/compute/main.c

+27-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,26 @@
1212
#define BINDINGS_LENGTH (1)
1313
#define BIND_GROUP_LAYOUTS_LENGTH (1)
1414

15+
void request_adapter_callback(WGPUAdapterId const *received, void *userdata) {
16+
WGPUAdapterId *id = (WGPUAdapterId*) userdata;
17+
*id = *received;
18+
}
19+
20+
void read_buffer_map(
21+
WGPUBufferMapAsyncStatus status,
22+
const uint8_t *data,
23+
uint8_t *userdata) {
24+
(void)userdata;
25+
if (status == WGPUBufferMapAsyncStatus_Success) {
26+
uint32_t *times = (uint32_t *) data;
27+
printf("Times: [%d, %d, %d, %d]\n",
28+
times[0],
29+
times[1],
30+
times[2],
31+
times[3]);
32+
}
33+
}
34+
1535
int main(
1636
int argc,
1737
char *argv[]) {
@@ -32,7 +52,13 @@ int main(
3252

3353
uint32_t numbers_length = size / sizeof(uint32_t);
3454

35-
WGPUAdapterId adapter = wgpu_request_adapter(NULL);
55+
WGPUAdapterId adapter = { 0 };
56+
wgpu_request_adapter_async(
57+
NULL,
58+
request_adapter_callback,
59+
(void *) &adapter
60+
);
61+
3662
WGPUDeviceId device = wgpu_adapter_request_device(adapter, NULL);
3763

3864
uint8_t *staging_memory;

examples/framework.c

-15
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,3 @@ WGPUU32Array read_file(const char *name) {
2323
.length = length / 4,
2424
};
2525
}
26-
27-
void read_buffer_map(
28-
WGPUBufferMapAsyncStatus status,
29-
const uint8_t *data,
30-
uint8_t *userdata) {
31-
(void)userdata;
32-
if (status == WGPUBufferMapAsyncStatus_Success) {
33-
uint32_t *times = (uint32_t *) data;
34-
printf("Times: [%d, %d, %d, %d]\n",
35-
times[0],
36-
times[1],
37-
times[2],
38-
times[3]);
39-
}
40-
}

examples/triangle/main.c

+11-2
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,21 @@
3232
#define RENDER_PASS_ATTACHMENTS_LENGTH (1)
3333
#define BIND_GROUP_LAYOUTS_LENGTH (1)
3434

35+
void request_adapter_callback(WGPUAdapterId const *received, void *userdata) {
36+
WGPUAdapterId *id = (WGPUAdapterId*) userdata;
37+
*id = *received;
38+
}
39+
3540
int main() {
36-
WGPUAdapterId adapter = wgpu_request_adapter(
41+
WGPUAdapterId adapter = { 0 };
42+
wgpu_request_adapter_async(
3743
&(WGPURequestAdapterOptions){
3844
.power_preference = WGPUPowerPreference_LowPower,
3945
.backends = 2 | 4 | 8,
40-
});
46+
},
47+
request_adapter_callback,
48+
(void *) &adapter
49+
);
4150

4251
WGPUDeviceId device = wgpu_adapter_request_device(adapter,
4352
&(WGPUDeviceDescriptor){

ffi/wgpu.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,8 @@ typedef struct {
651651
WGPUBackendBit backends;
652652
} WGPURequestAdapterOptions;
653653

654+
typedef void (*WGPURequestAdapterCallback)(const WGPUAdapterId *adapter, void *userdata);
655+
654656
typedef struct {
655657
WGPUTextureViewId view_id;
656658
} WGPUSwapChainOutput;
@@ -972,7 +974,9 @@ void wgpu_render_pass_set_viewport(WGPURenderPassId pass_id,
972974
#endif
973975

974976
#if defined(WGPU_LOCAL)
975-
WGPUAdapterId wgpu_request_adapter(const WGPURequestAdapterOptions *desc);
977+
void wgpu_request_adapter_async(const WGPURequestAdapterOptions *desc,
978+
WGPURequestAdapterCallback callback,
979+
void *userdata);
976980
#endif
977981

978982
#if defined(WGPU_LOCAL)

wgpu-native/src/instance.rs

+37-11
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use hal::{self, adapter::PhysicalDevice as _, queue::QueueFamily as _, Instance
2626
#[cfg(feature = "local")]
2727
use std::marker::PhantomData;
2828

29+
use std::ffi::c_void;
2930

3031
#[derive(Debug)]
3132
pub struct Instance {
@@ -301,7 +302,21 @@ pub extern "C" fn wgpu_create_surface_from_windows_hwnd(
301302
))
302303
}
303304

304-
pub fn request_adapter(
305+
pub type RequestAdapterCallback =
306+
extern "C" fn(adapter: *const AdapterId, userdata: *mut c_void);
307+
308+
pub fn request_adapter_async(
309+
global: &Global,
310+
desc: &RequestAdapterOptions,
311+
input_ids: &[Input<AdapterId>],
312+
callback: RequestAdapterCallback,
313+
userdata: *mut c_void,
314+
) {
315+
let adapter = pick_adapter(global, desc, input_ids);
316+
callback(adapter.as_ref().map_or(&AdapterId::ERROR, |x| x as *const _), userdata);
317+
}
318+
319+
fn pick_adapter(
305320
global: &Global,
306321
desc: &RequestAdapterOptions,
307322
input_ids: &[Input<AdapterId>],
@@ -320,10 +335,6 @@ pub fn request_adapter(
320335
None
321336
}
322337
};
323-
#[cfg(not(feature = "local"))]
324-
let pick = |_output, input_maybe| input_maybe;
325-
#[cfg(feature = "local")]
326-
let pick = |output, _input_maybe| Some(output);
327338

328339
let id_vulkan = find_input(Backend::Vulkan);
329340
let id_metal = find_input(Backend::Metal);
@@ -397,6 +408,16 @@ pub fn request_adapter(
397408
PowerPreference::LowPower => integrated.or(other).or(discrete).or(virt),
398409
PowerPreference::HighPerformance => discrete.or(other).or(integrated).or(virt),
399410
};
411+
412+
#[allow(unused_variables)]
413+
let local_or_remote_id = |local_id, remote_id| {
414+
#[cfg(not(feature = "local"))]
415+
let id = remote_id;
416+
#[cfg(feature = "local")]
417+
let id = Some(local_id);
418+
id
419+
};
420+
400421
let mut token = Token::root();
401422

402423
let mut selected = preferred_gpu.unwrap_or(0);
@@ -415,7 +436,7 @@ pub fn request_adapter(
415436
adapter,
416437
&mut token,
417438
);
418-
return pick(id_out, id_vulkan);
439+
return local_or_remote_id(id_out, id_vulkan);
419440
}
420441
selected -= adapters_vk.len();
421442
}
@@ -431,7 +452,7 @@ pub fn request_adapter(
431452
adapter,
432453
&mut token,
433454
);
434-
return pick(id_out, id_metal);
455+
return local_or_remote_id(id_out, id_metal);
435456
}
436457
selected -= adapters_mtl.len();
437458
}
@@ -447,7 +468,7 @@ pub fn request_adapter(
447468
adapter,
448469
&mut token,
449470
);
450-
return pick(id_out, id_dx12);
471+
return local_or_remote_id(id_out, id_dx12);
451472
}
452473
selected -= adapters_dx12.len();
453474
if selected < adapters_dx11.len() {
@@ -460,18 +481,23 @@ pub fn request_adapter(
460481
adapter,
461482
&mut token,
462483
);
463-
return pick(id_out, id_dx11);
484+
return local_or_remote_id(id_out, id_dx11);
464485
}
465486
selected -= adapters_dx11.len();
466487
}
488+
467489
let _ = (selected, id_vulkan, id_metal, id_dx12, id_dx11);
468490
unreachable!()
469491
}
470492

471493
#[cfg(feature = "local")]
472494
#[no_mangle]
473-
pub extern "C" fn wgpu_request_adapter(desc: Option<&RequestAdapterOptions>) -> AdapterId {
474-
request_adapter(&*GLOBAL, &desc.cloned().unwrap_or_default(), &[]).unwrap()
495+
pub extern "C" fn wgpu_request_adapter_async(
496+
desc: Option<&RequestAdapterOptions>,
497+
callback: RequestAdapterCallback,
498+
userdata: *mut c_void,
499+
) {
500+
request_adapter_async(&*GLOBAL, &desc.cloned().unwrap_or_default(), &[], callback, userdata);
475501
}
476502

477503
pub fn adapter_request_device<B: GfxBackend>(

wgpu-remote/src/server.rs

+16-3
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,23 @@ pub extern "C" fn wgpu_server_instance_request_adapter(
2828
ids: *const wgn::AdapterId,
2929
id_length: usize,
3030
) -> i8 {
31+
extern "C" fn request_adapter_callback(
32+
data: *const wgn::AdapterId,
33+
user_data: *mut std::ffi::c_void,
34+
) {
35+
unsafe {
36+
*(user_data as *mut wgn::AdapterId) = *data;
37+
}
38+
}
39+
3140
let ids = unsafe { slice::from_raw_parts(ids, id_length) };
32-
match wgn::request_adapter(global, desc, ids) {
33-
Some(id) => ids.iter().position(|&i| i == id).unwrap() as i8,
34-
None => -1,
41+
let mut adapter_id: wgn::AdapterId = wgn::AdapterId::ERROR;
42+
let adapter_id_ref = &mut adapter_id;
43+
wgn::request_adapter_async(global, desc, ids, request_adapter_callback, adapter_id_ref as *mut _ as *mut std::ffi::c_void);
44+
if adapter_id == wgn::AdapterId::ERROR {
45+
-1
46+
} else {
47+
ids.iter().position(|&i| i == adapter_id).unwrap() as i8
3548
}
3649
}
3750

0 commit comments

Comments
 (0)