From 241585667f17cdde943bbeabf2ac2e5d61abbfd7 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Thu, 11 Jul 2024 16:01:32 -0700 Subject: [PATCH] anv: reimplement the anv_fake_nonlocal_memory workaround MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 94989b45a5ed ("anv,driconf: Add fake non device local memory WA for Total War: Warhammer 3") implemented a workaround to make Warhammer 3 work on ADL, but the game still doesn't work on LNL, which uses xe.ko, and MTL, which uses i915.ko: it still fails at launch claiming it couldn't allocate memory. So in this implementation, instead of clearing DEVICE_LOCAL_BIT we just duplicate our memory types, one having the bit and one not having. v2: - Check for VK_MAX_MEMORY_TYPES (José) - Invert the order of the memory types (José) - Fix white space issue (José) v3: - Comment our non-spec-compliance (José) - Remove useless lines (José) Link: https://gitlab.freedesktop.org/mesa/mesa/-/issues/8721 Fixes: 94989b45a5ed ("anv,driconf: Add fake non device local memory WA for Total War: Warhammer 3") Reviewed-by: José Roberto de Souza Signed-off-by: Paulo Zanoni Part-of: --- src/intel/vulkan/anv_device.c | 47 ++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/src/intel/vulkan/anv_device.c b/src/intel/vulkan/anv_device.c index 47661262f5d..1eeb31672a0 100644 --- a/src/intel/vulkan/anv_device.c +++ b/src/intel/vulkan/anv_device.c @@ -2030,6 +2030,31 @@ anv_physical_device_init_heaps(struct anv_physical_device *device, int fd) if (result != VK_SUCCESS) return result; + /* Some games (e.g., Total War: WARHAMMER III) sometimes seem to expect to + * find memory types both with and without + * VK_MEMORY_TYPE_PROPERTY_DEVICE_LOCAL_BIT. So here we duplicate all our + * memory types just to make these games happy. + * This behavior is not spec-compliant as we still only have one heap that + * is now inconsistent with some of the memory types, but the game doesn't + * seem to care about it. + */ + if (device->instance->anv_fake_nonlocal_memory && + !anv_physical_device_has_vram(device)) { + const uint32_t base_types_count = device->memory.type_count; + for (int i = 0; i < base_types_count; i++) { + if (!(device->memory.types[i].propertyFlags & + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)) + continue; + + struct anv_memory_type *new_type = + &device->memory.types[device->memory.type_count++]; + *new_type = device->memory.types[i]; + + device->memory.types[i].propertyFlags &= + ~VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + } + } + /* Replicate all non protected memory types for descriptor buffers because * we want to identify memory allocations to place them in the right memory * heap. @@ -2069,6 +2094,8 @@ anv_physical_device_init_heaps(struct anv_physical_device *device, int fd) new_type->descriptor_buffer = true; } + assert(device->memory.type_count <= VK_MAX_MEMORY_TYPES); + for (unsigned i = 0; i < device->memory.type_count; i++) { VkMemoryPropertyFlags props = device->memory.types[i].propertyFlags; if ((props & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) && @@ -2934,26 +2961,6 @@ void anv_GetPhysicalDeviceMemoryProperties( .flags = physical_device->memory.heaps[i].flags, }; } - - /* Some games (e.g. Total War: WARHAMMER III) sometimes completely refuse - * to use memory types with VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT set. - * On iGPUs we have only device-local memory, so we must hide it - * from the flags. - * - * Additionally, TW also seems to crash if a non-local but also - * non host-visible memory is present, so we should be careful which - * memory types we hide this flag from. - */ - if (physical_device->instance->anv_fake_nonlocal_memory && - !anv_physical_device_has_vram(physical_device)) { - for (uint32_t i = 0; i < physical_device->memory.type_count; i++) { - if (pMemoryProperties->memoryTypes[i].propertyFlags & - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) { - pMemoryProperties->memoryTypes[i].propertyFlags &= - ~VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; - } - } - } } static void