2021-02-04 06:50:54 +00:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
2021-09-22 20:13:00 +01:00
|
|
|
#include "vk_render_pass.h"
|
|
|
|
|
2021-03-10 14:27:14 +00:00
|
|
|
#include "vk_alloc.h"
|
2021-09-22 20:13:00 +01:00
|
|
|
#include "vk_command_buffer.h"
|
2021-02-04 06:50:54 +00:00
|
|
|
#include "vk_common_entrypoints.h"
|
|
|
|
#include "vk_device.h"
|
2021-02-04 07:13:33 +00:00
|
|
|
#include "vk_format.h"
|
2021-09-22 20:13:00 +01:00
|
|
|
#include "vk_framebuffer.h"
|
|
|
|
#include "vk_image.h"
|
2021-02-04 06:50:54 +00:00
|
|
|
#include "vk_util.h"
|
|
|
|
|
2021-02-04 07:13:33 +00:00
|
|
|
#include "util/log.h"
|
|
|
|
|
2021-02-04 06:50:54 +00:00
|
|
|
static void
|
|
|
|
translate_references(VkAttachmentReference2 **reference_ptr,
|
2021-02-04 07:13:33 +00:00
|
|
|
uint32_t reference_count,
|
2021-02-04 06:50:54 +00:00
|
|
|
const VkAttachmentReference *reference,
|
2021-02-04 07:13:33 +00:00
|
|
|
const VkRenderPassCreateInfo *pass_info,
|
|
|
|
bool is_input_attachment)
|
2021-02-04 06:50:54 +00:00
|
|
|
{
|
|
|
|
VkAttachmentReference2 *reference2 = *reference_ptr;
|
2021-02-04 07:13:33 +00:00
|
|
|
*reference_ptr += reference_count;
|
|
|
|
for (uint32_t i = 0; i < reference_count; i++) {
|
2021-02-04 06:50:54 +00:00
|
|
|
reference2[i] = (VkAttachmentReference2) {
|
|
|
|
.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,
|
|
|
|
.pNext = NULL,
|
|
|
|
.attachment = reference[i].attachment,
|
|
|
|
.layout = reference[i].layout,
|
|
|
|
};
|
2021-02-04 07:13:33 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
2021-02-04 06:50:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-12 06:24:23 +00:00
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL
|
2021-02-04 06:50:54 +00:00
|
|
|
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;
|
|
|
|
}
|
2021-03-10 14:27:14 +00:00
|
|
|
|
|
|
|
VK_MULTIALLOC(ma);
|
2021-03-11 02:20:37 +00:00
|
|
|
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);
|
2021-03-10 14:27:14 +00:00
|
|
|
if (!vk_multialloc_alloc2(&ma, &device->alloc, pAllocator,
|
|
|
|
VK_SYSTEM_ALLOCATION_SCOPE_COMMAND))
|
|
|
|
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
|
|
|
|
|
|
|
VkAttachmentReference2 *reference_ptr = references;
|
2021-02-04 06:50:54 +00:00
|
|
|
|
2021-02-04 07:13:33 +00:00
|
|
|
const VkRenderPassMultiviewCreateInfo *multiview_info = NULL;
|
|
|
|
const VkRenderPassInputAttachmentAspectCreateInfo *aspect_info = NULL;
|
2021-02-04 06:50:54 +00:00
|
|
|
vk_foreach_struct(ext, pCreateInfo->pNext) {
|
2021-02-04 07:13:33 +00:00
|
|
|
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);
|
2021-02-04 06:50:54 +00:00
|
|
|
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,
|
2021-02-04 07:40:26 +00:00
|
|
|
.preserveAttachmentCount = pCreateInfo->pSubpasses[i].preserveAttachmentCount,
|
|
|
|
.pPreserveAttachments = pCreateInfo->pSubpasses[i].pPreserveAttachments,
|
2021-02-04 06:50:54 +00:00
|
|
|
};
|
|
|
|
|
2021-02-04 07:36:06 +00:00
|
|
|
if (multiview_info && multiview_info->subpassCount) {
|
|
|
|
assert(multiview_info->subpassCount == pCreateInfo->subpassCount);
|
2021-02-04 06:50:54 +00:00
|
|
|
subpasses[i].viewMask = multiview_info->pViewMasks[i];
|
2021-02-04 07:36:06 +00:00
|
|
|
}
|
2021-02-04 06:50:54 +00:00
|
|
|
|
|
|
|
subpasses[i].pInputAttachments = reference_ptr;
|
|
|
|
translate_references(&reference_ptr,
|
2021-02-04 07:13:33 +00:00
|
|
|
subpasses[i].inputAttachmentCount,
|
2021-02-04 06:50:54 +00:00
|
|
|
pCreateInfo->pSubpasses[i].pInputAttachments,
|
2021-02-04 07:13:33 +00:00
|
|
|
pCreateInfo, true);
|
2021-02-04 06:50:54 +00:00
|
|
|
subpasses[i].pColorAttachments = reference_ptr;
|
|
|
|
translate_references(&reference_ptr,
|
2021-02-04 07:13:33 +00:00
|
|
|
subpasses[i].colorAttachmentCount,
|
2021-02-04 06:50:54 +00:00
|
|
|
pCreateInfo->pSubpasses[i].pColorAttachments,
|
2021-02-04 07:13:33 +00:00
|
|
|
pCreateInfo, false);
|
2021-02-04 06:50:54 +00:00
|
|
|
subpasses[i].pResolveAttachments = NULL;
|
|
|
|
if (pCreateInfo->pSubpasses[i].pResolveAttachments) {
|
|
|
|
subpasses[i].pResolveAttachments = reference_ptr;
|
|
|
|
translate_references(&reference_ptr,
|
2021-02-04 07:13:33 +00:00
|
|
|
subpasses[i].colorAttachmentCount,
|
2021-02-04 06:50:54 +00:00
|
|
|
pCreateInfo->pSubpasses[i].pResolveAttachments,
|
2021-02-04 07:13:33 +00:00
|
|
|
pCreateInfo, false);
|
2021-02-04 06:50:54 +00:00
|
|
|
}
|
|
|
|
subpasses[i].pDepthStencilAttachment = NULL;
|
|
|
|
if (pCreateInfo->pSubpasses[i].pDepthStencilAttachment) {
|
|
|
|
subpasses[i].pDepthStencilAttachment = reference_ptr;
|
2021-02-04 07:13:33 +00:00
|
|
|
translate_references(&reference_ptr, 1,
|
2021-02-04 06:50:54 +00:00
|
|
|
pCreateInfo->pSubpasses[i].pDepthStencilAttachment,
|
2021-02-04 07:13:33 +00:00
|
|
|
pCreateInfo, false);
|
2021-02-04 06:50:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-10 14:27:14 +00:00
|
|
|
assert(reference_ptr == references + reference_count);
|
2021-02-04 06:50:54 +00:00
|
|
|
|
2021-02-04 07:13:33 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-04 06:50:54 +00:00
|
|
|
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,
|
|
|
|
};
|
|
|
|
|
2021-02-04 07:36:06 +00:00
|
|
|
if (multiview_info && multiview_info->dependencyCount) {
|
|
|
|
assert(multiview_info->dependencyCount == pCreateInfo->dependencyCount);
|
2021-02-04 06:50:54 +00:00
|
|
|
dependencies[i].viewOffset = multiview_info->pViewOffsets[i];
|
2021-02-04 07:36:06 +00:00
|
|
|
}
|
2021-02-04 06:50:54 +00:00
|
|
|
}
|
|
|
|
|
2021-03-10 14:27:14 +00:00
|
|
|
*create_info = (VkRenderPassCreateInfo2) {
|
2021-02-04 06:50:54 +00:00
|
|
|
.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,
|
|
|
|
};
|
|
|
|
|
2021-02-04 07:36:06 +00:00
|
|
|
if (multiview_info && multiview_info->correlationMaskCount > 0) {
|
2021-03-10 14:27:14 +00:00
|
|
|
create_info->correlatedViewMaskCount = multiview_info->correlationMaskCount;
|
|
|
|
create_info->pCorrelatedViewMasks = multiview_info->pCorrelationMasks;
|
2021-02-04 06:50:54 +00:00
|
|
|
}
|
|
|
|
|
2021-03-10 14:27:14 +00:00
|
|
|
VkResult result =
|
|
|
|
device->dispatch_table.CreateRenderPass2(_device, create_info,
|
|
|
|
pAllocator, pRenderPass);
|
|
|
|
|
|
|
|
vk_free2(&device->alloc, pAllocator, create_info);
|
|
|
|
|
|
|
|
return result;
|
2021-02-04 06:50:54 +00:00
|
|
|
}
|
2021-03-15 14:31:05 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
2021-09-22 20:13:00 +01:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|