From 72f104791d1547a6ad88cec2d9244ae48fe56c68 Mon Sep 17 00:00:00 2001 From: Yiwei Zhang Date: Thu, 24 Aug 2023 12:26:32 -0700 Subject: [PATCH] venus: expose at least one cached memory type 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 Part-of: --- src/virtio/vulkan/vn_device_memory.c | 9 +++++++ src/virtio/vulkan/vn_physical_device.c | 43 +++++++++++++++++++++++++++++----- src/virtio/vulkan/vn_physical_device.h | 2 ++ 3 files changed, 48 insertions(+), 6 deletions(-) diff --git a/src/virtio/vulkan/vn_device_memory.c b/src/virtio/vulkan/vn_device_memory.c index 39789b1..51659c9 100644 --- a/src/virtio/vulkan/vn_device_memory.c +++ b/src/virtio/vulkan/vn_device_memory.c @@ -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; diff --git a/src/virtio/vulkan/vn_physical_device.c b/src/virtio/vulkan/vn_physical_device.c index 1e78364..a0a98ad 100644 --- a/src/virtio/vulkan/vn_physical_device.c +++ b/src/virtio/vulkan/vn_physical_device.c @@ -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 diff --git a/src/virtio/vulkan/vn_physical_device.h b/src/virtio/vulkan/vn_physical_device.h index d77cd85..af1f4fb 100644 --- a/src/virtio/vulkan/vn_physical_device.h +++ b/src/virtio/vulkan/vn_physical_device.h @@ -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; -- 2.7.4