diff --git a/src/vulkan/wrapper/wrapper_device_memory.c b/src/vulkan/wrapper/wrapper_device_memory.c index 216d5432760..dba787c3b1d 100644 --- a/src/vulkan/wrapper/wrapper_device_memory.c +++ b/src/vulkan/wrapper/wrapper_device_memory.c @@ -13,6 +13,8 @@ #include #include #include +#include +#include static int safe_ioctl(int fd, unsigned long request, void *arg) @@ -508,6 +510,54 @@ wrapper_device_memory_from_handle(struct wrapper_device *device, return mem; } +/* Called with resource_mutex held. This diagnostic deliberately uses stderr: + * the direct-driver path has no WRAPPER_LOG error, and the member's existing + * error-channel capture was silent. Bound output even during a retry storm. + * Bytes are cumulative successful requests, NOT live/resident memory. Counts + * cover client entrypoints only, not the wrapper's internal allocations. + */ +static void +wrapper_memory_diag(struct wrapper_device *device, + const VkMemoryAllocateInfo *info, uint32_t requested_type, + const char *backend, VkResult result) +{ + const VkPhysicalDeviceMemoryProperties *props = &device->physical->memory_properties; + const uint32_t type = info->memoryTypeIndex; + const uint32_t heap = props->memoryTypes[type].heapIndex; + const VkMemoryDedicatedAllocateInfo *dedicated = + vk_find_struct_const(info->pNext, MEMORY_DEDICATED_ALLOCATE_INFO); + if (!device->memory_diag_allocs && !device->memory_diag_failures) { + fprintf(stderr, "WRAPPER_MEM_DIAG v1 device=%p driver=%s max_allocations=%u placed=%u extension=%u\n", + (void *)device, device->physical->properties2.properties.deviceName, + device->physical->properties2.properties.limits.maxMemoryAllocationCount, + (unsigned)device->vk.enabled_features.memoryMapPlaced, + (unsigned)device->vk.enabled_extensions.EXT_map_memory_placed); + } + uint64_t n; + if (result == VK_SUCCESS) { + n = ++device->memory_diag_allocs; + device->memory_diag_total_bytes += info->allocationSize; + if (n > 8 && n % 1024) + return; + } else { + n = ++device->memory_diag_failures; + if (n > 16 && (n & (n - 1))) + return; + } + fprintf(stderr, "WRAPPER_MEM_DIAG device=%p backend=%s result=%d size=%" PRIu64 + " requested_type=%u type=%u heap=%u flags=0x%x heap_size=%" PRIu64 + " dedicated_image=%u dedicated_buffer=%u allocs=%" PRIu64 + " frees=%" PRIu64 " failures=%" PRIu64 " cumulative_bytes=%" PRIu64 "\n", + (void *)device, backend, result, (uint64_t)info->allocationSize, + requested_type, type, heap, props->memoryTypes[type].propertyFlags, + (uint64_t)props->memoryHeaps[heap].size, + (unsigned)(dedicated && dedicated->image != VK_NULL_HANDLE), + (unsigned)(dedicated && dedicated->buffer != VK_NULL_HANDLE), + device->memory_diag_allocs, device->memory_diag_frees, + device->memory_diag_failures, device->memory_diag_total_bytes); + fflush(stderr); +} + VKAPI_ATTR VkResult VKAPI_CALL wrapper_AllocateMemory(VkDevice _device, const VkMemoryAllocateInfo* pAllocateInfo, @@ -517,6 +567,8 @@ wrapper_AllocateMemory(VkDevice _device, struct wrapper_device_memory *mem; VkResult result; VkMemoryAllocateInfo coherent_allocate_info; + const uint32_t requested_type = pAllocateInfo->memoryTypeIndex; + const char *backend = "wrapper-metadata"; if (device->physical->coherent_memory_type[pAllocateInfo->memoryTypeIndex] != pAllocateInfo->memoryTypeIndex) { @@ -598,16 +650,19 @@ wrapper_AllocateMemory(VkDevice _device, } if (strstr(device->physical->resource_type, "ahb")) { + backend = "ahb"; WRAPPER_LOG(info, "Using AHardwareBuffer memory backend"); result = wrapper_allocate_memory_ahardware_buffer(device, &memory_allocate_info, pAllocator, &mem->dispatch_handle, &mem->ahardware_buffer); } else if (strstr(device->physical->resource_type, "dmabuf")) { + backend = "dmabuf"; WRAPPER_LOG(info, "Using DMABUF memory backend"); result = wrapper_allocate_memory_dmaheap(device, &memory_allocate_info, pAllocator, &mem->dispatch_handle, &mem->fd); } else if (strstr(device->physical->resource_type, "opaque")) { + backend = "opaque-fd"; WRAPPER_LOG(info, "Using opaque fd memory backend"); result = wrapper_allocate_memory_opaque_fd(device, &memory_allocate_info, pAllocator, &mem->dispatch_handle, &mem->fd); @@ -617,17 +672,20 @@ wrapper_AllocateMemory(VkDevice _device, result = VK_ERROR_INVALID_EXTERNAL_HANDLE; #define VALID_HANDLE(type) (valid_handle_types == 0 || (type & valid_handle_types) != 0) if (VALID_HANDLE(VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT)) { + backend = "auto-dmabuf"; result = wrapper_allocate_memory_dmaheap(device, &memory_allocate_info, pAllocator, &mem->dispatch_handle, &mem->fd); } if (result != VK_SUCCESS && VALID_HANDLE(VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)) { + backend = "auto-ahb"; wrapper_device_memory_reset(mem); result = wrapper_allocate_memory_ahardware_buffer(device, &memory_allocate_info, pAllocator, &mem->dispatch_handle, &mem->ahardware_buffer); } if (result != VK_SUCCESS && VALID_HANDLE(VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT)) { + backend = "auto-opaque-fd"; wrapper_device_memory_reset(mem); result = wrapper_allocate_memory_opaque_fd(device, &memory_allocate_info, pAllocator, &mem->dispatch_handle, &mem->fd); @@ -660,12 +718,16 @@ wrapper_AllocateMemory(VkDevice _device, } out: + wrapper_memory_diag(device, pAllocateInfo, requested_type, backend, result); simple_mtx_unlock(&device->resource_mutex); return result; fallback: result = device->dispatch_table.AllocateMemory(device->dispatch_handle, pAllocateInfo, pAllocator, pMemory); + simple_mtx_lock(&device->resource_mutex); + wrapper_memory_diag(device, pAllocateInfo, requested_type, "direct-driver", result); + simple_mtx_unlock(&device->resource_mutex); if (result == VK_SUCCESS && !(property_flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)) { simple_mtx_lock(&device->resource_mutex); _mesa_hash_table_u64_insert(device->device_only_memory, (uint64_t)*pMemory, device); @@ -690,6 +752,12 @@ wrapper_FreeMemory(VkDevice _device, VkDeviceMemory _memory, VK_FROM_HANDLE(wrapper_device, device, _device); struct wrapper_device_memory *mem; + if (_memory != VK_NULL_HANDLE) { + simple_mtx_lock(&device->resource_mutex); + device->memory_diag_frees++; + simple_mtx_unlock(&device->resource_mutex); + } + mem = wrapper_device_memory_from_handle(device, _memory); if (mem) { mem->alloc = pAllocator; diff --git a/src/vulkan/wrapper/wrapper_private.h b/src/vulkan/wrapper/wrapper_private.h index d87b019ba39..f2a8fc30e88 100644 --- a/src/vulkan/wrapper/wrapper_private.h +++ b/src/vulkan/wrapper/wrapper_private.h @@ -93,6 +93,9 @@ struct wrapper_device { struct list_head fence_list; struct hash_table_u64 *buffer_table; struct hash_table_u64 *device_only_memory; /* allocations the host cannot map */ + /* Allocation diagnostic counters, protected by resource_mutex. */ + uint64_t memory_diag_allocs, memory_diag_frees, memory_diag_failures; + uint64_t memory_diag_total_bytes; struct hash_table_u64 *image_table; struct hash_table_u64 *image_view_table; struct hash_table_u64 *imageless_fb_table;