Home | History | Annotate | Download | only in vulkan
      1 /*
      2  * Copyright  2015 Intel Corporation
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8  * and/or sell copies of the Software, and to permit persons to whom the
      9  * Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice (including the next
     12  * paragraph) shall be included in all copies or substantial portions of the
     13  * Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
     21  * IN THE SOFTWARE.
     22  */
     23 
     24 #include "anv_private.h"
     25 
     26 VkResult anv_CreateRenderPass(
     27     VkDevice                                    _device,
     28     const VkRenderPassCreateInfo*               pCreateInfo,
     29     const VkAllocationCallbacks*                pAllocator,
     30     VkRenderPass*                               pRenderPass)
     31 {
     32    ANV_FROM_HANDLE(anv_device, device, _device);
     33    struct anv_render_pass *pass;
     34    size_t size;
     35    size_t attachments_offset;
     36 
     37    assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO);
     38 
     39    size = sizeof(*pass);
     40    size += pCreateInfo->subpassCount * sizeof(pass->subpasses[0]);
     41    attachments_offset = size;
     42    size += pCreateInfo->attachmentCount * sizeof(pass->attachments[0]);
     43 
     44    pass = vk_alloc2(&device->alloc, pAllocator, size, 8,
     45                      VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
     46    if (pass == NULL)
     47       return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
     48 
     49    /* Clear the subpasses along with the parent pass. This required because
     50     * each array member of anv_subpass must be a valid pointer if not NULL.
     51     */
     52    memset(pass, 0, size);
     53    pass->attachment_count = pCreateInfo->attachmentCount;
     54    pass->subpass_count = pCreateInfo->subpassCount;
     55    pass->attachments = (void *) pass + attachments_offset;
     56 
     57    pass->subpass_usages =
     58       vk_zalloc2(&device->alloc, pAllocator,
     59                  pass->subpass_count * pass->attachment_count *
     60                                        sizeof(*pass->subpass_usages),
     61                  8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
     62    if (pass->subpass_usages == NULL) {
     63       vk_free2(&device->alloc, pAllocator, pass);
     64       return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
     65    }
     66 
     67    enum anv_subpass_usage *usages = pass->subpass_usages;
     68    for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) {
     69       struct anv_render_pass_attachment *att = &pass->attachments[i];
     70 
     71       att->format = pCreateInfo->pAttachments[i].format;
     72       att->samples = pCreateInfo->pAttachments[i].samples;
     73       att->usage = 0;
     74       att->load_op = pCreateInfo->pAttachments[i].loadOp;
     75       att->store_op = pCreateInfo->pAttachments[i].storeOp;
     76       att->stencil_load_op = pCreateInfo->pAttachments[i].stencilLoadOp;
     77       att->initial_layout = pCreateInfo->pAttachments[i].initialLayout;
     78       att->final_layout = pCreateInfo->pAttachments[i].finalLayout;
     79       att->subpass_usage = usages;
     80       usages += pass->subpass_count;
     81    }
     82 
     83    uint32_t subpass_attachment_count = 0, *p;
     84    for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) {
     85       const VkSubpassDescription *desc = &pCreateInfo->pSubpasses[i];
     86 
     87       subpass_attachment_count +=
     88          desc->inputAttachmentCount +
     89          desc->colorAttachmentCount +
     90          /* Count colorAttachmentCount again for resolve_attachments */
     91          desc->colorAttachmentCount;
     92    }
     93 
     94    pass->subpass_attachments =
     95       vk_alloc2(&device->alloc, pAllocator,
     96                  subpass_attachment_count * sizeof(uint32_t), 8,
     97                  VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
     98    if (pass->subpass_attachments == NULL) {
     99       vk_free2(&device->alloc, pAllocator, pass->subpass_usages);
    100       vk_free2(&device->alloc, pAllocator, pass);
    101       return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
    102    }
    103 
    104    p = pass->subpass_attachments;
    105    for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) {
    106       const VkSubpassDescription *desc = &pCreateInfo->pSubpasses[i];
    107       struct anv_subpass *subpass = &pass->subpasses[i];
    108 
    109       subpass->input_count = desc->inputAttachmentCount;
    110       subpass->color_count = desc->colorAttachmentCount;
    111 
    112       if (desc->inputAttachmentCount > 0) {
    113          subpass->input_attachments = p;
    114          p += desc->inputAttachmentCount;
    115 
    116          for (uint32_t j = 0; j < desc->inputAttachmentCount; j++) {
    117             uint32_t a = desc->pInputAttachments[j].attachment;
    118             subpass->input_attachments[j] = a;
    119             if (a != VK_ATTACHMENT_UNUSED) {
    120                pass->attachments[a].usage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
    121                pass->attachments[a].subpass_usage[i] |= ANV_SUBPASS_USAGE_INPUT;
    122                pass->attachments[a].last_subpass_idx = i;
    123 
    124                if (desc->pDepthStencilAttachment &&
    125                    a == desc->pDepthStencilAttachment->attachment)
    126                   subpass->has_ds_self_dep = true;
    127             }
    128          }
    129       }
    130 
    131       if (desc->colorAttachmentCount > 0) {
    132          subpass->color_attachments = p;
    133          p += desc->colorAttachmentCount;
    134 
    135          for (uint32_t j = 0; j < desc->colorAttachmentCount; j++) {
    136             uint32_t a = desc->pColorAttachments[j].attachment;
    137             subpass->color_attachments[j] = a;
    138             if (a != VK_ATTACHMENT_UNUSED) {
    139                pass->attachments[a].usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
    140                pass->attachments[a].subpass_usage[i] |= ANV_SUBPASS_USAGE_DRAW;
    141                pass->attachments[a].last_subpass_idx = i;
    142             }
    143          }
    144       }
    145 
    146       subpass->has_resolve = false;
    147       if (desc->pResolveAttachments) {
    148          subpass->resolve_attachments = p;
    149          p += desc->colorAttachmentCount;
    150 
    151          for (uint32_t j = 0; j < desc->colorAttachmentCount; j++) {
    152             uint32_t a = desc->pResolveAttachments[j].attachment;
    153             subpass->resolve_attachments[j] = a;
    154             if (a != VK_ATTACHMENT_UNUSED) {
    155                subpass->has_resolve = true;
    156                uint32_t color_att = desc->pColorAttachments[j].attachment;
    157                pass->attachments[color_att].usage |=
    158                   VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
    159                pass->attachments[a].usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
    160 
    161                pass->attachments[color_att].subpass_usage[i] |=
    162                   ANV_SUBPASS_USAGE_RESOLVE_SRC;
    163                pass->attachments[a].subpass_usage[i] |=
    164                   ANV_SUBPASS_USAGE_RESOLVE_DST;
    165                pass->attachments[a].last_subpass_idx = i;
    166             }
    167          }
    168       }
    169 
    170       if (desc->pDepthStencilAttachment) {
    171          uint32_t a = desc->pDepthStencilAttachment->attachment;
    172          subpass->depth_stencil_attachment = a;
    173          subpass->depth_stencil_layout =
    174             desc->pDepthStencilAttachment->layout;
    175          if (a != VK_ATTACHMENT_UNUSED) {
    176             pass->attachments[a].usage |=
    177                VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
    178             pass->attachments[a].subpass_usage[i] |= ANV_SUBPASS_USAGE_DRAW;
    179             pass->attachments[a].last_subpass_idx = i;
    180          }
    181       } else {
    182          subpass->depth_stencil_attachment = VK_ATTACHMENT_UNUSED;
    183          subpass->depth_stencil_layout = VK_IMAGE_LAYOUT_UNDEFINED;
    184       }
    185    }
    186 
    187    *pRenderPass = anv_render_pass_to_handle(pass);
    188 
    189    return VK_SUCCESS;
    190 }
    191 
    192 void anv_DestroyRenderPass(
    193     VkDevice                                    _device,
    194     VkRenderPass                                _pass,
    195     const VkAllocationCallbacks*                pAllocator)
    196 {
    197    ANV_FROM_HANDLE(anv_device, device, _device);
    198    ANV_FROM_HANDLE(anv_render_pass, pass, _pass);
    199 
    200    if (!pass)
    201       return;
    202 
    203    vk_free2(&device->alloc, pAllocator, pass->subpass_attachments);
    204    vk_free2(&device->alloc, pAllocator, pass->subpass_usages);
    205    vk_free2(&device->alloc, pAllocator, pass);
    206 }
    207 
    208 void anv_GetRenderAreaGranularity(
    209     VkDevice                                    device,
    210     VkRenderPass                                renderPass,
    211     VkExtent2D*                                 pGranularity)
    212 {
    213    ANV_FROM_HANDLE(anv_render_pass, pass, renderPass);
    214 
    215    /* This granularity satisfies HiZ fast clear alignment requirements
    216     * for all sample counts.
    217     */
    218    for (unsigned i = 0; i < pass->subpass_count; ++i) {
    219       if (pass->subpasses[i].depth_stencil_attachment !=
    220           VK_ATTACHMENT_UNUSED) {
    221          *pGranularity = (VkExtent2D) { .width = 8, .height = 4 };
    222          return;
    223       }
    224    }
    225 
    226    *pGranularity = (VkExtent2D) { 1, 1 };
    227 }
    228