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;
|
2022-07-19 09:39:14 +01:00
|
|
|
|
vk_foreach_struct_const(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 =
|
2022-02-10 15:43:27 +00:00
|
|
|
|
ds_resolve != NULL && ds_resolve->pDepthStencilResolveAttachment &&
|
2021-09-22 20:13:00 +01:00
|
|
|
|
ds_resolve->pDepthStencilResolveAttachment->attachment != VK_ATTACHMENT_UNUSED;
|
|
|
|
|
|
2022-02-10 15:43:27 +00:00
|
|
|
|
const VkFragmentShadingRateAttachmentInfoKHR *fsr_att_info =
|
|
|
|
|
vk_find_struct_const(desc->pNext,
|
|
|
|
|
FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR);
|
|
|
|
|
|
|
|
|
|
bool has_fragment_shading_rate_attachment =
|
|
|
|
|
fsr_att_info && fsr_att_info->pFragmentShadingRateAttachment &&
|
|
|
|
|
fsr_att_info->pFragmentShadingRateAttachment->attachment != VK_ATTACHMENT_UNUSED;
|
|
|
|
|
|
2021-09-22 20:13:00 +01:00
|
|
|
|
return desc->inputAttachmentCount +
|
|
|
|
|
desc->colorAttachmentCount +
|
|
|
|
|
(desc->pResolveAttachments ? desc->colorAttachmentCount : 0) +
|
|
|
|
|
has_depth_stencil_attachment +
|
2022-02-10 15:43:27 +00:00
|
|
|
|
has_depth_stencil_resolve_attachment +
|
|
|
|
|
has_fragment_shading_rate_attachment;
|
2021-09-22 20:13:00 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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,
|
2022-02-09 22:30:38 +00:00
|
|
|
|
.view_mask = 0,
|
2021-09-22 20:13:00 +01:00
|
|
|
|
.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:
|
2022-02-10 15:43:27 +00:00
|
|
|
|
case VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR:
|
2021-09-22 20:13:00 +01:00
|
|
|
|
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;
|
2022-05-06 20:53:03 +01:00
|
|
|
|
uint32_t subpass_color_attachment_count = 0;
|
2021-09-22 20:13:00 +01:00
|
|
|
|
for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) {
|
|
|
|
|
subpass_attachment_count +=
|
|
|
|
|
num_subpass_attachments2(&pCreateInfo->pSubpasses[i]);
|
2022-05-06 20:53:03 +01:00
|
|
|
|
subpass_color_attachment_count +=
|
2022-02-10 23:30:01 +00:00
|
|
|
|
pCreateInfo->pSubpasses[i].colorAttachmentCount;
|
2021-09-22 20:13:00 +01:00
|
|
|
|
}
|
|
|
|
|
VK_MULTIALLOC_DECL(&ma, struct vk_subpass_attachment, subpass_attachments,
|
|
|
|
|
subpass_attachment_count);
|
2022-02-10 23:30:01 +00:00
|
|
|
|
VK_MULTIALLOC_DECL(&ma, VkFormat, subpass_color_formats,
|
2022-05-06 20:53:03 +01:00
|
|
|
|
subpass_color_attachment_count);
|
|
|
|
|
VK_MULTIALLOC_DECL(&ma, VkSampleCountFlagBits, subpass_color_samples,
|
|
|
|
|
subpass_color_attachment_count);
|
2021-09-22 20:13:00 +01:00
|
|
|
|
|
|
|
|
|
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;
|
2022-02-10 23:30:01 +00:00
|
|
|
|
VkFormat *next_subpass_color_format = subpass_color_formats;
|
2022-05-06 20:53:03 +01:00
|
|
|
|
VkSampleCountFlagBits *next_subpass_color_samples = subpass_color_samples;
|
2021-09-22 20:13:00 +01:00
|
|
|
|
for (uint32_t s = 0; s < pCreateInfo->subpassCount; s++) {
|
|
|
|
|
const VkSubpassDescription2 *desc = &pCreateInfo->pSubpasses[s];
|
|
|
|
|
struct vk_subpass *subpass = &pass->subpasses[s];
|
2022-07-22 06:03:34 +01:00
|
|
|
|
const VkMultisampledRenderToSingleSampledInfoEXT *mrtss =
|
|
|
|
|
vk_find_struct_const(desc->pNext, MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_INFO_EXT);
|
|
|
|
|
if (mrtss && !mrtss->multisampledRenderToSingleSampledEnable)
|
|
|
|
|
mrtss = NULL;
|
2021-09-22 20:13:00 +01:00
|
|
|
|
|
|
|
|
|
subpass->attachment_count = num_subpass_attachments2(desc);
|
|
|
|
|
subpass->attachments = next_subpass_attachment;
|
2022-02-09 22:30:38 +00:00
|
|
|
|
|
|
|
|
|
/* From the Vulkan 1.3.204 spec:
|
|
|
|
|
*
|
|
|
|
|
* VUID-VkRenderPassCreateInfo2-viewMask-03058
|
|
|
|
|
*
|
|
|
|
|
* "The VkSubpassDescription2::viewMask member of all elements of
|
|
|
|
|
* pSubpasses must either all be 0, or all not be 0"
|
|
|
|
|
*/
|
|
|
|
|
if (desc->viewMask)
|
|
|
|
|
pass->is_multiview = true;
|
|
|
|
|
assert(pass->is_multiview == (desc->viewMask != 0));
|
|
|
|
|
|
|
|
|
|
/* For all view masks in the vk_render_pass data structure, we use a
|
|
|
|
|
* mask of 1 for non-multiview instead of a mask of 0.
|
|
|
|
|
*/
|
|
|
|
|
subpass->view_mask = desc->viewMask ? desc->viewMask : 1;
|
|
|
|
|
pass->view_mask |= subpass->view_mask;
|
2021-09-22 20:13:00 +01:00
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
2022-07-22 06:03:34 +01:00
|
|
|
|
if (ds_resolve) {
|
|
|
|
|
if (ds_resolve->pDepthStencilResolveAttachment &&
|
|
|
|
|
ds_resolve->pDepthStencilResolveAttachment->attachment != VK_ATTACHMENT_UNUSED) {
|
|
|
|
|
subpass->depth_stencil_resolve_attachment = next_subpass_attachment++;
|
2021-09-22 20:13:00 +01:00
|
|
|
|
|
2022-07-22 06:03:34 +01:00
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
if (subpass->depth_stencil_resolve_attachment || mrtss) {
|
|
|
|
|
/* 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;
|
|
|
|
|
}
|
2021-09-22 20:13:00 +01:00
|
|
|
|
}
|
2022-02-10 23:30:01 +00:00
|
|
|
|
|
2022-02-10 15:43:27 +00:00
|
|
|
|
const VkFragmentShadingRateAttachmentInfoKHR *fsr_att_info =
|
|
|
|
|
vk_find_struct_const(desc->pNext,
|
|
|
|
|
FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR);
|
|
|
|
|
|
|
|
|
|
if (fsr_att_info && fsr_att_info->pFragmentShadingRateAttachment &&
|
|
|
|
|
fsr_att_info->pFragmentShadingRateAttachment->attachment != VK_ATTACHMENT_UNUSED) {
|
|
|
|
|
subpass->fragment_shading_rate_attachment = next_subpass_attachment++;
|
|
|
|
|
vk_subpass_attachment_init(subpass->fragment_shading_rate_attachment,
|
|
|
|
|
pass, s,
|
|
|
|
|
fsr_att_info->pFragmentShadingRateAttachment,
|
|
|
|
|
pCreateInfo->pAttachments,
|
|
|
|
|
VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR);
|
|
|
|
|
subpass->fragment_shading_rate_attachment_texel_size =
|
|
|
|
|
fsr_att_info->shadingRateAttachmentTexelSize;
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-12 22:47:46 +01:00
|
|
|
|
/* Figure out any self-dependencies */
|
|
|
|
|
assert(desc->colorAttachmentCount <= 32);
|
|
|
|
|
uint32_t color_self_deps = 0;
|
|
|
|
|
bool has_depth_self_dep = false;
|
|
|
|
|
bool has_stencil_self_dep = false;
|
|
|
|
|
for (uint32_t a = 0; a < desc->inputAttachmentCount; a++) {
|
|
|
|
|
if (desc->pInputAttachments[a].attachment == VK_ATTACHMENT_UNUSED)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
for (uint32_t c = 0; c < desc->colorAttachmentCount; c++) {
|
|
|
|
|
if (desc->pColorAttachments[c].attachment ==
|
|
|
|
|
desc->pInputAttachments[a].attachment) {
|
|
|
|
|
subpass->input_attachments[a].layout =
|
|
|
|
|
VK_IMAGE_LAYOUT_SUBPASS_SELF_DEPENDENCY_MESA;
|
|
|
|
|
subpass->color_attachments[c].layout =
|
|
|
|
|
VK_IMAGE_LAYOUT_SUBPASS_SELF_DEPENDENCY_MESA;
|
|
|
|
|
color_self_deps |= (1u << c);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (desc->pDepthStencilAttachment != NULL &&
|
|
|
|
|
desc->pDepthStencilAttachment->attachment ==
|
|
|
|
|
desc->pInputAttachments[a].attachment) {
|
|
|
|
|
VkImageAspectFlags aspects =
|
|
|
|
|
subpass->input_attachments[a].aspects;
|
|
|
|
|
if (aspects & VK_IMAGE_ASPECT_DEPTH_BIT) {
|
|
|
|
|
subpass->input_attachments[a].layout =
|
|
|
|
|
VK_IMAGE_LAYOUT_SUBPASS_SELF_DEPENDENCY_MESA;
|
|
|
|
|
subpass->depth_stencil_attachment->layout =
|
|
|
|
|
VK_IMAGE_LAYOUT_SUBPASS_SELF_DEPENDENCY_MESA;
|
|
|
|
|
has_depth_self_dep = true;
|
|
|
|
|
}
|
|
|
|
|
if (aspects & VK_IMAGE_ASPECT_STENCIL_BIT) {
|
|
|
|
|
subpass->input_attachments[a].stencil_layout =
|
|
|
|
|
VK_IMAGE_LAYOUT_SUBPASS_SELF_DEPENDENCY_MESA;
|
|
|
|
|
subpass->depth_stencil_attachment->stencil_layout =
|
|
|
|
|
VK_IMAGE_LAYOUT_SUBPASS_SELF_DEPENDENCY_MESA;
|
|
|
|
|
has_stencil_self_dep = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-10 23:30:01 +00:00
|
|
|
|
VkFormat *color_formats = NULL;
|
2022-05-06 20:53:03 +01:00
|
|
|
|
VkSampleCountFlagBits *color_samples = NULL;
|
2022-02-10 23:30:01 +00:00
|
|
|
|
VkSampleCountFlagBits samples = 0;
|
|
|
|
|
if (desc->colorAttachmentCount > 0) {
|
|
|
|
|
color_formats = next_subpass_color_format;
|
2022-05-06 20:53:03 +01:00
|
|
|
|
color_samples = next_subpass_color_samples;
|
2022-02-10 23:30:01 +00:00
|
|
|
|
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;
|
2022-05-06 20:53:03 +01:00
|
|
|
|
color_samples[a] = VK_SAMPLE_COUNT_1_BIT;
|
2022-02-10 23:30:01 +00:00
|
|
|
|
} else {
|
|
|
|
|
const VkAttachmentDescription2 *att =
|
|
|
|
|
&pCreateInfo->pAttachments[ref->attachment];
|
|
|
|
|
|
|
|
|
|
color_formats[a] = att->format;
|
2022-05-06 20:53:03 +01:00
|
|
|
|
color_samples[a] = att->samples;
|
2022-02-10 23:30:01 +00:00
|
|
|
|
|
|
|
|
|
samples |= att->samples;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
next_subpass_color_format += desc->colorAttachmentCount;
|
2022-05-06 20:53:03 +01:00
|
|
|
|
next_subpass_color_samples += desc->colorAttachmentCount;
|
2022-02-10 23:30:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VkFormat depth_format = VK_FORMAT_UNDEFINED;
|
|
|
|
|
VkFormat stencil_format = VK_FORMAT_UNDEFINED;
|
2022-05-06 20:53:03 +01:00
|
|
|
|
VkSampleCountFlagBits depth_stencil_samples = VK_SAMPLE_COUNT_1_BIT;
|
2022-02-10 23:30:01 +00:00
|
|
|
|
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;
|
|
|
|
|
|
2022-05-06 20:53:03 +01:00
|
|
|
|
depth_stencil_samples = att->samples;
|
|
|
|
|
|
2022-02-10 23:30:01 +00:00
|
|
|
|
samples |= att->samples;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-09 22:28:28 +00:00
|
|
|
|
subpass->self_dep_info = (VkRenderingSelfDependencyInfoMESA) {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_RENDERING_SELF_DEPENDENCY_INFO_MESA,
|
|
|
|
|
.colorSelfDependencies = color_self_deps,
|
|
|
|
|
.depthSelfDependency = has_depth_self_dep,
|
|
|
|
|
.stencilSelfDependency = has_stencil_self_dep,
|
|
|
|
|
};
|
|
|
|
|
|
2022-05-06 20:53:03 +01:00
|
|
|
|
subpass->sample_count_info_amd = (VkAttachmentSampleCountInfoAMD) {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_ATTACHMENT_SAMPLE_COUNT_INFO_AMD,
|
|
|
|
|
.pNext = &subpass->self_dep_info,
|
|
|
|
|
.colorAttachmentCount = desc->colorAttachmentCount,
|
|
|
|
|
.pColorAttachmentSamples = color_samples,
|
|
|
|
|
.depthStencilAttachmentSamples = depth_stencil_samples,
|
|
|
|
|
};
|
|
|
|
|
|
2022-02-10 23:30:01 +00:00
|
|
|
|
subpass->pipeline_info = (VkPipelineRenderingCreateInfo) {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,
|
2022-05-06 20:53:03 +01:00
|
|
|
|
.pNext = &subpass->sample_count_info_amd,
|
2022-02-10 23:30:01 +00:00
|
|
|
|
.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,
|
2022-05-06 20:53:03 +01:00
|
|
|
|
.pNext = &subpass->sample_count_info_amd,
|
2022-02-10 23:30:01 +00:00
|
|
|
|
/* 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,
|
|
|
|
|
};
|
2022-07-22 06:03:34 +01:00
|
|
|
|
|
|
|
|
|
if (mrtss) {
|
|
|
|
|
assert(mrtss->multisampledRenderToSingleSampledEnable);
|
|
|
|
|
subpass->mrtss = (VkMultisampledRenderToSingleSampledInfoEXT) {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_INFO_EXT,
|
|
|
|
|
.multisampledRenderToSingleSampledEnable = VK_TRUE,
|
|
|
|
|
.rasterizationSamples = mrtss->rasterizationSamples,
|
|
|
|
|
};
|
|
|
|
|
subpass->self_dep_info.pNext = &subpass->mrtss;
|
|
|
|
|
}
|
2021-09-22 20:13:00 +01:00
|
|
|
|
}
|
|
|
|
|
assert(next_subpass_attachment ==
|
|
|
|
|
subpass_attachments + subpass_attachment_count);
|
2022-02-10 23:30:01 +00:00
|
|
|
|
assert(next_subpass_color_format ==
|
2022-05-06 20:53:03 +01:00
|
|
|
|
subpass_color_formats + subpass_color_attachment_count);
|
|
|
|
|
assert(next_subpass_color_samples ==
|
|
|
|
|
subpass_color_samples + subpass_color_attachment_count);
|
2021-09-22 20:13:00 +01:00
|
|
|
|
|
2022-02-09 22:30:38 +00:00
|
|
|
|
/* Walk backwards over the subpasses to compute view masks and
|
|
|
|
|
* last_subpass masks for all attachments.
|
|
|
|
|
*/
|
|
|
|
|
for (uint32_t s = 0; s < pCreateInfo->subpassCount; s++) {
|
|
|
|
|
struct vk_subpass *subpass =
|
|
|
|
|
&pass->subpasses[(pCreateInfo->subpassCount - 1) - s];
|
|
|
|
|
|
|
|
|
|
/* First, compute last_subpass for all the attachments */
|
|
|
|
|
for (uint32_t a = 0; a < subpass->attachment_count; a++) {
|
|
|
|
|
struct vk_subpass_attachment *att = &subpass->attachments[a];
|
|
|
|
|
if (att->attachment == VK_ATTACHMENT_UNUSED)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
assert(att->attachment < pass->attachment_count);
|
|
|
|
|
const struct vk_render_pass_attachment *pass_att =
|
|
|
|
|
&pass->attachments[att->attachment];
|
|
|
|
|
|
|
|
|
|
att->last_subpass = subpass->view_mask & ~pass_att->view_mask;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Then compute pass_att->view_mask. We do the two separately so that
|
|
|
|
|
* we end up with the right last_subpass even if the same attachment is
|
|
|
|
|
* used twice within a subpass.
|
|
|
|
|
*/
|
|
|
|
|
for (uint32_t a = 0; a < subpass->attachment_count; a++) {
|
|
|
|
|
const struct vk_subpass_attachment *att = &subpass->attachments[a];
|
|
|
|
|
if (att->attachment == VK_ATTACHMENT_UNUSED)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
assert(att->attachment < pass->attachment_count);
|
|
|
|
|
struct vk_render_pass_attachment *pass_att =
|
|
|
|
|
&pass->attachments[att->attachment];
|
|
|
|
|
|
|
|
|
|
pass_att->view_mask |= subpass->view_mask;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-22 20:13:00 +01:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-10 23:30:01 +00:00
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-06 20:53:03 +01:00
|
|
|
|
const VkAttachmentSampleCountInfoAMD *
|
|
|
|
|
vk_get_pipeline_sample_count_info_amd(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].sample_count_info_amd;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return vk_find_struct_const(info->pNext, ATTACHMENT_SAMPLE_COUNT_INFO_AMD);
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-10 23:30:01 +00:00
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-31 21:53:51 +01:00
|
|
|
|
const VkRenderingInfo *
|
|
|
|
|
vk_get_command_buffer_inheritance_as_rendering_resume(
|
|
|
|
|
VkCommandBufferLevel level,
|
|
|
|
|
const VkCommandBufferBeginInfo *pBeginInfo,
|
|
|
|
|
void *stack_data)
|
|
|
|
|
{
|
|
|
|
|
struct vk_gcbiarr_data *data = stack_data;
|
|
|
|
|
|
|
|
|
|
/* 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;
|
|
|
|
|
|
|
|
|
|
VK_FROM_HANDLE(vk_render_pass, pass, inheritance->renderPass);
|
|
|
|
|
if (pass == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
assert(inheritance->subpass < pass->subpass_count);
|
|
|
|
|
const struct vk_subpass *subpass = &pass->subpasses[inheritance->subpass];
|
|
|
|
|
|
|
|
|
|
VK_FROM_HANDLE(vk_framebuffer, fb, inheritance->framebuffer);
|
2022-07-01 13:02:59 +01:00
|
|
|
|
if (fb == NULL || (fb->flags & VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT))
|
2022-05-31 21:53:51 +01:00
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
data->rendering = (VkRenderingInfo) {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
|
|
|
|
|
.flags = VK_RENDERING_RESUMING_BIT,
|
|
|
|
|
.renderArea = {
|
|
|
|
|
.offset = { 0, 0 },
|
|
|
|
|
.extent = { fb->width, fb->height },
|
|
|
|
|
},
|
|
|
|
|
.layerCount = fb->layers,
|
|
|
|
|
.viewMask = pass->is_multiview ? subpass->view_mask : 0,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
VkRenderingAttachmentInfo *attachments = data->attachments;
|
|
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < subpass->color_count; i++) {
|
|
|
|
|
const struct vk_subpass_attachment *sp_att =
|
|
|
|
|
&subpass->color_attachments[i];
|
|
|
|
|
if (sp_att->attachment == VK_ATTACHMENT_UNUSED) {
|
|
|
|
|
attachments[i] = (VkRenderingAttachmentInfo) {
|
|
|
|
|
.imageView = VK_NULL_HANDLE,
|
|
|
|
|
};
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert(sp_att->attachment < pass->attachment_count);
|
|
|
|
|
attachments[i] = (VkRenderingAttachmentInfo) {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
|
|
|
|
|
.imageView = fb->attachments[sp_att->attachment],
|
|
|
|
|
.imageLayout = sp_att->layout,
|
|
|
|
|
.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
|
|
|
|
|
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
data->rendering.colorAttachmentCount = subpass->color_count;
|
|
|
|
|
data->rendering.pColorAttachments = attachments;
|
|
|
|
|
attachments += subpass->color_count;
|
|
|
|
|
|
|
|
|
|
if (subpass->depth_stencil_attachment) {
|
|
|
|
|
const struct vk_subpass_attachment *sp_att =
|
|
|
|
|
subpass->depth_stencil_attachment;
|
|
|
|
|
assert(sp_att->attachment < pass->attachment_count);
|
|
|
|
|
|
|
|
|
|
VK_FROM_HANDLE(vk_image_view, iview, fb->attachments[sp_att->attachment]);
|
|
|
|
|
if (iview->image->aspects & VK_IMAGE_ASPECT_DEPTH_BIT) {
|
|
|
|
|
*attachments = (VkRenderingAttachmentInfo) {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
|
|
|
|
|
.imageView = vk_image_view_to_handle(iview),
|
|
|
|
|
.imageLayout = sp_att->layout,
|
|
|
|
|
.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
|
|
|
|
|
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
|
|
|
|
|
};
|
|
|
|
|
data->rendering.pDepthAttachment = attachments++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (iview->image->aspects & VK_IMAGE_ASPECT_STENCIL_BIT) {
|
|
|
|
|
*attachments = (VkRenderingAttachmentInfo) {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
|
|
|
|
|
.imageView = vk_image_view_to_handle(iview),
|
|
|
|
|
.imageLayout = sp_att->stencil_layout,
|
|
|
|
|
.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
|
|
|
|
|
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
|
|
|
|
|
};
|
|
|
|
|
data->rendering.pStencilAttachment = attachments++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (subpass->fragment_shading_rate_attachment) {
|
|
|
|
|
const struct vk_subpass_attachment *sp_att =
|
|
|
|
|
subpass->fragment_shading_rate_attachment;
|
|
|
|
|
assert(sp_att->attachment < pass->attachment_count);
|
|
|
|
|
|
|
|
|
|
data->fsr_att = (VkRenderingFragmentShadingRateAttachmentInfoKHR) {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR,
|
|
|
|
|
.imageView = fb->attachments[sp_att->attachment],
|
|
|
|
|
.imageLayout = sp_att->layout,
|
|
|
|
|
.shadingRateAttachmentTexelSize =
|
|
|
|
|
subpass->fragment_shading_rate_attachment_texel_size,
|
|
|
|
|
};
|
|
|
|
|
__vk_append_struct(&data->rendering, &data->fsr_att);
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-25 23:05:12 +01:00
|
|
|
|
/* Append this one last because it lives in the subpass and we don't want
|
|
|
|
|
* to be changed by appending other structures later.
|
|
|
|
|
*/
|
|
|
|
|
__vk_append_struct(&data->rendering, (void *)&subpass->self_dep_info);
|
|
|
|
|
|
2022-05-31 21:53:51 +01:00
|
|
|
|
return &data->rendering;
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-22 20:13:00 +01:00
|
|
|
|
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);
|
|
|
|
|
}
|
2022-02-09 22:30:38 +00:00
|
|
|
|
|
|
|
|
|
VKAPI_ATTR void VKAPI_CALL
|
|
|
|
|
vk_common_GetRenderAreaGranularity(VkDevice device,
|
|
|
|
|
VkRenderPass renderPass,
|
|
|
|
|
VkExtent2D *pGranularity)
|
|
|
|
|
{
|
|
|
|
|
*pGranularity = (VkExtent2D) { 1, 1 };
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-07 00:14:26 +01:00
|
|
|
|
static VkRenderPassSampleLocationsBeginInfoEXT *
|
|
|
|
|
clone_rp_sample_locations(const VkRenderPassSampleLocationsBeginInfoEXT *loc)
|
|
|
|
|
{
|
|
|
|
|
uint32_t sl_count = 0;
|
|
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < loc->attachmentInitialSampleLocationsCount; i++) {
|
|
|
|
|
const VkAttachmentSampleLocationsEXT *att_sl_in =
|
|
|
|
|
&loc->pAttachmentInitialSampleLocations[i];
|
|
|
|
|
sl_count += att_sl_in->sampleLocationsInfo.sampleLocationsCount;
|
|
|
|
|
}
|
|
|
|
|
for (uint32_t i = 0; i < loc->postSubpassSampleLocationsCount; i++) {
|
|
|
|
|
const VkSubpassSampleLocationsEXT *sp_sl_in =
|
|
|
|
|
&loc->pPostSubpassSampleLocations[i];
|
|
|
|
|
sl_count += sp_sl_in->sampleLocationsInfo.sampleLocationsCount;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VK_MULTIALLOC(ma);
|
|
|
|
|
VK_MULTIALLOC_DECL(&ma, VkRenderPassSampleLocationsBeginInfoEXT, new_loc, 1);
|
|
|
|
|
VK_MULTIALLOC_DECL(&ma, VkAttachmentSampleLocationsEXT, new_att_sl,
|
|
|
|
|
loc->attachmentInitialSampleLocationsCount);
|
|
|
|
|
VK_MULTIALLOC_DECL(&ma, VkSubpassSampleLocationsEXT, new_sp_sl,
|
|
|
|
|
loc->postSubpassSampleLocationsCount);
|
|
|
|
|
VK_MULTIALLOC_DECL(&ma, VkSampleLocationEXT, sl, sl_count);
|
|
|
|
|
if (!vk_multialloc_alloc(&ma, vk_default_allocator(),
|
|
|
|
|
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT))
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
VkSampleLocationEXT *next_sl = sl;
|
|
|
|
|
for (uint32_t i = 0; i < loc->attachmentInitialSampleLocationsCount; i++) {
|
|
|
|
|
const VkAttachmentSampleLocationsEXT *att_sl_in =
|
|
|
|
|
&loc->pAttachmentInitialSampleLocations[i];
|
|
|
|
|
const VkSampleLocationsInfoEXT *sli_in = &att_sl_in->sampleLocationsInfo;
|
|
|
|
|
|
|
|
|
|
typed_memcpy(next_sl, sli_in->pSampleLocations,
|
|
|
|
|
sli_in->sampleLocationsCount);
|
|
|
|
|
|
|
|
|
|
new_att_sl[i] = (VkAttachmentSampleLocationsEXT) {
|
|
|
|
|
.attachmentIndex = att_sl_in->attachmentIndex,
|
|
|
|
|
.sampleLocationsInfo = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT,
|
|
|
|
|
.sampleLocationsPerPixel = sli_in->sampleLocationsPerPixel,
|
|
|
|
|
.sampleLocationGridSize = sli_in->sampleLocationGridSize,
|
|
|
|
|
.sampleLocationsCount = sli_in->sampleLocationsCount,
|
|
|
|
|
.pSampleLocations = next_sl,
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
next_sl += sli_in->sampleLocationsCount;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < loc->postSubpassSampleLocationsCount; i++) {
|
|
|
|
|
const VkSubpassSampleLocationsEXT *sp_sl_in =
|
|
|
|
|
&loc->pPostSubpassSampleLocations[i];
|
|
|
|
|
const VkSampleLocationsInfoEXT *sli_in = &sp_sl_in->sampleLocationsInfo;
|
|
|
|
|
|
|
|
|
|
typed_memcpy(next_sl, sli_in->pSampleLocations,
|
|
|
|
|
sli_in->sampleLocationsCount);
|
|
|
|
|
|
|
|
|
|
new_sp_sl[i] = (VkSubpassSampleLocationsEXT) {
|
|
|
|
|
.subpassIndex = sp_sl_in->subpassIndex,
|
|
|
|
|
.sampleLocationsInfo = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT,
|
|
|
|
|
.sampleLocationsPerPixel = sli_in->sampleLocationsPerPixel,
|
|
|
|
|
.sampleLocationGridSize = sli_in->sampleLocationGridSize,
|
|
|
|
|
.sampleLocationsCount = sli_in->sampleLocationsCount,
|
|
|
|
|
.pSampleLocations = next_sl,
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
next_sl += sli_in->sampleLocationsCount;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert(next_sl == sl + sl_count);
|
|
|
|
|
|
|
|
|
|
*new_loc = (VkRenderPassSampleLocationsBeginInfoEXT) {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_SAMPLE_LOCATIONS_BEGIN_INFO_EXT,
|
|
|
|
|
.attachmentInitialSampleLocationsCount = loc->attachmentInitialSampleLocationsCount,
|
|
|
|
|
.pAttachmentInitialSampleLocations = new_att_sl,
|
|
|
|
|
.postSubpassSampleLocationsCount = loc->postSubpassSampleLocationsCount,
|
|
|
|
|
.pPostSubpassSampleLocations = new_sp_sl,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return new_loc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const VkSampleLocationsInfoEXT *
|
|
|
|
|
get_subpass_sample_locations(const VkRenderPassSampleLocationsBeginInfoEXT *loc,
|
|
|
|
|
uint32_t subpass_idx)
|
|
|
|
|
{
|
|
|
|
|
for (uint32_t i = 0; i < loc->postSubpassSampleLocationsCount; i++) {
|
|
|
|
|
if (loc->pPostSubpassSampleLocations[i].subpassIndex == subpass_idx)
|
|
|
|
|
return &loc->pPostSubpassSampleLocations[i].sampleLocationsInfo;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-09 22:30:38 +00:00
|
|
|
|
static bool
|
|
|
|
|
vk_image_layout_supports_input_attachment(VkImageLayout layout)
|
|
|
|
|
{
|
|
|
|
|
switch (layout) {
|
|
|
|
|
case VK_IMAGE_LAYOUT_GENERAL:
|
|
|
|
|
case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
|
|
|
|
|
case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
|
|
|
|
|
case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL:
|
|
|
|
|
case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL:
|
|
|
|
|
case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL:
|
|
|
|
|
case VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL:
|
|
|
|
|
case VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR:
|
2022-05-12 22:47:46 +01:00
|
|
|
|
#ifdef __GNUC__
|
|
|
|
|
#pragma GCC diagnostic push
|
|
|
|
|
#pragma GCC diagnostic ignored "-Wswitch"
|
|
|
|
|
#endif
|
|
|
|
|
case VK_IMAGE_LAYOUT_SUBPASS_SELF_DEPENDENCY_MESA:
|
|
|
|
|
#ifdef __GNUC__
|
|
|
|
|
#pragma GCC diagnostic pop
|
|
|
|
|
#endif
|
2022-02-09 22:30:38 +00:00
|
|
|
|
return true;
|
|
|
|
|
default:
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct stage_access {
|
|
|
|
|
VkPipelineStageFlagBits2 stages;
|
|
|
|
|
VkAccessFlagBits2 access;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
vk_image_layout_are_all_aspects_read_only(VkImageLayout layout,
|
|
|
|
|
VkImageAspectFlags aspects)
|
|
|
|
|
{
|
|
|
|
|
u_foreach_bit(a, aspects) {
|
|
|
|
|
VkImageAspectFlagBits aspect = 1u << a;
|
|
|
|
|
if (!vk_image_layout_is_read_only(layout, aspect))
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static struct stage_access
|
|
|
|
|
stage_access_for_layout(VkImageLayout layout, VkImageAspectFlags aspects)
|
|
|
|
|
{
|
|
|
|
|
VkPipelineStageFlagBits2 stages = 0;
|
|
|
|
|
VkAccessFlagBits2 access = 0;
|
|
|
|
|
|
|
|
|
|
if (vk_image_layout_supports_input_attachment(layout)) {
|
|
|
|
|
stages |= VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT;
|
|
|
|
|
access |= VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (aspects & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
|
|
|
|
|
stages |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
|
|
|
|
|
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
|
|
|
|
|
access |= VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
|
|
|
|
|
if (!vk_image_layout_are_all_aspects_read_only(layout, aspects)) {
|
|
|
|
|
access |= VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
|
|
|
|
|
|
|
|
|
/* It might be a resolve attachment */
|
2022-07-01 13:02:59 +01:00
|
|
|
|
stages |= VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT;
|
2022-02-09 22:30:38 +00:00
|
|
|
|
access |= VK_ACCESS_2_TRANSFER_WRITE_BIT;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
/* Color */
|
|
|
|
|
if (!vk_image_layout_are_all_aspects_read_only(layout, aspects)) {
|
|
|
|
|
/* There are no read-only color attachments */
|
|
|
|
|
stages |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
|
|
|
|
access |= VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT |
|
|
|
|
|
VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT;
|
|
|
|
|
|
|
|
|
|
/* It might be a resolve attachment */
|
2022-07-01 13:02:59 +01:00
|
|
|
|
stages |= VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT;
|
2022-02-09 22:30:38 +00:00
|
|
|
|
access |= VK_ACCESS_2_TRANSFER_WRITE_BIT;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (struct stage_access) {
|
|
|
|
|
.stages = stages,
|
|
|
|
|
.access = access,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
transition_image_range(const struct vk_image_view *image_view,
|
|
|
|
|
VkImageSubresourceRange range,
|
|
|
|
|
VkImageLayout old_layout,
|
|
|
|
|
VkImageLayout new_layout,
|
|
|
|
|
VkImageLayout old_stencil_layout,
|
|
|
|
|
VkImageLayout new_stencil_layout,
|
2022-05-07 00:14:26 +01:00
|
|
|
|
const VkSampleLocationsInfoEXT *sample_locations,
|
2022-02-09 22:30:38 +00:00
|
|
|
|
uint32_t *barrier_count,
|
|
|
|
|
uint32_t max_barrier_count,
|
|
|
|
|
VkImageMemoryBarrier2 *barriers)
|
|
|
|
|
{
|
|
|
|
|
VkImageAspectFlags aspects_left = range.aspectMask;
|
|
|
|
|
while (aspects_left) {
|
|
|
|
|
range.aspectMask = aspects_left;
|
|
|
|
|
|
|
|
|
|
/* If we have a depth/stencil image and one of the layouts doesn't match
|
|
|
|
|
* between depth and stencil, we need two barriers. Restrict to depth
|
|
|
|
|
* and we'll pick up stencil on the next iteration.
|
|
|
|
|
*/
|
|
|
|
|
if (range.aspectMask == (VK_IMAGE_ASPECT_DEPTH_BIT |
|
|
|
|
|
VK_IMAGE_ASPECT_STENCIL_BIT) &&
|
|
|
|
|
(old_layout != old_stencil_layout ||
|
|
|
|
|
new_layout != new_stencil_layout))
|
|
|
|
|
range.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
|
|
|
|
|
|
|
|
|
|
if (range.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT) {
|
|
|
|
|
/* We're down to a single aspect bit so this is going to be the last
|
|
|
|
|
* iteration and it's fine to stomp the input variables here.
|
|
|
|
|
*/
|
|
|
|
|
old_layout = old_stencil_layout;
|
|
|
|
|
new_layout = new_stencil_layout;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (new_layout != old_layout) {
|
|
|
|
|
/* We could go about carefully calculating every possible way the
|
|
|
|
|
* attachment may have been used in the render pass or we can break
|
|
|
|
|
* out the big hammer and throw in any stage and access flags
|
|
|
|
|
* possible for the given layouts.
|
|
|
|
|
*/
|
|
|
|
|
struct stage_access src_sa, dst_sa;
|
|
|
|
|
src_sa = stage_access_for_layout(old_layout, range.aspectMask);
|
|
|
|
|
dst_sa = stage_access_for_layout(new_layout, range.aspectMask);
|
|
|
|
|
|
|
|
|
|
assert(*barrier_count < max_barrier_count);
|
|
|
|
|
barriers[(*barrier_count)++] = (VkImageMemoryBarrier2) {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
|
2022-05-07 00:14:26 +01:00
|
|
|
|
.pNext = sample_locations,
|
2022-02-09 22:30:38 +00:00
|
|
|
|
.srcStageMask = src_sa.stages,
|
|
|
|
|
.srcAccessMask = src_sa.access,
|
|
|
|
|
.dstStageMask = dst_sa.stages,
|
|
|
|
|
.dstAccessMask = dst_sa.access,
|
|
|
|
|
.oldLayout = old_layout,
|
|
|
|
|
.newLayout = new_layout,
|
|
|
|
|
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
|
|
|
|
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
|
|
|
|
.image = vk_image_to_handle(image_view->image),
|
|
|
|
|
.subresourceRange = range,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
aspects_left &= ~range.aspectMask;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-17 18:58:39 +00:00
|
|
|
|
static bool
|
|
|
|
|
can_use_attachment_initial_layout(struct vk_command_buffer *cmd_buffer,
|
|
|
|
|
uint32_t att_idx,
|
|
|
|
|
uint32_t view_mask,
|
|
|
|
|
VkImageLayout *layout_out,
|
|
|
|
|
VkImageLayout *stencil_layout_out)
|
|
|
|
|
{
|
|
|
|
|
const struct vk_render_pass *pass = cmd_buffer->render_pass;
|
|
|
|
|
const struct vk_framebuffer *framebuffer = cmd_buffer->framebuffer;
|
|
|
|
|
const struct vk_render_pass_attachment *rp_att = &pass->attachments[att_idx];
|
|
|
|
|
struct vk_attachment_state *att_state = &cmd_buffer->attachments[att_idx];
|
|
|
|
|
const struct vk_image_view *image_view = att_state->image_view;
|
|
|
|
|
|
|
|
|
|
if ((rp_att->aspects & ~VK_IMAGE_ASPECT_STENCIL_BIT) &&
|
|
|
|
|
rp_att->load_op != VK_ATTACHMENT_LOAD_OP_CLEAR)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if ((rp_att->aspects & VK_IMAGE_ASPECT_STENCIL_BIT) &&
|
|
|
|
|
rp_att->stencil_load_op != VK_ATTACHMENT_LOAD_OP_CLEAR)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (cmd_buffer->render_area.offset.x != 0 ||
|
|
|
|
|
cmd_buffer->render_area.offset.y != 0 ||
|
|
|
|
|
cmd_buffer->render_area.extent.width != image_view->extent.width ||
|
|
|
|
|
cmd_buffer->render_area.extent.height != image_view->extent.height)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (image_view->image->image_type == VK_IMAGE_TYPE_3D) {
|
|
|
|
|
/* For 3D images, the view has to be the whole thing */
|
|
|
|
|
if (image_view->base_array_layer != 0)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (pass->is_multiview) {
|
|
|
|
|
if (!util_is_power_of_two_or_zero(view_mask + 1) ||
|
|
|
|
|
util_last_bit(view_mask) != image_view->layer_count)
|
|
|
|
|
return false;
|
|
|
|
|
} else {
|
|
|
|
|
if (framebuffer->layers != image_view->layer_count)
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Finally, check if the entire thing is undefined. It's ok to smash the
|
|
|
|
|
* view_mask now as the only thing using it will be the loop below.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/* 3D is stupidly special. See transition_attachment() */
|
|
|
|
|
if (image_view->image->image_type == VK_IMAGE_TYPE_3D)
|
|
|
|
|
view_mask = 1;
|
|
|
|
|
|
|
|
|
|
VkImageLayout layout = VK_IMAGE_LAYOUT_MAX_ENUM;
|
|
|
|
|
VkImageLayout stencil_layout = VK_IMAGE_LAYOUT_MAX_ENUM;
|
|
|
|
|
|
|
|
|
|
assert(view_mask != 0);
|
|
|
|
|
u_foreach_bit(view, view_mask) {
|
|
|
|
|
assert(view >= 0 && view < MESA_VK_MAX_MULTIVIEW_VIEW_COUNT);
|
|
|
|
|
struct vk_attachment_view_state *att_view_state = &att_state->views[view];
|
|
|
|
|
|
|
|
|
|
if (rp_att->aspects & ~VK_IMAGE_ASPECT_STENCIL_BIT) {
|
|
|
|
|
if (layout == VK_IMAGE_LAYOUT_MAX_ENUM)
|
|
|
|
|
layout = att_view_state->layout;
|
|
|
|
|
else if (layout != att_view_state->layout)
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (rp_att->aspects & VK_IMAGE_ASPECT_STENCIL_BIT) {
|
|
|
|
|
if (stencil_layout == VK_IMAGE_LAYOUT_MAX_ENUM)
|
|
|
|
|
stencil_layout = att_view_state->stencil_layout;
|
|
|
|
|
else if (stencil_layout != att_view_state->stencil_layout)
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (layout != VK_IMAGE_LAYOUT_MAX_ENUM)
|
|
|
|
|
*layout_out = layout;
|
|
|
|
|
else if (layout_out != NULL)
|
|
|
|
|
*layout_out = VK_IMAGE_LAYOUT_UNDEFINED;
|
|
|
|
|
|
|
|
|
|
if (stencil_layout != VK_IMAGE_LAYOUT_MAX_ENUM)
|
|
|
|
|
*stencil_layout_out = stencil_layout;
|
|
|
|
|
else if (stencil_layout_out != NULL)
|
|
|
|
|
*stencil_layout_out = VK_IMAGE_LAYOUT_UNDEFINED;
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
set_attachment_layout(struct vk_command_buffer *cmd_buffer,
|
|
|
|
|
uint32_t att_idx,
|
|
|
|
|
uint32_t view_mask,
|
|
|
|
|
VkImageLayout layout,
|
|
|
|
|
VkImageLayout stencil_layout)
|
|
|
|
|
{
|
|
|
|
|
struct vk_attachment_state *att_state = &cmd_buffer->attachments[att_idx];
|
|
|
|
|
|
|
|
|
|
u_foreach_bit(view, view_mask) {
|
|
|
|
|
assert(view >= 0 && view < MESA_VK_MAX_MULTIVIEW_VIEW_COUNT);
|
|
|
|
|
struct vk_attachment_view_state *att_view_state = &att_state->views[view];
|
|
|
|
|
|
|
|
|
|
att_view_state->layout = layout;
|
|
|
|
|
att_view_state->stencil_layout = stencil_layout;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-09 22:30:38 +00:00
|
|
|
|
static void
|
|
|
|
|
transition_attachment(struct vk_command_buffer *cmd_buffer,
|
|
|
|
|
uint32_t att_idx,
|
|
|
|
|
uint32_t view_mask,
|
|
|
|
|
VkImageLayout layout,
|
|
|
|
|
VkImageLayout stencil_layout,
|
|
|
|
|
uint32_t *barrier_count,
|
|
|
|
|
uint32_t max_barrier_count,
|
|
|
|
|
VkImageMemoryBarrier2 *barriers)
|
|
|
|
|
{
|
|
|
|
|
const struct vk_render_pass *pass = cmd_buffer->render_pass;
|
|
|
|
|
const struct vk_framebuffer *framebuffer = cmd_buffer->framebuffer;
|
|
|
|
|
const struct vk_render_pass_attachment *pass_att =
|
|
|
|
|
&pass->attachments[att_idx];
|
|
|
|
|
struct vk_attachment_state *att_state = &cmd_buffer->attachments[att_idx];
|
|
|
|
|
const struct vk_image_view *image_view = att_state->image_view;
|
|
|
|
|
|
|
|
|
|
/* 3D is stupidly special. From the Vulkan 1.3.204 spec:
|
|
|
|
|
*
|
|
|
|
|
* "When the VkImageSubresourceRange structure is used to select a
|
|
|
|
|
* subset of the slices of a 3D image’s mip level in order to create
|
|
|
|
|
* a 2D or 2D array image view of a 3D image created with
|
|
|
|
|
* VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT, baseArrayLayer and
|
|
|
|
|
* layerCount specify the first slice index and the number of slices
|
|
|
|
|
* to include in the created image view. Such an image view can be
|
|
|
|
|
* used as a framebuffer attachment that refers only to the specified
|
|
|
|
|
* range of slices of the selected mip level. However, any layout
|
|
|
|
|
* transitions performed on such an attachment view during a render
|
|
|
|
|
* pass instance still apply to the entire subresource referenced
|
|
|
|
|
* which includes all the slices of the selected mip level."
|
|
|
|
|
*
|
|
|
|
|
* To deal with this, we expand out the layer range to include the
|
|
|
|
|
* entire 3D image and treat them as having only a single view even when
|
|
|
|
|
* multiview is enabled. This later part means that we effectively only
|
|
|
|
|
* track one image layout for the entire attachment rather than one per
|
|
|
|
|
* view like we do for all the others.
|
|
|
|
|
*/
|
|
|
|
|
if (image_view->image->image_type == VK_IMAGE_TYPE_3D)
|
|
|
|
|
view_mask = 1;
|
|
|
|
|
|
|
|
|
|
u_foreach_bit(view, view_mask) {
|
|
|
|
|
assert(view >= 0 && view < MESA_VK_MAX_MULTIVIEW_VIEW_COUNT);
|
|
|
|
|
struct vk_attachment_view_state *att_view_state = &att_state->views[view];
|
|
|
|
|
|
|
|
|
|
/* First, check to see if we even need a transition */
|
|
|
|
|
if (att_view_state->layout == layout &&
|
|
|
|
|
att_view_state->stencil_layout == stencil_layout)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
VkImageSubresourceRange range = {
|
|
|
|
|
.aspectMask = pass_att->aspects,
|
|
|
|
|
.baseMipLevel = image_view->base_mip_level,
|
|
|
|
|
.levelCount = 1,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* From the Vulkan 1.3.207 spec:
|
|
|
|
|
*
|
|
|
|
|
* "Automatic layout transitions apply to the entire image
|
|
|
|
|
* subresource attached to the framebuffer. If multiview is not
|
|
|
|
|
* enabled and the attachment is a view of a 1D or 2D image, the
|
|
|
|
|
* automatic layout transitions apply to the number of layers
|
|
|
|
|
* specified by VkFramebufferCreateInfo::layers. If multiview is
|
|
|
|
|
* enabled and the attachment is a view of a 1D or 2D image, the
|
|
|
|
|
* automatic layout transitions apply to the layers corresponding to
|
|
|
|
|
* views which are used by some subpass in the render pass, even if
|
|
|
|
|
* that subpass does not reference the given attachment. If the
|
|
|
|
|
* attachment view is a 2D or 2D array view of a 3D image, even if
|
|
|
|
|
* the attachment view only refers to a subset of the slices of the
|
|
|
|
|
* selected mip level of the 3D image, automatic layout transitions
|
|
|
|
|
* apply to the entire subresource referenced which is the entire mip
|
|
|
|
|
* level in this case."
|
|
|
|
|
*/
|
|
|
|
|
if (image_view->image->image_type == VK_IMAGE_TYPE_3D) {
|
|
|
|
|
assert(view == 0);
|
|
|
|
|
range.baseArrayLayer = 0;
|
|
|
|
|
range.layerCount = image_view->extent.depth;
|
|
|
|
|
} else if (pass->is_multiview) {
|
|
|
|
|
range.baseArrayLayer = image_view->base_array_layer + view;
|
|
|
|
|
range.layerCount = 1;
|
|
|
|
|
} else {
|
|
|
|
|
assert(view == 0);
|
|
|
|
|
range.baseArrayLayer = image_view->base_array_layer;
|
|
|
|
|
range.layerCount = framebuffer->layers;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
transition_image_range(image_view, range,
|
|
|
|
|
att_view_state->layout, layout,
|
|
|
|
|
att_view_state->stencil_layout, stencil_layout,
|
2022-05-07 00:14:26 +01:00
|
|
|
|
att_view_state->sample_locations,
|
2022-02-09 22:30:38 +00:00
|
|
|
|
barrier_count, max_barrier_count, barriers);
|
|
|
|
|
|
|
|
|
|
att_view_state->layout = layout;
|
|
|
|
|
att_view_state->stencil_layout = stencil_layout;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
load_attachment(struct vk_command_buffer *cmd_buffer,
|
|
|
|
|
uint32_t att_idx, uint32_t view_mask,
|
|
|
|
|
VkImageLayout layout, VkImageLayout stencil_layout)
|
|
|
|
|
{
|
|
|
|
|
const struct vk_render_pass *pass = cmd_buffer->render_pass;
|
|
|
|
|
const struct vk_framebuffer *framebuffer = cmd_buffer->framebuffer;
|
|
|
|
|
const struct vk_render_pass_attachment *rp_att = &pass->attachments[att_idx];
|
|
|
|
|
struct vk_attachment_state *att_state = &cmd_buffer->attachments[att_idx];
|
|
|
|
|
struct vk_device_dispatch_table *disp =
|
|
|
|
|
&cmd_buffer->base.device->dispatch_table;
|
|
|
|
|
|
|
|
|
|
/* Don't load any views we've already loaded */
|
|
|
|
|
view_mask &= ~att_state->views_loaded;
|
|
|
|
|
if (view_mask == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/* From here on, if we return, we loaded the views */
|
|
|
|
|
att_state->views_loaded |= view_mask;
|
|
|
|
|
|
|
|
|
|
/* We only need to load/store if there's a clear */
|
|
|
|
|
bool need_load_store = false;
|
|
|
|
|
if ((rp_att->aspects & ~VK_IMAGE_ASPECT_STENCIL_BIT) &&
|
|
|
|
|
rp_att->load_op == VK_ATTACHMENT_LOAD_OP_CLEAR)
|
|
|
|
|
need_load_store = true;
|
|
|
|
|
|
|
|
|
|
if ((rp_att->aspects & VK_IMAGE_ASPECT_STENCIL_BIT) &&
|
|
|
|
|
rp_att->stencil_load_op == VK_ATTACHMENT_LOAD_OP_CLEAR)
|
|
|
|
|
need_load_store = true;
|
|
|
|
|
|
|
|
|
|
if (!need_load_store)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
const VkRenderingAttachmentInfo att = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
|
|
|
|
|
.imageView = vk_image_view_to_handle(att_state->image_view),
|
|
|
|
|
.imageLayout = layout,
|
|
|
|
|
.loadOp = rp_att->load_op,
|
|
|
|
|
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
|
|
|
|
|
.clearValue = att_state->clear_value,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const VkRenderingAttachmentInfo stencil_att = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
|
|
|
|
|
.imageView = vk_image_view_to_handle(att_state->image_view),
|
|
|
|
|
.imageLayout = stencil_layout,
|
|
|
|
|
.loadOp = rp_att->stencil_load_op,
|
|
|
|
|
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
|
|
|
|
|
.clearValue = att_state->clear_value,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
VkRenderingInfo render = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
|
|
|
|
|
.renderArea = cmd_buffer->render_area,
|
|
|
|
|
.layerCount = pass->is_multiview ? 1 : framebuffer->layers,
|
|
|
|
|
.viewMask = pass->is_multiview ? view_mask : 0,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (rp_att->aspects & (VK_IMAGE_ASPECT_DEPTH_BIT |
|
|
|
|
|
VK_IMAGE_ASPECT_STENCIL_BIT)) {
|
|
|
|
|
if (rp_att->aspects & VK_IMAGE_ASPECT_DEPTH_BIT)
|
|
|
|
|
render.pDepthAttachment = &att;
|
|
|
|
|
if (rp_att->aspects & VK_IMAGE_ASPECT_STENCIL_BIT)
|
|
|
|
|
render.pStencilAttachment = &stencil_att;
|
|
|
|
|
} else {
|
|
|
|
|
render.colorAttachmentCount = 1;
|
|
|
|
|
render.pColorAttachments = &att;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
disp->CmdBeginRendering(vk_command_buffer_to_handle(cmd_buffer), &render);
|
|
|
|
|
disp->CmdEndRendering(vk_command_buffer_to_handle(cmd_buffer));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
begin_subpass(struct vk_command_buffer *cmd_buffer,
|
|
|
|
|
const VkSubpassBeginInfo *begin_info)
|
|
|
|
|
{
|
|
|
|
|
const struct vk_render_pass *pass = cmd_buffer->render_pass;
|
|
|
|
|
const struct vk_framebuffer *framebuffer = cmd_buffer->framebuffer;
|
|
|
|
|
const uint32_t subpass_idx = cmd_buffer->subpass_idx;
|
|
|
|
|
assert(subpass_idx < pass->subpass_count);
|
|
|
|
|
const struct vk_subpass *subpass = &pass->subpasses[subpass_idx];
|
|
|
|
|
struct vk_device_dispatch_table *disp =
|
|
|
|
|
&cmd_buffer->base.device->dispatch_table;
|
|
|
|
|
|
|
|
|
|
/* First, we figure out all our attachments and attempt to handle image
|
|
|
|
|
* layout transitions and load ops as part of vkCmdBeginRendering if we
|
|
|
|
|
* can. For any we can't handle this way, we'll need explicit barriers
|
|
|
|
|
* or quick vkCmdBegin/EndRendering to do the load op.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
STACK_ARRAY(VkRenderingAttachmentInfo, color_attachments,
|
|
|
|
|
subpass->color_count);
|
2022-02-17 18:58:39 +00:00
|
|
|
|
STACK_ARRAY(VkRenderingAttachmentInitialLayoutInfoMESA,
|
|
|
|
|
color_attachment_initial_layouts,
|
|
|
|
|
subpass->color_count);
|
2022-02-09 22:30:38 +00:00
|
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < subpass->color_count; i++) {
|
|
|
|
|
const struct vk_subpass_attachment *sp_att =
|
|
|
|
|
&subpass->color_attachments[i];
|
|
|
|
|
VkRenderingAttachmentInfo *color_attachment = &color_attachments[i];
|
|
|
|
|
|
|
|
|
|
if (sp_att->attachment == VK_ATTACHMENT_UNUSED) {
|
|
|
|
|
*color_attachment = (VkRenderingAttachmentInfo) {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
|
|
|
|
|
.imageView = VK_NULL_HANDLE,
|
|
|
|
|
};
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert(sp_att->attachment < pass->attachment_count);
|
|
|
|
|
const struct vk_render_pass_attachment *rp_att =
|
|
|
|
|
&pass->attachments[sp_att->attachment];
|
|
|
|
|
struct vk_attachment_state *att_state =
|
|
|
|
|
&cmd_buffer->attachments[sp_att->attachment];
|
|
|
|
|
|
|
|
|
|
*color_attachment = (VkRenderingAttachmentInfo) {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
|
|
|
|
|
.imageView = vk_image_view_to_handle(att_state->image_view),
|
|
|
|
|
.imageLayout = sp_att->layout,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (!(subpass->view_mask & att_state->views_loaded)) {
|
|
|
|
|
/* None of these views have been used before */
|
|
|
|
|
color_attachment->loadOp = rp_att->load_op;
|
|
|
|
|
color_attachment->clearValue = att_state->clear_value;
|
|
|
|
|
att_state->views_loaded |= subpass->view_mask;
|
2022-02-17 18:58:39 +00:00
|
|
|
|
|
|
|
|
|
VkImageLayout initial_layout;
|
|
|
|
|
if (can_use_attachment_initial_layout(cmd_buffer,
|
|
|
|
|
sp_att->attachment,
|
|
|
|
|
subpass->view_mask,
|
|
|
|
|
&initial_layout, NULL) &&
|
|
|
|
|
sp_att->layout != initial_layout) {
|
|
|
|
|
assert(color_attachment->loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR);
|
|
|
|
|
|
|
|
|
|
VkRenderingAttachmentInitialLayoutInfoMESA *color_initial_layout =
|
|
|
|
|
&color_attachment_initial_layouts[i];
|
|
|
|
|
*color_initial_layout = (VkRenderingAttachmentInitialLayoutInfoMESA) {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INITIAL_LAYOUT_INFO_MESA,
|
|
|
|
|
.initialLayout = initial_layout,
|
|
|
|
|
};
|
|
|
|
|
__vk_append_struct(color_attachment, color_initial_layout);
|
|
|
|
|
|
|
|
|
|
set_attachment_layout(cmd_buffer, sp_att->attachment,
|
|
|
|
|
subpass->view_mask,
|
|
|
|
|
sp_att->layout, VK_IMAGE_LAYOUT_UNDEFINED);
|
|
|
|
|
}
|
2022-02-09 22:30:38 +00:00
|
|
|
|
} else {
|
|
|
|
|
/* We've seen at least one of the views of this attachment before so
|
|
|
|
|
* we need to LOAD_OP_LOAD.
|
|
|
|
|
*/
|
|
|
|
|
color_attachment->loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!(subpass->view_mask & ~sp_att->last_subpass)) {
|
|
|
|
|
/* This is the last subpass for every view */
|
|
|
|
|
color_attachment->storeOp = rp_att->store_op;
|
|
|
|
|
} else {
|
|
|
|
|
/* For at least one of our views, this isn't the last subpass
|
|
|
|
|
*
|
|
|
|
|
* In the edge case where we have lots of weird overlap between view
|
|
|
|
|
* masks of different subThis may mean that we get STORE_OP_STORE in
|
|
|
|
|
* some places where it may have wanted STORE_OP_NONE but that should
|
|
|
|
|
* be harmless.
|
|
|
|
|
*/
|
|
|
|
|
color_attachment->storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (sp_att->resolve != NULL) {
|
|
|
|
|
assert(sp_att->resolve->attachment < pass->attachment_count);
|
|
|
|
|
struct vk_attachment_state *res_att_state =
|
|
|
|
|
&cmd_buffer->attachments[sp_att->resolve->attachment];
|
|
|
|
|
|
|
|
|
|
/* Resolve attachments are entirely overwritten by the resolve
|
|
|
|
|
* operation so the load op really doesn't matter. We can consider
|
|
|
|
|
* the resolve as being the load.
|
|
|
|
|
*/
|
|
|
|
|
res_att_state->views_loaded |= subpass->view_mask;
|
|
|
|
|
|
|
|
|
|
if (vk_format_is_int(res_att_state->image_view->format))
|
|
|
|
|
color_attachment->resolveMode = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;
|
|
|
|
|
else
|
|
|
|
|
color_attachment->resolveMode = VK_RESOLVE_MODE_AVERAGE_BIT;
|
|
|
|
|
|
|
|
|
|
color_attachment->resolveImageView =
|
|
|
|
|
vk_image_view_to_handle(res_att_state->image_view);
|
|
|
|
|
color_attachment->resolveImageLayout = sp_att->resolve->layout;
|
2022-07-22 06:03:34 +01:00
|
|
|
|
} else if (subpass->mrtss.multisampledRenderToSingleSampledEnable &&
|
|
|
|
|
rp_att->samples == VK_SAMPLE_COUNT_1_BIT) {
|
|
|
|
|
if (vk_format_is_int(att_state->image_view->format))
|
|
|
|
|
color_attachment->resolveMode = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;
|
|
|
|
|
else
|
|
|
|
|
color_attachment->resolveMode = VK_RESOLVE_MODE_AVERAGE_BIT;
|
2022-02-09 22:30:38 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VkRenderingAttachmentInfo depth_attachment = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
|
|
|
|
|
};
|
|
|
|
|
VkRenderingAttachmentInfo stencil_attachment = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
|
|
|
|
|
};
|
2022-02-17 18:58:39 +00:00
|
|
|
|
VkRenderingAttachmentInitialLayoutInfoMESA depth_initial_layout = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INITIAL_LAYOUT_INFO_MESA,
|
|
|
|
|
};
|
|
|
|
|
VkRenderingAttachmentInitialLayoutInfoMESA stencil_initial_layout = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INITIAL_LAYOUT_INFO_MESA,
|
|
|
|
|
};
|
2022-02-09 22:30:38 +00:00
|
|
|
|
|
2022-05-07 00:14:26 +01:00
|
|
|
|
const VkSampleLocationsInfoEXT *sample_locations = NULL;
|
2022-02-09 22:30:38 +00:00
|
|
|
|
if (subpass->depth_stencil_attachment != NULL) {
|
|
|
|
|
const struct vk_subpass_attachment *sp_att =
|
|
|
|
|
subpass->depth_stencil_attachment;
|
|
|
|
|
|
|
|
|
|
assert(sp_att->attachment < pass->attachment_count);
|
|
|
|
|
const struct vk_render_pass_attachment *rp_att =
|
|
|
|
|
&pass->attachments[sp_att->attachment];
|
|
|
|
|
struct vk_attachment_state *att_state =
|
|
|
|
|
&cmd_buffer->attachments[sp_att->attachment];
|
|
|
|
|
|
|
|
|
|
assert(sp_att->aspects == rp_att->aspects);
|
|
|
|
|
if (rp_att->aspects & VK_IMAGE_ASPECT_DEPTH_BIT) {
|
|
|
|
|
depth_attachment.imageView =
|
|
|
|
|
vk_image_view_to_handle(att_state->image_view);
|
|
|
|
|
depth_attachment.imageLayout = sp_att->layout;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (rp_att->aspects & VK_IMAGE_ASPECT_STENCIL_BIT) {
|
|
|
|
|
stencil_attachment.imageView =
|
|
|
|
|
vk_image_view_to_handle(att_state->image_view);
|
|
|
|
|
stencil_attachment.imageLayout = sp_att->stencil_layout;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!(subpass->view_mask & att_state->views_loaded)) {
|
|
|
|
|
/* None of these views have been used before */
|
|
|
|
|
depth_attachment.loadOp = rp_att->load_op;
|
|
|
|
|
depth_attachment.clearValue = att_state->clear_value;
|
|
|
|
|
stencil_attachment.loadOp = rp_att->stencil_load_op;
|
|
|
|
|
stencil_attachment.clearValue = att_state->clear_value;
|
|
|
|
|
att_state->views_loaded |= subpass->view_mask;
|
2022-02-17 18:58:39 +00:00
|
|
|
|
|
|
|
|
|
VkImageLayout initial_layout, initial_stencil_layout;
|
|
|
|
|
if (can_use_attachment_initial_layout(cmd_buffer,
|
|
|
|
|
sp_att->attachment,
|
|
|
|
|
subpass->view_mask,
|
|
|
|
|
&initial_layout,
|
|
|
|
|
&initial_stencil_layout)) {
|
|
|
|
|
if ((rp_att->aspects & VK_IMAGE_ASPECT_DEPTH_BIT) &&
|
|
|
|
|
sp_att->layout != initial_layout) {
|
|
|
|
|
assert(depth_attachment.loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR);
|
|
|
|
|
depth_initial_layout.initialLayout = initial_layout;
|
|
|
|
|
__vk_append_struct(&depth_attachment,
|
|
|
|
|
&depth_initial_layout);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((rp_att->aspects & VK_IMAGE_ASPECT_STENCIL_BIT) &&
|
|
|
|
|
sp_att->stencil_layout != initial_stencil_layout) {
|
|
|
|
|
assert(stencil_attachment.loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR);
|
|
|
|
|
stencil_initial_layout.initialLayout = initial_stencil_layout;
|
|
|
|
|
__vk_append_struct(&stencil_attachment,
|
|
|
|
|
&stencil_initial_layout);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
set_attachment_layout(cmd_buffer, sp_att->attachment,
|
|
|
|
|
subpass->view_mask,
|
|
|
|
|
sp_att->layout, sp_att->stencil_layout);
|
|
|
|
|
}
|
2022-02-09 22:30:38 +00:00
|
|
|
|
} else {
|
|
|
|
|
/* We've seen at least one of the views of this attachment before so
|
|
|
|
|
* we need to LOAD_OP_LOAD.
|
|
|
|
|
*/
|
|
|
|
|
depth_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
|
|
|
|
stencil_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!(subpass->view_mask & ~sp_att->last_subpass)) {
|
|
|
|
|
/* This is the last subpass for every view */
|
|
|
|
|
depth_attachment.storeOp = rp_att->store_op;
|
|
|
|
|
stencil_attachment.storeOp = rp_att->stencil_store_op;
|
|
|
|
|
} else {
|
|
|
|
|
/* For at least one of our views, this isn't the last subpass
|
|
|
|
|
*
|
|
|
|
|
* In the edge case where we have lots of weird overlap between view
|
|
|
|
|
* masks of different subThis may mean that we get STORE_OP_STORE in
|
|
|
|
|
* some places where it may have wanted STORE_OP_NONE but that should
|
|
|
|
|
* be harmless.
|
|
|
|
|
*/
|
|
|
|
|
depth_attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
|
|
|
|
stencil_attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-07 00:14:26 +01:00
|
|
|
|
/* From the Vulkan 1.3.212 spec:
|
|
|
|
|
*
|
|
|
|
|
* "If the current render pass does not use the attachment as a
|
|
|
|
|
* depth/stencil attachment in any subpass that happens-before, the
|
|
|
|
|
* automatic layout transition uses the sample locations state
|
|
|
|
|
* specified in the sampleLocationsInfo member of the element of the
|
|
|
|
|
* VkRenderPassSampleLocationsBeginInfoEXT::pAttachmentInitialSampleLocations
|
|
|
|
|
* array for which the attachmentIndex member equals the attachment
|
|
|
|
|
* index of the attachment, if one is specified. Otherwise, the
|
|
|
|
|
* automatic layout transition uses the sample locations state
|
|
|
|
|
* specified in the sampleLocationsInfo member of the element of the
|
|
|
|
|
* VkRenderPassSampleLocationsBeginInfoEXT::pPostSubpassSampleLocations
|
|
|
|
|
* array for which the subpassIndex member equals the index of the
|
|
|
|
|
* subpass that last used the attachment as a depth/stencil
|
|
|
|
|
* attachment, if one is specified."
|
|
|
|
|
*
|
|
|
|
|
* Unfortunately, this says nothing whatsoever about multiview.
|
|
|
|
|
* However, since multiview render passes are described as a single-view
|
|
|
|
|
* render pass repeated per-view, we assume this is per-view.
|
|
|
|
|
*/
|
|
|
|
|
if (cmd_buffer->pass_sample_locations != NULL &&
|
|
|
|
|
(att_state->image_view->image->create_flags &
|
|
|
|
|
VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT)) {
|
|
|
|
|
sample_locations =
|
|
|
|
|
get_subpass_sample_locations(cmd_buffer->pass_sample_locations,
|
|
|
|
|
subpass_idx);
|
|
|
|
|
|
|
|
|
|
u_foreach_bit(view, subpass->view_mask)
|
|
|
|
|
att_state->views[view].sample_locations = sample_locations;
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-22 06:03:34 +01:00
|
|
|
|
if (sp_att->resolve != NULL ||
|
|
|
|
|
(subpass->mrtss.multisampledRenderToSingleSampledEnable &&
|
|
|
|
|
rp_att->samples == VK_SAMPLE_COUNT_1_BIT)) {
|
|
|
|
|
const struct vk_subpass_attachment *res_sp_att = sp_att->resolve ? sp_att->resolve : sp_att;
|
2022-02-09 22:30:38 +00:00
|
|
|
|
assert(res_sp_att->attachment < pass->attachment_count);
|
|
|
|
|
const struct vk_render_pass_attachment *res_rp_att =
|
|
|
|
|
&pass->attachments[res_sp_att->attachment];
|
|
|
|
|
struct vk_attachment_state *res_att_state =
|
|
|
|
|
&cmd_buffer->attachments[res_sp_att->attachment];
|
|
|
|
|
|
|
|
|
|
/* From the Vulkan 1.3.204 spec:
|
|
|
|
|
*
|
|
|
|
|
* "VkSubpassDescriptionDepthStencilResolve::depthResolveMode is
|
|
|
|
|
* ignored if the VkFormat of the pDepthStencilResolveAttachment
|
|
|
|
|
* does not have a depth component. Similarly,
|
|
|
|
|
* VkSubpassDescriptionDepthStencilResolve::stencilResolveMode is
|
|
|
|
|
* ignored if the VkFormat of the pDepthStencilResolveAttachment
|
|
|
|
|
* does not have a stencil component."
|
|
|
|
|
*
|
|
|
|
|
* TODO: Should we handle this here or when we create the render
|
|
|
|
|
* pass? Handling it here makes load ops "correct" in the sense
|
|
|
|
|
* that, if we resolve to the wrong aspect, we will still consider
|
|
|
|
|
* it bound and clear it if requested.
|
|
|
|
|
*/
|
2022-07-01 13:02:59 +01:00
|
|
|
|
VkResolveModeFlagBits depth_resolve_mode = VK_RESOLVE_MODE_NONE;
|
2022-02-09 22:30:38 +00:00
|
|
|
|
if (res_rp_att->aspects & VK_IMAGE_ASPECT_DEPTH_BIT)
|
|
|
|
|
depth_resolve_mode = subpass->depth_resolve_mode;
|
|
|
|
|
|
2022-07-01 13:02:59 +01:00
|
|
|
|
VkResolveModeFlagBits stencil_resolve_mode = VK_RESOLVE_MODE_NONE;
|
2022-02-09 22:30:38 +00:00
|
|
|
|
if (res_rp_att->aspects & VK_IMAGE_ASPECT_STENCIL_BIT)
|
|
|
|
|
stencil_resolve_mode = subpass->stencil_resolve_mode;
|
|
|
|
|
|
|
|
|
|
VkImageAspectFlags resolved_aspects = 0;
|
|
|
|
|
|
|
|
|
|
if (depth_resolve_mode != VK_RESOLVE_MODE_NONE) {
|
|
|
|
|
depth_attachment.resolveMode = depth_resolve_mode;
|
2022-07-22 06:03:34 +01:00
|
|
|
|
if (sp_att->resolve)
|
|
|
|
|
depth_attachment.resolveImageView =
|
|
|
|
|
vk_image_view_to_handle(res_att_state->image_view);
|
2022-02-09 22:30:38 +00:00
|
|
|
|
depth_attachment.resolveImageLayout =
|
|
|
|
|
sp_att->resolve->layout;
|
|
|
|
|
|
|
|
|
|
resolved_aspects |= VK_IMAGE_ASPECT_DEPTH_BIT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (stencil_resolve_mode != VK_RESOLVE_MODE_NONE) {
|
|
|
|
|
stencil_attachment.resolveMode = stencil_resolve_mode;
|
2022-07-22 06:03:34 +01:00
|
|
|
|
if (sp_att->resolve)
|
|
|
|
|
stencil_attachment.resolveImageView =
|
|
|
|
|
vk_image_view_to_handle(res_att_state->image_view);
|
2022-02-09 22:30:38 +00:00
|
|
|
|
stencil_attachment.resolveImageLayout =
|
|
|
|
|
sp_att->resolve->stencil_layout;
|
|
|
|
|
|
|
|
|
|
resolved_aspects |= VK_IMAGE_ASPECT_STENCIL_BIT;
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-22 06:03:34 +01:00
|
|
|
|
if (sp_att->resolve && resolved_aspects == rp_att->aspects) {
|
2022-02-09 22:30:38 +00:00
|
|
|
|
/* The resolve attachment is entirely overwritten by the
|
|
|
|
|
* resolve operation so the load op really doesn't matter.
|
|
|
|
|
* We can consider the resolve as being the load.
|
|
|
|
|
*/
|
|
|
|
|
res_att_state->views_loaded |= subpass->view_mask;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Next, handle any barriers we need. This may include a general
|
|
|
|
|
* VkMemoryBarrier for subpass dependencies and it may include some
|
|
|
|
|
* number of VkImageMemoryBarriers for layout transitions.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
bool needs_mem_barrier = false;
|
|
|
|
|
VkMemoryBarrier2 mem_barrier = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
|
|
|
|
|
};
|
|
|
|
|
for (uint32_t d = 0; d < pass->dependency_count; d++) {
|
|
|
|
|
const struct vk_subpass_dependency *dep = &pass->dependencies[d];
|
|
|
|
|
if (dep->dst_subpass != subpass_idx)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (dep->flags & VK_DEPENDENCY_VIEW_LOCAL_BIT) {
|
|
|
|
|
/* From the Vulkan 1.3.204 spec:
|
|
|
|
|
*
|
|
|
|
|
* VUID-VkSubpassDependency2-dependencyFlags-03091
|
|
|
|
|
*
|
|
|
|
|
* "If dependencyFlags includes VK_DEPENDENCY_VIEW_LOCAL_BIT,
|
|
|
|
|
* dstSubpass must not be equal to VK_SUBPASS_EXTERNAL"
|
|
|
|
|
*/
|
|
|
|
|
assert(dep->src_subpass != VK_SUBPASS_EXTERNAL);
|
|
|
|
|
|
|
|
|
|
assert(dep->src_subpass < pass->subpass_count);
|
|
|
|
|
const struct vk_subpass *src_subpass =
|
|
|
|
|
&pass->subpasses[dep->src_subpass];
|
|
|
|
|
|
|
|
|
|
/* Figure out the set of views in the source subpass affected by this
|
|
|
|
|
* dependency.
|
|
|
|
|
*/
|
|
|
|
|
uint32_t src_dep_view_mask = subpass->view_mask;
|
|
|
|
|
if (dep->view_offset >= 0)
|
|
|
|
|
src_dep_view_mask <<= dep->view_offset;
|
|
|
|
|
else
|
|
|
|
|
src_dep_view_mask >>= -dep->view_offset;
|
|
|
|
|
|
|
|
|
|
/* From the Vulkan 1.3.204 spec:
|
|
|
|
|
*
|
|
|
|
|
* "If the dependency is view-local, then each view (dstView) in
|
|
|
|
|
* the destination subpass depends on the view dstView +
|
|
|
|
|
* pViewOffsets[dependency] in the source subpass. If there is not
|
|
|
|
|
* such a view in the source subpass, then this dependency does
|
|
|
|
|
* not affect that view in the destination subpass."
|
|
|
|
|
*/
|
|
|
|
|
if (!(src_subpass->view_mask & src_dep_view_mask))
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
needs_mem_barrier = true;
|
|
|
|
|
mem_barrier.srcStageMask |= dep->src_stage_mask;
|
|
|
|
|
mem_barrier.srcAccessMask |= dep->src_access_mask;
|
|
|
|
|
mem_barrier.dstStageMask |= dep->dst_stage_mask;
|
|
|
|
|
mem_barrier.dstAccessMask |= dep->dst_access_mask;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t max_image_barrier_count = 0;
|
|
|
|
|
for (uint32_t a = 0; a < subpass->attachment_count; a++) {
|
|
|
|
|
const struct vk_subpass_attachment *sp_att = &subpass->attachments[a];
|
|
|
|
|
if (sp_att->attachment == VK_ATTACHMENT_UNUSED)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
assert(sp_att->attachment < pass->attachment_count);
|
|
|
|
|
const struct vk_render_pass_attachment *rp_att =
|
|
|
|
|
&pass->attachments[sp_att->attachment];
|
|
|
|
|
|
|
|
|
|
max_image_barrier_count += util_bitcount(subpass->view_mask) *
|
|
|
|
|
util_bitcount(rp_att->aspects);
|
|
|
|
|
}
|
|
|
|
|
STACK_ARRAY(VkImageMemoryBarrier2, image_barriers, max_image_barrier_count);
|
|
|
|
|
uint32_t image_barrier_count = 0;
|
|
|
|
|
|
|
|
|
|
for (uint32_t a = 0; a < subpass->attachment_count; a++) {
|
|
|
|
|
const struct vk_subpass_attachment *sp_att = &subpass->attachments[a];
|
|
|
|
|
if (sp_att->attachment == VK_ATTACHMENT_UNUSED)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
/* If we're using an initial layout, the attachment will already be
|
|
|
|
|
* marked as transitioned and this will be a no-op.
|
|
|
|
|
*/
|
|
|
|
|
transition_attachment(cmd_buffer, sp_att->attachment,
|
|
|
|
|
subpass->view_mask,
|
|
|
|
|
sp_att->layout, sp_att->stencil_layout,
|
|
|
|
|
&image_barrier_count,
|
|
|
|
|
max_image_barrier_count,
|
|
|
|
|
image_barriers);
|
|
|
|
|
}
|
|
|
|
|
assert(image_barrier_count <= max_image_barrier_count);
|
|
|
|
|
|
|
|
|
|
if (needs_mem_barrier || image_barrier_count > 0) {
|
|
|
|
|
const VkDependencyInfo dependency_info = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
|
|
|
|
|
.dependencyFlags = 0,
|
|
|
|
|
.memoryBarrierCount = needs_mem_barrier ? 1 : 0,
|
|
|
|
|
.pMemoryBarriers = needs_mem_barrier ? &mem_barrier : NULL,
|
|
|
|
|
.imageMemoryBarrierCount = image_barrier_count,
|
|
|
|
|
.pImageMemoryBarriers = image_barrier_count > 0 ?
|
|
|
|
|
image_barriers : NULL,
|
|
|
|
|
};
|
|
|
|
|
disp->CmdPipelineBarrier2(vk_command_buffer_to_handle(cmd_buffer),
|
|
|
|
|
&dependency_info);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
STACK_ARRAY_FINISH(image_barriers);
|
|
|
|
|
|
|
|
|
|
/* Next, handle any VK_ATTACHMENT_LOAD_OP_CLEAR that we couldn't handle
|
|
|
|
|
* directly by emitting a quick vkCmdBegin/EndRendering to do the load.
|
|
|
|
|
*/
|
|
|
|
|
for (uint32_t a = 0; a < subpass->attachment_count; a++) {
|
|
|
|
|
const struct vk_subpass_attachment *sp_att = &subpass->attachments[a];
|
|
|
|
|
if (sp_att->attachment == VK_ATTACHMENT_UNUSED)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
load_attachment(cmd_buffer, sp_att->attachment, subpass->view_mask,
|
|
|
|
|
sp_att->layout, sp_att->stencil_layout);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* TODO: Handle preserve attachments
|
|
|
|
|
*
|
|
|
|
|
* For immediate renderers, this isn't a big deal as LOAD_OP_LOAD and
|
|
|
|
|
* STORE_OP_STORE are effectively free. However, before this gets used on
|
|
|
|
|
* a tiling GPU, we should really hook up preserve attachments and use them
|
|
|
|
|
* to determine when we can use LOAD/STORE_OP_DONT_CARE between subpasses.
|
|
|
|
|
*/
|
|
|
|
|
|
2022-02-10 15:43:27 +00:00
|
|
|
|
VkRenderingInfo rendering = {
|
2022-02-09 22:30:38 +00:00
|
|
|
|
.sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
|
|
|
|
|
.renderArea = cmd_buffer->render_area,
|
|
|
|
|
.layerCount = pass->is_multiview ? 1 : framebuffer->layers,
|
|
|
|
|
.viewMask = pass->is_multiview ? subpass->view_mask : 0,
|
|
|
|
|
.colorAttachmentCount = subpass->color_count,
|
|
|
|
|
.pColorAttachments = color_attachments,
|
|
|
|
|
.pDepthAttachment = &depth_attachment,
|
|
|
|
|
.pStencilAttachment = &stencil_attachment,
|
|
|
|
|
};
|
2022-02-10 15:43:27 +00:00
|
|
|
|
|
|
|
|
|
VkRenderingFragmentShadingRateAttachmentInfoKHR fsr_attachment;
|
|
|
|
|
if (subpass->fragment_shading_rate_attachment) {
|
|
|
|
|
const struct vk_subpass_attachment *sp_att =
|
|
|
|
|
subpass->fragment_shading_rate_attachment;
|
|
|
|
|
|
|
|
|
|
assert(sp_att->attachment < pass->attachment_count);
|
|
|
|
|
struct vk_attachment_state *att_state =
|
|
|
|
|
&cmd_buffer->attachments[sp_att->attachment];
|
|
|
|
|
|
|
|
|
|
/* Fragment shading rate attachments have no loadOp (it's implicitly
|
|
|
|
|
* LOAD_OP_LOAD) so we need to ensure the load op happens.
|
|
|
|
|
*/
|
|
|
|
|
load_attachment(cmd_buffer, sp_att->attachment, subpass->view_mask,
|
|
|
|
|
sp_att->layout, sp_att->stencil_layout);
|
|
|
|
|
|
|
|
|
|
fsr_attachment = (VkRenderingFragmentShadingRateAttachmentInfoKHR) {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR,
|
|
|
|
|
.imageView = vk_image_view_to_handle(att_state->image_view),
|
|
|
|
|
.imageLayout = sp_att->layout,
|
|
|
|
|
.shadingRateAttachmentTexelSize =
|
|
|
|
|
subpass->fragment_shading_rate_attachment_texel_size,
|
|
|
|
|
};
|
|
|
|
|
__vk_append_struct(&rendering, &fsr_attachment);
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-07 00:14:26 +01:00
|
|
|
|
VkSampleLocationsInfoEXT sample_locations_tmp;
|
|
|
|
|
if (sample_locations) {
|
|
|
|
|
sample_locations_tmp = *sample_locations;
|
|
|
|
|
__vk_append_struct(&rendering, &sample_locations_tmp);
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-26 01:52:22 +01:00
|
|
|
|
/* Append this one last because it lives in the subpass and we don't want
|
|
|
|
|
* to be changed by appending other structures later.
|
|
|
|
|
*/
|
|
|
|
|
__vk_append_struct(&rendering, (void *)&subpass->self_dep_info);
|
|
|
|
|
|
2022-02-09 22:30:38 +00:00
|
|
|
|
disp->CmdBeginRendering(vk_command_buffer_to_handle(cmd_buffer),
|
|
|
|
|
&rendering);
|
|
|
|
|
|
|
|
|
|
STACK_ARRAY_FINISH(color_attachments);
|
2022-02-17 18:58:39 +00:00
|
|
|
|
STACK_ARRAY_FINISH(color_attachment_initial_layouts);
|
2022-02-09 22:30:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
end_subpass(struct vk_command_buffer *cmd_buffer,
|
|
|
|
|
const VkSubpassEndInfo *end_info)
|
|
|
|
|
{
|
|
|
|
|
struct vk_device_dispatch_table *disp =
|
|
|
|
|
&cmd_buffer->base.device->dispatch_table;
|
|
|
|
|
disp->CmdEndRendering(vk_command_buffer_to_handle(cmd_buffer));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VKAPI_ATTR void VKAPI_CALL
|
|
|
|
|
vk_common_CmdBeginRenderPass2(VkCommandBuffer commandBuffer,
|
|
|
|
|
const VkRenderPassBeginInfo *pRenderPassBeginInfo,
|
|
|
|
|
const VkSubpassBeginInfo *pSubpassBeginInfo)
|
|
|
|
|
{
|
|
|
|
|
VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, commandBuffer);
|
|
|
|
|
VK_FROM_HANDLE(vk_render_pass, pass, pRenderPassBeginInfo->renderPass);
|
|
|
|
|
VK_FROM_HANDLE(vk_framebuffer, framebuffer,
|
|
|
|
|
pRenderPassBeginInfo->framebuffer);
|
|
|
|
|
|
|
|
|
|
assert(cmd_buffer->render_pass == NULL);
|
|
|
|
|
cmd_buffer->render_pass = pass;
|
|
|
|
|
cmd_buffer->subpass_idx = 0;
|
|
|
|
|
|
|
|
|
|
assert(cmd_buffer->framebuffer == NULL);
|
|
|
|
|
cmd_buffer->framebuffer = framebuffer;
|
|
|
|
|
|
|
|
|
|
cmd_buffer->render_area = pRenderPassBeginInfo->renderArea;
|
|
|
|
|
|
|
|
|
|
assert(cmd_buffer->attachments == NULL);
|
|
|
|
|
if (pass->attachment_count > ARRAY_SIZE(cmd_buffer->_attachments)) {
|
|
|
|
|
cmd_buffer->attachments = malloc(pass->attachment_count *
|
|
|
|
|
sizeof(*cmd_buffer->attachments));
|
|
|
|
|
} else {
|
|
|
|
|
cmd_buffer->attachments = cmd_buffer->_attachments;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const VkRenderPassAttachmentBeginInfo *attach_begin =
|
|
|
|
|
vk_find_struct_const(pRenderPassBeginInfo,
|
|
|
|
|
RENDER_PASS_ATTACHMENT_BEGIN_INFO);
|
|
|
|
|
if (!attach_begin)
|
|
|
|
|
assert(pass->attachment_count == framebuffer->attachment_count);
|
|
|
|
|
|
|
|
|
|
const VkImageView *image_views;
|
|
|
|
|
if (attach_begin && attach_begin->attachmentCount != 0) {
|
|
|
|
|
assert(attach_begin->attachmentCount == pass->attachment_count);
|
|
|
|
|
image_views = attach_begin->pAttachments;
|
|
|
|
|
} else {
|
|
|
|
|
assert(framebuffer->attachment_count >= pass->attachment_count);
|
|
|
|
|
image_views = framebuffer->attachments;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (uint32_t a = 0; a < pass->attachment_count; ++a) {
|
|
|
|
|
VK_FROM_HANDLE(vk_image_view, image_view, image_views[a]);
|
|
|
|
|
const struct vk_render_pass_attachment *pass_att = &pass->attachments[a];
|
|
|
|
|
struct vk_attachment_state *att_state = &cmd_buffer->attachments[a];
|
|
|
|
|
|
|
|
|
|
/* From the Vulkan 1.3.204 spec:
|
2022-03-30 17:49:41 +01:00
|
|
|
|
*
|
|
|
|
|
* VUID-VkFramebufferCreateInfo-pAttachments-00880
|
|
|
|
|
*
|
|
|
|
|
* "If renderpass is not VK_NULL_HANDLE and flags does not include
|
|
|
|
|
* VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT, each element of pAttachments
|
|
|
|
|
* must have been created with a VkFormat value that matches the
|
|
|
|
|
* VkFormat specified by the corresponding VkAttachmentDescription in
|
|
|
|
|
* renderPass"
|
|
|
|
|
*
|
|
|
|
|
* and
|
2022-02-09 22:30:38 +00:00
|
|
|
|
*
|
|
|
|
|
* VUID-VkRenderPassBeginInfo-framebuffer-03216
|
|
|
|
|
*
|
|
|
|
|
* "If framebuffer was created with a VkFramebufferCreateInfo::flags
|
|
|
|
|
* value that included VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT, each
|
|
|
|
|
* element of the pAttachments member of a
|
|
|
|
|
* VkRenderPassAttachmentBeginInfo structure included in the pNext
|
|
|
|
|
* chain must be a VkImageView of an image created with a value of
|
|
|
|
|
* VkImageViewCreateInfo::format equal to the corresponding value of
|
|
|
|
|
* VkAttachmentDescription::format in renderPass"
|
|
|
|
|
*/
|
|
|
|
|
assert(image_view->format == pass_att->format);
|
|
|
|
|
|
|
|
|
|
/* From the Vulkan 1.3.204 spec:
|
2022-03-30 17:49:41 +01:00
|
|
|
|
*
|
|
|
|
|
* VUID-VkFramebufferCreateInfo-pAttachments-00881
|
|
|
|
|
*
|
|
|
|
|
* "If renderpass is not VK_NULL_HANDLE and flags does not include
|
|
|
|
|
* VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT, each element of pAttachments
|
|
|
|
|
* must have been created with a samples value that matches the
|
|
|
|
|
* samples value specified by the corresponding
|
|
|
|
|
* VkAttachmentDescription in renderPass"
|
|
|
|
|
*
|
|
|
|
|
* and
|
2022-02-09 22:30:38 +00:00
|
|
|
|
*
|
|
|
|
|
* UID-VkRenderPassBeginInfo-framebuffer-03217
|
|
|
|
|
*
|
|
|
|
|
* "If framebuffer was created with a VkFramebufferCreateInfo::flags
|
|
|
|
|
* value that included VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT, each
|
|
|
|
|
* element of the pAttachments member of a
|
|
|
|
|
* VkRenderPassAttachmentBeginInfo structure included in the pNext
|
|
|
|
|
* chain must be a VkImageView of an image created with a value of
|
|
|
|
|
* VkImageCreateInfo::samples equal to the corresponding value of
|
|
|
|
|
* VkAttachmentDescription::samples in renderPass"
|
|
|
|
|
*/
|
|
|
|
|
assert(image_view->image->samples == pass_att->samples);
|
|
|
|
|
|
2022-02-10 15:43:27 +00:00
|
|
|
|
/* From the Vulkan 1.3.204 spec:
|
|
|
|
|
*
|
|
|
|
|
* If multiview is enabled and the shading rate attachment has
|
|
|
|
|
* multiple layers, the shading rate attachment texel is selected
|
|
|
|
|
* from the layer determined by the ViewIndex built-in. If multiview
|
|
|
|
|
* is disabled, and both the shading rate attachment and the
|
|
|
|
|
* framebuffer have multiple layers, the shading rate attachment
|
|
|
|
|
* texel is selected from the layer determined by the Layer built-in.
|
|
|
|
|
* Otherwise, the texel is unconditionally selected from the first
|
|
|
|
|
* layer of the attachment.
|
|
|
|
|
*/
|
|
|
|
|
if (!(image_view->usage & VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR))
|
|
|
|
|
assert(util_last_bit(pass_att->view_mask) <= image_view->layer_count);
|
2022-02-09 22:30:38 +00:00
|
|
|
|
|
|
|
|
|
*att_state = (struct vk_attachment_state) {
|
|
|
|
|
.image_view = image_view,
|
|
|
|
|
.views_loaded = 0,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
for (uint32_t v = 0; v < MESA_VK_MAX_MULTIVIEW_VIEW_COUNT; v++) {
|
|
|
|
|
att_state->views[v] = (struct vk_attachment_view_state) {
|
|
|
|
|
.layout = pass_att->initial_layout,
|
|
|
|
|
.stencil_layout = pass_att->initial_stencil_layout,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (a < pRenderPassBeginInfo->clearValueCount)
|
|
|
|
|
att_state->clear_value = pRenderPassBeginInfo->pClearValues[a];
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-07 00:14:26 +01:00
|
|
|
|
const VkRenderPassSampleLocationsBeginInfoEXT *rp_sl_info =
|
|
|
|
|
vk_find_struct_const(pRenderPassBeginInfo->pNext,
|
|
|
|
|
RENDER_PASS_SAMPLE_LOCATIONS_BEGIN_INFO_EXT);
|
|
|
|
|
if (rp_sl_info) {
|
|
|
|
|
cmd_buffer->pass_sample_locations = clone_rp_sample_locations(rp_sl_info);
|
|
|
|
|
assert(cmd_buffer->pass_sample_locations);
|
|
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < rp_sl_info->attachmentInitialSampleLocationsCount; i++) {
|
|
|
|
|
const VkAttachmentSampleLocationsEXT *att_sl =
|
|
|
|
|
&rp_sl_info->pAttachmentInitialSampleLocations[i];
|
|
|
|
|
|
|
|
|
|
assert(att_sl->attachmentIndex < pass->attachment_count);
|
|
|
|
|
struct vk_attachment_state *att_state =
|
|
|
|
|
&cmd_buffer->attachments[att_sl->attachmentIndex];
|
|
|
|
|
|
|
|
|
|
/* Sample locations only matter for depth/stencil images created with
|
|
|
|
|
* VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT
|
|
|
|
|
*/
|
|
|
|
|
if (vk_format_is_depth_or_stencil(att_state->image_view->format) &&
|
|
|
|
|
(att_state->image_view->image->create_flags &
|
|
|
|
|
VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT)) {
|
|
|
|
|
for (uint32_t v = 0; v < MESA_VK_MAX_MULTIVIEW_VIEW_COUNT; v++)
|
|
|
|
|
att_state->views[v].sample_locations = &att_sl->sampleLocationsInfo;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-09 22:30:38 +00:00
|
|
|
|
begin_subpass(cmd_buffer, pSubpassBeginInfo);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
vk_command_buffer_reset_render_pass(struct vk_command_buffer *cmd_buffer)
|
|
|
|
|
{
|
|
|
|
|
cmd_buffer->render_pass = NULL;
|
|
|
|
|
cmd_buffer->subpass_idx = 0;
|
|
|
|
|
cmd_buffer->framebuffer = NULL;
|
|
|
|
|
if (cmd_buffer->attachments != cmd_buffer->_attachments)
|
|
|
|
|
free(cmd_buffer->attachments);
|
|
|
|
|
cmd_buffer->attachments = NULL;
|
2022-05-07 00:14:26 +01:00
|
|
|
|
if (cmd_buffer->pass_sample_locations != NULL)
|
|
|
|
|
vk_free(vk_default_allocator(), cmd_buffer->pass_sample_locations);
|
|
|
|
|
cmd_buffer->pass_sample_locations = NULL;
|
2022-02-09 22:30:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VKAPI_ATTR void VKAPI_CALL
|
|
|
|
|
vk_common_CmdNextSubpass2(VkCommandBuffer commandBuffer,
|
|
|
|
|
const VkSubpassBeginInfo *pSubpassBeginInfo,
|
|
|
|
|
const VkSubpassEndInfo *pSubpassEndInfo)
|
|
|
|
|
{
|
|
|
|
|
VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, commandBuffer);
|
|
|
|
|
|
|
|
|
|
end_subpass(cmd_buffer, pSubpassEndInfo);
|
|
|
|
|
cmd_buffer->subpass_idx++;
|
|
|
|
|
begin_subpass(cmd_buffer, pSubpassBeginInfo);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VKAPI_ATTR void VKAPI_CALL
|
|
|
|
|
vk_common_CmdEndRenderPass2(VkCommandBuffer commandBuffer,
|
|
|
|
|
const VkSubpassEndInfo *pSubpassEndInfo)
|
|
|
|
|
{
|
|
|
|
|
VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, commandBuffer);
|
|
|
|
|
const struct vk_render_pass *pass = cmd_buffer->render_pass;
|
|
|
|
|
struct vk_device_dispatch_table *disp =
|
|
|
|
|
&cmd_buffer->base.device->dispatch_table;
|
|
|
|
|
|
|
|
|
|
end_subpass(cmd_buffer, pSubpassEndInfo);
|
|
|
|
|
|
|
|
|
|
/* Make sure all our attachments end up in their finalLayout */
|
|
|
|
|
|
|
|
|
|
uint32_t max_image_barrier_count = 0;
|
|
|
|
|
for (uint32_t a = 0; a < pass->attachment_count; a++) {
|
|
|
|
|
const struct vk_render_pass_attachment *rp_att = &pass->attachments[a];
|
|
|
|
|
|
|
|
|
|
max_image_barrier_count += util_bitcount(pass->view_mask) *
|
|
|
|
|
util_bitcount(rp_att->aspects);
|
|
|
|
|
}
|
|
|
|
|
STACK_ARRAY(VkImageMemoryBarrier2, image_barriers, max_image_barrier_count);
|
|
|
|
|
uint32_t image_barrier_count = 0;
|
|
|
|
|
|
|
|
|
|
for (uint32_t a = 0; a < pass->attachment_count; a++) {
|
|
|
|
|
const struct vk_render_pass_attachment *rp_att = &pass->attachments[a];
|
|
|
|
|
|
|
|
|
|
transition_attachment(cmd_buffer, a, pass->view_mask,
|
|
|
|
|
rp_att->final_layout,
|
|
|
|
|
rp_att->final_stencil_layout,
|
|
|
|
|
&image_barrier_count,
|
|
|
|
|
max_image_barrier_count,
|
|
|
|
|
image_barriers);
|
|
|
|
|
}
|
|
|
|
|
assert(image_barrier_count <= max_image_barrier_count);
|
|
|
|
|
|
|
|
|
|
if (image_barrier_count > 0) {
|
|
|
|
|
const VkDependencyInfo dependency_info = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
|
|
|
|
|
.dependencyFlags = 0,
|
|
|
|
|
.imageMemoryBarrierCount = image_barrier_count,
|
|
|
|
|
.pImageMemoryBarriers = image_barriers,
|
|
|
|
|
};
|
|
|
|
|
disp->CmdPipelineBarrier2(vk_command_buffer_to_handle(cmd_buffer),
|
|
|
|
|
&dependency_info);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
STACK_ARRAY_FINISH(image_barriers);
|
|
|
|
|
|
|
|
|
|
vk_command_buffer_reset_render_pass(cmd_buffer);
|
|
|
|
|
}
|