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