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_image.h"
127ec681f3Smrg
137ec681f3Smrg#include "venus-protocol/vn_protocol_driver_image.h"
147ec681f3Smrg#include "venus-protocol/vn_protocol_driver_image_view.h"
157ec681f3Smrg#include "venus-protocol/vn_protocol_driver_sampler.h"
167ec681f3Smrg#include "venus-protocol/vn_protocol_driver_sampler_ycbcr_conversion.h"
177ec681f3Smrg
187ec681f3Smrg#include "vn_android.h"
197ec681f3Smrg#include "vn_device.h"
207ec681f3Smrg#include "vn_device_memory.h"
217ec681f3Smrg#include "vn_wsi.h"
227ec681f3Smrg
237ec681f3Smrgstatic void
247ec681f3Smrgvn_image_init_memory_requirements(struct vn_image *img,
257ec681f3Smrg                                  struct vn_device *dev,
267ec681f3Smrg                                  const VkImageCreateInfo *create_info)
277ec681f3Smrg{
287ec681f3Smrg   uint32_t plane_count = 1;
297ec681f3Smrg   if (create_info->flags & VK_IMAGE_CREATE_DISJOINT_BIT) {
307ec681f3Smrg      /* TODO VkDrmFormatModifierPropertiesEXT::drmFormatModifierPlaneCount */
317ec681f3Smrg      assert(create_info->tiling != VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT);
327ec681f3Smrg
337ec681f3Smrg      switch (create_info->format) {
347ec681f3Smrg      case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
357ec681f3Smrg      case VK_FORMAT_G8_B8R8_2PLANE_422_UNORM:
367ec681f3Smrg      case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
377ec681f3Smrg      case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16:
387ec681f3Smrg      case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16:
397ec681f3Smrg      case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16:
407ec681f3Smrg      case VK_FORMAT_G16_B16R16_2PLANE_420_UNORM:
417ec681f3Smrg      case VK_FORMAT_G16_B16R16_2PLANE_422_UNORM:
427ec681f3Smrg         plane_count = 2;
437ec681f3Smrg         break;
447ec681f3Smrg      case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
457ec681f3Smrg      case VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM:
467ec681f3Smrg      case VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM:
477ec681f3Smrg      case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16:
487ec681f3Smrg      case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16:
497ec681f3Smrg      case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16:
507ec681f3Smrg      case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16:
517ec681f3Smrg      case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16:
527ec681f3Smrg      case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16:
537ec681f3Smrg      case VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM:
547ec681f3Smrg      case VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM:
557ec681f3Smrg      case VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM:
567ec681f3Smrg         plane_count = 3;
577ec681f3Smrg         break;
587ec681f3Smrg      default:
597ec681f3Smrg         plane_count = 1;
607ec681f3Smrg         break;
617ec681f3Smrg      }
627ec681f3Smrg   }
637ec681f3Smrg   assert(plane_count <= ARRAY_SIZE(img->memory_requirements));
647ec681f3Smrg
657ec681f3Smrg   /* TODO add a per-device cache for the requirements */
667ec681f3Smrg   for (uint32_t i = 0; i < plane_count; i++) {
677ec681f3Smrg      img->memory_requirements[i].sType =
687ec681f3Smrg         VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2;
697ec681f3Smrg      img->memory_requirements[i].pNext = &img->dedicated_requirements[i];
707ec681f3Smrg      img->dedicated_requirements[i].sType =
717ec681f3Smrg         VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS;
727ec681f3Smrg      img->dedicated_requirements[i].pNext = NULL;
737ec681f3Smrg   }
747ec681f3Smrg
757ec681f3Smrg   VkDevice dev_handle = vn_device_to_handle(dev);
767ec681f3Smrg   VkImage img_handle = vn_image_to_handle(img);
777ec681f3Smrg   if (plane_count == 1) {
787ec681f3Smrg      vn_call_vkGetImageMemoryRequirements2(
797ec681f3Smrg         dev->instance, dev_handle,
807ec681f3Smrg         &(VkImageMemoryRequirementsInfo2){
817ec681f3Smrg            .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,
827ec681f3Smrg            .image = img_handle,
837ec681f3Smrg         },
847ec681f3Smrg         &img->memory_requirements[0]);
857ec681f3Smrg
867ec681f3Smrg      /* AHB backed image requires dedicated allocation */
877ec681f3Smrg      if (img->deferred_info) {
887ec681f3Smrg         img->dedicated_requirements[0].prefersDedicatedAllocation = VK_TRUE;
897ec681f3Smrg         img->dedicated_requirements[0].requiresDedicatedAllocation = VK_TRUE;
907ec681f3Smrg      }
917ec681f3Smrg   } else {
927ec681f3Smrg      for (uint32_t i = 0; i < plane_count; i++) {
937ec681f3Smrg         vn_call_vkGetImageMemoryRequirements2(
947ec681f3Smrg            dev->instance, dev_handle,
957ec681f3Smrg            &(VkImageMemoryRequirementsInfo2){
967ec681f3Smrg               .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,
977ec681f3Smrg               .pNext =
987ec681f3Smrg                  &(VkImagePlaneMemoryRequirementsInfo){
997ec681f3Smrg                     .sType =
1007ec681f3Smrg                        VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO,
1017ec681f3Smrg                     .planeAspect = VK_IMAGE_ASPECT_PLANE_0_BIT << i,
1027ec681f3Smrg                  },
1037ec681f3Smrg               .image = img_handle,
1047ec681f3Smrg            },
1057ec681f3Smrg            &img->memory_requirements[i]);
1067ec681f3Smrg      }
1077ec681f3Smrg   }
1087ec681f3Smrg}
1097ec681f3Smrg
1107ec681f3Smrgstatic VkResult
1117ec681f3Smrgvn_image_store_deferred_create_info(
1127ec681f3Smrg   const VkImageCreateInfo *create_info,
1137ec681f3Smrg   const VkAllocationCallbacks *alloc,
1147ec681f3Smrg   struct vn_image_create_deferred_info **out_info)
1157ec681f3Smrg{
1167ec681f3Smrg   struct vn_image_create_deferred_info *info = NULL;
1177ec681f3Smrg   VkBaseOutStructure *dst = NULL;
1187ec681f3Smrg
1197ec681f3Smrg   info = vk_zalloc(alloc, sizeof(*info), VN_DEFAULT_ALIGN,
1207ec681f3Smrg                    VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
1217ec681f3Smrg   if (!info)
1227ec681f3Smrg      return VK_ERROR_OUT_OF_HOST_MEMORY;
1237ec681f3Smrg
1247ec681f3Smrg   info->create = *create_info;
1257ec681f3Smrg   dst = (void *)&info->create;
1267ec681f3Smrg
1277ec681f3Smrg   vk_foreach_struct_const(src, create_info->pNext) {
1287ec681f3Smrg      void *pnext = NULL;
1297ec681f3Smrg      switch (src->sType) {
1307ec681f3Smrg      case VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO:
1317ec681f3Smrg         memcpy(&info->list, src, sizeof(info->list));
1327ec681f3Smrg         pnext = &info->list;
1337ec681f3Smrg         break;
1347ec681f3Smrg      case VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO:
1357ec681f3Smrg         memcpy(&info->stencil, src, sizeof(info->stencil));
1367ec681f3Smrg         pnext = &info->stencil;
1377ec681f3Smrg         break;
1387ec681f3Smrg      default:
1397ec681f3Smrg         break;
1407ec681f3Smrg      }
1417ec681f3Smrg
1427ec681f3Smrg      if (pnext) {
1437ec681f3Smrg         dst->pNext = pnext;
1447ec681f3Smrg         dst = pnext;
1457ec681f3Smrg      }
1467ec681f3Smrg   }
1477ec681f3Smrg   dst->pNext = NULL;
1487ec681f3Smrg
1497ec681f3Smrg   *out_info = info;
1507ec681f3Smrg
1517ec681f3Smrg   return VK_SUCCESS;
1527ec681f3Smrg}
1537ec681f3Smrg
1547ec681f3Smrgstatic VkResult
1557ec681f3Smrgvn_image_init(struct vn_device *dev,
1567ec681f3Smrg              const VkImageCreateInfo *create_info,
1577ec681f3Smrg              struct vn_image *img)
1587ec681f3Smrg{
1597ec681f3Smrg   VkDevice device = vn_device_to_handle(dev);
1607ec681f3Smrg   VkImage image = vn_image_to_handle(img);
1617ec681f3Smrg   VkResult result = VK_SUCCESS;
1627ec681f3Smrg
1637ec681f3Smrg   img->sharing_mode = create_info->sharingMode;
1647ec681f3Smrg
1657ec681f3Smrg   /* TODO async */
1667ec681f3Smrg   result =
1677ec681f3Smrg      vn_call_vkCreateImage(dev->instance, device, create_info, NULL, &image);
1687ec681f3Smrg   if (result != VK_SUCCESS)
1697ec681f3Smrg      return result;
1707ec681f3Smrg
1717ec681f3Smrg   vn_image_init_memory_requirements(img, dev, create_info);
1727ec681f3Smrg
1737ec681f3Smrg   return VK_SUCCESS;
1747ec681f3Smrg}
1757ec681f3Smrg
1767ec681f3SmrgVkResult
1777ec681f3Smrgvn_image_create(struct vn_device *dev,
1787ec681f3Smrg                const VkImageCreateInfo *create_info,
1797ec681f3Smrg                const VkAllocationCallbacks *alloc,
1807ec681f3Smrg                struct vn_image **out_img)
1817ec681f3Smrg{
1827ec681f3Smrg   struct vn_image *img = NULL;
1837ec681f3Smrg   VkResult result = VK_SUCCESS;
1847ec681f3Smrg
1857ec681f3Smrg   img = vk_zalloc(alloc, sizeof(*img), VN_DEFAULT_ALIGN,
1867ec681f3Smrg                   VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
1877ec681f3Smrg   if (!img)
1887ec681f3Smrg      return VK_ERROR_OUT_OF_HOST_MEMORY;
1897ec681f3Smrg
1907ec681f3Smrg   vn_object_base_init(&img->base, VK_OBJECT_TYPE_IMAGE, &dev->base);
1917ec681f3Smrg
1927ec681f3Smrg   result = vn_image_init(dev, create_info, img);
1937ec681f3Smrg   if (result != VK_SUCCESS) {
1947ec681f3Smrg      vn_object_base_fini(&img->base);
1957ec681f3Smrg      vk_free(alloc, img);
1967ec681f3Smrg      return result;
1977ec681f3Smrg   }
1987ec681f3Smrg
1997ec681f3Smrg   *out_img = img;
2007ec681f3Smrg
2017ec681f3Smrg   return VK_SUCCESS;
2027ec681f3Smrg}
2037ec681f3Smrg
2047ec681f3SmrgVkResult
2057ec681f3Smrgvn_image_init_deferred(struct vn_device *dev,
2067ec681f3Smrg                       const VkImageCreateInfo *create_info,
2077ec681f3Smrg                       struct vn_image *img)
2087ec681f3Smrg{
2097ec681f3Smrg   VkResult result = vn_image_init(dev, create_info, img);
2107ec681f3Smrg   img->deferred_info->initialized = result == VK_SUCCESS;
2117ec681f3Smrg   return result;
2127ec681f3Smrg}
2137ec681f3Smrg
2147ec681f3SmrgVkResult
2157ec681f3Smrgvn_image_create_deferred(struct vn_device *dev,
2167ec681f3Smrg                         const VkImageCreateInfo *create_info,
2177ec681f3Smrg                         const VkAllocationCallbacks *alloc,
2187ec681f3Smrg                         struct vn_image **out_img)
2197ec681f3Smrg{
2207ec681f3Smrg   struct vn_image *img = NULL;
2217ec681f3Smrg   VkResult result = VK_SUCCESS;
2227ec681f3Smrg
2237ec681f3Smrg   img = vk_zalloc(alloc, sizeof(*img), VN_DEFAULT_ALIGN,
2247ec681f3Smrg                   VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
2257ec681f3Smrg   if (!img)
2267ec681f3Smrg      return VK_ERROR_OUT_OF_HOST_MEMORY;
2277ec681f3Smrg
2287ec681f3Smrg   vn_object_base_init(&img->base, VK_OBJECT_TYPE_IMAGE, &dev->base);
2297ec681f3Smrg
2307ec681f3Smrg   result = vn_image_store_deferred_create_info(create_info, alloc,
2317ec681f3Smrg                                                &img->deferred_info);
2327ec681f3Smrg   if (result != VK_SUCCESS) {
2337ec681f3Smrg      vn_object_base_fini(&img->base);
2347ec681f3Smrg      vk_free(alloc, img);
2357ec681f3Smrg      return result;
2367ec681f3Smrg   }
2377ec681f3Smrg
2387ec681f3Smrg   *out_img = img;
2397ec681f3Smrg
2407ec681f3Smrg   return VK_SUCCESS;
2417ec681f3Smrg}
2427ec681f3Smrg
2437ec681f3Smrg/* image commands */
2447ec681f3Smrg
2457ec681f3SmrgVkResult
2467ec681f3Smrgvn_CreateImage(VkDevice device,
2477ec681f3Smrg               const VkImageCreateInfo *pCreateInfo,
2487ec681f3Smrg               const VkAllocationCallbacks *pAllocator,
2497ec681f3Smrg               VkImage *pImage)
2507ec681f3Smrg{
2517ec681f3Smrg   struct vn_device *dev = vn_device_from_handle(device);
2527ec681f3Smrg   const VkAllocationCallbacks *alloc =
2537ec681f3Smrg      pAllocator ? pAllocator : &dev->base.base.alloc;
2547ec681f3Smrg   struct vn_image *img;
2557ec681f3Smrg   VkResult result;
2567ec681f3Smrg
2577ec681f3Smrg   const struct wsi_image_create_info *wsi_info =
2587ec681f3Smrg      vn_wsi_find_wsi_image_create_info(pCreateInfo);
2597ec681f3Smrg   const VkNativeBufferANDROID *anb_info =
2607ec681f3Smrg      vn_android_find_native_buffer(pCreateInfo);
2617ec681f3Smrg   const VkExternalMemoryImageCreateInfo *external_info =
2627ec681f3Smrg      vk_find_struct_const(pCreateInfo->pNext,
2637ec681f3Smrg                           EXTERNAL_MEMORY_IMAGE_CREATE_INFO);
2647ec681f3Smrg   const bool ahb_info =
2657ec681f3Smrg      external_info &&
2667ec681f3Smrg      external_info->handleTypes ==
2677ec681f3Smrg         VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;
2687ec681f3Smrg
2697ec681f3Smrg   if (wsi_info) {
2707ec681f3Smrg      result = vn_wsi_create_image(dev, pCreateInfo, wsi_info, alloc, &img);
2717ec681f3Smrg   } else if (anb_info) {
2727ec681f3Smrg      result =
2737ec681f3Smrg         vn_android_image_from_anb(dev, pCreateInfo, anb_info, alloc, &img);
2747ec681f3Smrg   } else if (ahb_info) {
2757ec681f3Smrg      result = vn_android_image_from_ahb(dev, pCreateInfo, alloc, &img);
2767ec681f3Smrg   } else {
2777ec681f3Smrg      result = vn_image_create(dev, pCreateInfo, alloc, &img);
2787ec681f3Smrg   }
2797ec681f3Smrg
2807ec681f3Smrg   if (result != VK_SUCCESS)
2817ec681f3Smrg      return vn_error(dev->instance, result);
2827ec681f3Smrg
2837ec681f3Smrg   *pImage = vn_image_to_handle(img);
2847ec681f3Smrg   return VK_SUCCESS;
2857ec681f3Smrg}
2867ec681f3Smrg
2877ec681f3Smrgvoid
2887ec681f3Smrgvn_DestroyImage(VkDevice device,
2897ec681f3Smrg                VkImage image,
2907ec681f3Smrg                const VkAllocationCallbacks *pAllocator)
2917ec681f3Smrg{
2927ec681f3Smrg   struct vn_device *dev = vn_device_from_handle(device);
2937ec681f3Smrg   struct vn_image *img = vn_image_from_handle(image);
2947ec681f3Smrg   const VkAllocationCallbacks *alloc =
2957ec681f3Smrg      pAllocator ? pAllocator : &dev->base.base.alloc;
2967ec681f3Smrg
2977ec681f3Smrg   if (!img)
2987ec681f3Smrg      return;
2997ec681f3Smrg
3007ec681f3Smrg   if (img->private_memory != VK_NULL_HANDLE)
3017ec681f3Smrg      vn_FreeMemory(device, img->private_memory, pAllocator);
3027ec681f3Smrg
3037ec681f3Smrg   /* must not ask renderer to destroy uninitialized deferred image */
3047ec681f3Smrg   if (!img->deferred_info || img->deferred_info->initialized)
3057ec681f3Smrg      vn_async_vkDestroyImage(dev->instance, device, image, NULL);
3067ec681f3Smrg
3077ec681f3Smrg   if (img->deferred_info)
3087ec681f3Smrg      vk_free(alloc, img->deferred_info);
3097ec681f3Smrg
3107ec681f3Smrg   vn_object_base_fini(&img->base);
3117ec681f3Smrg   vk_free(alloc, img);
3127ec681f3Smrg}
3137ec681f3Smrg
3147ec681f3Smrgvoid
3157ec681f3Smrgvn_GetImageMemoryRequirements(VkDevice device,
3167ec681f3Smrg                              VkImage image,
3177ec681f3Smrg                              VkMemoryRequirements *pMemoryRequirements)
3187ec681f3Smrg{
3197ec681f3Smrg   const struct vn_image *img = vn_image_from_handle(image);
3207ec681f3Smrg
3217ec681f3Smrg   *pMemoryRequirements = img->memory_requirements[0].memoryRequirements;
3227ec681f3Smrg}
3237ec681f3Smrg
3247ec681f3Smrgvoid
3257ec681f3Smrgvn_GetImageSparseMemoryRequirements(
3267ec681f3Smrg   VkDevice device,
3277ec681f3Smrg   VkImage image,
3287ec681f3Smrg   uint32_t *pSparseMemoryRequirementCount,
3297ec681f3Smrg   VkSparseImageMemoryRequirements *pSparseMemoryRequirements)
3307ec681f3Smrg{
3317ec681f3Smrg   struct vn_device *dev = vn_device_from_handle(device);
3327ec681f3Smrg
3337ec681f3Smrg   /* TODO per-device cache */
3347ec681f3Smrg   vn_call_vkGetImageSparseMemoryRequirements(dev->instance, device, image,
3357ec681f3Smrg                                              pSparseMemoryRequirementCount,
3367ec681f3Smrg                                              pSparseMemoryRequirements);
3377ec681f3Smrg}
3387ec681f3Smrg
3397ec681f3Smrgvoid
3407ec681f3Smrgvn_GetImageMemoryRequirements2(VkDevice device,
3417ec681f3Smrg                               const VkImageMemoryRequirementsInfo2 *pInfo,
3427ec681f3Smrg                               VkMemoryRequirements2 *pMemoryRequirements)
3437ec681f3Smrg{
3447ec681f3Smrg   const struct vn_image *img = vn_image_from_handle(pInfo->image);
3457ec681f3Smrg   union {
3467ec681f3Smrg      VkBaseOutStructure *pnext;
3477ec681f3Smrg      VkMemoryRequirements2 *two;
3487ec681f3Smrg      VkMemoryDedicatedRequirements *dedicated;
3497ec681f3Smrg   } u = { .two = pMemoryRequirements };
3507ec681f3Smrg
3517ec681f3Smrg   uint32_t plane = 0;
3527ec681f3Smrg   const VkImagePlaneMemoryRequirementsInfo *plane_info =
3537ec681f3Smrg      vk_find_struct_const(pInfo->pNext,
3547ec681f3Smrg                           IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO);
3557ec681f3Smrg   if (plane_info) {
3567ec681f3Smrg      switch (plane_info->planeAspect) {
3577ec681f3Smrg      case VK_IMAGE_ASPECT_PLANE_1_BIT:
3587ec681f3Smrg         plane = 1;
3597ec681f3Smrg         break;
3607ec681f3Smrg      case VK_IMAGE_ASPECT_PLANE_2_BIT:
3617ec681f3Smrg         plane = 2;
3627ec681f3Smrg         break;
3637ec681f3Smrg      default:
3647ec681f3Smrg         plane = 0;
3657ec681f3Smrg         break;
3667ec681f3Smrg      }
3677ec681f3Smrg   }
3687ec681f3Smrg
3697ec681f3Smrg   while (u.pnext) {
3707ec681f3Smrg      switch (u.pnext->sType) {
3717ec681f3Smrg      case VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2:
3727ec681f3Smrg         u.two->memoryRequirements =
3737ec681f3Smrg            img->memory_requirements[plane].memoryRequirements;
3747ec681f3Smrg         break;
3757ec681f3Smrg      case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS:
3767ec681f3Smrg         u.dedicated->prefersDedicatedAllocation =
3777ec681f3Smrg            img->dedicated_requirements[plane].prefersDedicatedAllocation;
3787ec681f3Smrg         u.dedicated->requiresDedicatedAllocation =
3797ec681f3Smrg            img->dedicated_requirements[plane].requiresDedicatedAllocation;
3807ec681f3Smrg         break;
3817ec681f3Smrg      default:
3827ec681f3Smrg         break;
3837ec681f3Smrg      }
3847ec681f3Smrg      u.pnext = u.pnext->pNext;
3857ec681f3Smrg   }
3867ec681f3Smrg}
3877ec681f3Smrg
3887ec681f3Smrgvoid
3897ec681f3Smrgvn_GetImageSparseMemoryRequirements2(
3907ec681f3Smrg   VkDevice device,
3917ec681f3Smrg   const VkImageSparseMemoryRequirementsInfo2 *pInfo,
3927ec681f3Smrg   uint32_t *pSparseMemoryRequirementCount,
3937ec681f3Smrg   VkSparseImageMemoryRequirements2 *pSparseMemoryRequirements)
3947ec681f3Smrg{
3957ec681f3Smrg   struct vn_device *dev = vn_device_from_handle(device);
3967ec681f3Smrg
3977ec681f3Smrg   /* TODO per-device cache */
3987ec681f3Smrg   vn_call_vkGetImageSparseMemoryRequirements2(dev->instance, device, pInfo,
3997ec681f3Smrg                                               pSparseMemoryRequirementCount,
4007ec681f3Smrg                                               pSparseMemoryRequirements);
4017ec681f3Smrg}
4027ec681f3Smrg
4037ec681f3SmrgVkResult
4047ec681f3Smrgvn_BindImageMemory(VkDevice device,
4057ec681f3Smrg                   VkImage image,
4067ec681f3Smrg                   VkDeviceMemory memory,
4077ec681f3Smrg                   VkDeviceSize memoryOffset)
4087ec681f3Smrg{
4097ec681f3Smrg   struct vn_device *dev = vn_device_from_handle(device);
4107ec681f3Smrg   struct vn_device_memory *mem = vn_device_memory_from_handle(memory);
4117ec681f3Smrg
4127ec681f3Smrg   if (mem->base_memory) {
4137ec681f3Smrg      memory = vn_device_memory_to_handle(mem->base_memory);
4147ec681f3Smrg      memoryOffset += mem->base_offset;
4157ec681f3Smrg   }
4167ec681f3Smrg
4177ec681f3Smrg   vn_async_vkBindImageMemory(dev->instance, device, image, memory,
4187ec681f3Smrg                              memoryOffset);
4197ec681f3Smrg
4207ec681f3Smrg   return VK_SUCCESS;
4217ec681f3Smrg}
4227ec681f3Smrg
4237ec681f3SmrgVkResult
4247ec681f3Smrgvn_BindImageMemory2(VkDevice device,
4257ec681f3Smrg                    uint32_t bindInfoCount,
4267ec681f3Smrg                    const VkBindImageMemoryInfo *pBindInfos)
4277ec681f3Smrg{
4287ec681f3Smrg   struct vn_device *dev = vn_device_from_handle(device);
4297ec681f3Smrg   const VkAllocationCallbacks *alloc = &dev->base.base.alloc;
4307ec681f3Smrg
4317ec681f3Smrg   VkBindImageMemoryInfo *local_infos = NULL;
4327ec681f3Smrg   for (uint32_t i = 0; i < bindInfoCount; i++) {
4337ec681f3Smrg      const VkBindImageMemoryInfo *info = &pBindInfos[i];
4347ec681f3Smrg      struct vn_device_memory *mem =
4357ec681f3Smrg         vn_device_memory_from_handle(info->memory);
4367ec681f3Smrg      /* TODO handle VkBindImageMemorySwapchainInfoKHR */
4377ec681f3Smrg      if (!mem || !mem->base_memory)
4387ec681f3Smrg         continue;
4397ec681f3Smrg
4407ec681f3Smrg      if (!local_infos) {
4417ec681f3Smrg         const size_t size = sizeof(*local_infos) * bindInfoCount;
4427ec681f3Smrg         local_infos = vk_alloc(alloc, size, VN_DEFAULT_ALIGN,
4437ec681f3Smrg                                VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
4447ec681f3Smrg         if (!local_infos)
4457ec681f3Smrg            return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
4467ec681f3Smrg
4477ec681f3Smrg         memcpy(local_infos, pBindInfos, size);
4487ec681f3Smrg      }
4497ec681f3Smrg
4507ec681f3Smrg      local_infos[i].memory = vn_device_memory_to_handle(mem->base_memory);
4517ec681f3Smrg      local_infos[i].memoryOffset += mem->base_offset;
4527ec681f3Smrg   }
4537ec681f3Smrg   if (local_infos)
4547ec681f3Smrg      pBindInfos = local_infos;
4557ec681f3Smrg
4567ec681f3Smrg   vn_async_vkBindImageMemory2(dev->instance, device, bindInfoCount,
4577ec681f3Smrg                               pBindInfos);
4587ec681f3Smrg
4597ec681f3Smrg   vk_free(alloc, local_infos);
4607ec681f3Smrg
4617ec681f3Smrg   return VK_SUCCESS;
4627ec681f3Smrg}
4637ec681f3Smrg
4647ec681f3SmrgVkResult
4657ec681f3Smrgvn_GetImageDrmFormatModifierPropertiesEXT(
4667ec681f3Smrg   VkDevice device,
4677ec681f3Smrg   VkImage image,
4687ec681f3Smrg   VkImageDrmFormatModifierPropertiesEXT *pProperties)
4697ec681f3Smrg{
4707ec681f3Smrg   struct vn_device *dev = vn_device_from_handle(device);
4717ec681f3Smrg
4727ec681f3Smrg   /* TODO local cache */
4737ec681f3Smrg   return vn_call_vkGetImageDrmFormatModifierPropertiesEXT(
4747ec681f3Smrg      dev->instance, device, image, pProperties);
4757ec681f3Smrg}
4767ec681f3Smrg
4777ec681f3Smrgvoid
4787ec681f3Smrgvn_GetImageSubresourceLayout(VkDevice device,
4797ec681f3Smrg                             VkImage image,
4807ec681f3Smrg                             const VkImageSubresource *pSubresource,
4817ec681f3Smrg                             VkSubresourceLayout *pLayout)
4827ec681f3Smrg{
4837ec681f3Smrg   struct vn_device *dev = vn_device_from_handle(device);
4847ec681f3Smrg
4857ec681f3Smrg   /* TODO local cache */
4867ec681f3Smrg   vn_call_vkGetImageSubresourceLayout(dev->instance, device, image,
4877ec681f3Smrg                                       pSubresource, pLayout);
4887ec681f3Smrg}
4897ec681f3Smrg
4907ec681f3Smrg/* image view commands */
4917ec681f3Smrg
4927ec681f3SmrgVkResult
4937ec681f3Smrgvn_CreateImageView(VkDevice device,
4947ec681f3Smrg                   const VkImageViewCreateInfo *pCreateInfo,
4957ec681f3Smrg                   const VkAllocationCallbacks *pAllocator,
4967ec681f3Smrg                   VkImageView *pView)
4977ec681f3Smrg{
4987ec681f3Smrg   struct vn_device *dev = vn_device_from_handle(device);
4997ec681f3Smrg   const VkAllocationCallbacks *alloc =
5007ec681f3Smrg      pAllocator ? pAllocator : &dev->base.base.alloc;
5017ec681f3Smrg
5027ec681f3Smrg   struct vn_image_view *view =
5037ec681f3Smrg      vk_zalloc(alloc, sizeof(*view), VN_DEFAULT_ALIGN,
5047ec681f3Smrg                VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
5057ec681f3Smrg   if (!view)
5067ec681f3Smrg      return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
5077ec681f3Smrg
5087ec681f3Smrg   vn_object_base_init(&view->base, VK_OBJECT_TYPE_IMAGE_VIEW, &dev->base);
5097ec681f3Smrg   view->image = vn_image_from_handle(pCreateInfo->image);
5107ec681f3Smrg
5117ec681f3Smrg   VkImageView view_handle = vn_image_view_to_handle(view);
5127ec681f3Smrg   vn_async_vkCreateImageView(dev->instance, device, pCreateInfo, NULL,
5137ec681f3Smrg                              &view_handle);
5147ec681f3Smrg
5157ec681f3Smrg   *pView = view_handle;
5167ec681f3Smrg
5177ec681f3Smrg   return VK_SUCCESS;
5187ec681f3Smrg}
5197ec681f3Smrg
5207ec681f3Smrgvoid
5217ec681f3Smrgvn_DestroyImageView(VkDevice device,
5227ec681f3Smrg                    VkImageView imageView,
5237ec681f3Smrg                    const VkAllocationCallbacks *pAllocator)
5247ec681f3Smrg{
5257ec681f3Smrg   struct vn_device *dev = vn_device_from_handle(device);
5267ec681f3Smrg   struct vn_image_view *view = vn_image_view_from_handle(imageView);
5277ec681f3Smrg   const VkAllocationCallbacks *alloc =
5287ec681f3Smrg      pAllocator ? pAllocator : &dev->base.base.alloc;
5297ec681f3Smrg
5307ec681f3Smrg   if (!view)
5317ec681f3Smrg      return;
5327ec681f3Smrg
5337ec681f3Smrg   vn_async_vkDestroyImageView(dev->instance, device, imageView, NULL);
5347ec681f3Smrg
5357ec681f3Smrg   vn_object_base_fini(&view->base);
5367ec681f3Smrg   vk_free(alloc, view);
5377ec681f3Smrg}
5387ec681f3Smrg
5397ec681f3Smrg/* sampler commands */
5407ec681f3Smrg
5417ec681f3SmrgVkResult
5427ec681f3Smrgvn_CreateSampler(VkDevice device,
5437ec681f3Smrg                 const VkSamplerCreateInfo *pCreateInfo,
5447ec681f3Smrg                 const VkAllocationCallbacks *pAllocator,
5457ec681f3Smrg                 VkSampler *pSampler)
5467ec681f3Smrg{
5477ec681f3Smrg   struct vn_device *dev = vn_device_from_handle(device);
5487ec681f3Smrg   const VkAllocationCallbacks *alloc =
5497ec681f3Smrg      pAllocator ? pAllocator : &dev->base.base.alloc;
5507ec681f3Smrg
5517ec681f3Smrg   struct vn_sampler *sampler =
5527ec681f3Smrg      vk_zalloc(alloc, sizeof(*sampler), VN_DEFAULT_ALIGN,
5537ec681f3Smrg                VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
5547ec681f3Smrg   if (!sampler)
5557ec681f3Smrg      return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
5567ec681f3Smrg
5577ec681f3Smrg   vn_object_base_init(&sampler->base, VK_OBJECT_TYPE_SAMPLER, &dev->base);
5587ec681f3Smrg
5597ec681f3Smrg   VkSampler sampler_handle = vn_sampler_to_handle(sampler);
5607ec681f3Smrg   vn_async_vkCreateSampler(dev->instance, device, pCreateInfo, NULL,
5617ec681f3Smrg                            &sampler_handle);
5627ec681f3Smrg
5637ec681f3Smrg   *pSampler = sampler_handle;
5647ec681f3Smrg
5657ec681f3Smrg   return VK_SUCCESS;
5667ec681f3Smrg}
5677ec681f3Smrg
5687ec681f3Smrgvoid
5697ec681f3Smrgvn_DestroySampler(VkDevice device,
5707ec681f3Smrg                  VkSampler _sampler,
5717ec681f3Smrg                  const VkAllocationCallbacks *pAllocator)
5727ec681f3Smrg{
5737ec681f3Smrg   struct vn_device *dev = vn_device_from_handle(device);
5747ec681f3Smrg   struct vn_sampler *sampler = vn_sampler_from_handle(_sampler);
5757ec681f3Smrg   const VkAllocationCallbacks *alloc =
5767ec681f3Smrg      pAllocator ? pAllocator : &dev->base.base.alloc;
5777ec681f3Smrg
5787ec681f3Smrg   if (!sampler)
5797ec681f3Smrg      return;
5807ec681f3Smrg
5817ec681f3Smrg   vn_async_vkDestroySampler(dev->instance, device, _sampler, NULL);
5827ec681f3Smrg
5837ec681f3Smrg   vn_object_base_fini(&sampler->base);
5847ec681f3Smrg   vk_free(alloc, sampler);
5857ec681f3Smrg}
5867ec681f3Smrg
5877ec681f3Smrg/* sampler YCbCr conversion commands */
5887ec681f3Smrg
5897ec681f3SmrgVkResult
5907ec681f3Smrgvn_CreateSamplerYcbcrConversion(
5917ec681f3Smrg   VkDevice device,
5927ec681f3Smrg   const VkSamplerYcbcrConversionCreateInfo *pCreateInfo,
5937ec681f3Smrg   const VkAllocationCallbacks *pAllocator,
5947ec681f3Smrg   VkSamplerYcbcrConversion *pYcbcrConversion)
5957ec681f3Smrg{
5967ec681f3Smrg   struct vn_device *dev = vn_device_from_handle(device);
5977ec681f3Smrg   const VkAllocationCallbacks *alloc =
5987ec681f3Smrg      pAllocator ? pAllocator : &dev->base.base.alloc;
5997ec681f3Smrg   const VkExternalFormatANDROID *ext_info =
6007ec681f3Smrg      vk_find_struct_const(pCreateInfo->pNext, EXTERNAL_FORMAT_ANDROID);
6017ec681f3Smrg
6027ec681f3Smrg   VkSamplerYcbcrConversionCreateInfo local_info;
6037ec681f3Smrg   if (ext_info && ext_info->externalFormat) {
6047ec681f3Smrg      assert(pCreateInfo->format == VK_FORMAT_UNDEFINED);
6057ec681f3Smrg
6067ec681f3Smrg      local_info = *pCreateInfo;
6077ec681f3Smrg      local_info.format =
6087ec681f3Smrg         vn_android_drm_format_to_vk_format(ext_info->externalFormat);
6097ec681f3Smrg      local_info.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
6107ec681f3Smrg      local_info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
6117ec681f3Smrg      local_info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
6127ec681f3Smrg      local_info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
6137ec681f3Smrg      pCreateInfo = &local_info;
6147ec681f3Smrg
6157ec681f3Smrg      assert(pCreateInfo->format != VK_FORMAT_UNDEFINED);
6167ec681f3Smrg   }
6177ec681f3Smrg
6187ec681f3Smrg   struct vn_sampler_ycbcr_conversion *conv =
6197ec681f3Smrg      vk_zalloc(alloc, sizeof(*conv), VN_DEFAULT_ALIGN,
6207ec681f3Smrg                VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
6217ec681f3Smrg   if (!conv)
6227ec681f3Smrg      return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
6237ec681f3Smrg
6247ec681f3Smrg   vn_object_base_init(&conv->base, VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION,
6257ec681f3Smrg                       &dev->base);
6267ec681f3Smrg
6277ec681f3Smrg   VkSamplerYcbcrConversion conv_handle =
6287ec681f3Smrg      vn_sampler_ycbcr_conversion_to_handle(conv);
6297ec681f3Smrg   vn_async_vkCreateSamplerYcbcrConversion(dev->instance, device, pCreateInfo,
6307ec681f3Smrg                                           NULL, &conv_handle);
6317ec681f3Smrg
6327ec681f3Smrg   *pYcbcrConversion = conv_handle;
6337ec681f3Smrg
6347ec681f3Smrg   return VK_SUCCESS;
6357ec681f3Smrg}
6367ec681f3Smrg
6377ec681f3Smrgvoid
6387ec681f3Smrgvn_DestroySamplerYcbcrConversion(VkDevice device,
6397ec681f3Smrg                                 VkSamplerYcbcrConversion ycbcrConversion,
6407ec681f3Smrg                                 const VkAllocationCallbacks *pAllocator)
6417ec681f3Smrg{
6427ec681f3Smrg   struct vn_device *dev = vn_device_from_handle(device);
6437ec681f3Smrg   struct vn_sampler_ycbcr_conversion *conv =
6447ec681f3Smrg      vn_sampler_ycbcr_conversion_from_handle(ycbcrConversion);
6457ec681f3Smrg   const VkAllocationCallbacks *alloc =
6467ec681f3Smrg      pAllocator ? pAllocator : &dev->base.base.alloc;
6477ec681f3Smrg
6487ec681f3Smrg   if (!conv)
6497ec681f3Smrg      return;
6507ec681f3Smrg
6517ec681f3Smrg   vn_async_vkDestroySamplerYcbcrConversion(dev->instance, device,
6527ec681f3Smrg                                            ycbcrConversion, NULL);
6537ec681f3Smrg
6547ec681f3Smrg   vn_object_base_fini(&conv->base);
6557ec681f3Smrg   vk_free(alloc, conv);
6567ec681f3Smrg}
657