17ec681f3Smrg/*
27ec681f3Smrg * Copyright 2019 Google LLC
37ec681f3Smrg * SPDX-License-Identifier: MIT
47ec681f3Smrg *
57ec681f3Smrg * based in part on anv and radv which are:
67ec681f3Smrg * Copyright © 2015 Intel Corporation
77ec681f3Smrg * Copyright © 2016 Red Hat.
87ec681f3Smrg * Copyright © 2016 Bas Nieuwenhuizen
97ec681f3Smrg */
107ec681f3Smrg
117ec681f3Smrg#include "vn_render_pass.h"
127ec681f3Smrg
137ec681f3Smrg#include "venus-protocol/vn_protocol_driver_framebuffer.h"
147ec681f3Smrg#include "venus-protocol/vn_protocol_driver_render_pass.h"
157ec681f3Smrg
167ec681f3Smrg#include "vn_device.h"
177ec681f3Smrg#include "vn_image.h"
187ec681f3Smrg
197ec681f3Smrg#define COUNT_PRESENT_SRC(atts, att_count, initial_count, final_count)       \
207ec681f3Smrg   do {                                                                      \
217ec681f3Smrg      *initial_count = 0;                                                    \
227ec681f3Smrg      *final_count = 0;                                                      \
237ec681f3Smrg      for (uint32_t i = 0; i < att_count; i++) {                             \
247ec681f3Smrg         if (atts[i].initialLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)       \
257ec681f3Smrg            (*initial_count)++;                                              \
267ec681f3Smrg         if (atts[i].finalLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)         \
277ec681f3Smrg            (*final_count)++;                                                \
287ec681f3Smrg      }                                                                      \
297ec681f3Smrg   } while (false)
307ec681f3Smrg
317ec681f3Smrg#define REPLACE_PRESENT_SRC(pass, atts, att_count, out_atts)                 \
327ec681f3Smrg   do {                                                                      \
337ec681f3Smrg      struct vn_present_src_attachment *_acquire_atts =                      \
347ec681f3Smrg         pass->present_src_attachments;                                      \
357ec681f3Smrg      struct vn_present_src_attachment *_release_atts =                      \
367ec681f3Smrg         _acquire_atts + pass->acquire_count;                                \
377ec681f3Smrg                                                                             \
387ec681f3Smrg      memcpy(out_atts, atts, sizeof(*atts) * att_count);                     \
397ec681f3Smrg      for (uint32_t i = 0; i < att_count; i++) {                             \
407ec681f3Smrg         if (out_atts[i].initialLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) { \
417ec681f3Smrg            out_atts[i].initialLayout = VN_PRESENT_SRC_INTERNAL_LAYOUT;      \
427ec681f3Smrg            _acquire_atts->acquire = true;                                   \
437ec681f3Smrg            _acquire_atts->index = i;                                        \
447ec681f3Smrg            _acquire_atts++;                                                 \
457ec681f3Smrg         }                                                                   \
467ec681f3Smrg         if (out_atts[i].finalLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) {   \
477ec681f3Smrg            out_atts[i].finalLayout = VN_PRESENT_SRC_INTERNAL_LAYOUT;        \
487ec681f3Smrg            _release_atts->acquire = false;                                  \
497ec681f3Smrg            _release_atts->index = i;                                        \
507ec681f3Smrg            _release_atts++;                                                 \
517ec681f3Smrg         }                                                                   \
527ec681f3Smrg      }                                                                      \
537ec681f3Smrg   } while (false)
547ec681f3Smrg
557ec681f3Smrgstatic void
567ec681f3Smrgvn_render_pass_count_present_src(const VkRenderPassCreateInfo *create_info,
577ec681f3Smrg                                 uint32_t *initial_count,
587ec681f3Smrg                                 uint32_t *final_count)
597ec681f3Smrg{
607ec681f3Smrg   COUNT_PRESENT_SRC(create_info->pAttachments, create_info->attachmentCount,
617ec681f3Smrg                     initial_count, final_count);
627ec681f3Smrg}
637ec681f3Smrg
647ec681f3Smrgstatic void
657ec681f3Smrgvn_render_pass_count_present_src2(const VkRenderPassCreateInfo2 *create_info,
667ec681f3Smrg                                  uint32_t *initial_count,
677ec681f3Smrg                                  uint32_t *final_count)
687ec681f3Smrg{
697ec681f3Smrg   COUNT_PRESENT_SRC(create_info->pAttachments, create_info->attachmentCount,
707ec681f3Smrg                     initial_count, final_count);
717ec681f3Smrg}
727ec681f3Smrg
737ec681f3Smrgstatic void
747ec681f3Smrgvn_render_pass_replace_present_src(struct vn_render_pass *pass,
757ec681f3Smrg                                   const VkRenderPassCreateInfo *create_info,
767ec681f3Smrg                                   VkAttachmentDescription *out_atts)
777ec681f3Smrg{
787ec681f3Smrg   REPLACE_PRESENT_SRC(pass, create_info->pAttachments,
797ec681f3Smrg                       create_info->attachmentCount, out_atts);
807ec681f3Smrg}
817ec681f3Smrg
827ec681f3Smrgstatic void
837ec681f3Smrgvn_render_pass_replace_present_src2(struct vn_render_pass *pass,
847ec681f3Smrg                                    const VkRenderPassCreateInfo2 *create_info,
857ec681f3Smrg                                    VkAttachmentDescription2 *out_atts)
867ec681f3Smrg{
877ec681f3Smrg   REPLACE_PRESENT_SRC(pass, create_info->pAttachments,
887ec681f3Smrg                       create_info->attachmentCount, out_atts);
897ec681f3Smrg}
907ec681f3Smrg
917ec681f3Smrgstatic void
927ec681f3Smrgvn_render_pass_setup_present_src_barriers(struct vn_render_pass *pass)
937ec681f3Smrg{
947ec681f3Smrg   /* TODO parse VkSubpassDependency for more accurate barriers */
957ec681f3Smrg   for (uint32_t i = 0; i < pass->present_src_count; i++) {
967ec681f3Smrg      struct vn_present_src_attachment *att =
977ec681f3Smrg         &pass->present_src_attachments[i];
987ec681f3Smrg
997ec681f3Smrg      if (att->acquire) {
1007ec681f3Smrg         att->src_stage_mask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
1017ec681f3Smrg         att->src_access_mask = 0;
1027ec681f3Smrg
1037ec681f3Smrg         att->dst_stage_mask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
1047ec681f3Smrg         att->dst_access_mask =
1057ec681f3Smrg            VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
1067ec681f3Smrg      } else {
1077ec681f3Smrg         att->src_stage_mask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
1087ec681f3Smrg         att->src_access_mask = VK_ACCESS_MEMORY_WRITE_BIT;
1097ec681f3Smrg
1107ec681f3Smrg         att->dst_stage_mask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
1117ec681f3Smrg         att->dst_access_mask = 0;
1127ec681f3Smrg      }
1137ec681f3Smrg   }
1147ec681f3Smrg}
1157ec681f3Smrg
1167ec681f3Smrgstatic struct vn_render_pass *
1177ec681f3Smrgvn_render_pass_create(struct vn_device *dev,
1187ec681f3Smrg                      uint32_t acquire_count,
1197ec681f3Smrg                      uint32_t release_count,
1207ec681f3Smrg                      const VkAllocationCallbacks *alloc)
1217ec681f3Smrg{
1227ec681f3Smrg   const uint32_t total_count = acquire_count + release_count;
1237ec681f3Smrg   struct vn_render_pass *pass = vk_zalloc(
1247ec681f3Smrg      alloc,
1257ec681f3Smrg      sizeof(*pass) + sizeof(pass->present_src_attachments[0]) * total_count,
1267ec681f3Smrg      VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
1277ec681f3Smrg   if (!pass)
1287ec681f3Smrg      return NULL;
1297ec681f3Smrg
1307ec681f3Smrg   vn_object_base_init(&pass->base, VK_OBJECT_TYPE_RENDER_PASS, &dev->base);
1317ec681f3Smrg
1327ec681f3Smrg   pass->acquire_count = acquire_count;
1337ec681f3Smrg   pass->release_count = release_count;
1347ec681f3Smrg   pass->present_src_count = total_count;
1357ec681f3Smrg
1367ec681f3Smrg   return pass;
1377ec681f3Smrg}
1387ec681f3Smrg
1397ec681f3Smrg/* render pass commands */
1407ec681f3Smrg
1417ec681f3SmrgVkResult
1427ec681f3Smrgvn_CreateRenderPass(VkDevice device,
1437ec681f3Smrg                    const VkRenderPassCreateInfo *pCreateInfo,
1447ec681f3Smrg                    const VkAllocationCallbacks *pAllocator,
1457ec681f3Smrg                    VkRenderPass *pRenderPass)
1467ec681f3Smrg{
1477ec681f3Smrg   struct vn_device *dev = vn_device_from_handle(device);
1487ec681f3Smrg   const VkAllocationCallbacks *alloc =
1497ec681f3Smrg      pAllocator ? pAllocator : &dev->base.base.alloc;
1507ec681f3Smrg
1517ec681f3Smrg   uint32_t acquire_count;
1527ec681f3Smrg   uint32_t release_count;
1537ec681f3Smrg   vn_render_pass_count_present_src(pCreateInfo, &acquire_count,
1547ec681f3Smrg                                    &release_count);
1557ec681f3Smrg
1567ec681f3Smrg   struct vn_render_pass *pass =
1577ec681f3Smrg      vn_render_pass_create(dev, acquire_count, release_count, alloc);
1587ec681f3Smrg   if (!pass)
1597ec681f3Smrg      return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
1607ec681f3Smrg
1617ec681f3Smrg   VkRenderPassCreateInfo local_pass_info;
1627ec681f3Smrg   if (pass->present_src_count) {
1637ec681f3Smrg      VkAttachmentDescription *temp_atts =
1647ec681f3Smrg         vk_alloc(alloc, sizeof(*temp_atts) * pCreateInfo->attachmentCount,
1657ec681f3Smrg                  VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
1667ec681f3Smrg      if (!temp_atts) {
1677ec681f3Smrg         vk_free(alloc, pass);
1687ec681f3Smrg         return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
1697ec681f3Smrg      }
1707ec681f3Smrg
1717ec681f3Smrg      vn_render_pass_replace_present_src(pass, pCreateInfo, temp_atts);
1727ec681f3Smrg      vn_render_pass_setup_present_src_barriers(pass);
1737ec681f3Smrg
1747ec681f3Smrg      local_pass_info = *pCreateInfo;
1757ec681f3Smrg      local_pass_info.pAttachments = temp_atts;
1767ec681f3Smrg      pCreateInfo = &local_pass_info;
1777ec681f3Smrg   }
1787ec681f3Smrg
1797ec681f3Smrg   VkRenderPass pass_handle = vn_render_pass_to_handle(pass);
1807ec681f3Smrg   vn_async_vkCreateRenderPass(dev->instance, device, pCreateInfo, NULL,
1817ec681f3Smrg                               &pass_handle);
1827ec681f3Smrg
1837ec681f3Smrg   if (pCreateInfo == &local_pass_info)
1847ec681f3Smrg      vk_free(alloc, (void *)local_pass_info.pAttachments);
1857ec681f3Smrg
1867ec681f3Smrg   *pRenderPass = pass_handle;
1877ec681f3Smrg
1887ec681f3Smrg   return VK_SUCCESS;
1897ec681f3Smrg}
1907ec681f3Smrg
1917ec681f3SmrgVkResult
1927ec681f3Smrgvn_CreateRenderPass2(VkDevice device,
1937ec681f3Smrg                     const VkRenderPassCreateInfo2 *pCreateInfo,
1947ec681f3Smrg                     const VkAllocationCallbacks *pAllocator,
1957ec681f3Smrg                     VkRenderPass *pRenderPass)
1967ec681f3Smrg{
1977ec681f3Smrg   struct vn_device *dev = vn_device_from_handle(device);
1987ec681f3Smrg   const VkAllocationCallbacks *alloc =
1997ec681f3Smrg      pAllocator ? pAllocator : &dev->base.base.alloc;
2007ec681f3Smrg
2017ec681f3Smrg   uint32_t acquire_count;
2027ec681f3Smrg   uint32_t release_count;
2037ec681f3Smrg   vn_render_pass_count_present_src2(pCreateInfo, &acquire_count,
2047ec681f3Smrg                                     &release_count);
2057ec681f3Smrg
2067ec681f3Smrg   struct vn_render_pass *pass =
2077ec681f3Smrg      vn_render_pass_create(dev, acquire_count, release_count, alloc);
2087ec681f3Smrg   if (!pass)
2097ec681f3Smrg      return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
2107ec681f3Smrg
2117ec681f3Smrg   VkRenderPassCreateInfo2 local_pass_info;
2127ec681f3Smrg   if (pass->present_src_count) {
2137ec681f3Smrg      VkAttachmentDescription2 *temp_atts =
2147ec681f3Smrg         vk_alloc(alloc, sizeof(*temp_atts) * pCreateInfo->attachmentCount,
2157ec681f3Smrg                  VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
2167ec681f3Smrg      if (!temp_atts) {
2177ec681f3Smrg         vk_free(alloc, pass);
2187ec681f3Smrg         return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
2197ec681f3Smrg      }
2207ec681f3Smrg
2217ec681f3Smrg      vn_render_pass_replace_present_src2(pass, pCreateInfo, temp_atts);
2227ec681f3Smrg      vn_render_pass_setup_present_src_barriers(pass);
2237ec681f3Smrg
2247ec681f3Smrg      local_pass_info = *pCreateInfo;
2257ec681f3Smrg      local_pass_info.pAttachments = temp_atts;
2267ec681f3Smrg      pCreateInfo = &local_pass_info;
2277ec681f3Smrg   }
2287ec681f3Smrg
2297ec681f3Smrg   VkRenderPass pass_handle = vn_render_pass_to_handle(pass);
2307ec681f3Smrg   vn_async_vkCreateRenderPass2(dev->instance, device, pCreateInfo, NULL,
2317ec681f3Smrg                                &pass_handle);
2327ec681f3Smrg
2337ec681f3Smrg   if (pCreateInfo == &local_pass_info)
2347ec681f3Smrg      vk_free(alloc, (void *)local_pass_info.pAttachments);
2357ec681f3Smrg
2367ec681f3Smrg   *pRenderPass = pass_handle;
2377ec681f3Smrg
2387ec681f3Smrg   return VK_SUCCESS;
2397ec681f3Smrg}
2407ec681f3Smrg
2417ec681f3Smrgvoid
2427ec681f3Smrgvn_DestroyRenderPass(VkDevice device,
2437ec681f3Smrg                     VkRenderPass renderPass,
2447ec681f3Smrg                     const VkAllocationCallbacks *pAllocator)
2457ec681f3Smrg{
2467ec681f3Smrg   struct vn_device *dev = vn_device_from_handle(device);
2477ec681f3Smrg   struct vn_render_pass *pass = vn_render_pass_from_handle(renderPass);
2487ec681f3Smrg   const VkAllocationCallbacks *alloc =
2497ec681f3Smrg      pAllocator ? pAllocator : &dev->base.base.alloc;
2507ec681f3Smrg
2517ec681f3Smrg   if (!pass)
2527ec681f3Smrg      return;
2537ec681f3Smrg
2547ec681f3Smrg   vn_async_vkDestroyRenderPass(dev->instance, device, renderPass, NULL);
2557ec681f3Smrg
2567ec681f3Smrg   vn_object_base_fini(&pass->base);
2577ec681f3Smrg   vk_free(alloc, pass);
2587ec681f3Smrg}
2597ec681f3Smrg
2607ec681f3Smrgvoid
2617ec681f3Smrgvn_GetRenderAreaGranularity(VkDevice device,
2627ec681f3Smrg                            VkRenderPass renderPass,
2637ec681f3Smrg                            VkExtent2D *pGranularity)
2647ec681f3Smrg{
2657ec681f3Smrg   struct vn_device *dev = vn_device_from_handle(device);
2667ec681f3Smrg   struct vn_render_pass *pass = vn_render_pass_from_handle(renderPass);
2677ec681f3Smrg
2687ec681f3Smrg   if (!pass->granularity.width) {
2697ec681f3Smrg      vn_call_vkGetRenderAreaGranularity(dev->instance, device, renderPass,
2707ec681f3Smrg                                         &pass->granularity);
2717ec681f3Smrg   }
2727ec681f3Smrg
2737ec681f3Smrg   *pGranularity = pass->granularity;
2747ec681f3Smrg}
2757ec681f3Smrg
2767ec681f3Smrg/* framebuffer commands */
2777ec681f3Smrg
2787ec681f3SmrgVkResult
2797ec681f3Smrgvn_CreateFramebuffer(VkDevice device,
2807ec681f3Smrg                     const VkFramebufferCreateInfo *pCreateInfo,
2817ec681f3Smrg                     const VkAllocationCallbacks *pAllocator,
2827ec681f3Smrg                     VkFramebuffer *pFramebuffer)
2837ec681f3Smrg{
2847ec681f3Smrg   struct vn_device *dev = vn_device_from_handle(device);
2857ec681f3Smrg   const VkAllocationCallbacks *alloc =
2867ec681f3Smrg      pAllocator ? pAllocator : &dev->base.base.alloc;
2877ec681f3Smrg
2887ec681f3Smrg   /* Two render passes differ only in attachment image layouts are considered
2897ec681f3Smrg    * compatible.  We must not use pCreateInfo->renderPass here.
2907ec681f3Smrg    */
2917ec681f3Smrg   const bool imageless =
2927ec681f3Smrg      pCreateInfo->flags & VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT;
2937ec681f3Smrg   const uint32_t view_count = imageless ? 0 : pCreateInfo->attachmentCount;
2947ec681f3Smrg
2957ec681f3Smrg   struct vn_framebuffer *fb =
2967ec681f3Smrg      vk_zalloc(alloc, sizeof(*fb) + sizeof(*fb->image_views) * view_count,
2977ec681f3Smrg                VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
2987ec681f3Smrg   if (!fb)
2997ec681f3Smrg      return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
3007ec681f3Smrg
3017ec681f3Smrg   vn_object_base_init(&fb->base, VK_OBJECT_TYPE_FRAMEBUFFER, &dev->base);
3027ec681f3Smrg
3037ec681f3Smrg   fb->image_view_count = view_count;
3047ec681f3Smrg   memcpy(fb->image_views, pCreateInfo->pAttachments,
3057ec681f3Smrg          sizeof(*pCreateInfo->pAttachments) * view_count);
3067ec681f3Smrg
3077ec681f3Smrg   VkFramebuffer fb_handle = vn_framebuffer_to_handle(fb);
3087ec681f3Smrg   vn_async_vkCreateFramebuffer(dev->instance, device, pCreateInfo, NULL,
3097ec681f3Smrg                                &fb_handle);
3107ec681f3Smrg
3117ec681f3Smrg   *pFramebuffer = fb_handle;
3127ec681f3Smrg
3137ec681f3Smrg   return VK_SUCCESS;
3147ec681f3Smrg}
3157ec681f3Smrg
3167ec681f3Smrgvoid
3177ec681f3Smrgvn_DestroyFramebuffer(VkDevice device,
3187ec681f3Smrg                      VkFramebuffer framebuffer,
3197ec681f3Smrg                      const VkAllocationCallbacks *pAllocator)
3207ec681f3Smrg{
3217ec681f3Smrg   struct vn_device *dev = vn_device_from_handle(device);
3227ec681f3Smrg   struct vn_framebuffer *fb = vn_framebuffer_from_handle(framebuffer);
3237ec681f3Smrg   const VkAllocationCallbacks *alloc =
3247ec681f3Smrg      pAllocator ? pAllocator : &dev->base.base.alloc;
3257ec681f3Smrg
3267ec681f3Smrg   if (!fb)
3277ec681f3Smrg      return;
3287ec681f3Smrg
3297ec681f3Smrg   vn_async_vkDestroyFramebuffer(dev->instance, device, framebuffer, NULL);
3307ec681f3Smrg
3317ec681f3Smrg   vn_object_base_fini(&fb->base);
3327ec681f3Smrg   vk_free(alloc, fb);
3337ec681f3Smrg}
334