From 874aeb8743d71badac30b2ea5ad392088a8ba9d7 Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Wed, 22 Sep 2021 14:13:00 -0500 Subject: [PATCH] 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 Part-of: --- src/vulkan/runtime/vk_image.h | 2 + src/vulkan/runtime/vk_render_pass.c | 307 ++++++++++++++++++++++++++++++++++++ src/vulkan/runtime/vk_render_pass.h | 206 ++++++++++++++++++++++++ 3 files changed, 515 insertions(+) create mode 100644 src/vulkan/runtime/vk_render_pass.h diff --git a/src/vulkan/runtime/vk_image.h b/src/vulkan/runtime/vk_image.h index e21c499..fb58cbf 100644 --- a/src/vulkan/runtime/vk_image.h +++ b/src/vulkan/runtime/vk_image.h @@ -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, diff --git a/src/vulkan/runtime/vk_render_pass.c b/src/vulkan/runtime/vk_render_pass.c index fa736ec..faaa3f2 100644 --- a/src/vulkan/runtime/vk_render_pass.c +++ b/src/vulkan/runtime/vk_render_pass.c @@ -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); +} diff --git a/src/vulkan/runtime/vk_render_pass.h b/src/vulkan/runtime/vk_render_pass.h new file mode 100644 index 0000000..17b4773 --- /dev/null +++ b/src/vulkan/runtime/vk_render_pass.h @@ -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 */ -- 2.7.4