mesa/src/vulkan/runtime/vk_render_pass.c

599 lines
24 KiB
C
Raw Normal View History

/*
* Copyright © 2020 Valve 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.
*/
#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"
static void
translate_references(VkAttachmentReference2 **reference_ptr,
uint32_t reference_count,
const VkAttachmentReference *reference,
const VkRenderPassCreateInfo *pass_info,
bool is_input_attachment)
{
VkAttachmentReference2 *reference2 = *reference_ptr;
*reference_ptr += reference_count;
for (uint32_t i = 0; i < reference_count; i++) {
reference2[i] = (VkAttachmentReference2) {
.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,
.pNext = NULL,
.attachment = reference[i].attachment,
.layout = reference[i].layout,
};
if (is_input_attachment &&
reference2[i].attachment != VK_ATTACHMENT_UNUSED) {
assert(reference2[i].attachment < pass_info->attachmentCount);
const VkAttachmentDescription *att =
&pass_info->pAttachments[reference2[i].attachment];
reference2[i].aspectMask = vk_format_aspects(att->format);
}
}
}
VKAPI_ATTR VkResult VKAPI_CALL
vk_common_CreateRenderPass(VkDevice _device,
const VkRenderPassCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkRenderPass *pRenderPass)
{
VK_FROM_HANDLE(vk_device, device, _device);
uint32_t reference_count = 0;
for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) {
reference_count += pCreateInfo->pSubpasses[i].inputAttachmentCount;
reference_count += pCreateInfo->pSubpasses[i].colorAttachmentCount;
if (pCreateInfo->pSubpasses[i].pResolveAttachments)
reference_count += pCreateInfo->pSubpasses[i].colorAttachmentCount;
if (pCreateInfo->pSubpasses[i].pDepthStencilAttachment)
reference_count += 1;
}
VK_MULTIALLOC(ma);
VK_MULTIALLOC_DECL(&ma, VkRenderPassCreateInfo2, create_info, 1);
VK_MULTIALLOC_DECL(&ma, VkSubpassDescription2, subpasses,
pCreateInfo->subpassCount);
VK_MULTIALLOC_DECL(&ma, VkAttachmentDescription2, attachments,
pCreateInfo->attachmentCount);
VK_MULTIALLOC_DECL(&ma, VkSubpassDependency2, dependencies,
pCreateInfo->dependencyCount);
VK_MULTIALLOC_DECL(&ma, VkAttachmentReference2, references,
reference_count);
if (!vk_multialloc_alloc2(&ma, &device->alloc, pAllocator,
VK_SYSTEM_ALLOCATION_SCOPE_COMMAND))
return VK_ERROR_OUT_OF_HOST_MEMORY;
VkAttachmentReference2 *reference_ptr = references;
const VkRenderPassMultiviewCreateInfo *multiview_info = NULL;
const VkRenderPassInputAttachmentAspectCreateInfo *aspect_info = NULL;
vk_foreach_struct(ext, pCreateInfo->pNext) {
switch (ext->sType) {
case VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO:
aspect_info = (const VkRenderPassInputAttachmentAspectCreateInfo *)ext;
/* We don't care about this information */
break;
case VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO:
multiview_info = (const VkRenderPassMultiviewCreateInfo*) ext;
break;
default:
mesa_logd("%s: ignored VkStructureType %u\n", __func__, ext->sType);
break;
}
}
for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) {
attachments[i] = (VkAttachmentDescription2) {
.sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,
.pNext = NULL,
.flags = pCreateInfo->pAttachments[i].flags,
.format = pCreateInfo->pAttachments[i].format,
.samples = pCreateInfo->pAttachments[i].samples,
.loadOp = pCreateInfo->pAttachments[i].loadOp,
.storeOp = pCreateInfo->pAttachments[i].storeOp,
.stencilLoadOp = pCreateInfo->pAttachments[i].stencilLoadOp,
.stencilStoreOp = pCreateInfo->pAttachments[i].stencilStoreOp,
.initialLayout = pCreateInfo->pAttachments[i].initialLayout,
.finalLayout = pCreateInfo->pAttachments[i].finalLayout,
};
}
for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) {
subpasses[i] = (VkSubpassDescription2) {
.sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2,
.pNext = NULL,
.flags = pCreateInfo->pSubpasses[i].flags,
.pipelineBindPoint = pCreateInfo->pSubpasses[i].pipelineBindPoint,
.viewMask = 0,
.inputAttachmentCount = pCreateInfo->pSubpasses[i].inputAttachmentCount,
.colorAttachmentCount = pCreateInfo->pSubpasses[i].colorAttachmentCount,
.preserveAttachmentCount = pCreateInfo->pSubpasses[i].preserveAttachmentCount,
.pPreserveAttachments = pCreateInfo->pSubpasses[i].pPreserveAttachments,
};
if (multiview_info && multiview_info->subpassCount) {
assert(multiview_info->subpassCount == pCreateInfo->subpassCount);
subpasses[i].viewMask = multiview_info->pViewMasks[i];
}
subpasses[i].pInputAttachments = reference_ptr;
translate_references(&reference_ptr,
subpasses[i].inputAttachmentCount,
pCreateInfo->pSubpasses[i].pInputAttachments,
pCreateInfo, true);
subpasses[i].pColorAttachments = reference_ptr;
translate_references(&reference_ptr,
subpasses[i].colorAttachmentCount,
pCreateInfo->pSubpasses[i].pColorAttachments,
pCreateInfo, false);
subpasses[i].pResolveAttachments = NULL;
if (pCreateInfo->pSubpasses[i].pResolveAttachments) {
subpasses[i].pResolveAttachments = reference_ptr;
translate_references(&reference_ptr,
subpasses[i].colorAttachmentCount,
pCreateInfo->pSubpasses[i].pResolveAttachments,
pCreateInfo, false);
}
subpasses[i].pDepthStencilAttachment = NULL;
if (pCreateInfo->pSubpasses[i].pDepthStencilAttachment) {
subpasses[i].pDepthStencilAttachment = reference_ptr;
translate_references(&reference_ptr, 1,
pCreateInfo->pSubpasses[i].pDepthStencilAttachment,
pCreateInfo, false);
}
}
assert(reference_ptr == references + reference_count);
if (aspect_info != NULL) {
for (uint32_t i = 0; i < aspect_info->aspectReferenceCount; i++) {
const VkInputAttachmentAspectReference *ref =
&aspect_info->pAspectReferences[i];
assert(ref->subpass < pCreateInfo->subpassCount);
VkSubpassDescription2 *subpass = &subpasses[ref->subpass];
assert(ref->inputAttachmentIndex < subpass->inputAttachmentCount);
VkAttachmentReference2 *att = (VkAttachmentReference2 *)
&subpass->pInputAttachments[ref->inputAttachmentIndex];
att->aspectMask = ref->aspectMask;
}
}
for (uint32_t i = 0; i < pCreateInfo->dependencyCount; i++) {
dependencies[i] = (VkSubpassDependency2) {
.sType = VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2,
.pNext = NULL,
.srcSubpass = pCreateInfo->pDependencies[i].srcSubpass,
.dstSubpass = pCreateInfo->pDependencies[i].dstSubpass,
.srcStageMask = pCreateInfo->pDependencies[i].srcStageMask,
.dstStageMask = pCreateInfo->pDependencies[i].dstStageMask,
.srcAccessMask = pCreateInfo->pDependencies[i].srcAccessMask,
.dstAccessMask = pCreateInfo->pDependencies[i].dstAccessMask,
.dependencyFlags = pCreateInfo->pDependencies[i].dependencyFlags,
.viewOffset = 0,
};
if (multiview_info && multiview_info->dependencyCount) {
assert(multiview_info->dependencyCount == pCreateInfo->dependencyCount);
dependencies[i].viewOffset = multiview_info->pViewOffsets[i];
}
}
*create_info = (VkRenderPassCreateInfo2) {
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2,
.pNext = pCreateInfo->pNext,
.flags = pCreateInfo->flags,
.attachmentCount = pCreateInfo->attachmentCount,
.pAttachments = attachments,
.subpassCount = pCreateInfo->subpassCount,
.pSubpasses = subpasses,
.dependencyCount = pCreateInfo->dependencyCount,
.pDependencies = dependencies,
};
if (multiview_info && multiview_info->correlationMaskCount > 0) {
create_info->correlatedViewMaskCount = multiview_info->correlationMaskCount;
create_info->pCorrelatedViewMasks = multiview_info->pCorrelationMasks;
}
VkResult result =
device->dispatch_table.CreateRenderPass2(_device, create_info,
pAllocator, pRenderPass);
vk_free2(&device->alloc, pAllocator, create_info);
return result;
}
VKAPI_ATTR void VKAPI_CALL
vk_common_CmdBeginRenderPass(VkCommandBuffer commandBuffer,
const VkRenderPassBeginInfo* pRenderPassBegin,
VkSubpassContents contents)
{
/* We don't have a vk_command_buffer object but we can assume, since we're
* using common dispatch, that it's a vk_object of some sort.
*/
struct vk_object_base *disp = (struct vk_object_base *)commandBuffer;
VkSubpassBeginInfo info = {
.sType = VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO,
.contents = contents,
};
disp->device->dispatch_table.CmdBeginRenderPass2(commandBuffer,
pRenderPassBegin, &info);
}
VKAPI_ATTR void VKAPI_CALL
vk_common_CmdEndRenderPass(VkCommandBuffer commandBuffer)
{
/* We don't have a vk_command_buffer object but we can assume, since we're
* using common dispatch, that it's a vk_object of some sort.
*/
struct vk_object_base *disp = (struct vk_object_base *)commandBuffer;
VkSubpassEndInfo info = {
.sType = VK_STRUCTURE_TYPE_SUBPASS_END_INFO,
};
disp->device->dispatch_table.CmdEndRenderPass2(commandBuffer, &info);
}
VKAPI_ATTR void VKAPI_CALL
vk_common_CmdNextSubpass(VkCommandBuffer commandBuffer,
VkSubpassContents contents)
{
/* We don't have a vk_command_buffer object but we can assume, since we're
* using common dispatch, that it's a vk_object of some sort.
*/
struct vk_object_base *disp = (struct vk_object_base *)commandBuffer;
VkSubpassBeginInfo begin_info = {
.sType = VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO,
.contents = contents,
};
VkSubpassEndInfo end_info = {
.sType = VK_STRUCTURE_TYPE_SUBPASS_END_INFO,
};
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);
}