aboutsummaryrefslogtreecommitdiff
path: root/src/image/layout.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/image/layout.rs')
-rw-r--r--src/image/layout.rs241
1 files changed, 208 insertions, 33 deletions
diff --git a/src/image/layout.rs b/src/image/layout.rs
index 2e29f58..16f4bc0 100644
--- a/src/image/layout.rs
+++ b/src/image/layout.rs
@@ -7,42 +7,202 @@
// notice may not be copied, modified, or distributed except
// according to those terms.
-/// Layout of an image.
-///
-/// > **Note**: In vulkano, image layouts are mostly a low-level detail. You can ignore them,
-/// > unless you use an unsafe function that states in its documentation that you must take care of
-/// > an image's layout.
-///
-/// In the Vulkan API, each mipmap level of each array layer is in one of the layouts of this enum.
-///
-/// Unless you use some sort of high-level shortcut function, an image always starts in either
-/// the `Undefined` or the `Preinitialized` layout.
-/// Before you can use an image for a given purpose, you must ensure that the image in question is
-/// in the layout required for that purpose. For example if you want to write data to an image, you
-/// must first transition the image to the `TransferDstOptimal` layout. The `General` layout can
-/// also be used as a general-purpose fit-all layout, but using it will result in slower operations.
-///
-/// Transitioning between layouts can only be done through a GPU-side operation that is part of
-/// a command buffer.
-#[derive(Debug, Copy, Clone, PartialEq, Eq)]
-#[repr(i32)]
-pub enum ImageLayout {
- Undefined = ash::vk::ImageLayout::UNDEFINED.as_raw(),
- General = ash::vk::ImageLayout::GENERAL.as_raw(),
- ColorAttachmentOptimal = ash::vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL.as_raw(),
- DepthStencilAttachmentOptimal = ash::vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL.as_raw(),
- DepthStencilReadOnlyOptimal = ash::vk::ImageLayout::DEPTH_STENCIL_READ_ONLY_OPTIMAL.as_raw(),
- ShaderReadOnlyOptimal = ash::vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL.as_raw(),
- TransferSrcOptimal = ash::vk::ImageLayout::TRANSFER_SRC_OPTIMAL.as_raw(),
- TransferDstOptimal = ash::vk::ImageLayout::TRANSFER_DST_OPTIMAL.as_raw(),
- Preinitialized = ash::vk::ImageLayout::PREINITIALIZED.as_raw(),
- PresentSrc = ash::vk::ImageLayout::PRESENT_SRC_KHR.as_raw(),
+use crate::{descriptor_set::layout::DescriptorType, macros::vulkan_enum};
+
+vulkan_enum! {
+ #[non_exhaustive]
+
+ /// In-memory layout of the pixel data of an image.
+ ///
+ /// The pixel data of a Vulkan image is arranged in a particular way, which is called its
+ /// *layout*. Each image subresource (mipmap level and array layer) in an image can have a
+ /// different layout, but usually the whole image has its data in the same layout. Layouts are
+ /// abstract in the sense that the user does not know the specific details of each layout; the
+ /// device driver is free to implement each layout in the way it sees fit.
+ ///
+ /// The layout of a newly created image is either `Undefined` or `Preinitialized`. Every
+ /// operation that can be performed on an image is only possible with specific layouts, so
+ /// before the operation is performed, the user must perform a *layout transition* on the
+ /// image. This rearranges the pixel data from one layout into another. Layout transitions are
+ /// performed as part of pipeline barriers in a command buffer.
+ ///
+ /// The `General` layout is compatible with any operation, so layout transitions are never
+ /// needed. However, the other layouts, while more restricted, are usually better optimised for
+ /// a particular type of operation than `General`, so they are usually preferred.
+ ///
+ /// Vulkan does not keep track of layouts itself, so it is the responsibility of the user to
+ /// keep track of this information. When performing a layout transition, the previous layout
+ /// must be specified as well. Some operations allow for different layouts, but require the
+ /// user to specify which one. Vulkano helps with this by providing sensible defaults,
+ /// automatically tracking the layout of each image when creating a command buffer, and adding
+ /// layout transitions where needed.
+ ImageLayout = ImageLayout(i32);
+
+ /// The layout of the data is unknown, and the image is treated as containing no valid data.
+ /// Transitioning from `Undefined` will discard any existing pixel data.
+ Undefined = UNDEFINED,
+
+ /// A general-purpose layout that can be used for any operation. Some operations may only allow
+ /// `General`, such as storage images, but many have a more specific layout that is better
+ /// optimized for that purpose.
+ General = GENERAL,
+
+ /// For a color image used as a color or resolve attachment in a framebuffer. Images that are
+ /// transitioned into this layout must have the `color_attachment` usage enabled.
+ ColorAttachmentOptimal = COLOR_ATTACHMENT_OPTIMAL,
+
+ /// For a depth/stencil image used as a depth/stencil attachment in a framebuffer.
+ DepthStencilAttachmentOptimal = DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
+
+ /// For a depth/stencil image used as a read-only depth/stencil attachment in a framebuffer, or
+ /// as a (combined) sampled image or input attachment in a shader.
+ DepthStencilReadOnlyOptimal = DEPTH_STENCIL_READ_ONLY_OPTIMAL,
+
+ /// For a color image used as a (combined) sampled image or input attachment in a shader.
+ /// Images that are transitioned into this layout must have the `sampled` or `input_attachment`
+ /// usages enabled.
+ ShaderReadOnlyOptimal = SHADER_READ_ONLY_OPTIMAL,
+
+ /// For operations that transfer data from an image (copy, blit).
+ TransferSrcOptimal = TRANSFER_SRC_OPTIMAL,
+
+ /// For operations that transfer data to an image (copy, blit, clear).
+ TransferDstOptimal = TRANSFER_DST_OPTIMAL,
+
+ /// When creating an image, this specifies that the initial data is going to be directly
+ /// written to from the CPU. Unlike `Undefined`, the image is assumed to contain valid data when
+ /// transitioning from this layout. However, this only works right when the image has linear
+ /// tiling, optimal tiling gives undefined results.
+ Preinitialized = PREINITIALIZED,
+
+ /// A combination of `DepthStencilReadOnlyOptimal` for the depth aspect of the image,
+ /// and `DepthStencilAttachmentOptimal` for the stencil aspect of the image.
+ DepthReadOnlyStencilAttachmentOptimal = DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL {
+ api_version: V1_1,
+ device_extensions: [khr_maintenance2],
+ },
+
+ /// A combination of `DepthStencilAttachmentOptimal` for the depth aspect of the image,
+ /// and `DepthStencilReadOnlyOptimal` for the stencil aspect of the image.
+ DepthAttachmentStencilReadOnlyOptimal = DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL {
+ api_version: V1_1,
+ device_extensions: [khr_maintenance2],
+ },
+
+ /* TODO: enable
+ // TODO: document
+ DepthAttachmentOptimal = DEPTH_ATTACHMENT_OPTIMAL {
+ api_version: V1_2,
+ device_extensions: [khr_separate_depth_stencil_layouts],
+ },*/
+
+ /* TODO: enable
+ // TODO: document
+ DepthReadOnlyOptimal = DEPTH_READ_ONLY_OPTIMAL {
+ api_version: V1_2,
+ device_extensions: [khr_separate_depth_stencil_layouts],
+ },*/
+
+ /* TODO: enable
+ // TODO: document
+ StencilAttachmentOptimal = STENCIL_ATTACHMENT_OPTIMAL {
+ api_version: V1_2,
+ device_extensions: [khr_separate_depth_stencil_layouts],
+ },*/
+
+ /* TODO: enable
+ // TODO: document
+ StencilReadOnlyOptimal = STENCIL_READ_ONLY_OPTIMAL {
+ api_version: V1_2,
+ device_extensions: [khr_separate_depth_stencil_layouts],
+ },*/
+
+ /* TODO: enable
+ // TODO: document
+ ReadOnlyOptimal = READ_ONLY_OPTIMAL {
+ api_version: V1_3,
+ device_extensions: [khr_synchronization2],
+ },*/
+
+ /* TODO: enable
+ // TODO: document
+ AttachmentOptimal = ATTACHMENT_OPTIMAL {
+ api_version: V1_3,
+ device_extensions: [khr_synchronization2],
+ },*/
+
+ /// The layout of images that are held in a swapchain. Images are in this layout when they are
+ /// acquired from the swapchain, and must be transitioned back into this layout before
+ /// presenting them.
+ PresentSrc = PRESENT_SRC_KHR {
+ device_extensions: [khr_swapchain],
+ },
+
+ /* TODO: enable
+ // TODO: document
+ VideoDecodeDst = VIDEO_DECODE_DST_KHR {
+ device_extensions: [khr_video_decode_queue],
+ },*/
+
+ /* TODO: enable
+ // TODO: document
+ VideoDecodeSrc = VIDEO_DECODE_SRC_KHR {
+ device_extensions: [khr_video_decode_queue],
+ },*/
+
+ /* TODO: enable
+ // TODO: document
+ VideoDecodeDpb = VIDEO_DECODE_DPB_KHR {
+ device_extensions: [khr_video_decode_queue],
+ },*/
+
+ /* TODO: enable
+ // TODO: document
+ SharedPresent = SHARED_PRESENT_KHR {
+ device_extensions: [khr_shared_presentable_image],
+ },*/
+
+ /* TODO: enable
+ // TODO: document
+ FragmentDensityMapOptimal = FRAGMENT_DENSITY_MAP_OPTIMAL_EXT {
+ device_extensions: [ext_fragment_density_map],
+ },*/
+
+ /* TODO: enable
+ // TODO: document
+ FragmentShadingRateAttachmentOptimal = FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR {
+ device_extensions: [khr_fragment_shading_rate],
+ },*/
+
+ /* TODO: enable
+ // TODO: document
+ VideoEncodeDst = VIDEO_ENCODE_DST_KHR {
+ device_extensions: [khr_video_encode_queue],
+ },*/
+
+ /* TODO: enable
+ // TODO: document
+ VideoEncodeSrc = VIDEO_ENCODE_SRC_KHR {
+ device_extensions: [khr_video_encode_queue],
+ },*/
+
+ /* TODO: enable
+ // TODO: document
+ VideoEncodeDpb = VIDEO_ENCODE_DPB_KHR {
+ device_extensions: [khr_video_encode_queue],
+ },*/
+
+ /* TODO: enable
+ // TODO: document
+ AttachmentFeedbackLoopOptimal = ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT {
+ device_extensions: [ext_attachment_feedback_loop_layout],
+ },*/
}
-impl From<ImageLayout> for ash::vk::ImageLayout {
+impl Default for ImageLayout {
#[inline]
- fn from(val: ImageLayout) -> Self {
- Self::from_raw(val as i32)
+ fn default() -> Self {
+ ImageLayout::Undefined
}
}
@@ -58,3 +218,18 @@ pub struct ImageDescriptorLayouts {
/// The image layout to use in a descriptor as an input attachment.
pub input_attachment: ImageLayout,
}
+
+impl ImageDescriptorLayouts {
+ /// Returns the layout for the given descriptor type. Panics if `descriptor_type` is not an
+ /// image descriptor type.
+ #[inline]
+ pub fn layout_for(&self, descriptor_type: DescriptorType) -> ImageLayout {
+ match descriptor_type {
+ DescriptorType::CombinedImageSampler => self.combined_image_sampler,
+ DescriptorType::SampledImage => self.sampled_image,
+ DescriptorType::StorageImage => self.storage_image,
+ DescriptorType::InputAttachment => self.input_attachment,
+ _ => panic!("{:?} is not an image descriptor type", descriptor_type),
+ }
+ }
+}