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/. */
6 error::{ErrMsg, ErrorBuffer, ErrorBufferType},
7 identity::IdentityRecyclerFactory,
8 wgpu_string, AdapterInformation, ByteBuf, CommandEncoderAction, DeviceAction, DropAction,
9 QueueWriteAction, TextureAction,
12 use nsstring::{nsACString, nsCString, nsString};
14 use wgc::{gfx_select, id};
15 use wgc::{pipeline::CreateShaderModuleError, resource::BufferAccessError};
19 use std::sync::atomic::{AtomicU32, Ordering};
21 // The seemingly redundant u64 suffixes help cbindgen with generating the right C++ code.
22 // See https://github.com/mozilla/cbindgen/issues/849.
24 /// We limit the size of buffer allocations for stability reason.
25 /// We can reconsider this limit in the future. Note that some drivers (mesa for example),
26 /// have issues when the size of a buffer, mapping or copy command does not fit into a
27 /// signed 32 bits integer, so beyond a certain size, large allocations will need some form
28 /// of driver allow/blocklist.
29 pub const MAX_BUFFER_SIZE: wgt::BufferAddress = 1u64 << 30u64;
30 // Mesa has issues with height/depth that don't fit in a 16 bits signed integers.
31 const MAX_TEXTURE_EXTENT: u32 = std::i16::MAX as u32;
33 fn restrict_limits(limits: wgt::Limits) -> wgt::Limits {
35 max_buffer_size: limits.max_buffer_size.min(MAX_BUFFER_SIZE),
36 max_texture_dimension_1d: limits.max_texture_dimension_1d.min(MAX_TEXTURE_EXTENT),
37 max_texture_dimension_2d: limits.max_texture_dimension_2d.min(MAX_TEXTURE_EXTENT),
38 max_texture_dimension_3d: limits.max_texture_dimension_3d.min(MAX_TEXTURE_EXTENT),
39 max_non_sampler_bindings: 10_000,
44 // hide wgc's global in private
45 pub struct Global(wgc::global::Global<IdentityRecyclerFactory>);
47 impl std::ops::Deref for Global {
48 type Target = wgc::global::Global<IdentityRecyclerFactory>;
49 fn deref(&self) -> &Self::Target {
55 pub extern "C" fn wgpu_server_new(factory: IdentityRecyclerFactory) -> *mut Global {
56 log::info!("Initializing WGPU server");
57 let backends_pref = static_prefs::pref!("dom.webgpu.wgpu-backend").to_string();
58 let backends = if backends_pref.is_empty() {
59 wgt::Backends::PRIMARY
62 "Selecting backends based on dom.webgpu.wgpu-backend pref: {:?}",
65 wgc::instance::parse_backends_from_comma_list(&backends_pref)
67 let global = Global(wgc::global::Global::new(
70 wgt::InstanceDescriptor {
72 dx12_shader_compiler: wgt::Dx12Compiler::Fxc,
73 gles_minor_version: wgt::Gles3MinorVersion::Automatic,
76 Box::into_raw(Box::new(global))
81 /// This function is unsafe because improper use may lead to memory
82 /// problems. For example, a double-free may occur if the function is called
83 /// twice on the same raw pointer.
85 pub unsafe extern "C" fn wgpu_server_delete(global: *mut Global) {
86 log::info!("Terminating WGPU server");
87 let _ = Box::from_raw(global);
91 pub extern "C" fn wgpu_server_poll_all_devices(global: &Global, force_wait: bool) {
92 global.poll_all_devices(force_wait).unwrap();
95 /// Request an adapter according to the specified options.
96 /// Provide the list of IDs to pick from.
98 /// Returns the index in this list, or -1 if unable to pick.
102 /// This function is unsafe as there is no guarantee that the given pointer is
103 /// valid for `id_length` elements.
105 pub unsafe extern "C" fn wgpu_server_instance_request_adapter(
107 desc: &wgc::instance::RequestAdapterOptions,
108 ids: *const id::AdapterId,
110 mut error_buf: ErrorBuffer,
112 let ids = slice::from_raw_parts(ids, id_length);
113 match global.request_adapter(
115 wgc::instance::AdapterInputs::IdSet(ids, |i| i.backend()),
117 Ok(id) => ids.iter().position(|&i| i == id).unwrap() as i8,
126 pub unsafe extern "C" fn wgpu_server_adapter_pack_info(
128 self_id: Option<id::AdapterId>,
129 byte_buf: &mut ByteBuf,
131 let mut data = Vec::new();
134 let wgt::AdapterInfo {
142 } = gfx_select!(id => global.adapter_get_info(id)).unwrap();
144 let info = AdapterInformation {
146 limits: restrict_limits(gfx_select!(id => global.adapter_limits(id)).unwrap()),
147 features: gfx_select!(id => global.adapter_features(id)).unwrap(),
156 bincode::serialize_into(&mut data, &info).unwrap();
159 bincode::serialize_into(&mut data, &0u64).unwrap();
162 *byte_buf = ByteBuf::from_vec(data);
165 static TRACE_IDX: AtomicU32 = AtomicU32::new(0);
168 pub unsafe extern "C" fn wgpu_server_adapter_request_device(
170 self_id: id::AdapterId,
172 new_id: id::DeviceId,
173 mut error_buf: ErrorBuffer,
175 let desc: wgc::device::DeviceDescriptor = bincode::deserialize(byte_buf.as_slice()).unwrap();
176 let trace_string = std::env::var("WGPU_TRACE").ok().map(|s| {
177 let idx = TRACE_IDX.fetch_add(1, Ordering::Relaxed);
178 let path = format!("{}/{}/", s, idx);
180 if std::fs::create_dir_all(&path).is_err() {
181 log::warn!("Failed to create directory {:?} for wgpu recording.", path);
186 let trace_path = trace_string
188 .map(|string| std::path::Path::new(string.as_str()));
190 gfx_select!(self_id => global.adapter_request_device(self_id, &desc, trace_path, new_id));
191 if let Some(err) = error {
197 pub extern "C" fn wgpu_server_adapter_drop(global: &Global, adapter_id: id::AdapterId) {
198 gfx_select!(adapter_id => global.adapter_drop(adapter_id))
202 pub extern "C" fn wgpu_server_device_drop(global: &Global, self_id: id::DeviceId) {
203 gfx_select!(self_id => global.device_drop(self_id))
206 impl ShaderModuleCompilationMessage {
207 fn set_error(&mut self, error: &CreateShaderModuleError, source: &str) {
208 // The WebGPU spec says that if the message doesn't point to a particular position in
209 // the source, the line number, position, offset and lengths should be zero.
210 self.line_number = 0;
212 self.utf16_offset = 0;
213 self.utf16_length = 0;
215 if let Some(location) = error.location(source) {
216 self.line_number = location.line_number as u64;
217 self.line_pos = location.line_position as u64;
219 let start = location.offset as usize;
220 let end = start + location.length as usize;
221 self.utf16_offset = source[0..start].chars().map(|c| c.len_utf16() as u64).sum();
222 self.utf16_length = source[start..end]
224 .map(|c| c.len_utf16() as u64)
228 let error_string = error.to_string();
230 if !error_string.is_empty() {
231 self.message = nsString::from(&error_string[..]);
236 /// A compilation message representation for the ffi boundary.
237 /// the message is immediately copied into an equivalent C++
238 /// structure that owns its strings.
241 pub struct ShaderModuleCompilationMessage {
242 pub line_number: u64,
244 pub utf16_offset: u64,
245 pub utf16_length: u64,
246 pub message: nsString,
249 /// Creates a shader module and returns an object describing the errors if any.
251 /// If there was no error, the returned pointer is nil.
253 pub extern "C" fn wgpu_server_device_create_shader_module(
255 self_id: id::DeviceId,
256 module_id: id::ShaderModuleId,
257 label: Option<&nsACString>,
259 out_message: &mut ShaderModuleCompilationMessage,
261 let utf8_label = label.map(|utf16| utf16.to_string());
262 let label = utf8_label.as_ref().map(|s| Cow::from(&s[..]));
264 let source_str = code.to_utf8();
266 let source = wgc::pipeline::ShaderModuleSource::Wgsl(Cow::from(&source_str[..]));
268 let desc = wgc::pipeline::ShaderModuleDescriptor {
270 shader_bound_checks: wgt::ShaderBoundChecks::new(),
273 let (_, error) = gfx_select!(
274 self_id => global.device_create_shader_module(
275 self_id, &desc, source, module_id
279 if let Some(err) = error {
280 out_message.set_error(&err, &source_str[..]);
284 // Avoid allocating the structure that holds errors in the common case (no errors).
289 pub extern "C" fn wgpu_server_device_create_buffer(
291 self_id: id::DeviceId,
292 buffer_id: id::BufferId,
293 label: Option<&nsACString>,
294 size: wgt::BufferAddress,
296 mapped_at_creation: bool,
297 shm_allocation_failed: bool,
298 mut error_buf: ErrorBuffer,
300 let utf8_label = label.map(|utf16| utf16.to_string());
301 let label = utf8_label.as_ref().map(|s| Cow::from(&s[..]));
302 let usage = wgt::BufferUsages::from_bits_retain(usage);
304 // Don't trust the graphics driver with buffer sizes larger than our conservative max texture size.
305 if shm_allocation_failed || size > MAX_BUFFER_SIZE {
306 error_buf.init(ErrMsg {
307 message: "Out of memory",
308 r#type: ErrorBufferType::OutOfMemory,
310 gfx_select!(self_id => global.create_buffer_error(buffer_id, label));
314 let desc = wgc::resource::BufferDescriptor {
320 let (_, error) = gfx_select!(self_id => global.device_create_buffer(self_id, &desc, buffer_id));
321 if let Some(err) = error {
328 /// Callers are responsible for ensuring `callback` is well-formed.
330 pub unsafe extern "C" fn wgpu_server_buffer_map(
332 buffer_id: id::BufferId,
333 start: wgt::BufferAddress,
334 size: wgt::BufferAddress,
335 map_mode: wgc::device::HostMap,
336 callback: wgc::resource::BufferMapCallbackC,
338 let callback = wgc::resource::BufferMapCallback::from_c(callback);
339 let operation = wgc::resource::BufferMapOperation {
343 // All errors are also exposed to the mapping callback, so we handle them there and ignore
344 // the returned value of buffer_map_async.
345 let _ = gfx_select!(buffer_id => global.buffer_map_async(
347 start .. start + size,
353 pub struct MappedBufferSlice {
360 /// This function is unsafe as there is no guarantee that the given pointer is
361 /// valid for `size` elements.
363 pub unsafe extern "C" fn wgpu_server_buffer_get_mapped_range(
365 buffer_id: id::BufferId,
366 start: wgt::BufferAddress,
367 size: wgt::BufferAddress,
368 ) -> MappedBufferSlice {
369 let result = gfx_select!(buffer_id => global.buffer_get_mapped_range(
375 // TODO: error reporting.
378 .map(|(ptr, length)| MappedBufferSlice { ptr, length })
379 .unwrap_or(MappedBufferSlice {
380 ptr: std::ptr::null_mut(),
386 pub extern "C" fn wgpu_server_buffer_unmap(
388 buffer_id: id::BufferId,
389 mut error_buf: ErrorBuffer,
391 if let Err(e) = gfx_select!(buffer_id => global.buffer_unmap(buffer_id)) {
393 // NOTE: This is presumed by CTS test cases, and was even formally specified in the
394 // WebGPU spec. previously, but this doesn't seem formally specified now. :confused:
396 // TODO: upstream this; see <https://bugzilla.mozilla.org/show_bug.cgi?id=1842297>.
397 BufferAccessError::Invalid => (),
398 other => error_buf.init(other),
404 pub extern "C" fn wgpu_server_buffer_destroy(global: &Global, self_id: id::BufferId) {
405 // Per spec, there is no need for the buffer or even device to be in a valid state,
406 // even calling calling destroy multiple times is fine, so no error to push into
408 let _ = gfx_select!(self_id => global.buffer_destroy(self_id));
412 pub extern "C" fn wgpu_server_buffer_drop(global: &Global, self_id: id::BufferId) {
413 gfx_select!(self_id => global.buffer_drop(self_id, false));
417 fn device_action<A: wgc::hal_api::HalApi>(
419 self_id: id::DeviceId,
420 action: DeviceAction,
421 mut error_buf: ErrorBuffer,
424 DeviceAction::CreateTexture(id, desc) => {
425 let max = MAX_TEXTURE_EXTENT;
426 if desc.size.width > max
427 || desc.size.height > max
428 || desc.size.depth_or_array_layers > max
430 gfx_select!(self_id => self.create_texture_error(id, desc.label));
431 error_buf.init(ErrMsg {
432 message: "Out of memory",
433 r#type: ErrorBufferType::OutOfMemory,
437 let (_, error) = self.device_create_texture::<A>(self_id, &desc, id);
438 if let Some(err) = error {
442 DeviceAction::CreateSampler(id, desc) => {
443 let (_, error) = self.device_create_sampler::<A>(self_id, &desc, id);
444 if let Some(err) = error {
448 DeviceAction::CreateBindGroupLayout(id, desc) => {
449 let (_, error) = self.device_create_bind_group_layout::<A>(self_id, &desc, id);
450 if let Some(err) = error {
454 DeviceAction::CreatePipelineLayout(id, desc) => {
455 let (_, error) = self.device_create_pipeline_layout::<A>(self_id, &desc, id);
456 if let Some(err) = error {
460 DeviceAction::CreateBindGroup(id, desc) => {
461 let (_, error) = self.device_create_bind_group::<A>(self_id, &desc, id);
462 if let Some(err) = error {
466 DeviceAction::CreateShaderModule(id, desc, code) => {
467 let source = wgc::pipeline::ShaderModuleSource::Wgsl(code);
468 let (_, error) = self.device_create_shader_module::<A>(self_id, &desc, source, id);
469 if let Some(err) = error {
473 DeviceAction::CreateComputePipeline(id, desc, implicit) => {
474 let implicit_ids = implicit
476 .map(|imp| wgc::device::ImplicitPipelineIds {
477 root_id: imp.pipeline,
478 group_ids: &imp.bind_groups,
481 self.device_create_compute_pipeline::<A>(self_id, &desc, id, implicit_ids);
482 if let Some(err) = error {
486 DeviceAction::CreateRenderPipeline(id, desc, implicit) => {
487 let implicit_ids = implicit
489 .map(|imp| wgc::device::ImplicitPipelineIds {
490 root_id: imp.pipeline,
491 group_ids: &imp.bind_groups,
494 self.device_create_render_pipeline::<A>(self_id, &desc, id, implicit_ids);
495 if let Some(err) = error {
499 DeviceAction::CreateRenderBundle(id, encoder, desc) => {
500 let (_, error) = self.render_bundle_encoder_finish::<A>(encoder, &desc, id);
501 if let Some(err) = error {
505 DeviceAction::CreateRenderBundleError(buffer_id, label) => {
506 self.create_render_bundle_error::<A>(buffer_id, label);
508 DeviceAction::CreateCommandEncoder(id, desc) => {
509 let (_, error) = self.device_create_command_encoder::<A>(self_id, &desc, id);
510 if let Some(err) = error {
514 DeviceAction::Error { message, r#type } => {
515 error_buf.init(ErrMsg {
523 fn texture_action<A: wgc::hal_api::HalApi>(
525 self_id: id::TextureId,
526 action: TextureAction,
527 mut error_buf: ErrorBuffer,
530 TextureAction::CreateView(id, desc) => {
531 let (_, error) = self.texture_create_view::<A>(self_id, &desc, id);
532 if let Some(err) = error {
539 fn command_encoder_action<A: wgc::hal_api::HalApi>(
541 self_id: id::CommandEncoderId,
542 action: CommandEncoderAction,
543 mut error_buf: ErrorBuffer,
546 CommandEncoderAction::CopyBufferToBuffer {
553 if let Err(err) = self.command_encoder_copy_buffer_to_buffer::<A>(
554 self_id, src, src_offset, dst, dst_offset, size,
559 CommandEncoderAction::CopyBufferToTexture { src, dst, size } => {
561 self.command_encoder_copy_buffer_to_texture::<A>(self_id, &src, &dst, &size)
566 CommandEncoderAction::CopyTextureToBuffer { src, dst, size } => {
568 self.command_encoder_copy_texture_to_buffer::<A>(self_id, &src, &dst, &size)
573 CommandEncoderAction::CopyTextureToTexture { src, dst, size } => {
575 self.command_encoder_copy_texture_to_texture::<A>(self_id, &src, &dst, &size)
580 CommandEncoderAction::RunComputePass {
584 if let Err(err) = self.command_encoder_run_compute_pass_impl::<A>(
587 timestamp_writes.as_ref(),
592 CommandEncoderAction::WriteTimestamp {
597 self.command_encoder_write_timestamp::<A>(self_id, query_set_id, query_index)
602 CommandEncoderAction::ResolveQuerySet {
609 if let Err(err) = self.command_encoder_resolve_query_set::<A>(
620 CommandEncoderAction::RunRenderPass {
623 target_depth_stencil,
625 occlusion_query_set_id,
627 if let Err(err) = self.command_encoder_run_render_pass_impl::<A>(
631 target_depth_stencil.as_ref(),
632 timestamp_writes.as_ref(),
633 occlusion_query_set_id,
638 CommandEncoderAction::ClearBuffer { dst, offset, size } => {
639 if let Err(err) = self.command_encoder_clear_buffer::<A>(self_id, dst, offset, size)
644 CommandEncoderAction::ClearTexture {
646 ref subresource_range,
649 self.command_encoder_clear_texture::<A>(self_id, dst, subresource_range)
654 CommandEncoderAction::PushDebugGroup(marker) => {
655 if let Err(err) = self.command_encoder_push_debug_group::<A>(self_id, &marker) {
659 CommandEncoderAction::PopDebugGroup => {
660 if let Err(err) = self.command_encoder_pop_debug_group::<A>(self_id) {
664 CommandEncoderAction::InsertDebugMarker(marker) => {
665 if let Err(err) = self.command_encoder_insert_debug_marker::<A>(self_id, &marker) {
674 pub unsafe extern "C" fn wgpu_server_device_action(
676 self_id: id::DeviceId,
678 error_buf: ErrorBuffer,
680 let action = bincode::deserialize(byte_buf.as_slice()).unwrap();
681 gfx_select!(self_id => global.device_action(self_id, action, error_buf));
685 pub unsafe extern "C" fn wgpu_server_texture_action(
687 self_id: id::TextureId,
689 error_buf: ErrorBuffer,
691 let action = bincode::deserialize(byte_buf.as_slice()).unwrap();
692 gfx_select!(self_id => global.texture_action(self_id, action, error_buf));
696 pub unsafe extern "C" fn wgpu_server_command_encoder_action(
698 self_id: id::CommandEncoderId,
700 error_buf: ErrorBuffer,
702 let action = bincode::deserialize(byte_buf.as_slice()).unwrap();
703 gfx_select!(self_id => global.command_encoder_action(self_id, action, error_buf));
707 pub extern "C" fn wgpu_server_device_create_encoder(
709 self_id: id::DeviceId,
710 desc: &wgt::CommandEncoderDescriptor<Option<&nsACString>>,
711 new_id: id::CommandEncoderId,
712 mut error_buf: ErrorBuffer,
714 let utf8_label = desc.label.map(|utf16| utf16.to_string());
715 let label = utf8_label.as_ref().map(|s| Cow::from(&s[..]));
717 let desc = desc.map_label(|_| label);
719 gfx_select!(self_id => global.device_create_command_encoder(self_id, &desc, new_id));
720 if let Some(err) = error {
726 pub extern "C" fn wgpu_server_encoder_finish(
728 self_id: id::CommandEncoderId,
729 desc: &wgt::CommandBufferDescriptor<Option<&nsACString>>,
730 mut error_buf: ErrorBuffer,
732 let label = wgpu_string(desc.label);
733 let desc = desc.map_label(|_| label);
734 let (_, error) = gfx_select!(self_id => global.command_encoder_finish(self_id, &desc));
735 if let Some(err) = error {
741 pub extern "C" fn wgpu_server_encoder_drop(global: &Global, self_id: id::CommandEncoderId) {
742 gfx_select!(self_id => global.command_encoder_drop(self_id));
746 pub extern "C" fn wgpu_server_command_buffer_drop(global: &Global, self_id: id::CommandBufferId) {
747 gfx_select!(self_id => global.command_buffer_drop(self_id));
751 pub extern "C" fn wgpu_server_render_bundle_drop(global: &Global, self_id: id::RenderBundleId) {
752 gfx_select!(self_id => global.render_bundle_drop(self_id));
756 pub unsafe extern "C" fn wgpu_server_encoder_copy_texture_to_buffer(
758 self_id: id::CommandEncoderId,
759 source: &wgc::command::ImageCopyTexture,
760 dst_buffer: wgc::id::BufferId,
761 dst_layout: &crate::ImageDataLayout,
762 size: &wgt::Extent3d,
764 let destination = wgc::command::ImageCopyBuffer {
766 layout: dst_layout.into_wgt(),
768 gfx_select!(self_id => global.command_encoder_copy_texture_to_buffer(self_id, source, &destination, size)).unwrap();
773 /// This function is unsafe as there is no guarantee that the given pointer is
774 /// valid for `command_buffer_id_length` elements.
776 pub unsafe extern "C" fn wgpu_server_queue_submit(
778 self_id: id::QueueId,
779 command_buffer_ids: *const id::CommandBufferId,
780 command_buffer_id_length: usize,
781 mut error_buf: ErrorBuffer,
783 let command_buffers = slice::from_raw_parts(command_buffer_ids, command_buffer_id_length);
784 let result = gfx_select!(self_id => global.queue_submit(self_id, command_buffers));
785 if let Err(err) = result {
791 pub unsafe extern "C" fn wgpu_server_on_submitted_work_done(
793 self_id: id::QueueId,
794 callback: wgc::device::queue::SubmittedWorkDoneClosureC,
796 gfx_select!(self_id => global.queue_on_submitted_work_done(self_id, wgc::device::queue::SubmittedWorkDoneClosure::from_c(callback))).unwrap();
801 /// This function is unsafe as there is no guarantee that the given pointer is
802 /// valid for `data_length` elements.
804 pub unsafe extern "C" fn wgpu_server_queue_write_action(
806 self_id: id::QueueId,
810 mut error_buf: ErrorBuffer,
812 let action: QueueWriteAction = bincode::deserialize(byte_buf.as_slice()).unwrap();
813 let data = slice::from_raw_parts(data, data_length);
814 let result = match action {
815 QueueWriteAction::Buffer { dst, offset } => {
816 gfx_select!(self_id => global.queue_write_buffer(self_id, dst, offset, data))
818 QueueWriteAction::Texture { dst, layout, size } => {
819 gfx_select!(self_id => global.queue_write_texture(self_id, &dst, data, &layout, &size))
822 if let Err(err) = result {
828 pub extern "C" fn wgpu_server_bind_group_layout_drop(
830 self_id: id::BindGroupLayoutId,
832 gfx_select!(self_id => global.bind_group_layout_drop(self_id));
836 pub extern "C" fn wgpu_server_pipeline_layout_drop(global: &Global, self_id: id::PipelineLayoutId) {
837 gfx_select!(self_id => global.pipeline_layout_drop(self_id));
841 pub extern "C" fn wgpu_server_bind_group_drop(global: &Global, self_id: id::BindGroupId) {
842 gfx_select!(self_id => global.bind_group_drop(self_id));
846 pub extern "C" fn wgpu_server_shader_module_drop(global: &Global, self_id: id::ShaderModuleId) {
847 gfx_select!(self_id => global.shader_module_drop(self_id));
851 pub extern "C" fn wgpu_server_compute_pipeline_drop(
853 self_id: id::ComputePipelineId,
855 gfx_select!(self_id => global.compute_pipeline_drop(self_id));
859 pub extern "C" fn wgpu_server_render_pipeline_drop(global: &Global, self_id: id::RenderPipelineId) {
860 gfx_select!(self_id => global.render_pipeline_drop(self_id));
864 pub extern "C" fn wgpu_server_texture_drop(global: &Global, self_id: id::TextureId) {
865 gfx_select!(self_id => global.texture_drop(self_id, false));
869 pub extern "C" fn wgpu_server_texture_view_drop(global: &Global, self_id: id::TextureViewId) {
870 gfx_select!(self_id => global.texture_view_drop(self_id, false)).unwrap();
874 pub extern "C" fn wgpu_server_sampler_drop(global: &Global, self_id: id::SamplerId) {
875 gfx_select!(self_id => global.sampler_drop(self_id));
879 pub extern "C" fn wgpu_server_compute_pipeline_get_bind_group_layout(
881 self_id: id::ComputePipelineId,
883 assign_id: id::BindGroupLayoutId,
884 mut error_buf: ErrorBuffer,
886 let (_, error) = gfx_select!(self_id => global.compute_pipeline_get_bind_group_layout(self_id, index, assign_id));
887 if let Some(err) = error {
893 pub extern "C" fn wgpu_server_render_pipeline_get_bind_group_layout(
895 self_id: id::RenderPipelineId,
897 assign_id: id::BindGroupLayoutId,
898 mut error_buf: ErrorBuffer,
900 let (_, error) = gfx_select!(self_id => global.render_pipeline_get_bind_group_layout(self_id, index, assign_id));
901 if let Some(err) = error {
906 /// Encode the freeing of the selected ID into a byte buf.
908 pub extern "C" fn wgpu_server_adapter_free(id: id::AdapterId, drop_byte_buf: &mut ByteBuf) {
909 *drop_byte_buf = DropAction::Adapter(id).to_byte_buf();
912 pub extern "C" fn wgpu_server_device_free(id: id::DeviceId, drop_byte_buf: &mut ByteBuf) {
913 *drop_byte_buf = DropAction::Device(id).to_byte_buf();
916 pub extern "C" fn wgpu_server_shader_module_free(
917 id: id::ShaderModuleId,
918 drop_byte_buf: &mut ByteBuf,
920 *drop_byte_buf = DropAction::ShaderModule(id).to_byte_buf();
923 pub extern "C" fn wgpu_server_pipeline_layout_free(
924 id: id::PipelineLayoutId,
925 drop_byte_buf: &mut ByteBuf,
927 *drop_byte_buf = DropAction::PipelineLayout(id).to_byte_buf();
930 pub extern "C" fn wgpu_server_bind_group_layout_free(
931 id: id::BindGroupLayoutId,
932 drop_byte_buf: &mut ByteBuf,
934 *drop_byte_buf = DropAction::BindGroupLayout(id).to_byte_buf();
937 pub extern "C" fn wgpu_server_bind_group_free(id: id::BindGroupId, drop_byte_buf: &mut ByteBuf) {
938 *drop_byte_buf = DropAction::BindGroup(id).to_byte_buf();
941 pub extern "C" fn wgpu_server_command_buffer_free(
942 id: id::CommandBufferId,
943 drop_byte_buf: &mut ByteBuf,
945 *drop_byte_buf = DropAction::CommandBuffer(id).to_byte_buf();
948 pub extern "C" fn wgpu_server_render_bundle_free(
949 id: id::RenderBundleId,
950 drop_byte_buf: &mut ByteBuf,
952 *drop_byte_buf = DropAction::RenderBundle(id).to_byte_buf();
955 pub extern "C" fn wgpu_server_render_pipeline_free(
956 id: id::RenderPipelineId,
957 drop_byte_buf: &mut ByteBuf,
959 *drop_byte_buf = DropAction::RenderPipeline(id).to_byte_buf();
962 pub extern "C" fn wgpu_server_compute_pipeline_free(
963 id: id::ComputePipelineId,
964 drop_byte_buf: &mut ByteBuf,
966 *drop_byte_buf = DropAction::ComputePipeline(id).to_byte_buf();
969 pub extern "C" fn wgpu_server_buffer_free(id: id::BufferId, drop_byte_buf: &mut ByteBuf) {
970 *drop_byte_buf = DropAction::Buffer(id).to_byte_buf();
973 pub extern "C" fn wgpu_server_texture_free(id: id::TextureId, drop_byte_buf: &mut ByteBuf) {
974 *drop_byte_buf = DropAction::Texture(id).to_byte_buf();
977 pub extern "C" fn wgpu_server_texture_view_free(
978 id: id::TextureViewId,
979 drop_byte_buf: &mut ByteBuf,
981 *drop_byte_buf = DropAction::TextureView(id).to_byte_buf();
984 pub extern "C" fn wgpu_server_sampler_free(id: id::SamplerId, drop_byte_buf: &mut ByteBuf) {
985 *drop_byte_buf = DropAction::Sampler(id).to_byte_buf();