Render Passes

The Vulkan runtime code in Mesa provides several helpful utilities to make managing render passes easier.


It is strongly recommended that drivers implement VK_KHR_create_renderpass2 directly and not bother implementing the old Vulkan 1.0 entrypoints. If a driver does not implement them, the following will be implemented in common code in terms of their VK_KHR_create_renderpass2 counterparts:

  • vkCreateRenderPass()

  • vkCmdBeginRenderPass()

  • vkCmdNextSubpass()

  • vkCmdEndRenderPass()

Common VkRenderPass implementation

The Vulkan runtime code in Mesa provides a common implementation of VkRenderPass called vk_render_pass which drivers can optionally use. Unlike most Vulkan runtime structs, it’s not really designed to be used as a base for a driver-specific struct. It does, however, contain all the information passed to vkCreateRenderPass2() so it can be used in a driver so long as that driver doesn’t need to do any additional compilation at vkCreateRenderPass2() time. If a driver chooses to use vk_render_pass, the Vulkan runtime provides implementations of vkCreateRenderPass2() and vkDestroyRenderPass().


For drivers which don’t need to do subpass combining, it is recommended that they skip implementing render passes entirely and implement VK_KHR_dynamic_rendering instead. If they choose to do so, the runtime will provide the following, implemented in terms of vkCmdBeginRendering() and vkCmdEndRendering():

  • vkCmdBeginRenderPass2()

  • vkCmdNextSubpass2()

  • vkCmdEndRenderPass2()

We also provide a no-op implementation of vkGetRenderAreaGranularity() which returns a render area granularity of 1x1.

Drivers which wish to use the common render pass implementation in this way must also support a Mesa-specific pseudo-extension which optionally provides an initial image layout for each attachment at vkCmdBeginRendering() time. This is required for us to combine render pass clears with layout transitions, often from VK_IMAGE_LAYOUT_UNDEFINED. On at least Intel and AMD, combining these transitions with clears is important for performance.

struct VkRenderingAttachmentInitialLayoutInfoMESA

Pseudo-extension struct that may be chained into VkRenderingAttachmentInfo to indicate an initial layout for the attachment. This is only allowed if all of the following conditions are met:

  1. VkRenderingAttachmentInfo::loadOp == LOAD_OP_CLEAR

  2. VkRenderingInfo::renderArea is tne entire image view LOD

  3. For 3D image attachments, VkRenderingInfo::viewMask == 0 AND VkRenderingInfo::layerCount references the entire bound image view OR VkRenderingInfo::viewMask is dense (no holes) and references the entire bound image view. (2D and 2D array images have no such requirement.)

If this struct is included in the pNext chain of a VkRenderingAttachmentInfo, the driver is responsible for transitioning the bound region of the image from VkRenderingAttachmentInitialLayoutInfoMESA::initialLayout to VkRenderingAttachmentInfo::imageLayout prior to rendering.

VkImageLayout initialLayout

Initial layout of the attachment

Because render passes and subpass indices are also passed into vkCmdCreateGraphicsPipelines() and vkCmdExecuteCommands() which we can’t implement on the driver’s behalf, we provide a couple of helpers for getting the render pass information in terms of the relevant VK_KHR_dynamic_rendering:

const VkPipelineRenderingCreateInfo *vk_get_pipeline_rendering_create_info(const VkGraphicsPipelineCreateInfo *info)

Returns the VkPipelineRenderingCreateInfo for a graphics pipeline

For render-pass-free drivers, this can be used in the implementation of vkCreateGraphicsPipelines to get the VkPipelineRenderingCreateInfo. If VkGraphicsPipelineCreateInfo::renderPass is not VK_NULL_HANDLE, it will return a representation of the specified subpass as a VkPipelineRenderingCreateInfo. If VkGraphicsPipelineCreateInfo::renderPass is VK_NULL_HANDLE and there is a VkPipelineRenderingCreateInfo in the pNext chain of VkGraphicsPipelineCreateInfo, it will return that.

  • info[in] One of the pCreateInfos from vkCreateGraphicsPipelines

const VkCommandBufferInheritanceRenderingInfo *vk_get_command_buffer_inheritance_rendering_info(VkCommandBufferLevel level, const VkCommandBufferBeginInfo *pBeginInfo)

Returns the VkCommandBufferInheritanceRenderingInfo for secondary command buffer execution

For render-pass-free drivers, this can be used in the implementation of vkCmdExecuteCommands to get the VkCommandBufferInheritanceRenderingInfo. If VkCommandBufferInheritanceInfo::renderPass is not VK_NULL_HANDLE, it will return a representation of the specified subpass as a VkCommandBufferInheritanceRenderingInfo. If VkCommandBufferInheritanceInfo::renderPass is not VK_NULL_HANDLE and there is a VkCommandBufferInheritanceRenderingInfo in the pNext chain of VkCommandBufferBeginInfo, it will return that.

  • level[in] The nesting level of this command buffer

  • pBeginInfo[in] The pBeginInfo from vkBeginCommandBuffer

Apart from handling layout transitions, the common render pass implementation mostly ignores input attachments. It is expected that the driver call nir_lower_input_attachments() to turn them into texturing operations. The driver must support texturing from an input attachment at the same time as rendering to it in order to support Vulkan subpass self-dependencies. VK_EXT_attachment_feedback_loop_layout provides information on when these self dependencies are present.

