vulkano_taskgraph/command_buffer/commands/
copy.rs

1use crate::{
2    command_buffer::{RecordingCommandBuffer, Result},
3    resource::{AccessTypes, ImageLayoutType},
4    Id,
5};
6use ash::vk;
7use smallvec::SmallVec;
8use std::cmp;
9use vulkano::{
10    buffer::Buffer,
11    device::DeviceOwned,
12    image::{sampler::Filter, Image, ImageAspects, ImageSubresourceLayers},
13    DeviceSize, Version, VulkanObject,
14};
15
16/// # Commands to transfer data between resources
17impl RecordingCommandBuffer<'_> {
18    /// Copies data from a buffer to another buffer.
19    pub unsafe fn copy_buffer(
20        &mut self,
21        copy_buffer_info: &CopyBufferInfo<'_>,
22    ) -> Result<&mut Self> {
23        Ok(unsafe { self.copy_buffer_unchecked(copy_buffer_info) })
24    }
25
26    pub unsafe fn copy_buffer_unchecked(
27        &mut self,
28        copy_buffer_info: &CopyBufferInfo<'_>,
29    ) -> &mut Self {
30        let &CopyBufferInfo {
31            src_buffer,
32            dst_buffer,
33            regions,
34            _ne: _,
35        } = copy_buffer_info;
36
37        let src_buffer = unsafe { self.accesses.buffer_unchecked(src_buffer) };
38        let dst_buffer = unsafe { self.accesses.buffer_unchecked(dst_buffer) };
39
40        let fns = self.device().fns();
41
42        if self.device().api_version() >= Version::V1_3
43            || self.device().enabled_extensions().khr_copy_commands2
44        {
45            let cmd_copy_buffer2 = if self.device().api_version() >= Version::V1_3 {
46                fns.v1_3.cmd_copy_buffer2
47            } else {
48                fns.khr_copy_commands2.cmd_copy_buffer2_khr
49            };
50
51            if regions.is_empty() {
52                let regions_vk = [vk::BufferCopy2::default()
53                    .src_offset(0)
54                    .dst_offset(0)
55                    .size(cmp::min(src_buffer.size(), dst_buffer.size()))];
56
57                let copy_buffer_info_vk = vk::CopyBufferInfo2::default()
58                    .src_buffer(src_buffer.handle())
59                    .dst_buffer(dst_buffer.handle())
60                    .regions(&regions_vk);
61
62                unsafe { cmd_copy_buffer2(self.handle(), &copy_buffer_info_vk) };
63            } else {
64                let regions_vk = regions
65                    .iter()
66                    .map(|region| {
67                        let &BufferCopy {
68                            src_offset,
69                            dst_offset,
70                            size,
71                            _ne,
72                        } = region;
73
74                        vk::BufferCopy2::default()
75                            .src_offset(src_offset)
76                            .dst_offset(dst_offset)
77                            .size(size)
78                    })
79                    .collect::<SmallVec<[_; 8]>>();
80
81                let copy_buffer_info_vk = vk::CopyBufferInfo2::default()
82                    .src_buffer(src_buffer.handle())
83                    .dst_buffer(dst_buffer.handle())
84                    .regions(&regions_vk);
85
86                unsafe { cmd_copy_buffer2(self.handle(), &copy_buffer_info_vk) };
87            }
88        } else {
89            let cmd_copy_buffer = fns.v1_0.cmd_copy_buffer;
90
91            if regions.is_empty() {
92                let region_vk = vk::BufferCopy {
93                    src_offset: 0,
94                    dst_offset: 0,
95                    size: cmp::min(src_buffer.size(), dst_buffer.size()),
96                };
97
98                unsafe {
99                    cmd_copy_buffer(
100                        self.handle(),
101                        src_buffer.handle(),
102                        dst_buffer.handle(),
103                        1,
104                        &region_vk,
105                    )
106                };
107            } else {
108                let regions_vk = regions
109                    .iter()
110                    .map(|copy| {
111                        let &BufferCopy {
112                            src_offset,
113                            dst_offset,
114                            size,
115                            _ne: _,
116                        } = copy;
117
118                        vk::BufferCopy {
119                            src_offset,
120                            dst_offset,
121                            size,
122                        }
123                    })
124                    .collect::<SmallVec<[_; 8]>>();
125
126                unsafe {
127                    cmd_copy_buffer(
128                        self.handle(),
129                        src_buffer.handle(),
130                        dst_buffer.handle(),
131                        regions_vk.len() as u32,
132                        regions_vk.as_ptr(),
133                    )
134                };
135            }
136        }
137
138        self
139    }
140
141    /// Copies data from an image to another image.
142    ///
143    /// There are several restrictions:
144    ///
145    /// - The number of samples in the source and destination images must be equal.
146    /// - The size of the uncompressed element format of the source image must be equal to the
147    ///   compressed element format of the destination.
148    /// - If you copy between depth, stencil or depth-stencil images, the format of both images
149    ///   must match exactly.
150    /// - For two-dimensional images, the Z coordinate must be 0 for the image offsets and 1 for
151    ///   the extent. Same for the Y coordinate for one-dimensional images.
152    /// - For non-array images, the base array layer must be 0 and the number of layers must be 1.
153    ///
154    /// If `layer_count` is greater than 1, the copy will happen between each individual layer as
155    /// if they were separate images.
156    pub unsafe fn copy_image(&mut self, copy_image_info: &CopyImageInfo<'_>) -> Result<&mut Self> {
157        Ok(unsafe { self.copy_image_unchecked(copy_image_info) })
158    }
159
160    pub unsafe fn copy_image_unchecked(
161        &mut self,
162        copy_image_info: &CopyImageInfo<'_>,
163    ) -> &mut Self {
164        let &CopyImageInfo {
165            src_image,
166            src_image_layout,
167            dst_image,
168            dst_image_layout,
169            regions,
170            _ne: _,
171        } = copy_image_info;
172
173        let src_image = unsafe { self.accesses.image_unchecked(src_image) };
174        let src_image_layout = AccessTypes::COPY_TRANSFER_READ.image_layout(src_image_layout);
175        let dst_image = unsafe { self.accesses.image_unchecked(dst_image) };
176        let dst_image_layout = AccessTypes::COPY_TRANSFER_WRITE.image_layout(dst_image_layout);
177
178        let fns = self.device().fns();
179
180        if self.device().api_version() >= Version::V1_3
181            || self.device().enabled_extensions().khr_copy_commands2
182        {
183            let cmd_copy_image2 = if self.device().api_version() >= Version::V1_3 {
184                fns.v1_3.cmd_copy_image2
185            } else {
186                fns.khr_copy_commands2.cmd_copy_image2_khr
187            };
188
189            if regions.is_empty() {
190                let min_array_layers = cmp::min(src_image.array_layers(), dst_image.array_layers());
191                let src_extent = src_image.extent();
192                let dst_extent = dst_image.extent();
193                let regions_vk = [vk::ImageCopy2::default()
194                    .src_subresource(
195                        ImageSubresourceLayers {
196                            array_layers: 0..min_array_layers,
197                            ..src_image.subresource_layers()
198                        }
199                        .to_vk(),
200                    )
201                    .src_offset(convert_offset([0; 3]))
202                    .dst_subresource(
203                        ImageSubresourceLayers {
204                            array_layers: 0..min_array_layers,
205                            ..dst_image.subresource_layers()
206                        }
207                        .to_vk(),
208                    )
209                    .dst_offset(convert_offset([0; 3]))
210                    .extent(convert_extent([
211                        cmp::min(src_extent[0], dst_extent[0]),
212                        cmp::min(src_extent[1], dst_extent[1]),
213                        cmp::min(src_extent[2], dst_extent[2]),
214                    ]))];
215
216                let copy_image_info_vk = vk::CopyImageInfo2::default()
217                    .src_image(src_image.handle())
218                    .src_image_layout(src_image_layout.into())
219                    .dst_image(dst_image.handle())
220                    .dst_image_layout(dst_image_layout.into())
221                    .regions(&regions_vk);
222
223                unsafe { cmd_copy_image2(self.handle(), &copy_image_info_vk) };
224            } else {
225                let regions_vk = regions
226                    .iter()
227                    .map(|region| {
228                        let &ImageCopy {
229                            ref src_subresource,
230                            src_offset,
231                            ref dst_subresource,
232                            dst_offset,
233                            extent,
234                            _ne: _,
235                        } = region;
236
237                        vk::ImageCopy2::default()
238                            .src_subresource(src_subresource.to_vk())
239                            .src_offset(convert_offset(src_offset))
240                            .dst_subresource(dst_subresource.to_vk())
241                            .dst_offset(convert_offset(dst_offset))
242                            .extent(convert_extent(extent))
243                    })
244                    .collect::<SmallVec<[_; 8]>>();
245
246                let copy_image_info_vk = vk::CopyImageInfo2::default()
247                    .src_image(src_image.handle())
248                    .src_image_layout(src_image_layout.into())
249                    .dst_image(dst_image.handle())
250                    .dst_image_layout(dst_image_layout.into())
251                    .regions(&regions_vk);
252
253                unsafe { cmd_copy_image2(self.handle(), &copy_image_info_vk) };
254            }
255        } else {
256            let cmd_copy_image = fns.v1_0.cmd_copy_image;
257
258            if regions.is_empty() {
259                let min_array_layers = cmp::min(src_image.array_layers(), dst_image.array_layers());
260                let src_extent = src_image.extent();
261                let dst_extent = dst_image.extent();
262                let region_vk = vk::ImageCopy {
263                    src_subresource: ImageSubresourceLayers {
264                        array_layers: 0..min_array_layers,
265                        ..src_image.subresource_layers()
266                    }
267                    .to_vk(),
268                    src_offset: convert_offset([0; 3]),
269                    dst_subresource: ImageSubresourceLayers {
270                        array_layers: 0..min_array_layers,
271                        ..dst_image.subresource_layers()
272                    }
273                    .to_vk(),
274                    dst_offset: convert_offset([0; 3]),
275                    extent: convert_extent([
276                        cmp::min(src_extent[0], dst_extent[0]),
277                        cmp::min(src_extent[1], dst_extent[1]),
278                        cmp::min(src_extent[2], dst_extent[2]),
279                    ]),
280                };
281
282                unsafe {
283                    cmd_copy_image(
284                        self.handle(),
285                        src_image.handle(),
286                        src_image_layout.into(),
287                        dst_image.handle(),
288                        dst_image_layout.into(),
289                        1,
290                        &region_vk,
291                    )
292                };
293            } else {
294                let regions_vk: SmallVec<[_; 8]> = regions
295                    .iter()
296                    .map(|region| {
297                        let &ImageCopy {
298                            ref src_subresource,
299                            src_offset,
300                            ref dst_subresource,
301                            dst_offset,
302                            extent,
303                            _ne: _,
304                        } = region;
305
306                        vk::ImageCopy {
307                            src_subresource: src_subresource.to_vk(),
308                            src_offset: convert_offset(src_offset),
309                            dst_subresource: dst_subresource.to_vk(),
310                            dst_offset: convert_offset(dst_offset),
311                            extent: convert_extent(extent),
312                        }
313                    })
314                    .collect();
315
316                unsafe {
317                    cmd_copy_image(
318                        self.handle(),
319                        src_image.handle(),
320                        src_image_layout.into(),
321                        dst_image.handle(),
322                        dst_image_layout.into(),
323                        regions_vk.len() as u32,
324                        regions_vk.as_ptr(),
325                    )
326                };
327            }
328        }
329
330        self
331    }
332
333    /// Copies from a buffer to an image.
334    pub unsafe fn copy_buffer_to_image(
335        &mut self,
336        copy_buffer_to_image_info: &CopyBufferToImageInfo<'_>,
337    ) -> Result<&mut Self> {
338        Ok(unsafe { self.copy_buffer_to_image_unchecked(copy_buffer_to_image_info) })
339    }
340
341    pub unsafe fn copy_buffer_to_image_unchecked(
342        &mut self,
343        copy_buffer_to_image_info: &CopyBufferToImageInfo<'_>,
344    ) -> &mut Self {
345        let &CopyBufferToImageInfo {
346            src_buffer,
347            dst_image,
348            dst_image_layout,
349            regions,
350            _ne: _,
351        } = copy_buffer_to_image_info;
352
353        let src_buffer = unsafe { self.accesses.buffer_unchecked(src_buffer) };
354        let dst_image = unsafe { self.accesses.image_unchecked(dst_image) };
355        let dst_image_layout = AccessTypes::COPY_TRANSFER_WRITE.image_layout(dst_image_layout);
356
357        let fns = self.device().fns();
358
359        if self.device().api_version() >= Version::V1_3
360            || self.device().enabled_extensions().khr_copy_commands2
361        {
362            let cmd_copy_buffer_to_image2 = if self.device().api_version() >= Version::V1_3 {
363                fns.v1_3.cmd_copy_buffer_to_image2
364            } else {
365                fns.khr_copy_commands2.cmd_copy_buffer_to_image2_khr
366            };
367
368            if regions.is_empty() {
369                let regions_vk = [vk::BufferImageCopy2::default()
370                    .buffer_offset(0)
371                    .buffer_row_length(0)
372                    .buffer_image_height(0)
373                    .image_subresource(dst_image.subresource_layers().to_vk())
374                    .image_offset(convert_offset([0; 3]))
375                    .image_extent(convert_extent(dst_image.extent()))];
376
377                let copy_buffer_to_image_info_vk = vk::CopyBufferToImageInfo2::default()
378                    .src_buffer(src_buffer.handle())
379                    .dst_image(dst_image.handle())
380                    .dst_image_layout(dst_image_layout.into())
381                    .regions(&regions_vk);
382
383                unsafe { cmd_copy_buffer_to_image2(self.handle(), &copy_buffer_to_image_info_vk) };
384            } else {
385                let regions_vk = regions
386                    .iter()
387                    .map(|region| {
388                        let &BufferImageCopy {
389                            buffer_offset,
390                            buffer_row_length,
391                            buffer_image_height,
392                            ref image_subresource,
393                            image_offset,
394                            image_extent,
395                            _ne: _,
396                        } = region;
397
398                        vk::BufferImageCopy2::default()
399                            .buffer_offset(buffer_offset)
400                            .buffer_row_length(buffer_row_length)
401                            .buffer_image_height(buffer_image_height)
402                            .image_subresource(image_subresource.to_vk())
403                            .image_offset(convert_offset(image_offset))
404                            .image_extent(convert_extent(image_extent))
405                    })
406                    .collect::<SmallVec<[_; 8]>>();
407
408                let copy_buffer_to_image_info_vk = vk::CopyBufferToImageInfo2::default()
409                    .src_buffer(src_buffer.handle())
410                    .dst_image(dst_image.handle())
411                    .dst_image_layout(dst_image_layout.into())
412                    .regions(&regions_vk);
413
414                unsafe { cmd_copy_buffer_to_image2(self.handle(), &copy_buffer_to_image_info_vk) };
415            }
416        } else {
417            let cmd_copy_buffer_to_image = fns.v1_0.cmd_copy_buffer_to_image;
418
419            if regions.is_empty() {
420                let region_vk = vk::BufferImageCopy {
421                    buffer_offset: 0,
422                    buffer_row_length: 0,
423                    buffer_image_height: 0,
424                    image_subresource: dst_image.subresource_layers().to_vk(),
425                    image_offset: convert_offset([0; 3]),
426                    image_extent: convert_extent(dst_image.extent()),
427                };
428
429                unsafe {
430                    cmd_copy_buffer_to_image(
431                        self.handle(),
432                        src_buffer.handle(),
433                        dst_image.handle(),
434                        dst_image_layout.into(),
435                        1,
436                        &region_vk,
437                    )
438                };
439            } else {
440                let regions_vk = regions
441                    .iter()
442                    .map(|region| {
443                        let &BufferImageCopy {
444                            buffer_offset,
445                            buffer_row_length,
446                            buffer_image_height,
447                            ref image_subresource,
448                            image_offset,
449                            image_extent,
450                            _ne: _,
451                        } = region;
452
453                        vk::BufferImageCopy {
454                            buffer_offset,
455                            buffer_row_length,
456                            buffer_image_height,
457                            image_subresource: image_subresource.to_vk(),
458                            image_offset: convert_offset(image_offset),
459                            image_extent: convert_extent(image_extent),
460                        }
461                    })
462                    .collect::<SmallVec<[_; 8]>>();
463
464                unsafe {
465                    cmd_copy_buffer_to_image(
466                        self.handle(),
467                        src_buffer.handle(),
468                        dst_image.handle(),
469                        dst_image_layout.into(),
470                        regions_vk.len() as u32,
471                        regions_vk.as_ptr(),
472                    )
473                };
474            }
475        }
476
477        self
478    }
479
480    /// Copies from an image to a buffer.
481    pub unsafe fn copy_image_to_buffer(
482        &mut self,
483        copy_image_to_buffer_info: &CopyImageToBufferInfo<'_>,
484    ) -> Result<&mut Self> {
485        Ok(unsafe { self.copy_image_to_buffer_unchecked(copy_image_to_buffer_info) })
486    }
487
488    pub unsafe fn copy_image_to_buffer_unchecked(
489        &mut self,
490        copy_image_to_buffer_info: &CopyImageToBufferInfo<'_>,
491    ) -> &mut Self {
492        let &CopyImageToBufferInfo {
493            src_image,
494            src_image_layout,
495            dst_buffer,
496            regions,
497            _ne: _,
498        } = copy_image_to_buffer_info;
499
500        let src_image = unsafe { self.accesses.image_unchecked(src_image) };
501        let src_image_layout = AccessTypes::COPY_TRANSFER_READ.image_layout(src_image_layout);
502        let dst_buffer = unsafe { self.accesses.buffer_unchecked(dst_buffer) };
503
504        let fns = self.device().fns();
505
506        if self.device().api_version() >= Version::V1_3
507            || self.device().enabled_extensions().khr_copy_commands2
508        {
509            let cmd_copy_image_to_buffer2 = if self.device().api_version() >= Version::V1_3 {
510                fns.v1_3.cmd_copy_image_to_buffer2
511            } else {
512                fns.khr_copy_commands2.cmd_copy_image_to_buffer2_khr
513            };
514
515            if regions.is_empty() {
516                let regions_vk = [vk::BufferImageCopy2::default()
517                    .buffer_offset(0)
518                    .buffer_row_length(0)
519                    .buffer_image_height(0)
520                    .image_subresource(src_image.subresource_layers().to_vk())
521                    .image_offset(convert_offset([0; 3]))
522                    .image_extent(convert_extent(src_image.extent()))];
523
524                let copy_image_to_buffer_info_vk = vk::CopyImageToBufferInfo2::default()
525                    .src_image(src_image.handle())
526                    .src_image_layout(src_image_layout.into())
527                    .dst_buffer(dst_buffer.handle())
528                    .regions(&regions_vk);
529
530                unsafe { cmd_copy_image_to_buffer2(self.handle(), &copy_image_to_buffer_info_vk) };
531            } else {
532                let regions_vk = regions
533                    .iter()
534                    .map(|region| {
535                        let &BufferImageCopy {
536                            buffer_offset,
537                            buffer_row_length,
538                            buffer_image_height,
539                            ref image_subresource,
540                            image_offset,
541                            image_extent,
542                            _ne: _,
543                        } = region;
544
545                        vk::BufferImageCopy2::default()
546                            .buffer_offset(buffer_offset)
547                            .buffer_row_length(buffer_row_length)
548                            .buffer_image_height(buffer_image_height)
549                            .image_subresource(image_subresource.to_vk())
550                            .image_offset(convert_offset(image_offset))
551                            .image_extent(convert_extent(image_extent))
552                    })
553                    .collect::<SmallVec<[_; 8]>>();
554
555                let copy_image_to_buffer_info_vk = vk::CopyImageToBufferInfo2::default()
556                    .src_image(src_image.handle())
557                    .src_image_layout(src_image_layout.into())
558                    .dst_buffer(dst_buffer.handle())
559                    .regions(&regions_vk);
560
561                unsafe { cmd_copy_image_to_buffer2(self.handle(), &copy_image_to_buffer_info_vk) };
562            }
563        } else {
564            let cmd_copy_image_to_buffer = fns.v1_0.cmd_copy_image_to_buffer;
565
566            if regions.is_empty() {
567                let region_vk = vk::BufferImageCopy {
568                    buffer_offset: 0,
569                    buffer_row_length: 0,
570                    buffer_image_height: 0,
571                    image_subresource: src_image.subresource_layers().to_vk(),
572                    image_offset: convert_offset([0; 3]),
573                    image_extent: convert_extent(src_image.extent()),
574                };
575
576                unsafe {
577                    cmd_copy_image_to_buffer(
578                        self.handle(),
579                        src_image.handle(),
580                        src_image_layout.into(),
581                        dst_buffer.handle(),
582                        1,
583                        &region_vk,
584                    )
585                };
586            } else {
587                let regions_vk = regions
588                    .iter()
589                    .map(|region| {
590                        let &BufferImageCopy {
591                            buffer_offset,
592                            buffer_row_length,
593                            buffer_image_height,
594                            ref image_subresource,
595                            image_offset,
596                            image_extent,
597                            _ne: _,
598                        } = region;
599
600                        vk::BufferImageCopy {
601                            buffer_offset,
602                            buffer_row_length,
603                            buffer_image_height,
604                            image_subresource: image_subresource.to_vk(),
605                            image_offset: convert_offset(image_offset),
606                            image_extent: convert_extent(image_extent),
607                        }
608                    })
609                    .collect::<SmallVec<[_; 8]>>();
610
611                unsafe {
612                    cmd_copy_image_to_buffer(
613                        self.handle(),
614                        src_image.handle(),
615                        src_image_layout.into(),
616                        dst_buffer.handle(),
617                        regions_vk.len() as u32,
618                        regions_vk.as_ptr(),
619                    )
620                };
621            }
622        }
623
624        self
625    }
626
627    /// Blits an image to another.
628    ///
629    /// A *blit* is similar to an image copy operation, except that the portion of the image that
630    /// is transferred can be resized. You choose an area of the source and an area of the
631    /// destination, and the implementation will resize the area of the source so that it matches
632    /// the size of the area of the destination before writing it.
633    ///
634    /// Blit operations have several restrictions:
635    ///
636    /// - Blit operations are only allowed on queue families that support graphics operations.
637    /// - The format of the source and destination images must support blit operations, which
638    ///   depends on the Vulkan implementation. Vulkan guarantees that some specific formats must
639    ///   always be supported. See tables 52 to 61 of the specifications.
640    /// - Only single-sampled images are allowed.
641    /// - You can only blit between two images whose formats belong to the same type. The types
642    ///   are: floating-point, signed integers, unsigned integers, depth-stencil.
643    /// - If you blit between depth, stencil or depth-stencil images, the format of both images
644    ///   must match exactly.
645    /// - If you blit between depth, stencil or depth-stencil images, only the `Nearest` filter is
646    ///   allowed.
647    /// - For two-dimensional images, the Z coordinate must be 0 for the top-left offset and 1 for
648    ///   the bottom-right offset. Same for the Y coordinate for one-dimensional images.
649    /// - For non-array images, the base array layer must be 0 and the number of layers must be 1.
650    ///
651    /// If `layer_count` is greater than 1, the blit will happen between each individual layer as
652    /// if they were separate images.
653    pub unsafe fn blit_image(&mut self, blit_image_info: &BlitImageInfo<'_>) -> Result<&mut Self> {
654        Ok(unsafe { self.blit_image_unchecked(blit_image_info) })
655    }
656
657    pub unsafe fn blit_image_unchecked(
658        &mut self,
659        blit_image_info: &BlitImageInfo<'_>,
660    ) -> &mut Self {
661        let &BlitImageInfo {
662            src_image,
663            src_image_layout,
664            dst_image,
665            dst_image_layout,
666            regions,
667            filter,
668            _ne: _,
669        } = blit_image_info;
670
671        let src_image = unsafe { self.accesses.image_unchecked(src_image) };
672        let src_image_layout = AccessTypes::BLIT_TRANSFER_READ.image_layout(src_image_layout);
673        let dst_image = unsafe { self.accesses.image_unchecked(dst_image) };
674        let dst_image_layout = AccessTypes::BLIT_TRANSFER_WRITE.image_layout(dst_image_layout);
675
676        let fns = self.device().fns();
677
678        if self.device().api_version() >= Version::V1_3
679            || self.device().enabled_extensions().khr_copy_commands2
680        {
681            let cmd_blit_image2 = if self.device().api_version() >= Version::V1_3 {
682                fns.v1_3.cmd_blit_image2
683            } else {
684                fns.khr_copy_commands2.cmd_blit_image2_khr
685            };
686
687            if regions.is_empty() {
688                let min_array_layers = cmp::min(src_image.array_layers(), dst_image.array_layers());
689                let regions_vk = [vk::ImageBlit2::default()
690                    .src_subresource(
691                        ImageSubresourceLayers {
692                            array_layers: 0..min_array_layers,
693                            ..src_image.subresource_layers()
694                        }
695                        .to_vk(),
696                    )
697                    .src_offsets([[0; 3], src_image.extent()].map(convert_offset))
698                    .dst_subresource(
699                        ImageSubresourceLayers {
700                            array_layers: 0..min_array_layers,
701                            ..src_image.subresource_layers()
702                        }
703                        .to_vk(),
704                    )
705                    .dst_offsets([[0; 3], dst_image.extent()].map(convert_offset))];
706
707                let blit_image_info_vk = vk::BlitImageInfo2::default()
708                    .src_image(src_image.handle())
709                    .src_image_layout(src_image_layout.into())
710                    .dst_image(dst_image.handle())
711                    .dst_image_layout(dst_image_layout.into())
712                    .regions(&regions_vk)
713                    .filter(filter.into());
714
715                unsafe { cmd_blit_image2(self.handle(), &blit_image_info_vk) };
716            } else {
717                let regions_vk = regions
718                    .iter()
719                    .map(|region| {
720                        let &ImageBlit {
721                            ref src_subresource,
722                            src_offsets,
723                            ref dst_subresource,
724                            dst_offsets,
725                            _ne: _,
726                        } = region;
727
728                        vk::ImageBlit2::default()
729                            .src_subresource(src_subresource.to_vk())
730                            .src_offsets(src_offsets.map(convert_offset))
731                            .dst_subresource(dst_subresource.to_vk())
732                            .dst_offsets(dst_offsets.map(convert_offset))
733                    })
734                    .collect::<SmallVec<[_; 8]>>();
735
736                let blit_image_info_vk = vk::BlitImageInfo2::default()
737                    .src_image(src_image.handle())
738                    .src_image_layout(src_image_layout.into())
739                    .dst_image(dst_image.handle())
740                    .dst_image_layout(dst_image_layout.into())
741                    .regions(&regions_vk)
742                    .filter(filter.into());
743
744                unsafe { cmd_blit_image2(self.handle(), &blit_image_info_vk) };
745            }
746        } else {
747            let cmd_blit_image = fns.v1_0.cmd_blit_image;
748
749            if regions.is_empty() {
750                let min_array_layers = cmp::min(src_image.array_layers(), dst_image.array_layers());
751                let region_vk = vk::ImageBlit {
752                    src_subresource: ImageSubresourceLayers {
753                        array_layers: 0..min_array_layers,
754                        ..src_image.subresource_layers()
755                    }
756                    .to_vk(),
757                    src_offsets: [[0; 3], src_image.extent()].map(convert_offset),
758                    dst_subresource: ImageSubresourceLayers {
759                        array_layers: 0..min_array_layers,
760                        ..dst_image.subresource_layers()
761                    }
762                    .to_vk(),
763                    dst_offsets: [[0; 3], dst_image.extent()].map(convert_offset),
764                };
765
766                unsafe {
767                    cmd_blit_image(
768                        self.handle(),
769                        src_image.handle(),
770                        src_image_layout.into(),
771                        dst_image.handle(),
772                        dst_image_layout.into(),
773                        1,
774                        &region_vk,
775                        filter.into(),
776                    )
777                };
778            } else {
779                let regions_vk = regions
780                    .iter()
781                    .map(|region| {
782                        let &ImageBlit {
783                            ref src_subresource,
784                            src_offsets,
785                            ref dst_subresource,
786                            dst_offsets,
787                            _ne: _,
788                        } = region;
789
790                        vk::ImageBlit {
791                            src_subresource: src_subresource.to_vk(),
792                            src_offsets: src_offsets.map(convert_offset),
793                            dst_subresource: dst_subresource.to_vk(),
794                            dst_offsets: dst_offsets.map(convert_offset),
795                        }
796                    })
797                    .collect::<SmallVec<[_; 8]>>();
798
799                unsafe {
800                    cmd_blit_image(
801                        self.handle(),
802                        src_image.handle(),
803                        src_image_layout.into(),
804                        dst_image.handle(),
805                        dst_image_layout.into(),
806                        regions_vk.len() as u32,
807                        regions_vk.as_ptr(),
808                        filter.into(),
809                    )
810                };
811            }
812        }
813
814        self
815    }
816
817    /// Resolves a multisampled image into a single-sampled image.
818    pub unsafe fn resolve_image(
819        &mut self,
820        resolve_image_info: &ResolveImageInfo<'_>,
821    ) -> Result<&mut Self> {
822        Ok(unsafe { self.resolve_image_unchecked(resolve_image_info) })
823    }
824
825    pub unsafe fn resolve_image_unchecked(
826        &mut self,
827        resolve_image_info: &ResolveImageInfo<'_>,
828    ) -> &mut Self {
829        let &ResolveImageInfo {
830            src_image,
831            src_image_layout,
832            dst_image,
833            dst_image_layout,
834            regions,
835            _ne: _,
836        } = resolve_image_info;
837
838        let src_image = unsafe { self.accesses.image_unchecked(src_image) };
839        let src_image_layout = AccessTypes::RESOLVE_TRANSFER_READ.image_layout(src_image_layout);
840        let dst_image = unsafe { self.accesses.image_unchecked(dst_image) };
841        let dst_image_layout = AccessTypes::RESOLVE_TRANSFER_WRITE.image_layout(dst_image_layout);
842
843        let fns = self.device().fns();
844
845        if self.device().api_version() >= Version::V1_3
846            || self.device().enabled_extensions().khr_copy_commands2
847        {
848            let cmd_resolve_image2 = if self.device().api_version() >= Version::V1_3 {
849                fns.v1_3.cmd_resolve_image2
850            } else {
851                fns.khr_copy_commands2.cmd_resolve_image2_khr
852            };
853
854            if regions.is_empty() {
855                let min_array_layers = cmp::min(src_image.array_layers(), dst_image.array_layers());
856                let src_extent = src_image.extent();
857                let dst_extent = dst_image.extent();
858                let regions_vk = [vk::ImageResolve2::default()
859                    .src_subresource(
860                        ImageSubresourceLayers {
861                            array_layers: 0..min_array_layers,
862                            ..src_image.subresource_layers()
863                        }
864                        .to_vk(),
865                    )
866                    .src_offset(convert_offset([0; 3]))
867                    .dst_subresource(
868                        ImageSubresourceLayers {
869                            array_layers: 0..min_array_layers,
870                            ..src_image.subresource_layers()
871                        }
872                        .to_vk(),
873                    )
874                    .dst_offset(convert_offset([0; 3]))
875                    .extent(convert_extent([
876                        cmp::min(src_extent[0], dst_extent[0]),
877                        cmp::min(src_extent[1], dst_extent[1]),
878                        cmp::min(src_extent[2], dst_extent[2]),
879                    ]))];
880
881                let resolve_image_info_vk = vk::ResolveImageInfo2::default()
882                    .src_image(src_image.handle())
883                    .src_image_layout(src_image_layout.into())
884                    .dst_image(dst_image.handle())
885                    .dst_image_layout(dst_image_layout.into())
886                    .regions(&regions_vk);
887
888                unsafe { cmd_resolve_image2(self.handle(), &resolve_image_info_vk) };
889            } else {
890                let regions_vk = regions
891                    .iter()
892                    .map(|region| {
893                        let &ImageResolve {
894                            ref src_subresource,
895                            src_offset,
896                            ref dst_subresource,
897                            dst_offset,
898                            extent,
899                            _ne: _,
900                        } = region;
901
902                        vk::ImageResolve2::default()
903                            .src_subresource(src_subresource.to_vk())
904                            .src_offset(convert_offset(src_offset))
905                            .dst_subresource(dst_subresource.to_vk())
906                            .dst_offset(convert_offset(dst_offset))
907                            .extent(convert_extent(extent))
908                    })
909                    .collect::<SmallVec<[_; 8]>>();
910
911                let resolve_image_info_vk = vk::ResolveImageInfo2::default()
912                    .src_image(src_image.handle())
913                    .src_image_layout(src_image_layout.into())
914                    .dst_image(dst_image.handle())
915                    .dst_image_layout(dst_image_layout.into())
916                    .regions(&regions_vk);
917
918                unsafe { cmd_resolve_image2(self.handle(), &resolve_image_info_vk) };
919            }
920        } else {
921            let cmd_resolve_image = fns.v1_0.cmd_resolve_image;
922
923            if regions.is_empty() {
924                let min_array_layers = cmp::min(src_image.array_layers(), dst_image.array_layers());
925                let src_extent = src_image.extent();
926                let dst_extent = dst_image.extent();
927                let regions_vk = [vk::ImageResolve {
928                    src_subresource: ImageSubresourceLayers {
929                        array_layers: 0..min_array_layers,
930                        ..src_image.subresource_layers()
931                    }
932                    .to_vk(),
933                    src_offset: convert_offset([0; 3]),
934                    dst_subresource: ImageSubresourceLayers {
935                        array_layers: 0..min_array_layers,
936                        ..dst_image.subresource_layers()
937                    }
938                    .to_vk(),
939                    dst_offset: convert_offset([0; 3]),
940                    extent: convert_extent([
941                        cmp::min(src_extent[0], dst_extent[0]),
942                        cmp::min(src_extent[1], dst_extent[1]),
943                        cmp::min(src_extent[2], dst_extent[2]),
944                    ]),
945                }];
946
947                unsafe {
948                    cmd_resolve_image(
949                        self.handle(),
950                        src_image.handle(),
951                        src_image_layout.into(),
952                        dst_image.handle(),
953                        dst_image_layout.into(),
954                        regions_vk.len() as u32,
955                        regions_vk.as_ptr(),
956                    )
957                };
958            } else {
959                let regions_vk = regions
960                    .iter()
961                    .map(|region| {
962                        let &ImageResolve {
963                            ref src_subresource,
964                            src_offset,
965                            ref dst_subresource,
966                            dst_offset,
967                            extent,
968                            _ne: _,
969                        } = region;
970
971                        vk::ImageResolve {
972                            src_subresource: src_subresource.to_vk(),
973                            src_offset: convert_offset(src_offset),
974                            dst_subresource: dst_subresource.to_vk(),
975                            dst_offset: convert_offset(dst_offset),
976                            extent: convert_extent(extent),
977                        }
978                    })
979                    .collect::<SmallVec<[_; 8]>>();
980
981                unsafe {
982                    cmd_resolve_image(
983                        self.handle(),
984                        src_image.handle(),
985                        src_image_layout.into(),
986                        dst_image.handle(),
987                        dst_image_layout.into(),
988                        regions_vk.len() as u32,
989                        regions_vk.as_ptr(),
990                    )
991                };
992            }
993        }
994
995        self
996    }
997}
998
999/// Parameters to copy data from a buffer to another buffer.
1000///
1001/// The fields of `regions` represent bytes.
1002#[derive(Clone, Debug)]
1003pub struct CopyBufferInfo<'a> {
1004    /// The buffer to copy from.
1005    ///
1006    /// The default value is [`Id::INVALID`], which must be overridden.
1007    pub src_buffer: Id<Buffer>,
1008
1009    /// The buffer to copy to.
1010    ///
1011    /// The default value is [`Id::INVALID`], which must be overridden.
1012    pub dst_buffer: Id<Buffer>,
1013
1014    /// The regions of both buffers to copy between, specified in bytes.
1015    ///
1016    /// The default value is a single region, with zero offsets and a `size` equal to the smallest
1017    /// of the two buffers.
1018    pub regions: &'a [BufferCopy<'a>],
1019
1020    pub _ne: crate::NonExhaustive<'a>,
1021}
1022
1023impl Default for CopyBufferInfo<'_> {
1024    #[inline]
1025    fn default() -> Self {
1026        CopyBufferInfo {
1027            src_buffer: Id::INVALID,
1028            dst_buffer: Id::INVALID,
1029            regions: &[],
1030            _ne: crate::NE,
1031        }
1032    }
1033}
1034
1035/// A region of data to copy between buffers.
1036#[derive(Clone, Debug)]
1037pub struct BufferCopy<'a> {
1038    /// The offset in bytes or elements from the start of `src_buffer` that copying will start
1039    /// from.
1040    ///
1041    /// The default value is `0`.
1042    pub src_offset: DeviceSize,
1043
1044    /// The offset in bytes or elements from the start of `dst_buffer` that copying will start
1045    /// from.
1046    ///
1047    /// The default value is `0`.
1048    pub dst_offset: DeviceSize,
1049
1050    /// The number of bytes or elements to copy.
1051    ///
1052    /// The default value is `0`, which must be overridden.
1053    pub size: DeviceSize,
1054
1055    pub _ne: crate::NonExhaustive<'a>,
1056}
1057
1058impl Default for BufferCopy<'_> {
1059    #[inline]
1060    fn default() -> Self {
1061        Self {
1062            src_offset: 0,
1063            dst_offset: 0,
1064            size: 0,
1065            _ne: crate::NE,
1066        }
1067    }
1068}
1069
1070/// Parameters to copy data from an image to another image.
1071#[derive(Clone, Debug)]
1072pub struct CopyImageInfo<'a> {
1073    /// The image to copy from.
1074    ///
1075    /// The default value is [`Id::INVALID`], which must be overridden.
1076    pub src_image: Id<Image>,
1077
1078    /// The layout used for `src_image` during the copy operation.
1079    ///
1080    /// The default value is [`ImageLayoutType::Optimal`].
1081    pub src_image_layout: ImageLayoutType,
1082
1083    /// The image to copy to.
1084    ///
1085    /// The default value is [`Id::INVALID`], which must be overridden.
1086    pub dst_image: Id<Image>,
1087
1088    /// The layout used for `dst_image` during the copy operation.
1089    ///
1090    /// The default value is [`ImageLayoutType::Optimal`].
1091    pub dst_image_layout: ImageLayoutType,
1092
1093    /// The regions of both images to copy between.
1094    ///
1095    /// The default value is a single region, covering the first mip level, and the smallest of the
1096    /// array layers and extent of the two images. All aspects of each image are selected, or
1097    /// `plane0` if the image is multi-planar.
1098    pub regions: &'a [ImageCopy<'a>],
1099
1100    pub _ne: crate::NonExhaustive<'a>,
1101}
1102
1103impl Default for CopyImageInfo<'_> {
1104    #[inline]
1105    fn default() -> Self {
1106        CopyImageInfo {
1107            src_image: Id::INVALID,
1108            src_image_layout: ImageLayoutType::Optimal,
1109            dst_image: Id::INVALID,
1110            dst_image_layout: ImageLayoutType::Optimal,
1111            regions: &[],
1112            _ne: crate::NE,
1113        }
1114    }
1115}
1116
1117/// A region of data to copy between images.
1118#[derive(Clone, Debug)]
1119pub struct ImageCopy<'a> {
1120    /// The subresource of `src_image` to copy from.
1121    ///
1122    /// The default value is empty, which must be overridden.
1123    pub src_subresource: ImageSubresourceLayers,
1124
1125    /// The offset from the zero coordinate of `src_image` that copying will start from.
1126    ///
1127    /// The default value is `[0; 3]`.
1128    pub src_offset: [u32; 3],
1129
1130    /// The subresource of `dst_image` to copy to.
1131    ///
1132    /// The default value is empty, which must be overridden.
1133    pub dst_subresource: ImageSubresourceLayers,
1134
1135    /// The offset from the zero coordinate of `dst_image` that copying will start from.
1136    ///
1137    /// The default value is `[0; 3]`.
1138    pub dst_offset: [u32; 3],
1139
1140    /// The extent of texels to copy.
1141    ///
1142    /// The default value is `[0; 3]`, which must be overridden.
1143    pub extent: [u32; 3],
1144
1145    pub _ne: crate::NonExhaustive<'a>,
1146}
1147
1148impl Default for ImageCopy<'_> {
1149    #[inline]
1150    fn default() -> Self {
1151        Self {
1152            src_subresource: ImageSubresourceLayers {
1153                aspects: ImageAspects::empty(),
1154                mip_level: 0,
1155                array_layers: 0..0,
1156            },
1157            src_offset: [0; 3],
1158            dst_subresource: ImageSubresourceLayers {
1159                aspects: ImageAspects::empty(),
1160                mip_level: 0,
1161                array_layers: 0..0,
1162            },
1163            dst_offset: [0; 3],
1164            extent: [0; 3],
1165            _ne: crate::NE,
1166        }
1167    }
1168}
1169
1170/// Parameters to copy data from a buffer to an image.
1171#[derive(Clone, Debug)]
1172pub struct CopyBufferToImageInfo<'a> {
1173    /// The buffer to copy from.
1174    ///
1175    /// The default value is [`Id::INVALID`], which must be overridden.
1176    pub src_buffer: Id<Buffer>,
1177
1178    /// The image to copy to.
1179    ///
1180    /// The default value is [`Id::INVALID`], which must be overridden.
1181    pub dst_image: Id<Image>,
1182
1183    /// The layout used for `dst_image` during the copy operation.
1184    ///
1185    /// The default value is [`ImageLayoutType::Optimal`].
1186    pub dst_image_layout: ImageLayoutType,
1187
1188    /// The regions of the buffer and image to copy between.
1189    ///
1190    /// The default value is a single region, covering all of the buffer and the first mip level of
1191    /// the image. All aspects of the image are selected, or `plane0` if the image is multi-planar.
1192    pub regions: &'a [BufferImageCopy<'a>],
1193
1194    pub _ne: crate::NonExhaustive<'a>,
1195}
1196
1197impl Default for CopyBufferToImageInfo<'_> {
1198    #[inline]
1199    fn default() -> Self {
1200        CopyBufferToImageInfo {
1201            src_buffer: Id::INVALID,
1202            dst_image: Id::INVALID,
1203            dst_image_layout: ImageLayoutType::Optimal,
1204            regions: &[],
1205            _ne: crate::NE,
1206        }
1207    }
1208}
1209
1210/// Parameters to copy data from an image to a buffer.
1211#[derive(Clone, Debug)]
1212pub struct CopyImageToBufferInfo<'a> {
1213    /// The image to copy from.
1214    ///
1215    /// The default value is [`Id::INVALID`], which must be overridden.
1216    pub src_image: Id<Image>,
1217
1218    /// The layout used for `src_image` during the copy operation.
1219    ///
1220    /// The default value is [`ImageLayoutType::Optimal`].
1221    pub src_image_layout: ImageLayoutType,
1222
1223    /// The buffer to copy to.
1224    ///
1225    /// The default value is [`Id::INVALID`], which must be overridden.
1226    pub dst_buffer: Id<Buffer>,
1227
1228    /// The regions of the image and buffer to copy between.
1229    ///
1230    /// The default value is a single region, covering all of the buffer and the first mip level of
1231    /// the image. All aspects of the image are selected, or `plane0` if the image is multi-planar.
1232    pub regions: &'a [BufferImageCopy<'a>],
1233
1234    pub _ne: crate::NonExhaustive<'a>,
1235}
1236
1237impl Default for CopyImageToBufferInfo<'_> {
1238    #[inline]
1239    fn default() -> Self {
1240        CopyImageToBufferInfo {
1241            src_image: Id::INVALID,
1242            src_image_layout: ImageLayoutType::Optimal,
1243            dst_buffer: Id::INVALID,
1244            regions: &[],
1245            _ne: crate::NE,
1246        }
1247    }
1248}
1249
1250/// A region of data to copy between a buffer and an image.
1251#[derive(Clone, Debug)]
1252pub struct BufferImageCopy<'a> {
1253    /// The offset in bytes from the start of the buffer that copying will start from.
1254    ///
1255    /// The default value is `0`.
1256    pub buffer_offset: DeviceSize,
1257
1258    /// The number of texels between successive rows of image data in the buffer.
1259    ///
1260    /// If set to `0`, the width of the image is used.
1261    ///
1262    /// The default value is `0`.
1263    pub buffer_row_length: u32,
1264
1265    /// The number of rows between successive depth slices of image data in the buffer.
1266    ///
1267    /// If set to `0`, the height of the image is used.
1268    ///
1269    /// The default value is `0`.
1270    pub buffer_image_height: u32,
1271
1272    /// The subresource of the image to copy from/to.
1273    ///
1274    /// The default value is empty, which must be overridden.
1275    pub image_subresource: ImageSubresourceLayers,
1276
1277    /// The offset from the zero coordinate of the image that copying will start from.
1278    ///
1279    /// The default value is `[0; 3]`.
1280    pub image_offset: [u32; 3],
1281
1282    /// The extent of texels in the image to copy.
1283    ///
1284    /// The default value is `[0; 3]`, which must be overridden.
1285    pub image_extent: [u32; 3],
1286
1287    pub _ne: crate::NonExhaustive<'a>,
1288}
1289
1290impl Default for BufferImageCopy<'_> {
1291    #[inline]
1292    fn default() -> Self {
1293        Self {
1294            buffer_offset: 0,
1295            buffer_row_length: 0,
1296            buffer_image_height: 0,
1297            image_subresource: ImageSubresourceLayers {
1298                aspects: ImageAspects::empty(),
1299                mip_level: 0,
1300                array_layers: 0..0,
1301            },
1302            image_offset: [0; 3],
1303            image_extent: [0; 3],
1304            _ne: crate::NE,
1305        }
1306    }
1307}
1308
1309/// Parameters to blit image data.
1310#[derive(Clone, Debug)]
1311pub struct BlitImageInfo<'a> {
1312    /// The image to blit from.
1313    ///
1314    /// The default value is [`Id::INVALID`], which must be overridden.
1315    pub src_image: Id<Image>,
1316
1317    /// The layout used for `src_image` during the blit operation.
1318    ///
1319    /// The default value is [`ImageLayoutType::Optimal`].
1320    pub src_image_layout: ImageLayoutType,
1321
1322    /// The image to blit to.
1323    ///
1324    /// The default value is [`Id::INVALID`], which must be overridden.
1325    pub dst_image: Id<Image>,
1326
1327    /// The layout used for `dst_image` during the blit operation.
1328    ///
1329    /// The default value is [`ImageLayoutType::Optimal`].
1330    pub dst_image_layout: ImageLayoutType,
1331
1332    /// The regions of both images to blit between.
1333    ///
1334    /// The default value is a single region, covering the first mip level, and the smallest of the
1335    /// array layers of the two images. The whole extent of each image is covered, scaling if
1336    /// necessary. All aspects of each image are selected, or `plane0` if the image is
1337    /// multi-planar.
1338    pub regions: &'a [ImageBlit<'a>],
1339
1340    /// The filter to use for sampling `src_image` when the `src_extent` and
1341    /// `dst_extent` of a region are not the same size.
1342    ///
1343    /// The default value is [`Filter::Nearest`].
1344    pub filter: Filter,
1345
1346    pub _ne: crate::NonExhaustive<'a>,
1347}
1348
1349impl Default for BlitImageInfo<'_> {
1350    #[inline]
1351    fn default() -> Self {
1352        BlitImageInfo {
1353            src_image: Id::INVALID,
1354            src_image_layout: ImageLayoutType::Optimal,
1355            dst_image: Id::INVALID,
1356            dst_image_layout: ImageLayoutType::Optimal,
1357            regions: &[],
1358            filter: Filter::Nearest,
1359            _ne: crate::NE,
1360        }
1361    }
1362}
1363
1364/// A region of data to blit between images.
1365#[derive(Clone, Debug)]
1366pub struct ImageBlit<'a> {
1367    /// The subresource of `src_image` to blit from.
1368    ///
1369    /// The default value is empty, which must be overridden.
1370    pub src_subresource: ImageSubresourceLayers,
1371
1372    /// The offsets from the zero coordinate of `src_image`, defining two corners of the region
1373    /// to blit from.
1374    /// If the ordering of the two offsets differs between source and destination, the image will
1375    /// be flipped.
1376    ///
1377    /// The default value is `[[0; 3]; 2]`, which must be overridden.
1378    pub src_offsets: [[u32; 3]; 2],
1379
1380    /// The subresource of `dst_image` to blit to.
1381    ///
1382    /// The default value is empty, which must be overridden.
1383    pub dst_subresource: ImageSubresourceLayers,
1384
1385    /// The offset from the zero coordinate of `dst_image` defining two corners of the
1386    /// region to blit to.
1387    /// If the ordering of the two offsets differs between source and destination, the image will
1388    /// be flipped.
1389    ///
1390    /// The default value is `[[0; 3]; 2]`, which must be overridden.
1391    pub dst_offsets: [[u32; 3]; 2],
1392
1393    pub _ne: crate::NonExhaustive<'a>,
1394}
1395
1396impl Default for ImageBlit<'_> {
1397    #[inline]
1398    fn default() -> Self {
1399        Self {
1400            src_subresource: ImageSubresourceLayers {
1401                aspects: ImageAspects::empty(),
1402                mip_level: 0,
1403                array_layers: 0..0,
1404            },
1405            src_offsets: [[0; 3]; 2],
1406            dst_subresource: ImageSubresourceLayers {
1407                aspects: ImageAspects::empty(),
1408                mip_level: 0,
1409                array_layers: 0..0,
1410            },
1411            dst_offsets: [[0; 3]; 2],
1412            _ne: crate::NE,
1413        }
1414    }
1415}
1416
1417/// Parameters to resolve image data.
1418#[derive(Clone, Debug)]
1419pub struct ResolveImageInfo<'a> {
1420    /// The multisampled image to resolve from.
1421    ///
1422    /// The default value is [`Id::INVALID`], which must be overridden.
1423    pub src_image: Id<Image>,
1424
1425    /// The layout used for `src_image` during the resolve operation.
1426    ///
1427    /// The default value is [`ImageLayoutType::Optimal`].
1428    pub src_image_layout: ImageLayoutType,
1429
1430    /// The non-multisampled image to resolve into.
1431    ///
1432    /// The default value is [`Id::INVALID`], which must be overridden.
1433    pub dst_image: Id<Image>,
1434
1435    /// The layout used for `dst_image` during the resolve operation.
1436    ///
1437    /// The default value is [`ImageLayoutType::Optimal`].
1438    pub dst_image_layout: ImageLayoutType,
1439
1440    /// The regions of both images to resolve between.
1441    ///
1442    /// The default value is a single region, covering the first mip level, and the smallest of the
1443    /// array layers and extent of the two images. All aspects of each image are selected, or
1444    /// `plane0` if the image is multi-planar.
1445    pub regions: &'a [ImageResolve<'a>],
1446
1447    pub _ne: crate::NonExhaustive<'a>,
1448}
1449
1450impl Default for ResolveImageInfo<'_> {
1451    #[inline]
1452    fn default() -> Self {
1453        ResolveImageInfo {
1454            src_image: Id::INVALID,
1455            src_image_layout: ImageLayoutType::Optimal,
1456            dst_image: Id::INVALID,
1457            dst_image_layout: ImageLayoutType::Optimal,
1458            regions: &[],
1459            _ne: crate::NE,
1460        }
1461    }
1462}
1463
1464/// A region of data to resolve between images.
1465#[derive(Clone, Debug)]
1466pub struct ImageResolve<'a> {
1467    /// The subresource of `src_image` to resolve from.
1468    ///
1469    /// The default value is empty, which must be overridden.
1470    pub src_subresource: ImageSubresourceLayers,
1471
1472    /// The offset from the zero coordinate of `src_image` that resolving will start from.
1473    ///
1474    /// The default value is `[0; 3]`.
1475    pub src_offset: [u32; 3],
1476
1477    /// The subresource of `dst_image` to resolve into.
1478    ///
1479    /// The default value is empty, which must be overridden.
1480    pub dst_subresource: ImageSubresourceLayers,
1481
1482    /// The offset from the zero coordinate of `dst_image` that resolving will start from.
1483    ///
1484    /// The default value is `[0; 3]`.
1485    pub dst_offset: [u32; 3],
1486
1487    /// The extent of texels to resolve.
1488    ///
1489    /// The default value is `[0; 3]`, which must be overridden.
1490    pub extent: [u32; 3],
1491
1492    pub _ne: crate::NonExhaustive<'a>,
1493}
1494
1495impl Default for ImageResolve<'_> {
1496    #[inline]
1497    fn default() -> Self {
1498        Self {
1499            src_subresource: ImageSubresourceLayers {
1500                aspects: ImageAspects::empty(),
1501                mip_level: 0,
1502                array_layers: 0..0,
1503            },
1504            src_offset: [0; 3],
1505            dst_subresource: ImageSubresourceLayers {
1506                aspects: ImageAspects::empty(),
1507                mip_level: 0,
1508                array_layers: 0..0,
1509            },
1510            dst_offset: [0; 3],
1511            extent: [0; 3],
1512            _ne: crate::NE,
1513        }
1514    }
1515}
1516
1517fn convert_offset(offset: [u32; 3]) -> vk::Offset3D {
1518    vk::Offset3D {
1519        x: offset[0] as i32,
1520        y: offset[1] as i32,
1521        z: offset[2] as i32,
1522    }
1523}
1524
1525fn convert_extent(extent: [u32; 3]) -> vk::Extent3D {
1526    vk::Extent3D {
1527        width: extent[0],
1528        height: extent[1],
1529        depth: extent[2],
1530    }
1531}