client.rs (72870B)
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::{ 6 cow_label, wgpu_string, AdapterInformation, ByteBuf, CommandEncoderAction, DeviceAction, 7 FfiSlice, QueueWriteAction, RawString, TexelCopyBufferLayout, TextureAction, 8 }; 9 10 use crate::{BufferMapResult, Message, QueueWriteDataSource, ServerMessage, SwapChainId}; 11 12 use wgc::naga::front::wgsl::ImplementedLanguageExtension; 13 use wgc::{command::RenderBundleEncoder, id, identity::IdentityManager}; 14 use wgt::{ 15 error::WebGpuError, BufferAddress, BufferSize, DynamicOffset, IndexFormat, TextureFormat, 16 }; 17 18 use wgc::id::markers; 19 20 use parking_lot::Mutex; 21 22 use nsstring::{nsACString, nsCString, nsString}; 23 24 use std::array; 25 use std::fmt::Write; 26 use std::{borrow::Cow, ptr}; 27 28 use self::render_pass::{FfiRenderPassColorAttachment, RenderPassDepthStencilAttachment}; 29 30 pub mod render_pass; 31 32 #[repr(C)] 33 pub struct ConstantEntry { 34 key: RawString, 35 value: f64, 36 } 37 38 #[repr(C)] 39 pub struct ProgrammableStageDescriptor<'a> { 40 module: id::ShaderModuleId, 41 entry_point: RawString, 42 constants: FfiSlice<'a, ConstantEntry>, 43 } 44 45 impl ProgrammableStageDescriptor<'_> { 46 fn to_wgpu(&self) -> wgc::pipeline::ProgrammableStageDescriptor<'_> { 47 let constants = unsafe { self.constants.as_slice() } 48 .iter() 49 .map(|ce| { 50 ( 51 unsafe { std::ffi::CStr::from_ptr(ce.key) } 52 .to_str() 53 .unwrap() 54 .to_string(), 55 ce.value, 56 ) 57 }) 58 .collect(); 59 wgc::pipeline::ProgrammableStageDescriptor { 60 module: self.module, 61 entry_point: cow_label(&self.entry_point), 62 constants, 63 zero_initialize_workgroup_memory: true, 64 } 65 } 66 } 67 68 #[repr(C)] 69 pub struct ComputePipelineDescriptor<'a> { 70 label: Option<&'a nsACString>, 71 layout: Option<id::PipelineLayoutId>, 72 stage: ProgrammableStageDescriptor<'a>, 73 } 74 75 #[repr(C)] 76 pub struct VertexBufferLayout<'a> { 77 array_stride: wgt::BufferAddress, 78 step_mode: wgt::VertexStepMode, 79 attributes: FfiSlice<'a, wgt::VertexAttribute>, 80 } 81 82 #[repr(C)] 83 pub struct VertexState<'a> { 84 stage: ProgrammableStageDescriptor<'a>, 85 buffers: FfiSlice<'a, VertexBufferLayout<'a>>, 86 } 87 88 impl VertexState<'_> { 89 fn to_wgpu(&self) -> wgc::pipeline::VertexState<'_> { 90 let buffer_layouts = unsafe { self.buffers.as_slice() } 91 .iter() 92 .map(|vb| wgc::pipeline::VertexBufferLayout { 93 array_stride: vb.array_stride, 94 step_mode: vb.step_mode, 95 attributes: Cow::Borrowed(unsafe { vb.attributes.as_slice() }), 96 }) 97 .collect(); 98 wgc::pipeline::VertexState { 99 stage: self.stage.to_wgpu(), 100 buffers: Cow::Owned(buffer_layouts), 101 } 102 } 103 } 104 105 #[repr(C)] 106 pub struct ColorTargetState<'a> { 107 format: wgt::TextureFormat, 108 blend: Option<&'a wgt::BlendState>, 109 write_mask: wgt::ColorWrites, 110 } 111 112 #[repr(C)] 113 pub struct FragmentState<'a> { 114 stage: ProgrammableStageDescriptor<'a>, 115 targets: FfiSlice<'a, ColorTargetState<'a>>, 116 } 117 118 impl FragmentState<'_> { 119 fn to_wgpu(&self) -> wgc::pipeline::FragmentState<'_> { 120 let color_targets = unsafe { self.targets.as_slice() } 121 .iter() 122 .map(|ct| { 123 Some(wgt::ColorTargetState { 124 format: ct.format, 125 blend: ct.blend.cloned(), 126 write_mask: ct.write_mask, 127 }) 128 }) 129 .collect(); 130 wgc::pipeline::FragmentState { 131 stage: self.stage.to_wgpu(), 132 targets: Cow::Owned(color_targets), 133 } 134 } 135 } 136 137 #[repr(C)] 138 pub struct PrimitiveState<'a> { 139 topology: wgt::PrimitiveTopology, 140 strip_index_format: Option<&'a wgt::IndexFormat>, 141 front_face: wgt::FrontFace, 142 cull_mode: Option<&'a wgt::Face>, 143 polygon_mode: wgt::PolygonMode, 144 unclipped_depth: bool, 145 } 146 147 impl PrimitiveState<'_> { 148 fn to_wgpu(&self) -> wgt::PrimitiveState { 149 wgt::PrimitiveState { 150 topology: self.topology, 151 strip_index_format: self.strip_index_format.cloned(), 152 front_face: self.front_face.clone(), 153 cull_mode: self.cull_mode.cloned(), 154 polygon_mode: self.polygon_mode, 155 unclipped_depth: self.unclipped_depth, 156 conservative: false, 157 } 158 } 159 } 160 161 #[repr(C)] 162 pub struct RenderPipelineDescriptor<'a> { 163 label: Option<&'a nsACString>, 164 layout: Option<id::PipelineLayoutId>, 165 vertex: &'a VertexState<'a>, 166 primitive: PrimitiveState<'a>, 167 fragment: Option<&'a FragmentState<'a>>, 168 depth_stencil: Option<&'a wgt::DepthStencilState>, 169 multisample: wgt::MultisampleState, 170 } 171 172 #[repr(C)] 173 pub enum RawTextureSampleType { 174 Float, 175 UnfilterableFloat, 176 Uint, 177 Sint, 178 Depth, 179 } 180 181 #[repr(C)] 182 pub enum RawBindingType { 183 UniformBuffer, 184 StorageBuffer, 185 ReadonlyStorageBuffer, 186 Sampler, 187 SampledTexture, 188 ReadonlyStorageTexture, 189 WriteonlyStorageTexture, 190 ReadWriteStorageTexture, 191 ExternalTexture, 192 } 193 194 #[repr(C)] 195 pub struct BindGroupLayoutEntry<'a> { 196 binding: u32, 197 visibility: wgt::ShaderStages, 198 ty: RawBindingType, 199 has_dynamic_offset: bool, 200 min_binding_size: Option<wgt::BufferSize>, 201 view_dimension: Option<&'a wgt::TextureViewDimension>, 202 texture_sample_type: Option<&'a RawTextureSampleType>, 203 multisampled: bool, 204 storage_texture_format: Option<&'a wgt::TextureFormat>, 205 sampler_filter: bool, 206 sampler_compare: bool, 207 } 208 209 #[repr(C)] 210 pub struct BindGroupLayoutDescriptor<'a> { 211 label: Option<&'a nsACString>, 212 entries: FfiSlice<'a, BindGroupLayoutEntry<'a>>, 213 } 214 215 #[repr(C)] 216 #[derive(Debug)] 217 pub struct BindGroupEntry { 218 binding: u32, 219 buffer: Option<id::BufferId>, 220 offset: wgt::BufferAddress, 221 222 // In `wgpu_core::binding_model::BufferBinding`, these are an 223 // `Option<BufferAddress>`. But since `BufferAddress` can be zero, that is 224 // not a type that cbindgen can express in C++, so we use this pair of 225 // values instead. 226 size_passed: bool, 227 size: wgt::BufferAddress, 228 229 sampler: Option<id::SamplerId>, 230 texture_view: Option<id::TextureViewId>, 231 external_texture: Option<id::ExternalTextureId>, 232 } 233 234 #[repr(C)] 235 pub struct BindGroupDescriptor<'a> { 236 label: Option<&'a nsACString>, 237 layout: id::BindGroupLayoutId, 238 entries: FfiSlice<'a, BindGroupEntry>, 239 } 240 241 #[repr(C)] 242 pub struct PipelineLayoutDescriptor<'a> { 243 label: Option<&'a nsACString>, 244 bind_group_layouts: FfiSlice<'a, id::BindGroupLayoutId>, 245 } 246 247 #[repr(C)] 248 pub struct SamplerDescriptor<'a> { 249 label: Option<&'a nsACString>, 250 address_modes: [wgt::AddressMode; 3], 251 mag_filter: wgt::FilterMode, 252 min_filter: wgt::FilterMode, 253 mipmap_filter: wgt::MipmapFilterMode, 254 lod_min_clamp: f32, 255 lod_max_clamp: f32, 256 compare: Option<&'a wgt::CompareFunction>, 257 max_anisotropy: u16, 258 } 259 260 #[repr(C)] 261 pub struct RenderBundleEncoderDescriptor<'a> { 262 label: Option<&'a nsACString>, 263 color_formats: FfiSlice<'a, wgt::TextureFormat>, 264 depth_stencil_format: Option<&'a wgt::TextureFormat>, 265 depth_read_only: bool, 266 stencil_read_only: bool, 267 sample_count: u32, 268 } 269 270 #[derive(Debug)] 271 struct IdentityHub { 272 adapters: IdentityManager<markers::Adapter>, 273 devices: IdentityManager<markers::Device>, 274 queues: IdentityManager<markers::Queue>, 275 buffers: IdentityManager<markers::Buffer>, 276 command_encoders: IdentityManager<markers::CommandEncoder>, 277 render_pass_encoders: IdentityManager<markers::RenderPassEncoder>, 278 compute_pass_encoders: IdentityManager<markers::ComputePassEncoder>, 279 render_bundle_encoders: IdentityManager<markers::RenderBundleEncoder>, 280 command_buffers: IdentityManager<markers::CommandBuffer>, 281 render_bundles: IdentityManager<markers::RenderBundle>, 282 bind_group_layouts: IdentityManager<markers::BindGroupLayout>, 283 pipeline_layouts: IdentityManager<markers::PipelineLayout>, 284 bind_groups: IdentityManager<markers::BindGroup>, 285 shader_modules: IdentityManager<markers::ShaderModule>, 286 compute_pipelines: IdentityManager<markers::ComputePipeline>, 287 render_pipelines: IdentityManager<markers::RenderPipeline>, 288 textures: IdentityManager<markers::Texture>, 289 texture_views: IdentityManager<markers::TextureView>, 290 external_texture_sources: IdentityManager<crate::ExternalTextureSource>, 291 external_textures: IdentityManager<markers::ExternalTexture>, 292 samplers: IdentityManager<markers::Sampler>, 293 query_sets: IdentityManager<markers::QuerySet>, 294 } 295 296 impl Default for IdentityHub { 297 fn default() -> Self { 298 IdentityHub { 299 adapters: IdentityManager::new(), 300 devices: IdentityManager::new(), 301 queues: IdentityManager::new(), 302 buffers: IdentityManager::new(), 303 command_encoders: IdentityManager::new(), 304 render_pass_encoders: IdentityManager::new(), 305 compute_pass_encoders: IdentityManager::new(), 306 render_bundle_encoders: IdentityManager::new(), 307 command_buffers: IdentityManager::new(), 308 render_bundles: IdentityManager::new(), 309 bind_group_layouts: IdentityManager::new(), 310 pipeline_layouts: IdentityManager::new(), 311 bind_groups: IdentityManager::new(), 312 shader_modules: IdentityManager::new(), 313 compute_pipelines: IdentityManager::new(), 314 render_pipelines: IdentityManager::new(), 315 textures: IdentityManager::new(), 316 texture_views: IdentityManager::new(), 317 external_texture_sources: IdentityManager::new(), 318 external_textures: IdentityManager::new(), 319 samplers: IdentityManager::new(), 320 query_sets: IdentityManager::new(), 321 } 322 } 323 } 324 325 /// Opaque pointer to `mozilla::webgpu::WebGPUChild`. 326 #[derive(Debug, Clone, Copy)] 327 #[repr(transparent)] 328 pub struct WebGPUChildPtr(*mut core::ffi::c_void); 329 330 #[derive(Debug)] 331 pub struct Client { 332 owner: WebGPUChildPtr, 333 message_queue: Mutex<MessageQueue>, 334 identities: Mutex<IdentityHub>, 335 } 336 337 impl Client { 338 fn queue_message(&self, message: &Message) { 339 let mut message_queue = self.message_queue.lock(); 340 message_queue.push(self.owner, message); 341 } 342 fn get_serialized_messages(&self) -> (u32, Vec<u8>) { 343 let mut message_queue = self.message_queue.lock(); 344 message_queue.flush() 345 } 346 } 347 348 #[derive(Debug)] 349 struct MessageQueue { 350 on_message_queued: extern "C" fn(WebGPUChildPtr), 351 352 serialized_messages: std::io::Cursor<Vec<u8>>, 353 nr_of_queued_messages: u32, 354 } 355 356 impl MessageQueue { 357 fn new(on_message_queued: extern "C" fn(WebGPUChildPtr)) -> Self { 358 Self { 359 on_message_queued, 360 serialized_messages: std::io::Cursor::new(Vec::new()), 361 nr_of_queued_messages: 0, 362 } 363 } 364 365 fn push(&mut self, child: WebGPUChildPtr, message: &Message) { 366 use bincode::Options; 367 let options = bincode::DefaultOptions::new() 368 .with_fixint_encoding() 369 .allow_trailing_bytes(); 370 let mut serializer = bincode::Serializer::new(&mut self.serialized_messages, options); 371 372 use serde::Serialize; 373 message.serialize(&mut serializer).unwrap(); 374 375 self.nr_of_queued_messages = self.nr_of_queued_messages.checked_add(1).unwrap(); 376 (self.on_message_queued)(child); 377 378 // Force send when we have queued up at least 4k messages. 379 // We must comply with some static limits: 380 // - `IPC::Message::MAX_DESCRIPTORS_PER_MESSAGE` (32767): currently, 381 // no message can refer to more than one shmem handle; 4k is well below 32k. 382 // - `IPC::Channel::kMaximumMessageSize` (256 * 1024 * 1024, when fuzzing): 383 // with a limit of 4k messages, each message can be up to 64KiB; while we have 384 // some messages that can have arbitrary size (ex. `CreateShaderModule`) most 385 // have a static size. 386 // If we ever violate the limits, the worst that can happen is that we trigger asserts. 387 if self.nr_of_queued_messages >= 4 * 1024 { 388 let (nr_of_messages, serialized_messages) = self.flush(); 389 let serialized_messages = ByteBuf::from_vec(serialized_messages); 390 unsafe { wgpu_child_send_messages(child, nr_of_messages, serialized_messages) }; 391 } 392 } 393 394 fn flush(&mut self) -> (u32, Vec<u8>) { 395 let nr_of_messages = self.nr_of_queued_messages; 396 self.nr_of_queued_messages = 0; 397 ( 398 nr_of_messages, 399 core::mem::take(&mut self.serialized_messages).into_inner(), 400 ) 401 } 402 } 403 404 #[no_mangle] 405 pub extern "C" fn wgpu_client_get_queued_messages( 406 client: &Client, 407 serialized_messages_bb: &mut ByteBuf, 408 ) -> u32 { 409 let (nr_of_messages, serialized_messages) = client.get_serialized_messages(); 410 *serialized_messages_bb = ByteBuf::from_vec(serialized_messages); 411 nr_of_messages 412 } 413 414 #[no_mangle] 415 pub extern "C" fn wgpu_client_new( 416 owner: WebGPUChildPtr, 417 on_message_queued: extern "C" fn(WebGPUChildPtr), 418 ) -> *mut Client { 419 log::info!("Initializing WGPU client"); 420 let client = Client { 421 owner, 422 message_queue: Mutex::new(MessageQueue::new(on_message_queued)), 423 identities: Mutex::new(IdentityHub::default()), 424 }; 425 Box::into_raw(Box::new(client)) 426 } 427 428 /// # Safety 429 /// 430 /// This function is unsafe because improper use may lead to memory 431 /// problems. For example, a double-free may occur if the function is called 432 /// twice on the same raw pointer. 433 #[no_mangle] 434 pub unsafe extern "C" fn wgpu_client_delete(client: *mut Client) { 435 log::info!("Terminating WGPU client"); 436 let _client = Box::from_raw(client); 437 } 438 439 #[no_mangle] 440 pub extern "C" fn wgpu_client_fill_default_limits(limits: &mut wgt::Limits) { 441 *limits = wgt::Limits::default(); 442 } 443 444 /// Writes the single `WGSLLanguageFeature` associated with `index`, appending its identifier to the 445 /// provided `buffer`. If `index` does not correspond to a valid feature index, then do nothing. 446 /// 447 /// This function enables an FFI consumer to extract all implemented features in a loop, like so: 448 /// 449 /// ```rust 450 /// let mut buffer = nsstring::nsCString::new(); 451 /// for index in 0usize.. { 452 /// buffer.truncate(); 453 /// wgpu_client_instance_get_wgsl_language_feature(&mut buffer, index); 454 /// if buffer.is_empty() { 455 /// break; 456 /// } 457 /// // Handle the identifier in `buffer`… 458 /// } 459 /// ``` 460 #[no_mangle] 461 pub extern "C" fn wgpu_client_instance_get_wgsl_language_feature( 462 buffer: &mut nsstring::nsCString, 463 index: usize, 464 ) { 465 match ImplementedLanguageExtension::all().get(index) { 466 Some(some) => buffer.write_str(some.to_ident()).unwrap(), 467 None => (), 468 } 469 } 470 471 #[repr(C)] 472 pub struct FfiDeviceDescriptor<'a> { 473 pub label: Option<&'a nsACString>, 474 pub required_features: wgt::FeaturesWebGPU, 475 pub required_limits: wgt::Limits, 476 } 477 478 #[repr(C)] 479 pub struct DeviceQueueId { 480 device: id::DeviceId, 481 queue: id::QueueId, 482 } 483 484 #[no_mangle] 485 pub extern "C" fn wgpu_client_request_device( 486 client: &Client, 487 adapter_id: id::AdapterId, 488 desc: &FfiDeviceDescriptor, 489 ) -> DeviceQueueId { 490 let identities = client.identities.lock(); 491 let device_id = identities.devices.process(); 492 let queue_id = identities.queues.process(); 493 drop(identities); 494 495 let label = wgpu_string(desc.label); 496 let required_features = 497 wgt::Features::from_internal_flags(wgt::FeaturesWGPU::empty(), desc.required_features); 498 let desc = wgt::DeviceDescriptor { 499 label, 500 required_features, 501 required_limits: desc.required_limits.clone(), 502 memory_hints: wgt::MemoryHints::MemoryUsage, 503 // The content process is untrusted, so this value is ignored 504 // by the GPU process. The GPU process overwrites this with 505 // the result of consulting the `WGPU_TRACE` environment 506 // variable itself in `wgpu_server_adapter_request_device`. 507 trace: wgt::Trace::Off, 508 // The content process is untrusted, so this value is ignored 509 // by the GPU process. The GPU process overwrites this with 510 // `ExperimentalFeatures::disabled()`. 511 experimental_features: wgt::ExperimentalFeatures::disabled(), 512 }; 513 let message = Message::RequestDevice { 514 adapter_id, 515 device_id, 516 queue_id, 517 desc, 518 }; 519 client.queue_message(&message); 520 DeviceQueueId { 521 device: device_id, 522 queue: queue_id, 523 } 524 } 525 526 #[no_mangle] 527 pub extern "C" fn wgpu_client_make_render_pass_encoder_id( 528 client: &Client, 529 ) -> id::RenderPassEncoderId { 530 client.identities.lock().render_pass_encoders.process() 531 } 532 #[no_mangle] 533 pub extern "C" fn wgpu_client_make_compute_pass_encoder_id( 534 client: &Client, 535 ) -> id::ComputePassEncoderId { 536 client.identities.lock().compute_pass_encoders.process() 537 } 538 #[no_mangle] 539 pub extern "C" fn wgpu_client_make_render_bundle_encoder_id( 540 client: &Client, 541 ) -> id::RenderBundleEncoderId { 542 client.identities.lock().render_bundle_encoders.process() 543 } 544 545 #[rustfmt::skip] 546 mod drop { 547 use super::*; 548 549 #[no_mangle] pub extern "C" fn wgpu_client_destroy_buffer(client: &Client, id: id::BufferId) { client.queue_message(&Message::DestroyBuffer(id)); } 550 #[no_mangle] pub extern "C" fn wgpu_client_destroy_texture(client: &Client, id: id::TextureId) { client.queue_message(&Message::DestroyTexture(id)); } 551 #[no_mangle] pub extern "C" fn wgpu_client_destroy_external_texture(client: &Client, id: id::ExternalTextureId) { client.queue_message(&Message::DestroyExternalTexture(id)); } 552 #[no_mangle] pub extern "C" fn wgpu_client_destroy_external_texture_source(client: &Client, id: crate::ExternalTextureSourceId) { client.queue_message(&&Message::DestroyExternalTextureSource(id)); } 553 #[no_mangle] pub extern "C" fn wgpu_client_destroy_device(client: &Client, id: id::DeviceId) { client.queue_message(&Message::DestroyDevice(id)); } 554 555 #[no_mangle] pub extern "C" fn wgpu_client_drop_adapter(client: &Client, id: id::AdapterId) { client.queue_message(&Message::DropAdapter(id)); client.identities.lock().adapters.free(id); } 556 #[no_mangle] pub extern "C" fn wgpu_client_drop_device(client: &Client, id: id::DeviceId) { client.queue_message(&Message::DropDevice(id)); client.identities.lock().devices.free(id); } 557 #[no_mangle] pub extern "C" fn wgpu_client_drop_queue(client: &Client, id: id::QueueId) { client.queue_message(&Message::DropQueue(id)); client.identities.lock().queues.free(id); } 558 #[no_mangle] pub extern "C" fn wgpu_client_drop_buffer(client: &Client, id: id::BufferId) { client.queue_message(&Message::DropBuffer(id)); client.identities.lock().buffers.free(id); } 559 #[no_mangle] pub extern "C" fn wgpu_client_drop_command_encoder(client: &Client, id: id::CommandEncoderId) { client.queue_message(&Message::DropCommandEncoder(id)); client.identities.lock().command_encoders.free(id); } 560 #[no_mangle] pub extern "C" fn wgpu_client_drop_render_pass_encoder(client: &Client, id: id::RenderPassEncoderId) { client.queue_message(&Message::DropRenderPassEncoder(id)); client.identities.lock().render_pass_encoders.free(id); } 561 #[no_mangle] pub extern "C" fn wgpu_client_drop_compute_pass_encoder(client: &Client, id: id::ComputePassEncoderId) { client.queue_message(&Message::DropComputePassEncoder(id)); client.identities.lock().compute_pass_encoders.free(id); } 562 #[no_mangle] pub extern "C" fn wgpu_client_drop_render_bundle_encoder(client: &Client, id: id::RenderBundleEncoderId) { client.queue_message(&Message::DropRenderBundleEncoder(id)); client.identities.lock().render_bundle_encoders.free(id); } 563 #[no_mangle] pub extern "C" fn wgpu_client_drop_command_buffer(client: &Client, id: id::CommandBufferId) { client.queue_message(&Message::DropCommandBuffer(id)); client.identities.lock().command_buffers.free(id); } 564 #[no_mangle] pub extern "C" fn wgpu_client_drop_render_bundle(client: &Client, id: id::RenderBundleId) { client.queue_message(&Message::DropRenderBundle(id)); client.identities.lock().render_bundles.free(id); } 565 #[no_mangle] pub extern "C" fn wgpu_client_drop_bind_group_layout(client: &Client, id: id::BindGroupLayoutId) { client.queue_message(&Message::DropBindGroupLayout(id)); client.identities.lock().bind_group_layouts.free(id); } 566 #[no_mangle] pub extern "C" fn wgpu_client_drop_pipeline_layout(client: &Client, id: id::PipelineLayoutId) { client.queue_message(&Message::DropPipelineLayout(id)); client.identities.lock().pipeline_layouts.free(id); } 567 #[no_mangle] pub extern "C" fn wgpu_client_drop_bind_group(client: &Client, id: id::BindGroupId) { client.queue_message(&Message::DropBindGroup(id)); client.identities.lock().bind_groups.free(id); } 568 #[no_mangle] pub extern "C" fn wgpu_client_drop_shader_module(client: &Client, id: id::ShaderModuleId) { client.queue_message(&Message::DropShaderModule(id)); client.identities.lock().shader_modules.free(id); } 569 #[no_mangle] pub extern "C" fn wgpu_client_drop_compute_pipeline(client: &Client, id: id::ComputePipelineId) { client.queue_message(&Message::DropComputePipeline(id)); client.identities.lock().compute_pipelines.free(id); } 570 #[no_mangle] pub extern "C" fn wgpu_client_drop_render_pipeline(client: &Client, id: id::RenderPipelineId) { client.queue_message(&Message::DropRenderPipeline(id)); client.identities.lock().render_pipelines.free(id); } 571 #[no_mangle] pub extern "C" fn wgpu_client_drop_texture(client: &Client, id: id::TextureId) { client.queue_message(&Message::DropTexture(id)); client.identities.lock().textures.free(id); } 572 #[no_mangle] pub extern "C" fn wgpu_client_drop_texture_view(client: &Client, id: id::TextureViewId) { client.queue_message(&Message::DropTextureView(id)); client.identities.lock().texture_views.free(id); } 573 #[no_mangle] pub extern "C" fn wgpu_client_drop_external_texture(client: &Client, id: id::ExternalTextureId) { client.queue_message(&Message::DropExternalTexture(id)); client.identities.lock().external_textures.free(id); } 574 #[no_mangle] pub extern "C" fn wgpu_client_drop_external_texture_source(client: &Client, id: crate::ExternalTextureSourceId) { client.queue_message(&Message::DropExternalTextureSource(id)); client.identities.lock().external_texture_sources.free(id); } 575 #[no_mangle] pub extern "C" fn wgpu_client_drop_sampler(client: &Client, id: id::SamplerId) { client.queue_message(&Message::DropSampler(id)); client.identities.lock().samplers.free(id); } 576 #[no_mangle] pub extern "C" fn wgpu_client_drop_query_set(client: &Client, id: id::QuerySetId) { client.queue_message(&Message::DropQuerySet(id)); client.identities.lock().query_sets.free(id); } 577 } 578 579 #[repr(C)] 580 pub struct FfiShaderModuleCompilationMessage { 581 pub line_number: u64, 582 pub line_pos: u64, 583 pub utf16_offset: u64, 584 pub utf16_length: u64, 585 pub message: nsString, 586 } 587 588 extern "C" { 589 fn wgpu_child_send_messages( 590 child: WebGPUChildPtr, 591 nr_of_messages: u32, 592 serialized_messages: ByteBuf, 593 ); 594 fn wgpu_child_resolve_request_adapter_promise( 595 child: WebGPUChildPtr, 596 adapter_id: id::AdapterId, 597 adapter_info: Option<&AdapterInformation<nsString>>, 598 ); 599 fn wgpu_child_resolve_request_device_promise( 600 child: WebGPUChildPtr, 601 device_id: id::DeviceId, 602 queue_id: id::QueueId, 603 error: Option<&nsCString>, 604 ); 605 fn wgpu_child_resolve_pop_error_scope_promise( 606 child: WebGPUChildPtr, 607 device_id: id::DeviceId, 608 ty: u8, 609 message: &nsCString, 610 ); 611 fn wgpu_child_resolve_create_pipeline_promise( 612 child: WebGPUChildPtr, 613 pipeline_id: id::RawId, 614 is_render_pipeline: bool, 615 is_validation_error: bool, 616 error: Option<&nsCString>, 617 ); 618 fn wgpu_child_resolve_create_shader_module_promise( 619 child: WebGPUChildPtr, 620 shader_module_id: id::ShaderModuleId, 621 messages: FfiSlice<FfiShaderModuleCompilationMessage>, 622 ); 623 fn wgpu_child_resolve_buffer_map_promise( 624 child: WebGPUChildPtr, 625 buffer_id: id::BufferId, 626 is_writable: bool, 627 offset: u64, 628 size: u64, 629 error: Option<&nsCString>, 630 ); 631 fn wgpu_child_resolve_on_submitted_work_done_promise( 632 child: WebGPUChildPtr, 633 queue_id: id::QueueId, 634 ); 635 } 636 637 #[no_mangle] 638 pub extern "C" fn wgpu_client_receive_server_message(client: &Client, byte_buf: &ByteBuf) { 639 let message: ServerMessage = bincode::deserialize(unsafe { byte_buf.as_slice() }).unwrap(); 640 match message { 641 ServerMessage::RequestAdapterResponse(adapter_id, adapter_information) => { 642 if let Some(AdapterInformation { 643 backend, 644 device_type, 645 device, 646 driver_info, 647 driver, 648 features, 649 id, 650 limits, 651 name, 652 vendor, 653 support_use_shared_texture_in_swap_chain, 654 transient_saves_memory, 655 subgroup_min_size, 656 subgroup_max_size, 657 }) = adapter_information 658 { 659 let nss = |s: &str| { 660 let mut ns_string = nsString::new(); 661 ns_string.assign_str(s); 662 ns_string 663 }; 664 let adapter_info = AdapterInformation { 665 backend, 666 device_type, 667 device, 668 driver_info: nss(&driver_info), 669 driver: nss(&driver), 670 features, 671 id, 672 limits, 673 name: nss(&name), 674 vendor, 675 support_use_shared_texture_in_swap_chain, 676 transient_saves_memory, 677 subgroup_min_size, 678 subgroup_max_size, 679 }; 680 unsafe { 681 wgpu_child_resolve_request_adapter_promise( 682 client.owner, 683 adapter_id, 684 Some(&adapter_info), 685 ); 686 } 687 } else { 688 unsafe { 689 wgpu_child_resolve_request_adapter_promise(client.owner, adapter_id, None); 690 } 691 client.identities.lock().adapters.free(adapter_id) 692 } 693 } 694 ServerMessage::RequestDeviceResponse(device_id, queue_id, error) => { 695 if let Some(error) = error { 696 let error = nsCString::from(error); 697 unsafe { 698 wgpu_child_resolve_request_device_promise( 699 client.owner, 700 device_id, 701 queue_id, 702 Some(&error), 703 ); 704 } 705 let identities = client.identities.lock(); 706 identities.devices.free(device_id); 707 identities.queues.free(queue_id); 708 } else { 709 unsafe { 710 wgpu_child_resolve_request_device_promise( 711 client.owner, 712 device_id, 713 queue_id, 714 None, 715 ); 716 } 717 } 718 } 719 ServerMessage::PopErrorScopeResponse(device_id, ty, message) => { 720 let message = nsCString::from(message.as_ref()); 721 unsafe { 722 wgpu_child_resolve_pop_error_scope_promise(client.owner, device_id, ty, &message); 723 } 724 } 725 ServerMessage::CreateRenderPipelineResponse { pipeline_id, error } => { 726 let is_render_pipeline = true; 727 if let Some(error) = error { 728 let ns_error = nsCString::from(error.error); 729 unsafe { 730 wgpu_child_resolve_create_pipeline_promise( 731 client.owner, 732 pipeline_id.into_raw(), 733 is_render_pipeline, 734 error.is_validation_error, 735 Some(&ns_error), 736 ); 737 } 738 client.identities.lock().render_pipelines.free(pipeline_id); 739 } else { 740 unsafe { 741 wgpu_child_resolve_create_pipeline_promise( 742 client.owner, 743 pipeline_id.into_raw(), 744 is_render_pipeline, 745 false, 746 None, 747 ); 748 } 749 } 750 } 751 ServerMessage::CreateComputePipelineResponse { pipeline_id, error } => { 752 let is_render_pipeline = false; 753 if let Some(error) = error { 754 let ns_error = nsCString::from(error.error); 755 unsafe { 756 wgpu_child_resolve_create_pipeline_promise( 757 client.owner, 758 pipeline_id.into_raw(), 759 is_render_pipeline, 760 error.is_validation_error, 761 Some(&ns_error), 762 ); 763 } 764 client.identities.lock().compute_pipelines.free(pipeline_id); 765 } else { 766 unsafe { 767 wgpu_child_resolve_create_pipeline_promise( 768 client.owner, 769 pipeline_id.into_raw(), 770 is_render_pipeline, 771 false, 772 None, 773 ); 774 } 775 } 776 } 777 ServerMessage::CreateShaderModuleResponse(shader_module_id, compilation_messages) => { 778 let ffi_compilation_messages: Vec<_> = compilation_messages 779 .iter() 780 .map(|m| FfiShaderModuleCompilationMessage { 781 line_number: m.line_number, 782 line_pos: m.line_pos, 783 utf16_offset: m.utf16_offset, 784 utf16_length: m.utf16_length, 785 message: nsString::from(&m.message), 786 }) 787 .collect(); 788 789 unsafe { 790 wgpu_child_resolve_create_shader_module_promise( 791 client.owner, 792 shader_module_id, 793 FfiSlice::from_slice(&ffi_compilation_messages), 794 ) 795 } 796 } 797 ServerMessage::BufferMapResponse(buffer_id, buffer_map_result) => { 798 match buffer_map_result { 799 BufferMapResult::Success { 800 is_writable, 801 offset, 802 size, 803 } => unsafe { 804 wgpu_child_resolve_buffer_map_promise( 805 client.owner, 806 buffer_id, 807 is_writable, 808 offset, 809 size, 810 None, 811 ); 812 }, 813 BufferMapResult::Error(error) => { 814 let ns_error = nsCString::from(error.as_ref()); 815 unsafe { 816 wgpu_child_resolve_buffer_map_promise( 817 client.owner, 818 buffer_id, 819 false, 820 0, 821 0, 822 Some(&ns_error), 823 ); 824 } 825 } 826 }; 827 } 828 ServerMessage::QueueOnSubmittedWorkDoneResponse(queue_id) => unsafe { 829 wgpu_child_resolve_on_submitted_work_done_promise(client.owner, queue_id); 830 }, 831 832 ServerMessage::FreeSwapChainBufferIds(buffer_ids) => { 833 let identities = client.identities.lock(); 834 for id in buffer_ids { 835 identities.buffers.free(id); 836 } 837 } 838 } 839 } 840 841 #[no_mangle] 842 pub extern "C" fn wgpu_client_request_adapter( 843 client: &Client, 844 power_preference: wgt::PowerPreference, 845 force_fallback_adapter: bool, 846 ) -> id::AdapterId { 847 let adapter_id = client.identities.lock().adapters.process(); 848 let message = Message::RequestAdapter { 849 adapter_id, 850 power_preference, 851 force_fallback_adapter, 852 }; 853 client.queue_message(&message); 854 adapter_id 855 } 856 857 #[no_mangle] 858 pub extern "C" fn wgpu_client_pop_error_scope(client: &Client, device_id: id::DeviceId) { 859 let message = Message::Device(device_id, DeviceAction::PopErrorScope); 860 client.queue_message(&message); 861 } 862 863 #[no_mangle] 864 pub extern "C" fn wgpu_client_create_shader_module( 865 client: &Client, 866 device_id: id::DeviceId, 867 label: Option<&nsACString>, 868 code: &nsACString, 869 ) -> id::ShaderModuleId { 870 let shader_module_id = client.identities.lock().shader_modules.process(); 871 let label = wgpu_string(label); 872 let action = 873 DeviceAction::CreateShaderModule(shader_module_id, label, Cow::Owned(code.to_string())); 874 let message = Message::Device(device_id, action); 875 client.queue_message(&message); 876 shader_module_id 877 } 878 879 #[no_mangle] 880 pub extern "C" fn wgpu_client_on_submitted_work_done(client: &Client, queue_id: id::QueueId) { 881 let message = Message::QueueOnSubmittedWorkDone(queue_id); 882 client.queue_message(&message); 883 } 884 885 #[no_mangle] 886 pub extern "C" fn wgpu_client_create_swap_chain( 887 client: &Client, 888 device_id: id::DeviceId, 889 queue_id: id::QueueId, 890 width: i32, 891 height: i32, 892 format: crate::SurfaceFormat, 893 remote_texture_owner_id: crate::RemoteTextureOwnerId, 894 use_shared_texture_in_swap_chain: bool, 895 ) { 896 let identities = client.identities.lock(); 897 let buffer_ids: [id::BufferId; crate::MAX_SWAPCHAIN_BUFFER_COUNT] = 898 array::from_fn(|_| identities.buffers.process()); 899 drop(identities); 900 901 let message = Message::CreateSwapChain { 902 device_id, 903 queue_id, 904 width, 905 height, 906 format, 907 buffer_ids, 908 remote_texture_owner_id, 909 use_shared_texture_in_swap_chain, 910 }; 911 client.queue_message(&message); 912 } 913 914 #[no_mangle] 915 pub extern "C" fn wgpu_client_swap_chain_present( 916 client: &Client, 917 texture_id: id::TextureId, 918 command_encoder_id: id::CommandEncoderId, 919 command_buffer_id: id::CommandBufferId, 920 remote_texture_id: crate::RemoteTextureId, 921 remote_texture_owner_id: crate::RemoteTextureOwnerId, 922 ) { 923 let message = Message::SwapChainPresent { 924 texture_id, 925 command_encoder_id, 926 command_buffer_id, 927 remote_texture_id, 928 remote_texture_owner_id, 929 }; 930 client.queue_message(&message); 931 } 932 933 #[no_mangle] 934 pub extern "C" fn wgpu_client_swap_chain_drop( 935 client: &Client, 936 remote_texture_owner_id: crate::RemoteTextureOwnerId, 937 txn_type: crate::RemoteTextureTxnType, 938 txn_id: crate::RemoteTextureTxnId, 939 ) { 940 let message = Message::SwapChainDrop { 941 remote_texture_owner_id, 942 txn_type, 943 txn_id, 944 }; 945 client.queue_message(&message); 946 } 947 948 #[no_mangle] 949 pub extern "C" fn wgpu_client_queue_submit( 950 client: &Client, 951 device_id: id::DeviceId, 952 queue_id: id::QueueId, 953 command_buffers: FfiSlice<'_, id::CommandBufferId>, 954 swap_chain_textures: FfiSlice<'_, id::TextureId>, 955 external_texture_sources: FfiSlice<'_, crate::ExternalTextureSourceId>, 956 ) { 957 let message = Message::QueueSubmit( 958 device_id, 959 queue_id, 960 Cow::Borrowed(unsafe { command_buffers.as_slice() }), 961 Cow::Borrowed(unsafe { swap_chain_textures.as_slice() }), 962 Cow::Borrowed(unsafe { external_texture_sources.as_slice() }), 963 ); 964 client.queue_message(&message); 965 } 966 967 #[no_mangle] 968 pub extern "C" fn wgpu_client_buffer_map( 969 client: &Client, 970 device_id: id::DeviceId, 971 buffer_id: id::BufferId, 972 mode: u32, 973 offset: u64, 974 size: u64, 975 ) { 976 let message = Message::BufferMap { 977 device_id, 978 buffer_id, 979 mode, 980 offset, 981 size, 982 }; 983 client.queue_message(&message); 984 } 985 986 #[no_mangle] 987 pub extern "C" fn wgpu_client_buffer_unmap( 988 client: &Client, 989 device_id: id::DeviceId, 990 buffer_id: id::BufferId, 991 flush: bool, 992 ) { 993 let message = Message::BufferUnmap(device_id, buffer_id, flush); 994 client.queue_message(&message); 995 } 996 997 #[no_mangle] 998 pub extern "C" fn wgpu_client_push_error_scope( 999 client: &Client, 1000 device_id: id::DeviceId, 1001 filter: u8, 1002 ) { 1003 let action = DeviceAction::PushErrorScope(filter); 1004 let message = Message::Device(device_id, action); 1005 client.queue_message(&message); 1006 } 1007 1008 #[no_mangle] 1009 pub extern "C" fn wgpu_client_create_buffer( 1010 client: &Client, 1011 device_id: id::DeviceId, 1012 desc: &wgt::BufferDescriptor<Option<&nsACString>>, 1013 shmem_handle_index: usize, 1014 ) -> id::BufferId { 1015 let buffer_id = client.identities.lock().buffers.process(); 1016 let label = wgpu_string(desc.label); 1017 let desc = desc.map_label(|_| label); 1018 let action = DeviceAction::CreateBuffer { 1019 buffer_id, 1020 desc, 1021 shmem_handle_index, 1022 }; 1023 let message = Message::Device(device_id, action); 1024 client.queue_message(&message); 1025 buffer_id 1026 } 1027 1028 #[no_mangle] 1029 pub extern "C" fn wgpu_client_create_texture( 1030 client: &Client, 1031 device_id: id::DeviceId, 1032 desc: &wgt::TextureDescriptor<Option<&nsACString>, FfiSlice<TextureFormat>>, 1033 swap_chain_id: Option<&SwapChainId>, 1034 ) -> id::TextureId { 1035 let label = wgpu_string(desc.label); 1036 1037 let id = client.identities.lock().textures.process(); 1038 1039 let view_formats = unsafe { desc.view_formats.as_slice() }.to_vec(); 1040 1041 let action = DeviceAction::CreateTexture( 1042 id, 1043 desc.map_label_and_view_formats(|_| label, |_| view_formats), 1044 swap_chain_id.copied(), 1045 ); 1046 let message = Message::Device(device_id, action); 1047 client.queue_message(&message); 1048 1049 id 1050 } 1051 1052 #[no_mangle] 1053 pub extern "C" fn wgpu_client_make_texture_id(client: &Client) -> id::TextureId { 1054 client.identities.lock().textures.process() 1055 } 1056 1057 #[no_mangle] 1058 pub extern "C" fn wgpu_client_free_texture_id(client: &Client, id: id::TextureId) { 1059 client.identities.lock().textures.free(id) 1060 } 1061 1062 #[no_mangle] 1063 pub extern "C" fn wgpu_client_create_texture_view( 1064 client: &Client, 1065 device_id: id::DeviceId, 1066 texture_id: id::TextureId, 1067 desc: &crate::TextureViewDescriptor, 1068 ) -> id::TextureViewId { 1069 let label = wgpu_string(desc.label); 1070 1071 let id = client.identities.lock().texture_views.process(); 1072 1073 let wgpu_desc = wgc::resource::TextureViewDescriptor { 1074 label, 1075 format: desc.format.cloned(), 1076 dimension: desc.dimension.cloned(), 1077 range: wgt::ImageSubresourceRange { 1078 aspect: desc.aspect, 1079 base_mip_level: desc.base_mip_level, 1080 mip_level_count: desc.mip_level_count.map(|ptr| *ptr), 1081 base_array_layer: desc.base_array_layer, 1082 array_layer_count: desc.array_layer_count.map(|ptr| *ptr), 1083 }, 1084 usage: None, 1085 }; 1086 1087 let action = TextureAction::CreateView(id, wgpu_desc); 1088 let message = Message::Texture(device_id, texture_id, action); 1089 client.queue_message(&message); 1090 id 1091 } 1092 1093 #[no_mangle] 1094 pub extern "C" fn wgpu_client_make_texture_view_id(client: &Client) -> id::TextureViewId { 1095 client.identities.lock().texture_views.process() 1096 } 1097 1098 #[no_mangle] 1099 pub extern "C" fn wgpu_client_free_texture_view_id(client: &Client, id: id::TextureViewId) { 1100 client.identities.lock().texture_views.free(id) 1101 } 1102 1103 #[no_mangle] 1104 pub extern "C" fn wgpu_client_make_external_texture_source_id( 1105 client: &Client, 1106 ) -> crate::ExternalTextureSourceId { 1107 client.identities.lock().external_texture_sources.process() 1108 } 1109 1110 #[no_mangle] 1111 pub extern "C" fn wgpu_client_create_external_texture( 1112 client: &Client, 1113 device_id: id::DeviceId, 1114 desc: &crate::ExternalTextureDescriptor<Option<&nsACString>>, 1115 ) -> id::ExternalTextureId { 1116 let desc = desc.map_label(|l| wgpu_string(*l)); 1117 let id = client.identities.lock().external_textures.process(); 1118 1119 let action = DeviceAction::CreateExternalTexture(id, desc); 1120 let message = Message::Device(device_id, action); 1121 client.queue_message(&message); 1122 id 1123 } 1124 1125 #[no_mangle] 1126 pub extern "C" fn wgpu_client_create_sampler( 1127 client: &Client, 1128 device_id: id::DeviceId, 1129 desc: &SamplerDescriptor, 1130 ) -> id::SamplerId { 1131 let label = wgpu_string(desc.label); 1132 1133 let id = client.identities.lock().samplers.process(); 1134 1135 let wgpu_desc = wgc::resource::SamplerDescriptor { 1136 label, 1137 address_modes: desc.address_modes, 1138 mag_filter: desc.mag_filter, 1139 min_filter: desc.min_filter, 1140 mipmap_filter: desc.mipmap_filter, 1141 lod_min_clamp: desc.lod_min_clamp, 1142 lod_max_clamp: desc.lod_max_clamp, 1143 compare: desc.compare.cloned(), 1144 anisotropy_clamp: desc.max_anisotropy, 1145 border_color: None, 1146 }; 1147 let action = DeviceAction::CreateSampler(id, wgpu_desc); 1148 let message = Message::Device(device_id, action); 1149 client.queue_message(&message); 1150 id 1151 } 1152 1153 #[no_mangle] 1154 pub extern "C" fn wgpu_client_make_command_encoder_id(client: &Client) -> id::CommandEncoderId { 1155 client.identities.lock().command_encoders.process() 1156 } 1157 1158 #[no_mangle] 1159 pub extern "C" fn wgpu_client_free_command_encoder_id(client: &Client, id: id::CommandEncoderId) { 1160 client.identities.lock().command_encoders.free(id) 1161 } 1162 1163 #[no_mangle] 1164 pub extern "C" fn wgpu_client_make_command_buffer_id(client: &Client) -> id::CommandBufferId { 1165 client.identities.lock().command_buffers.process() 1166 } 1167 1168 #[no_mangle] 1169 pub extern "C" fn wgpu_client_free_command_buffer_id(client: &Client, id: id::CommandBufferId) { 1170 client.identities.lock().command_buffers.free(id) 1171 } 1172 1173 #[no_mangle] 1174 pub extern "C" fn wgpu_client_create_command_encoder( 1175 client: &Client, 1176 device_id: id::DeviceId, 1177 desc: &wgt::CommandEncoderDescriptor<Option<&nsACString>>, 1178 ) -> id::CommandEncoderId { 1179 let label = wgpu_string(desc.label); 1180 1181 let id = client.identities.lock().command_encoders.process(); 1182 1183 let action = DeviceAction::CreateCommandEncoder(id, desc.map_label(|_| label)); 1184 let message = Message::Device(device_id, action); 1185 client.queue_message(&message); 1186 id 1187 } 1188 1189 #[no_mangle] 1190 pub extern "C" fn wgpu_device_create_render_bundle_encoder( 1191 client: &Client, 1192 device_id: id::DeviceId, 1193 desc: &RenderBundleEncoderDescriptor, 1194 ) -> *mut wgc::command::RenderBundleEncoder { 1195 let label = wgpu_string(desc.label); 1196 1197 let color_formats: Vec<_> = unsafe { desc.color_formats.as_slice() } 1198 .iter() 1199 .map(|format| Some(format.clone())) 1200 .collect(); 1201 let descriptor = wgc::command::RenderBundleEncoderDescriptor { 1202 label, 1203 color_formats: Cow::Owned(color_formats), 1204 depth_stencil: desc 1205 .depth_stencil_format 1206 .map(|&format| wgt::RenderBundleDepthStencil { 1207 format, 1208 depth_read_only: desc.depth_read_only, 1209 stencil_read_only: desc.stencil_read_only, 1210 }), 1211 sample_count: desc.sample_count, 1212 multiview: None, 1213 }; 1214 match wgc::command::RenderBundleEncoder::new(&descriptor, device_id) { 1215 Ok(encoder) => Box::into_raw(Box::new(encoder)), 1216 Err(e) => { 1217 let message = format!("Error in `Device::create_render_bundle_encoder`: {}", e); 1218 let action = DeviceAction::Error { 1219 message, 1220 r#type: e.webgpu_error_type(), 1221 }; 1222 let message = Message::Device(device_id, action); 1223 client.queue_message(&message); 1224 ptr::null_mut() 1225 } 1226 } 1227 } 1228 1229 #[no_mangle] 1230 pub unsafe extern "C" fn wgpu_render_bundle_encoder_destroy( 1231 pass: *mut wgc::command::RenderBundleEncoder, 1232 ) { 1233 // The RB encoder is just a boxed Rust struct, it doesn't have any API primitives 1234 // associated with it right now, but in the future it will. 1235 let _ = Box::from_raw(pass); 1236 } 1237 1238 #[no_mangle] 1239 pub unsafe extern "C" fn wgpu_client_create_render_bundle( 1240 client: &Client, 1241 device_id: id::DeviceId, 1242 encoder: *mut wgc::command::RenderBundleEncoder, 1243 desc: &wgt::RenderBundleDescriptor<Option<&nsACString>>, 1244 ) -> id::RenderBundleId { 1245 let label = wgpu_string(desc.label); 1246 1247 let id = client.identities.lock().render_bundles.process(); 1248 1249 let action = 1250 DeviceAction::CreateRenderBundle(id, *Box::from_raw(encoder), desc.map_label(|_| label)); 1251 let message = Message::Device(device_id, action); 1252 client.queue_message(&message); 1253 id 1254 } 1255 1256 #[no_mangle] 1257 pub unsafe extern "C" fn wgpu_client_create_render_bundle_error( 1258 client: &Client, 1259 device_id: id::DeviceId, 1260 label: Option<&nsACString>, 1261 ) -> id::RenderBundleId { 1262 let label = wgpu_string(label); 1263 1264 let id = client.identities.lock().render_bundles.process(); 1265 1266 let action = DeviceAction::CreateRenderBundleError(id, label); 1267 let message = Message::Device(device_id, action); 1268 client.queue_message(&message); 1269 id 1270 } 1271 1272 #[repr(C)] 1273 pub struct RawQuerySetDescriptor<'a> { 1274 label: Option<&'a nsACString>, 1275 ty: RawQueryType, 1276 count: u32, 1277 } 1278 1279 #[repr(C)] 1280 #[derive(Clone, Copy, Debug)] 1281 pub enum RawQueryType { 1282 Occlusion, 1283 Timestamp, 1284 } 1285 1286 #[no_mangle] 1287 pub extern "C" fn wgpu_client_create_query_set( 1288 client: &Client, 1289 device_id: id::DeviceId, 1290 desc: &RawQuerySetDescriptor, 1291 ) -> wgc::id::QuerySetId { 1292 let &RawQuerySetDescriptor { label, ty, count } = desc; 1293 1294 let label = wgpu_string(label); 1295 let ty = match ty { 1296 RawQueryType::Occlusion => wgt::QueryType::Occlusion, 1297 RawQueryType::Timestamp => wgt::QueryType::Timestamp, 1298 }; 1299 1300 let desc = wgc::resource::QuerySetDescriptor { label, ty, count }; 1301 1302 let id = client.identities.lock().query_sets.process(); 1303 1304 let action = DeviceAction::CreateQuerySet(id, desc); 1305 let message = Message::Device(device_id, action); 1306 client.queue_message(&message); 1307 1308 id 1309 } 1310 1311 #[repr(C)] 1312 pub struct ComputePassDescriptor<'a> { 1313 pub label: Option<&'a nsACString>, 1314 pub timestamp_writes: Option<&'a PassTimestampWrites<'a>>, 1315 } 1316 1317 #[repr(C)] 1318 pub struct PassTimestampWrites<'a> { 1319 pub query_set: id::QuerySetId, 1320 pub beginning_of_pass_write_index: Option<&'a u32>, 1321 pub end_of_pass_write_index: Option<&'a u32>, 1322 } 1323 1324 #[no_mangle] 1325 pub unsafe extern "C" fn wgpu_command_encoder_begin_compute_pass( 1326 desc: &ComputePassDescriptor, 1327 ) -> *mut crate::command::RecordedComputePass { 1328 let &ComputePassDescriptor { 1329 label, 1330 timestamp_writes, 1331 } = desc; 1332 1333 let label = wgpu_string(label); 1334 1335 let timestamp_writes = timestamp_writes.map(|tsw| { 1336 let &PassTimestampWrites { 1337 query_set, 1338 beginning_of_pass_write_index, 1339 end_of_pass_write_index, 1340 } = tsw; 1341 let beginning_of_pass_write_index = beginning_of_pass_write_index.cloned(); 1342 let end_of_pass_write_index = end_of_pass_write_index.cloned(); 1343 wgc::command::PassTimestampWrites { 1344 query_set, 1345 beginning_of_pass_write_index, 1346 end_of_pass_write_index, 1347 } 1348 }); 1349 1350 let pass = crate::command::RecordedComputePass::new(&wgc::command::ComputePassDescriptor { 1351 label, 1352 timestamp_writes, 1353 }); 1354 Box::into_raw(Box::new(pass)) 1355 } 1356 1357 #[no_mangle] 1358 pub unsafe extern "C" fn wgpu_compute_pass_finish( 1359 client: &Client, 1360 device_id: id::DeviceId, 1361 encoder_id: id::CommandEncoderId, 1362 pass: *mut crate::command::RecordedComputePass, 1363 ) { 1364 let pass = *Box::from_raw(pass); 1365 let message = Message::ReplayComputePass(device_id, encoder_id, pass); 1366 client.queue_message(&message); 1367 } 1368 1369 #[no_mangle] 1370 pub unsafe extern "C" fn wgpu_compute_pass_destroy(pass: *mut crate::command::RecordedComputePass) { 1371 let _ = Box::from_raw(pass); 1372 } 1373 1374 #[repr(C)] 1375 pub struct RenderPassDescriptor<'a> { 1376 pub label: Option<&'a nsACString>, 1377 pub color_attachments: FfiSlice<'a, FfiRenderPassColorAttachment>, 1378 pub depth_stencil_attachment: Option<&'a RenderPassDepthStencilAttachment>, 1379 pub timestamp_writes: Option<&'a PassTimestampWrites<'a>>, 1380 pub occlusion_query_set: Option<wgc::id::QuerySetId>, 1381 } 1382 1383 #[no_mangle] 1384 pub unsafe extern "C" fn wgpu_command_encoder_begin_render_pass( 1385 desc: &RenderPassDescriptor, 1386 ) -> *mut crate::command::RecordedRenderPass { 1387 let &RenderPassDescriptor { 1388 label, 1389 color_attachments, 1390 depth_stencil_attachment, 1391 timestamp_writes, 1392 occlusion_query_set, 1393 } = desc; 1394 1395 let label = wgpu_string(label).map(|l| l.to_string()); 1396 1397 let timestamp_writes = timestamp_writes.map(|tsw| { 1398 let &PassTimestampWrites { 1399 query_set, 1400 beginning_of_pass_write_index, 1401 end_of_pass_write_index, 1402 } = tsw; 1403 let beginning_of_pass_write_index = beginning_of_pass_write_index.cloned(); 1404 let end_of_pass_write_index = end_of_pass_write_index.cloned(); 1405 wgc::command::PassTimestampWrites { 1406 query_set, 1407 beginning_of_pass_write_index, 1408 end_of_pass_write_index, 1409 } 1410 }); 1411 1412 let color_attachments: Vec<_> = color_attachments 1413 .as_slice() 1414 .iter() 1415 .map(|color_attachment| Some(color_attachment.clone().to_wgpu())) 1416 .collect(); 1417 let depth_stencil_attachment = depth_stencil_attachment.cloned().map(|dsa| dsa.to_wgpu()); 1418 let pass = crate::command::RecordedRenderPass::new( 1419 label, 1420 color_attachments, 1421 depth_stencil_attachment, 1422 timestamp_writes, 1423 occlusion_query_set, 1424 ); 1425 Box::into_raw(Box::new(pass)) 1426 } 1427 1428 #[no_mangle] 1429 pub unsafe extern "C" fn wgpu_render_pass_finish( 1430 client: &Client, 1431 device_id: id::DeviceId, 1432 encoder_id: id::CommandEncoderId, 1433 pass: *mut crate::command::RecordedRenderPass, 1434 ) { 1435 let pass = *Box::from_raw(pass); 1436 let message = Message::ReplayRenderPass(device_id, encoder_id, pass); 1437 client.queue_message(&message); 1438 } 1439 1440 #[no_mangle] 1441 pub unsafe extern "C" fn wgpu_render_pass_destroy(pass: *mut crate::command::RecordedRenderPass) { 1442 let _ = Box::from_raw(pass); 1443 } 1444 1445 #[no_mangle] 1446 pub unsafe extern "C" fn wgpu_client_create_bind_group_layout( 1447 client: &Client, 1448 device_id: id::DeviceId, 1449 desc: &BindGroupLayoutDescriptor, 1450 ) -> id::BindGroupLayoutId { 1451 let label = wgpu_string(desc.label); 1452 1453 let id = client.identities.lock().bind_group_layouts.process(); 1454 1455 let entries = desc 1456 .entries 1457 .as_slice() 1458 .iter() 1459 .map(|entry| { 1460 wgt::BindGroupLayoutEntry { 1461 binding: entry.binding, 1462 visibility: entry.visibility, 1463 count: None, 1464 ty: match entry.ty { 1465 RawBindingType::UniformBuffer => wgt::BindingType::Buffer { 1466 ty: wgt::BufferBindingType::Uniform, 1467 has_dynamic_offset: entry.has_dynamic_offset, 1468 min_binding_size: entry.min_binding_size, 1469 }, 1470 RawBindingType::StorageBuffer => wgt::BindingType::Buffer { 1471 ty: wgt::BufferBindingType::Storage { read_only: false }, 1472 has_dynamic_offset: entry.has_dynamic_offset, 1473 min_binding_size: entry.min_binding_size, 1474 }, 1475 RawBindingType::ReadonlyStorageBuffer => wgt::BindingType::Buffer { 1476 ty: wgt::BufferBindingType::Storage { read_only: true }, 1477 has_dynamic_offset: entry.has_dynamic_offset, 1478 min_binding_size: entry.min_binding_size, 1479 }, 1480 RawBindingType::Sampler => { 1481 wgt::BindingType::Sampler(if entry.sampler_compare { 1482 wgt::SamplerBindingType::Comparison 1483 } else if entry.sampler_filter { 1484 wgt::SamplerBindingType::Filtering 1485 } else { 1486 wgt::SamplerBindingType::NonFiltering 1487 }) 1488 } 1489 RawBindingType::SampledTexture => wgt::BindingType::Texture { 1490 //TODO: the spec has a bug here 1491 view_dimension: *entry 1492 .view_dimension 1493 .unwrap_or(&wgt::TextureViewDimension::D2), 1494 sample_type: match entry.texture_sample_type { 1495 None | Some(RawTextureSampleType::Float) => { 1496 wgt::TextureSampleType::Float { filterable: true } 1497 } 1498 Some(RawTextureSampleType::UnfilterableFloat) => { 1499 wgt::TextureSampleType::Float { filterable: false } 1500 } 1501 Some(RawTextureSampleType::Uint) => wgt::TextureSampleType::Uint, 1502 Some(RawTextureSampleType::Sint) => wgt::TextureSampleType::Sint, 1503 Some(RawTextureSampleType::Depth) => wgt::TextureSampleType::Depth, 1504 }, 1505 multisampled: entry.multisampled, 1506 }, 1507 RawBindingType::ReadonlyStorageTexture => wgt::BindingType::StorageTexture { 1508 access: wgt::StorageTextureAccess::ReadOnly, 1509 view_dimension: *entry.view_dimension.unwrap(), 1510 format: *entry.storage_texture_format.unwrap(), 1511 }, 1512 RawBindingType::WriteonlyStorageTexture => wgt::BindingType::StorageTexture { 1513 access: wgt::StorageTextureAccess::WriteOnly, 1514 view_dimension: *entry.view_dimension.unwrap(), 1515 format: *entry.storage_texture_format.unwrap(), 1516 }, 1517 RawBindingType::ReadWriteStorageTexture => wgt::BindingType::StorageTexture { 1518 access: wgt::StorageTextureAccess::ReadWrite, 1519 view_dimension: *entry.view_dimension.unwrap(), 1520 format: *entry.storage_texture_format.unwrap(), 1521 }, 1522 RawBindingType::ExternalTexture => wgt::BindingType::ExternalTexture, 1523 }, 1524 } 1525 }) 1526 .collect(); 1527 let wgpu_desc = wgc::binding_model::BindGroupLayoutDescriptor { 1528 label, 1529 entries: Cow::Owned(entries), 1530 }; 1531 1532 let action = DeviceAction::CreateBindGroupLayout(id, wgpu_desc); 1533 let message = Message::Device(device_id, action); 1534 client.queue_message(&message); 1535 id 1536 } 1537 1538 #[no_mangle] 1539 pub unsafe extern "C" fn wgpu_client_render_pipeline_get_bind_group_layout( 1540 client: &Client, 1541 device_id: id::DeviceId, 1542 pipeline_id: id::RenderPipelineId, 1543 index: u32, 1544 ) -> id::BindGroupLayoutId { 1545 let bgl_id = client.identities.lock().bind_group_layouts.process(); 1546 1547 let action = DeviceAction::RenderPipelineGetBindGroupLayout(pipeline_id, index, bgl_id); 1548 let message = Message::Device(device_id, action); 1549 client.queue_message(&message); 1550 1551 bgl_id 1552 } 1553 1554 #[no_mangle] 1555 pub unsafe extern "C" fn wgpu_client_compute_pipeline_get_bind_group_layout( 1556 client: &Client, 1557 device_id: id::DeviceId, 1558 pipeline_id: id::ComputePipelineId, 1559 index: u32, 1560 ) -> id::BindGroupLayoutId { 1561 let bgl_id = client.identities.lock().bind_group_layouts.process(); 1562 1563 let action = DeviceAction::ComputePipelineGetBindGroupLayout(pipeline_id, index, bgl_id); 1564 let message = Message::Device(device_id, action); 1565 client.queue_message(&message); 1566 1567 bgl_id 1568 } 1569 1570 #[no_mangle] 1571 pub unsafe extern "C" fn wgpu_client_create_pipeline_layout( 1572 client: &Client, 1573 device_id: id::DeviceId, 1574 desc: &PipelineLayoutDescriptor, 1575 ) -> id::PipelineLayoutId { 1576 let label = wgpu_string(desc.label); 1577 1578 let id = client.identities.lock().pipeline_layouts.process(); 1579 1580 let wgpu_desc = wgc::binding_model::PipelineLayoutDescriptor { 1581 label, 1582 bind_group_layouts: Cow::Borrowed(desc.bind_group_layouts.as_slice()), 1583 immediate_size: 0, 1584 }; 1585 1586 let action = DeviceAction::CreatePipelineLayout(id, wgpu_desc); 1587 let message = Message::Device(device_id, action); 1588 client.queue_message(&message); 1589 id 1590 } 1591 1592 #[no_mangle] 1593 pub unsafe extern "C" fn wgpu_client_create_bind_group( 1594 client: &Client, 1595 device_id: id::DeviceId, 1596 desc: &BindGroupDescriptor, 1597 ) -> id::BindGroupId { 1598 let label = wgpu_string(desc.label); 1599 1600 let id = client.identities.lock().bind_groups.process(); 1601 1602 let entries = desc 1603 .entries 1604 .as_slice() 1605 .iter() 1606 .map(|entry| wgc::binding_model::BindGroupEntry { 1607 binding: entry.binding, 1608 resource: if let Some(id) = entry.buffer { 1609 wgc::binding_model::BindingResource::Buffer(wgc::binding_model::BufferBinding { 1610 buffer: id, 1611 offset: entry.offset, 1612 size: entry.size_passed.then_some(entry.size), 1613 }) 1614 } else if let Some(id) = entry.sampler { 1615 wgc::binding_model::BindingResource::Sampler(id) 1616 } else if let Some(id) = entry.texture_view { 1617 wgc::binding_model::BindingResource::TextureView(id) 1618 } else if let Some(id) = entry.external_texture { 1619 wgc::binding_model::BindingResource::ExternalTexture(id) 1620 } else { 1621 panic!("Unexpected binding entry {:?}", entry); 1622 }, 1623 }) 1624 .collect(); 1625 let wgpu_desc = wgc::binding_model::BindGroupDescriptor { 1626 label, 1627 layout: desc.layout, 1628 entries: Cow::Owned(entries), 1629 }; 1630 1631 let action = DeviceAction::CreateBindGroup(id, wgpu_desc); 1632 let message = Message::Device(device_id, action); 1633 client.queue_message(&message); 1634 id 1635 } 1636 1637 #[no_mangle] 1638 pub unsafe extern "C" fn wgpu_client_create_compute_pipeline( 1639 client: &Client, 1640 device_id: id::DeviceId, 1641 desc: &ComputePipelineDescriptor, 1642 is_async: bool, 1643 ) -> id::ComputePipelineId { 1644 let label = wgpu_string(desc.label); 1645 1646 let identities = client.identities.lock(); 1647 let id = identities.compute_pipelines.process(); 1648 1649 let wgpu_desc = wgc::pipeline::ComputePipelineDescriptor { 1650 label, 1651 layout: desc.layout, 1652 stage: desc.stage.to_wgpu(), 1653 cache: None, 1654 }; 1655 1656 let action = DeviceAction::CreateComputePipeline(id, wgpu_desc, is_async); 1657 let message = Message::Device(device_id, action); 1658 client.queue_message(&message); 1659 id 1660 } 1661 1662 #[no_mangle] 1663 pub unsafe extern "C" fn wgpu_client_create_render_pipeline( 1664 client: &Client, 1665 device_id: id::DeviceId, 1666 desc: &RenderPipelineDescriptor, 1667 is_async: bool, 1668 ) -> id::RenderPipelineId { 1669 let label = wgpu_string(desc.label); 1670 1671 let identities = client.identities.lock(); 1672 let id = identities.render_pipelines.process(); 1673 1674 let wgpu_desc = wgc::pipeline::RenderPipelineDescriptor { 1675 label, 1676 layout: desc.layout, 1677 vertex: desc.vertex.to_wgpu(), 1678 fragment: desc.fragment.map(FragmentState::to_wgpu), 1679 primitive: desc.primitive.to_wgpu(), 1680 depth_stencil: desc.depth_stencil.cloned(), 1681 multisample: desc.multisample.clone(), 1682 multiview_mask: None, 1683 cache: None, 1684 }; 1685 1686 let action = DeviceAction::CreateRenderPipeline(id, wgpu_desc, is_async); 1687 let message = Message::Device(device_id, action); 1688 client.queue_message(&message); 1689 id 1690 } 1691 1692 #[no_mangle] 1693 pub unsafe extern "C" fn wgpu_command_encoder_copy_buffer_to_buffer( 1694 client: &Client, 1695 device_id: id::DeviceId, 1696 command_encoder_id: id::CommandEncoderId, 1697 src: id::BufferId, 1698 src_offset: wgt::BufferAddress, 1699 dst: id::BufferId, 1700 dst_offset: wgt::BufferAddress, 1701 size: wgt::BufferAddress, 1702 ) { 1703 // In Javascript, `size === undefined` means "copy from src_offset to end of 1704 // buffer". The `size` argument to this function uses a value of 1705 // `wgt::BufferAddress::MAX` to encode that case. (Valid copy 1706 // sizes must be multiples of four, so in the case that the application 1707 // really asked to copy BufferAddress::MAX bytes, 1708 // CommandEncoder::CopyBufferToBuffer decrements it by four, which 1709 // will still fail for mis-alignment.) 1710 let size = (size != wgt::BufferAddress::MAX).then_some(size); 1711 let action = CommandEncoderAction::CopyBufferToBuffer { 1712 src, 1713 src_offset, 1714 dst, 1715 dst_offset, 1716 size, 1717 }; 1718 let message = Message::CommandEncoder(device_id, command_encoder_id, action); 1719 client.queue_message(&message); 1720 } 1721 1722 #[no_mangle] 1723 pub unsafe extern "C" fn wgpu_command_encoder_copy_texture_to_buffer( 1724 client: &Client, 1725 device_id: id::DeviceId, 1726 command_encoder_id: id::CommandEncoderId, 1727 src: wgc::command::TexelCopyTextureInfo, 1728 dst_buffer: wgc::id::BufferId, 1729 dst_layout: &TexelCopyBufferLayout, 1730 size: wgt::Extent3d, 1731 ) { 1732 let action = CommandEncoderAction::CopyTextureToBuffer { 1733 src, 1734 dst: wgc::command::TexelCopyBufferInfo { 1735 buffer: dst_buffer, 1736 layout: dst_layout.into_wgt(), 1737 }, 1738 size, 1739 }; 1740 let message = Message::CommandEncoder(device_id, command_encoder_id, action); 1741 client.queue_message(&message); 1742 } 1743 1744 #[no_mangle] 1745 pub unsafe extern "C" fn wgpu_command_encoder_copy_buffer_to_texture( 1746 client: &Client, 1747 device_id: id::DeviceId, 1748 command_encoder_id: id::CommandEncoderId, 1749 src_buffer: wgc::id::BufferId, 1750 src_layout: &TexelCopyBufferLayout, 1751 dst: wgc::command::TexelCopyTextureInfo, 1752 size: wgt::Extent3d, 1753 ) { 1754 let action = CommandEncoderAction::CopyBufferToTexture { 1755 src: wgc::command::TexelCopyBufferInfo { 1756 buffer: src_buffer, 1757 layout: src_layout.into_wgt(), 1758 }, 1759 dst, 1760 size, 1761 }; 1762 let message = Message::CommandEncoder(device_id, command_encoder_id, action); 1763 client.queue_message(&message); 1764 } 1765 1766 #[no_mangle] 1767 pub unsafe extern "C" fn wgpu_command_encoder_copy_texture_to_texture( 1768 client: &Client, 1769 device_id: id::DeviceId, 1770 command_encoder_id: id::CommandEncoderId, 1771 src: wgc::command::TexelCopyTextureInfo, 1772 dst: wgc::command::TexelCopyTextureInfo, 1773 size: wgt::Extent3d, 1774 ) { 1775 let action = CommandEncoderAction::CopyTextureToTexture { src, dst, size }; 1776 let message = Message::CommandEncoder(device_id, command_encoder_id, action); 1777 client.queue_message(&message); 1778 } 1779 1780 #[no_mangle] 1781 pub unsafe extern "C" fn wgpu_command_encoder_clear_buffer( 1782 client: &Client, 1783 device_id: id::DeviceId, 1784 command_encoder_id: id::CommandEncoderId, 1785 dst: wgc::id::BufferId, 1786 offset: u64, 1787 size: Option<&u64>, 1788 ) { 1789 let action = CommandEncoderAction::ClearBuffer { 1790 dst, 1791 offset, 1792 size: size.cloned(), 1793 }; 1794 let message = Message::CommandEncoder(device_id, command_encoder_id, action); 1795 client.queue_message(&message); 1796 } 1797 1798 #[no_mangle] 1799 pub extern "C" fn wgpu_command_encoder_push_debug_group( 1800 client: &Client, 1801 device_id: id::DeviceId, 1802 command_encoder_id: id::CommandEncoderId, 1803 marker: &nsACString, 1804 ) { 1805 let string = marker.to_string(); 1806 let action = CommandEncoderAction::PushDebugGroup(string); 1807 let message = Message::CommandEncoder(device_id, command_encoder_id, action); 1808 client.queue_message(&message); 1809 } 1810 1811 #[no_mangle] 1812 pub unsafe extern "C" fn wgpu_command_encoder_pop_debug_group( 1813 client: &Client, 1814 device_id: id::DeviceId, 1815 command_encoder_id: id::CommandEncoderId, 1816 ) { 1817 let action = CommandEncoderAction::PopDebugGroup; 1818 let message = Message::CommandEncoder(device_id, command_encoder_id, action); 1819 client.queue_message(&message); 1820 } 1821 1822 #[no_mangle] 1823 pub unsafe extern "C" fn wgpu_command_encoder_insert_debug_marker( 1824 client: &Client, 1825 device_id: id::DeviceId, 1826 command_encoder_id: id::CommandEncoderId, 1827 marker: &nsACString, 1828 ) { 1829 let string = marker.to_string(); 1830 let action = CommandEncoderAction::InsertDebugMarker(string); 1831 let message = Message::CommandEncoder(device_id, command_encoder_id, action); 1832 client.queue_message(&message); 1833 } 1834 1835 #[no_mangle] 1836 pub unsafe extern "C" fn wgpu_command_encoder_resolve_query_set( 1837 client: &Client, 1838 device_id: id::DeviceId, 1839 command_encoder_id: id::CommandEncoderId, 1840 query_set_id: id::QuerySetId, 1841 start_query: u32, 1842 query_count: u32, 1843 destination: id::BufferId, 1844 destination_offset: wgt::BufferAddress, 1845 ) { 1846 let action = CommandEncoderAction::ResolveQuerySet { 1847 query_set: query_set_id, 1848 start_query, 1849 query_count, 1850 destination, 1851 destination_offset, 1852 }; 1853 let message = Message::CommandEncoder(device_id, command_encoder_id, action); 1854 client.queue_message(&message); 1855 } 1856 1857 #[no_mangle] 1858 pub unsafe extern "C" fn wgpu_report_internal_error( 1859 client: &Client, 1860 device_id: id::DeviceId, 1861 message: *const core::ffi::c_char, 1862 ) { 1863 let action = DeviceAction::Error { 1864 message: core::ffi::CStr::from_ptr(message) 1865 .to_str() 1866 .unwrap() 1867 .to_string(), 1868 r#type: wgt::error::ErrorType::Internal, 1869 }; 1870 let message = Message::Device(device_id, action); 1871 client.queue_message(&message); 1872 } 1873 1874 #[no_mangle] 1875 pub unsafe extern "C" fn wgpu_report_validation_error( 1876 client: &Client, 1877 device_id: id::DeviceId, 1878 message: *const core::ffi::c_char, 1879 ) { 1880 let action = DeviceAction::Error { 1881 message: core::ffi::CStr::from_ptr(message) 1882 .to_str() 1883 .unwrap() 1884 .to_string(), 1885 r#type: wgt::error::ErrorType::Validation, 1886 }; 1887 let message = Message::Device(device_id, action); 1888 client.queue_message(&message); 1889 } 1890 1891 #[no_mangle] 1892 pub unsafe extern "C" fn wgpu_command_encoder_finish( 1893 client: &Client, 1894 device_id: id::DeviceId, 1895 command_encoder_id: id::CommandEncoderId, 1896 desc: &wgt::CommandBufferDescriptor<Option<&nsACString>>, 1897 ) -> id::CommandBufferId { 1898 let command_buffer_id = client.identities.lock().command_buffers.process(); 1899 let label = wgpu_string(desc.label); 1900 let message = Message::CommandEncoderFinish( 1901 device_id, 1902 command_encoder_id, 1903 command_buffer_id, 1904 desc.map_label(|_| label), 1905 ); 1906 client.queue_message(&message); 1907 command_buffer_id 1908 } 1909 1910 #[no_mangle] 1911 pub unsafe extern "C" fn wgpu_queue_write_buffer_inline( 1912 client: &Client, 1913 device_id: id::DeviceId, 1914 queue_id: id::QueueId, 1915 dst: id::BufferId, 1916 offset: wgt::BufferAddress, 1917 data_buffer_index: usize, 1918 ) { 1919 let data_source = QueueWriteDataSource::DataBuffer(data_buffer_index); 1920 1921 let action = QueueWriteAction::Buffer { dst, offset }; 1922 let message = Message::QueueWrite { 1923 device_id, 1924 queue_id, 1925 data_source, 1926 action, 1927 }; 1928 client.queue_message(&message); 1929 } 1930 1931 #[no_mangle] 1932 pub unsafe extern "C" fn wgpu_queue_write_buffer_via_shmem( 1933 client: &Client, 1934 device_id: id::DeviceId, 1935 queue_id: id::QueueId, 1936 dst: id::BufferId, 1937 offset: wgt::BufferAddress, 1938 shmem_handle_index: usize, 1939 ) { 1940 let data_source = QueueWriteDataSource::Shmem(shmem_handle_index); 1941 1942 let action = QueueWriteAction::Buffer { dst, offset }; 1943 let message = Message::QueueWrite { 1944 device_id, 1945 queue_id, 1946 data_source, 1947 action, 1948 }; 1949 client.queue_message(&message); 1950 } 1951 1952 #[no_mangle] 1953 pub unsafe extern "C" fn wgpu_queue_write_texture_via_shmem( 1954 client: &Client, 1955 device_id: id::DeviceId, 1956 queue_id: id::QueueId, 1957 dst: wgt::TexelCopyTextureInfo<id::TextureId>, 1958 layout: TexelCopyBufferLayout, 1959 size: wgt::Extent3d, 1960 shmem_handle_index: usize, 1961 ) { 1962 let data_source = QueueWriteDataSource::Shmem(shmem_handle_index); 1963 1964 let layout = layout.into_wgt(); 1965 let action = QueueWriteAction::Texture { dst, layout, size }; 1966 let message = Message::QueueWrite { 1967 device_id, 1968 queue_id, 1969 data_source, 1970 action, 1971 }; 1972 client.queue_message(&message); 1973 } 1974 1975 #[repr(C)] 1976 pub struct TextureFormatBlockInfo { 1977 copy_size: u32, 1978 width: u32, 1979 height: u32, 1980 } 1981 1982 /// Obtain the block size and dimensions for a single aspect. 1983 /// 1984 /// Populates `info` and returns true on success. Returns false if `format` has 1985 /// multiple aspects and `aspect` is `All`. 1986 #[no_mangle] 1987 pub extern "C" fn wgpu_texture_format_get_block_info( 1988 format: wgt::TextureFormat, 1989 aspect: wgt::TextureAspect, 1990 info: &mut TextureFormatBlockInfo, 1991 ) -> bool { 1992 let (width, height) = format.block_dimensions(); 1993 let (copy_size, ret) = match format.block_copy_size(Some(aspect)) { 1994 Some(size) => (size, true), 1995 None => (0, false), 1996 }; 1997 *info = TextureFormatBlockInfo { 1998 width, 1999 height, 2000 copy_size, 2001 }; 2002 ret 2003 } 2004 2005 #[no_mangle] 2006 pub extern "C" fn wgpu_client_use_shared_texture_in_swapChain(format: wgt::TextureFormat) -> bool { 2007 let supported = match format { 2008 wgt::TextureFormat::Bgra8Unorm => true, 2009 _ => false, 2010 }; 2011 2012 supported 2013 } 2014 2015 #[no_mangle] 2016 pub unsafe extern "C" fn wgpu_render_bundle_set_bind_group( 2017 bundle: &mut RenderBundleEncoder, 2018 index: u32, 2019 bind_group_id: Option<id::BindGroupId>, 2020 offsets: *const DynamicOffset, 2021 offset_length: usize, 2022 ) { 2023 wgc::command::bundle_ffi::wgpu_render_bundle_set_bind_group( 2024 bundle, 2025 index, 2026 bind_group_id, 2027 offsets, 2028 offset_length, 2029 ) 2030 } 2031 2032 #[no_mangle] 2033 pub extern "C" fn wgpu_render_bundle_set_pipeline( 2034 bundle: &mut RenderBundleEncoder, 2035 pipeline_id: id::RenderPipelineId, 2036 ) { 2037 wgc::command::bundle_ffi::wgpu_render_bundle_set_pipeline(bundle, pipeline_id) 2038 } 2039 2040 #[no_mangle] 2041 pub extern "C" fn wgpu_render_bundle_set_vertex_buffer( 2042 bundle: &mut RenderBundleEncoder, 2043 slot: u32, 2044 buffer_id: id::BufferId, 2045 offset: BufferAddress, 2046 size: Option<&BufferSize>, 2047 ) { 2048 wgc::command::bundle_ffi::wgpu_render_bundle_set_vertex_buffer( 2049 bundle, 2050 slot, 2051 buffer_id, 2052 offset, 2053 size.copied(), 2054 ) 2055 } 2056 2057 #[no_mangle] 2058 pub extern "C" fn wgpu_render_bundle_set_index_buffer( 2059 encoder: &mut RenderBundleEncoder, 2060 buffer: id::BufferId, 2061 index_format: IndexFormat, 2062 offset: BufferAddress, 2063 size: Option<&BufferSize>, 2064 ) { 2065 wgc::command::bundle_ffi::wgpu_render_bundle_set_index_buffer( 2066 encoder, 2067 buffer, 2068 index_format, 2069 offset, 2070 size.copied(), 2071 ) 2072 } 2073 2074 #[no_mangle] 2075 pub extern "C" fn wgpu_render_bundle_draw( 2076 bundle: &mut RenderBundleEncoder, 2077 vertex_count: u32, 2078 instance_count: u32, 2079 first_vertex: u32, 2080 first_instance: u32, 2081 ) { 2082 wgc::command::bundle_ffi::wgpu_render_bundle_draw( 2083 bundle, 2084 vertex_count, 2085 instance_count, 2086 first_vertex, 2087 first_instance, 2088 ) 2089 } 2090 2091 #[no_mangle] 2092 pub extern "C" fn wgpu_render_bundle_draw_indexed( 2093 bundle: &mut RenderBundleEncoder, 2094 index_count: u32, 2095 instance_count: u32, 2096 first_index: u32, 2097 base_vertex: i32, 2098 first_instance: u32, 2099 ) { 2100 wgc::command::bundle_ffi::wgpu_render_bundle_draw_indexed( 2101 bundle, 2102 index_count, 2103 instance_count, 2104 first_index, 2105 base_vertex, 2106 first_instance, 2107 ) 2108 } 2109 2110 #[no_mangle] 2111 pub extern "C" fn wgpu_render_bundle_draw_indirect( 2112 bundle: &mut RenderBundleEncoder, 2113 buffer_id: id::BufferId, 2114 offset: BufferAddress, 2115 ) { 2116 wgc::command::bundle_ffi::wgpu_render_bundle_draw_indirect(bundle, buffer_id, offset) 2117 } 2118 2119 #[no_mangle] 2120 pub extern "C" fn wgpu_render_bundle_draw_indexed_indirect( 2121 bundle: &mut RenderBundleEncoder, 2122 buffer_id: id::BufferId, 2123 offset: BufferAddress, 2124 ) { 2125 wgc::command::bundle_ffi::wgpu_render_bundle_draw_indexed_indirect(bundle, buffer_id, offset) 2126 } 2127 2128 #[no_mangle] 2129 pub unsafe extern "C" fn wgpu_render_bundle_push_debug_group( 2130 _bundle: &mut RenderBundleEncoder, 2131 _label: RawString, 2132 ) { 2133 wgc::command::bundle_ffi::wgpu_render_bundle_push_debug_group(_bundle, _label) 2134 } 2135 2136 #[no_mangle] 2137 pub extern "C" fn wgpu_render_bundle_pop_debug_group(_bundle: &mut RenderBundleEncoder) { 2138 wgc::command::bundle_ffi::wgpu_render_bundle_pop_debug_group(_bundle) 2139 } 2140 2141 #[no_mangle] 2142 pub unsafe extern "C" fn wgpu_render_bundle_insert_debug_marker( 2143 _bundle: &mut RenderBundleEncoder, 2144 _label: RawString, 2145 ) { 2146 wgc::command::bundle_ffi::wgpu_render_bundle_insert_debug_marker(_bundle, _label) 2147 }