From 8aec37fe0c317dd7d604f768b8a1e40539984f08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Roberto=20de=20Souza?= Date: Tue, 16 Apr 2024 07:38:56 -0700 Subject: [PATCH] anv: Add support for compressed images allocation in Xe2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Xe2 replaces auxiliary surface mapping by software to compress buffers, instead it reserves part of the memory for the compression purpose. To enable compression in Xe2 it is necessary bind memory with one of the PAT indexes that has compression enabled. It is still always returning false in anv_image_is_pat_compressible() as it still needs more work before compression can be enabled but the foundation for the compressed allocation is here. Reviewed-by: Rohan Garg Signed-off-by: José Roberto de Souza Part-of: --- src/intel/vulkan/anv_device.c | 32 +++++++++++++++++---- src/intel/vulkan/anv_image.c | 49 +++++++++++++++++++++++++++++--- src/intel/vulkan/anv_private.h | 6 ++++ src/intel/vulkan/xe/anv_device.c | 21 +++++++++++--- 4 files changed, 95 insertions(+), 13 deletions(-) diff --git a/src/intel/vulkan/anv_device.c b/src/intel/vulkan/anv_device.c index 7baf73abede..6c67a85fb58 100644 --- a/src/intel/vulkan/anv_device.c +++ b/src/intel/vulkan/anv_device.c @@ -372,7 +372,12 @@ get_device_extensions(const struct anv_physical_device *device, .EXT_graphics_pipeline_library = !debug_get_bool_option("ANV_NO_GPL", false), .EXT_host_query_reset = true, .EXT_image_2d_view_of_3d = true, - .EXT_image_compression_control = device->instance->compression_control_enabled, + /* Because of Xe2 PAT selected compression and the Vulkan spec + * requirement to always return the same memory types for Images with + * same properties we can't support EXT_image_compression_control on Xe2+ + */ + .EXT_image_compression_control = device->instance->compression_control_enabled && + device->info.ver < 20, .EXT_image_robustness = true, .EXT_image_drm_format_modifier = true, .EXT_image_sliced_view_of_3d = true, @@ -2001,6 +2006,8 @@ anv_physical_device_init_heaps(struct anv_physical_device *device, int fd) break; } + assert(device->memory.type_count < ARRAY_SIZE(device->memory.types)); + if (result != VK_SUCCESS) return result; @@ -2012,17 +2019,27 @@ anv_physical_device_init_heaps(struct anv_physical_device *device, int fd) BITFIELD_RANGE(0, device->memory.type_count); device->memory.protected_mem_types = 0; device->memory.desc_buffer_mem_types = 0; + device->memory.compressed_mem_types = 0; - uint32_t base_types_count = device->memory.type_count; + const uint32_t base_types_count = device->memory.type_count; for (int i = 0; i < base_types_count; i++) { + bool skip = false; + if (device->memory.types[i].propertyFlags & VK_MEMORY_PROPERTY_PROTECTED_BIT) { device->memory.protected_mem_types |= BITFIELD_BIT(i); device->memory.default_buffer_mem_types &= (~BITFIELD_BIT(i)); - continue; + skip = true; } - assert(device->memory.type_count < ARRAY_SIZE(device->memory.types)); + if (device->memory.types[i].compressed) { + device->memory.compressed_mem_types |= BITFIELD_BIT(i); + device->memory.default_buffer_mem_types &= (~BITFIELD_BIT(i)); + skip = true; + } + + if (skip) + continue; device->memory.desc_buffer_mem_types |= BITFIELD_BIT(device->memory.type_count); @@ -4453,6 +4470,9 @@ VkResult anv_AllocateMemory( if (mem_type->propertyFlags & VK_MEMORY_PROPERTY_PROTECTED_BIT) alloc_flags |= ANV_BO_ALLOC_PROTECTED; + if (mem_type->compressed) + alloc_flags |= ANV_BO_ALLOC_COMPRESSED; + /* For now, always allocated AUX-TT aligned memory, regardless of dedicated * allocations. An application can for example, suballocate a large * VkDeviceMemory and try to bind an image created with a CCS modifier. In @@ -5657,7 +5677,9 @@ anv_device_get_pat_entry(struct anv_device *device, return &device->info->pat.writecombining; } - if ((alloc_flags & (ANV_BO_ALLOC_HOST_CACHED_COHERENT)) == ANV_BO_ALLOC_HOST_CACHED_COHERENT) + if (alloc_flags & ANV_BO_ALLOC_COMPRESSED) + return &device->info->pat.compressed; + else if ((alloc_flags & (ANV_BO_ALLOC_HOST_CACHED_COHERENT)) == ANV_BO_ALLOC_HOST_CACHED_COHERENT) return &device->info->pat.cached_coherent; else if (alloc_flags & (ANV_BO_ALLOC_EXTERNAL | ANV_BO_ALLOC_SCANOUT)) return &device->info->pat.scanout; diff --git a/src/intel/vulkan/anv_image.c b/src/intel/vulkan/anv_image.c index 28721c4474a..143aa5a76d6 100644 --- a/src/intel/vulkan/anv_image.c +++ b/src/intel/vulkan/anv_image.c @@ -1984,6 +1984,43 @@ resolve_ahw_image(struct anv_device *device, #endif } +static bool +anv_image_is_pat_compressible(struct anv_device *device, struct anv_image *image) +{ + if (INTEL_DEBUG(DEBUG_NO_CCS)) + return false; + + if (device->info->ver < 20) + return false; + + /* + * Be aware that Vulkan spec requires that Images with some properties + * always returns the same memory types, so this function also needs to + * have the same return for the same set of properties. + * + * For images created with a color format, the memoryTypeBits member is + * identical for all VkImage objects created with the same combination + * of values for the tiling member, the + * VK_IMAGE_CREATE_SPARSE_BINDING_BIT bit of the flags member, the + * VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT bit of the flags + * member, handleTypes member of VkExternalMemoryImageCreateInfo, and + * the VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT of the usage member in + * the VkImageCreateInfo structure passed to vkCreateImage. + * + * For images created with a depth/stencil format, the memoryTypeBits + * member is identical for all VkImage objects created with the same + * combination of values for the format member, the tiling member, the + * VK_IMAGE_CREATE_SPARSE_BINDING_BIT bit of the flags member, the + * VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT bit of the flags + * member, handleTypes member of VkExternalMemoryImageCreateInfo, and + * the VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT of the usage member in + * the VkImageCreateInfo structure passed to vkCreateImage. + */ + + /* TODO: check for other compression requirements and return true */ + return false; +} + void anv_image_get_memory_requirements(struct anv_device *device, struct anv_image *image, @@ -1997,10 +2034,14 @@ anv_image_get_memory_requirements(struct anv_device *device, * only if the memory type `i` in the VkPhysicalDeviceMemoryProperties * structure for the physical device is supported. */ - uint32_t memory_types = - (image->vk.create_flags & VK_IMAGE_CREATE_PROTECTED_BIT) ? - device->physical->memory.protected_mem_types : - device->physical->memory.default_buffer_mem_types; + uint32_t memory_types; + + if (image->vk.create_flags & VK_IMAGE_CREATE_PROTECTED_BIT) + memory_types = device->physical->memory.protected_mem_types; + else if (anv_image_is_pat_compressible(device, image)) + memory_types = device->physical->memory.compressed_mem_types; + else + memory_types = device->physical->memory.default_buffer_mem_types; vk_foreach_struct(ext, pMemoryRequirements->pNext) { switch (ext->sType) { diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h index 945f5ea3bd9..9f192e5db99 100644 --- a/src/intel/vulkan/anv_private.h +++ b/src/intel/vulkan/anv_private.h @@ -446,6 +446,9 @@ enum anv_bo_alloc_flags { /** For descriptor buffer pools */ ANV_BO_ALLOC_DESCRIPTOR_BUFFER_POOL = (1 << 21), + + /** Compressed buffer, only supported in Xe2+ */ + ANV_BO_ALLOC_COMPRESSED = (1 << 22), }; /** Specifies that the BO should be cached and coherent. */ @@ -943,6 +946,7 @@ struct anv_memory_type { uint32_t heapIndex; /* Whether this is the descriptor buffer memory type */ bool descriptor_buffer; + bool compressed; }; struct anv_memory_heap { @@ -1102,6 +1106,8 @@ struct anv_physical_device { uint32_t desc_buffer_mem_types; /** Mask of memory types of protected buffers/images */ uint32_t protected_mem_types; + /** Mask of memory types of compressed buffers/images */ + uint32_t compressed_mem_types; } memory; struct { diff --git a/src/intel/vulkan/xe/anv_device.c b/src/intel/vulkan/xe/anv_device.c index 9eabea31f52..97b1fb46446 100644 --- a/src/intel/vulkan/xe/anv_device.c +++ b/src/intel/vulkan/xe/anv_device.c @@ -98,18 +98,24 @@ VkResult anv_xe_physical_device_init_memory_types(struct anv_physical_device *device) { if (anv_physical_device_has_vram(device)) { - device->memory.type_count = 3; - device->memory.types[0] = (struct anv_memory_type) { + if (device->info.ver >= 20) { + device->memory.types[device->memory.type_count++] = (struct anv_memory_type) { + .propertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + .heapIndex = 0, + .compressed = true, + }; + } + device->memory.types[device->memory.type_count++] = (struct anv_memory_type) { .propertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, .heapIndex = 0, }; - device->memory.types[1] = (struct anv_memory_type) { + device->memory.types[device->memory.type_count++] = (struct anv_memory_type) { .propertyFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT, .heapIndex = 1, }; - device->memory.types[2] = (struct anv_memory_type) { + device->memory.types[device->memory.type_count++] = (struct anv_memory_type) { .propertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, @@ -142,6 +148,13 @@ anv_xe_physical_device_init_memory_types(struct anv_physical_device *device) .heapIndex = 0, }; } else { + if (device->info.ver >= 20) { + device->memory.types[device->memory.type_count++] = (struct anv_memory_type) { + .propertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + .heapIndex = 0, + .compressed = true, + }; + } device->memory.types[device->memory.type_count++] = (struct anv_memory_type) { .propertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |