Skip to content

Use callback for request_adapter #375

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

Merged
merged 2 commits into from
Nov 8, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 27 additions & 1 deletion examples/compute/main.c
Original file line number Diff line number Diff line change
@@ -12,6 +12,26 @@
#define BINDINGS_LENGTH (1)
#define BIND_GROUP_LAYOUTS_LENGTH (1)

void request_adapter_callback(WGPUAdapterId const *received, void *userdata) {
WGPUAdapterId *id = (WGPUAdapterId*) userdata;
*id = *received;
}

void read_buffer_map(
WGPUBufferMapAsyncStatus status,
const uint8_t *data,
uint8_t *userdata) {
(void)userdata;
if (status == WGPUBufferMapAsyncStatus_Success) {
uint32_t *times = (uint32_t *) data;
printf("Times: [%d, %d, %d, %d]\n",
times[0],
times[1],
times[2],
times[3]);
}
}

int main(
int argc,
char *argv[]) {
@@ -32,7 +52,13 @@ int main(

uint32_t numbers_length = size / sizeof(uint32_t);

WGPUAdapterId adapter = wgpu_request_adapter(NULL);
WGPUAdapterId adapter = { 0 };
wgpu_request_adapter_async(
NULL,
request_adapter_callback,
(void *) &adapter
);

WGPUDeviceId device = wgpu_adapter_request_device(adapter, NULL);

uint8_t *staging_memory;
15 changes: 0 additions & 15 deletions examples/framework.c
Original file line number Diff line number Diff line change
@@ -23,18 +23,3 @@ WGPUU32Array read_file(const char *name) {
.length = length / 4,
};
}

void read_buffer_map(
WGPUBufferMapAsyncStatus status,
const uint8_t *data,
uint8_t *userdata) {
(void)userdata;
if (status == WGPUBufferMapAsyncStatus_Success) {
uint32_t *times = (uint32_t *) data;
printf("Times: [%d, %d, %d, %d]\n",
times[0],
times[1],
times[2],
times[3]);
}
}
13 changes: 11 additions & 2 deletions examples/triangle/main.c
Original file line number Diff line number Diff line change
@@ -32,12 +32,21 @@
#define RENDER_PASS_ATTACHMENTS_LENGTH (1)
#define BIND_GROUP_LAYOUTS_LENGTH (1)

void request_adapter_callback(WGPUAdapterId const *received, void *userdata) {
WGPUAdapterId *id = (WGPUAdapterId*) userdata;
*id = *received;
}

int main() {
WGPUAdapterId adapter = wgpu_request_adapter(
WGPUAdapterId adapter = { 0 };
wgpu_request_adapter_async(
&(WGPURequestAdapterOptions){
.power_preference = WGPUPowerPreference_LowPower,
.backends = 2 | 4 | 8,
});
},
request_adapter_callback,
(void *) &adapter
);

WGPUDeviceId device = wgpu_adapter_request_device(adapter,
&(WGPUDeviceDescriptor){
6 changes: 5 additions & 1 deletion ffi/wgpu.h
Original file line number Diff line number Diff line change
@@ -651,6 +651,8 @@ typedef struct {
WGPUBackendBit backends;
} WGPURequestAdapterOptions;

typedef void (*WGPURequestAdapterCallback)(const WGPUAdapterId *adapter, void *userdata);

typedef struct {
WGPUTextureViewId view_id;
} WGPUSwapChainOutput;
@@ -972,7 +974,9 @@ void wgpu_render_pass_set_viewport(WGPURenderPassId pass_id,
#endif

#if defined(WGPU_LOCAL)
WGPUAdapterId wgpu_request_adapter(const WGPURequestAdapterOptions *desc);
void wgpu_request_adapter_async(const WGPURequestAdapterOptions *desc,
WGPURequestAdapterCallback callback,
void *userdata);
#endif

#if defined(WGPU_LOCAL)
48 changes: 37 additions & 11 deletions wgpu-native/src/instance.rs
Original file line number Diff line number Diff line change
@@ -26,6 +26,7 @@ use hal::{self, adapter::PhysicalDevice as _, queue::QueueFamily as _, Instance
#[cfg(feature = "local")]
use std::marker::PhantomData;

use std::ffi::c_void;

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

pub fn request_adapter(
pub type RequestAdapterCallback =
extern "C" fn(adapter: *const AdapterId, userdata: *mut c_void);
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I noticed we use *mut u8 for userdata in buffer mapping, but maybe we should consider using *mut c_void like we do here. For example, we expect userdata to generally be a user-provided type anyway (not necessarily a byte array), so is there any benefit from requiring *mut u8?

Copy link
Member

Choose a reason for hiding this comment

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

yes, I agree, *mut void seems more appropriate. We might need to file a PR to upstream webgpu header


pub fn request_adapter_async(
global: &Global,
desc: &RequestAdapterOptions,
input_ids: &[Input<AdapterId>],
callback: RequestAdapterCallback,
userdata: *mut c_void,
) {
let adapter = pick_adapter(global, desc, input_ids);
callback(adapter.as_ref().map_or(&AdapterId::ERROR, |x| x as *const _), userdata);
}

fn pick_adapter(
global: &Global,
desc: &RequestAdapterOptions,
input_ids: &[Input<AdapterId>],
@@ -320,10 +335,6 @@ pub fn request_adapter(
None
}
};
#[cfg(not(feature = "local"))]
let pick = |_output, input_maybe| input_maybe;
#[cfg(feature = "local")]
let pick = |output, _input_maybe| Some(output);

let id_vulkan = find_input(Backend::Vulkan);
let id_metal = find_input(Backend::Metal);
@@ -397,6 +408,16 @@ pub fn request_adapter(
PowerPreference::LowPower => integrated.or(other).or(discrete).or(virt),
PowerPreference::HighPerformance => discrete.or(other).or(integrated).or(virt),
};

#[allow(unused_variables)]
let local_or_remote_id = |local_id, remote_id| {
#[cfg(not(feature = "local"))]
let id = remote_id;
#[cfg(feature = "local")]
let id = Some(local_id);
id
};

let mut token = Token::root();

let mut selected = preferred_gpu.unwrap_or(0);
@@ -415,7 +436,7 @@ pub fn request_adapter(
adapter,
&mut token,
);
return pick(id_out, id_vulkan);
return local_or_remote_id(id_out, id_vulkan);
}
selected -= adapters_vk.len();
}
@@ -431,7 +452,7 @@ pub fn request_adapter(
adapter,
&mut token,
);
return pick(id_out, id_metal);
return local_or_remote_id(id_out, id_metal);
}
selected -= adapters_mtl.len();
}
@@ -447,7 +468,7 @@ pub fn request_adapter(
adapter,
&mut token,
);
return pick(id_out, id_dx12);
return local_or_remote_id(id_out, id_dx12);
}
selected -= adapters_dx12.len();
if selected < adapters_dx11.len() {
@@ -460,18 +481,23 @@ pub fn request_adapter(
adapter,
&mut token,
);
return pick(id_out, id_dx11);
return local_or_remote_id(id_out, id_dx11);
}
selected -= adapters_dx11.len();
}

