venus: expose at least one cached memory type
authorYiwei Zhang <zzyiwei@chromium.org>
Thu, 24 Aug 2023 19:26:32 +0000 (12:26 -0700)
committerMarge Bot <emma+marge@anholt.net>
Mon, 28 Aug 2023 18:21:48 +0000 (18:21 +0000)
Kernel makes every mapping coherent. If a memory type is truly
incoherent, it's better to remove the host-visible flag than silently
making it coherent. However, for app compatibility purpose, when
coherent-cached memory type is unavailable, we emulate the first cached
memory type with the first coherent memory type.

Signed-off-by: Yiwei Zhang <zzyiwei@chromium.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24875>

src/virtio/vulkan/vn_device_memory.c
src/virtio/vulkan/vn_physical_device.c
src/virtio/vulkan/vn_physical_device.h

index 39789b1..51659c9 100644 (file)
@@ -507,6 +507,15 @@ vn_AllocateMemory(VkDevice device,
    const VkAllocationCallbacks *alloc =
       pAllocator ? pAllocator : &dev->base.base.alloc;
 
+   /* see vn_physical_device_init_memory_properties */
+   VkMemoryAllocateInfo local_info;
+   if (pAllocateInfo->memoryTypeIndex ==
+       dev->physical_device->incoherent_cached) {
+      local_info = *pAllocateInfo;
+      local_info.memoryTypeIndex = dev->physical_device->coherent_uncached;
+      pAllocateInfo = &local_info;
+   }
+
    const VkExportMemoryAllocateInfo *export_info = NULL;
    const VkImportAndroidHardwareBufferInfoANDROID *import_ahb_info = NULL;
    const VkImportMemoryFdInfoKHR *import_fd_info = NULL;
index 1e78364..a0a98ad 100644 (file)
@@ -715,18 +715,49 @@ vn_physical_device_init_memory_properties(
    vn_call_vkGetPhysicalDeviceMemoryProperties2(
       instance, vn_physical_device_to_handle(physical_dev), props2);
 
+   /* Kernel makes every mapping coherent. If a memory type is truly
+    * incoherent, it's better to remove the host-visible flag than silently
+    * making it coherent. However, for app compatibility purpose, when
+    * coherent-cached memory type is unavailable, we emulate the first cached
+    * memory type with the first coherent memory type.
+    */
+   uint32_t coherent_uncached = VK_MAX_MEMORY_TYPES;
+   uint32_t incoherent_cached = VK_MAX_MEMORY_TYPES;
+
    for (uint32_t i = 0; i < props1->memoryTypeCount; i++) {
-      VkMemoryType *type = &props1->memoryTypes[i];
+      const VkMemoryPropertyFlags flags =
+         props1->memoryTypes[i].propertyFlags;
+      const bool coherent = flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
+      const bool cached = flags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
+      if (coherent && cached) {
+         coherent_uncached = VK_MAX_MEMORY_TYPES;
+         incoherent_cached = VK_MAX_MEMORY_TYPES;
+         break;
+      } else if (coherent && coherent_uncached == VK_MAX_MEMORY_TYPES) {
+         coherent_uncached = i;
+      } else if (cached && incoherent_cached == VK_MAX_MEMORY_TYPES) {
+         incoherent_cached = i;
+      }
+   }
 
-      /* Kernel makes every mapping coherent.  If a memory type is truly
-       * incoherent, it's better to remove the host-visible flag than silently
-       * making it coherent.
-       */
-      if (!(type->propertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
+   for (uint32_t i = 0; i < props1->memoryTypeCount; i++) {
+      VkMemoryType *type = &props1->memoryTypes[i];
+      if (i == incoherent_cached) {
+         /* Only get here if no coherent+cached type is available, and the
+          * spec guarantees that there is at least one coherent type, so it
+          * must be coherent+uncached, hence the index is always valid.
+          */
+         assert(coherent_uncached < props1->memoryTypeCount);
+         type->heapIndex = props1->memoryTypes[coherent_uncached].heapIndex;
+      } else if (!(type->propertyFlags &
+                   VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
          type->propertyFlags &= ~(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
                                   VK_MEMORY_PROPERTY_HOST_CACHED_BIT);
       }
    }
+
+   physical_dev->coherent_uncached = coherent_uncached;
+   physical_dev->incoherent_cached = incoherent_cached;
 }
 
 static void
index d77cd85..af1f4fb 100644 (file)
@@ -75,6 +75,8 @@ struct vn_physical_device {
    bool sparse_binding_disabled;
 
    VkPhysicalDeviceMemoryProperties2 memory_properties;
+   uint32_t coherent_uncached;
+   uint32_t incoherent_cached;
 
    struct {
       VkExternalMemoryHandleTypeFlagBits renderer_handle_type;