From 1f0c8560440e8e62ffef2fa4dec3d3d36b71ca65 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: (cherry picked from commit 241585667f17cdde943bbeabf2ac2e5d61abbfd7) --- .pick_status.json | 2 +- src/intel/vulkan/anv_device.c | 47 ++++++++++++++++++++--------------- 2 files changed, 28 insertions(+), 21 deletions(-) diff --git a/.pick_status.json b/.pick_status.json index 7e91f1bb6b7..cc044e5e788 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -264,7 +264,7 @@ "description": "anv: reimplement the anv_fake_nonlocal_memory workaround", "nominated": true, "nomination_type": 1, - "resolution": 0, + "resolution": 1, "main_sha": null, "because_sha": "94989b45a5ed91088777f9be100c0ceba474ce52", "notes": null diff --git a/src/intel/vulkan/anv_device.c b/src/intel/vulkan/anv_device.c index 2e4e20f0251..220841ced73 100644 --- a/src/intel/vulkan/anv_device.c +++ b/src/intel/vulkan/anv_device.c @@ -1946,6 +1946,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. @@ -1975,6 +2000,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) && @@ -2863,26 +2890,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