let _ = (selected, id_vulkan, id_metal, id_dx12, id_dx11);
unreachable!()
}

#[cfg(feature = "local")]
#[no_mangle]
pub extern "C" fn wgpu_request_adapter(desc: Option<&RequestAdapterOptions>) -> AdapterId {
request_adapter(&*GLOBAL, &desc.cloned().unwrap_or_default(), &[]).unwrap()
pub extern "C" fn wgpu_request_adapter_async(
desc: Option<&RequestAdapterOptions>,
callback: RequestAdapterCallback,
userdata: *mut c_void,
) {
request_adapter_async(&*GLOBAL, &desc.cloned().unwrap_or_default(), &[], callback, userdata);
}

pub fn adapter_request_device<B: GfxBackend>(
19 changes: 16 additions & 3 deletions wgpu-remote/src/server.rs
Original file line number Diff line number Diff line change
@@ -28,10 +28,23 @@ pub extern "C" fn wgpu_server_instance_request_adapter(
ids: *const wgn::AdapterId,
id_length: usize,
) -> i8 {
extern "C" fn request_adapter_callback(
data: *const wgn::AdapterId,
user_data: *mut std::ffi::c_void,
) {
unsafe {
*(user_data as *mut wgn::AdapterId) = *data;
}
}

let ids = unsafe { slice::from_raw_parts(ids, id_length) };
match wgn::request_adapter(global, desc, ids) {
Some(id) => ids.iter().position(|&i| i == id).unwrap() as i8,
None => -1,
let mut adapter_id: wgn::AdapterId = wgn::AdapterId::ERROR;
let adapter_id_ref = &mut adapter_id;
wgn::request_adapter_async(global, desc, ids, request_adapter_callback, adapter_id_ref as *mut _ as *mut std::ffi::c_void);
if adapter_id == wgn::AdapterId::ERROR {
-1
} else {
ids.iter().position(|&i| i == adapter_id).unwrap() as i8
}
}