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