1use alloc::{borrow::ToOwned as _, collections::BTreeMap, ffi::CString, sync::Arc, vec::Vec};
2use core::{
3 ffi::CStr,
4 mem::{self, MaybeUninit},
5 num::NonZeroU32,
6 ptr,
7 time::Duration,
8};
9
10use arrayvec::ArrayVec;
11use ash::{ext, vk};
12use hashbrown::hash_map::Entry;
13use parking_lot::Mutex;
14
15use super::{conv, descriptor::DescriptorCounts, RawTlasInstance};
16use crate::TlasInstance;
17
18impl super::DeviceShared {
19 pub(super) unsafe fn set_object_name(&self, object: impl vk::Handle, name: &str) {
37 let Some(extension) = self.extension_fns.debug_utils.as_ref() else {
38 return;
39 };
40
41 let mut buffer: [u8; 64] = [0u8; 64];
44 let buffer_vec: Vec<u8>;
45
46 let name_bytes = if name.len() < buffer.len() {
48 buffer[..name.len()].copy_from_slice(name.as_bytes());
50 buffer[name.len()] = 0;
52 &buffer[..name.len() + 1]
53 } else {
54 buffer_vec = name
57 .as_bytes()
58 .iter()
59 .cloned()
60 .chain(core::iter::once(0))
61 .collect();
62 &buffer_vec
63 };
64
65 let name = CStr::from_bytes_until_nul(name_bytes).expect("We have added a null byte");
66
67 let _result = unsafe {
68 extension.set_debug_utils_object_name(
69 &vk::DebugUtilsObjectNameInfoEXT::default()
70 .object_handle(object)
71 .object_name(name),
72 )
73 };
74 }
75
76 pub fn make_render_pass(
77 &self,
78 key: super::RenderPassKey,
79 ) -> Result<vk::RenderPass, crate::DeviceError> {
80 Ok(match self.render_passes.lock().entry(key) {
81 Entry::Occupied(e) => *e.get(),
82 Entry::Vacant(e) => {
83 let super::RenderPassKey {
84 ref colors,
85 ref depth_stencil,
86 sample_count,
87 multiview_mask,
88 } = *e.key();
89
90 let mut vk_attachments = Vec::new();
91 let mut color_refs = Vec::with_capacity(colors.len());
92 let mut resolve_refs = Vec::with_capacity(color_refs.capacity());
93 let mut ds_ref = None;
94 let samples = vk::SampleCountFlags::from_raw(sample_count);
95 let unused = vk::AttachmentReference {
96 attachment: vk::ATTACHMENT_UNUSED,
97 layout: vk::ImageLayout::UNDEFINED,
98 };
99 for cat in colors.iter() {
100 let (color_ref, resolve_ref) =
101 if let Some(super::ColorAttachmentKey { base, resolve }) = cat {
102 let super::AttachmentKey {
103 format,
104 layout,
105 ops,
106 } = *base;
107
108 let color_ref = vk::AttachmentReference {
109 attachment: vk_attachments.len() as u32,
110 layout,
111 };
112 vk_attachments.push({
113 let (load_op, store_op) = conv::map_attachment_ops(ops);
114 vk::AttachmentDescription::default()
115 .format(format)
116 .samples(samples)
117 .load_op(load_op)
118 .store_op(store_op)
119 .initial_layout(layout)
120 .final_layout(layout)
121 });
122 let resolve_ref = if let Some(rat) = resolve {
123 let super::AttachmentKey {
124 format,
125 layout,
126 ops,
127 } = *rat;
128
129 let (load_op, store_op) = conv::map_attachment_ops(ops);
130 let vk_attachment = vk::AttachmentDescription::default()
131 .format(format)
132 .samples(vk::SampleCountFlags::TYPE_1)
133 .load_op(load_op)
134 .store_op(store_op)
135 .initial_layout(layout)
136 .final_layout(layout);
137 vk_attachments.push(vk_attachment);
138
139 vk::AttachmentReference {
140 attachment: vk_attachments.len() as u32 - 1,
141 layout,
142 }
143 } else {
144 unused
145 };
146
147 (color_ref, resolve_ref)
148 } else {
149 (unused, unused)
150 };
151
152 color_refs.push(color_ref);
153 resolve_refs.push(resolve_ref);
154 }
155
156 if let Some(ds) = depth_stencil {
157 let super::DepthStencilAttachmentKey {
158 ref base,
159 stencil_ops,
160 } = *ds;
161
162 let super::AttachmentKey {
163 format,
164 layout,
165 ops,
166 } = *base;
167
168 ds_ref = Some(vk::AttachmentReference {
169 attachment: vk_attachments.len() as u32,
170 layout,
171 });
172 let (load_op, store_op) = conv::map_attachment_ops(ops);
173 let (stencil_load_op, stencil_store_op) = conv::map_attachment_ops(stencil_ops);
174 let vk_attachment = vk::AttachmentDescription::default()
175 .format(format)
176 .samples(samples)
177 .load_op(load_op)
178 .store_op(store_op)
179 .stencil_load_op(stencil_load_op)
180 .stencil_store_op(stencil_store_op)
181 .initial_layout(layout)
182 .final_layout(layout);
183 vk_attachments.push(vk_attachment);
184 }
185
186 let vk_subpasses = [{
187 let mut vk_subpass = vk::SubpassDescription::default()
188 .pipeline_bind_point(vk::PipelineBindPoint::GRAPHICS)
189 .color_attachments(&color_refs)
190 .resolve_attachments(&resolve_refs);
191
192 if self
193 .workarounds
194 .contains(super::Workarounds::EMPTY_RESOLVE_ATTACHMENT_LISTS)
195 && resolve_refs.is_empty()
196 {
197 vk_subpass.p_resolve_attachments = ptr::null();
198 }
199
200 if let Some(ref reference) = ds_ref {
201 vk_subpass = vk_subpass.depth_stencil_attachment(reference)
202 }
203 vk_subpass
204 }];
205
206 let mut vk_info = vk::RenderPassCreateInfo::default()
207 .attachments(&vk_attachments)
208 .subpasses(&vk_subpasses);
209
210 let mut multiview_info;
211 let mask;
212 if let Some(multiview_mask) = multiview_mask {
213 mask = [multiview_mask.get()];
214
215 multiview_info = vk::RenderPassMultiviewCreateInfoKHR::default()
217 .view_masks(&mask)
218 .correlation_masks(&mask);
219 vk_info = vk_info.push_next(&mut multiview_info);
220 }
221
222 let raw = unsafe {
223 self.raw
224 .create_render_pass(&vk_info, None)
225 .map_err(super::map_host_device_oom_err)?
226 };
227
228 *e.insert(raw)
229 }
230 })
231 }
232
233 fn make_memory_ranges<'a, I: 'a + Iterator<Item = crate::MemoryRange>>(
234 &self,
235 buffer: &'a super::Buffer,
236 ranges: I,
237 ) -> Option<impl 'a + Iterator<Item = vk::MappedMemoryRange<'a>>> {
238 let super::BufferOwnership::Managed(ref allocation) = buffer.ownership else {
239 return None;
240 };
241 let allocation = allocation.lock();
242 let mask = self.private_caps.non_coherent_map_mask;
243 Some(ranges.map(move |range| {
244 vk::MappedMemoryRange::default()
245 .memory(allocation.memory())
246 .offset((allocation.offset() + range.start) & !mask)
247 .size((range.end - range.start + mask) & !mask)
248 }))
249 }
250}
251
252struct CompiledStage {
253 create_info: vk::PipelineShaderStageCreateInfo<'static>,
254 _entry_point: CString,
255 temp_raw_module: Option<vk::ShaderModule>,
256}
257
258impl super::Device {
259 pub unsafe fn texture_from_raw(
269 &self,
270 vk_image: vk::Image,
271 desc: &crate::TextureDescriptor,
272 drop_callback: Option<crate::DropCallback>,
273 memory: super::TextureMemory,
274 ) -> super::Texture {
275 let identity = self.shared.texture_identity_factory.next();
276 let drop_guard = crate::DropGuard::from_option(drop_callback);
277
278 if let Some(label) = desc.label {
279 unsafe { self.shared.set_object_name(vk_image, label) };
280 }
281
282 super::Texture {
283 raw: vk_image,
284 drop_guard,
285 memory,
286 format: desc.format,
287 copy_size: desc.copy_extent(),
288 identity,
289 }
290 }
291
292 fn find_memory_type_index(
293 &self,
294 type_bits_req: u32,
295 flags_req: vk::MemoryPropertyFlags,
296 ) -> Option<usize> {
297 let mem_properties = unsafe {
298 self.shared
299 .instance
300 .raw
301 .get_physical_device_memory_properties(self.shared.physical_device)
302 };
303
304 for (i, mem_ty) in mem_properties.memory_types_as_slice().iter().enumerate() {
306 let types_bits = 1 << i;
307 let is_required_memory_type = type_bits_req & types_bits != 0;
308 let has_required_properties = mem_ty.property_flags & flags_req == flags_req;
309 if is_required_memory_type && has_required_properties {
310 return Some(i);
311 }
312 }
313
314 None
315 }
316
317 fn create_image_without_memory(
318 &self,
319 desc: &crate::TextureDescriptor,
320 external_memory_image_create_info: Option<&mut vk::ExternalMemoryImageCreateInfo>,
321 ) -> Result<ImageWithoutMemory, crate::DeviceError> {
322 self.create_image_without_memory_with_tiling(
323 desc,
324 vk::ImageTiling::OPTIMAL,
325 external_memory_image_create_info,
326 None,
327 )
328 }
329
330 fn create_image_without_memory_with_tiling(
331 &self,
332 desc: &crate::TextureDescriptor,
333 tiling: vk::ImageTiling,
334 external_memory_image_create_info: Option<&mut vk::ExternalMemoryImageCreateInfo>,
335 drm_modifier_info: Option<&mut vk::ImageDrmFormatModifierExplicitCreateInfoEXT>,
336 ) -> Result<ImageWithoutMemory, crate::DeviceError> {
337 let copy_size = desc.copy_extent();
338
339 let mut raw_flags = vk::ImageCreateFlags::empty();
340 if desc.dimension == wgt::TextureDimension::D3
341 && desc.usage.contains(wgt::TextureUses::COLOR_TARGET)
342 {
343 raw_flags |= vk::ImageCreateFlags::TYPE_2D_ARRAY_COMPATIBLE;
344 }
345 if desc.is_cube_compatible() {
346 raw_flags |= vk::ImageCreateFlags::CUBE_COMPATIBLE;
347 }
348
349 let original_format = self.shared.private_caps.map_texture_format(desc.format);
350 let mut vk_view_formats = vec![];
351 if !desc.view_formats.is_empty() {
352 raw_flags |= vk::ImageCreateFlags::MUTABLE_FORMAT;
353
354 if self.shared.private_caps.image_format_list {
355 vk_view_formats = desc
356 .view_formats
357 .iter()
358 .map(|f| self.shared.private_caps.map_texture_format(*f))
359 .collect();
360 vk_view_formats.push(original_format)
361 }
362 }
363 if desc.format.is_multi_planar_format() {
364 raw_flags |=
365 vk::ImageCreateFlags::MUTABLE_FORMAT | vk::ImageCreateFlags::EXTENDED_USAGE;
366 }
367
368 let mut vk_info = vk::ImageCreateInfo::default()
369 .flags(raw_flags)
370 .image_type(conv::map_texture_dimension(desc.dimension))
371 .format(original_format)
372 .extent(conv::map_copy_extent(©_size))
373 .mip_levels(desc.mip_level_count)
374 .array_layers(desc.array_layer_count())
375 .samples(vk::SampleCountFlags::from_raw(desc.sample_count))
376 .tiling(tiling)
377 .usage(conv::map_texture_usage(desc.usage))
378 .sharing_mode(vk::SharingMode::EXCLUSIVE)
379 .initial_layout(vk::ImageLayout::UNDEFINED);
380
381 let mut format_list_info = vk::ImageFormatListCreateInfo::default();
382 if !vk_view_formats.is_empty() {
383 format_list_info = format_list_info.view_formats(&vk_view_formats);
384 vk_info = vk_info.push_next(&mut format_list_info);
385 }
386
387 if let Some(ext_info) = external_memory_image_create_info {
388 vk_info = vk_info.push_next(ext_info);
389 }
390
391 if let Some(drm_info) = drm_modifier_info {
392 vk_info = vk_info.push_next(drm_info);
393 }
394
395 let raw = unsafe { self.shared.raw.create_image(&vk_info, None) }.map_err(map_err)?;
396 fn map_err(err: vk::Result) -> crate::DeviceError {
397 super::map_host_device_oom_and_ioca_err(err)
400 }
401 let mut req = unsafe { self.shared.raw.get_image_memory_requirements(raw) };
402
403 if desc.usage.contains(wgt::TextureUses::TRANSIENT) {
404 let mem_type_index = self.find_memory_type_index(
405 req.memory_type_bits,
406 vk::MemoryPropertyFlags::LAZILY_ALLOCATED,
407 );
408 if let Some(mem_type_index) = mem_type_index {
409 req.memory_type_bits = 1 << mem_type_index;
410 }
411 }
412
413 Ok(ImageWithoutMemory {
414 raw,
415 requirements: req,
416 })
417 }
418
419 #[cfg(windows)]
425 pub unsafe fn texture_from_d3d11_shared_handle(
426 &self,
427 d3d11_shared_handle: windows::Win32::Foundation::HANDLE,
428 desc: &crate::TextureDescriptor,
429 ) -> Result<super::Texture, crate::DeviceError> {
430 if !self
431 .shared
432 .features
433 .contains(wgt::Features::VULKAN_EXTERNAL_MEMORY_WIN32)
434 {
435 log::error!("Vulkan driver does not support VK_KHR_external_memory_win32");
436 return Err(crate::DeviceError::Unexpected);
437 }
438
439 let mut external_memory_image_info = vk::ExternalMemoryImageCreateInfo::default()
440 .handle_types(vk::ExternalMemoryHandleTypeFlags::D3D11_TEXTURE);
441
442 let image =
443 self.create_image_without_memory(desc, Some(&mut external_memory_image_info))?;
444
445 let mut dedicated_allocate_info =
448 vk::MemoryDedicatedAllocateInfo::default().image(image.raw);
449
450 let mut import_memory_info = vk::ImportMemoryWin32HandleInfoKHR::default()
451 .handle_type(vk::ExternalMemoryHandleTypeFlags::D3D11_TEXTURE)
452 .handle(d3d11_shared_handle.0 as _);
453 #[allow(clippy::unnecessary_mut_passed)]
455 {
456 import_memory_info.p_next = <*const _>::cast(&mut dedicated_allocate_info);
457 }
458
459 let mem_type_index = self
460 .find_memory_type_index(
461 image.requirements.memory_type_bits,
462 vk::MemoryPropertyFlags::DEVICE_LOCAL,
463 )
464 .ok_or(crate::DeviceError::Unexpected)?;
465
466 let memory_allocate_info = vk::MemoryAllocateInfo::default()
467 .allocation_size(image.requirements.size)
468 .memory_type_index(mem_type_index as _)
469 .push_next(&mut import_memory_info);
470 let memory = unsafe { self.shared.raw.allocate_memory(&memory_allocate_info, None) }
471 .map_err(super::map_host_device_oom_err)?;
472
473 unsafe { self.shared.raw.bind_image_memory(image.raw, memory, 0) }
474 .map_err(super::map_host_device_oom_err)?;
475
476 Ok(unsafe {
477 self.texture_from_raw(
478 image.raw,
479 desc,
480 None,
481 super::TextureMemory::Dedicated(memory),
482 )
483 })
484 }
485
486 #[cfg(unix)]
497 pub unsafe fn texture_from_dmabuf_fd(
498 &self,
499 fd: std::os::unix::io::OwnedFd,
500 desc: &crate::TextureDescriptor,
501 drm_modifier: u64,
502 stride: u64,
503 offset: u64,
504 ) -> Result<super::Texture, crate::DeviceError> {
505 use std::os::unix::io::IntoRawFd;
506
507 if !self
508 .shared
509 .features
510 .contains(wgt::Features::VULKAN_EXTERNAL_MEMORY_DMA_BUF)
511 {
512 log::error!(
513 "Vulkan driver does not support VK_EXT_external_memory_dma_buf \
514 or VK_EXT_image_drm_format_modifier"
515 );
516 return Err(crate::DeviceError::Unexpected);
517 }
518
519 let external_memory_fd_fn = self
520 .shared
521 .extension_fns
522 .external_memory_fd
523 .as_ref()
524 .ok_or_else(|| {
525 log::error!("VK_KHR_external_memory_fd extension not loaded");
526 crate::DeviceError::Unexpected
527 })?;
528
529 let mut external_memory_image_info = vk::ExternalMemoryImageCreateInfo::default()
530 .handle_types(vk::ExternalMemoryHandleTypeFlags::DMA_BUF_EXT);
531
532 let plane_layout = vk::SubresourceLayout {
533 offset,
534 row_pitch: stride,
535 size: 0,
536 array_pitch: 0,
537 depth_pitch: 0,
538 };
539 let mut drm_modifier_info = vk::ImageDrmFormatModifierExplicitCreateInfoEXT::default()
540 .drm_format_modifier(drm_modifier)
541 .plane_layouts(core::slice::from_ref(&plane_layout));
542
543 let image = self.create_image_without_memory_with_tiling(
544 desc,
545 vk::ImageTiling::DRM_FORMAT_MODIFIER_EXT,
546 Some(&mut external_memory_image_info),
547 Some(&mut drm_modifier_info),
548 )?;
549
550 let fd_raw = fd.into_raw_fd();
553
554 let result = self.import_dmabuf_memory(
555 external_memory_fd_fn,
556 fd_raw,
557 image.raw,
558 &image.requirements,
559 );
560
561 match result {
562 Ok(memory) => Ok(unsafe {
563 self.texture_from_raw(
564 image.raw,
565 desc,
566 None,
567 super::TextureMemory::Dedicated(memory),
568 )
569 }),
570 Err(e) => {
571 unsafe { self.shared.raw.destroy_image(image.raw, None) };
573 Err(e)
574 }
575 }
576 }
577
578 #[cfg(unix)]
583 fn import_dmabuf_memory(
584 &self,
585 external_memory_fd_fn: &ash::khr::external_memory_fd::Device,
586 fd_raw: i32,
587 image: vk::Image,
588 requirements: &vk::MemoryRequirements,
589 ) -> Result<vk::DeviceMemory, crate::DeviceError> {
590 let mut fd_props = vk::MemoryFdPropertiesKHR::default();
591 unsafe {
592 external_memory_fd_fn.get_memory_fd_properties(
593 vk::ExternalMemoryHandleTypeFlags::DMA_BUF_EXT,
594 fd_raw,
595 &mut fd_props,
596 )
597 }
598 .map_err(|e| {
599 unsafe { libc::close(fd_raw) };
600 super::map_host_device_oom_err(e)
601 })?;
602
603 let mem_type_index = self
604 .find_memory_type_index(
605 requirements.memory_type_bits & fd_props.memory_type_bits,
606 vk::MemoryPropertyFlags::empty(),
607 )
608 .ok_or_else(|| {
609 unsafe { libc::close(fd_raw) };
610 crate::DeviceError::Unexpected
611 })?;
612
613 let mut dedicated_allocate_info = vk::MemoryDedicatedAllocateInfo::default().image(image);
614
615 let mut import_memory_info = vk::ImportMemoryFdInfoKHR::default()
616 .handle_type(vk::ExternalMemoryHandleTypeFlags::DMA_BUF_EXT)
617 .fd(fd_raw);
618
619 let memory_allocate_info = vk::MemoryAllocateInfo::default()
620 .allocation_size(requirements.size)
621 .memory_type_index(mem_type_index as _)
622 .push_next(&mut import_memory_info)
623 .push_next(&mut dedicated_allocate_info);
624
625 let memory = unsafe { self.shared.raw.allocate_memory(&memory_allocate_info, None) }
628 .map_err(|e| {
629 unsafe { libc::close(fd_raw) };
630 super::map_host_device_oom_err(e)
631 })?;
632
633 unsafe { self.shared.raw.bind_image_memory(image, memory, 0) }.map_err(|e| {
635 unsafe { self.shared.raw.free_memory(memory, None) };
636 super::map_host_device_oom_err(e)
637 })?;
638
639 Ok(memory)
640 }
641
642 fn create_shader_module_impl(
643 &self,
644 spv: &[u32],
645 label: &crate::Label<'_>,
646 ) -> Result<vk::ShaderModule, crate::DeviceError> {
647 let vk_info = vk::ShaderModuleCreateInfo::default()
648 .flags(vk::ShaderModuleCreateFlags::empty())
649 .code(spv);
650
651 let raw = unsafe {
652 profiling::scope!("vkCreateShaderModule");
653 self.shared
654 .raw
655 .create_shader_module(&vk_info, None)
656 .map_err(map_err)?
657 };
658 fn map_err(err: vk::Result) -> crate::DeviceError {
659 super::map_host_device_oom_err(err)
662 }
663
664 if let Some(label) = label {
665 unsafe { self.shared.set_object_name(raw, label) };
666 }
667
668 Ok(raw)
669 }
670
671 fn compile_stage(
672 &self,
673 stage: &crate::ProgrammableStage<super::ShaderModule>,
674 naga_stage: naga::ShaderStage,
675 binding_map: &naga::back::spv::BindingMap,
676 ) -> Result<CompiledStage, crate::PipelineError> {
677 let stage_flags = crate::auxil::map_naga_stage(naga_stage);
678 let vk_module = match *stage.module {
679 super::ShaderModule::Raw(raw) => raw,
680 super::ShaderModule::Intermediate {
681 ref naga_shader,
682 runtime_checks,
683 } => {
684 let pipeline_options = naga::back::spv::PipelineOptions {
685 entry_point: stage.entry_point.to_owned(),
686 shader_stage: naga_stage,
687 };
688 let needs_temp_options = !runtime_checks.bounds_checks
689 || !runtime_checks.force_loop_bounding
690 || !runtime_checks.ray_query_initialization_tracking
691 || !binding_map.is_empty()
692 || naga_shader.debug_source.is_some()
693 || !stage.zero_initialize_workgroup_memory
694 || !runtime_checks.task_shader_dispatch_tracking
695 || !runtime_checks.mesh_shader_primitive_indices_clamp;
696
697 let mut temp_options;
698 let options = if needs_temp_options {
699 temp_options = self.naga_options.clone();
700 if !runtime_checks.bounds_checks {
701 temp_options.bounds_check_policies = naga::proc::BoundsCheckPolicies {
702 index: naga::proc::BoundsCheckPolicy::Unchecked,
703 buffer: naga::proc::BoundsCheckPolicy::Unchecked,
704 image_load: naga::proc::BoundsCheckPolicy::Unchecked,
705 binding_array: naga::proc::BoundsCheckPolicy::Unchecked,
706 };
707 }
708 if !runtime_checks.force_loop_bounding {
709 temp_options.force_loop_bounding = false;
710 }
711 if !runtime_checks.ray_query_initialization_tracking {
712 temp_options.ray_query_initialization_tracking = false;
713 }
714 if !binding_map.is_empty() {
715 temp_options.binding_map = binding_map.clone();
716 }
717
718 if let Some(ref debug) = naga_shader.debug_source {
719 temp_options.debug_info = Some(naga::back::spv::DebugInfo {
720 source_code: &debug.source_code,
721 file_name: debug.file_name.as_ref(),
722 language: naga::back::spv::SourceLanguage::WGSL,
723 })
724 }
725 if !stage.zero_initialize_workgroup_memory {
726 temp_options.zero_initialize_workgroup_memory =
727 naga::back::spv::ZeroInitializeWorkgroupMemoryMode::None;
728 }
729 if !runtime_checks.task_shader_dispatch_tracking {
730 temp_options.task_dispatch_limits = None;
731 }
732 temp_options.mesh_shader_primitive_indices_clamp =
733 runtime_checks.mesh_shader_primitive_indices_clamp;
734
735 &temp_options
736 } else {
737 &self.naga_options
738 };
739
740 let (module, info) = naga::back::pipeline_constants::process_overrides(
741 &naga_shader.module,
742 &naga_shader.info,
743 Some((naga_stage, stage.entry_point)),
744 stage.constants,
745 )
746 .map_err(|e| {
747 crate::PipelineError::PipelineConstants(stage_flags, format!("{e}"))
748 })?;
749
750 let spv = {
751 profiling::scope!("naga::spv::write_vec");
752 naga::back::spv::write_vec(&module, &info, options, Some(&pipeline_options))
753 }
754 .map_err(|e| crate::PipelineError::Linkage(stage_flags, format!("{e}")))?;
755 self.create_shader_module_impl(&spv, &None)?
756 }
757 };
758
759 let mut flags = vk::PipelineShaderStageCreateFlags::empty();
760 if self.shared.features.contains(wgt::Features::SUBGROUP) {
761 flags |= vk::PipelineShaderStageCreateFlags::ALLOW_VARYING_SUBGROUP_SIZE
762 }
763
764 let entry_point = CString::new(stage.entry_point).unwrap();
765 let mut create_info = vk::PipelineShaderStageCreateInfo::default()
766 .flags(flags)
767 .stage(conv::map_shader_stage(stage_flags))
768 .module(vk_module);
769
770 create_info.p_name = entry_point.as_ptr();
772
773 Ok(CompiledStage {
774 create_info,
775 _entry_point: entry_point,
776 temp_raw_module: match *stage.module {
777 super::ShaderModule::Raw(_) => None,
778 super::ShaderModule::Intermediate { .. } => Some(vk_module),
779 },
780 })
781 }
782
783 pub fn queue_family_index(&self) -> u32 {
789 self.shared.family_index
790 }
791
792 pub fn queue_index(&self) -> u32 {
793 self.shared.queue_index
794 }
795
796 pub fn raw_device(&self) -> &ash::Device {
797 &self.shared.raw
798 }
799
800 pub fn raw_physical_device(&self) -> vk::PhysicalDevice {
801 self.shared.physical_device
802 }
803
804 pub fn raw_queue(&self) -> vk::Queue {
805 self.shared.raw_queue
806 }
807
808 pub fn enabled_device_extensions(&self) -> &[&'static CStr] {
809 &self.shared.enabled_extensions
810 }
811
812 pub fn shared_instance(&self) -> &super::InstanceShared {
813 &self.shared.instance
814 }
815
816 fn error_if_would_oom_on_resource_allocation(
817 &self,
818 needs_host_access: bool,
819 size: u64,
820 ) -> Result<(), crate::DeviceError> {
821 let Some(threshold) = self
822 .shared
823 .instance
824 .memory_budget_thresholds
825 .for_resource_creation
826 else {
827 return Ok(());
828 };
829
830 if !self
831 .shared
832 .enabled_extensions
833 .contains(&ext::memory_budget::NAME)
834 {
835 return Ok(());
836 }
837
838 let get_physical_device_properties = self
839 .shared
840 .instance
841 .get_physical_device_properties
842 .as_ref()
843 .unwrap();
844
845 let mut memory_budget_properties = vk::PhysicalDeviceMemoryBudgetPropertiesEXT::default();
846
847 let mut memory_properties =
848 vk::PhysicalDeviceMemoryProperties2::default().push_next(&mut memory_budget_properties);
849
850 unsafe {
851 get_physical_device_properties.get_physical_device_memory_properties2(
852 self.shared.physical_device,
853 &mut memory_properties,
854 );
855 }
856
857 let mut host_visible_heaps = [false; vk::MAX_MEMORY_HEAPS];
858 let mut device_local_heaps = [false; vk::MAX_MEMORY_HEAPS];
859
860 let memory_properties = memory_properties.memory_properties;
861
862 for i in 0..memory_properties.memory_type_count {
863 let memory_type = memory_properties.memory_types[i as usize];
864 let flags = memory_type.property_flags;
865
866 if flags.intersects(
867 vk::MemoryPropertyFlags::LAZILY_ALLOCATED | vk::MemoryPropertyFlags::PROTECTED,
868 ) {
869 continue; }
871
872 if flags.contains(vk::MemoryPropertyFlags::HOST_VISIBLE) {
873 host_visible_heaps[memory_type.heap_index as usize] = true;
874 }
875
876 if flags.contains(vk::MemoryPropertyFlags::DEVICE_LOCAL) {
877 device_local_heaps[memory_type.heap_index as usize] = true;
878 }
879 }
880
881 let heaps = if needs_host_access {
882 host_visible_heaps
883 } else {
884 device_local_heaps
885 };
886
887 for (i, check) in heaps.iter().enumerate() {
892 if !check {
893 continue;
894 }
895
896 let heap_usage = memory_budget_properties.heap_usage[i];
897 let heap_budget = memory_budget_properties.heap_budget[i];
898
899 if heap_usage + size >= heap_budget / 100 * threshold as u64 {
900 return Err(crate::DeviceError::OutOfMemory);
901 }
902 }
903
904 Ok(())
905 }
906}
907
908impl crate::Device for super::Device {
909 type A = super::Api;
910
911 unsafe fn create_buffer(
912 &self,
913 desc: &crate::BufferDescriptor,
914 ) -> Result<super::Buffer, crate::DeviceError> {
915 let vk_info = vk::BufferCreateInfo::default()
916 .size(desc.size)
917 .usage(conv::map_buffer_usage(desc.usage))
918 .sharing_mode(vk::SharingMode::EXCLUSIVE);
919
920 let raw = unsafe {
921 self.shared
922 .raw
923 .create_buffer(&vk_info, None)
924 .map_err(super::map_host_device_oom_and_ioca_err)?
925 };
926
927 let mut requirements = unsafe { self.shared.raw.get_buffer_memory_requirements(raw) };
928
929 let is_cpu_read = desc.usage.contains(wgt::BufferUses::MAP_READ);
930 let is_cpu_write = desc.usage.contains(wgt::BufferUses::MAP_WRITE);
931
932 let location = match (is_cpu_read, is_cpu_write) {
933 (true, true) => gpu_allocator::MemoryLocation::CpuToGpu,
934 (true, false) => gpu_allocator::MemoryLocation::GpuToCpu,
935 (false, true) => gpu_allocator::MemoryLocation::CpuToGpu,
936 (false, false) => gpu_allocator::MemoryLocation::GpuOnly,
937 };
938
939 let needs_host_access = is_cpu_read || is_cpu_write;
940
941 self.error_if_would_oom_on_resource_allocation(needs_host_access, requirements.size)
942 .inspect_err(|_| {
943 unsafe { self.shared.raw.destroy_buffer(raw, None) };
944 })?;
945
946 let name = desc.label.unwrap_or("Unlabeled buffer");
947
948 if desc
949 .usage
950 .contains(wgt::BufferUses::ACCELERATION_STRUCTURE_SCRATCH)
951 {
952 requirements.alignment = requirements
954 .alignment
955 .max(self.shared.private_caps.scratch_buffer_alignment as u64);
956 }
957
958 let allocation = self
959 .mem_allocator
960 .lock()
961 .allocate(&gpu_allocator::vulkan::AllocationCreateDesc {
962 name,
963 requirements: vk::MemoryRequirements {
964 memory_type_bits: requirements.memory_type_bits & self.valid_ash_memory_types,
965 ..requirements
966 },
967 location,
968 linear: true, allocation_scheme: gpu_allocator::vulkan::AllocationScheme::GpuAllocatorManaged,
970 })
971 .inspect_err(|_| {
972 unsafe { self.shared.raw.destroy_buffer(raw, None) };
973 })?;
974
975 unsafe {
976 self.shared
977 .raw
978 .bind_buffer_memory(raw, allocation.memory(), allocation.offset())
979 }
980 .map_err(super::map_host_device_oom_and_ioca_err)
981 .inspect_err(|_| {
982 unsafe { self.shared.raw.destroy_buffer(raw, None) };
983 })?;
984
985 if let Some(label) = desc.label {
986 unsafe { self.shared.set_object_name(raw, label) };
987 }
988
989 self.counters.buffer_memory.add(allocation.size() as isize);
990 self.counters.buffers.add(1);
991
992 Ok(super::Buffer {
993 raw,
994 ownership: super::BufferOwnership::Managed(Mutex::new(
995 super::BufferMemoryBacking::Managed(allocation),
996 )),
997 })
998 }
999 unsafe fn destroy_buffer(&self, buffer: super::Buffer) {
1000 match buffer.ownership {
1001 super::BufferOwnership::Managed(allocation) => {
1002 unsafe { self.shared.raw.destroy_buffer(buffer.raw, None) };
1003 let allocation = allocation.into_inner();
1004 self.counters.buffer_memory.sub(allocation.size() as isize);
1005 match allocation {
1006 super::BufferMemoryBacking::Managed(allocation) => {
1007 let result = self.mem_allocator.lock().free(allocation);
1008 if let Err(err) = result {
1009 log::warn!("Failed to free buffer allocation: {err}");
1010 }
1011 }
1012 super::BufferMemoryBacking::VulkanMemory { memory, .. } => unsafe {
1013 self.shared.raw.free_memory(memory, None);
1014 },
1015 }
1016 }
1017 super::BufferOwnership::RawHandle => {
1018 unsafe { self.shared.raw.destroy_buffer(buffer.raw, None) };
1019 }
1020 super::BufferOwnership::External(_drop_guard) => {
1021 }
1024 }
1025
1026 self.counters.buffers.sub(1);
1027 }
1028
1029 unsafe fn add_raw_buffer(&self, _buffer: &super::Buffer) {
1030 self.counters.buffers.add(1);
1031 }
1032
1033 unsafe fn map_buffer(
1034 &self,
1035 buffer: &super::Buffer,
1036 range: crate::MemoryRange,
1037 ) -> Result<crate::BufferMapping, crate::DeviceError> {
1038 let super::BufferOwnership::Managed(ref allocation) = buffer.ownership else {
1039 crate::hal_usage_error("tried to map external buffer")
1040 };
1041 let mut allocation = allocation.lock();
1042 let super::BufferMemoryBacking::Managed(ref mut allocation) = *allocation else {
1043 crate::hal_usage_error("tried to map externally created buffer")
1044 };
1045 let is_coherent = allocation
1046 .memory_properties()
1047 .contains(vk::MemoryPropertyFlags::HOST_COHERENT);
1048 Ok(crate::BufferMapping {
1049 ptr: unsafe {
1050 allocation
1051 .mapped_ptr()
1052 .unwrap()
1053 .cast()
1054 .offset(range.start as isize)
1055 },
1056 is_coherent,
1057 })
1058 }
1059
1060 unsafe fn unmap_buffer(&self, buffer: &super::Buffer) {
1061 match buffer.ownership {
1062 super::BufferOwnership::Managed(_) => {
1063 }
1065 super::BufferOwnership::RawHandle | super::BufferOwnership::External(_) => {
1066 crate::hal_usage_error("tried to unmap external buffer")
1067 }
1068 }
1069 }
1070
1071 unsafe fn flush_mapped_ranges<I>(&self, buffer: &super::Buffer, ranges: I)
1072 where
1073 I: Iterator<Item = crate::MemoryRange>,
1074 {
1075 if let Some(vk_ranges) = self.shared.make_memory_ranges(buffer, ranges) {
1076 unsafe {
1077 self.shared
1078 .raw
1079 .flush_mapped_memory_ranges(
1080 &smallvec::SmallVec::<[vk::MappedMemoryRange; 32]>::from_iter(vk_ranges),
1081 )
1082 }
1083 .unwrap();
1084 }
1085 }
1086 unsafe fn invalidate_mapped_ranges<I>(&self, buffer: &super::Buffer, ranges: I)
1087 where
1088 I: Iterator<Item = crate::MemoryRange>,
1089 {
1090 if let Some(vk_ranges) = self.shared.make_memory_ranges(buffer, ranges) {
1091 unsafe {
1092 self.shared
1093 .raw
1094 .invalidate_mapped_memory_ranges(&smallvec::SmallVec::<
1095 [vk::MappedMemoryRange; 32],
1096 >::from_iter(vk_ranges))
1097 }
1098 .unwrap();
1099 }
1100 }
1101
1102 unsafe fn create_texture(
1103 &self,
1104 desc: &crate::TextureDescriptor,
1105 ) -> Result<super::Texture, crate::DeviceError> {
1106 let image = self.create_image_without_memory(desc, None)?;
1107
1108 self.error_if_would_oom_on_resource_allocation(false, image.requirements.size)
1109 .inspect_err(|_| {
1110 unsafe { self.shared.raw.destroy_image(image.raw, None) };
1111 })?;
1112
1113 let name = desc.label.unwrap_or("Unlabeled texture");
1114
1115 let allocation = self
1116 .mem_allocator
1117 .lock()
1118 .allocate(&gpu_allocator::vulkan::AllocationCreateDesc {
1119 name,
1120 requirements: vk::MemoryRequirements {
1121 memory_type_bits: image.requirements.memory_type_bits
1122 & self.valid_ash_memory_types,
1123 ..image.requirements
1124 },
1125 location: gpu_allocator::MemoryLocation::GpuOnly,
1126 linear: false,
1127 allocation_scheme: gpu_allocator::vulkan::AllocationScheme::GpuAllocatorManaged,
1128 })
1129 .inspect_err(|_| {
1130 unsafe { self.shared.raw.destroy_image(image.raw, None) };
1131 })?;
1132
1133 self.counters.texture_memory.add(allocation.size() as isize);
1134
1135 unsafe {
1136 self.shared
1137 .raw
1138 .bind_image_memory(image.raw, allocation.memory(), allocation.offset())
1139 }
1140 .map_err(super::map_host_device_oom_err)
1141 .inspect_err(|_| {
1142 unsafe { self.shared.raw.destroy_image(image.raw, None) };
1143 })?;
1144
1145 Ok(unsafe {
1146 self.texture_from_raw(
1147 image.raw,
1148 desc,
1149 None,
1150 super::TextureMemory::Allocation(allocation),
1151 )
1152 })
1153 }
1154
1155 unsafe fn destroy_texture(&self, texture: super::Texture) {
1156 if texture.drop_guard.is_none() {
1157 unsafe { self.shared.raw.destroy_image(texture.raw, None) };
1158 }
1159
1160 match texture.memory {
1161 super::TextureMemory::Allocation(allocation) => {
1162 self.counters.texture_memory.sub(allocation.size() as isize);
1163 let result = self.mem_allocator.lock().free(allocation);
1164 if let Err(err) = result {
1165 log::warn!("Failed to free texture allocation: {err}");
1166 }
1167 }
1168 super::TextureMemory::Dedicated(memory) => unsafe {
1169 self.shared.raw.free_memory(memory, None);
1170 },
1171 super::TextureMemory::External => {}
1172 }
1173
1174 self.counters.textures.sub(1);
1175 }
1176
1177 unsafe fn add_raw_texture(&self, _texture: &super::Texture) {
1178 self.counters.textures.add(1);
1179 }
1180
1181 unsafe fn create_texture_view(
1182 &self,
1183 texture: &super::Texture,
1184 desc: &crate::TextureViewDescriptor,
1185 ) -> Result<super::TextureView, crate::DeviceError> {
1186 let subresource_range = conv::map_subresource_range(&desc.range, texture.format);
1187 let raw_format = self.shared.private_caps.map_texture_format(desc.format);
1188 let mut vk_info = vk::ImageViewCreateInfo::default()
1189 .flags(vk::ImageViewCreateFlags::empty())
1190 .image(texture.raw)
1191 .view_type(conv::map_view_dimension(desc.dimension))
1192 .format(raw_format)
1193 .subresource_range(subresource_range);
1194 let layers =
1195 NonZeroU32::new(subresource_range.layer_count).expect("Unexpected zero layer count");
1196
1197 let mut image_view_info;
1198 if self.shared.private_caps.image_view_usage && !desc.usage.is_empty() {
1199 image_view_info =
1200 vk::ImageViewUsageCreateInfo::default().usage(conv::map_texture_usage(desc.usage));
1201 vk_info = vk_info.push_next(&mut image_view_info);
1202 }
1203
1204 let raw = unsafe { self.shared.raw.create_image_view(&vk_info, None) }
1205 .map_err(super::map_host_device_oom_and_ioca_err)?;
1206
1207 if let Some(label) = desc.label {
1208 unsafe { self.shared.set_object_name(raw, label) };
1209 }
1210
1211 let identity = self.shared.texture_view_identity_factory.next();
1212
1213 self.counters.texture_views.add(1);
1214
1215 Ok(super::TextureView {
1216 raw_texture: texture.raw,
1217 raw,
1218 _layers: layers,
1219 format: desc.format,
1220 raw_format,
1221 base_mip_level: desc.range.base_mip_level,
1222 dimension: desc.dimension,
1223 texture_identity: texture.identity,
1224 view_identity: identity,
1225 })
1226 }
1227 unsafe fn destroy_texture_view(&self, view: super::TextureView) {
1228 unsafe { self.shared.raw.destroy_image_view(view.raw, None) };
1229
1230 self.counters.texture_views.sub(1);
1231 }
1232
1233 unsafe fn create_sampler(
1234 &self,
1235 desc: &crate::SamplerDescriptor,
1236 ) -> Result<super::Sampler, crate::DeviceError> {
1237 let mut create_info = vk::SamplerCreateInfo::default()
1238 .flags(vk::SamplerCreateFlags::empty())
1239 .mag_filter(conv::map_filter_mode(desc.mag_filter))
1240 .min_filter(conv::map_filter_mode(desc.min_filter))
1241 .mipmap_mode(conv::map_mip_filter_mode(desc.mipmap_filter))
1242 .address_mode_u(conv::map_address_mode(desc.address_modes[0]))
1243 .address_mode_v(conv::map_address_mode(desc.address_modes[1]))
1244 .address_mode_w(conv::map_address_mode(desc.address_modes[2]))
1245 .min_lod(desc.lod_clamp.start)
1246 .max_lod(desc.lod_clamp.end);
1247
1248 if let Some(fun) = desc.compare {
1249 create_info = create_info
1250 .compare_enable(true)
1251 .compare_op(conv::map_comparison(fun));
1252 }
1253
1254 if desc.anisotropy_clamp != 1 {
1255 create_info = create_info
1258 .anisotropy_enable(true)
1259 .max_anisotropy(desc.anisotropy_clamp as f32);
1260 }
1261
1262 if let Some(color) = desc.border_color {
1263 create_info = create_info.border_color(conv::map_border_color(color));
1264 }
1265
1266 let mut sampler_cache_guard = self.shared.sampler_cache.lock();
1267
1268 let raw = sampler_cache_guard.create_sampler(&self.shared.raw, create_info)?;
1269
1270 if let Some(label) = desc.label {
1274 unsafe { self.shared.set_object_name(raw, label) };
1277 }
1278
1279 drop(sampler_cache_guard);
1280
1281 self.counters.samplers.add(1);
1282
1283 Ok(super::Sampler { raw, create_info })
1284 }
1285 unsafe fn destroy_sampler(&self, sampler: super::Sampler) {
1286 self.shared.sampler_cache.lock().destroy_sampler(
1287 &self.shared.raw,
1288 sampler.create_info,
1289 sampler.raw,
1290 );
1291
1292 self.counters.samplers.sub(1);
1293 }
1294
1295 unsafe fn create_command_encoder(
1296 &self,
1297 desc: &crate::CommandEncoderDescriptor<super::Queue>,
1298 ) -> Result<super::CommandEncoder, crate::DeviceError> {
1299 let vk_info = vk::CommandPoolCreateInfo::default()
1300 .queue_family_index(desc.queue.family_index)
1301 .flags(vk::CommandPoolCreateFlags::TRANSIENT);
1302
1303 let raw = unsafe {
1304 self.shared
1305 .raw
1306 .create_command_pool(&vk_info, None)
1307 .map_err(super::map_host_device_oom_err)?
1308 };
1309
1310 self.counters.command_encoders.add(1);
1311
1312 Ok(super::CommandEncoder {
1313 raw,
1314 device: Arc::clone(&self.shared),
1315 active: vk::CommandBuffer::null(),
1316 bind_point: vk::PipelineBindPoint::default(),
1317 temp: super::Temp::default(),
1318 free: Vec::new(),
1319 discarded: Vec::new(),
1320 rpass_debug_marker_active: false,
1321 end_of_pass_timer_query: None,
1322 framebuffers: Default::default(),
1323 temp_texture_views: Default::default(),
1324 counters: Arc::clone(&self.counters),
1325 current_pipeline_is_multiview: false,
1326 })
1327 }
1328
1329 unsafe fn create_bind_group_layout(
1330 &self,
1331 desc: &crate::BindGroupLayoutDescriptor,
1332 ) -> Result<super::BindGroupLayout, crate::DeviceError> {
1333 let mut vk_bindings = Vec::new();
1338 let mut binding_flags = Vec::new();
1339 let mut binding_map = Vec::new();
1340 let mut next_binding = 0;
1341 let mut contains_binding_arrays = false;
1342 let mut desc_count = DescriptorCounts::default();
1343 for entry in desc.entries {
1344 if entry.count.is_some() {
1345 contains_binding_arrays = true;
1346 }
1347
1348 let partially_bound = desc
1349 .flags
1350 .contains(crate::BindGroupLayoutFlags::PARTIALLY_BOUND);
1351 let mut flags = vk::DescriptorBindingFlags::empty();
1352 if partially_bound && entry.count.is_some() {
1353 flags |= vk::DescriptorBindingFlags::PARTIALLY_BOUND;
1354 }
1355 if entry.count.is_some() {
1356 flags |= vk::DescriptorBindingFlags::UPDATE_AFTER_BIND;
1357 }
1358
1359 let count = entry.count.map_or(1, |c| c.get());
1360 match entry.ty {
1361 wgt::BindingType::ExternalTexture => unimplemented!(),
1362 _ => {
1363 vk_bindings.push(vk::DescriptorSetLayoutBinding {
1364 binding: next_binding,
1365 descriptor_type: conv::map_binding_type(entry.ty),
1366 descriptor_count: count,
1367 stage_flags: conv::map_shader_stage(entry.visibility),
1368 p_immutable_samplers: ptr::null(),
1369 _marker: Default::default(),
1370 });
1371 binding_flags.push(flags);
1372 binding_map.push((
1373 entry.binding,
1374 super::BindingInfo {
1375 binding: next_binding,
1376 binding_array_size: entry.count,
1377 },
1378 ));
1379 next_binding += 1;
1380 }
1381 }
1382
1383 match entry.ty {
1384 wgt::BindingType::Buffer {
1385 ty,
1386 has_dynamic_offset,
1387 ..
1388 } => match ty {
1389 wgt::BufferBindingType::Uniform => {
1390 if has_dynamic_offset {
1391 desc_count.uniform_buffer_dynamic += count;
1392 } else {
1393 desc_count.uniform_buffer += count;
1394 }
1395 }
1396 wgt::BufferBindingType::Storage { .. } => {
1397 if has_dynamic_offset {
1398 desc_count.storage_buffer_dynamic += count;
1399 } else {
1400 desc_count.storage_buffer += count;
1401 }
1402 }
1403 },
1404 wgt::BindingType::Sampler { .. } => {
1405 desc_count.sampler += count;
1406 }
1407 wgt::BindingType::Texture { .. } => {
1408 desc_count.sampled_image += count;
1409 }
1410 wgt::BindingType::StorageTexture { .. } => {
1411 desc_count.storage_image += count;
1412 }
1413 wgt::BindingType::AccelerationStructure { .. } => {
1414 desc_count.acceleration_structure += count;
1415 }
1416 wgt::BindingType::ExternalTexture => unimplemented!(),
1417 }
1418 }
1419
1420 let vk_info = vk::DescriptorSetLayoutCreateInfo::default()
1421 .bindings(&vk_bindings)
1422 .flags(if contains_binding_arrays {
1423 vk::DescriptorSetLayoutCreateFlags::UPDATE_AFTER_BIND_POOL
1424 } else {
1425 vk::DescriptorSetLayoutCreateFlags::empty()
1426 });
1427
1428 let mut binding_flag_info =
1429 vk::DescriptorSetLayoutBindingFlagsCreateInfo::default().binding_flags(&binding_flags);
1430
1431 let vk_info = vk_info.push_next(&mut binding_flag_info);
1432
1433 let raw = unsafe {
1434 self.shared
1435 .raw
1436 .create_descriptor_set_layout(&vk_info, None)
1437 .map_err(super::map_host_device_oom_err)?
1438 };
1439
1440 if let Some(label) = desc.label {
1441 unsafe { self.shared.set_object_name(raw, label) };
1442 }
1443
1444 let layout = super::BindGroupLayout {
1445 raw,
1446 desc_count,
1447 entries: desc.entries.into(),
1448 binding_map,
1449 contains_binding_arrays,
1450 };
1451
1452 let result = self
1453 .desc_allocator
1454 .lock()
1455 .register_layout(&self.shared.raw, &layout);
1456 if let Err(err) = result {
1457 unsafe {
1458 self.shared
1459 .raw
1460 .destroy_descriptor_set_layout(layout.raw, None)
1461 };
1462 return Err(err);
1463 }
1464
1465 self.counters.bind_group_layouts.add(1);
1466
1467 Ok(layout)
1468 }
1469 unsafe fn destroy_bind_group_layout(&self, bg_layout: super::BindGroupLayout) {
1470 self.desc_allocator
1471 .lock()
1472 .unregister_layout(&self.shared.raw, &bg_layout);
1473
1474 unsafe {
1475 self.shared
1476 .raw
1477 .destroy_descriptor_set_layout(bg_layout.raw, None)
1478 };
1479
1480 self.counters.bind_group_layouts.sub(1);
1481 }
1482
1483 unsafe fn create_pipeline_layout(
1484 &self,
1485 desc: &crate::PipelineLayoutDescriptor<super::BindGroupLayout>,
1486 ) -> Result<super::PipelineLayout, crate::DeviceError> {
1487 let vk_set_layouts = desc
1489 .bind_group_layouts
1490 .iter()
1491 .map(|bgl| match bgl {
1492 Some(bgl) => bgl.raw,
1493 None => {
1494 self.shared.empty_descriptor_set_layout
1502 }
1503 })
1504 .collect::<Vec<_>>();
1505 let vk_immediates_ranges: Option<vk::PushConstantRange> = if desc.immediate_size != 0 {
1506 Some(vk::PushConstantRange {
1507 stage_flags: vk::ShaderStageFlags::ALL,
1508 offset: 0,
1509 size: desc.immediate_size,
1510 })
1511 } else {
1512 None
1513 };
1514
1515 let vk_info = vk::PipelineLayoutCreateInfo::default()
1516 .flags(vk::PipelineLayoutCreateFlags::empty())
1517 .set_layouts(&vk_set_layouts)
1518 .push_constant_ranges(vk_immediates_ranges.as_slice());
1519
1520 let raw = {
1521 profiling::scope!("vkCreatePipelineLayout");
1522 unsafe {
1523 self.shared
1524 .raw
1525 .create_pipeline_layout(&vk_info, None)
1526 .map_err(super::map_host_device_oom_err)?
1527 }
1528 };
1529
1530 if let Some(label) = desc.label {
1531 unsafe { self.shared.set_object_name(raw, label) };
1532 }
1533
1534 let mut binding_map = BTreeMap::new();
1535 for (group, layout) in desc.bind_group_layouts.iter().enumerate() {
1536 let Some(layout) = layout else {
1537 continue;
1538 };
1539
1540 for &(binding, binding_info) in &layout.binding_map {
1541 binding_map.insert(
1542 naga::ResourceBinding {
1543 group: group as u32,
1544 binding,
1545 },
1546 naga::back::spv::BindingInfo {
1547 descriptor_set: group as u32,
1548 binding: binding_info.binding,
1549 binding_array_size: binding_info.binding_array_size.map(NonZeroU32::get),
1550 },
1551 );
1552 }
1553 }
1554
1555 self.counters.pipeline_layouts.add(1);
1556 Ok(super::PipelineLayout { raw, binding_map })
1557 }
1558 unsafe fn destroy_pipeline_layout(&self, pipeline_layout: super::PipelineLayout) {
1559 unsafe {
1560 self.shared
1561 .raw
1562 .destroy_pipeline_layout(pipeline_layout.raw, None)
1563 };
1564
1565 self.counters.pipeline_layouts.sub(1);
1566 }
1567
1568 unsafe fn create_bind_group(
1569 &self,
1570 desc: &crate::BindGroupDescriptor<
1571 super::BindGroupLayout,
1572 super::Buffer,
1573 super::Sampler,
1574 super::TextureView,
1575 super::AccelerationStructure,
1576 >,
1577 ) -> Result<super::BindGroup, crate::DeviceError> {
1578 let set = unsafe {
1579 self.desc_allocator
1580 .lock()
1581 .alloc(&self.shared.raw, desc.layout)?
1582 };
1583
1584 if let Some(label) = desc.label {
1585 unsafe { self.shared.set_object_name(set.raw(), label) };
1586 }
1587
1588 struct ExtendStack<'a, T> {
1595 remainder: &'a mut [MaybeUninit<T>],
1596 }
1597
1598 impl<'a, T> ExtendStack<'a, T> {
1599 fn from_vec_capacity(vec: &'a mut Vec<T>) -> Self {
1600 Self {
1601 remainder: vec.spare_capacity_mut(),
1602 }
1603 }
1604
1605 fn extend_one(self, value: T) -> (Self, &'a mut T) {
1606 let (to_init, remainder) = self.remainder.split_first_mut().unwrap();
1607 let init = to_init.write(value);
1608 (Self { remainder }, init)
1609 }
1610
1611 fn extend(
1612 self,
1613 iter: impl IntoIterator<Item = T> + ExactSizeIterator,
1614 ) -> (Self, &'a mut [T]) {
1615 let (to_init, remainder) = self.remainder.split_at_mut(iter.len());
1616
1617 for (value, to_init) in iter.into_iter().zip(to_init.iter_mut()) {
1618 to_init.write(value);
1619 }
1620
1621 let init = {
1624 unsafe { mem::transmute::<&mut [MaybeUninit<T>], &mut [T]>(to_init) }
1631 };
1632 (Self { remainder }, init)
1633 }
1634 }
1635
1636 let mut writes = Vec::with_capacity(desc.entries.len());
1637 let mut buffer_infos = Vec::with_capacity(desc.buffers.len());
1638 let mut buffer_infos = ExtendStack::from_vec_capacity(&mut buffer_infos);
1639 let mut image_infos = Vec::with_capacity(desc.samplers.len() + desc.textures.len());
1640 let mut image_infos = ExtendStack::from_vec_capacity(&mut image_infos);
1641 let mut acceleration_structure_infos =
1646 Vec::with_capacity(desc.acceleration_structures.len());
1647 let mut acceleration_structure_infos =
1648 ExtendStack::from_vec_capacity(&mut acceleration_structure_infos);
1649 let mut raw_acceleration_structures =
1650 Vec::with_capacity(desc.acceleration_structures.len());
1651 let mut raw_acceleration_structures =
1652 ExtendStack::from_vec_capacity(&mut raw_acceleration_structures);
1653
1654 let layout_and_entry_iter = desc.entries.iter().map(|entry| {
1655 let layout = desc
1656 .layout
1657 .entries
1658 .iter()
1659 .find(|layout_entry| layout_entry.binding == entry.binding)
1660 .expect("internal error: no layout entry found with binding slot");
1661 (layout, entry)
1662 });
1663 let mut next_binding = 0;
1664 for (layout, entry) in layout_and_entry_iter {
1665 let write = vk::WriteDescriptorSet::default().dst_set(set.raw());
1666
1667 match layout.ty {
1668 wgt::BindingType::Sampler(_) => {
1669 let start = entry.resource_index;
1670 let end = start + entry.count;
1671 let local_image_infos;
1672 (image_infos, local_image_infos) =
1673 image_infos.extend(desc.samplers[start as usize..end as usize].iter().map(
1674 |sampler| vk::DescriptorImageInfo::default().sampler(sampler.raw),
1675 ));
1676 writes.push(
1677 write
1678 .dst_binding(next_binding)
1679 .descriptor_type(conv::map_binding_type(layout.ty))
1680 .image_info(local_image_infos),
1681 );
1682 next_binding += 1;
1683 }
1684 wgt::BindingType::Texture { .. } | wgt::BindingType::StorageTexture { .. } => {
1685 let start = entry.resource_index;
1686 let end = start + entry.count;
1687 let local_image_infos;
1688 (image_infos, local_image_infos) =
1689 image_infos.extend(desc.textures[start as usize..end as usize].iter().map(
1690 |binding| {
1691 let layout =
1692 conv::derive_image_layout(binding.usage, binding.view.format);
1693 vk::DescriptorImageInfo::default()
1694 .image_view(binding.view.raw)
1695 .image_layout(layout)
1696 },
1697 ));
1698 writes.push(
1699 write
1700 .dst_binding(next_binding)
1701 .descriptor_type(conv::map_binding_type(layout.ty))
1702 .image_info(local_image_infos),
1703 );
1704 next_binding += 1;
1705 }
1706 wgt::BindingType::Buffer { .. } => {
1707 let start = entry.resource_index;
1708 let end = start + entry.count;
1709 let local_buffer_infos;
1710 (buffer_infos, local_buffer_infos) =
1711 buffer_infos.extend(desc.buffers[start as usize..end as usize].iter().map(
1712 |binding| {
1713 vk::DescriptorBufferInfo::default()
1714 .buffer(binding.buffer.raw)
1715 .offset(binding.offset)
1716 .range(
1717 binding.size.map_or(vk::WHOLE_SIZE, wgt::BufferSize::get),
1718 )
1719 },
1720 ));
1721 writes.push(
1722 write
1723 .dst_binding(next_binding)
1724 .descriptor_type(conv::map_binding_type(layout.ty))
1725 .buffer_info(local_buffer_infos),
1726 );
1727 next_binding += 1;
1728 }
1729 wgt::BindingType::AccelerationStructure { .. } => {
1730 let start = entry.resource_index;
1731 let end = start + entry.count;
1732
1733 let local_raw_acceleration_structures;
1734 (
1735 raw_acceleration_structures,
1736 local_raw_acceleration_structures,
1737 ) = raw_acceleration_structures.extend(
1738 desc.acceleration_structures[start as usize..end as usize]
1739 .iter()
1740 .map(|acceleration_structure| acceleration_structure.raw),
1741 );
1742
1743 let local_acceleration_structure_infos;
1744 (
1745 acceleration_structure_infos,
1746 local_acceleration_structure_infos,
1747 ) = acceleration_structure_infos.extend_one(
1748 vk::WriteDescriptorSetAccelerationStructureKHR::default()
1749 .acceleration_structures(local_raw_acceleration_structures),
1750 );
1751
1752 writes.push(
1753 write
1754 .dst_binding(next_binding)
1755 .descriptor_type(conv::map_binding_type(layout.ty))
1756 .descriptor_count(entry.count)
1757 .push_next(local_acceleration_structure_infos),
1758 );
1759 next_binding += 1;
1760 }
1761 wgt::BindingType::ExternalTexture => unimplemented!(),
1762 }
1763 }
1764
1765 unsafe { self.shared.raw.update_descriptor_sets(&writes, &[]) };
1766
1767 self.counters.bind_groups.add(1);
1768
1769 Ok(super::BindGroup { set })
1770 }
1771
1772 unsafe fn destroy_bind_group(&self, group: super::BindGroup) {
1773 unsafe { self.desc_allocator.lock().free(&self.shared.raw, group.set) };
1774
1775 self.counters.bind_groups.sub(1);
1776 }
1777
1778 unsafe fn create_shader_module(
1779 &self,
1780 desc: &crate::ShaderModuleDescriptor,
1781 shader: crate::ShaderInput,
1782 ) -> Result<super::ShaderModule, crate::ShaderError> {
1783 let shader_module = match shader {
1784 crate::ShaderInput::Naga(naga_shader)
1785 if self
1786 .shared
1787 .workarounds
1788 .contains(super::Workarounds::SEPARATE_ENTRY_POINTS)
1789 || !naga_shader.module.overrides.is_empty() =>
1790 {
1791 super::ShaderModule::Intermediate {
1792 naga_shader,
1793 runtime_checks: desc.runtime_checks,
1794 }
1795 }
1796 crate::ShaderInput::Naga(naga_shader) => {
1797 let mut naga_options = self.naga_options.clone();
1798 naga_options.debug_info =
1799 naga_shader
1800 .debug_source
1801 .as_ref()
1802 .map(|d| naga::back::spv::DebugInfo {
1803 source_code: d.source_code.as_ref(),
1804 file_name: d.file_name.as_ref(),
1805 language: naga::back::spv::SourceLanguage::WGSL,
1806 });
1807 if !desc.runtime_checks.bounds_checks {
1808 naga_options.bounds_check_policies = naga::proc::BoundsCheckPolicies {
1809 index: naga::proc::BoundsCheckPolicy::Unchecked,
1810 buffer: naga::proc::BoundsCheckPolicy::Unchecked,
1811 image_load: naga::proc::BoundsCheckPolicy::Unchecked,
1812 binding_array: naga::proc::BoundsCheckPolicy::Unchecked,
1813 };
1814 }
1815 let spv = naga::back::spv::write_vec(
1816 &naga_shader.module,
1817 &naga_shader.info,
1818 &naga_options,
1819 None,
1820 )
1821 .map_err(|e| crate::ShaderError::Compilation(format!("{e}")))?;
1822 super::ShaderModule::Raw(self.create_shader_module_impl(&spv, &desc.label)?)
1823 }
1824 crate::ShaderInput::SpirV(data) => {
1825 super::ShaderModule::Raw(self.create_shader_module_impl(data, &desc.label)?)
1826 }
1827 crate::ShaderInput::MetalLib { .. }
1828 | crate::ShaderInput::Msl { .. }
1829 | crate::ShaderInput::Dxil { .. }
1830 | crate::ShaderInput::Hlsl { .. }
1831 | crate::ShaderInput::Glsl { .. } => unreachable!(),
1832 };
1833
1834 self.counters.shader_modules.add(1);
1835
1836 Ok(shader_module)
1837 }
1838
1839 unsafe fn destroy_shader_module(&self, module: super::ShaderModule) {
1840 match module {
1841 super::ShaderModule::Raw(raw) => {
1842 unsafe { self.shared.raw.destroy_shader_module(raw, None) };
1843 }
1844 super::ShaderModule::Intermediate { .. } => {}
1845 }
1846
1847 self.counters.shader_modules.sub(1);
1848 }
1849
1850 unsafe fn create_render_pipeline(
1851 &self,
1852 desc: &crate::RenderPipelineDescriptor<
1853 super::PipelineLayout,
1854 super::ShaderModule,
1855 super::PipelineCache,
1856 >,
1857 ) -> Result<super::RenderPipeline, crate::PipelineError> {
1858 let dynamic_states = [
1859 vk::DynamicState::VIEWPORT,
1860 vk::DynamicState::SCISSOR,
1861 vk::DynamicState::BLEND_CONSTANTS,
1862 vk::DynamicState::STENCIL_REFERENCE,
1863 ];
1864 let mut compatible_rp_key = super::RenderPassKey {
1865 sample_count: desc.multisample.count,
1866 multiview_mask: desc.multiview_mask,
1867 ..Default::default()
1868 };
1869 let mut stages = ArrayVec::<_, { crate::MAX_CONCURRENT_SHADER_STAGES }>::new();
1870 let mut vertex_buffers = Vec::new();
1871 let mut vertex_attributes = Vec::new();
1872
1873 if let crate::VertexProcessor::Standard {
1874 vertex_buffers: desc_vertex_buffers,
1875 vertex_stage: _,
1876 } = &desc.vertex_processor
1877 {
1878 vertex_buffers = Vec::with_capacity(desc_vertex_buffers.len());
1879 for (i, vb) in desc_vertex_buffers.iter().enumerate() {
1880 let Some(vb) = vb else {
1881 continue;
1882 };
1883 vertex_buffers.push(vk::VertexInputBindingDescription {
1884 binding: i as u32,
1885 stride: vb.array_stride as u32,
1886 input_rate: match vb.step_mode {
1887 wgt::VertexStepMode::Vertex => vk::VertexInputRate::VERTEX,
1888 wgt::VertexStepMode::Instance => vk::VertexInputRate::INSTANCE,
1889 },
1890 });
1891 for at in vb.attributes {
1892 vertex_attributes.push(vk::VertexInputAttributeDescription {
1893 location: at.shader_location,
1894 binding: i as u32,
1895 format: conv::map_vertex_format(at.format),
1896 offset: at.offset as u32,
1897 });
1898 }
1899 }
1900 }
1901
1902 let vk_vertex_input = vk::PipelineVertexInputStateCreateInfo::default()
1903 .vertex_binding_descriptions(&vertex_buffers)
1904 .vertex_attribute_descriptions(&vertex_attributes);
1905
1906 let vk_input_assembly = vk::PipelineInputAssemblyStateCreateInfo::default()
1907 .topology(conv::map_topology(desc.primitive.topology))
1908 .primitive_restart_enable(desc.primitive.strip_index_format.is_some());
1909
1910 let mut compiled_vs = None;
1911 let mut compiled_ms = None;
1912 let mut compiled_ts = None;
1913 match &desc.vertex_processor {
1914 crate::VertexProcessor::Standard {
1915 vertex_buffers: _,
1916 vertex_stage,
1917 } => {
1918 compiled_vs = Some(self.compile_stage(
1919 vertex_stage,
1920 naga::ShaderStage::Vertex,
1921 &desc.layout.binding_map,
1922 )?);
1923 stages.push(compiled_vs.as_ref().unwrap().create_info);
1924 }
1925 crate::VertexProcessor::Mesh {
1926 task_stage,
1927 mesh_stage,
1928 } => {
1929 if let Some(t) = task_stage.as_ref() {
1930 compiled_ts = Some(self.compile_stage(
1931 t,
1932 naga::ShaderStage::Task,
1933 &desc.layout.binding_map,
1934 )?);
1935 stages.push(compiled_ts.as_ref().unwrap().create_info);
1936 }
1937 compiled_ms = Some(self.compile_stage(
1938 mesh_stage,
1939 naga::ShaderStage::Mesh,
1940 &desc.layout.binding_map,
1941 )?);
1942 stages.push(compiled_ms.as_ref().unwrap().create_info);
1943 }
1944 }
1945 let compiled_fs = match desc.fragment_stage {
1946 Some(ref stage) => {
1947 let compiled = self.compile_stage(
1948 stage,
1949 naga::ShaderStage::Fragment,
1950 &desc.layout.binding_map,
1951 )?;
1952 stages.push(compiled.create_info);
1953 Some(compiled)
1954 }
1955 None => None,
1956 };
1957
1958 let mut vk_rasterization = vk::PipelineRasterizationStateCreateInfo::default()
1959 .polygon_mode(conv::map_polygon_mode(desc.primitive.polygon_mode))
1960 .front_face(conv::map_front_face(desc.primitive.front_face))
1961 .line_width(1.0)
1962 .depth_clamp_enable(desc.primitive.unclipped_depth);
1963 if let Some(face) = desc.primitive.cull_mode {
1964 vk_rasterization = vk_rasterization.cull_mode(conv::map_cull_face(face))
1965 }
1966 let mut vk_rasterization_conservative_state =
1967 vk::PipelineRasterizationConservativeStateCreateInfoEXT::default()
1968 .conservative_rasterization_mode(
1969 vk::ConservativeRasterizationModeEXT::OVERESTIMATE,
1970 );
1971 if desc.primitive.conservative {
1972 vk_rasterization = vk_rasterization.push_next(&mut vk_rasterization_conservative_state);
1973 }
1974
1975 let mut vk_depth_stencil = vk::PipelineDepthStencilStateCreateInfo::default();
1976 if let Some(ref ds) = desc.depth_stencil {
1977 let vk_format = self.shared.private_caps.map_texture_format(ds.format);
1978 let vk_layout = if ds.is_read_only(desc.primitive.cull_mode) {
1979 vk::ImageLayout::DEPTH_STENCIL_READ_ONLY_OPTIMAL
1980 } else {
1981 vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL
1982 };
1983 compatible_rp_key.depth_stencil = Some(super::DepthStencilAttachmentKey {
1984 base: super::AttachmentKey::compatible(vk_format, vk_layout),
1985 stencil_ops: crate::AttachmentOps::all(),
1986 });
1987
1988 if ds.is_depth_enabled() {
1989 vk_depth_stencil = vk_depth_stencil
1990 .depth_test_enable(true)
1991 .depth_write_enable(ds.depth_write_enabled.unwrap_or_default())
1992 .depth_compare_op(conv::map_comparison(ds.depth_compare.unwrap_or_default()));
1993 }
1994 if ds.stencil.is_enabled() {
1995 let s = &ds.stencil;
1996 let front = conv::map_stencil_face(&s.front, s.read_mask, s.write_mask);
1997 let back = conv::map_stencil_face(&s.back, s.read_mask, s.write_mask);
1998 vk_depth_stencil = vk_depth_stencil
1999 .stencil_test_enable(true)
2000 .front(front)
2001 .back(back);
2002 }
2003
2004 if ds.bias.is_enabled() {
2005 vk_rasterization = vk_rasterization
2006 .depth_bias_enable(true)
2007 .depth_bias_constant_factor(ds.bias.constant as f32)
2008 .depth_bias_clamp(ds.bias.clamp)
2009 .depth_bias_slope_factor(ds.bias.slope_scale);
2010 }
2011 }
2012
2013 let vk_viewport = vk::PipelineViewportStateCreateInfo::default()
2014 .flags(vk::PipelineViewportStateCreateFlags::empty())
2015 .scissor_count(1)
2016 .viewport_count(1);
2017
2018 let vk_sample_mask = [
2019 desc.multisample.mask as u32,
2020 (desc.multisample.mask >> 32) as u32,
2021 ];
2022 let vk_multisample = vk::PipelineMultisampleStateCreateInfo::default()
2023 .rasterization_samples(vk::SampleCountFlags::from_raw(desc.multisample.count))
2024 .alpha_to_coverage_enable(desc.multisample.alpha_to_coverage_enabled)
2025 .sample_mask(&vk_sample_mask);
2026
2027 let mut vk_attachments = Vec::with_capacity(desc.color_targets.len());
2028 for cat in desc.color_targets {
2029 let (key, attarchment) = if let Some(cat) = cat.as_ref() {
2030 let mut vk_attachment = vk::PipelineColorBlendAttachmentState::default()
2031 .color_write_mask(vk::ColorComponentFlags::from_raw(cat.write_mask.bits()));
2032 if let Some(ref blend) = cat.blend {
2033 let (color_op, color_src, color_dst) = conv::map_blend_component(&blend.color);
2034 let (alpha_op, alpha_src, alpha_dst) = conv::map_blend_component(&blend.alpha);
2035 vk_attachment = vk_attachment
2036 .blend_enable(true)
2037 .color_blend_op(color_op)
2038 .src_color_blend_factor(color_src)
2039 .dst_color_blend_factor(color_dst)
2040 .alpha_blend_op(alpha_op)
2041 .src_alpha_blend_factor(alpha_src)
2042 .dst_alpha_blend_factor(alpha_dst);
2043 }
2044
2045 let vk_format = self.shared.private_caps.map_texture_format(cat.format);
2046 (
2047 Some(super::ColorAttachmentKey {
2048 base: super::AttachmentKey::compatible(
2049 vk_format,
2050 vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL,
2051 ),
2052 resolve: None,
2053 }),
2054 vk_attachment,
2055 )
2056 } else {
2057 (None, vk::PipelineColorBlendAttachmentState::default())
2058 };
2059
2060 compatible_rp_key.colors.push(key);
2061 vk_attachments.push(attarchment);
2062 }
2063
2064 let vk_color_blend =
2065 vk::PipelineColorBlendStateCreateInfo::default().attachments(&vk_attachments);
2066
2067 let vk_dynamic_state =
2068 vk::PipelineDynamicStateCreateInfo::default().dynamic_states(&dynamic_states);
2069
2070 let raw_pass = self.shared.make_render_pass(compatible_rp_key)?;
2071
2072 let vk_infos = [{
2073 vk::GraphicsPipelineCreateInfo::default()
2074 .layout(desc.layout.raw)
2075 .stages(&stages)
2076 .vertex_input_state(&vk_vertex_input)
2077 .input_assembly_state(&vk_input_assembly)
2078 .rasterization_state(&vk_rasterization)
2079 .viewport_state(&vk_viewport)
2080 .multisample_state(&vk_multisample)
2081 .depth_stencil_state(&vk_depth_stencil)
2082 .color_blend_state(&vk_color_blend)
2083 .dynamic_state(&vk_dynamic_state)
2084 .render_pass(raw_pass)
2085 }];
2086
2087 let pipeline_cache = desc
2088 .cache
2089 .map(|it| it.raw)
2090 .unwrap_or(vk::PipelineCache::null());
2091
2092 let mut raw_vec = {
2093 profiling::scope!("vkCreateGraphicsPipelines");
2094 unsafe {
2095 self.shared
2096 .raw
2097 .create_graphics_pipelines(pipeline_cache, &vk_infos, None)
2098 .map_err(|(_, e)| super::map_pipeline_err(e))
2099 }?
2100 };
2101
2102 let raw = raw_vec.pop().unwrap();
2103 if let Some(label) = desc.label {
2104 unsafe { self.shared.set_object_name(raw, label) };
2105 }
2106
2107 if let Some(CompiledStage {
2108 temp_raw_module: Some(raw_module),
2109 ..
2110 }) = compiled_vs
2111 {
2112 unsafe { self.shared.raw.destroy_shader_module(raw_module, None) };
2113 }
2114 if let Some(CompiledStage {
2115 temp_raw_module: Some(raw_module),
2116 ..
2117 }) = compiled_ts
2118 {
2119 unsafe { self.shared.raw.destroy_shader_module(raw_module, None) };
2120 }
2121 if let Some(CompiledStage {
2122 temp_raw_module: Some(raw_module),
2123 ..
2124 }) = compiled_ms
2125 {
2126 unsafe { self.shared.raw.destroy_shader_module(raw_module, None) };
2127 }
2128 if let Some(CompiledStage {
2129 temp_raw_module: Some(raw_module),
2130 ..
2131 }) = compiled_fs
2132 {
2133 unsafe { self.shared.raw.destroy_shader_module(raw_module, None) };
2134 }
2135
2136 self.counters.render_pipelines.add(1);
2137
2138 Ok(super::RenderPipeline {
2139 raw,
2140 is_multiview: desc.multiview_mask.is_some(),
2141 })
2142 }
2143
2144 unsafe fn destroy_render_pipeline(&self, pipeline: super::RenderPipeline) {
2145 unsafe { self.shared.raw.destroy_pipeline(pipeline.raw, None) };
2146
2147 self.counters.render_pipelines.sub(1);
2148 }
2149
2150 unsafe fn create_compute_pipeline(
2151 &self,
2152 desc: &crate::ComputePipelineDescriptor<
2153 super::PipelineLayout,
2154 super::ShaderModule,
2155 super::PipelineCache,
2156 >,
2157 ) -> Result<super::ComputePipeline, crate::PipelineError> {
2158 let compiled = self.compile_stage(
2159 &desc.stage,
2160 naga::ShaderStage::Compute,
2161 &desc.layout.binding_map,
2162 )?;
2163
2164 let vk_infos = [{
2165 vk::ComputePipelineCreateInfo::default()
2166 .layout(desc.layout.raw)
2167 .stage(compiled.create_info)
2168 }];
2169
2170 let pipeline_cache = desc
2171 .cache
2172 .map(|it| it.raw)
2173 .unwrap_or(vk::PipelineCache::null());
2174
2175 let mut raw_vec = {
2176 profiling::scope!("vkCreateComputePipelines");
2177 unsafe {
2178 self.shared
2179 .raw
2180 .create_compute_pipelines(pipeline_cache, &vk_infos, None)
2181 .map_err(|(_, e)| super::map_pipeline_err(e))
2182 }?
2183 };
2184
2185 let raw = raw_vec.pop().unwrap();
2186 if let Some(label) = desc.label {
2187 unsafe { self.shared.set_object_name(raw, label) };
2188 }
2189
2190 if let Some(raw_module) = compiled.temp_raw_module {
2191 unsafe { self.shared.raw.destroy_shader_module(raw_module, None) };
2192 }
2193
2194 self.counters.compute_pipelines.add(1);
2195
2196 Ok(super::ComputePipeline { raw })
2197 }
2198
2199 unsafe fn destroy_compute_pipeline(&self, pipeline: super::ComputePipeline) {
2200 unsafe { self.shared.raw.destroy_pipeline(pipeline.raw, None) };
2201
2202 self.counters.compute_pipelines.sub(1);
2203 }
2204
2205 unsafe fn create_pipeline_cache(
2206 &self,
2207 desc: &crate::PipelineCacheDescriptor<'_>,
2208 ) -> Result<super::PipelineCache, crate::PipelineCacheError> {
2209 let mut info = vk::PipelineCacheCreateInfo::default();
2210 if let Some(data) = desc.data {
2211 info = info.initial_data(data)
2212 }
2213 profiling::scope!("vkCreatePipelineCache");
2214 let raw = unsafe { self.shared.raw.create_pipeline_cache(&info, None) }
2215 .map_err(super::map_host_device_oom_err)?;
2216
2217 Ok(super::PipelineCache { raw })
2218 }
2219 fn pipeline_cache_validation_key(&self) -> Option<[u8; 16]> {
2220 Some(self.shared.pipeline_cache_validation_key)
2221 }
2222 unsafe fn destroy_pipeline_cache(&self, cache: super::PipelineCache) {
2223 unsafe { self.shared.raw.destroy_pipeline_cache(cache.raw, None) }
2224 }
2225 unsafe fn create_query_set(
2226 &self,
2227 desc: &wgt::QuerySetDescriptor<crate::Label>,
2228 ) -> Result<super::QuerySet, crate::DeviceError> {
2229 self.error_if_would_oom_on_resource_allocation(true, desc.count as u64 * 256)?;
2232
2233 let (vk_type, pipeline_statistics) = match desc.ty {
2234 wgt::QueryType::Occlusion => (
2235 vk::QueryType::OCCLUSION,
2236 vk::QueryPipelineStatisticFlags::empty(),
2237 ),
2238 wgt::QueryType::PipelineStatistics(statistics) => (
2239 vk::QueryType::PIPELINE_STATISTICS,
2240 conv::map_pipeline_statistics(statistics),
2241 ),
2242 wgt::QueryType::Timestamp => (
2243 vk::QueryType::TIMESTAMP,
2244 vk::QueryPipelineStatisticFlags::empty(),
2245 ),
2246 };
2247
2248 let vk_info = vk::QueryPoolCreateInfo::default()
2249 .query_type(vk_type)
2250 .query_count(desc.count)
2251 .pipeline_statistics(pipeline_statistics);
2252
2253 let raw = unsafe { self.shared.raw.create_query_pool(&vk_info, None) }
2254 .map_err(super::map_host_device_oom_err)?;
2255 if let Some(label) = desc.label {
2256 unsafe { self.shared.set_object_name(raw, label) };
2257 }
2258
2259 self.counters.query_sets.add(1);
2260
2261 Ok(super::QuerySet { raw })
2262 }
2263
2264 unsafe fn destroy_query_set(&self, set: super::QuerySet) {
2265 unsafe { self.shared.raw.destroy_query_pool(set.raw, None) };
2266
2267 self.counters.query_sets.sub(1);
2268 }
2269
2270 unsafe fn create_fence(&self) -> Result<super::Fence, crate::DeviceError> {
2271 self.counters.fences.add(1);
2272
2273 Ok(if self.shared.private_caps.timeline_semaphores {
2274 let mut sem_type_info =
2275 vk::SemaphoreTypeCreateInfo::default().semaphore_type(vk::SemaphoreType::TIMELINE);
2276 let vk_info = vk::SemaphoreCreateInfo::default().push_next(&mut sem_type_info);
2277 let raw = unsafe { self.shared.raw.create_semaphore(&vk_info, None) }
2278 .map_err(super::map_host_device_oom_err)?;
2279
2280 super::Fence::TimelineSemaphore(raw)
2281 } else {
2282 super::Fence::FencePool {
2283 last_completed: 0,
2284 active: Vec::new(),
2285 free: Vec::new(),
2286 }
2287 })
2288 }
2289 unsafe fn destroy_fence(&self, fence: super::Fence) {
2290 match fence {
2291 super::Fence::TimelineSemaphore(raw) => {
2292 unsafe { self.shared.raw.destroy_semaphore(raw, None) };
2293 }
2294 super::Fence::FencePool {
2295 active,
2296 free,
2297 last_completed: _,
2298 } => {
2299 for (_, raw) in active {
2300 unsafe { self.shared.raw.destroy_fence(raw, None) };
2301 }
2302 for raw in free {
2303 unsafe { self.shared.raw.destroy_fence(raw, None) };
2304 }
2305 }
2306 }
2307
2308 self.counters.fences.sub(1);
2309 }
2310 unsafe fn get_fence_value(
2311 &self,
2312 fence: &super::Fence,
2313 ) -> Result<crate::FenceValue, crate::DeviceError> {
2314 fence.get_latest(
2315 &self.shared.raw,
2316 self.shared.extension_fns.timeline_semaphore.as_ref(),
2317 )
2318 }
2319 unsafe fn wait(
2320 &self,
2321 fence: &super::Fence,
2322 wait_value: crate::FenceValue,
2323 timeout: Option<Duration>,
2324 ) -> Result<bool, crate::DeviceError> {
2325 let timeout_ns = timeout
2326 .unwrap_or(Duration::MAX)
2327 .as_nanos()
2328 .min(u64::MAX as _) as u64;
2329 self.shared.wait_for_fence(fence, wait_value, timeout_ns)
2330 }
2331
2332 unsafe fn start_graphics_debugger_capture(&self) -> bool {
2333 #[cfg(feature = "renderdoc")]
2334 {
2335 let raw_vk_instance =
2337 vk::Handle::as_raw(self.shared.instance.raw.handle()) as *mut *mut _;
2338 let raw_vk_instance_dispatch_table = unsafe { *raw_vk_instance };
2339 unsafe {
2340 self.render_doc
2341 .start_frame_capture(raw_vk_instance_dispatch_table, ptr::null_mut())
2342 }
2343 }
2344 #[cfg(not(feature = "renderdoc"))]
2345 false
2346 }
2347 unsafe fn stop_graphics_debugger_capture(&self) {
2348 #[cfg(feature = "renderdoc")]
2349 {
2350 let raw_vk_instance =
2352 vk::Handle::as_raw(self.shared.instance.raw.handle()) as *mut *mut _;
2353 let raw_vk_instance_dispatch_table = unsafe { *raw_vk_instance };
2354
2355 unsafe {
2356 self.render_doc
2357 .end_frame_capture(raw_vk_instance_dispatch_table, ptr::null_mut())
2358 }
2359 }
2360 }
2361
2362 unsafe fn pipeline_cache_get_data(&self, cache: &super::PipelineCache) -> Option<Vec<u8>> {
2363 let data = unsafe { self.raw_device().get_pipeline_cache_data(cache.raw) };
2364 data.ok()
2365 }
2366
2367 unsafe fn get_acceleration_structure_build_sizes<'a>(
2368 &self,
2369 desc: &crate::GetAccelerationStructureBuildSizesDescriptor<'a, super::Buffer>,
2370 ) -> crate::AccelerationStructureBuildSizes {
2371 const CAPACITY: usize = 8;
2372
2373 let ray_tracing_functions = self
2374 .shared
2375 .extension_fns
2376 .ray_tracing
2377 .as_ref()
2378 .expect("Feature `RAY_TRACING` not enabled");
2379
2380 let (geometries, primitive_counts) = match *desc.entries {
2381 crate::AccelerationStructureEntries::Instances(ref instances) => {
2382 let instance_data = vk::AccelerationStructureGeometryInstancesDataKHR::default();
2383
2384 let geometry = vk::AccelerationStructureGeometryKHR::default()
2385 .geometry_type(vk::GeometryTypeKHR::INSTANCES)
2386 .geometry(vk::AccelerationStructureGeometryDataKHR {
2387 instances: instance_data,
2388 });
2389
2390 (
2391 smallvec::smallvec![geometry],
2392 smallvec::smallvec![instances.count],
2393 )
2394 }
2395 crate::AccelerationStructureEntries::Triangles(ref in_geometries) => {
2396 let mut primitive_counts =
2397 smallvec::SmallVec::<[u32; CAPACITY]>::with_capacity(in_geometries.len());
2398 let mut geometries = smallvec::SmallVec::<
2399 [vk::AccelerationStructureGeometryKHR; CAPACITY],
2400 >::with_capacity(in_geometries.len());
2401
2402 for triangles in in_geometries {
2403 let mut triangle_data =
2404 vk::AccelerationStructureGeometryTrianglesDataKHR::default()
2405 .index_type(vk::IndexType::NONE_KHR)
2406 .vertex_format(conv::map_vertex_format(triangles.vertex_format))
2407 .max_vertex(triangles.vertex_count)
2408 .vertex_stride(triangles.vertex_stride)
2409 .transform_data(vk::DeviceOrHostAddressConstKHR {
2419 device_address: if desc
2420 .flags
2421 .contains(wgt::AccelerationStructureFlags::USE_TRANSFORM)
2422 {
2423 unsafe {
2424 ray_tracing_functions
2425 .buffer_device_address
2426 .get_buffer_device_address(
2427 &vk::BufferDeviceAddressInfo::default().buffer(
2428 triangles
2429 .transform
2430 .as_ref()
2431 .unwrap()
2432 .buffer
2433 .raw,
2434 ),
2435 )
2436 }
2437 } else {
2438 0
2439 },
2440 });
2441
2442 let pritive_count = if let Some(ref indices) = triangles.indices {
2443 triangle_data =
2444 triangle_data.index_type(conv::map_index_format(indices.format));
2445 indices.count / 3
2446 } else {
2447 triangles.vertex_count / 3
2448 };
2449
2450 let geometry = vk::AccelerationStructureGeometryKHR::default()
2451 .geometry_type(vk::GeometryTypeKHR::TRIANGLES)
2452 .geometry(vk::AccelerationStructureGeometryDataKHR {
2453 triangles: triangle_data,
2454 })
2455 .flags(conv::map_acceleration_structure_geometry_flags(
2456 triangles.flags,
2457 ));
2458
2459 geometries.push(geometry);
2460 primitive_counts.push(pritive_count);
2461 }
2462 (geometries, primitive_counts)
2463 }
2464 crate::AccelerationStructureEntries::AABBs(ref in_geometries) => {
2465 let mut primitive_counts =
2466 smallvec::SmallVec::<[u32; CAPACITY]>::with_capacity(in_geometries.len());
2467 let mut geometries = smallvec::SmallVec::<
2468 [vk::AccelerationStructureGeometryKHR; CAPACITY],
2469 >::with_capacity(in_geometries.len());
2470 for aabb in in_geometries {
2471 let aabbs_data = vk::AccelerationStructureGeometryAabbsDataKHR::default()
2472 .stride(aabb.stride);
2473
2474 let geometry = vk::AccelerationStructureGeometryKHR::default()
2475 .geometry_type(vk::GeometryTypeKHR::AABBS)
2476 .geometry(vk::AccelerationStructureGeometryDataKHR { aabbs: aabbs_data })
2477 .flags(conv::map_acceleration_structure_geometry_flags(aabb.flags));
2478
2479 geometries.push(geometry);
2480 primitive_counts.push(aabb.count);
2481 }
2482 (geometries, primitive_counts)
2483 }
2484 };
2485
2486 let ty = match *desc.entries {
2487 crate::AccelerationStructureEntries::Instances(_) => {
2488 vk::AccelerationStructureTypeKHR::TOP_LEVEL
2489 }
2490 _ => vk::AccelerationStructureTypeKHR::BOTTOM_LEVEL,
2491 };
2492
2493 let geometry_info = vk::AccelerationStructureBuildGeometryInfoKHR::default()
2494 .ty(ty)
2495 .flags(conv::map_acceleration_structure_flags(desc.flags))
2496 .geometries(&geometries);
2497
2498 let mut raw = Default::default();
2499 unsafe {
2500 ray_tracing_functions
2501 .acceleration_structure
2502 .get_acceleration_structure_build_sizes(
2503 vk::AccelerationStructureBuildTypeKHR::DEVICE,
2504 &geometry_info,
2505 &primitive_counts,
2506 &mut raw,
2507 )
2508 }
2509
2510 crate::AccelerationStructureBuildSizes {
2511 acceleration_structure_size: raw.acceleration_structure_size,
2512 update_scratch_size: raw.update_scratch_size,
2513 build_scratch_size: raw.build_scratch_size,
2514 }
2515 }
2516
2517 unsafe fn get_acceleration_structure_device_address(
2518 &self,
2519 acceleration_structure: &super::AccelerationStructure,
2520 ) -> wgt::BufferAddress {
2521 let ray_tracing_functions = self
2522 .shared
2523 .extension_fns
2524 .ray_tracing
2525 .as_ref()
2526 .expect("Feature `RAY_TRACING` not enabled");
2527
2528 unsafe {
2529 ray_tracing_functions
2530 .acceleration_structure
2531 .get_acceleration_structure_device_address(
2532 &vk::AccelerationStructureDeviceAddressInfoKHR::default()
2533 .acceleration_structure(acceleration_structure.raw),
2534 )
2535 }
2536 }
2537
2538 unsafe fn create_acceleration_structure(
2539 &self,
2540 desc: &crate::AccelerationStructureDescriptor,
2541 ) -> Result<super::AccelerationStructure, crate::DeviceError> {
2542 let ray_tracing_functions = self
2543 .shared
2544 .extension_fns
2545 .ray_tracing
2546 .as_ref()
2547 .expect("Feature `RAY_TRACING` not enabled");
2548
2549 let vk_buffer_info = vk::BufferCreateInfo::default()
2550 .size(desc.size)
2551 .usage(
2552 vk::BufferUsageFlags::ACCELERATION_STRUCTURE_STORAGE_KHR
2553 | vk::BufferUsageFlags::SHADER_DEVICE_ADDRESS,
2554 )
2555 .sharing_mode(vk::SharingMode::EXCLUSIVE);
2556
2557 unsafe {
2558 let raw_buffer = self
2559 .shared
2560 .raw
2561 .create_buffer(&vk_buffer_info, None)
2562 .map_err(super::map_host_device_oom_and_ioca_err)?;
2563
2564 let requirements = self.shared.raw.get_buffer_memory_requirements(raw_buffer);
2565
2566 self.error_if_would_oom_on_resource_allocation(false, requirements.size)
2567 .inspect_err(|_| {
2568 self.shared.raw.destroy_buffer(raw_buffer, None);
2569 })?;
2570
2571 let name = desc
2572 .label
2573 .unwrap_or("Unlabeled acceleration structure buffer");
2574
2575 let allocation = self
2576 .mem_allocator
2577 .lock()
2578 .allocate(&gpu_allocator::vulkan::AllocationCreateDesc {
2579 name,
2580 requirements,
2581 location: gpu_allocator::MemoryLocation::GpuOnly,
2582 linear: true, allocation_scheme: gpu_allocator::vulkan::AllocationScheme::GpuAllocatorManaged,
2584 })
2585 .inspect_err(|_| {
2586 self.shared.raw.destroy_buffer(raw_buffer, None);
2587 })?;
2588
2589 self.shared
2590 .raw
2591 .bind_buffer_memory(raw_buffer, allocation.memory(), allocation.offset())
2592 .map_err(super::map_host_device_oom_and_ioca_err)
2593 .inspect_err(|_| {
2594 self.shared.raw.destroy_buffer(raw_buffer, None);
2595 })?;
2596
2597 if let Some(label) = desc.label {
2598 self.shared.set_object_name(raw_buffer, label);
2599 }
2600
2601 let vk_info = vk::AccelerationStructureCreateInfoKHR::default()
2602 .buffer(raw_buffer)
2603 .offset(0)
2604 .size(desc.size)
2605 .ty(conv::map_acceleration_structure_format(desc.format));
2606
2607 let raw_acceleration_structure = ray_tracing_functions
2608 .acceleration_structure
2609 .create_acceleration_structure(&vk_info, None)
2610 .map_err(super::map_host_oom_and_ioca_err)
2611 .inspect_err(|_| {
2612 self.shared.raw.destroy_buffer(raw_buffer, None);
2613 })?;
2614
2615 if let Some(label) = desc.label {
2616 self.shared
2617 .set_object_name(raw_acceleration_structure, label);
2618 }
2619
2620 let pool = if desc.allow_compaction {
2621 let vk_info = vk::QueryPoolCreateInfo::default()
2622 .query_type(vk::QueryType::ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR)
2623 .query_count(1);
2624
2625 let raw = self
2626 .shared
2627 .raw
2628 .create_query_pool(&vk_info, None)
2629 .map_err(super::map_host_device_oom_err)
2630 .inspect_err(|_| {
2631 ray_tracing_functions
2632 .acceleration_structure
2633 .destroy_acceleration_structure(raw_acceleration_structure, None);
2634 self.shared.raw.destroy_buffer(raw_buffer, None);
2635 })?;
2636 Some(raw)
2637 } else {
2638 None
2639 };
2640
2641 Ok(super::AccelerationStructure {
2642 raw: raw_acceleration_structure,
2643 buffer: raw_buffer,
2644 allocation,
2645 compacted_size_query: pool,
2646 })
2647 }
2648 }
2649
2650 unsafe fn destroy_acceleration_structure(
2651 &self,
2652 acceleration_structure: super::AccelerationStructure,
2653 ) {
2654 let ray_tracing_functions = self
2655 .shared
2656 .extension_fns
2657 .ray_tracing
2658 .as_ref()
2659 .expect("Feature `RAY_TRACING` not enabled");
2660
2661 unsafe {
2662 ray_tracing_functions
2663 .acceleration_structure
2664 .destroy_acceleration_structure(acceleration_structure.raw, None);
2665 self.shared
2666 .raw
2667 .destroy_buffer(acceleration_structure.buffer, None);
2668 let result = self
2669 .mem_allocator
2670 .lock()
2671 .free(acceleration_structure.allocation);
2672 if let Err(err) = result {
2673 log::warn!("Failed to free buffer acceleration structure: {err}");
2674 }
2675 if let Some(query) = acceleration_structure.compacted_size_query {
2676 self.shared.raw.destroy_query_pool(query, None)
2677 }
2678 }
2679 }
2680
2681 fn get_internal_counters(&self) -> wgt::HalCounters {
2682 self.counters
2683 .memory_allocations
2684 .set(self.shared.memory_allocations_counter.read());
2685
2686 self.counters.as_ref().clone()
2687 }
2688
2689 fn generate_allocator_report(&self) -> Option<wgt::AllocatorReport> {
2690 let gpu_allocator::AllocatorReport {
2691 allocations,
2692 blocks,
2693 total_allocated_bytes,
2694 total_capacity_bytes,
2695 } = self.mem_allocator.lock().generate_report();
2696
2697 let allocations = allocations
2698 .into_iter()
2699 .map(|alloc| wgt::AllocationReport {
2700 name: alloc.name,
2701 offset: alloc.offset,
2702 size: alloc.size,
2703 })
2704 .collect();
2705
2706 let blocks = blocks
2707 .into_iter()
2708 .map(|block| wgt::MemoryBlockReport {
2709 size: block.size,
2710 allocations: block.allocations.clone(),
2711 })
2712 .collect();
2713
2714 Some(wgt::AllocatorReport {
2715 allocations,
2716 blocks,
2717 total_allocated_bytes,
2718 total_reserved_bytes: total_capacity_bytes,
2719 })
2720 }
2721
2722 fn tlas_instance_to_bytes(&self, instance: TlasInstance) -> Vec<u8> {
2723 const MAX_U24: u32 = (1u32 << 24u32) - 1u32;
2724 let temp = RawTlasInstance {
2725 transform: instance.transform,
2726 custom_data_and_mask: (instance.custom_data & MAX_U24)
2727 | (u32::from(instance.mask) << 24),
2728 shader_binding_table_record_offset_and_flags: 0,
2729 acceleration_structure_reference: instance.blas_address,
2730 };
2731 bytemuck::bytes_of(&temp).to_vec()
2732 }
2733
2734 fn check_if_oom(&self) -> Result<(), crate::DeviceError> {
2735 let Some(threshold) = self
2736 .shared
2737 .instance
2738 .memory_budget_thresholds
2739 .for_device_loss
2740 else {
2741 return Ok(());
2742 };
2743
2744 if !self
2745 .shared
2746 .enabled_extensions
2747 .contains(&ext::memory_budget::NAME)
2748 {
2749 return Ok(());
2750 }
2751
2752 let get_physical_device_properties = self
2753 .shared
2754 .instance
2755 .get_physical_device_properties
2756 .as_ref()
2757 .unwrap();
2758
2759 let mut memory_budget_properties = vk::PhysicalDeviceMemoryBudgetPropertiesEXT::default();
2760
2761 let mut memory_properties =
2762 vk::PhysicalDeviceMemoryProperties2::default().push_next(&mut memory_budget_properties);
2763
2764 unsafe {
2765 get_physical_device_properties.get_physical_device_memory_properties2(
2766 self.shared.physical_device,
2767 &mut memory_properties,
2768 );
2769 }
2770
2771 let memory_properties = memory_properties.memory_properties;
2772
2773 for i in 0..memory_properties.memory_heap_count {
2774 let heap_usage = memory_budget_properties.heap_usage[i as usize];
2775 let heap_budget = memory_budget_properties.heap_budget[i as usize];
2776
2777 if heap_usage >= heap_budget / 100 * threshold as u64 {
2778 return Err(crate::DeviceError::OutOfMemory);
2779 }
2780 }
2781
2782 Ok(())
2783 }
2784}
2785
2786impl super::DeviceShared {
2787 pub(super) fn new_binary_semaphore(
2788 &self,
2789 name: &str,
2790 ) -> Result<vk::Semaphore, crate::DeviceError> {
2791 unsafe {
2792 let semaphore = self
2793 .raw
2794 .create_semaphore(&vk::SemaphoreCreateInfo::default(), None)
2795 .map_err(super::map_host_device_oom_err)?;
2796
2797 self.set_object_name(semaphore, name);
2798
2799 Ok(semaphore)
2800 }
2801 }
2802
2803 pub(super) fn wait_for_fence(
2804 &self,
2805 fence: &super::Fence,
2806 wait_value: crate::FenceValue,
2807 timeout_ns: u64,
2808 ) -> Result<bool, crate::DeviceError> {
2809 profiling::scope!("Device::wait");
2810 match *fence {
2811 super::Fence::TimelineSemaphore(raw) => {
2812 let semaphores = [raw];
2813 let values = [wait_value];
2814 let vk_info = vk::SemaphoreWaitInfo::default()
2815 .semaphores(&semaphores)
2816 .values(&values);
2817 let result = match self.extension_fns.timeline_semaphore {
2818 Some(super::ExtensionFn::Extension(ref ext)) => unsafe {
2819 ext.wait_semaphores(&vk_info, timeout_ns)
2820 },
2821 Some(super::ExtensionFn::Promoted) => unsafe {
2822 self.raw.wait_semaphores(&vk_info, timeout_ns)
2823 },
2824 None => unreachable!(),
2825 };
2826 match result {
2827 Ok(()) => Ok(true),
2828 Err(vk::Result::TIMEOUT) => Ok(false),
2829 Err(other) => Err(super::map_host_device_oom_and_lost_err(other)),
2830 }
2831 }
2832 super::Fence::FencePool {
2833 last_completed,
2834 ref active,
2835 free: _,
2836 } => {
2837 if wait_value <= last_completed {
2838 Ok(true)
2839 } else {
2840 match active.iter().find(|&&(value, _)| value >= wait_value) {
2841 Some(&(_, raw)) => {
2842 match unsafe { self.raw.wait_for_fences(&[raw], true, timeout_ns) } {
2843 Ok(()) => Ok(true),
2844 Err(vk::Result::TIMEOUT) => Ok(false),
2845 Err(other) => Err(super::map_host_device_oom_and_lost_err(other)),
2846 }
2847 }
2848 None => {
2849 crate::hal_usage_error(format!(
2850 "no signals reached value {wait_value}"
2851 ));
2852 }
2853 }
2854 }
2855 }
2856 }
2857 }
2858}
2859
2860struct ImageWithoutMemory {
2861 raw: vk::Image,
2862 requirements: vk::MemoryRequirements,
2863}