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