1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 use crate::identity::IdentityRecyclerFactory;
6
7 use wgc::{gfx_select, id};
8
9 use std::slice;
10
11 pub type Global = wgc::hub::Global<IdentityRecyclerFactory>;
12 pub type RawString = *const std::os::raw::c_char;
13
14 #[no_mangle]
wgpu_server_new(factory: IdentityRecyclerFactory) -> *mut Global15 pub extern "C" fn wgpu_server_new(factory: IdentityRecyclerFactory) -> *mut Global {
16 log::info!("Initializing WGPU server");
17 Box::into_raw(Box::new(Global::new("wgpu", factory)))
18 }
19
20 /// # Safety
21 ///
22 /// This function is unsafe because improper use may lead to memory
23 /// problems. For example, a double-free may occur if the function is called
24 /// twice on the same raw pointer.
25 #[no_mangle]
wgpu_server_delete(global: *mut Global)26 pub unsafe extern "C" fn wgpu_server_delete(global: *mut Global) {
27 log::info!("Terminating WGPU server");
28 let _ = Box::from_raw(global);
29 }
30
31 #[no_mangle]
wgpu_server_poll_all_devices(global: &Global, force_wait: bool)32 pub extern "C" fn wgpu_server_poll_all_devices(global: &Global, force_wait: bool) {
33 global.poll_all_devices(force_wait);
34 }
35
36 /// Request an adapter according to the specified options.
37 /// Provide the list of IDs to pick from.
38 ///
39 /// Returns the index in this list, or -1 if unable to pick.
40 ///
41 /// # Safety
42 ///
43 /// This function is unsafe as there is no guarantee that the given pointer is
44 /// valid for `id_length` elements.
45 #[no_mangle]
wgpu_server_instance_request_adapter( global: &Global, desc: &wgc::instance::RequestAdapterOptions, ids: *const id::AdapterId, id_length: usize, ) -> i846 pub unsafe extern "C" fn wgpu_server_instance_request_adapter(
47 global: &Global,
48 desc: &wgc::instance::RequestAdapterOptions,
49 ids: *const id::AdapterId,
50 id_length: usize,
51 ) -> i8 {
52 let ids = slice::from_raw_parts(ids, id_length);
53 match global.pick_adapter(
54 desc,
55 wgc::instance::AdapterInputs::IdSet(ids, |i| i.backend()),
56 ) {
57 Some(id) => ids.iter().position(|&i| i == id).unwrap() as i8,
58 None => -1,
59 }
60 }
61
62 #[no_mangle]
wgpu_server_adapter_request_device( global: &Global, self_id: id::AdapterId, desc: &wgt::DeviceDescriptor, new_id: id::DeviceId, )63 pub unsafe extern "C" fn wgpu_server_adapter_request_device(
64 global: &Global,
65 self_id: id::AdapterId,
66 desc: &wgt::DeviceDescriptor,
67 new_id: id::DeviceId,
68 ) {
69 let trace_string = std::env::var("WGPU_TRACE").ok();
70 let trace_path = trace_string
71 .as_ref()
72 .map(|string| std::path::Path::new(string.as_str()));
73 gfx_select!(self_id => global.adapter_request_device(self_id, desc, trace_path, new_id));
74 }
75
76 #[no_mangle]
wgpu_server_adapter_destroy(global: &Global, adapter_id: id::AdapterId)77 pub extern "C" fn wgpu_server_adapter_destroy(global: &Global, adapter_id: id::AdapterId) {
78 gfx_select!(adapter_id => global.adapter_destroy(adapter_id))
79 }
80
81 #[no_mangle]
wgpu_server_device_destroy(global: &Global, self_id: id::DeviceId)82 pub extern "C" fn wgpu_server_device_destroy(global: &Global, self_id: id::DeviceId) {
83 gfx_select!(self_id => global.device_destroy(self_id))
84 }
85
86 #[no_mangle]
wgpu_server_device_create_buffer( global: &Global, self_id: id::DeviceId, desc: &wgt::BufferDescriptor<RawString>, new_id: id::BufferId, )87 pub extern "C" fn wgpu_server_device_create_buffer(
88 global: &Global,
89 self_id: id::DeviceId,
90 desc: &wgt::BufferDescriptor<RawString>,
91 new_id: id::BufferId,
92 ) {
93 gfx_select!(self_id => global.device_create_buffer(self_id, desc, new_id));
94 }
95
96 /// # Safety
97 ///
98 /// This function is unsafe as there is no guarantee that the given pointer is
99 /// valid for `size` elements.
100 #[no_mangle]
wgpu_server_device_set_buffer_sub_data( global: &Global, self_id: id::DeviceId, buffer_id: id::BufferId, offset: wgt::BufferAddress, data: *const u8, size: wgt::BufferAddress, )101 pub unsafe extern "C" fn wgpu_server_device_set_buffer_sub_data(
102 global: &Global,
103 self_id: id::DeviceId,
104 buffer_id: id::BufferId,
105 offset: wgt::BufferAddress,
106 data: *const u8,
107 size: wgt::BufferAddress,
108 ) {
109 let slice = slice::from_raw_parts(data, size as usize);
110 gfx_select!(self_id => global.device_set_buffer_sub_data(self_id, buffer_id, offset, slice));
111 }
112
113 /// # Safety
114 ///
115 /// This function is unsafe as there is no guarantee that the given pointer is
116 /// valid for `size` elements.
117 #[no_mangle]
wgpu_server_buffer_map_read( global: &Global, buffer_id: id::BufferId, start: wgt::BufferAddress, size: wgt::BufferAddress, callback: wgc::device::BufferMapReadCallback, userdata: *mut u8, )118 pub extern "C" fn wgpu_server_buffer_map_read(
119 global: &Global,
120 buffer_id: id::BufferId,
121 start: wgt::BufferAddress,
122 size: wgt::BufferAddress,
123 callback: wgc::device::BufferMapReadCallback,
124 userdata: *mut u8,
125 ) {
126 let operation = wgc::resource::BufferMapOperation::Read { callback, userdata };
127
128 gfx_select!(buffer_id => global.buffer_map_async(
129 buffer_id,
130 start .. start + size,
131 operation
132 ));
133 }
134
135 #[no_mangle]
wgpu_server_buffer_unmap(global: &Global, buffer_id: id::BufferId)136 pub extern "C" fn wgpu_server_buffer_unmap(global: &Global, buffer_id: id::BufferId) {
137 gfx_select!(buffer_id => global.buffer_unmap(buffer_id));
138 }
139
140 #[no_mangle]
wgpu_server_buffer_destroy(global: &Global, self_id: id::BufferId)141 pub extern "C" fn wgpu_server_buffer_destroy(global: &Global, self_id: id::BufferId) {
142 gfx_select!(self_id => global.buffer_destroy(self_id));
143 }
144
145 #[no_mangle]
wgpu_server_device_create_encoder( global: &Global, self_id: id::DeviceId, desc: &wgt::CommandEncoderDescriptor, new_id: id::CommandEncoderId, )146 pub extern "C" fn wgpu_server_device_create_encoder(
147 global: &Global,
148 self_id: id::DeviceId,
149 desc: &wgt::CommandEncoderDescriptor,
150 new_id: id::CommandEncoderId,
151 ) {
152 gfx_select!(self_id => global.device_create_command_encoder(self_id, &desc, new_id));
153 }
154
155 #[no_mangle]
wgpu_server_encoder_finish( global: &Global, self_id: id::CommandEncoderId, desc: &wgt::CommandBufferDescriptor, )156 pub extern "C" fn wgpu_server_encoder_finish(
157 global: &Global,
158 self_id: id::CommandEncoderId,
159 desc: &wgt::CommandBufferDescriptor,
160 ) {
161 gfx_select!(self_id => global.command_encoder_finish(self_id, desc));
162 }
163
164 #[no_mangle]
wgpu_server_encoder_destroy(global: &Global, self_id: id::CommandEncoderId)165 pub extern "C" fn wgpu_server_encoder_destroy(global: &Global, self_id: id::CommandEncoderId) {
166 gfx_select!(self_id => global.command_encoder_destroy(self_id));
167 }
168
169 /// # Safety
170 ///
171 /// This function is unsafe as there is no guarantee that the given pointer is
172 /// valid for `byte_length` elements.
173 #[no_mangle]
wgpu_server_command_buffer_destroy( global: &Global, self_id: id::CommandBufferId, )174 pub extern "C" fn wgpu_server_command_buffer_destroy(
175 global: &Global,
176 self_id: id::CommandBufferId,
177 ) {
178 gfx_select!(self_id => global.command_buffer_destroy(self_id));
179 }
180
181 #[no_mangle]
wgpu_server_encoder_copy_buffer_to_buffer( global: &Global, self_id: id::CommandEncoderId, source_id: id::BufferId, source_offset: wgt::BufferAddress, destination_id: id::BufferId, destination_offset: wgt::BufferAddress, size: wgt::BufferAddress, )182 pub unsafe extern "C" fn wgpu_server_encoder_copy_buffer_to_buffer(
183 global: &Global,
184 self_id: id::CommandEncoderId,
185 source_id: id::BufferId,
186 source_offset: wgt::BufferAddress,
187 destination_id: id::BufferId,
188 destination_offset: wgt::BufferAddress,
189 size: wgt::BufferAddress,
190 ) {
191 gfx_select!(self_id => global.command_encoder_copy_buffer_to_buffer(self_id, source_id, source_offset, destination_id, destination_offset, size));
192 }
193
194 #[no_mangle]
wgpu_server_encoder_copy_texture_to_buffer( global: &Global, self_id: id::CommandEncoderId, source: &wgc::command::TextureCopyView, destination: &wgc::command::BufferCopyView, size: wgt::Extent3d, )195 pub unsafe extern "C" fn wgpu_server_encoder_copy_texture_to_buffer(
196 global: &Global,
197 self_id: id::CommandEncoderId,
198 source: &wgc::command::TextureCopyView,
199 destination: &wgc::command::BufferCopyView,
200 size: wgt::Extent3d,
201 ) {
202 gfx_select!(self_id => global.command_encoder_copy_texture_to_buffer(self_id, source, destination, size));
203 }
204
205 #[no_mangle]
wgpu_server_encoder_copy_buffer_to_texture( global: &Global, self_id: id::CommandEncoderId, source: &wgc::command::BufferCopyView, destination: &wgc::command::TextureCopyView, size: wgt::Extent3d, )206 pub unsafe extern "C" fn wgpu_server_encoder_copy_buffer_to_texture(
207 global: &Global,
208 self_id: id::CommandEncoderId,
209 source: &wgc::command::BufferCopyView,
210 destination: &wgc::command::TextureCopyView,
211 size: wgt::Extent3d,
212 ) {
213 gfx_select!(self_id => global.command_encoder_copy_buffer_to_texture(self_id, source, destination, size));
214 }
215
216 #[no_mangle]
wgpu_server_encoder_copy_texture_to_texture( global: &Global, self_id: id::CommandEncoderId, source: &wgc::command::TextureCopyView, destination: &wgc::command::TextureCopyView, size: wgt::Extent3d, )217 pub unsafe extern "C" fn wgpu_server_encoder_copy_texture_to_texture(
218 global: &Global,
219 self_id: id::CommandEncoderId,
220 source: &wgc::command::TextureCopyView,
221 destination: &wgc::command::TextureCopyView,
222 size: wgt::Extent3d,
223 ) {
224 gfx_select!(self_id => global.command_encoder_copy_texture_to_texture(self_id, source, destination, size));
225 }
226
227 /// # Safety
228 ///
229 /// This function is unsafe as there is no guarantee that the given pointers are
230 /// valid for `color_attachments_length` and `command_length` elements,
231 /// respectively.
232 #[no_mangle]
wgpu_server_encode_compute_pass( global: &Global, self_id: id::CommandEncoderId, bytes: *const u8, byte_length: usize, )233 pub unsafe extern "C" fn wgpu_server_encode_compute_pass(
234 global: &Global,
235 self_id: id::CommandEncoderId,
236 bytes: *const u8,
237 byte_length: usize,
238 ) {
239 let raw_data = slice::from_raw_parts(bytes, byte_length);
240 gfx_select!(self_id => global.command_encoder_run_compute_pass(self_id, raw_data));
241 }
242
243 /// # Safety
244 ///
245 /// This function is unsafe as there is no guarantee that the given pointers are
246 /// valid for `color_attachments_length` and `command_length` elements,
247 /// respectively.
248 #[no_mangle]
wgpu_server_encode_render_pass( global: &Global, self_id: id::CommandEncoderId, commands: *const u8, command_length: usize, )249 pub unsafe extern "C" fn wgpu_server_encode_render_pass(
250 global: &Global,
251 self_id: id::CommandEncoderId,
252 commands: *const u8,
253 command_length: usize,
254 ) {
255 let raw_pass = slice::from_raw_parts(commands, command_length);
256 gfx_select!(self_id => global.command_encoder_run_render_pass(self_id, raw_pass));
257 }
258
259 /// # Safety
260 ///
261 /// This function is unsafe as there is no guarantee that the given pointer is
262 /// valid for `command_buffer_id_length` elements.
263 #[no_mangle]
wgpu_server_queue_submit( global: &Global, self_id: id::QueueId, command_buffer_ids: *const id::CommandBufferId, command_buffer_id_length: usize, )264 pub unsafe extern "C" fn wgpu_server_queue_submit(
265 global: &Global,
266 self_id: id::QueueId,
267 command_buffer_ids: *const id::CommandBufferId,
268 command_buffer_id_length: usize,
269 ) {
270 let command_buffers = slice::from_raw_parts(command_buffer_ids, command_buffer_id_length);
271 gfx_select!(self_id => global.queue_submit(self_id, command_buffers));
272 }
273
274 #[no_mangle]
wgpu_server_device_create_bind_group_layout( global: &Global, self_id: id::DeviceId, desc: &wgc::binding_model::BindGroupLayoutDescriptor, new_id: id::BindGroupLayoutId, )275 pub extern "C" fn wgpu_server_device_create_bind_group_layout(
276 global: &Global,
277 self_id: id::DeviceId,
278 desc: &wgc::binding_model::BindGroupLayoutDescriptor,
279 new_id: id::BindGroupLayoutId,
280 ) {
281 gfx_select!(self_id => global.device_create_bind_group_layout(self_id, desc, new_id));
282 }
283
284 #[no_mangle]
wgpu_server_bind_group_layout_destroy( global: &Global, self_id: id::BindGroupLayoutId, )285 pub extern "C" fn wgpu_server_bind_group_layout_destroy(
286 global: &Global,
287 self_id: id::BindGroupLayoutId,
288 ) {
289 gfx_select!(self_id => global.bind_group_layout_destroy(self_id));
290 }
291
292 #[no_mangle]
wgpu_server_device_create_pipeline_layout( global: &Global, self_id: id::DeviceId, desc: &wgc::binding_model::PipelineLayoutDescriptor, new_id: id::PipelineLayoutId, )293 pub extern "C" fn wgpu_server_device_create_pipeline_layout(
294 global: &Global,
295 self_id: id::DeviceId,
296 desc: &wgc::binding_model::PipelineLayoutDescriptor,
297 new_id: id::PipelineLayoutId,
298 ) {
299 gfx_select!(self_id => global.device_create_pipeline_layout(self_id, desc, new_id));
300 }
301
302 #[no_mangle]
wgpu_server_pipeline_layout_destroy( global: &Global, self_id: id::PipelineLayoutId, )303 pub extern "C" fn wgpu_server_pipeline_layout_destroy(
304 global: &Global,
305 self_id: id::PipelineLayoutId,
306 ) {
307 gfx_select!(self_id => global.pipeline_layout_destroy(self_id));
308 }
309
310 #[no_mangle]
wgpu_server_device_create_bind_group( global: &Global, self_id: id::DeviceId, desc: &wgc::binding_model::BindGroupDescriptor, new_id: id::BindGroupId, )311 pub extern "C" fn wgpu_server_device_create_bind_group(
312 global: &Global,
313 self_id: id::DeviceId,
314 desc: &wgc::binding_model::BindGroupDescriptor,
315 new_id: id::BindGroupId,
316 ) {
317 gfx_select!(self_id => global.device_create_bind_group(self_id, desc, new_id));
318 }
319
320 #[no_mangle]
wgpu_server_bind_group_destroy(global: &Global, self_id: id::BindGroupId)321 pub extern "C" fn wgpu_server_bind_group_destroy(global: &Global, self_id: id::BindGroupId) {
322 gfx_select!(self_id => global.bind_group_destroy(self_id));
323 }
324
325 #[no_mangle]
wgpu_server_device_create_shader_module( global: &Global, self_id: id::DeviceId, desc: &wgc::pipeline::ShaderModuleDescriptor, new_id: id::ShaderModuleId, )326 pub extern "C" fn wgpu_server_device_create_shader_module(
327 global: &Global,
328 self_id: id::DeviceId,
329 desc: &wgc::pipeline::ShaderModuleDescriptor,
330 new_id: id::ShaderModuleId,
331 ) {
332 gfx_select!(self_id => global.device_create_shader_module(self_id, desc, new_id));
333 }
334
335 #[no_mangle]
wgpu_server_shader_module_destroy(global: &Global, self_id: id::ShaderModuleId)336 pub extern "C" fn wgpu_server_shader_module_destroy(global: &Global, self_id: id::ShaderModuleId) {
337 gfx_select!(self_id => global.shader_module_destroy(self_id));
338 }
339
340 #[no_mangle]
wgpu_server_device_create_compute_pipeline( global: &Global, self_id: id::DeviceId, desc: &wgc::pipeline::ComputePipelineDescriptor, new_id: id::ComputePipelineId, )341 pub extern "C" fn wgpu_server_device_create_compute_pipeline(
342 global: &Global,
343 self_id: id::DeviceId,
344 desc: &wgc::pipeline::ComputePipelineDescriptor,
345 new_id: id::ComputePipelineId,
346 ) {
347 gfx_select!(self_id => global.device_create_compute_pipeline(self_id, desc, new_id));
348 }
349
350 #[no_mangle]
wgpu_server_compute_pipeline_destroy( global: &Global, self_id: id::ComputePipelineId, )351 pub extern "C" fn wgpu_server_compute_pipeline_destroy(
352 global: &Global,
353 self_id: id::ComputePipelineId,
354 ) {
355 gfx_select!(self_id => global.compute_pipeline_destroy(self_id));
356 }
357
358 #[no_mangle]
wgpu_server_device_create_render_pipeline( global: &Global, self_id: id::DeviceId, desc: &wgc::pipeline::RenderPipelineDescriptor, new_id: id::RenderPipelineId, )359 pub extern "C" fn wgpu_server_device_create_render_pipeline(
360 global: &Global,
361 self_id: id::DeviceId,
362 desc: &wgc::pipeline::RenderPipelineDescriptor,
363 new_id: id::RenderPipelineId,
364 ) {
365 gfx_select!(self_id => global.device_create_render_pipeline(self_id, desc, new_id));
366 }
367
368 #[no_mangle]
wgpu_server_render_pipeline_destroy( global: &Global, self_id: id::RenderPipelineId, )369 pub extern "C" fn wgpu_server_render_pipeline_destroy(
370 global: &Global,
371 self_id: id::RenderPipelineId,
372 ) {
373 gfx_select!(self_id => global.render_pipeline_destroy(self_id));
374 }
375
376 #[no_mangle]
wgpu_server_device_create_texture( global: &Global, self_id: id::DeviceId, desc: &wgt::TextureDescriptor<RawString>, new_id: id::TextureId, )377 pub extern "C" fn wgpu_server_device_create_texture(
378 global: &Global,
379 self_id: id::DeviceId,
380 desc: &wgt::TextureDescriptor<RawString>,
381 new_id: id::TextureId,
382 ) {
383 gfx_select!(self_id => global.device_create_texture(self_id, desc, new_id));
384 }
385
386 #[no_mangle]
wgpu_server_texture_create_view( global: &Global, self_id: id::TextureId, desc: Option<&wgt::TextureViewDescriptor<RawString>>, new_id: id::TextureViewId, )387 pub extern "C" fn wgpu_server_texture_create_view(
388 global: &Global,
389 self_id: id::TextureId,
390 desc: Option<&wgt::TextureViewDescriptor<RawString>>,
391 new_id: id::TextureViewId,
392 ) {
393 gfx_select!(self_id => global.texture_create_view(self_id, desc, new_id));
394 }
395
396 #[no_mangle]
wgpu_server_texture_destroy(global: &Global, self_id: id::TextureId)397 pub extern "C" fn wgpu_server_texture_destroy(global: &Global, self_id: id::TextureId) {
398 gfx_select!(self_id => global.texture_destroy(self_id));
399 }
400
401 #[no_mangle]
wgpu_server_texture_view_destroy(global: &Global, self_id: id::TextureViewId)402 pub extern "C" fn wgpu_server_texture_view_destroy(global: &Global, self_id: id::TextureViewId) {
403 gfx_select!(self_id => global.texture_view_destroy(self_id));
404 }
405
406 #[no_mangle]
wgpu_server_device_create_sampler( global: &Global, self_id: id::DeviceId, desc: &wgt::SamplerDescriptor<RawString>, new_id: id::SamplerId, )407 pub extern "C" fn wgpu_server_device_create_sampler(
408 global: &Global,
409 self_id: id::DeviceId,
410 desc: &wgt::SamplerDescriptor<RawString>,
411 new_id: id::SamplerId,
412 ) {
413 gfx_select!(self_id => global.device_create_sampler(self_id, desc, new_id));
414 }
415
416 #[no_mangle]
wgpu_server_sampler_destroy(global: &Global, self_id: id::SamplerId)417 pub extern "C" fn wgpu_server_sampler_destroy(global: &Global, self_id: id::SamplerId) {
418 gfx_select!(self_id => global.sampler_destroy(self_id));
419 }
420