vulkan: Add a common vk_render_pass struct

This basically contains everything in pCreateInfo plus one or two extra
bits that might be useful.

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
2021-09-22 14:13:00 -05:00
committed by Jason Ekstrand
parent 83101429bf
commit 874aeb8743
3 changed files with 515 additions and 0 deletions

View File

@@ -208,6 +208,8 @@ struct vk_image_view {
/* VK_KHR_maintenance2 */
VkImageUsageFlags usage;
};
VK_DEFINE_NONDISP_HANDLE_CASTS(vk_image_view, base, VkImageView,
VK_OBJECT_TYPE_IMAGE_VIEW);
void vk_image_view_init(struct vk_device *device,
struct vk_image_view *image_view,

View File

@@ -21,10 +21,15 @@
* IN THE SOFTWARE.
*/
#include "vk_render_pass.h"
#include "vk_alloc.h"
#include "vk_command_buffer.h"
#include "vk_common_entrypoints.h"
#include "vk_device.h"
#include "vk_format.h"
#include "vk_framebuffer.h"
#include "vk_image.h"
#include "vk_util.h"
#include "util/log.h"
@@ -289,3 +294,305 @@ vk_common_CmdNextSubpass(VkCommandBuffer commandBuffer,
disp->device->dispatch_table.CmdNextSubpass2(commandBuffer, &begin_info,
&end_info);
}
static unsigned
num_subpass_attachments2(const VkSubpassDescription2 *desc)
{
bool has_depth_stencil_attachment =
desc->pDepthStencilAttachment != NULL &&
desc->pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED;
const VkSubpassDescriptionDepthStencilResolve *ds_resolve =
vk_find_struct_const(desc->pNext,
SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE);
bool has_depth_stencil_resolve_attachment =
ds_resolve && ds_resolve->pDepthStencilResolveAttachment &&
ds_resolve->pDepthStencilResolveAttachment->attachment != VK_ATTACHMENT_UNUSED;
return desc->inputAttachmentCount +
desc->colorAttachmentCount +
(desc->pResolveAttachments ? desc->colorAttachmentCount : 0) +
has_depth_stencil_attachment +
has_depth_stencil_resolve_attachment;
}
static void
vk_render_pass_attachment_init(struct vk_render_pass_attachment *att,
const VkAttachmentDescription2 *desc)
{
*att = (struct vk_render_pass_attachment) {
.format = desc->format,
.aspects = vk_format_aspects(desc->format),
.samples = desc->samples,
.load_op = desc->loadOp,
.store_op = desc->storeOp,
.stencil_load_op = desc->stencilLoadOp,
.stencil_store_op = desc->stencilStoreOp,
.initial_layout = desc->initialLayout,
.final_layout = desc->finalLayout,
.initial_stencil_layout = vk_att_desc_stencil_layout(desc, false),
.final_stencil_layout = vk_att_desc_stencil_layout(desc, true),
};
}
static void
vk_subpass_attachment_init(struct vk_subpass_attachment *att,
struct vk_render_pass *pass,
uint32_t subpass_idx,
const VkAttachmentReference2 *ref,
const VkAttachmentDescription2 *attachments,
VkImageUsageFlagBits usage)
{
if (ref->attachment >= pass->attachment_count) {
assert(ref->attachment == VK_ATTACHMENT_UNUSED);
*att = (struct vk_subpass_attachment) {
.attachment = VK_ATTACHMENT_UNUSED,
};
return;
}
struct vk_render_pass_attachment *pass_att =
&pass->attachments[ref->attachment];
*att = (struct vk_subpass_attachment) {
.attachment = ref->attachment,
.aspects = vk_format_aspects(pass_att->format),
.usage = usage,
.layout = ref->layout,
.stencil_layout = vk_att_ref_stencil_layout(ref, attachments),
};
switch (usage) {
case VK_IMAGE_USAGE_TRANSFER_DST_BIT:
break; /* No special aspect requirements */
case VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT:
/* From the Vulkan 1.2.184 spec:
*
* "aspectMask is ignored when this structure is used to describe
* anything other than an input attachment reference."
*/
assert(!(ref->aspectMask & ~att->aspects));
att->aspects = ref->aspectMask;
break;
case VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT:
assert(att->aspects == VK_IMAGE_ASPECT_COLOR_BIT);
break;
case VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT:
assert(!(att->aspects & ~(VK_IMAGE_ASPECT_DEPTH_BIT |
VK_IMAGE_ASPECT_STENCIL_BIT)));
break;
default:
unreachable("Invalid subpass attachment usage");
}
}
static void
vk_subpass_attachment_link_resolve(struct vk_subpass_attachment *att,
struct vk_subpass_attachment *resolve,
const VkRenderPassCreateInfo2 *info)
{
if (resolve->attachment == VK_ATTACHMENT_UNUSED)
return;
assert(att->attachment != VK_ATTACHMENT_UNUSED);
att->resolve = resolve;
}
VKAPI_ATTR VkResult VKAPI_CALL
vk_common_CreateRenderPass2(VkDevice _device,
const VkRenderPassCreateInfo2 *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkRenderPass *pRenderPass)
{
VK_FROM_HANDLE(vk_device, device, _device);
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2);
VK_MULTIALLOC(ma);
VK_MULTIALLOC_DECL(&ma, struct vk_render_pass, pass, 1);
VK_MULTIALLOC_DECL(&ma, struct vk_render_pass_attachment, attachments,
pCreateInfo->attachmentCount);
VK_MULTIALLOC_DECL(&ma, struct vk_subpass, subpasses,
pCreateInfo->subpassCount);
VK_MULTIALLOC_DECL(&ma, struct vk_subpass_dependency, dependencies,
pCreateInfo->dependencyCount);
uint32_t subpass_attachment_count = 0;
for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) {
subpass_attachment_count +=
num_subpass_attachments2(&pCreateInfo->pSubpasses[i]);
}
VK_MULTIALLOC_DECL(&ma, struct vk_subpass_attachment, subpass_attachments,
subpass_attachment_count);
if (!vk_object_multizalloc(device, &ma, pAllocator,
VK_OBJECT_TYPE_RENDER_PASS))
return VK_ERROR_OUT_OF_HOST_MEMORY;
pass->attachment_count = pCreateInfo->attachmentCount;
pass->attachments = attachments;
pass->subpass_count = pCreateInfo->subpassCount;
pass->subpasses = subpasses;
pass->dependency_count = pCreateInfo->dependencyCount;
pass->dependencies = dependencies;
for (uint32_t a = 0; a < pCreateInfo->attachmentCount; a++) {
vk_render_pass_attachment_init(&pass->attachments[a],
&pCreateInfo->pAttachments[a]);
}
struct vk_subpass_attachment *next_subpass_attachment = subpass_attachments;
for (uint32_t s = 0; s < pCreateInfo->subpassCount; s++) {
const VkSubpassDescription2 *desc = &pCreateInfo->pSubpasses[s];
struct vk_subpass *subpass = &pass->subpasses[s];
subpass->attachment_count = num_subpass_attachments2(desc);
subpass->attachments = next_subpass_attachment;
subpass->view_mask = desc->viewMask;
subpass->input_count = desc->inputAttachmentCount;
if (desc->inputAttachmentCount > 0) {
subpass->input_attachments = next_subpass_attachment;
next_subpass_attachment += desc->inputAttachmentCount;
for (uint32_t a = 0; a < desc->inputAttachmentCount; a++) {
vk_subpass_attachment_init(&subpass->input_attachments[a],
pass, s,
&desc->pInputAttachments[a],
pCreateInfo->pAttachments,
VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT);
}
}
subpass->color_count = desc->colorAttachmentCount;
if (desc->colorAttachmentCount > 0) {
subpass->color_attachments = next_subpass_attachment;
next_subpass_attachment += desc->colorAttachmentCount;
for (uint32_t a = 0; a < desc->colorAttachmentCount; a++) {
vk_subpass_attachment_init(&subpass->color_attachments[a],
pass, s,
&desc->pColorAttachments[a],
pCreateInfo->pAttachments,
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
}
}
if (desc->pResolveAttachments) {
subpass->color_resolve_count = desc->colorAttachmentCount;
subpass->color_resolve_attachments = next_subpass_attachment;
next_subpass_attachment += desc->colorAttachmentCount;
for (uint32_t a = 0; a < desc->colorAttachmentCount; a++) {
vk_subpass_attachment_init(&subpass->color_resolve_attachments[a],
pass, s,
&desc->pResolveAttachments[a],
pCreateInfo->pAttachments,
VK_IMAGE_USAGE_TRANSFER_DST_BIT);
vk_subpass_attachment_link_resolve(&subpass->color_attachments[a],
&subpass->color_resolve_attachments[a],
pCreateInfo);
}
}
if (desc->pDepthStencilAttachment &&
desc->pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) {
subpass->depth_stencil_attachment = next_subpass_attachment++;
vk_subpass_attachment_init(subpass->depth_stencil_attachment,
pass, s,
desc->pDepthStencilAttachment,
pCreateInfo->pAttachments,
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
}
const VkSubpassDescriptionDepthStencilResolve *ds_resolve =
vk_find_struct_const(desc->pNext,
SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE);
if (ds_resolve && ds_resolve->pDepthStencilResolveAttachment &&
ds_resolve->pDepthStencilResolveAttachment->attachment != VK_ATTACHMENT_UNUSED) {
subpass->depth_stencil_resolve_attachment = next_subpass_attachment++;
vk_subpass_attachment_init(subpass->depth_stencil_resolve_attachment,
pass, s,
ds_resolve->pDepthStencilResolveAttachment,
pCreateInfo->pAttachments,
VK_IMAGE_USAGE_TRANSFER_DST_BIT);
vk_subpass_attachment_link_resolve(subpass->depth_stencil_attachment,
subpass->depth_stencil_resolve_attachment,
pCreateInfo);
/* From the Vulkan 1.3.204 spec:
*
* VUID-VkSubpassDescriptionDepthStencilResolve-pDepthStencilResolveAttachment-03178
*
* "If pDepthStencilResolveAttachment is not NULL and does not
* have the value VK_ATTACHMENT_UNUSED, depthResolveMode and
* stencilResolveMode must not both be VK_RESOLVE_MODE_NONE"
*/
assert(ds_resolve->depthResolveMode != VK_RESOLVE_MODE_NONE ||
ds_resolve->stencilResolveMode != VK_RESOLVE_MODE_NONE);
subpass->depth_resolve_mode = ds_resolve->depthResolveMode;
subpass->stencil_resolve_mode = ds_resolve->stencilResolveMode;
}
}
assert(next_subpass_attachment ==
subpass_attachments + subpass_attachment_count);
pass->dependency_count = pCreateInfo->dependencyCount;
for (uint32_t d = 0; d < pCreateInfo->dependencyCount; d++) {
const VkSubpassDependency2 *dep = &pCreateInfo->pDependencies[d];
pass->dependencies[d] = (struct vk_subpass_dependency) {
.flags = dep->dependencyFlags,
.src_subpass = dep->srcSubpass,
.dst_subpass = dep->dstSubpass,
.src_stage_mask = (VkPipelineStageFlags2)dep->srcStageMask,
.dst_stage_mask = (VkPipelineStageFlags2)dep->dstStageMask,
.src_access_mask = (VkAccessFlags2)dep->srcAccessMask,
.dst_access_mask = (VkAccessFlags2)dep->dstAccessMask,
.view_offset = dep->viewOffset,
};
/* From the Vulkan 1.3.204 spec:
*
* "If a VkMemoryBarrier2 is included in the pNext chain,
* srcStageMask, dstStageMask, srcAccessMask, and dstAccessMask
* parameters are ignored. The synchronization and access scopes
* instead are defined by the parameters of VkMemoryBarrier2."
*/
const VkMemoryBarrier2 *barrier =
vk_find_struct_const(dep->pNext, MEMORY_BARRIER_2);
if (barrier != NULL) {
pass->dependencies[d].src_stage_mask = barrier->srcStageMask;
pass->dependencies[d].dst_stage_mask = barrier->dstStageMask;
pass->dependencies[d].src_access_mask = barrier->srcAccessMask;
pass->dependencies[d].dst_access_mask = barrier->dstAccessMask;
}
}
*pRenderPass = vk_render_pass_to_handle(pass);
return VK_SUCCESS;
}
VKAPI_ATTR void VKAPI_CALL
vk_common_DestroyRenderPass(VkDevice _device,
VkRenderPass renderPass,
const VkAllocationCallbacks *pAllocator)
{
VK_FROM_HANDLE(vk_device, device, _device);
VK_FROM_HANDLE(vk_render_pass, pass, renderPass);
if (!pass)
return;
vk_object_free(device, pAllocator, pass);
}

View File

@@ -0,0 +1,206 @@
/*
* Copyright © 2021 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#ifndef VK_RENDER_PASS_H
#define VK_RENDER_PASS_H
#include "vk_object.h"
#ifdef __cplusplus
extern "C" {
#endif
struct vk_subpass_attachment {
/** VkAttachmentReference2::attachment */
uint32_t attachment;
/** 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.
*/
VkImageAspectFlags aspects;
/** 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.
*/
VkImageUsageFlagBits usage;
/** VkAttachmentReference2::layout */
VkImageLayout layout;
/** VkAttachmentReferenceStencilLayout::stencilLayout
*
* 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.
*/
VkImageLayout stencil_layout;
/** Resolve attachment, if any */
struct vk_subpass_attachment *resolve;
};
struct vk_subpass {
/** Count of all attachments referenced by this subpass */
uint32_t attachment_count;
/** Array of all attachments referenced by this subpass */
struct vk_subpass_attachment *attachments;
/** VkSubpassDescription2::inputAttachmentCount */
uint32_t input_count;
/** VkSubpassDescription2::pInputAttachments */
struct vk_subpass_attachment *input_attachments;
/** VkSubpassDescription2::colorAttachmentCount */
uint32_t color_count;
/** VkSubpassDescription2::pColorAttachments */
struct vk_subpass_attachment *color_attachments;
/** VkSubpassDescription2::colorAttachmentCount or zero */
uint32_t color_resolve_count;
/** VkSubpassDescription2::pResolveAttachments */
struct vk_subpass_attachment *color_resolve_attachments;
/** VkSubpassDescription2::pDepthStencilAttachment */
struct vk_subpass_attachment *depth_stencil_attachment;
/** VkSubpassDescriptionDepthStencilResolve::pDepthStencilResolveAttachment */
struct vk_subpass_attachment *depth_stencil_resolve_attachment;
/** VkSubpassDescription2::viewMask */
uint32_t view_mask;
/** VkSubpassDescriptionDepthStencilResolve::depthResolveMode */
VkResolveModeFlagBitsKHR depth_resolve_mode;
/** VkSubpassDescriptionDepthStencilResolve::stencilResolveMode */
VkResolveModeFlagBitsKHR stencil_resolve_mode;
};
struct vk_render_pass_attachment {
/** VkAttachmentDescription2::format */
VkFormat format;
/** Aspects contained in format */
VkImageAspectFlags aspects;
/** VkAttachmentDescription2::samples */
uint32_t samples;
/** VkAttachmentDescription2::loadOp */
VkAttachmentLoadOp load_op;
/** VkAttachmentDescription2::storeOp */
VkAttachmentStoreOp store_op;
/** VkAttachmentDescription2::stencilLoadOp */
VkAttachmentLoadOp stencil_load_op;
/** VkAttachmentDescription2::stencilStoreOp */
VkAttachmentStoreOp stencil_store_op;
/** VkAttachmentDescription2::initialLayout */
VkImageLayout initial_layout;
/** VkAttachmentDescription2::finalLayout */
VkImageLayout final_layout;
/** VkAttachmentDescriptionStencilLayout::stencilInitialLayout
*
* 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 initial_stencil_layout;
/** VkAttachmentDescriptionStencilLayout::stencilFinalLayout
*
* 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.
*/
VkImageLayout final_stencil_layout;
};
struct vk_subpass_dependency {
/** VkSubpassDependency2::dependencyFlags */
VkDependencyFlags flags;
/** VkSubpassDependency2::srcSubpass */
uint32_t src_subpass;
/** VkSubpassDependency2::dstSubpass */
uint32_t dst_subpass;
/** VkSubpassDependency2::srcStageMask */
VkPipelineStageFlags2 src_stage_mask;
/** VkSubpassDependency2::dstStageMask */
VkPipelineStageFlags2 dst_stage_mask;
/** VkSubpassDependency2::srcAccessMask */
VkAccessFlags2 src_access_mask;
/** VkSubpassDependency2::dstAccessMask */
VkAccessFlags2 dst_access_mask;
/** VkSubpassDependency2::viewOffset */
int32_t view_offset;
};
struct vk_render_pass {
struct vk_object_base base;
/** VkRenderPassCreateInfo2::attachmentCount */
uint32_t attachment_count;
/** VkRenderPassCreateInfo2::pAttachments */
struct vk_render_pass_attachment *attachments;
/** VkRenderPassCreateInfo2::subpassCount */
uint32_t subpass_count;
/** VkRenderPassCreateInfo2::subpasses */
struct vk_subpass *subpasses;
/** VkRenderPassCreateInfo2::dependencyCount */
uint32_t dependency_count;
/** VkRenderPassCreateInfo2::pDependencies */
struct vk_subpass_dependency *dependencies;
};
VK_DEFINE_NONDISP_HANDLE_CASTS(vk_render_pass, base, VkRenderPass,
VK_OBJECT_TYPE_RENDER_PASS);
#ifdef __cplusplus
}
#endif
#endif /* VK_RENDER_PASS_H */