diff --git a/layersvt/device_memory_report/device_memory_report.cpp b/layersvt/device_memory_report/device_memory_report.cpp index dd915f648c..b59dfc98bd 100644 --- a/layersvt/device_memory_report/device_memory_report.cpp +++ b/layersvt/device_memory_report/device_memory_report.cpp @@ -182,8 +182,11 @@ void DeviceMemoryReport::UpdateAllocationUnboundCounter(const AllocationKey& key std::vector> intervals; intervals.reserve(allocation.sub_allocations.size()); for (const auto& suballocation : allocation.sub_allocations) { - if (suballocation.size > 0) { - VkDeviceSize end = (suballocation.offset + suballocation.size < suballocation.offset) ? UINT64_MAX : (suballocation.offset + suballocation.size); + // Only the part of a binding that lies within the allocation is bound memory of it; an + // out-of-range binding must not hide unbound bytes. Clamping here, not at bind time, means + // bindings recorded against a placeholder (total_size == 0) are counted once the size is known. + if (suballocation.size > 0 && suballocation.offset < allocation.total_size) { + VkDeviceSize end = suballocation.offset + std::min(suballocation.size, allocation.total_size - suballocation.offset); intervals.emplace_back(suballocation.offset, end); } } @@ -208,16 +211,16 @@ void DeviceMemoryReport::UpdateAllocationUnboundCounter(const AllocationKey& key bound_size += (current_end - current_start); } - uint64_t new_unbound = (allocation.total_size > bound_size) ? (allocation.total_size - bound_size) : 0; + // Intervals are clamped to the allocation, so bound_size never exceeds total_size. + uint64_t new_unbound = allocation.total_size - bound_size; const char* cluster_name = allocation.is_driver ? "driver" : "unbound_memory"; if (allocation.is_driver && (allocation.object_type == VK_OBJECT_TYPE_IMAGE || allocation.object_type == VK_OBJECT_TYPE_BUFFER)) { - auto res_it = resources_.find(allocation.object_handle); - const bool expected_is_image = (allocation.object_type == VK_OBJECT_TYPE_IMAGE); + auto res_it = resources_.find({allocation.object_type, allocation.object_handle}); // If the memory object has an associated resource of the matching type, use it as the track name. - if (res_it != resources_.end() && res_it->second.is_image == expected_is_image) { + if (res_it != resources_.end()) { cluster_name = res_it->second.GetCluster(allocation.mem_flags); } } @@ -247,6 +250,7 @@ struct AllocationTraceEvent { uint64_t memory_object_id; VkDeviceSize size; VkDeviceSize offset; + VkObjectType object_type; uint64_t object_handle; const char* memory_type; }; @@ -258,6 +262,7 @@ void EmitAllocationTraceEvent(const AllocationTraceEvent& event) { "memory_object_id", event.memory_object_id, "size", static_cast(event.size), "offset", static_cast(event.offset), + "object_type", static_cast(event.object_type), "object_handle", event.object_handle, "memory_type", event.memory_type); } @@ -281,28 +286,25 @@ void EmitDebugObjectName(VkObjectType object_type, uint64_t object_handle, std:: } // namespace -void DeviceMemoryReport::RemoveResourceBinding(uint64_t resource_handle) { - auto mem_it = resource_to_memory_map_.find(resource_handle); - if (mem_it == resource_to_memory_map_.end()) return; +void DeviceMemoryReport::RemoveResourceBinding(const ObjectKey& resource_key, Resource& resource) { + if (resource.bound_memory == 0) return; - uint64_t memory_handle = mem_it->second; - resource_to_memory_map_.erase(mem_it); + const uint64_t memory_handle = resource.bound_memory; + resource.bound_memory = 0; auto allocation_it = memory_allocations_.find(AllocationKey::App(memory_handle)); if (allocation_it == memory_allocations_.end()) return; auto& allocation = allocation_it->second; - auto resource_iterator = resources_.find(resource_handle); - bool is_image = (resource_iterator != resources_.end()) ? resource_iterator->second.is_image : false; - const char* cluster_name = (resource_iterator != resources_.end()) - ? resource_iterator->second.GetCluster(allocation.mem_flags) - : "unbound_memory"; + const auto& [object_type, object_handle] = resource_key; + bool is_image = (object_type == VK_OBJECT_TYPE_IMAGE); + const char* cluster_name = resource.GetCluster(allocation.mem_flags); auto& suballocations = allocation.sub_allocations; - // Search by resource handle to identify which specific suballocation to remove, + // Search by resource key to identify which specific suballocation to remove, // since a single memory block can have multiple resources bound to it. for (auto it = suballocations.begin(); it != suballocations.end(); ++it) { - if (it->resource_handle == resource_handle) { + if (it->object_type == object_type && it->resource_handle == object_handle) { VkDeviceSize suballocation_size = it->size; VkDeviceSize suballocation_offset = it->offset; SubtractCounterBytes(it->usage_track, suballocation_size); @@ -315,7 +317,8 @@ void DeviceMemoryReport::RemoveResourceBinding(uint64_t resource_handle) { .memory_object_id = memory_handle, .size = suballocation_size, .offset = suballocation_offset, - .object_handle = resource_handle, + .object_type = object_type, + .object_handle = object_handle, .memory_type = cluster_name, }); break; @@ -323,13 +326,14 @@ void DeviceMemoryReport::RemoveResourceBinding(uint64_t resource_handle) { } } -void DeviceMemoryReport::BindResourceMemory(uint64_t resource_handle, uint64_t memory_handle, VkDeviceSize memory_offset) { +void DeviceMemoryReport::BindResourceMemory(VkObjectType object_type, uint64_t resource_handle, uint64_t memory_handle, VkDeviceSize memory_offset) { std::lock_guard lock(counter_mutex_); - auto res_it = resources_.find(resource_handle); + const ObjectKey resource_key = {object_type, resource_handle}; + auto res_it = resources_.find(resource_key); if (res_it == resources_.end() || res_it->second.size == 0) return; // If the same resource handle is passed more than once, remove stale bindings first. - RemoveResourceBinding(resource_handle); + RemoveResourceBinding(resource_key, res_it->second); const AllocationKey key = AllocationKey::App(memory_handle); auto& allocation = memory_allocations_[key]; @@ -339,14 +343,14 @@ void DeviceMemoryReport::BindResourceMemory(uint64_t resource_handle, uint64_t m // Suballocations represent individual resources (like buffers or images) that are bound // to specific offset regions within a single large memory allocation. // We add a record here to track this specific resource's footprint within the larger memory block. - allocation.sub_allocations.push_back({ resource_handle, memory_offset, res_size, new_usage_track }); - resource_to_memory_map_[resource_handle] = memory_handle; + allocation.sub_allocations.push_back({ object_type, resource_handle, memory_offset, res_size, new_usage_track }); + res_it->second.bound_memory = memory_handle; // Each distinct virtual resource handle adds its virtual size to its specific category track upon binding. AddCounterBytes(new_usage_track, res_size); UpdateAllocationUnboundCounter(key); - bool is_image = res_it->second.is_image; + bool is_image = (object_type == VK_OBJECT_TYPE_IMAGE); const char* cluster_name = res_it->second.GetCluster(allocation.mem_flags); EmitAllocationTraceEvent({ .operation = "BIND", @@ -354,17 +358,18 @@ void DeviceMemoryReport::BindResourceMemory(uint64_t resource_handle, uint64_t m .memory_object_id = memory_handle, .size = res_size, .offset = memory_offset, + .object_type = object_type, .object_handle = resource_handle, .memory_type = cluster_name, }); } void DeviceMemoryReport::OnBindBufferMemory(uint64_t buffer_handle, uint64_t memory_handle, VkDeviceSize memory_offset) { - BindResourceMemory(buffer_handle, memory_handle, memory_offset); + BindResourceMemory(VK_OBJECT_TYPE_BUFFER, buffer_handle, memory_handle, memory_offset); } void DeviceMemoryReport::OnBindImageMemory(uint64_t image_handle, uint64_t memory_handle, VkDeviceSize memory_offset) { - BindResourceMemory(image_handle, memory_handle, memory_offset); + BindResourceMemory(VK_OBJECT_TYPE_IMAGE, image_handle, memory_handle, memory_offset); } void DeviceMemoryReport::RemoveAllocationTracking(const AllocationKey& key) { @@ -374,21 +379,23 @@ void DeviceMemoryReport::RemoveAllocationTracking(const AllocationKey& key) { auto& allocation = allocation_it->second; for (const auto& suballocation : allocation.sub_allocations) { SubtractCounterBytes(suballocation.usage_track, suballocation.size); - auto resource_iterator = resources_.find(suballocation.resource_handle); - bool is_image = (resource_iterator != resources_.end()) ? resource_iterator->second.is_image : false; - const char* cluster_name = (resource_iterator != resources_.end()) - ? resource_iterator->second.GetCluster(allocation.mem_flags) - : "unbound_memory"; + auto resource_iterator = resources_.find({suballocation.object_type, suballocation.resource_handle}); + bool is_image = (suballocation.object_type == VK_OBJECT_TYPE_IMAGE); + const char* cluster_name = "unbound_memory"; + if (resource_iterator != resources_.end()) { + cluster_name = resource_iterator->second.GetCluster(allocation.mem_flags); + resource_iterator->second.bound_memory = 0; + } EmitAllocationTraceEvent({ .operation = "DESTROY", .source = is_image ? "IMAGE" : "BUFFER", .memory_object_id = key.id, .size = suballocation.size, .offset = suballocation.offset, + .object_type = suballocation.object_type, .object_handle = suballocation.resource_handle, .memory_type = cluster_name, }); - resource_to_memory_map_.erase(suballocation.resource_handle); } if (allocation.applied_unbound_bytes > 0) { SubtractCounterBytes(allocation.unbound_usage_track, allocation.applied_unbound_bytes); @@ -396,14 +403,16 @@ void DeviceMemoryReport::RemoveAllocationTracking(const AllocationKey& key) { memory_allocations_.erase(allocation_it); } -void DeviceMemoryReport::OnRecordResourceSize(uint64_t resource_handle, VkDeviceSize size) { +void DeviceMemoryReport::OnRecordResourceSize(VkObjectType object_type, uint64_t resource_handle, VkDeviceSize size) { std::lock_guard lock(counter_mutex_); - resources_[resource_handle].size = size; + auto& res = resources_[{object_type, resource_handle}]; + res.is_image = (object_type == VK_OBJECT_TYPE_IMAGE); + res.size = size; } -VkDeviceSize DeviceMemoryReport::GetRecordedResourceSize(uint64_t resource_handle) { +VkDeviceSize DeviceMemoryReport::GetRecordedResourceSize(VkObjectType object_type, uint64_t resource_handle) { std::lock_guard lock(counter_mutex_); - auto it = resources_.find(resource_handle); + auto it = resources_.find({object_type, resource_handle}); return it != resources_.end() ? it->second.size : 0; } @@ -419,7 +428,6 @@ void DeviceMemoryReport::Reset() { has_callback_map_.clear(); device_memory_properties_map_.clear(); resources_.clear(); - resource_to_memory_map_.clear(); memory_allocations_.clear(); usage_memory_bytes_.clear(); debug_object_names_.clear(); @@ -445,6 +453,7 @@ void DeviceMemoryReport::ReattributeDriverAllocations(uint64_t object_handle, Vk .memory_object_id = key.id, .size = allocation.total_size, .offset = 0, + .object_type = allocation.object_type, .object_handle = allocation.object_handle, .memory_type = old_cluster_name, }); @@ -454,6 +463,7 @@ void DeviceMemoryReport::ReattributeDriverAllocations(uint64_t object_handle, Vk .memory_object_id = key.id, .size = allocation.total_size, .offset = 0, + .object_type = allocation.object_type, .object_handle = allocation.object_handle, .memory_type = allocation.cluster_name, }); @@ -462,7 +472,7 @@ void DeviceMemoryReport::ReattributeDriverAllocations(uint64_t object_handle, Vk void DeviceMemoryReport::OnCreateImage(uint64_t image_handle, VkImageUsageFlags usage) { std::lock_guard lock(counter_mutex_); - auto& res = resources_[image_handle]; + auto& res = resources_[{VK_OBJECT_TYPE_IMAGE, image_handle}]; res.is_image = true; res.image_usage = usage; ReattributeDriverAllocations(image_handle, VK_OBJECT_TYPE_IMAGE); @@ -470,7 +480,7 @@ void DeviceMemoryReport::OnCreateImage(uint64_t image_handle, VkImageUsageFlags void DeviceMemoryReport::OnCreateBuffer(uint64_t buffer_handle, VkBufferUsageFlags usage, VkDeviceSize size) { std::lock_guard lock(counter_mutex_); - auto& res = resources_[buffer_handle]; + auto& res = resources_[{VK_OBJECT_TYPE_BUFFER, buffer_handle}]; res.is_image = false; res.buffer_usage = usage; res.size = size; @@ -479,8 +489,11 @@ void DeviceMemoryReport::OnCreateBuffer(uint64_t buffer_handle, VkBufferUsageFla void DeviceMemoryReport::OnDestroyObject(uint64_t object_handle, VkObjectType object_type) { std::lock_guard lock(counter_mutex_); - RemoveResourceBinding(object_handle); - resources_.erase(object_handle); + auto res_it = resources_.find({object_type, object_handle}); + if (res_it != resources_.end()) { + RemoveResourceBinding(res_it->first, res_it->second); + resources_.erase(res_it); + } if (debug_object_names_.erase(std::make_pair(object_type, object_handle)) > 0) { EmitDebugObjectName(object_type, object_handle, ""); } @@ -570,13 +583,14 @@ void DeviceMemoryReport::DumpCurrentCountersAndAllocations() { .memory_object_id = memory_handle, .size = allocation.total_size, .offset = 0, + .object_type = allocation.object_type, .object_handle = allocation.object_handle, .memory_type = memory_type, }); for (const auto& suballocation : allocation.sub_allocations) { - auto resource_iterator = resources_.find(suballocation.resource_handle); - bool is_image = (resource_iterator != resources_.end()) ? resource_iterator->second.is_image : false; + auto resource_iterator = resources_.find({suballocation.object_type, suballocation.resource_handle}); + bool is_image = (suballocation.object_type == VK_OBJECT_TYPE_IMAGE); const char* cluster_name = (resource_iterator != resources_.end()) ? resource_iterator->second.GetCluster(allocation.mem_flags) : "unbound_memory"; @@ -587,6 +601,7 @@ void DeviceMemoryReport::DumpCurrentCountersAndAllocations() { .memory_object_id = memory_handle, .size = suballocation.size, .offset = suballocation.offset, + .object_type = suballocation.object_type, .object_handle = suballocation.resource_handle, .memory_type = cluster_name, }); @@ -614,6 +629,7 @@ void DeviceMemoryReport::OnMemoryReportEvent(const VkDeviceMemoryReportCallbackD const char* operation_name = nullptr; const char* memory_type = "unbound_memory"; VkDeviceSize event_size = pCallbackData->size; + VkObjectType event_object_type = pCallbackData->objectType; uint64_t event_object_handle = pCallbackData->objectHandle; if (pCallbackData->type == VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_ALLOCATE_EXT || pCallbackData->type == VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_IMPORT_EXT) { @@ -626,6 +642,7 @@ void DeviceMemoryReport::OnMemoryReportEvent(const VkDeviceMemoryReportCallbackD const MemoryAllocation& stale = existing_it->second; const char* stale_memory_type = is_driver ? stale.cluster_name : "unbound_memory"; const VkDeviceSize stale_size = stale.total_size; + const VkObjectType stale_object_type = stale.object_type; const uint64_t stale_object_handle = stale.object_handle; RemoveAllocationTracking(key); EmitAllocationTraceEvent({ @@ -634,6 +651,7 @@ void DeviceMemoryReport::OnMemoryReportEvent(const VkDeviceMemoryReportCallbackD .memory_object_id = key.id, .size = stale_size, .offset = 0, + .object_type = stale_object_type, .object_handle = stale_object_handle, .memory_type = stale_memory_type, }); @@ -656,6 +674,7 @@ void DeviceMemoryReport::OnMemoryReportEvent(const VkDeviceMemoryReportCallbackD if (allocation_iterator != memory_allocations_.end()) { memory_type = is_driver ? allocation_iterator->second.cluster_name : "unbound_memory"; event_size = allocation_iterator->second.total_size; + event_object_type = allocation_iterator->second.object_type; event_object_handle = allocation_iterator->second.object_handle; RemoveAllocationTracking(key); operation_name = "DESTROY"; @@ -669,6 +688,7 @@ void DeviceMemoryReport::OnMemoryReportEvent(const VkDeviceMemoryReportCallbackD .memory_object_id = key.id, .size = event_size, .offset = 0, + .object_type = event_object_type, .object_handle = event_object_handle, .memory_type = memory_type, }); @@ -720,6 +740,7 @@ void DeviceMemoryReport::OnAllocateMemory(VkDevice device, VkDeviceMemory memory .memory_object_id = handle, .size = size, .offset = 0, + .object_type = VK_OBJECT_TYPE_DEVICE_MEMORY, .object_handle = handle, .memory_type = "unbound_memory", }); @@ -743,6 +764,7 @@ void DeviceMemoryReport::OnFreeMemory(VkDevice device, VkDeviceMemory memory) { .memory_object_id = handle, .size = freed_size, .offset = 0, + .object_type = VK_OBJECT_TYPE_DEVICE_MEMORY, .object_handle = handle, .memory_type = "unbound_memory", }); diff --git a/layersvt/device_memory_report/device_memory_report.h b/layersvt/device_memory_report/device_memory_report.h index be446f1e72..faf06dd267 100644 --- a/layersvt/device_memory_report/device_memory_report.h +++ b/layersvt/device_memory_report/device_memory_report.h @@ -163,17 +163,19 @@ class DeviceMemoryReport { /** * @brief Records the size of a virtual resource (buffer or image) in bytes. + * @param object_type The type of the Vulkan resource (VK_OBJECT_TYPE_BUFFER or VK_OBJECT_TYPE_IMAGE). * @param resource_handle The 64-bit handle of the Vulkan object. * @param size Size in bytes from memory requirements or create info. */ - void OnRecordResourceSize(uint64_t resource_handle, VkDeviceSize size); + void OnRecordResourceSize(VkObjectType object_type, uint64_t resource_handle, VkDeviceSize size); /** * @brief Retrieves the recorded size of a virtual resource (for testing). + * @param object_type The type of the Vulkan resource (VK_OBJECT_TYPE_BUFFER or VK_OBJECT_TYPE_IMAGE). * @param resource_handle The 64-bit handle of the Vulkan object. * @return Size in bytes, or 0 if not tracked. */ - VkDeviceSize GetRecordedResourceSize(uint64_t resource_handle); + VkDeviceSize GetRecordedResourceSize(VkObjectType object_type, uint64_t resource_handle); /** * @brief Resets all tracked internal state (for testing). @@ -255,12 +257,22 @@ class DeviceMemoryReport { * @brief Represents a sub-allocation of a Vulkan resource (buffer or image) bound within a physical memory allocation. */ struct SubAllocation { + VkObjectType object_type; /**< Type of the bound Vulkan resource (VK_OBJECT_TYPE_BUFFER or VK_OBJECT_TYPE_IMAGE). */ uint64_t resource_handle; /**< Handle of the bound Vulkan resource (buffer or image). */ VkDeviceSize offset; /**< Offset in bytes within the physical memory allocation where the resource is bound. */ VkDeviceSize size; /**< Size in bytes of the sub-allocated resource. */ std::string usage_track; /**< Name of the memory usage trace counter category for this sub-allocation. */ }; + /** + * @brief Identifies a Vulkan object as (object_type, handle). + * + * Non-dispatchable Vulkan handles (VkBuffer, VkImage, VkDeviceMemory) are only unique within + * their own object type, so the type is part of the key to prevent colliding handles of + * different types from overwriting each other's metadata, bindings or names. + */ + using ObjectKey = std::pair; + /** * @brief Tracks state and sub-allocations for a physical device memory allocation. */ @@ -308,6 +320,7 @@ class DeviceMemoryReport { VkImageUsageFlags image_usage = 0; VkBufferUsageFlags buffer_usage = 0; VkDeviceSize size = 0; + uint64_t bound_memory = 0; /**< VkDeviceMemory handle the resource is bound to, or 0 if unbound. */ const char* GetCluster(VkMemoryPropertyFlags mem_flags) const { if (is_image) { @@ -320,7 +333,7 @@ class DeviceMemoryReport { /** * @brief Helper to bind resource memory (buffers and images). */ - void BindResourceMemory(uint64_t resource_handle, uint64_t memory_handle, VkDeviceSize memory_offset); + void BindResourceMemory(VkObjectType object_type, uint64_t resource_handle, uint64_t memory_handle, VkDeviceSize memory_offset); /** * @brief Updates unbound memory category counter for a physical memory slab. @@ -331,7 +344,7 @@ class DeviceMemoryReport { /** * @brief Removes a sub-allocation of a resource from a physical memory slab if bound. */ - void RemoveResourceBinding(uint64_t resource_handle); + void RemoveResourceBinding(const ObjectKey& resource_key, Resource& resource); /** * @brief Removes all sub-allocations and tracking for a memory slab being freed. @@ -391,14 +404,9 @@ class DeviceMemoryReport { std::unordered_map device_memory_properties_map_; /** - * @brief Maps a virtual resource handle to its metadata. - */ - std::unordered_map resources_; - - /** - * @brief Maps a virtual resource handle to the physical memory handle it is bound to. + * @brief Maps a virtual resource (object type and handle) to its metadata and current binding. */ - std::unordered_map resource_to_memory_map_; + std::map resources_; /** * @brief Maps an allocation key (application VkDeviceMemory handle or driver memoryObjectId) @@ -422,5 +430,5 @@ class DeviceMemoryReport { * handle is renamed. Guarded by counter_mutex_. std::map is used instead of unordered_map for * pair key support and deterministic replay order. */ - std::map, std::string> debug_object_names_; + std::map debug_object_names_; }; diff --git a/layersvt/device_memory_report/device_memory_report_handwritten_functions.h b/layersvt/device_memory_report/device_memory_report_handwritten_functions.h index fe2c96bc7f..a666078fa4 100644 --- a/layersvt/device_memory_report/device_memory_report_handwritten_functions.h +++ b/layersvt/device_memory_report/device_memory_report_handwritten_functions.h @@ -365,11 +365,11 @@ VKAPI_ATTR VkResult VKAPI_CALL vkBindBufferMemory(VkDevice device, VkBuffer buff assert(table->BindBufferMemory != nullptr); assert(buffer != VK_NULL_HANDLE); assert(memory != VK_NULL_HANDLE); - if (DeviceMemoryReport::Get().GetRecordedResourceSize(reinterpret_cast(buffer)) == 0) { + if (DeviceMemoryReport::Get().GetRecordedResourceSize(VK_OBJECT_TYPE_BUFFER, reinterpret_cast(buffer)) == 0) { if (table->GetBufferMemoryRequirements) { VkMemoryRequirements mem_reqs; table->GetBufferMemoryRequirements(device, buffer, &mem_reqs); - DeviceMemoryReport::Get().OnRecordResourceSize(reinterpret_cast(buffer), mem_reqs.size); + DeviceMemoryReport::Get().OnRecordResourceSize(VK_OBJECT_TYPE_BUFFER, reinterpret_cast(buffer), mem_reqs.size); } } VkResult result = table->BindBufferMemory(device, buffer, memory, memoryOffset); @@ -385,11 +385,11 @@ VKAPI_ATTR VkResult VKAPI_CALL vkBindImageMemory(VkDevice device, VkImage image, assert(table->BindImageMemory != nullptr); assert(image != VK_NULL_HANDLE); assert(memory != VK_NULL_HANDLE); - if (DeviceMemoryReport::Get().GetRecordedResourceSize(reinterpret_cast(image)) == 0) { + if (DeviceMemoryReport::Get().GetRecordedResourceSize(VK_OBJECT_TYPE_IMAGE, reinterpret_cast(image)) == 0) { if (table->GetImageMemoryRequirements) { VkMemoryRequirements mem_reqs; table->GetImageMemoryRequirements(device, image, &mem_reqs); - DeviceMemoryReport::Get().OnRecordResourceSize(reinterpret_cast(image), mem_reqs.size); + DeviceMemoryReport::Get().OnRecordResourceSize(VK_OBJECT_TYPE_IMAGE, reinterpret_cast(image), mem_reqs.size); } } VkResult result = table->BindImageMemory(device, image, memory, memoryOffset); @@ -404,10 +404,10 @@ static void RecordBufferBindings(VkDevice device, uint32_t bindInfoCount, const for (uint32_t i = 0; i < bindInfoCount; ++i) { assert(pBindInfos[i].buffer != VK_NULL_HANDLE); assert(pBindInfos[i].memory != VK_NULL_HANDLE); - if (DeviceMemoryReport::Get().GetRecordedResourceSize(reinterpret_cast(pBindInfos[i].buffer)) == 0) { + if (DeviceMemoryReport::Get().GetRecordedResourceSize(VK_OBJECT_TYPE_BUFFER, reinterpret_cast(pBindInfos[i].buffer)) == 0) { VkMemoryRequirements mem_reqs; table->GetBufferMemoryRequirements(device, pBindInfos[i].buffer, &mem_reqs); - DeviceMemoryReport::Get().OnRecordResourceSize(reinterpret_cast(pBindInfos[i].buffer), mem_reqs.size); + DeviceMemoryReport::Get().OnRecordResourceSize(VK_OBJECT_TYPE_BUFFER, reinterpret_cast(pBindInfos[i].buffer), mem_reqs.size); } DeviceMemoryReport::Get().OnBindBufferMemory(reinterpret_cast(pBindInfos[i].buffer), reinterpret_cast(pBindInfos[i].memory), pBindInfos[i].memoryOffset); } @@ -440,7 +440,7 @@ static void RecordImageBinds(VkDevice device, uint32_t bindInfoCount, const VkBi for (uint32_t i = 0; i < bindInfoCount; ++i) { assert(pBindInfos[i].image != VK_NULL_HANDLE); assert(pBindInfos[i].memory != VK_NULL_HANDLE); - if (DeviceMemoryReport::Get().GetRecordedResourceSize(reinterpret_cast(pBindInfos[i].image)) == 0) { + if (DeviceMemoryReport::Get().GetRecordedResourceSize(VK_OBJECT_TYPE_IMAGE, reinterpret_cast(pBindInfos[i].image)) == 0) { bool is_plane_bind = false; for (const auto* header = reinterpret_cast(pBindInfos[i].pNext); header != nullptr; header = header->pNext) { @@ -452,7 +452,7 @@ static void RecordImageBinds(VkDevice device, uint32_t bindInfoCount, const VkBi if (!is_plane_bind) { VkMemoryRequirements mem_reqs; table->GetImageMemoryRequirements(device, pBindInfos[i].image, &mem_reqs); - DeviceMemoryReport::Get().OnRecordResourceSize(reinterpret_cast(pBindInfos[i].image), mem_reqs.size); + DeviceMemoryReport::Get().OnRecordResourceSize(VK_OBJECT_TYPE_IMAGE, reinterpret_cast(pBindInfos[i].image), mem_reqs.size); } } DeviceMemoryReport::Get().OnBindImageMemory(reinterpret_cast(pBindInfos[i].image), reinterpret_cast(pBindInfos[i].memory), pBindInfos[i].memoryOffset); @@ -494,7 +494,7 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateImage(VkDevice device, const VkImageCreat if (device_dispatch_table(device)->GetImageMemoryRequirements && (pCreateInfo->flags & VK_IMAGE_CREATE_DISJOINT_BIT) == 0) { VkMemoryRequirements mem_reqs; device_dispatch_table(device)->GetImageMemoryRequirements(device, *pImage, &mem_reqs); - DeviceMemoryReport::Get().OnRecordResourceSize(reinterpret_cast(*pImage), mem_reqs.size); + DeviceMemoryReport::Get().OnRecordResourceSize(VK_OBJECT_TYPE_IMAGE, reinterpret_cast(*pImage), mem_reqs.size); } } return result; @@ -523,7 +523,7 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateBuffer(VkDevice device, const VkBufferCre if (device_dispatch_table(device)->GetBufferMemoryRequirements) { VkMemoryRequirements mem_reqs; device_dispatch_table(device)->GetBufferMemoryRequirements(device, *pBuffer, &mem_reqs); - DeviceMemoryReport::Get().OnRecordResourceSize(reinterpret_cast(*pBuffer), mem_reqs.size); + DeviceMemoryReport::Get().OnRecordResourceSize(VK_OBJECT_TYPE_BUFFER, reinterpret_cast(*pBuffer), mem_reqs.size); } } return result; @@ -545,14 +545,14 @@ VKAPI_ATTR void VKAPI_CALL vkGetImageMemoryRequirements(VkDevice device, VkImage if (device_dispatch_table(device)->GetImageMemoryRequirements) { device_dispatch_table(device)->GetImageMemoryRequirements(device, image, pMemoryRequirements); if (image != VK_NULL_HANDLE && pMemoryRequirements != nullptr) { - DeviceMemoryReport::Get().OnRecordResourceSize(reinterpret_cast(image), pMemoryRequirements->size); + DeviceMemoryReport::Get().OnRecordResourceSize(VK_OBJECT_TYPE_IMAGE, reinterpret_cast(image), pMemoryRequirements->size); } } } static void RecordImageRequirements(const VkImageMemoryRequirementsInfo2* pInfo, const VkMemoryRequirements2* pMemoryRequirements) { if (pInfo != nullptr && pInfo->image != VK_NULL_HANDLE && pMemoryRequirements != nullptr) { - DeviceMemoryReport::Get().OnRecordResourceSize(reinterpret_cast(pInfo->image), pMemoryRequirements->memoryRequirements.size); + DeviceMemoryReport::Get().OnRecordResourceSize(VK_OBJECT_TYPE_IMAGE, reinterpret_cast(pInfo->image), pMemoryRequirements->memoryRequirements.size); } } @@ -577,14 +577,14 @@ VKAPI_ATTR void VKAPI_CALL vkGetBufferMemoryRequirements(VkDevice device, VkBuff if (device_dispatch_table(device)->GetBufferMemoryRequirements) { device_dispatch_table(device)->GetBufferMemoryRequirements(device, buffer, pMemoryRequirements); if (buffer != VK_NULL_HANDLE && pMemoryRequirements != nullptr) { - DeviceMemoryReport::Get().OnRecordResourceSize(reinterpret_cast(buffer), pMemoryRequirements->size); + DeviceMemoryReport::Get().OnRecordResourceSize(VK_OBJECT_TYPE_BUFFER, reinterpret_cast(buffer), pMemoryRequirements->size); } } } static void RecordBufferRequirements2(const VkBufferMemoryRequirementsInfo2* pInfo, const VkMemoryRequirements2* pMemoryRequirements) { if (pInfo != nullptr && pInfo->buffer != VK_NULL_HANDLE && pMemoryRequirements != nullptr) { - DeviceMemoryReport::Get().OnRecordResourceSize(reinterpret_cast(pInfo->buffer), pMemoryRequirements->memoryRequirements.size); + DeviceMemoryReport::Get().OnRecordResourceSize(VK_OBJECT_TYPE_BUFFER, reinterpret_cast(pInfo->buffer), pMemoryRequirements->memoryRequirements.size); } } diff --git a/layersvt/test/test_devicememoryreport.cpp b/layersvt/test/test_devicememoryreport.cpp index e2d9615dce..fa673c5cf8 100644 --- a/layersvt/test/test_devicememoryreport.cpp +++ b/layersvt/test/test_devicememoryreport.cpp @@ -179,7 +179,7 @@ TEST_F(DeviceMemoryReportTests, BufferImageBindingAndCallbackSuppression) { uint64_t memory_handle = 0x9000; DeviceMemoryReport::Get().OnCreateBuffer(buffer_handle, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, 1024); DeviceMemoryReport::Get().OnCreateImage(image_handle, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); - DeviceMemoryReport::Get().OnRecordResourceSize(image_handle, 2048); + DeviceMemoryReport::Get().OnRecordResourceSize(VK_OBJECT_TYPE_IMAGE, image_handle, 2048); DeviceMemoryReport::Get().OnBindBufferMemory(buffer_handle, memory_handle, 0); DeviceMemoryReport::Get().OnBindImageMemory(image_handle, memory_handle, 1024); @@ -240,11 +240,11 @@ TEST_F(DeviceMemoryReportTests, UsageTypeBreakdown) { DeviceMemoryReport::Get().OnCreateImage(storage_img, VK_IMAGE_USAGE_STORAGE_BIT); DeviceMemoryReport::Get().OnCreateImage(transient_img, VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT); - DeviceMemoryReport::Get().OnRecordResourceSize(color_img, 65536); - DeviceMemoryReport::Get().OnRecordResourceSize(depth_img, 65536); - DeviceMemoryReport::Get().OnRecordResourceSize(sampled_img, 65536); - DeviceMemoryReport::Get().OnRecordResourceSize(storage_img, 65536); - DeviceMemoryReport::Get().OnRecordResourceSize(transient_img, 65536); + DeviceMemoryReport::Get().OnRecordResourceSize(VK_OBJECT_TYPE_IMAGE, color_img, 65536); + DeviceMemoryReport::Get().OnRecordResourceSize(VK_OBJECT_TYPE_IMAGE, depth_img, 65536); + DeviceMemoryReport::Get().OnRecordResourceSize(VK_OBJECT_TYPE_IMAGE, sampled_img, 65536); + DeviceMemoryReport::Get().OnRecordResourceSize(VK_OBJECT_TYPE_IMAGE, storage_img, 65536); + DeviceMemoryReport::Get().OnRecordResourceSize(VK_OBJECT_TYPE_IMAGE, transient_img, 65536); // Register buffers DeviceMemoryReport::Get().OnCreateBuffer(vtx_buf, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, 4096); @@ -325,7 +325,7 @@ TEST_F(DeviceMemoryReportTests, MemoryAliasingAndOverlap) { // - vulkan.mem.app.usage.color_render_target += 4,000 B // - Merged intervals: [0, 4000) -> bound_size = 4,000 B, unbound_memory = 6,000 B DeviceMemoryReport::Get().OnCreateImage(image_a, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); - DeviceMemoryReport::Get().OnRecordResourceSize(image_a, 4000); + DeviceMemoryReport::Get().OnRecordResourceSize(VK_OBJECT_TYPE_IMAGE, image_a, 4000); DeviceMemoryReport::Get().OnBindImageMemory(image_a, mem_handle, 0); // Step 3: Bind Resource B (Sampled Texture Image) to range [2000, 6000) (size = 4000 B). @@ -336,7 +336,7 @@ TEST_F(DeviceMemoryReportTests, MemoryAliasingAndOverlap) { // - Physical slab bound_size = 6,000 B (overlapping physical region is NOT double-counted). // - Remaining unbound headroom: unbound_memory = 10,000 - 6,000 = 4,000 B. DeviceMemoryReport::Get().OnCreateImage(image_b, VK_IMAGE_USAGE_SAMPLED_BIT); - DeviceMemoryReport::Get().OnRecordResourceSize(image_b, 4000); + DeviceMemoryReport::Get().OnRecordResourceSize(VK_OBJECT_TYPE_IMAGE, image_b, 4000); DeviceMemoryReport::Get().OnBindImageMemory(image_b, mem_handle, 2000); // Step 4: Bind Resource C (Vertex Buffer) to disjoint range [8000, 9500) (size = 1500 B). @@ -365,6 +365,43 @@ TEST_F(DeviceMemoryReportTests, MemoryAliasingAndOverlap) { EXPECT_TRUE(true); } +TEST_F(DeviceMemoryReportTests, BindingsAreClampedToTheirAllocation) { + TEST_DESCRIPTION("Only the part of a binding that lies within its VkDeviceMemory allocation counts as bound"); + + InitializeDeviceMemoryReportPerfetto(); + const std::string unbound_track = "vulkan.mem.app.usage.unbound_memory"; + + VkDeviceMemoryReportCallbackDataEXT cb_data = {}; + cb_data.sType = VK_STRUCTURE_TYPE_DEVICE_MEMORY_REPORT_CALLBACK_DATA_EXT; + cb_data.type = VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_ALLOCATE_EXT; + cb_data.objectType = VK_OBJECT_TYPE_DEVICE_MEMORY; + cb_data.memoryObjectId = 0x7000; + cb_data.objectHandle = 0xE001; + cb_data.size = 16000; + DeviceMemoryReport::MemoryReportCallback(&cb_data, nullptr); + EXPECT_EQ(DeviceMemoryReport::Get().GetUsageCounterBytes(unbound_track), 16000u); + + // [12000, 20000) overhangs the 16,000-byte allocation, so only [12000, 16000) is bound. + DeviceMemoryReport::Get().OnCreateBuffer(0xE101, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, 8000); + DeviceMemoryReport::Get().OnBindBufferMemory(0xE101, 0xE001, 12000); + EXPECT_EQ(DeviceMemoryReport::Get().GetUsageCounterBytes(unbound_track), 12000u); + + // [20000, 21000) lies entirely outside the allocation, so nothing more is bound. + DeviceMemoryReport::Get().OnCreateBuffer(0xE102, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, 1000); + DeviceMemoryReport::Get().OnBindBufferMemory(0xE102, 0xE001, 20000); + EXPECT_EQ(DeviceMemoryReport::Get().GetUsageCounterBytes(unbound_track), 12000u); + + // A binding recorded before its allocation is reported is clamped once the allocation size is known. + DeviceMemoryReport::Get().OnCreateBuffer(0xE103, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, 4000); + DeviceMemoryReport::Get().OnBindBufferMemory(0xE103, 0xE002, 8000); + cb_data.memoryObjectId = 0x7001; + cb_data.objectHandle = 0xE002; + cb_data.size = 10000; + DeviceMemoryReport::MemoryReportCallback(&cb_data, nullptr); + // 12,000 B from the first allocation plus 10,000 - 2,000 B from the second. + EXPECT_EQ(DeviceMemoryReport::Get().GetUsageCounterBytes(unbound_track), 20000u); +} + TEST_F(DeviceMemoryReportTests, ClusterClassificationFunctions) { TEST_DESCRIPTION("Test cluster classification for buffer and image usages with memory properties"); @@ -526,7 +563,7 @@ TEST_F(DeviceMemoryReportTests, DriverVsAppUnboundMemoryAttribution) { // Register a virtual image resource with handle shared_handle DeviceMemoryReport::Get().OnCreateImage(shared_handle, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); - DeviceMemoryReport::Get().OnRecordResourceSize(shared_handle, 4096); + DeviceMemoryReport::Get().OnRecordResourceSize(VK_OBJECT_TYPE_IMAGE, shared_handle, 4096); // Case 1: Driver allocation where objectHandle is the virtual resource handle (flags is always 0 per spec) VkDeviceMemoryReportCallbackDataEXT driver_callback_data = {}; @@ -753,6 +790,69 @@ TEST_F(DeviceMemoryReportTests, DriverMemoryObjectIdCollidingWithAppHandle) { DeviceMemoryReport::Get().OnDestroyObject(buffer_handle, VK_OBJECT_TYPE_BUFFER); } +TEST_F(DeviceMemoryReportTests, BufferAndImageWithCollidingHandlesAreTrackedIndependently) { + TEST_DESCRIPTION("Test that a VkBuffer and a VkImage sharing a handle value keep independent metadata and bindings"); + + InitializeDeviceMemoryReportPerfetto(); + + // Non-dispatchable handles are only unique within their own object type. + const uint64_t shared_handle = 0xF201; + const uint64_t memory_handle = 0xF202; + + VkDeviceMemoryReportCallbackDataEXT app_cb = {}; + app_cb.sType = VK_STRUCTURE_TYPE_DEVICE_MEMORY_REPORT_CALLBACK_DATA_EXT; + app_cb.type = VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_ALLOCATE_EXT; + app_cb.memoryObjectId = 0x9201; + app_cb.size = 16384; + app_cb.objectType = VK_OBJECT_TYPE_DEVICE_MEMORY; + app_cb.objectHandle = memory_handle; + DeviceMemoryReport::MemoryReportCallback(&app_cb, nullptr); + + DeviceMemoryReport::Get().OnCreateBuffer(shared_handle, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, 4096); + DeviceMemoryReport::Get().OnCreateImage(shared_handle, VK_IMAGE_USAGE_SAMPLED_BIT); + DeviceMemoryReport::Get().OnRecordResourceSize(VK_OBJECT_TYPE_IMAGE, shared_handle, 8192); + + // Recording the image's size must not overwrite the buffer's. + EXPECT_EQ(DeviceMemoryReport::Get().GetRecordedResourceSize(VK_OBJECT_TYPE_BUFFER, shared_handle), 4096u); + EXPECT_EQ(DeviceMemoryReport::Get().GetRecordedResourceSize(VK_OBJECT_TYPE_IMAGE, shared_handle), 8192u); + auto buffer_resource = DeviceMemoryReportTestPeer::FindResource(VK_OBJECT_TYPE_BUFFER, shared_handle); + auto image_resource = DeviceMemoryReportTestPeer::FindResource(VK_OBJECT_TYPE_IMAGE, shared_handle); + ASSERT_TRUE(buffer_resource.has_value()); + ASSERT_TRUE(image_resource.has_value()); + EXPECT_FALSE(buffer_resource->is_image); + EXPECT_TRUE(image_resource->is_image); + + // Binding both into the same block keeps two distinct suballocations. + DeviceMemoryReport::Get().OnBindBufferMemory(shared_handle, memory_handle, 0); + DeviceMemoryReport::Get().OnBindImageMemory(shared_handle, memory_handle, 4096); + EXPECT_EQ(DeviceMemoryReport::Get().GetUsageCounterBytes("vulkan.mem.app.usage.geometry_mesh"), 4096u); + EXPECT_EQ(DeviceMemoryReport::Get().GetUsageCounterBytes("vulkan.mem.app.usage.static_texture"), 8192u); + EXPECT_EQ(DeviceMemoryReport::Get().GetUsageCounterBytes("vulkan.mem.app.usage.unbound_memory"), 4096u); + auto allocation = DeviceMemoryReportTestPeer::FindAllocation(memory_handle); + ASSERT_TRUE(allocation.has_value()); + ASSERT_EQ(allocation->sub_allocations.size(), 2u); + EXPECT_EQ(allocation->sub_allocations[0].object_type, VK_OBJECT_TYPE_BUFFER); + EXPECT_EQ(allocation->sub_allocations[1].object_type, VK_OBJECT_TYPE_IMAGE); + + // Destroying the buffer unbinds only the buffer. + DeviceMemoryReport::Get().OnDestroyObject(shared_handle, VK_OBJECT_TYPE_BUFFER); + EXPECT_EQ(DeviceMemoryReport::Get().GetUsageCounterBytes("vulkan.mem.app.usage.geometry_mesh"), 0u); + EXPECT_EQ(DeviceMemoryReport::Get().GetUsageCounterBytes("vulkan.mem.app.usage.static_texture"), 8192u); + EXPECT_EQ(DeviceMemoryReport::Get().GetUsageCounterBytes("vulkan.mem.app.usage.unbound_memory"), 8192u); + EXPECT_FALSE(DeviceMemoryReportTestPeer::FindResource(VK_OBJECT_TYPE_BUFFER, shared_handle).has_value()); + EXPECT_TRUE(DeviceMemoryReportTestPeer::FindResource(VK_OBJECT_TYPE_IMAGE, shared_handle).has_value()); + allocation = DeviceMemoryReportTestPeer::FindAllocation(memory_handle); + ASSERT_TRUE(allocation.has_value()); + ASSERT_EQ(allocation->sub_allocations.size(), 1u); + EXPECT_EQ(allocation->sub_allocations[0].object_type, VK_OBJECT_TYPE_IMAGE); + + app_cb.type = VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_FREE_EXT; + DeviceMemoryReport::MemoryReportCallback(&app_cb, nullptr); + EXPECT_EQ(DeviceMemoryReport::Get().GetUsageCounterBytes("vulkan.mem.app.usage.static_texture"), 0u); + EXPECT_EQ(DeviceMemoryReport::Get().GetUsageCounterBytes("vulkan.mem.app.usage.unbound_memory"), 0u); + DeviceMemoryReport::Get().OnDestroyObject(shared_handle, VK_OBJECT_TYPE_IMAGE); +} + TEST_F(DeviceMemoryReportTests, MemoryReportSnapshotDump) { TEST_DESCRIPTION("Test DumpCurrentCountersAndAllocations state dump and instant event emissions when a trace session begins"); @@ -774,11 +874,11 @@ TEST_F(DeviceMemoryReportTests, MemoryReportSnapshotDump) { // Bind a buffer and an image sub-allocation DeviceMemoryReport::Get().OnCreateBuffer(buffer_handle, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, 4096); - DeviceMemoryReport::Get().OnRecordResourceSize(buffer_handle, 4096); + DeviceMemoryReport::Get().OnRecordResourceSize(VK_OBJECT_TYPE_BUFFER, buffer_handle, 4096); DeviceMemoryReport::Get().OnBindBufferMemory(buffer_handle, memory_handle, 0); DeviceMemoryReport::Get().OnCreateImage(image_handle, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); - DeviceMemoryReport::Get().OnRecordResourceSize(image_handle, 4096); + DeviceMemoryReport::Get().OnRecordResourceSize(VK_OBJECT_TYPE_IMAGE, image_handle, 4096); DeviceMemoryReport::Get().OnBindImageMemory(image_handle, memory_handle, 4096); auto allocation = DeviceMemoryReportTestPeer::FindAllocation(memory_handle); @@ -806,8 +906,8 @@ TEST_F(DeviceMemoryReportTests, MemoryReportSnapshotDump) { // Verify post-destruction state EXPECT_FALSE(DeviceMemoryReportTestPeer::FindAllocation(memory_handle).has_value()); - EXPECT_FALSE(DeviceMemoryReportTestPeer::FindResource(buffer_handle).has_value()); - EXPECT_FALSE(DeviceMemoryReportTestPeer::FindResource(image_handle).has_value()); + EXPECT_FALSE(DeviceMemoryReportTestPeer::FindResource(VK_OBJECT_TYPE_BUFFER, buffer_handle).has_value()); + EXPECT_FALSE(DeviceMemoryReportTestPeer::FindResource(VK_OBJECT_TYPE_IMAGE, image_handle).has_value()); } diff --git a/layersvt/test/test_devicememoryreport_dispatch.cpp b/layersvt/test/test_devicememoryreport_dispatch.cpp index f6ff1f364e..008f6361c3 100644 --- a/layersvt/test/test_devicememoryreport_dispatch.cpp +++ b/layersvt/test/test_devicememoryreport_dispatch.cpp @@ -210,7 +210,7 @@ TEST_F(DeviceMemoryReportDispatchTests, ProactiveMemoryRequirementsQuery) { VkImage image = VK_NULL_HANDLE; ASSERT_EQ(vkCreateImage(device.handle(), &image_info, nullptr, &image), VK_SUCCESS); EXPECT_EQ(g_image_requirements_queries, 1); - EXPECT_EQ(DeviceMemoryReport::Get().GetRecordedResourceSize(AsObjectHandle(image)), 16384u); + EXPECT_EQ(DeviceMemoryReport::Get().GetRecordedResourceSize(VK_OBJECT_TYPE_IMAGE, AsObjectHandle(image)), 16384u); VkBufferCreateInfo buffer_info = {}; buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; @@ -221,7 +221,7 @@ TEST_F(DeviceMemoryReportDispatchTests, ProactiveMemoryRequirementsQuery) { VkBuffer buffer = VK_NULL_HANDLE; ASSERT_EQ(vkCreateBuffer(device.handle(), &buffer_info, nullptr, &buffer), VK_SUCCESS); EXPECT_EQ(g_buffer_requirements_queries, 1); - EXPECT_EQ(DeviceMemoryReport::Get().GetRecordedResourceSize(AsObjectHandle(buffer)), 2048u); + EXPECT_EQ(DeviceMemoryReport::Get().GetRecordedResourceSize(VK_OBJECT_TYPE_BUFFER, AsObjectHandle(buffer)), 2048u); vkDestroyImage(device.handle(), image, nullptr); vkDestroyBuffer(device.handle(), buffer, nullptr); @@ -235,13 +235,13 @@ TEST_F(DeviceMemoryReportDispatchTests, BindBufferMemoryQueriesUnknownResourceSi VkBuffer buffer = MakeHandle(0xB1000); VkDeviceMemory memory = MakeHandle(0xB1001); - ASSERT_EQ(DeviceMemoryReport::Get().GetRecordedResourceSize(AsObjectHandle(buffer)), 0u); + ASSERT_EQ(DeviceMemoryReport::Get().GetRecordedResourceSize(VK_OBJECT_TYPE_BUFFER, AsObjectHandle(buffer)), 0u); g_buffer_requirements_size = 4096; EXPECT_EQ(vkBindBufferMemory(device.handle(), buffer, memory, 0), VK_SUCCESS); EXPECT_EQ(g_buffer_requirements_queries, 1); - EXPECT_EQ(DeviceMemoryReport::Get().GetRecordedResourceSize(AsObjectHandle(buffer)), 4096u); + EXPECT_EQ(DeviceMemoryReport::Get().GetRecordedResourceSize(VK_OBJECT_TYPE_BUFFER, AsObjectHandle(buffer)), 4096u); } TEST_F(DeviceMemoryReportDispatchTests, BindImageMemoryQueriesUnknownResourceSize) { @@ -249,13 +249,13 @@ TEST_F(DeviceMemoryReportDispatchTests, BindImageMemoryQueriesUnknownResourceSiz VkImage image = MakeHandle(0xB2000); VkDeviceMemory memory = MakeHandle(0xB2001); - ASSERT_EQ(DeviceMemoryReport::Get().GetRecordedResourceSize(AsObjectHandle(image)), 0u); + ASSERT_EQ(DeviceMemoryReport::Get().GetRecordedResourceSize(VK_OBJECT_TYPE_IMAGE, AsObjectHandle(image)), 0u); g_image_requirements_size = 65536; EXPECT_EQ(vkBindImageMemory(device.handle(), image, memory, 0), VK_SUCCESS); EXPECT_EQ(g_image_requirements_queries, 1); - EXPECT_EQ(DeviceMemoryReport::Get().GetRecordedResourceSize(AsObjectHandle(image)), 65536u); + EXPECT_EQ(DeviceMemoryReport::Get().GetRecordedResourceSize(VK_OBJECT_TYPE_IMAGE, AsObjectHandle(image)), 65536u); } TEST_F(DeviceMemoryReportDispatchTests, BindMemory2QueriesUnknownResourceSizes) { @@ -294,10 +294,10 @@ TEST_F(DeviceMemoryReportDispatchTests, BindMemory2QueriesUnknownResourceSizes) EXPECT_EQ(g_buffer_requirements_queries, 2); EXPECT_EQ(g_image_requirements_queries, 2); - EXPECT_EQ(DeviceMemoryReport::Get().GetRecordedResourceSize(AsObjectHandle(buffer)), 1024u); - EXPECT_EQ(DeviceMemoryReport::Get().GetRecordedResourceSize(AsObjectHandle(buffer_khr)), 1024u); - EXPECT_EQ(DeviceMemoryReport::Get().GetRecordedResourceSize(AsObjectHandle(image)), 8192u); - EXPECT_EQ(DeviceMemoryReport::Get().GetRecordedResourceSize(AsObjectHandle(image_khr)), 8192u); + EXPECT_EQ(DeviceMemoryReport::Get().GetRecordedResourceSize(VK_OBJECT_TYPE_BUFFER, AsObjectHandle(buffer)), 1024u); + EXPECT_EQ(DeviceMemoryReport::Get().GetRecordedResourceSize(VK_OBJECT_TYPE_BUFFER, AsObjectHandle(buffer_khr)), 1024u); + EXPECT_EQ(DeviceMemoryReport::Get().GetRecordedResourceSize(VK_OBJECT_TYPE_IMAGE, AsObjectHandle(image)), 8192u); + EXPECT_EQ(DeviceMemoryReport::Get().GetRecordedResourceSize(VK_OBJECT_TYPE_IMAGE, AsObjectHandle(image_khr)), 8192u); } TEST_F(DeviceMemoryReportDispatchTests, BindMemoryKeepsAlreadyRecordedSizes) { @@ -307,8 +307,8 @@ TEST_F(DeviceMemoryReportDispatchTests, BindMemoryKeepsAlreadyRecordedSizes) { VkImage image = MakeHandle(0xB4001); VkDeviceMemory memory = MakeHandle(0xB4002); - DeviceMemoryReport::Get().OnRecordResourceSize(AsObjectHandle(buffer), 2048); - DeviceMemoryReport::Get().OnRecordResourceSize(AsObjectHandle(image), 4096); + DeviceMemoryReport::Get().OnRecordResourceSize(VK_OBJECT_TYPE_BUFFER, AsObjectHandle(buffer), 2048); + DeviceMemoryReport::Get().OnRecordResourceSize(VK_OBJECT_TYPE_IMAGE, AsObjectHandle(image), 4096); g_buffer_requirements_size = 999; g_image_requirements_size = 999; @@ -318,8 +318,8 @@ TEST_F(DeviceMemoryReportDispatchTests, BindMemoryKeepsAlreadyRecordedSizes) { EXPECT_EQ(g_buffer_requirements_queries, 0); EXPECT_EQ(g_image_requirements_queries, 0); - EXPECT_EQ(DeviceMemoryReport::Get().GetRecordedResourceSize(AsObjectHandle(buffer)), 2048u); - EXPECT_EQ(DeviceMemoryReport::Get().GetRecordedResourceSize(AsObjectHandle(image)), 4096u); + EXPECT_EQ(DeviceMemoryReport::Get().GetRecordedResourceSize(VK_OBJECT_TYPE_BUFFER, AsObjectHandle(buffer)), 2048u); + EXPECT_EQ(DeviceMemoryReport::Get().GetRecordedResourceSize(VK_OBJECT_TYPE_IMAGE, AsObjectHandle(image)), 4096u); } TEST_F(DeviceMemoryReportDispatchTests, BindImageMemory2SkipsDisjointImagePlaneBind) { @@ -330,7 +330,7 @@ TEST_F(DeviceMemoryReportDispatchTests, BindImageMemory2SkipsDisjointImagePlaneB VkImage image = MakeHandle(0xB4800); VkDeviceMemory memory = MakeHandle(0xB4801); - ASSERT_EQ(DeviceMemoryReport::Get().GetRecordedResourceSize(AsObjectHandle(image)), 0u); + ASSERT_EQ(DeviceMemoryReport::Get().GetRecordedResourceSize(VK_OBJECT_TYPE_IMAGE, AsObjectHandle(image)), 0u); VkBindImagePlaneMemoryInfo plane_info = {}; plane_info.sType = VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO; @@ -351,7 +351,7 @@ TEST_F(DeviceMemoryReportDispatchTests, BindImageMemory2SkipsDisjointImagePlaneB EXPECT_EQ(vkBindImageMemory2(device.handle(), 1, &image_bind), VK_SUCCESS); EXPECT_EQ(g_image_requirements_queries, 0); - EXPECT_EQ(DeviceMemoryReport::Get().GetRecordedResourceSize(AsObjectHandle(image)), 0u); + EXPECT_EQ(DeviceMemoryReport::Get().GetRecordedResourceSize(VK_OBJECT_TYPE_IMAGE, AsObjectHandle(image)), 0u); } TEST_F(DeviceMemoryReportDispatchTests, SetDebugUtilsObjectNameStandaloneAndChained) { diff --git a/layersvt/test/test_devicememoryreport_peer.h b/layersvt/test/test_devicememoryreport_peer.h index f2d6fd9885..f9164cb782 100644 --- a/layersvt/test/test_devicememoryreport_peer.h +++ b/layersvt/test/test_devicememoryreport_peer.h @@ -37,10 +37,10 @@ class DeviceMemoryReportTestPeer { return FindAllocationByKey(DeviceMemoryReport::AllocationKey::Driver(memory_object_id)); } - static std::optional FindResource(uint64_t resource_handle) { + static std::optional FindResource(VkObjectType object_type, uint64_t resource_handle) { auto& report = DeviceMemoryReport::Get(); std::lock_guard lock(report.counter_mutex_); - auto it = report.resources_.find(resource_handle); + auto it = report.resources_.find({object_type, resource_handle}); if (it == report.resources_.end()) { return std::nullopt; }