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