venus: fix AHB image format properties query
authorYiwei Zhang <zzyiwei@chromium.org>
Sun, 23 May 2021 21:05:15 +0000 (21:05 +0000)
committerMarge Bot <eric+marge@anholt.net>
Wed, 26 May 2021 20:26:18 +0000 (20:26 +0000)
1. bail early if there's no compatiable AHB format
2. check against the corresponding drm format modifier

Signed-off-by: Yiwei Zhang <zzyiwei@chromium.org>
Reviewed-by: Chia-I Wu <olvaffe@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10960>

src/virtio/vulkan/vn_android.c
src/virtio/vulkan/vn_android.h
src/virtio/vulkan/vn_device.c

index cf7d99e..463c166 100644 (file)
@@ -867,3 +867,83 @@ vn_GetAndroidHardwareBufferPropertiesANDROID(
 
    return VK_SUCCESS;
 }
+
+static AHardwareBuffer *
+vn_android_ahb_allocate(uint32_t width,
+                        uint32_t height,
+                        uint32_t layers,
+                        uint32_t format,
+                        uint64_t usage)
+{
+   AHardwareBuffer *ahb = NULL;
+   AHardwareBuffer_Desc desc;
+   int ret = 0;
+
+   memset(&desc, 0, sizeof(desc));
+   desc.width = width;
+   desc.height = height;
+   desc.layers = layers;
+   desc.format = format;
+   desc.usage = usage;
+
+   ret = AHardwareBuffer_allocate(&desc, &ahb);
+   if (ret) {
+      /* We just log the error code here for now since the platform falsely
+       * maps all gralloc allocation failures to oom.
+       */
+      vn_log(NULL, "AHB alloc(w=%u,h=%u,l=%u,f=%u,u=%" PRIu64 ") failed(%d)",
+             width, height, layers, format, usage, ret);
+      return NULL;
+   }
+
+   return ahb;
+}
+
+bool
+vn_android_get_drm_format_modifier_info(
+   const VkPhysicalDeviceImageFormatInfo2 *format_info,
+   VkPhysicalDeviceImageDrmFormatModifierInfoEXT *out_info)
+{
+   /* To properly fill VkPhysicalDeviceImageDrmFormatModifierInfoEXT, we have
+    * to allocate an ahb to retrieve the drm format modifier. For the image
+    * sharing mode, we assume VK_SHARING_MODE_EXCLUSIVE for now.
+    */
+   AHardwareBuffer *ahb = NULL;
+   const native_handle_t *handle = NULL;
+   uint32_t format = 0;
+   uint64_t usage = 0;
+   uint32_t strides[4] = { 0, 0, 0, 0 };
+   uint32_t offsets[4] = { 0, 0, 0, 0 };
+   uint64_t format_modifier = 0;
+
+   assert(format_info->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT);
+
+   format = vn_android_ahb_format_from_vk_format(format_info->format);
+   if (!format)
+      return false;
+
+   usage = vn_android_get_ahb_usage(format_info->usage, format_info->flags);
+   ahb = vn_android_ahb_allocate(16, 16, 1, format, usage);
+   if (!ahb)
+      return false;
+
+   handle = AHardwareBuffer_getNativeHandle(ahb);
+   if (!vn_android_get_gralloc_buffer_info(handle, strides, offsets,
+                                           &format_modifier)) {
+      AHardwareBuffer_release(ahb);
+      return false;
+   }
+
+   *out_info = (VkPhysicalDeviceImageDrmFormatModifierInfoEXT){
+      .sType =
+         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT,
+      .pNext = NULL,
+      .drmFormatModifier = format_modifier,
+      .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
+      .queueFamilyIndexCount = 0,
+      .pQueueFamilyIndices = NULL,
+   };
+
+   AHardwareBuffer_release(ahb);
+   return true;
+}
index 72d0a23..fdb2b6c 100644 (file)
@@ -52,6 +52,11 @@ vn_android_image_from_anb(struct vn_device *dev,
                           const VkAllocationCallbacks *alloc,
                           struct vn_image **out_img);
 
+bool
+vn_android_get_drm_format_modifier_info(
+   const VkPhysicalDeviceImageFormatInfo2 *format_info,
+   VkPhysicalDeviceImageDrmFormatModifierInfoEXT *out_info);
+
 uint64_t
 vn_android_get_ahb_usage(const VkImageUsageFlags usage,
                          const VkImageCreateFlags flags);
@@ -88,6 +93,14 @@ vn_android_image_from_anb(UNUSED struct vn_device *dev,
    return VK_ERROR_OUT_OF_HOST_MEMORY;
 }
 
+static inline bool
+vn_android_get_drm_format_modifier_info(
+   UNUSED const VkPhysicalDeviceImageFormatInfo2 *format_info,
+   UNUSED VkPhysicalDeviceImageDrmFormatModifierInfoEXT *out_info)
+{
+   return false;
+}
+
 static inline uint64_t
 vn_android_get_ahb_usage(UNUSED const VkImageUsageFlags usage,
                          UNUSED const VkImageCreateFlags flags)
index f324329..ab38776 100644 (file)
@@ -2718,6 +2718,7 @@ struct vn_physical_device_image_format_info {
    VkPhysicalDeviceExternalImageFormatInfo external;
    VkImageFormatListCreateInfo list;
    VkImageStencilUsageCreateInfo stencil_usage;
+   VkPhysicalDeviceImageDrmFormatModifierInfoEXT modifier;
 };
 
 static const VkPhysicalDeviceImageFormatInfo2 *
@@ -2729,12 +2730,16 @@ vn_physical_device_fix_image_format_info(
    local_info->format = *info;
    VkBaseOutStructure *dst = (void *)&local_info->format;
 
+   bool use_modifier = false;
    /* we should generate deep copy functions... */
    vk_foreach_struct_const(src, info->pNext) {
       void *pnext = NULL;
       switch (src->sType) {
       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO:
          memcpy(&local_info->external, src, sizeof(local_info->external));
+         use_modifier =
+            local_info->external.handleType ==
+            VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;
          local_info->external.handleType =
             physical_dev->external_memory.renderer_handle_type;
          pnext = &local_info->external;
@@ -2758,7 +2763,15 @@ vn_physical_device_fix_image_format_info(
       }
    }
 
-   dst->pNext = NULL;
+   if (use_modifier) {
+      local_info->format.tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT;
+      if (!vn_android_get_drm_format_modifier_info(&local_info->format,
+                                                   &local_info->modifier))
+         return NULL;
+   }
+
+   dst->pNext = use_modifier ? (void *)&local_info->modifier : NULL;
+
    return &local_info->format;
 }
 
@@ -2791,6 +2804,10 @@ vn_GetPhysicalDeviceImageFormatProperties2(
       if (external_info->handleType != renderer_handle_type) {
          pImageFormatInfo = vn_physical_device_fix_image_format_info(
             physical_dev, pImageFormatInfo, &local_info);
+         if (!pImageFormatInfo) {
+            return vn_error(physical_dev->instance,
+                            VK_ERROR_FORMAT_NOT_SUPPORTED);
+         }
       }
    }