* Copyright © Microsoft Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "dzn_private.h"
#include "vk_alloc.h"
#include "vk_format.h"
VKAPI_ATTR VkResult VKAPI_CALL
dzn_CreateRenderPass2(VkDevice dev,
const VkRenderPassCreateInfo2KHR *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkRenderPass *pRenderPass)
{
VK_FROM_HANDLE(dzn_device, device, dev);
VK_MULTIALLOC(ma);
VK_MULTIALLOC_DECL(&ma, dzn_render_pass, pass, 1);
VK_MULTIALLOC_DECL(&ma, dzn_subpass, subpasses,
pCreateInfo->subpassCount);
VK_MULTIALLOC_DECL(&ma, dzn_attachment, attachments,
pCreateInfo->attachmentCount);
if (!vk_multialloc_zalloc2(&ma, &device->vk.alloc, pAllocator,
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT))
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
vk_object_base_init(&device->vk, &pass->base, VK_OBJECT_TYPE_RENDER_PASS);
pass->subpasses = subpasses;
pass->subpass_count = pCreateInfo->subpassCount;
pass->attachments = attachments;
pass->attachment_count = pCreateInfo->attachmentCount;
assert(!pass->attachment_count || pass->attachments);
for (uint32_t i = 0; i < pass->attachment_count; i++) {
const VkAttachmentDescription2 *attachment = &pCreateInfo->pAttachments[i];
attachments[i].idx = i;
attachments[i].format = attachment->format;
assert(attachments[i].format);
if (vk_format_is_depth_or_stencil(attachment->format)) {
attachments[i].clear.depth =
attachment->loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR;
attachments[i].clear.stencil =
attachment->stencilLoadOp == VK_ATTACHMENT_LOAD_OP_CLEAR;
} else {
attachments[i].clear.color =
attachment->loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR;
}
attachments[i].samples = attachment->samples;
if (vk_format_has_stencil(attachment->format)) {
attachments[i].stencil.before =
dzn_image_layout_to_state(attachment->initialLayout, VK_IMAGE_ASPECT_STENCIL_BIT);
attachments[i].stencil.after =
dzn_image_layout_to_state(attachment->finalLayout, VK_IMAGE_ASPECT_STENCIL_BIT);
attachments[i].stencil.last = attachments[i].stencil.before;
}
if (vk_format_has_depth(attachment->format)) {
attachments[i].before =
dzn_image_layout_to_state(attachment->initialLayout, VK_IMAGE_ASPECT_STENCIL_BIT);
attachments[i].after =
dzn_image_layout_to_state(attachment->finalLayout, VK_IMAGE_ASPECT_STENCIL_BIT);
attachments[i].last = attachments[i].before;
} else {
assert(vk_format_is_color(attachment->format));
attachments[i].before =
dzn_image_layout_to_state(attachment->initialLayout, VK_IMAGE_ASPECT_COLOR_BIT);
attachments[i].after =
dzn_image_layout_to_state(attachment->finalLayout, VK_IMAGE_ASPECT_COLOR_BIT);
attachments[i].last = attachments[i].before;
}
}
assert(subpasses);
for (uint32_t i = 0; i < pass->subpass_count; i++) {
const VkSubpassDescription2 *subpass = &pCreateInfo->pSubpasses[i];
const VkSubpassDescription2 *subpass_after = NULL;
if (i + 1 < pass->subpass_count)
subpass_after = &pCreateInfo->pSubpasses[i + 1];
for (uint32_t j = 0; j < subpass->colorAttachmentCount; j++) {
uint32_t idx = subpass->pColorAttachments[j].attachment;
subpasses[i].colors[j].idx = idx;
if (idx != VK_ATTACHMENT_UNUSED) {
subpasses[i].colors[j].aspects = VK_IMAGE_ASPECT_COLOR_BIT;
subpasses[i].colors[j].before = attachments[idx].last;
subpasses[i].colors[j].during =
dzn_image_layout_to_state(subpass->pColorAttachments[j].layout,
VK_IMAGE_ASPECT_COLOR_BIT);
attachments[idx].last = subpasses[i].colors[j].during;
attachments[idx].aspects |= VK_IMAGE_ASPECT_COLOR_BIT;
subpasses[i].color_count = j + 1;
}
idx = subpass->pResolveAttachments ?
subpass->pResolveAttachments[j].attachment :
VK_ATTACHMENT_UNUSED;
subpasses[i].resolve[j].idx = idx;
if (idx != VK_ATTACHMENT_UNUSED) {
subpasses[i].resolve[j].aspects = VK_IMAGE_ASPECT_COLOR_BIT;
subpasses[i].resolve[j].before = attachments[idx].last;
subpasses[i].resolve[j].during =
dzn_image_layout_to_state(subpass->pResolveAttachments[j].layout,
VK_IMAGE_ASPECT_COLOR_BIT);
attachments[idx].last = subpasses[i].resolve[j].during;
attachments[idx].aspects |= VK_IMAGE_ASPECT_COLOR_BIT;
}
}
subpasses[i].zs.idx = VK_ATTACHMENT_UNUSED;
if (subpass->pDepthStencilAttachment) {
uint32_t idx = subpass->pDepthStencilAttachment->attachment;
subpasses[i].zs.idx = idx;
if (idx != VK_ATTACHMENT_UNUSED) {
subpasses[i].zs.aspects = vk_format_aspects(attachments[idx].format);
subpasses[i].zs.before = attachments[idx].last;
subpasses[i].zs.during = attachments[idx].last;
subpasses[i].zs.stencil.before = attachments[idx].stencil.last;
subpasses[i].zs.stencil.during = attachments[idx].stencil.last;
if (subpasses[i].zs.aspects & VK_IMAGE_ASPECT_STENCIL_BIT) {
subpasses[i].zs.stencil.during =
dzn_image_layout_to_state(subpass->pDepthStencilAttachment->layout,
VK_IMAGE_ASPECT_STENCIL_BIT);
}
if (subpasses[i].zs.aspects & VK_IMAGE_ASPECT_DEPTH_BIT) {
subpasses[i].zs.during =
dzn_image_layout_to_state(subpass->pDepthStencilAttachment->layout,
VK_IMAGE_ASPECT_DEPTH_BIT);
}
attachments[idx].last = subpasses[i].zs.during;
attachments[idx].stencil.last = subpasses[i].zs.stencil.during;
attachments[idx].aspects |= subpasses[i].zs.aspects;
}
}
subpasses[i].input_count = subpass->inputAttachmentCount;
for (uint32_t j = 0; j < subpasses[i].input_count; j++) {
uint32_t idx = subpass->pInputAttachments[j].attachment;
subpasses[i].inputs[j].idx = idx;
if (idx != VK_ATTACHMENT_UNUSED) {
subpasses[i].inputs[j].aspects = subpass->pInputAttachments[j].aspectMask;
subpasses[i].inputs[j].before = attachments[idx].last;
subpasses[i].inputs[j].during = attachments[idx].last;
subpasses[i].inputs[j].stencil.before = attachments[idx].stencil.last;
subpasses[i].inputs[j].stencil.during = attachments[idx].stencil.last;
if (subpasses[i].inputs[j].aspects & VK_IMAGE_ASPECT_STENCIL_BIT) {
subpasses[i].inputs[j].stencil.during =
dzn_image_layout_to_state(subpass->pInputAttachments[j].layout,
VK_IMAGE_ASPECT_STENCIL_BIT);
}
if (subpasses[i].inputs[j].aspects & VK_IMAGE_ASPECT_DEPTH_BIT) {
subpasses[i].inputs[j].during =
dzn_image_layout_to_state(subpass->pInputAttachments[j].layout,
VK_IMAGE_ASPECT_DEPTH_BIT);
attachments[idx].last = subpasses[i].inputs[j].during;
} else if (subpasses[i].inputs[j].aspects == VK_IMAGE_ASPECT_COLOR_BIT) {
subpasses[i].inputs[j].during =
dzn_image_layout_to_state(subpass->pInputAttachments[j].layout,
VK_IMAGE_ASPECT_COLOR_BIT);
}
attachments[idx].last = subpasses[i].inputs[j].during;
attachments[idx].stencil.last = subpasses[i].inputs[j].stencil.during;
attachments[idx].aspects |= subpass->pInputAttachments[j].aspectMask;
}
}
}
*pRenderPass = dzn_render_pass_to_handle(pass);
return VK_SUCCESS;
}
VKAPI_ATTR void VKAPI_CALL
dzn_DestroyRenderPass(VkDevice dev,
VkRenderPass p,
const VkAllocationCallbacks *pAllocator)
{
VK_FROM_HANDLE(dzn_device, device, dev);
VK_FROM_HANDLE(dzn_render_pass, pass, p);
if (!pass)
return;
vk_object_base_finish(&pass->base);
vk_free2(&device->vk.alloc, pAllocator, pass);
}
VKAPI_ATTR void VKAPI_CALL
dzn_GetRenderAreaGranularity(VkDevice device,
VkRenderPass pass,
VkExtent2D *pGranularity)
{
pGranularity->width = pGranularity->height = 1;
}