Aqoole_Hateenaの技術日記

vulkan+raytraceで色々描いてます

Image Layout Transitionsについて

Image Layout Transitions

memory dependenciesの例としてImage Layout Transitions*1がある。

Image Layouts

仕様書にはこのように書かれている。Vulkan® 1.2.202 - A Specification (with all registered Vulkan extensions)


Images are stored in implementation-dependent opaque layouts in memory. Each layout has limitations on what kinds of operations are supported for image subresources using the layout. At any given time, the data representing an image subresource in memory exists in a particular layout which is determined by the most recent layout transition that was performed on that image subresource. Applications have control over which layout each image subresource uses, and can transition an image subresource from one layout to another. Transitions can happen with an image memory barrier, included as part of a vkCmdPipelineBarrier or a vkCmdWaitEvents command buffer command (see Image Memory Barriers), or as part of a subpass dependency within a render pass (see VkSubpassDependency).

Imageは実装依存のlayoutでメモリに保存されており、各layoutごとにサポートされているoperationsが異なる。Image layoutは直前に行われたlayoutのままのため、アプリケーションの側で用途に応じてlayoutを遷移させる必要がある。

vkCmdPipelineBarrier()

具体的にはvkCmdPipelineBarrier()を用いて行う。vkCmdPipelineBarrier(3)

// Provided by VK_VERSION_1_0
void vkCmdPipelineBarrier(
    VkCommandBuffer                   commandBuffer,
    VkPipelineStageFlags                srcStageMask,
    VkPipelineStageFlags                dstStageMask,
    VkDependencyFlags                  dependencyFlags,
    uint32_t                                      memoryBarrierCount,
    const VkMemoryBarrier*            pMemoryBarriers,
    uint32_t                                      bufferMemoryBarrierCount,
    const VkBufferMemoryBarrier*  pBufferMemoryBarriers,
    uint32_t                                      imageMemoryBarrierCount,
    const VkImageMemoryBarrier* pImageMemoryBarriers);

最後の引数の部分のpImageMemoryBarriersにimage layoutの指定を行う。

// Provided by VK_VERSION_1_0
typedef struct VkImageMemoryBarrier {
    VkStructureType            sType;
    const void*                pNext;
    VkAccessFlags              srcAccessMask;
    VkAccessFlags              dstAccessMask;
    VkImageLayout              oldLayout;
    VkImageLayout              newLayout;
    uint32_t                   srcQueueFamilyIndex;
    uint32_t                   dstQueueFamilyIndex;
    VkImage                    image;
    VkImageSubresourceRange    subresourceRange;
} VkImageMemoryBarrier;

Access MaskとLayoutを指定してbarrier commandを発行する。
発行するタイミングはold layoutsでImageにアクセスする必要がなくなったのち、new layoutで必要になるまでである。
大抵の場合、swapchainのimageをrendering後のVK_IMAGE_LAYOUT_UNDEFINEDから、次にrenderingを行うためのVK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMALに遷移させる必要があると考えている。

Pipeline Stages

上記のvkCmdPipelineBarrier()に、pipeline stagesを入力するフィールドがある。
pipeline stagesについて、仕様書によるとVulkan® 1.2.203 - A Specification (with all registered Vulkan extensions)


The work performed by an action or synchronization command consists of multiple operations, which are performed as a sequence of logically independent steps known as pipeline stages.

複数のoperationsのあるworkはpipeline stagesという論理的に独立したstepsで実行される。
つまりpipeline stagesとは、pipeline内の論理的に独立したstepsである。


If a synchronization command includes a source stage mask, its first synchronization scope only includes execution of the pipeline stages specified in that mask, and its first access scope only includes memory accesses performed by pipeline stages specified in that mask.

If a synchronization command includes a destination stage mask, its second synchronization scope only includes execution of the pipeline stages specified in that mask, and its second access scope only includes memory access performed by pipeline stages specified in that mask.

vkCmdPipelineBarrier()はsrc, dstの両方のmaskを持つので、双方でscopeを持ち、制御している。

*1:e.g. by using an image memory barrier