vulkan: Add helpers for getting rendering info from a renderpass

These helpers are used by vkCreateGraphicsPipelines to get the
VkPipelineRenderingCreateInfo and in vkCmdBeginCommandBuffer to get the
VkCommandBufferInheritanceRenderingInfo.  This is required because the
Vulkan runtime code can't yet hook and modify calls made to driver-
provided functions.  Instead, we just provide a helper to be used in leu
of vk_find_struct_const().  The structs themselves are stored in the
render pass so we can pass back a pointer and there's no need to
construct one on the stack or stuff it in the pipeline.

Reviewed-by: Ivan Briano <ivan.briano@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14961>
This commit is contained in:
Jason Ekstrand 2022-02-10 17:30:01 -06:00
parent 1d726940d2
commit ca5ad9cbee
2 changed files with 174 additions and 0 deletions

View file

@ -424,12 +424,17 @@ vk_common_CreateRenderPass2(VkDevice _device,
pCreateInfo->dependencyCount);
uint32_t subpass_attachment_count = 0;
uint32_t subpass_color_format_count = 0;
for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) {
subpass_attachment_count +=
num_subpass_attachments2(&pCreateInfo->pSubpasses[i]);
subpass_color_format_count +=
pCreateInfo->pSubpasses[i].colorAttachmentCount;
}
VK_MULTIALLOC_DECL(&ma, struct vk_subpass_attachment, subpass_attachments,
subpass_attachment_count);
VK_MULTIALLOC_DECL(&ma, VkFormat, subpass_color_formats,
subpass_color_format_count);
if (!vk_object_multizalloc(device, &ma, pAllocator,
VK_OBJECT_TYPE_RENDER_PASS))
@ -448,6 +453,7 @@ vk_common_CreateRenderPass2(VkDevice _device,
}
struct vk_subpass_attachment *next_subpass_attachment = subpass_attachments;
VkFormat *next_subpass_color_format = subpass_color_formats;
for (uint32_t s = 0; s < pCreateInfo->subpassCount; s++) {
const VkSubpassDescription2 *desc = &pCreateInfo->pSubpasses[s];
struct vk_subpass *subpass = &pass->subpasses[s];
@ -559,9 +565,71 @@ vk_common_CreateRenderPass2(VkDevice _device,
subpass->depth_resolve_mode = ds_resolve->depthResolveMode;
subpass->stencil_resolve_mode = ds_resolve->stencilResolveMode;
}
VkFormat *color_formats = NULL;
VkSampleCountFlagBits samples = 0;
if (desc->colorAttachmentCount > 0) {
color_formats = next_subpass_color_format;
for (uint32_t a = 0; a < desc->colorAttachmentCount; a++) {
const VkAttachmentReference2 *ref = &desc->pColorAttachments[a];
if (ref->attachment >= pCreateInfo->attachmentCount) {
color_formats[a] = VK_FORMAT_UNDEFINED;
} else {
const VkAttachmentDescription2 *att =
&pCreateInfo->pAttachments[ref->attachment];
color_formats[a] = att->format;
assert(samples == 0 || samples == att->samples);
samples |= att->samples;
}
}
next_subpass_color_format += desc->colorAttachmentCount;
}
VkFormat depth_format = VK_FORMAT_UNDEFINED;
VkFormat stencil_format = VK_FORMAT_UNDEFINED;
if (desc->pDepthStencilAttachment != NULL) {
const VkAttachmentReference2 *ref = desc->pDepthStencilAttachment;
if (ref->attachment < pCreateInfo->attachmentCount) {
const VkAttachmentDescription2 *att =
&pCreateInfo->pAttachments[ref->attachment];
if (vk_format_has_depth(att->format))
depth_format = att->format;
if (vk_format_has_stencil(att->format))
stencil_format = att->format;
assert(samples == 0 || samples == att->samples);
samples |= att->samples;
}
}
subpass->pipeline_info = (VkPipelineRenderingCreateInfo) {
.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,
.viewMask = desc->viewMask,
.colorAttachmentCount = desc->colorAttachmentCount,
.pColorAttachmentFormats = color_formats,
.depthAttachmentFormat = depth_format,
.stencilAttachmentFormat = stencil_format,
};
subpass->inheritance_info = (VkCommandBufferInheritanceRenderingInfo) {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO,
/* If we're inheriting, the contents are clearly in secondaries */
.flags = VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT,
.viewMask = desc->viewMask,
.colorAttachmentCount = desc->colorAttachmentCount,
.pColorAttachmentFormats = color_formats,
.depthAttachmentFormat = depth_format,
.stencilAttachmentFormat = stencil_format,
.rasterizationSamples = samples,
};
}
assert(next_subpass_attachment ==
subpass_attachments + subpass_attachment_count);
assert(next_subpass_color_format ==
subpass_color_formats + subpass_color_format_count);
/* Walk backwards over the subpasses to compute view masks and
* last_subpass masks for all attachments.
@ -637,6 +705,62 @@ vk_common_CreateRenderPass2(VkDevice _device,
return VK_SUCCESS;
}
const VkPipelineRenderingCreateInfo *
vk_get_pipeline_rendering_create_info(const VkGraphicsPipelineCreateInfo *info)
{
VK_FROM_HANDLE(vk_render_pass, render_pass, info->renderPass);
if (render_pass != NULL) {
assert(info->subpass < render_pass->subpass_count);
return &render_pass->subpasses[info->subpass].pipeline_info;
}
return vk_find_struct_const(info->pNext, PIPELINE_RENDERING_CREATE_INFO);
}
const VkCommandBufferInheritanceRenderingInfo *
vk_get_command_buffer_inheritance_rendering_info(
VkCommandBufferLevel level,
const VkCommandBufferBeginInfo *pBeginInfo)
{
/* 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;
/* From the Vulkan 1.3.204 spec:
*
* "If VkCommandBufferInheritanceInfo::renderPass is not VK_NULL_HANDLE,
* or VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT is not specified
* in VkCommandBufferBeginInfo::flags, parameters of this structure are
* ignored."
*
* If we have a render pass that wins, even if a
* VkCommandBufferInheritanceRenderingInfo struct is included in the pNext
* chain.
*/
VK_FROM_HANDLE(vk_render_pass, render_pass, inheritance->renderPass);
if (render_pass != NULL) {
assert(inheritance->subpass < render_pass->subpass_count);
return &render_pass->subpasses[inheritance->subpass].inheritance_info;
}
return vk_find_struct_const(inheritance->pNext,
COMMAND_BUFFER_INHERITANCE_RENDERING_INFO);
}
VKAPI_ATTR void VKAPI_CALL
vk_common_DestroyRenderPass(VkDevice _device,
VkRenderPass renderPass,

View file

@ -114,6 +114,20 @@ struct vk_subpass {
/** VkSubpassDescriptionDepthStencilResolve::stencilResolveMode */
VkResolveModeFlagBitsKHR stencil_resolve_mode;
/** VkPipelineRenderingCreateInfo for this subpass
*
* Returned by vk_get_pipeline_rendering_create_info() if
* VkGraphicsPipelineCreateInfo::renderPass != VK_NULL_HANDLE.
*/
VkPipelineRenderingCreateInfo pipeline_info;
/** VkCommandBufferInheritanceRenderingInfo for this subpass
*
* Returned by vk_get_command_buffer_inheritance_rendering_info() if
* VkCommandBufferInheritanceInfo::renderPass != VK_NULL_HANDLE.
*/
VkCommandBufferInheritanceRenderingInfo inheritance_info;
};
struct vk_render_pass_attachment {
@ -227,6 +241,42 @@ struct vk_render_pass {
VK_DEFINE_NONDISP_HANDLE_CASTS(vk_render_pass, base, VkRenderPass,
VK_OBJECT_TYPE_RENDER_PASS);
/** Returns the VkPipelineRenderingCreateInfo for a graphics pipeline
*
* For render-pass-free drivers, this can be used in the implementaiton 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.
*
* @param[in] info One of the pCreateInfos from vkCreateGraphicsPipelines
*/
const VkPipelineRenderingCreateInfo *
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
* 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.
*
* @param[in] level The nesting level of this command buffer
* @param[in] pBeginInfo The pBeginInfo from vkBeginCommandBuffer
*/
const VkCommandBufferInheritanceRenderingInfo *
vk_get_command_buffer_inheritance_rendering_info(
VkCommandBufferLevel level,
const VkCommandBufferBeginInfo *pBeginInfo);
#ifdef __cplusplus
}
#endif