1use crate::GLOBAL;
6
7use core::{gfx_select, hub::Token, id};
8use wgt::{BackendBit, DeviceDescriptor, Limits};
9
10use std::{marker::PhantomData, slice};
11
12#[cfg(target_os = "macos")]
13use objc::{msg_send, runtime::Object, sel, sel_impl};
14
15pub type RequestAdapterCallback =
16 unsafe extern "C" fn(id: Option<id::AdapterId>, userdata: *mut std::ffi::c_void);
17
18pub fn wgpu_create_surface(raw_handle: raw_window_handle::RawWindowHandle) -> id::SurfaceId {
19 use raw_window_handle::RawWindowHandle as Rwh;
20
21 let instance = &GLOBAL.instance;
22 let surface = match raw_handle {
23 #[cfg(target_os = "ios")]
24 Rwh::IOS(h) => core::instance::Surface {
25 #[cfg(feature = "vulkan-portability")]
26 vulkan: None,
27 metal: instance
28 .metal
29 .create_surface_from_uiview(h.ui_view, cfg!(debug_assertions)),
30 },
31 #[cfg(target_os = "macos")]
32 Rwh::MacOS(h) => {
33 let ns_view = if h.ns_view.is_null() {
34 let ns_window = h.ns_window as *mut Object;
35 unsafe { msg_send![ns_window, contentView] }
36 } else {
37 h.ns_view
38 };
39 core::instance::Surface {
40 #[cfg(feature = "vulkan-portability")]
41 vulkan: instance
42 .vulkan
43 .as_ref()
44 .map(|inst| inst.create_surface_from_ns_view(ns_view)),
45 metal: instance
46 .metal
47 .create_surface_from_nsview(ns_view, cfg!(debug_assertions)),
48 }
49 }
50 #[cfg(all(unix, not(target_os = "ios"), not(target_os = "macos")))]
51 Rwh::Xlib(h) => core::instance::Surface {
52 vulkan: instance
53 .vulkan
54 .as_ref()
55 .map(|inst| inst.create_surface_from_xlib(h.display as _, h.window as _)),
56 },
57 #[cfg(all(unix, not(target_os = "ios"), not(target_os = "macos")))]
58 Rwh::Wayland(h) => core::instance::Surface {
59 vulkan: instance
60 .vulkan
61 .as_ref()
62 .map(|inst| inst.create_surface_from_wayland(h.display, h.surface)),
63 },
64 #[cfg(windows)]
65 Rwh::Windows(h) => core::instance::Surface {
66 vulkan: instance
67 .vulkan
68 .as_ref()
69 .map(|inst| inst.create_surface_from_hwnd(std::ptr::null_mut(), h.hwnd)),
70 dx12: instance
71 .dx12
72 .as_ref()
73 .map(|inst| inst.create_surface_from_hwnd(h.hwnd)),
74 dx11: instance.dx11.create_surface_from_hwnd(h.hwnd),
75 },
76 _ => panic!("Unsupported window handle"),
77 };
78
79 let mut token = Token::root();
80 GLOBAL
81 .surfaces
82 .register_identity(PhantomData, surface, &mut token)
83}
84
85#[cfg(all(unix, not(target_os = "ios"), not(target_os = "macos")))]
86#[no_mangle]
87pub extern "C" fn wgpu_create_surface_from_xlib(
88 display: *mut *const std::ffi::c_void,
89 window: libc::c_ulong,
90) -> id::SurfaceId {
91 use raw_window_handle::unix::XlibHandle;
92 wgpu_create_surface(raw_window_handle::RawWindowHandle::Xlib(XlibHandle {
93 window,
94 display: display as *mut _,
95 ..XlibHandle::empty()
96 }))
97}
98
99#[cfg(all(unix, not(target_os = "ios"), not(target_os = "macos")))]
100#[no_mangle]
101pub extern "C" fn wgpu_create_surface_from_wayland(
102 surface: *mut std::ffi::c_void,
103 display: *mut std::ffi::c_void,
104) -> id::SurfaceId {
105 use raw_window_handle::unix::WaylandHandle;
106 wgpu_create_surface(raw_window_handle::RawWindowHandle::Wayland(WaylandHandle {
107 surface,
108 display,
109 ..WaylandHandle::empty()
110 }))
111}
112
113#[cfg(any(target_os = "ios", target_os = "macos"))]
114#[no_mangle]
115pub extern "C" fn wgpu_create_surface_from_metal_layer(
116 layer: *mut std::ffi::c_void,
117) -> id::SurfaceId {
118 let surface = core::instance::Surface {
119 #[cfg(feature = "vulkan-portability")]
120 vulkan: None, metal: GLOBAL
122 .instance
123 .metal
124 .create_surface_from_layer(layer as *mut _, cfg!(debug_assertions)),
125 };
126
127 GLOBAL
128 .surfaces
129 .register_identity(PhantomData, surface, &mut Token::root())
130}
131
132#[cfg(windows)]
133#[no_mangle]
134pub extern "C" fn wgpu_create_surface_from_windows_hwnd(
135 _hinstance: *mut std::ffi::c_void,
136 hwnd: *mut std::ffi::c_void,
137) -> id::SurfaceId {
138 use raw_window_handle::windows::WindowsHandle;
139 wgpu_create_surface(raw_window_handle::RawWindowHandle::Windows(
140 raw_window_handle::windows::WindowsHandle {
141 hwnd,
142 ..WindowsHandle::empty()
143 },
144 ))
145}
146
147pub fn wgpu_enumerate_adapters(mask: BackendBit) -> Vec<id::AdapterId> {
148 GLOBAL.enumerate_adapters(core::instance::AdapterInputs::Mask(mask, || PhantomData))
149}
150
151#[no_mangle]
155pub unsafe extern "C" fn wgpu_request_adapter_async(
156 desc: Option<&core::instance::RequestAdapterOptions>,
157 mask: BackendBit,
158 callback: RequestAdapterCallback,
159 userdata: *mut std::ffi::c_void,
160) {
161 let id = GLOBAL.pick_adapter(
162 &desc.cloned().unwrap_or_default(),
163 core::instance::AdapterInputs::Mask(mask, || PhantomData),
164 );
165 callback(id, userdata);
166}
167
168#[no_mangle]
169pub extern "C" fn wgpu_adapter_request_device(
170 adapter_id: id::AdapterId,
171 desc: Option<&DeviceDescriptor>,
172) -> id::DeviceId {
173 let desc = &desc.cloned().unwrap_or_default();
174 gfx_select!(adapter_id => GLOBAL.adapter_request_device(adapter_id, desc, PhantomData))
175}
176
177pub fn adapter_get_info(adapter_id: id::AdapterId) -> core::instance::AdapterInfo {
178 gfx_select!(adapter_id => GLOBAL.adapter_get_info(adapter_id))
179}
180
181#[no_mangle]
182pub extern "C" fn wgpu_adapter_destroy(adapter_id: id::AdapterId) {
183 gfx_select!(adapter_id => GLOBAL.adapter_destroy(adapter_id))
184}
185
186#[no_mangle]
187pub extern "C" fn wgpu_device_get_limits(_device_id: id::DeviceId, limits: &mut Limits) {
188 *limits = Limits::default(); }
190
191#[no_mangle]
192pub extern "C" fn wgpu_device_create_buffer(
193 device_id: id::DeviceId,
194 desc: &wgt::BufferDescriptor,
195) -> id::BufferId {
196 gfx_select!(device_id => GLOBAL.device_create_buffer(device_id, desc, PhantomData))
197}
198
199#[no_mangle]
204pub unsafe extern "C" fn wgpu_device_create_buffer_mapped(
205 device_id: id::DeviceId,
206 desc: &wgt::BufferDescriptor,
207 mapped_ptr_out: *mut *mut u8,
208) -> id::BufferId {
209 let (id, ptr) =
210 gfx_select!(device_id => GLOBAL.device_create_buffer_mapped(device_id, desc, PhantomData));
211 *mapped_ptr_out = ptr;
212 id
213}
214
215#[no_mangle]
216pub extern "C" fn wgpu_buffer_destroy(buffer_id: id::BufferId) {
217 gfx_select!(buffer_id => GLOBAL.buffer_destroy(buffer_id))
218}
219
220#[no_mangle]
221pub extern "C" fn wgpu_device_create_texture(
222 device_id: id::DeviceId,
223 desc: &wgt::TextureDescriptor,
224) -> id::TextureId {
225 gfx_select!(device_id => GLOBAL.device_create_texture(device_id, desc, PhantomData))
226}
227
228#[no_mangle]
229pub extern "C" fn wgpu_texture_destroy(texture_id: id::TextureId) {
230 gfx_select!(texture_id => GLOBAL.texture_destroy(texture_id))
231}
232
233#[no_mangle]
234pub extern "C" fn wgpu_texture_create_view(
235 texture_id: id::TextureId,
236 desc: Option<&wgt::TextureViewDescriptor>,
237) -> id::TextureViewId {
238 gfx_select!(texture_id => GLOBAL.texture_create_view(texture_id, desc, PhantomData))
239}
240
241#[no_mangle]
242pub extern "C" fn wgpu_texture_view_destroy(texture_view_id: id::TextureViewId) {
243 gfx_select!(texture_view_id => GLOBAL.texture_view_destroy(texture_view_id))
244}
245
246#[no_mangle]
247pub extern "C" fn wgpu_device_create_sampler(
248 device_id: id::DeviceId,
249 desc: &wgt::SamplerDescriptor,
250) -> id::SamplerId {
251 gfx_select!(device_id => GLOBAL.device_create_sampler(device_id, desc, PhantomData))
252}
253
254#[no_mangle]
255pub extern "C" fn wgpu_sampler_destroy(sampler_id: id::SamplerId) {
256 gfx_select!(sampler_id => GLOBAL.sampler_destroy(sampler_id))
257}
258
259#[no_mangle]
260pub extern "C" fn wgpu_device_create_bind_group_layout(
261 device_id: id::DeviceId,
262 desc: &core::binding_model::BindGroupLayoutDescriptor,
263) -> id::BindGroupLayoutId {
264 gfx_select!(device_id => GLOBAL.device_create_bind_group_layout(device_id, desc, PhantomData))
265}
266
267#[no_mangle]
268pub extern "C" fn wgpu_device_create_pipeline_layout(
269 device_id: id::DeviceId,
270 desc: &core::binding_model::PipelineLayoutDescriptor,
271) -> id::PipelineLayoutId {
272 gfx_select!(device_id => GLOBAL.device_create_pipeline_layout(device_id, desc, PhantomData))
273}
274
275#[no_mangle]
276pub extern "C" fn wgpu_device_create_bind_group(
277 device_id: id::DeviceId,
278 desc: &core::binding_model::BindGroupDescriptor,
279) -> id::BindGroupId {
280 gfx_select!(device_id => GLOBAL.device_create_bind_group(device_id, desc, PhantomData))
281}
282
283#[no_mangle]
284pub extern "C" fn wgpu_bind_group_destroy(bind_group_id: id::BindGroupId) {
285 gfx_select!(bind_group_id => GLOBAL.bind_group_destroy(bind_group_id))
286}
287
288#[no_mangle]
289pub extern "C" fn wgpu_device_create_shader_module(
290 device_id: id::DeviceId,
291 desc: &core::pipeline::ShaderModuleDescriptor,
292) -> id::ShaderModuleId {
293 gfx_select!(device_id => GLOBAL.device_create_shader_module(device_id, desc, PhantomData))
294}
295
296#[no_mangle]
297pub extern "C" fn wgpu_device_create_command_encoder(
298 device_id: id::DeviceId,
299 desc: Option<&wgt::CommandEncoderDescriptor>,
300) -> id::CommandEncoderId {
301 let desc = &desc.cloned().unwrap_or_default();
302 gfx_select!(device_id => GLOBAL.device_create_command_encoder(device_id, desc, PhantomData))
303}
304
305#[no_mangle]
306pub extern "C" fn wgpu_command_encoder_destroy(command_encoder_id: id::CommandEncoderId) {
307 gfx_select!(command_encoder_id => GLOBAL.command_encoder_destroy(command_encoder_id))
308}
309
310#[no_mangle]
311pub extern "C" fn wgpu_command_buffer_destroy(command_buffer_id: id::CommandBufferId) {
312 gfx_select!(command_buffer_id => GLOBAL.command_buffer_destroy(command_buffer_id))
313}
314
315#[no_mangle]
316pub extern "C" fn wgpu_device_get_default_queue(device_id: id::DeviceId) -> id::QueueId {
317 device_id
318}
319
320#[no_mangle]
325pub unsafe extern "C" fn wgpu_queue_submit(
326 queue_id: id::QueueId,
327 command_buffers: *const id::CommandBufferId,
328 command_buffers_length: usize,
329) {
330 let command_buffer_ids = slice::from_raw_parts(command_buffers, command_buffers_length);
331 gfx_select!(queue_id => GLOBAL.queue_submit(queue_id, command_buffer_ids))
332}
333
334#[no_mangle]
335pub extern "C" fn wgpu_device_create_render_pipeline(
336 device_id: id::DeviceId,
337 desc: &core::pipeline::RenderPipelineDescriptor,
338) -> id::RenderPipelineId {
339 gfx_select!(device_id => GLOBAL.device_create_render_pipeline(device_id, desc, PhantomData))
340}
341
342#[no_mangle]
343pub extern "C" fn wgpu_device_create_compute_pipeline(
344 device_id: id::DeviceId,
345 desc: &core::pipeline::ComputePipelineDescriptor,
346) -> id::ComputePipelineId {
347 gfx_select!(device_id => GLOBAL.device_create_compute_pipeline(device_id, desc, PhantomData))
348}
349
350#[no_mangle]
351pub extern "C" fn wgpu_device_create_swap_chain(
352 device_id: id::DeviceId,
353 surface_id: id::SurfaceId,
354 desc: &wgt::SwapChainDescriptor,
355) -> id::SwapChainId {
356 gfx_select!(device_id => GLOBAL.device_create_swap_chain(device_id, surface_id, desc))
357}
358
359#[no_mangle]
360pub extern "C" fn wgpu_device_poll(device_id: id::DeviceId, force_wait: bool) {
361 gfx_select!(device_id => GLOBAL.device_poll(device_id, force_wait))
362}
363
364#[no_mangle]
365pub extern "C" fn wgpu_device_destroy(device_id: id::DeviceId) {
366 gfx_select!(device_id => GLOBAL.device_destroy(device_id))
367}
368
369#[no_mangle]
370pub extern "C" fn wgpu_buffer_map_read_async(
371 buffer_id: id::BufferId,
372 start: wgt::BufferAddress,
373 size: wgt::BufferAddress,
374 callback: core::device::BufferMapReadCallback,
375 userdata: *mut u8,
376) {
377 let operation = core::resource::BufferMapOperation::Read { callback, userdata };
378
379 gfx_select!(buffer_id => GLOBAL.buffer_map_async(buffer_id, wgt::BufferUsage::MAP_READ, start .. start + size, operation))
380}
381
382#[no_mangle]
383pub extern "C" fn wgpu_buffer_map_write_async(
384 buffer_id: id::BufferId,
385 start: wgt::BufferAddress,
386 size: wgt::BufferAddress,
387 callback: core::device::BufferMapWriteCallback,
388 userdata: *mut u8,
389) {
390 let operation = core::resource::BufferMapOperation::Write { callback, userdata };
391
392 gfx_select!(buffer_id => GLOBAL.buffer_map_async(buffer_id, wgt::BufferUsage::MAP_WRITE, start .. start + size, operation))
393}
394
395#[no_mangle]
396pub extern "C" fn wgpu_buffer_unmap(buffer_id: id::BufferId) {
397 gfx_select!(buffer_id => GLOBAL.buffer_unmap(buffer_id))
398}
399
400#[no_mangle]
401pub extern "C" fn wgpu_swap_chain_get_next_texture(
402 swap_chain_id: id::SwapChainId,
403) -> core::swap_chain::SwapChainOutput {
404 gfx_select!(swap_chain_id => GLOBAL.swap_chain_get_next_texture(swap_chain_id, PhantomData))
405 .unwrap_or(core::swap_chain::SwapChainOutput { view_id: None })
406}
407
408#[no_mangle]
409pub extern "C" fn wgpu_swap_chain_present(swap_chain_id: id::SwapChainId) {
410 gfx_select!(swap_chain_id => GLOBAL.swap_chain_present(swap_chain_id))
411}