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 <zzyiwei@chromium.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24875>
This commit is contained in:
Yiwei Zhang 2023-08-24 12:26:32 -07:00 committed by Marge Bot
parent 7c98510d17
commit 72f104791d
3 changed files with 48 additions and 6 deletions

View 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;

View 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++) {
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;
}
}
for (uint32_t i = 0; i < props1->memoryTypeCount; i++) {
VkMemoryType *type = &props1->memoryTypes[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)) {
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

View 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;