vk_render_pass reference

The following is a reference for the vk_render_pass structure and its substructures.

struct vk_render_pass
bool is_multiview

True if this render pass uses multiview

This is true if all subpasses have viewMask != 0.

uint32_t view_mask

Views used by this render pass or 1 for non-multiview

uint32_t attachment_count


struct vk_render_pass_attachment *attachments


uint32_t subpass_count


struct vk_subpass *subpasses


uint32_t dependency_count


VkAttachmentReference fragment_density_map


struct vk_subpass_dependency *dependencies


struct vk_render_pass_attachment
VkFormat format


VkImageAspectFlags aspects

Aspects contained in format

uint32_t samples


uint32_t view_mask

Views in which this attachment is used, 0 for unused

For non-multiview, this will be 1 if the attachment is used.

VkAttachmentLoadOp load_op


VkAttachmentStoreOp store_op


VkAttachmentLoadOp stencil_load_op


VkAttachmentStoreOp stencil_store_op


VkImageLayout initial_layout


VkImageLayout final_layout


VkImageLayout initial_stencil_layout


If VK_KHR_separate_depth_stencil_layouts is not used, this will be initial_layout if format contains stencil and VK_IMAGE_LAYOUT_UNDEFINED otherwise.

VkImageLayout final_stencil_layout


If VK_KHR_separate_depth_stencil_layouts is not used, this will be final_layout if format contains stencil and VK_IMAGE_LAYOUT_UNDEFINED otherwise.

struct vk_subpass
uint32_t attachment_count

Count of all attachments referenced by this subpass

struct vk_subpass_attachment *attachments

Array of all attachments referenced by this subpass

uint32_t input_count


struct vk_subpass_attachment *input_attachments


uint32_t color_count


struct vk_subpass_attachment *color_attachments


uint32_t color_resolve_count

VkSubpassDescription2::colorAttachmentCount or zero

struct vk_subpass_attachment *color_resolve_attachments


struct vk_subpass_attachment *depth_stencil_attachment


struct vk_subpass_attachment *depth_stencil_resolve_attachment


struct vk_subpass_attachment *fragment_shading_rate_attachment


uint32_t view_mask

VkSubpassDescription2::viewMask or 1 for non-multiview

For all view masks in the vk_render_pass data structure, we use a mask of 1 for non-multiview instead of a mask of 0. To determine if the render pass is multiview or not, see vk_render_pass::is_multiview.

VkResolveModeFlagBits depth_resolve_mode


VkResolveModeFlagBits stencil_resolve_mode


VkExtent2D fragment_shading_rate_attachment_texel_size


VkPipelineCreateFlagBits2KHR pipeline_flags

Extra VkPipelineCreateFlags for this subpass

VkAttachmentSampleCountInfoAMD sample_count_info_amd

VkAttachmentSampleCountInfoAMD for this subpass

This is in the pNext chain of pipeline_info and inheritance_info.

VkPipelineRenderingCreateInfo pipeline_info

VkPipelineRenderingCreateInfo for this subpass

Returned by vk_get_pipeline_rendering_create_info() if VkGraphicsPipelineCreateInfo::renderPass != VK_NULL_HANDLE.

VkCommandBufferInheritanceRenderingInfo inheritance_info

VkCommandBufferInheritanceRenderingInfo for this subpass

Returned by vk_get_command_buffer_inheritance_rendering_info() if VkCommandBufferInheritanceInfo::renderPass != VK_NULL_HANDLE.

VkMultisampledRenderToSingleSampledInfoEXT mrtss

VkMultisampledRenderToSingleSampledInfoEXT for this subpass

bool legacy_dithering_enabled

True if legacy dithering is enabled for this subpass.

struct vk_subpass_attachment
uint32_t attachment


VkImageAspectFlags aspects

Aspects referenced by this attachment

For an input attachment, this is VkAttachmentReference2::aspectMask. For all others, it’s equal to the vk_render_pass_attachment::aspects.

VkImageUsageFlagBits usage

Usage for this attachment

This is a single VK_IMAGE_USAGE_* describing the usage of this subpass attachment. Resolve attachments are VK_IMAGE_USAGE_TRANSFER_DST_BIT.

VkImageLayout layout


VkImageLayout stencil_layout


If VK_KHR_separate_depth_stencil_layouts is not used, this will be layout if the attachment contains stencil and VK_IMAGE_LAYOUT_UNDEFINED otherwise.

uint32_t last_subpass

A per-view mask for if this is the last use of this attachment

If the same render pass attachment is used multiple ways within a subpass, corresponding last_subpass bits will be set in all of them. For the non-multiview case, only the first bit is used.

struct vk_subpass_attachment *resolve

Resolve attachment, if any

struct vk_subpass_dependency
VkDependencyFlags flags


uint32_t src_subpass


uint32_t dst_subpass


VkPipelineStageFlags2 src_stage_mask


VkPipelineStageFlags2 dst_stage_mask


VkAccessFlags2 src_access_mask


VkAccessFlags2 dst_access_mask


int32_t view_offset