vulkan/render_pass: Add a better helper for render pass inheritance

Instead of making drivers dive into the render pass and framebuffer
themselves, provide a helper that constructs a VkRenderingInfo for a
render pass resume that they can use instead.  This should reduce code
duplication between driver implementations of BeginRendering and
BeginCommandBuffer.

Reviewed-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/16953>
This commit is contained in:
Jason Ekstrand 2022-05-31 15:53:51 -05:00 committed by Marge Bot
parent f904b95ef0
commit 3a204d5cf3
2 changed files with 158 additions and 2 deletions

View File

@ -820,6 +820,126 @@ vk_get_command_buffer_inheritance_rendering_info(
COMMAND_BUFFER_INHERITANCE_RENDERING_INFO);
}
const VkRenderingInfo *
vk_get_command_buffer_inheritance_as_rendering_resume(
VkCommandBufferLevel level,
const VkCommandBufferBeginInfo *pBeginInfo,
void *stack_data)
{
struct vk_gcbiarr_data *data = stack_data;
/* From the Vulkan 1.3.204 spec:
*
* "VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT specifies that a
* secondary command buffer is considered to be entirely inside a render
* pass. If this is a primary command buffer, then this bit is ignored."
*
* Since we're only concerned with the continue case here, we can ignore
* any primary command buffers.
*/
if (level == VK_COMMAND_BUFFER_LEVEL_PRIMARY)
return NULL;
if (!(pBeginInfo->flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT))
return NULL;
const VkCommandBufferInheritanceInfo *inheritance =
pBeginInfo->pInheritanceInfo;
VK_FROM_HANDLE(vk_render_pass, pass, inheritance->renderPass);
if (pass == NULL)
return NULL;
assert(inheritance->subpass < pass->subpass_count);
const struct vk_subpass *subpass = &pass->subpasses[inheritance->subpass];
VK_FROM_HANDLE(vk_framebuffer, fb, inheritance->framebuffer);
if (fb == NULL || (fb->flags & VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT_KHR))
return NULL;
data->rendering = (VkRenderingInfo) {
.sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
.flags = VK_RENDERING_RESUMING_BIT,
.renderArea = {
.offset = { 0, 0 },
.extent = { fb->width, fb->height },
},
.layerCount = fb->layers,
.viewMask = pass->is_multiview ? subpass->view_mask : 0,
};
VkRenderingAttachmentInfo *attachments = data->attachments;
for (unsigned i = 0; i < subpass->color_count; i++) {
const struct vk_subpass_attachment *sp_att =
&subpass->color_attachments[i];
if (sp_att->attachment == VK_ATTACHMENT_UNUSED) {
attachments[i] = (VkRenderingAttachmentInfo) {
.imageView = VK_NULL_HANDLE,
};
continue;
}
assert(sp_att->attachment < pass->attachment_count);
attachments[i] = (VkRenderingAttachmentInfo) {
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
.imageView = fb->attachments[sp_att->attachment],
.imageLayout = sp_att->layout,
.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
};
}
data->rendering.colorAttachmentCount = subpass->color_count;
data->rendering.pColorAttachments = attachments;
attachments += subpass->color_count;
if (subpass->depth_stencil_attachment) {
const struct vk_subpass_attachment *sp_att =
subpass->depth_stencil_attachment;
assert(sp_att->attachment < pass->attachment_count);
VK_FROM_HANDLE(vk_image_view, iview, fb->attachments[sp_att->attachment]);
if (iview->image->aspects & VK_IMAGE_ASPECT_DEPTH_BIT) {
*attachments = (VkRenderingAttachmentInfo) {
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
.imageView = vk_image_view_to_handle(iview),
.imageLayout = sp_att->layout,
.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
};
data->rendering.pDepthAttachment = attachments++;
}
if (iview->image->aspects & VK_IMAGE_ASPECT_STENCIL_BIT) {
*attachments = (VkRenderingAttachmentInfo) {
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
.imageView = vk_image_view_to_handle(iview),
.imageLayout = sp_att->stencil_layout,
.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
};
data->rendering.pStencilAttachment = attachments++;
}
}
if (subpass->fragment_shading_rate_attachment) {
const struct vk_subpass_attachment *sp_att =
subpass->fragment_shading_rate_attachment;
assert(sp_att->attachment < pass->attachment_count);
data->fsr_att = (VkRenderingFragmentShadingRateAttachmentInfoKHR) {
.sType = VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR,
.imageView = fb->attachments[sp_att->attachment],
.imageLayout = sp_att->layout,
.shadingRateAttachmentTexelSize =
subpass->fragment_shading_rate_attachment_texel_size,
};
__vk_append_struct(&data->rendering, &data->fsr_att);
}
return &data->rendering;
}
VKAPI_ATTR void VKAPI_CALL
vk_common_DestroyRenderPass(VkDevice _device,
VkRenderPass renderPass,

View File

@ -305,7 +305,7 @@ VK_DEFINE_NONDISP_HANDLE_CASTS(vk_render_pass, base, VkRenderPass,
/** Returns the VkPipelineRenderingCreateInfo for a graphics pipeline
*
* For render-pass-free drivers, this can be used in the implementaiton of
* 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
@ -322,7 +322,7 @@ vk_get_pipeline_rendering_create_info(const VkGraphicsPipelineCreateInfo *info);
* Returns the VkCommandBufferInheritanceRenderingInfo for secondary command
* buffer execution
*
* For render-pass-free drivers, this can be used in the implementaiton of
* 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
@ -339,6 +339,42 @@ vk_get_command_buffer_inheritance_rendering_info(
VkCommandBufferLevel level,
const VkCommandBufferBeginInfo *pBeginInfo);
struct vk_gcbiarr_data {
VkRenderingInfo rendering;
VkRenderingFragmentShadingRateAttachmentInfoKHR fsr_att;
VkRenderingAttachmentInfo attachments[];
};
#define VK_GCBIARR_DATA_SIZE(max_color_rts) (\
sizeof(struct vk_gcbiarr_data) + \
sizeof(VkRenderingAttachmentInfo) * ((max_color_rts) + 2) \
)
/**
* Constructs a VkRenderingInfo for the inheritance rendering info
*
* For render-pass-free drivers, this can be used in the implementaiton of
* vkCmdExecuteCommands to get a VkRenderingInfo representing the subpass and
* framebuffer provided via the inheritance info for a command buffer created
* with VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT. The mental model
* here is that VkExecuteCommands() implicitly suspends the render pass and
* VkBeginCommandBuffer() resumes it. If a VkRenderingInfo cannot be
* constructed due to a missing framebuffer or similar, NULL will be
* returned.
*
* @param[in] level The nesting level of this command buffer
* @param[in] pBeginInfo The pBeginInfo from vkBeginCommandBuffer
* @param[out] stack_data An opaque blob of data which will be overwritten by
* this function, passed in from the caller to avoid
* heap allocations. It must be at least
* VK_GCBIARR_DATA_SIZE(max_color_rts) bytes.
*/
const VkRenderingInfo *
vk_get_command_buffer_inheritance_as_rendering_resume(
VkCommandBufferLevel level,
const VkCommandBufferBeginInfo *pBeginInfo,
void *stack_data);
#ifdef __cplusplus
}
#endif