1use std::mem::MaybeUninit;
2
3use super::*;
4
5#[derive(Debug)]
6pub struct CommandBuffer {
7 command_buffer: vk::CommandBuffer,
8}
9
10impl CommandBuffer {
11 pub unsafe fn create(device: &Device) -> Result<Self> {
16 let command_buffer = {
18 let command_buffer_allocate_info = vk::CommandBufferAllocateInfo {
19 s_type: vk::StructureType::CommandBufferAllocateInfo,
20 p_next: null(),
21 command_pool: device.command_pool,
22 level: vk::CommandBufferLevel::Primary,
23 command_buffer_count: 1,
24 };
25 let mut command_buffer = MaybeUninit::uninit();
26 device.allocate_command_buffers(
27 &command_buffer_allocate_info,
28 command_buffer.as_mut_ptr(),
29 )?;
30 command_buffer.assume_init()
31 };
32
33 Ok(Self { command_buffer })
34 }
35
36 pub unsafe fn destroy(self, device: &Device) {
37 device.free_command_buffers(device.command_pool, 1, &self.command_buffer);
38 }
39
40 pub unsafe fn begin(&self, device: &Device) -> Result<()> {
41 device.reset_command_buffer(self.command_buffer, vk::CommandBufferResetFlags::empty())?;
43
44 device.begin_command_buffer(
46 self.command_buffer,
47 &vk::CommandBufferBeginInfo {
48 s_type: vk::StructureType::CommandBufferBeginInfo,
49 p_next: null(),
50 flags: vk::CommandBufferUsageFlagBits::OneTimeSubmit.into(),
51 p_inheritance_info: null(),
52 },
53 )?;
54
55 Ok(())
56 }
57
58 pub unsafe fn end(&self, device: &Device) -> Result<()> {
59 device.end_command_buffer(self.command_buffer)?;
60 Ok(())
61 }
62
63 #[must_use]
64 pub unsafe fn handle(&self) -> vk::CommandBuffer {
65 self.command_buffer
66 }
67
68 pub unsafe fn begin_rendering<Image>(
73 &self,
74 device: &Device,
75 color_attachment: (&Image, [f32; 4]),
76 depth_attachment: Option<(&Image, f32)>,
77 resolve_attachment: Option<&Image>,
78 ) where
79 Image: ImageOps,
80 {
81 let mut color_attachment_info = vk::RenderingAttachmentInfo {
83 s_type: vk::StructureType::RenderingAttachmentInfo,
84 p_next: null(),
85 image_view: color_attachment.0.image_view_handle(),
86 image_layout: vk::ImageLayout::AttachmentOptimal,
87 resolve_mode: vk::ResolveModeFlagBits::None,
88 resolve_image_view: vk::ImageView::null(),
89 resolve_image_layout: vk::ImageLayout::Undefined,
90 load_op: vk::AttachmentLoadOp::Clear,
91 store_op: vk::AttachmentStoreOp::Store,
92 clear_value: vk::ClearValue {
93 color: vk::ClearColorValue {
94 float32: color_attachment.1,
95 },
96 },
97 };
98
99 if let Some(resolve_attachment) = resolve_attachment {
101 color_attachment_info.resolve_mode = vk::ResolveModeFlagBits::Average;
102 color_attachment_info.resolve_image_view = resolve_attachment.image_view_handle();
103 color_attachment_info.resolve_image_layout = vk::ImageLayout::AttachmentOptimal;
104 }
105
106 let mut depth_attachment_info = vk::RenderingAttachmentInfo {
108 s_type: vk::StructureType::RenderingAttachmentInfo,
109 p_next: null(),
110 image_view: vk::ImageView::null(),
111 image_layout: vk::ImageLayout::AttachmentOptimal,
112 resolve_mode: vk::ResolveModeFlagBits::None,
113 resolve_image_view: vk::ImageView::null(),
114 resolve_image_layout: vk::ImageLayout::Undefined,
115 load_op: vk::AttachmentLoadOp::Clear,
116 store_op: vk::AttachmentStoreOp::Store,
117 clear_value: vk::ClearValue {
118 depth_stencil: vk::ClearDepthStencilValue {
119 depth: 1.0,
120 stencil: 0,
121 },
122 },
123 };
124 if let Some((depth_attachment, depth)) = depth_attachment {
125 depth_attachment_info.image_view = depth_attachment.image_view_handle();
126 depth_attachment_info.clear_value.depth_stencil.depth = depth;
127 }
128
129 let mut rendering_info = vk::RenderingInfo {
131 s_type: vk::StructureType::RenderingInfo,
132 p_next: null(),
133 flags: vk::RenderingFlags::empty(),
134 render_area: color_attachment.0.rect_2d(),
135 layer_count: 1,
136 view_mask: 0,
137 color_attachment_count: 1,
138 p_color_attachments: &color_attachment_info,
139 p_depth_attachment: null(),
140 p_stencil_attachment: null(),
141 };
142 if depth_attachment.is_some() {
143 rendering_info.p_depth_attachment = &depth_attachment_info;
144 }
145
146 device.cmd_begin_rendering(self.command_buffer, &rendering_info);
148 }
149
150 pub unsafe fn end_rendering(&self, device: &Device) {
151 device.cmd_end_rendering(self.command_buffer);
152 }
153
154 pub unsafe fn barrier(
159 &self,
160 device: &Device,
161 src_stage_mask: impl Into<vk::PipelineStageFlags2>,
162 src_access_mask: impl Into<vk::AccessFlags2>,
163 dst_stage_mask: impl Into<vk::PipelineStageFlags2>,
164 dst_access_mask: impl Into<vk::AccessFlags2>,
165 ) {
166 device.cmd_pipeline_barrier2(
167 self.command_buffer,
168 &vk::DependencyInfo {
169 s_type: vk::StructureType::DependencyInfo,
170 p_next: null(),
171 dependency_flags: vk::DependencyFlags::empty(),
172 memory_barrier_count: 1,
173 p_memory_barriers: &vk::MemoryBarrier2 {
174 s_type: vk::StructureType::MemoryBarrier2,
175 p_next: null(),
176 src_stage_mask: src_stage_mask.into(),
177 src_access_mask: src_access_mask.into(),
178 dst_stage_mask: dst_stage_mask.into(),
179 dst_access_mask: dst_access_mask.into(),
180 },
181 buffer_memory_barrier_count: 0,
182 p_buffer_memory_barriers: null(),
183 image_memory_barrier_count: 0,
184 p_image_memory_barriers: null(),
185 },
186 );
187 }
188
189 pub unsafe fn buffer_barrier(
190 &self,
191 device: &Device,
192 buffer: &impl BufferOps,
193 src_stage_mask: impl Into<vk::PipelineStageFlags2>,
194 src_access_mask: impl Into<vk::AccessFlags2>,
195 dst_stage_mask: impl Into<vk::PipelineStageFlags2>,
196 dst_access_mask: impl Into<vk::AccessFlags2>,
197 ) {
198 device.cmd_pipeline_barrier2(
199 self.command_buffer,
200 &vk::DependencyInfo {
201 s_type: vk::StructureType::DependencyInfo,
202 p_next: null(),
203 dependency_flags: vk::DependencyFlags::empty(),
204 memory_barrier_count: 0,
205 p_memory_barriers: null(),
206 buffer_memory_barrier_count: 1,
207 p_buffer_memory_barriers: &vk::BufferMemoryBarrier2 {
208 s_type: vk::StructureType::BufferMemoryBarrier2,
209 p_next: null(),
210 src_stage_mask: src_stage_mask.into(),
211 src_access_mask: src_access_mask.into(),
212 dst_stage_mask: dst_stage_mask.into(),
213 dst_access_mask: dst_access_mask.into(),
214 src_queue_family_index: vk::QUEUE_FAMILY_IGNORED,
215 dst_queue_family_index: vk::QUEUE_FAMILY_IGNORED,
216 buffer: buffer.buffer_handle(),
217 offset: 0,
218 size: vk::WHOLE_SIZE,
219 },
220 image_memory_barrier_count: 0,
221 p_image_memory_barriers: null(),
222 },
223 );
224 }
225
226 pub unsafe fn image_barrier(
227 &self,
228 device: &Device,
229 image: &impl ImageOps,
230 src_stage_mask: impl Into<vk::PipelineStageFlags2>,
231 src_access_mask: impl Into<vk::AccessFlags2>,
232 dst_stage_mask: impl Into<vk::PipelineStageFlags2>,
233 dst_access_mask: impl Into<vk::AccessFlags2>,
234 old_layout: vk::ImageLayout,
235 new_layout: vk::ImageLayout,
236 ) {
237 device.cmd_pipeline_barrier2(
238 self.command_buffer,
239 &vk::DependencyInfo {
240 s_type: vk::StructureType::DependencyInfo,
241 p_next: null(),
242 dependency_flags: vk::DependencyFlags::empty(),
243 memory_barrier_count: 0,
244 p_memory_barriers: null(),
245 buffer_memory_barrier_count: 0,
246 p_buffer_memory_barriers: null(),
247 image_memory_barrier_count: 1,
248 p_image_memory_barriers: &vk::ImageMemoryBarrier2 {
249 s_type: vk::StructureType::ImageMemoryBarrier2,
250 p_next: null(),
251 src_stage_mask: src_stage_mask.into(),
252 src_access_mask: src_access_mask.into(),
253 dst_stage_mask: dst_stage_mask.into(),
254 dst_access_mask: dst_access_mask.into(),
255 old_layout,
256 new_layout,
257 src_queue_family_index: vk::QUEUE_FAMILY_IGNORED,
258 dst_queue_family_index: vk::QUEUE_FAMILY_IGNORED,
259 image: image.image_handle(),
260 subresource_range: image.subresource_range(),
261 },
262 },
263 );
264 }
265
266 pub unsafe fn draw_mesh_tasks(
271 &self,
272 device: &Device,
273 group_count_x: u32,
274 group_count_y: u32,
275 group_count_z: u32,
276 ) {
277 device.cmd_draw_mesh_tasks_ext(
278 self.command_buffer,
279 group_count_x,
280 group_count_y,
281 group_count_z,
282 );
283 }
284
285 pub unsafe fn draw_mesh_tasks_indirect(
286 &self,
287 device: &Device,
288 buffer: &impl BufferOps,
289 offset: vk::DeviceSize,
290 draw_count: u32,
291 stride: u32,
292 ) {
293 device.cmd_draw_mesh_tasks_indirect_ext(
294 self.command_buffer,
295 buffer.buffer_handle(),
296 offset,
297 draw_count,
298 stride,
299 );
300 }
301
302 pub unsafe fn draw_mesh_tasks_indirect_count(
303 &self,
304 device: &Device,
305 buffer: &impl BufferOps,
306 offset: vk::DeviceSize,
307 count_buffer: &impl BufferOps,
308 count_buffer_offset: vk::DeviceSize,
309 max_draw_count: u32,
310 stride: u32,
311 ) {
312 device.cmd_draw_mesh_tasks_indirect_count_ext(
313 self.command_buffer,
314 buffer.buffer_handle(),
315 offset,
316 count_buffer.buffer_handle(),
317 count_buffer_offset,
318 max_draw_count,
319 stride,
320 );
321 }
322
323 pub unsafe fn dispatch(
324 &self,
325 device: &Device,
326 group_count_x: u32,
327 group_count_y: u32,
328 group_count_z: u32,
329 ) {
330 device.cmd_dispatch(
331 self.command_buffer,
332 group_count_x,
333 group_count_y,
334 group_count_z,
335 );
336 }
337
338 pub unsafe fn dispatch_indirect(
339 &self,
340 device: &Device,
341 buffer: &impl BufferOps,
342 offset: vk::DeviceSize,
343 ) {
344 device.cmd_dispatch_indirect(self.command_buffer, buffer.buffer_handle(), offset);
345 }
346
347 pub unsafe fn copy_buffer(
352 &self,
353 device: &Device,
354 src_buffer: (&impl BufferOps, vk::DeviceSize),
355 dst_buffer: (&impl BufferOps, vk::DeviceSize),
356 size: vk::DeviceSize,
357 ) {
358 device.cmd_copy_buffer2(
359 self.command_buffer,
360 &vk::CopyBufferInfo2 {
361 s_type: vk::StructureType::CopyBufferInfo2,
362 p_next: null(),
363 src_buffer: src_buffer.0.buffer_handle(),
364 dst_buffer: dst_buffer.0.buffer_handle(),
365 region_count: 1,
366 p_regions: &vk::BufferCopy2 {
367 s_type: vk::StructureType::BufferCopy2,
368 p_next: null(),
369 src_offset: src_buffer.1,
370 dst_offset: dst_buffer.1,
371 size,
372 },
373 },
374 );
375 }
376
377 pub unsafe fn copy_image(
378 &self,
379 device: &Device,
380 src_image: (&impl ImageOps, vk::ImageLayout),
381 dst_image: (&impl ImageOps, vk::ImageLayout),
382 extent: vk::Extent3D,
383 ) {
384 device.cmd_copy_image2(
385 self.command_buffer,
386 &vk::CopyImageInfo2 {
387 s_type: vk::StructureType::CopyImageInfo2,
388 p_next: null(),
389 src_image: src_image.0.image_handle(),
390 src_image_layout: src_image.1,
391 dst_image: dst_image.0.image_handle(),
392 dst_image_layout: dst_image.1,
393 region_count: 1,
394 p_regions: &vk::ImageCopy2 {
395 s_type: vk::StructureType::ImageCopy2,
396 p_next: null(),
397 src_subresource: src_image.0.subresource_layers(),
398 src_offset: vk::Offset3D { x: 0, y: 0, z: 0 },
399 dst_subresource: dst_image.0.subresource_layers(),
400 dst_offset: vk::Offset3D { x: 0, y: 0, z: 0 },
401 extent,
402 },
403 },
404 );
405 }
406
407 pub unsafe fn copy_buffer_to_image(
408 &self,
409 device: &Device,
410 src_buffer: (&impl BufferOps, vk::DeviceSize),
411 dst_image: &impl ImageOps,
412 ) {
413 device.cmd_copy_buffer_to_image2(
414 self.command_buffer,
415 &vk::CopyBufferToImageInfo2 {
416 s_type: vk::StructureType::CopyBufferToImageInfo2,
417 p_next: null(),
418 src_buffer: src_buffer.0.buffer_handle(),
419 dst_image: dst_image.image_handle(),
420 dst_image_layout: vk::ImageLayout::TransferDstOptimal,
421 region_count: 1,
422 p_regions: &vk::BufferImageCopy2 {
423 s_type: vk::StructureType::BufferImageCopy2,
424 p_next: null(),
425 buffer_offset: src_buffer.1,
426 buffer_row_length: 0,
427 buffer_image_height: 0,
428 image_subresource: dst_image.subresource_layers(),
429 image_offset: vk::Offset3D { x: 0, y: 0, z: 0 },
430 image_extent: dst_image.extent_3d(),
431 },
432 },
433 );
434 }
435
436 pub unsafe fn copy_image_to_buffer(
437 &self,
438 device: &Device,
439 src_image: &impl ImageOps,
440 dst_buffer: (&impl BufferOps, vk::DeviceSize),
441 ) {
442 device.cmd_copy_image_to_buffer2(
443 self.command_buffer,
444 &vk::CopyImageToBufferInfo2 {
445 s_type: vk::StructureType::CopyImageToBufferInfo2,
446 p_next: null(),
447 src_image: src_image.image_handle(),
448 src_image_layout: vk::ImageLayout::TransferSrcOptimal,
449 dst_buffer: dst_buffer.0.buffer_handle(),
450 region_count: 1,
451 p_regions: &vk::BufferImageCopy2 {
452 s_type: vk::StructureType::BufferImageCopy2,
453 p_next: null(),
454 buffer_offset: dst_buffer.1,
455 buffer_row_length: 0,
456 buffer_image_height: 0,
457 image_subresource: src_image.subresource_layers(),
458 image_offset: vk::Offset3D { x: 0, y: 0, z: 0 },
459 image_extent: src_image.extent_3d(),
460 },
461 },
462 );
463 }
464
465 pub unsafe fn bind_descriptor_storage(
470 &self,
471 device: &Device,
472 descriptor_storage: &DescriptorStorage,
473 pipeline_bind_point: vk::PipelineBindPoint,
474 ) {
475 let ds = descriptor_storage;
476 device.cmd_bind_descriptor_buffers_ext(
477 self.command_buffer,
478 1,
479 &vk::DescriptorBufferBindingInfoEXT {
480 s_type: vk::StructureType::DescriptorBufferBindingInfoEXT,
481 p_next: null_mut(),
482 address: ds.allocation.device_address(),
483 usage: ds.usage,
484 },
485 );
486 device.cmd_set_descriptor_buffer_offsets_ext(
487 self.command_buffer,
488 pipeline_bind_point,
489 ds.pipeline_layout,
490 0,
491 ds.set_count,
492 ds.buffer_indices.as_ptr(),
493 ds.offsets.as_ptr(),
494 );
495 }
496
497 pub unsafe fn push_constants<T>(
498 &self,
499 device: &Device,
500 descriptor_storage: &DescriptorStorage,
501 data: &T,
502 ) -> Result<()> {
503 let ds = descriptor_storage;
504 let Some(pcr) = ds.push_constant_range else {
505 bail!("Missing push constant range");
506 };
507 ensure!(pcr.size as usize == size_of::<T>());
508 device.cmd_push_constants(
509 self.command_buffer,
510 ds.pipeline_layout,
511 pcr.stage_flags,
512 pcr.offset,
513 pcr.size,
514 (data as *const T).cast(),
515 );
516 Ok(())
517 }
518
519 pub unsafe fn bind_shader(&self, device: &Device, shader: &Shader) {
524 device.cmd_bind_shaders_ext(
525 self.command_buffer,
526 shader.stages.len() as _,
527 shader.stages.as_ptr(),
528 shader.shaders.as_ptr(),
529 );
530 }
531
532 pub unsafe fn set_viewport(&self, device: &Device, viewport: &vk::Viewport) {
537 device.cmd_set_viewport_with_count(self.command_buffer, 1, viewport);
538 }
539
540 pub unsafe fn set_viewport_flip_y(&self, device: &Device, viewport: &vk::Viewport) {
541 self.set_viewport(
546 device,
547 &vk::Viewport {
548 x: viewport.x,
549 y: viewport.y + viewport.height,
550 width: viewport.width,
551 height: -viewport.height,
552 min_depth: viewport.min_depth,
553 max_depth: viewport.max_depth,
554 },
555 );
556 }
557
558 pub unsafe fn set_scissor(&self, device: &Device, scissor: &vk::Rect2D) {
559 device.cmd_set_scissor_with_count(self.command_buffer, 1, scissor);
560 }
561
562 pub unsafe fn set_samples(&self, device: &Device, samples: vk::SampleCountFlagBits) {
563 device.cmd_set_rasterization_samples_ext(self.command_buffer, samples);
564 }
565
566 pub unsafe fn set_front_face(&self, device: &Device, front_face: vk::FrontFace) {
567 device.cmd_set_front_face(self.command_buffer, front_face);
568 }
569
570 pub unsafe fn set_cull_mode(&self, device: &Device, cull_mode: impl Into<vk::CullModeFlags>) {
571 device.cmd_set_cull_mode(self.command_buffer, cull_mode.into());
572 }
573
574 pub unsafe fn set_depth_test(&self, device: &Device, depth_test: bool) {
575 device.cmd_set_depth_test_enable(self.command_buffer, depth_test.into());
576 }
577
578 pub unsafe fn set_depth_compare_op(&self, device: &Device, depth_compare_op: vk::CompareOp) {
579 device.cmd_set_depth_compare_op(self.command_buffer, depth_compare_op);
580 }
581
582 pub unsafe fn set_depth_write(&self, device: &Device, depth_write: bool) {
583 device.cmd_set_depth_write_enable(self.command_buffer, depth_write.into());
584 }
585
586 pub unsafe fn set_color_blend(&self, device: &Device, attachment: u32, color_blend: bool) {
587 device.cmd_set_color_blend_enable_ext(
588 self.command_buffer,
589 attachment,
590 1,
591 [color_blend.into()].as_ptr(),
592 );
593 }
594
595 pub unsafe fn set_color_blend_equation(
596 &self,
597 device: &Device,
598 attachment: u32,
599 color_blend_equation: &vk::ColorBlendEquationEXT,
600 ) {
601 device.cmd_set_color_blend_equation_ext(
602 self.command_buffer,
603 attachment,
604 1,
605 color_blend_equation,
606 );
607 }
608
609 pub unsafe fn set_color_write_mask(
610 &self,
611 device: &Device,
612 attachment: u32,
613 mask: vk::ColorComponentFlags,
614 ) {
615 device.cmd_set_color_write_mask_ext(self.command_buffer, attachment, 1, [mask].as_ptr());
616 }
617
618 pub unsafe fn set_color_write_mask_rgba(&self, device: &Device, attachment: u32) {
619 self.set_color_write_mask(
620 device,
621 attachment,
622 vk::ColorComponentFlagBits::R
623 | vk::ColorComponentFlagBits::G
624 | vk::ColorComponentFlagBits::B
625 | vk::ColorComponentFlagBits::A,
626 );
627 }
628
629 pub unsafe fn write_timestamp(&self, device: &Device, timestamps: &TimestampQuery, index: u32) {
634 device.cmd_write_timestamp2(
635 self.command_buffer,
636 vk::PipelineStageFlagBits2::AllCommands.into(),
637 timestamps.query_pool,
638 index,
639 );
640 }
641
642 pub unsafe fn begin_statistics(&self, device: &Device, statistics: &StatisticsQuery) {
643 device.cmd_begin_query(
644 self.command_buffer,
645 statistics.pipeline_statistic_query_pool,
646 0,
647 vk::QueryControlFlags::empty(),
648 );
649 device.cmd_begin_query(
650 self.command_buffer,
651 statistics.mesh_primitives_generated_query_pool,
652 0,
653 vk::QueryControlFlags::empty(),
654 );
655 }
656
657 pub unsafe fn end_statistics(&self, device: &Device, statistics: &StatisticsQuery) {
658 device.cmd_end_query(
659 self.command_buffer,
660 statistics.pipeline_statistic_query_pool,
661 0,
662 );
663 device.cmd_end_query(
664 self.command_buffer,
665 statistics.mesh_primitives_generated_query_pool,
666 0,
667 );
668 }
669
670 pub unsafe fn build_acceleration_structures(
675 &self,
676 device: &Device,
677 ty: vk::AccelerationStructureTypeKHR,
678 dst_acceleration_structure: vk::AccelerationStructureKHR,
679 geometry_count: u32,
680 geometries: &vk::AccelerationStructureGeometryKHR,
681 primitive_count: u32,
682 scratch_data: &impl BufferOps,
683 ) {
684 let acceleration_structure_build_geometry_info_khr =
685 vk::AccelerationStructureBuildGeometryInfoKHR {
686 s_type: vk::StructureType::AccelerationStructureBuildGeometryInfoKHR,
687 p_next: null(),
688 ty,
689 flags: vk::BuildAccelerationStructureFlagBitsKHR::PreferFastTraceKHR.into(),
690 mode: vk::BuildAccelerationStructureModeKHR::BuildKHR,
691 src_acceleration_structure: vk::AccelerationStructureKHR::null(),
692 dst_acceleration_structure,
693 geometry_count,
694 p_geometries: geometries as *const _,
695 pp_geometries: null(),
696 scratch_data: vk::DeviceOrHostAddressKHR {
697 device_address: scratch_data.memory().device_address(),
698 },
699 };
700 let acceleration_structure_build_range_info_khr =
701 vk::AccelerationStructureBuildRangeInfoKHR {
702 primitive_count,
703 primitive_offset: 0,
704 first_vertex: 0,
705 transform_offset: 0,
706 };
707
708 device.cmd_build_acceleration_structures_khr(
709 self.command_buffer,
710 1,
711 &acceleration_structure_build_geometry_info_khr,
712 [addr_of!(acceleration_structure_build_range_info_khr)].as_ptr(),
713 );
714 }
715
716 pub unsafe fn bind_ray_tracing_pipeline(&self, device: &Device, pipeline: vk::Pipeline) {
717 device.cmd_bind_pipeline(
718 self.command_buffer,
719 vk::PipelineBindPoint::RayTracingKHR,
720 pipeline,
721 );
722 }
723
724 pub unsafe fn trace_rays<Sbt>(
725 &self,
726 physical_device: &PhysicalDevice,
727 device: &Device,
728 raygen_sbt: Option<&Sbt>,
729 miss_sbt: Option<&Sbt>,
730 hit_sbt: Option<&Sbt>,
731 callable_sbt: Option<&Sbt>,
732 width: u32,
733 height: u32,
734 ) where
735 Sbt: BufferOps,
736 {
737 let rt_props = &physical_device.raytracing_pipeline_properties;
738 let shader_group_handle_size = u64::from(rt_props.shader_group_handle_size);
739
740 let mut raygen_sdar: vk::StridedDeviceAddressRegionKHR = zeroed();
741 if let Some(sbt) = raygen_sbt {
742 raygen_sdar.device_address = sbt.memory().device_address();
743 raygen_sdar.stride = shader_group_handle_size;
744 raygen_sdar.size = shader_group_handle_size;
745 }
746
747 let mut miss_sdar: vk::StridedDeviceAddressRegionKHR = zeroed();
748 if let Some(sbt) = miss_sbt {
749 miss_sdar.device_address = sbt.memory().device_address();
750 miss_sdar.stride = shader_group_handle_size;
751 miss_sdar.size = shader_group_handle_size;
752 }
753
754 let mut hit_sdar: vk::StridedDeviceAddressRegionKHR = zeroed();
755 if let Some(sbt) = hit_sbt {
756 hit_sdar.device_address = sbt.memory().device_address();
757 hit_sdar.stride = shader_group_handle_size;
758 hit_sdar.size = shader_group_handle_size;
759 }
760
761 let mut callable_sdar: vk::StridedDeviceAddressRegionKHR = zeroed();
762 if let Some(sbt) = callable_sbt {
763 callable_sdar.device_address = sbt.memory().device_address();
764 callable_sdar.stride = shader_group_handle_size;
765 callable_sdar.size = shader_group_handle_size;
766 }
767
768 device.cmd_trace_rays_khr(
769 self.command_buffer,
770 &raygen_sdar,
771 &miss_sdar,
772 &hit_sdar,
773 &callable_sdar,
774 width,
775 height,
776 1,
777 );
778 }
779}