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