1use crate::sealed::Sealed;
2
3pub use {
4 self::Samples::*,
5 crate::{
6 access::Access,
7 backend::Image,
8 encode::Encoder,
9 queue::{Ownership, QueueId},
10 stage::PipelineStages,
11 },
12};
13use {
14 crate::{
15 format::{AspectFlags, Format},
16 Extent2, Extent3, ImageSize, Offset3,
17 },
18 std::ops::Range,
19};
20
21bitflags::bitflags! {
22 #[cfg_attr(feature = "serde-1", derive(serde::Serialize, serde::Deserialize))]
24 pub struct ImageUsage: u32 {
25 const TRANSFER_SRC = 0x001;
27
28 const TRANSFER_DST = 0x002;
30
31 const SAMPLED = 0x004;
33
34 const STORAGE = 0x008;
36
37 const COLOR_ATTACHMENT = 0x010;
39
40 const DEPTH_STENCIL_ATTACHMENT = 0x020;
42
43 const INPUT_ATTACHMENT = 0x080;
45 }
46}
47
48impl ImageUsage {
49 pub fn is_render_target(self) -> bool {
51 self.intersects(Self::COLOR_ATTACHMENT | Self::DEPTH_STENCIL_ATTACHMENT)
52 }
53
54 pub fn is_render_target_only(self) -> bool {
57 self.is_render_target()
58 && !self.intersects(
59 Self::TRANSFER_SRC
60 | Self::TRANSFER_DST
61 | Self::SAMPLED
62 | Self::STORAGE
63 | Self::INPUT_ATTACHMENT,
64 )
65 }
66
67 pub fn is_read_only(self) -> bool {
70 !self.intersects(
71 Self::TRANSFER_DST
72 | Self::STORAGE
73 | Self::COLOR_ATTACHMENT
74 | Self::DEPTH_STENCIL_ATTACHMENT,
75 )
76 }
77}
78
79#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
86#[cfg_attr(feature = "serde-1", derive(serde::Serialize, serde::Deserialize))]
87pub enum Layout {
88 General,
92
93 ColorAttachmentOptimal,
95
96 DepthStencilAttachmentOptimal,
98
99 DepthStencilReadOnlyOptimal,
102
103 ShaderReadOnlyOptimal,
106
107 TransferSrcOptimal,
110
111 TransferDstOptimal,
114
115 Present,
118}
119
120impl Default for Layout {
121 fn default() -> Self {
122 Self::General
123 }
124}
125
126#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
128#[cfg_attr(feature = "serde-1", derive(serde::Serialize, serde::Deserialize))]
129pub enum ImageExtent {
130 D1 {
132 width: ImageSize,
134 },
135 D2 {
137 width: ImageSize,
139
140 height: ImageSize,
142 },
143 D3 {
145 width: ImageSize,
147
148 height: ImageSize,
150
151 depth: ImageSize,
153 },
154}
155
156impl From<Extent2> for ImageExtent {
157 fn from(extent: Extent2) -> Self {
158 ImageExtent::D2 {
159 width: extent.width,
160 height: extent.height,
161 }
162 }
163}
164
165impl From<Extent3> for ImageExtent {
166 fn from(extent: Extent3) -> Self {
167 ImageExtent::D3 {
168 width: extent.width,
169 height: extent.height,
170 depth: extent.depth,
171 }
172 }
173}
174
175impl ImageExtent {
176 pub fn into_3d(self) -> Extent3 {
179 match self {
180 Self::D1 { width } => Extent3::new(width, 1, 1),
181 Self::D2 { width, height } => Extent3::new(width, height, 1),
182 Self::D3 {
183 width,
184 height,
185 depth,
186 } => Extent3::new(width, height, depth),
187 }
188 }
189
190 pub fn into_2d(self) -> Extent2 {
194 match self {
195 Self::D1 { width } => Extent2::new(width, 1),
196 Self::D2 { width, height } => Extent2::new(width, height),
197 Self::D3 { width, height, .. } => Extent2::new(width, height),
198 }
199 }
200}
201
202impl PartialEq<Extent2> for ImageExtent {
203 fn eq(&self, rhs: &Extent2) -> bool {
204 match self {
205 ImageExtent::D2 { width, height } => *width == rhs.width && *height == rhs.height,
206 _ => false,
207 }
208 }
209}
210
211impl PartialEq<Extent3> for ImageExtent {
212 fn eq(&self, rhs: &Extent3) -> bool {
213 match self {
214 ImageExtent::D3 {
215 width,
216 height,
217 depth,
218 } => *width == rhs.width && *height == rhs.height && *depth == rhs.depth,
219 _ => false,
220 }
221 }
222}
223
224impl PartialEq<ImageExtent> for Extent2 {
225 fn eq(&self, rhs: &ImageExtent) -> bool {
226 match rhs {
227 ImageExtent::D2 { width, height } => self.width == *width && self.height == *height,
228 _ => false,
229 }
230 }
231}
232
233impl PartialEq<ImageExtent> for Extent3 {
234 fn eq(&self, rhs: &ImageExtent) -> bool {
235 match rhs {
236 ImageExtent::D3 {
237 width,
238 height,
239 depth,
240 } => self.width == *width && self.height == *height && self.depth == *depth,
241 _ => false,
242 }
243 }
244}
245
246#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
248#[cfg_attr(feature = "serde-1", derive(serde::Serialize, serde::Deserialize))]
249pub enum Samples {
250 Samples1,
252 Samples2,
254 Samples4,
256 Samples8,
258 Samples16,
260 Samples32,
262 Samples64,
264}
265
266impl Default for Samples {
267 fn default() -> Self {
268 Samples::Samples1
269 }
270}
271
272#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
274#[cfg_attr(feature = "serde-1", derive(serde::Serialize, serde::Deserialize))]
275pub struct ImageInfo {
276 pub extent: ImageExtent,
278
279 pub format: Format,
281
282 pub levels: u32,
284
285 pub layers: u32,
287
288 pub samples: Samples,
290
291 pub usage: ImageUsage,
293}
294#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
297#[cfg_attr(feature = "serde-1", derive(serde::Serialize, serde::Deserialize))]
298pub struct SubresourceRange {
299 pub aspect: AspectFlags,
300 pub first_level: u32,
301 pub level_count: u32,
302 pub first_layer: u32,
303 pub layer_count: u32,
304}
305
306impl SubresourceRange {
307 pub fn new(aspect: AspectFlags, levels: Range<u32>, layers: Range<u32>) -> Self {
308 assert!(levels.end >= levels.start);
309
310 assert!(layers.end >= layers.start);
311
312 SubresourceRange {
313 aspect,
314 first_level: levels.start,
315 level_count: levels.end - levels.start,
316 first_layer: layers.start,
317 layer_count: layers.end - layers.start,
318 }
319 }
320
321 pub fn subresource(subresource: Subresource) -> Self {
322 SubresourceRange {
323 aspect: subresource.aspect,
324 first_level: subresource.level,
325 level_count: 1,
326 first_layer: subresource.layer,
327 layer_count: 1,
328 }
329 }
330
331 pub fn layers(layers: SubresourceLayers) -> Self {
332 SubresourceRange {
333 aspect: layers.aspect,
334 first_level: layers.level,
335 level_count: 1,
336 first_layer: layers.first_layer,
337 layer_count: layers.layer_count,
338 }
339 }
340
341 pub fn whole(info: &ImageInfo) -> Self {
342 SubresourceRange {
343 aspect: info.format.aspect_flags(),
344 first_level: 0,
345 level_count: info.levels,
346 first_layer: 0,
347 layer_count: info.layers,
348 }
349 }
350
351 pub fn color(levels: Range<u32>, layers: Range<u32>) -> Self {
352 Self::new(AspectFlags::COLOR, levels, layers)
353 }
354
355 pub fn depth(levels: Range<u32>, layers: Range<u32>) -> Self {
356 Self::new(AspectFlags::DEPTH, levels, layers)
357 }
358
359 pub fn stencil(levels: Range<u32>, layers: Range<u32>) -> Self {
360 Self::new(AspectFlags::STENCIL, levels, layers)
361 }
362
363 pub fn depth_stencil(levels: Range<u32>, layers: Range<u32>) -> Self {
364 Self::new(AspectFlags::DEPTH | AspectFlags::STENCIL, levels, layers)
365 }
366}
367
368#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
372#[cfg_attr(feature = "serde-1", derive(serde::Serialize, serde::Deserialize))]
373pub struct SubresourceLayers {
374 pub aspect: AspectFlags,
375 pub level: u32,
376 pub first_layer: u32,
377 pub layer_count: u32,
378}
379
380impl SubresourceLayers {
381 pub fn new(aspect: AspectFlags, level: u32, layers: Range<u32>) -> Self {
382 assert!(layers.end >= layers.start);
383
384 SubresourceLayers {
385 aspect,
386 level,
387 first_layer: layers.start,
388 layer_count: layers.end - layers.start,
389 }
390 }
391
392 pub fn subresource(subresource: Subresource) -> Self {
393 SubresourceLayers {
394 aspect: subresource.aspect,
395 level: subresource.level,
396 first_layer: subresource.layer,
397 layer_count: 1,
398 }
399 }
400
401 pub fn all_layers(info: &ImageInfo, level: u32) -> Self {
402 assert!(level < info.levels);
403
404 SubresourceLayers {
405 aspect: info.format.aspect_flags(),
406 level,
407 first_layer: 0,
408 layer_count: info.layers,
409 }
410 }
411
412 pub fn color(level: u32, layers: Range<u32>) -> Self {
413 Self::new(AspectFlags::COLOR, level, layers)
414 }
415
416 pub fn depth(level: u32, layers: Range<u32>) -> Self {
417 Self::new(AspectFlags::DEPTH, level, layers)
418 }
419
420 pub fn stencil(level: u32, layers: Range<u32>) -> Self {
421 Self::new(AspectFlags::STENCIL, level, layers)
422 }
423
424 pub fn depth_stencil(level: u32, layers: Range<u32>) -> Self {
425 Self::new(AspectFlags::DEPTH | AspectFlags::STENCIL, level, layers)
426 }
427}
428
429impl From<SubresourceLayers> for SubresourceRange {
430 fn from(layers: SubresourceLayers) -> Self {
431 SubresourceRange::layers(layers)
432 }
433}
434
435#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
439#[cfg_attr(feature = "serde-1", derive(serde::Serialize, serde::Deserialize))]
440pub struct Subresource {
441 pub aspect: AspectFlags,
442 pub level: u32,
443 pub layer: u32,
444}
445
446impl Subresource {
447 pub fn new(aspect: AspectFlags, level: u32, layer: u32) -> Self {
448 Subresource {
449 aspect,
450 level,
451 layer,
452 }
453 }
454
455 pub fn from_info(info: &ImageInfo, level: u32, layer: u32) -> Self {
456 assert!(level < info.levels);
457
458 assert!(layer < info.layers);
459
460 Subresource {
461 aspect: info.format.aspect_flags(),
462 level,
463 layer,
464 }
465 }
466
467 pub fn color(level: u32, layer: u32) -> Self {
468 Self::new(AspectFlags::COLOR, level, layer)
469 }
470
471 pub fn depth(level: u32, layer: u32) -> Self {
472 Self::new(AspectFlags::DEPTH, level, layer)
473 }
474
475 pub fn stencil(level: u32, layer: u32) -> Self {
476 Self::new(AspectFlags::STENCIL, level, layer)
477 }
478
479 pub fn depth_stencil(level: u32, layer: u32) -> Self {
480 Self::new(AspectFlags::DEPTH | AspectFlags::STENCIL, level, layer)
481 }
482}
483
484impl From<Subresource> for SubresourceLayers {
485 fn from(subresource: Subresource) -> Self {
486 SubresourceLayers::subresource(subresource)
487 }
488}
489
490impl From<Subresource> for SubresourceRange {
491 fn from(subresource: Subresource) -> Self {
492 SubresourceRange::subresource(subresource)
493 }
494}
495
496#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
497#[cfg_attr(feature = "serde-1", derive(serde::Serialize, serde::Deserialize))]
498pub struct ImageBlit {
499 pub src_subresource: SubresourceLayers,
500 pub src_offsets: [Offset3; 2],
501 pub dst_subresource: SubresourceLayers,
502 pub dst_offsets: [Offset3; 2],
503}
504
505#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
506pub struct LayoutTransition<'a> {
507 pub image: &'a Image,
508 pub old_access: Access,
509 pub old_layout: Option<Layout>,
510 pub new_access: Access,
511 pub new_layout: Layout,
512 pub range: SubresourceRange,
513}
514
515#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
516pub struct ImageMemoryBarrier<'a> {
517 pub image: &'a Image,
518 pub old_access: Access,
519 pub old_layout: Option<Layout>,
520 pub new_access: Access,
521 pub new_layout: Layout,
522 pub family_transfer: Option<(u32, u32)>,
523 pub range: SubresourceRange,
524}
525
526impl<'a> ImageMemoryBarrier<'a> {
527 pub fn transition_whole(
528 image: &'a Image,
529 access: Range<Access>,
530 layout: Range<Layout>,
531 ) -> Self {
532 ImageMemoryBarrier {
533 range: SubresourceRange::whole(image.info()),
534 image,
535 old_access: access.start,
536 new_access: access.end,
537 old_layout: Some(layout.start),
538 new_layout: layout.end,
539 family_transfer: None,
540 }
541 }
542
543 pub fn initialize_whole(image: &'a Image, access: Access, layout: Layout) -> Self {
544 ImageMemoryBarrier {
545 range: SubresourceRange::whole(image.info()),
546 image,
547 old_access: Access::empty(),
548 old_layout: None,
549 new_access: access,
550 new_layout: layout,
551 family_transfer: None,
552 }
553 }
554}
555
556impl<'a> From<LayoutTransition<'a>> for ImageMemoryBarrier<'a> {
557 fn from(value: LayoutTransition<'a>) -> Self {
558 ImageMemoryBarrier {
559 image: value.image,
560 old_access: value.old_access,
561 old_layout: value.old_layout,
562 new_access: value.new_access,
563 new_layout: value.new_layout,
564 family_transfer: None,
565 range: value.range,
566 }
567 }
568}
569
570#[derive(Clone, Debug, PartialEq, Eq, Hash)]
571pub struct ImageSubresourceRange {
572 pub image: Image,
573 pub range: SubresourceRange,
574}
575
576#[derive(Clone, Debug, PartialEq, Eq, Hash)]
584pub struct ImageSubresourceState {
585 pub subresource: ImageSubresourceRange,
586 pub access: Access,
587 pub stages: PipelineStages,
588 pub layout: Option<Layout>,
589 pub family: Ownership,
590}
591
592impl ImageSubresourceState {
593 pub fn access<'a>(
595 &'a mut self,
596 access: Access,
597 stages: PipelineStages,
598 layout: Layout,
599 queue: QueueId,
600 encoder: &mut Encoder<'a>,
601 ) -> &'a Self {
602 match self.family {
603 Ownership::NotOwned => encoder.image_barriers(
604 self.stages,
605 stages,
606 encoder.scope().to_scope([ImageMemoryBarrier {
607 image: &self.subresource.image,
608 old_access: self.access,
609 new_access: access,
610 old_layout: self.layout,
611 new_layout: layout,
612 family_transfer: None,
613 range: self.subresource.range,
614 }]),
615 ),
616 Ownership::Owned { family } => {
617 assert_eq!(family, queue.family, "Wrong queue family owns the buffer");
618
619 encoder.image_barriers(
620 self.stages,
621 stages,
622 encoder.scope().to_scope([ImageMemoryBarrier {
623 image: &self.subresource.image,
624 old_access: self.access,
625 new_access: access,
626 old_layout: self.layout,
627 new_layout: layout,
628 family_transfer: None,
629 range: self.subresource.range,
630 }]),
631 )
632 }
633 Ownership::Transition { from, to } => {
634 assert_eq!(
635 to, queue.family,
636 "Image is being transitioned to wrong queue family"
637 );
638
639 encoder.image_barriers(
640 self.stages,
641 stages,
642 encoder.scope().to_scope([ImageMemoryBarrier {
643 image: &self.subresource.image,
644 old_access: self.access,
645 new_access: access,
646 old_layout: self.layout,
647 new_layout: layout,
648 family_transfer: Some((from, to)),
649 range: self.subresource.range,
650 }]),
651 )
652 }
653 }
654 self.stages = stages;
655 self.access = access;
656 self.layout = Some(layout);
657 self
658 }
659
660 pub fn overwrite<'a>(
662 &'a mut self,
663 access: Access,
664 stages: PipelineStages,
665 layout: Layout,
666 queue: QueueId,
667 encoder: &mut Encoder<'a>,
668 ) -> &'a ImageSubresourceRange {
669 encoder.image_barriers(
670 self.stages,
671 stages,
672 encoder.scope().to_scope([ImageMemoryBarrier {
673 image: &self.subresource.image,
674 old_access: Access::empty(),
675 new_access: access,
676 old_layout: None,
677 new_layout: layout,
678 family_transfer: None,
679 range: self.subresource.range,
680 }]),
681 );
682 self.family = Ownership::Owned {
683 family: queue.family,
684 };
685 self.stages = stages;
686 self.access = access;
687 self.layout = Some(layout);
688 &self.subresource
689 }
690}
691
692#[derive(Copy, Clone, Debug)]
693pub enum ColorAttachmentOptimal {}
694
695#[derive(Copy, Clone, Debug)]
696pub enum DepthStencilAttachmentOptimal {}
697
698#[derive(Copy, Clone, Debug)]
699pub enum DepthStencilReadOnlyOptimal {}
700
701#[derive(Copy, Clone, Debug)]
702pub enum ShaderReadOnlyOptimal {}
703
704#[derive(Copy, Clone, Debug)]
705pub enum TransferSrcOptimal {}
706
707#[derive(Copy, Clone, Debug)]
708pub enum TransferDstOptimal {}
709
710#[derive(Copy, Clone, Debug)]
711pub enum Present {}
712
713#[derive(Copy, Clone, Debug)]
714pub enum General {}
715
716pub trait StaticLayout {
717 const LAYOUT: Layout;
718}
719
720impl StaticLayout for ColorAttachmentOptimal {
721 const LAYOUT: Layout = Layout::ColorAttachmentOptimal;
722}
723impl StaticLayout for DepthStencilAttachmentOptimal {
724 const LAYOUT: Layout = Layout::DepthStencilAttachmentOptimal;
725}
726impl StaticLayout for DepthStencilReadOnlyOptimal {
727 const LAYOUT: Layout = Layout::DepthStencilReadOnlyOptimal;
728}
729impl StaticLayout for ShaderReadOnlyOptimal {
730 const LAYOUT: Layout = Layout::ShaderReadOnlyOptimal;
731}
732impl StaticLayout for TransferSrcOptimal {
733 const LAYOUT: Layout = Layout::TransferSrcOptimal;
734}
735impl StaticLayout for TransferDstOptimal {
736 const LAYOUT: Layout = Layout::TransferDstOptimal;
737}
738impl StaticLayout for Present {
739 const LAYOUT: Layout = Layout::Present;
740}
741impl StaticLayout for General {
742 const LAYOUT: Layout = Layout::General;
743}
744
745impl Sealed for (Image, Layout) {}