diff options
Diffstat (limited to 'src/image/layout.rs')
-rw-r--r-- | src/image/layout.rs | 241 |
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), + } + } +} |