diff --git a/src/intel/vulkan/anv_device.c b/src/intel/vulkan/anv_device.c index 312ef930927..43beaf847f1 100644 --- a/src/intel/vulkan/anv_device.c +++ b/src/intel/vulkan/anv_device.c @@ -333,6 +333,7 @@ get_device_extensions(const struct anv_physical_device *device, .EXT_depth_range_unrestricted = device->info.ver >= 20, .EXT_depth_clip_enable = true, .EXT_descriptor_indexing = true, + .EXT_device_memory_report = true, #ifdef VK_USE_PLATFORM_DISPLAY_KHR .EXT_display_control = true, #endif @@ -632,6 +633,9 @@ get_features(const struct anv_physical_device *pdevice, /* VK_EXT_global_priority_query */ .globalPriorityQuery = true, + /* VK_EXT_device_memory_report */ + .deviceMemoryReport = true, + /* VK_EXT_graphics_pipeline_library */ .graphicsPipelineLibrary = pdevice->vk.supported_extensions.EXT_graphics_pipeline_library, @@ -3142,6 +3146,10 @@ VkResult anv_CreateDevice( if (result != VK_SUCCESS) goto fail_alloc; + anv_device_memory_report_init(device, pCreateInfo); + if (result != VK_SUCCESS) + goto fail_device; + if (INTEL_DEBUG(DEBUG_BATCH | DEBUG_BATCH_STATS)) { for (unsigned i = 0; i < physical_device->queue.family_count; i++) { struct intel_batch_decode_ctx *decoder = &device->decoder[i]; @@ -3169,7 +3177,7 @@ VkResult anv_CreateDevice( device->fd = open(physical_device->path, O_RDWR | O_CLOEXEC); if (device->fd == -1) { result = vk_error(device, VK_ERROR_INITIALIZATION_FAILED); - goto fail_device; + goto fail_memory_report; } switch (device->info->kmd_type) { @@ -3727,6 +3735,8 @@ VkResult anv_CreateDevice( anv_device_destroy_context_or_vm(device); fail_fd: close(device->fd); + fail_memory_report: + anv_device_memory_report_finish(device); fail_device: vk_device_finish(&device->vk); fail_alloc: @@ -3853,6 +3863,7 @@ void anv_DestroyDevice( close(device->fd); + anv_device_memory_report_finish(device); vk_device_finish(&device->vk); vk_free(&device->vk.alloc, device); } @@ -3965,6 +3976,34 @@ anv_vma_free(struct anv_device *device, pthread_mutex_unlock(&device->vma_mutex); } +static void +anv_device_memory_emit_report(struct anv_device *dev, + struct anv_device_memory *mem, + bool is_alloc, + VkResult result) +{ + if (likely(!dev->memory_reports)) + return; + + const struct vk_device_memory *mem_vk = &mem->vk; + VkDeviceMemoryReportEventTypeEXT event_type; + if (result != VK_SUCCESS) { + event_type = VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_ALLOCATION_FAILED_EXT; + } else if (is_alloc) { + event_type = mem_vk->import_handle_type + ? VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_IMPORT_EXT + : VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_ALLOCATE_EXT; + } else { + event_type = mem_vk->import_handle_type + ? VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_UNIMPORT_EXT + : VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_FREE_EXT; + } + + anv_device_emit_device_memory_report(dev, event_type, mem->bo->gem_handle, mem_vk->size, + VK_OBJECT_TYPE_DEVICE_MEMORY, + (uint64_t)anv_device_memory_to_handle(mem), mem->type->heapIndex); +} + VkResult anv_AllocateMemory( VkDevice _device, const VkMemoryAllocateInfo* pAllocateInfo, @@ -4223,10 +4262,12 @@ VkResult anv_AllocateMemory( pthread_mutex_unlock(&device->mutex); *pMem = anv_device_memory_to_handle(mem); + anv_device_memory_emit_report(device, mem, true, VK_SUCCESS); return VK_SUCCESS; fail: + anv_device_memory_emit_report(device, mem, true, VK_ERROR_OUT_OF_HOST_MEMORY); vk_device_memory_destroy(&device->vk, pAllocator, &mem->vk); return result; @@ -4325,6 +4366,8 @@ void anv_FreeMemory( p_atomic_add(&device->physical->memory.heaps[mem->type->heapIndex].used, -mem->bo->size); + anv_device_memory_emit_report(device, mem, false, VK_SUCCESS); + anv_device_release_bo(device, mem->bo); vk_device_memory_destroy(&device->vk, pAllocator, &mem->vk); diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h index 74442f212c4..62542b751f7 100644 --- a/src/intel/vulkan/anv_private.h +++ b/src/intel/vulkan/anv_private.h @@ -1637,6 +1637,11 @@ struct anv_trtt_batch_bo { struct list_head link; }; +struct anv_device_memory_report { + PFN_vkDeviceMemoryReportCallbackEXT callback; + void *data; +}; + struct anv_device { struct vk_device vk; @@ -1865,8 +1870,82 @@ struct anv_device { bool using_sparse; struct anv_device_astc_emu astc_emu; + + struct anv_device_memory_report *memory_reports; + uint32_t memory_report_count; }; +static VkResult +anv_device_memory_report_init(struct anv_device *dev, + const VkDeviceCreateInfo *create_info) +{ + const struct vk_features *app_feats = &dev->vk.enabled_features; + if (!app_feats->deviceMemoryReport) + return VK_SUCCESS; + + uint32_t count = 0; + vk_foreach_struct_const(pnext, create_info->pNext) { + if (pnext->sType == + VK_STRUCTURE_TYPE_DEVICE_DEVICE_MEMORY_REPORT_CREATE_INFO_EXT) + count++; + } + + struct anv_device_memory_report *mem_reports = NULL; + if (count) { + mem_reports = + vk_alloc(&dev->vk.alloc, sizeof(*mem_reports) * count, + 8, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); + if (!mem_reports) + return VK_ERROR_OUT_OF_HOST_MEMORY; + } + + count = 0; + vk_foreach_struct_const(pnext, create_info->pNext) { + if (pnext->sType == + VK_STRUCTURE_TYPE_DEVICE_DEVICE_MEMORY_REPORT_CREATE_INFO_EXT) { + const struct VkDeviceDeviceMemoryReportCreateInfoEXT *report = + (void *)pnext; + mem_reports[count].callback = report->pfnUserCallback; + mem_reports[count].data = report->pUserData; + count++; + } + } + + dev->memory_report_count = count; + dev->memory_reports = mem_reports; + + return VK_SUCCESS; +} + +static inline void +anv_device_memory_report_finish(struct anv_device *dev) +{ + vk_free(&dev->vk.alloc, dev->memory_reports); +} + +static inline void +anv_device_emit_device_memory_report(struct anv_device *dev, + VkDeviceMemoryReportEventTypeEXT type, + uint64_t mem_obj_id, + VkDeviceSize size, + VkObjectType obj_type, + uint64_t obj_handle, + uint32_t heap_index) +{ + assert(dev->memory_reports); + const VkDeviceMemoryReportCallbackDataEXT report = { + .sType = VK_STRUCTURE_TYPE_DEVICE_MEMORY_REPORT_CALLBACK_DATA_EXT, + .type = type, + .memoryObjectId = mem_obj_id, + .size = size, + .objectType = obj_type, + .objectHandle = obj_handle, + .heapIndex = heap_index, + }; + for (uint32_t i = 0; i < dev->memory_report_count; i++) + dev->memory_reports[i].callback(&report, dev->memory_reports[i].data); +} + static inline uint32_t anv_get_first_render_queue_index(struct anv_physical_device *pdevice) {