Skip to main content

vulkano/image/
layout.rs

1use super::ImageAspect;
2use crate::macros::vulkan_enum;
3
4vulkan_enum! {
5    #[non_exhaustive]
6
7    /// In-memory layout of the pixel data of an image.
8    ///
9    /// The pixel data of a Vulkan image is arranged in a particular way, which is called its
10    /// *layout*. Each image subresource (mipmap level and array layer) in an image can have a
11    /// different layout, but usually the whole image has its data in the same layout. Layouts are
12    /// abstract in the sense that the user does not know the specific details of each layout; the
13    /// device driver is free to implement each layout in the way it sees fit.
14    ///
15    /// The layout of a newly created image is either `Undefined` or `Preinitialized`. Every
16    /// operation that can be performed on an image is only possible with specific layouts, so
17    /// before the operation is performed, the user must perform a *layout transition* on the
18    /// image. This rearranges the pixel data from one layout into another. Layout transitions are
19    /// performed as part of pipeline barriers in a command buffer.
20    ///
21    /// The `General` layout is compatible with any operation, so layout transitions are never
22    /// needed. However, the other layouts, while more restricted, are usually better optimised for
23    /// a particular type of operation than `General`, so they are usually preferred.
24    ///
25    /// Vulkan does not keep track of layouts itself, so it is the responsibility of the user to
26    /// keep track of this information. When performing a layout transition, the previous layout
27    /// must be specified as well. Some operations allow for different layouts, but require the
28    /// user to specify which one. Vulkano helps with this by providing sensible defaults,
29    /// automatically tracking the layout of each image when creating a command buffer, and adding
30    /// layout transitions where needed.
31    ImageLayout = ImageLayout(i32);
32
33    /// The layout of the data is unknown, and the image is treated as containing no valid data.
34    /// Transitioning from `Undefined` will discard any existing pixel data.
35    Undefined = UNDEFINED,
36
37    /// A general-purpose layout that can be used for any operation. Some operations may only allow
38    /// `General`, such as storage images, but many have a more specific layout that is better
39    /// optimized for that purpose.
40    General = GENERAL,
41
42    /// For a color image used as a color or resolve attachment in a framebuffer. Images that are
43    /// transitioned into this layout must have the `color_attachment` usage enabled.
44    ColorAttachmentOptimal = COLOR_ATTACHMENT_OPTIMAL,
45
46    /// A combination of `DepthAttachmentOptimal` for the depth aspect of the image,
47    /// and `StencilAttachmentOptimal` for the stencil aspect of the image.
48    DepthStencilAttachmentOptimal = DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
49
50    /// A combination of `DepthReadOnlyOptimal` for the depth aspect of the image,
51    /// and `StencilReadOnlyOptimal` for the stencil aspect of the image.
52    DepthStencilReadOnlyOptimal = DEPTH_STENCIL_READ_ONLY_OPTIMAL,
53
54    /// For a color image used as a (combined) sampled image or input attachment in a shader.
55    /// Images that are transitioned into this layout must have the `sampled` or `input_attachment`
56    /// usages enabled.
57    ShaderReadOnlyOptimal = SHADER_READ_ONLY_OPTIMAL,
58
59    /// For operations that transfer data from an image (copy, blit).
60    TransferSrcOptimal = TRANSFER_SRC_OPTIMAL,
61
62    /// For operations that transfer data to an image (copy, blit, clear).
63    TransferDstOptimal = TRANSFER_DST_OPTIMAL,
64
65    /// When creating an image, this specifies that the initial data is going to be directly
66    /// written to from the CPU. Unlike `Undefined`, the image is assumed to contain valid data when
67    /// transitioning from this layout. However, this only works right when the image has linear
68    /// tiling, optimal tiling gives undefined results.
69    Preinitialized = PREINITIALIZED,
70
71    /// A combination of `DepthReadOnlyOptimal` for the depth aspect of the image,
72    /// and `StencilAttachmentOptimal` for the stencil aspect of the image.
73    DepthReadOnlyStencilAttachmentOptimal = DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL
74    RequiresOneOf([
75        RequiresAllOf([APIVersion(V1_1)]),
76        RequiresAllOf([DeviceExtension(khr_maintenance2)]),
77    ]),
78
79    /// A combination of `DepthAttachmentOptimal` for the depth aspect of the image,
80    /// and `StencilReadOnlyOptimal` for the stencil aspect of the image.
81    DepthAttachmentStencilReadOnlyOptimal = DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL
82    RequiresOneOf([
83        RequiresAllOf([APIVersion(V1_1)]),
84        RequiresAllOf([DeviceExtension(khr_maintenance2)]),
85    ]),
86
87    /// For a depth image used as a depth attachment in a framebuffer.
88    DepthAttachmentOptimal = DEPTH_ATTACHMENT_OPTIMAL
89    RequiresOneOf([
90        RequiresAllOf([APIVersion(V1_2)]),
91        RequiresAllOf([DeviceExtension(khr_separate_depth_stencil_layouts)]),
92    ]),
93
94    /// For a depth image used as a read-only depth attachment in a framebuffer, or
95    /// as a (combined) sampled image or input attachment in a shader.
96    DepthReadOnlyOptimal = DEPTH_READ_ONLY_OPTIMAL
97    RequiresOneOf([
98        RequiresAllOf([APIVersion(V1_2)]),
99        RequiresAllOf([DeviceExtension(khr_separate_depth_stencil_layouts)]),
100    ]),
101
102    /// For a stencil image used as a stencil attachment in a framebuffer.
103    StencilAttachmentOptimal = STENCIL_ATTACHMENT_OPTIMAL
104    RequiresOneOf([
105        RequiresAllOf([APIVersion(V1_2)]),
106        RequiresAllOf([DeviceExtension(khr_separate_depth_stencil_layouts)]),
107    ]),
108
109    /// For a stencil image used as a read-only stencil attachment in a framebuffer, or
110    /// as a (combined) sampled image or input attachment in a shader.
111    StencilReadOnlyOptimal = STENCIL_READ_ONLY_OPTIMAL
112    RequiresOneOf([
113        RequiresAllOf([APIVersion(V1_2)]),
114        RequiresAllOf([DeviceExtension(khr_separate_depth_stencil_layouts)]),
115    ]),
116
117    /* TODO: enable
118    // TODO: document
119    ReadOnlyOptimal = READ_ONLY_OPTIMAL
120    RequiresOneOf([
121        RequiresAllOf([APIVersion(V1_3)]),
122        RequiresAllOf([DeviceExtension(khr_synchronization2)]),
123    ]),*/
124
125    /* TODO: enable
126    // TODO: document
127    AttachmentOptimal = ATTACHMENT_OPTIMAL
128    RequiresOneOf([
129        RequiresAllOf([APIVersion(V1_3)]),
130        RequiresAllOf([DeviceExtension(khr_synchronization2)]),
131    ]),*/
132
133    /// The layout of images that are held in a swapchain. Images are in this layout when they are
134    /// acquired from the swapchain, and must be transitioned back into this layout before
135    /// presenting them.
136    PresentSrc = PRESENT_SRC_KHR
137    RequiresOneOf([
138        RequiresAllOf([DeviceExtension(khr_swapchain)]),
139    ]),
140
141    /* TODO: enable
142    // TODO: document
143    VideoDecodeDst = VIDEO_DECODE_DST_KHR
144    RequiresOneOf([
145        RequiresAllOf([DeviceExtension(khr_video_decode_queue)]),
146    ]),*/
147
148    /* TODO: enable
149    // TODO: document
150    VideoDecodeSrc = VIDEO_DECODE_SRC_KHR
151    RequiresOneOf([
152        RequiresAllOf([DeviceExtension(khr_video_decode_queue)]),
153    ]),*/
154
155    /* TODO: enable
156    // TODO: document
157    VideoDecodeDpb = VIDEO_DECODE_DPB_KHR
158    RequiresOneOf([
159        RequiresAllOf([DeviceExtension(khr_video_decode_queue)]),
160    ]),*/
161
162    /* TODO: enable
163    // TODO: document
164    SharedPresent = SHARED_PRESENT_KHR
165    RequiresOneOf([
166        RequiresAllOf([DeviceExtension(khr_shared_presentable_image)]),
167    ]),*/
168
169    /* TODO: enable
170    // TODO: document
171    FragmentDensityMapOptimal = FRAGMENT_DENSITY_MAP_OPTIMAL_EXT
172    RequiresOneOf([
173        RequiresAllOf([DeviceExtension(ext_fragment_density_map)]),
174    ]),*/
175
176    /* TODO: enable
177    // TODO: document
178    FragmentShadingRateAttachmentOptimal = FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR
179    RequiresOneOf([
180        RequiresAllOf([DeviceExtension(khr_fragment_shading_rate)]),
181    ]),*/
182
183    /* TODO: enable
184    // TODO: document
185    VideoEncodeDst = VIDEO_ENCODE_DST_KHR
186    RequiresOneOf([
187        RequiresAllOf([DeviceExtension(khr_video_encode_queue)]),
188    ]),*/
189
190    /* TODO: enable
191    // TODO: document
192    VideoEncodeSrc = VIDEO_ENCODE_SRC_KHR
193    RequiresOneOf([
194        RequiresAllOf([DeviceExtension(khr_video_encode_queue)]),
195    ]),*/
196
197    /* TODO: enable
198    // TODO: document
199    VideoEncodeDpb = VIDEO_ENCODE_DPB_KHR
200    RequiresOneOf([
201        RequiresAllOf([DeviceExtension(khr_video_encode_queue)]),
202    ]),*/
203
204    /* TODO: enable
205    // TODO: document
206    AttachmentFeedbackLoopOptimal = ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT
207    RequiresOneOf([
208        RequiresAllOf([DeviceExtension(ext_attachment_feedback_loop_layout)]),
209    ]),*/
210}
211
212impl Default for ImageLayout {
213    #[inline]
214    fn default() -> Self {
215        ImageLayout::Undefined
216    }
217}
218
219impl ImageLayout {
220    /// If the layout can be used for `aspect`, returns whether `aspect` can be written to if an
221    /// image is in that layout.
222    pub fn is_writable(self, aspect: ImageAspect) -> bool {
223        match aspect {
224            ImageAspect::Color
225            | ImageAspect::Plane0
226            | ImageAspect::Plane1
227            | ImageAspect::Plane2 => match self {
228                ImageLayout::General
229                | ImageLayout::ColorAttachmentOptimal
230                | ImageLayout::TransferDstOptimal => true,
231                ImageLayout::Undefined
232                | ImageLayout::DepthStencilAttachmentOptimal
233                | ImageLayout::DepthStencilReadOnlyOptimal
234                | ImageLayout::ShaderReadOnlyOptimal
235                | ImageLayout::TransferSrcOptimal
236                | ImageLayout::Preinitialized
237                | ImageLayout::DepthReadOnlyStencilAttachmentOptimal
238                | ImageLayout::DepthAttachmentStencilReadOnlyOptimal
239                | ImageLayout::DepthAttachmentOptimal
240                | ImageLayout::DepthReadOnlyOptimal
241                | ImageLayout::StencilAttachmentOptimal
242                | ImageLayout::StencilReadOnlyOptimal
243                | ImageLayout::PresentSrc => false,
244            },
245            ImageAspect::Depth => match self {
246                ImageLayout::General
247                | ImageLayout::DepthStencilAttachmentOptimal
248                | ImageLayout::TransferDstOptimal
249                | ImageLayout::DepthAttachmentStencilReadOnlyOptimal
250                | ImageLayout::DepthAttachmentOptimal => true,
251
252                ImageLayout::Undefined
253                | ImageLayout::ColorAttachmentOptimal
254                | ImageLayout::DepthStencilReadOnlyOptimal
255                | ImageLayout::ShaderReadOnlyOptimal
256                | ImageLayout::TransferSrcOptimal
257                | ImageLayout::Preinitialized
258                | ImageLayout::DepthReadOnlyStencilAttachmentOptimal
259                | ImageLayout::DepthReadOnlyOptimal
260                | ImageLayout::StencilAttachmentOptimal
261                | ImageLayout::StencilReadOnlyOptimal
262                | ImageLayout::PresentSrc => false,
263            },
264            ImageAspect::Stencil => match self {
265                ImageLayout::General
266                | ImageLayout::DepthStencilAttachmentOptimal
267                | ImageLayout::TransferDstOptimal
268                | ImageLayout::DepthReadOnlyStencilAttachmentOptimal
269                | ImageLayout::StencilAttachmentOptimal => true,
270
271                ImageLayout::Undefined
272                | ImageLayout::ColorAttachmentOptimal
273                | ImageLayout::DepthStencilReadOnlyOptimal
274                | ImageLayout::ShaderReadOnlyOptimal
275                | ImageLayout::TransferSrcOptimal
276                | ImageLayout::Preinitialized
277                | ImageLayout::DepthAttachmentStencilReadOnlyOptimal
278                | ImageLayout::DepthAttachmentOptimal
279                | ImageLayout::DepthReadOnlyOptimal
280                | ImageLayout::StencilReadOnlyOptimal
281                | ImageLayout::PresentSrc => false,
282            },
283            ImageAspect::Metadata
284            | ImageAspect::MemoryPlane0
285            | ImageAspect::MemoryPlane1
286            | ImageAspect::MemoryPlane2
287            | ImageAspect::MemoryPlane3 => false,
288        }
289    }
290}