@@ -40,6 +40,7 @@ struct heap
4040 VkDeviceMemory mem;
4141 VkDeviceSize free;
4242 VkDeviceSize total;
43+ VkMemoryPropertyFlags flags;
4344 // / This one does not need to be concurrent safe, since each thread owns its own heap
4445 // / and only it may iterate over and modify the allocations list.
4546 std::list<suballocation> subs;
@@ -76,6 +77,10 @@ struct suballocator_private
7677 std::vector<lookup> tensor_lookup;
7778 // / Does this device have the an annoying optimal-to-linear padding requirement? If so, put optimal and linear objects in different memory heaps
7879 bool allow_mixed_tiling = true ;
80+ std::atomic_uint64_t used_bytes { 0 };
81+ std::atomic_uint_least32_t used_count { 0 };
82+ std::atomic_uint64_t allocated_bytes { 0 };
83+ std::atomic_uint_least32_t allocated_heaps { 0 };
7984
8085 void print_memory_usage ();
8186 uint32_t get_device_memory_type (uint32_t type_filter, VkMemoryPropertyFlags properties);
@@ -87,6 +92,7 @@ struct suballocator_private
8792 lava_tiling tiling, bool dedicated, VkMemoryAllocateFlags allocflags);
8893 void self_test ();
8994 void bind (heap& h, const suballocation& s);
95+ suballoc_metrics performance () const ;
9096
9197 inline bool needs_flush (unsigned memoryTypeIndex) { return !(memory_properties.memoryTypes [memoryTypeIndex].propertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); }
9298};
@@ -102,6 +108,22 @@ static VkMemoryPropertyFlags prune_memory_flags(VkMemoryPropertyFlags flags)
102108 return flags;
103109}
104110
111+ suballoc_metrics suballocator::performance () const
112+ {
113+ return priv->performance ();
114+ }
115+
116+ suballoc_metrics suballocator_private::performance () const
117+ {
118+ suballoc_metrics m;
119+ m.used = used_bytes;
120+ m.objects = used_count;
121+ m.heaps = allocated_heaps;
122+ m.allocated = allocated_bytes;
123+ m.efficiency = (double )used_bytes / (double )allocated_bytes;
124+ return m;
125+ }
126+
105127void suballocator_private::print_memory_usage ()
106128{
107129 printf (" Suballocator memory usage:\n " );
@@ -244,11 +266,14 @@ suballoc_location suballocator_private::add_object_new(VkDevice device, uint16_t
244266 {
245267 h.mem = (VkDeviceMemory)malloc (info.allocationSize );
246268 }
269+ allocated_bytes += info.allocationSize ;
270+ allocated_heaps++;
247271 h.free = info.allocationSize - s.size ;
248272 h.total = info.allocationSize ;
249273 h.memoryTypeIndex = memoryTypeIndex;
250274 h.tiling = tiling;
251275 h.subs .push_back (s);
276+ h.flags = flags;
252277 DLOG2 (" allocating new memory pool with size = %lu, free = %lu (memoryTypeIndex=%u, tiling=%u)" , (unsigned long )info.allocationSize ,
253278 (unsigned long )h.free , (unsigned )memoryTypeIndex, (unsigned )tiling);
254279 auto it = heaps.push_back (h);
@@ -260,13 +285,15 @@ suballoc_location suballocator_private::add_object_new(VkDevice device, uint16_t
260285suballoc_location suballocator_private::add_object (VkDevice device, uint16_t tid, uint32_t memoryTypeIndex, suballocation &s, VkMemoryPropertyFlags flags,
261286 lava_tiling tiling, bool dedicated, VkMemoryAllocateFlags allocflags)
262287{
288+ used_count++;
289+ used_bytes += s.size ;
290+ assert (s.alignment != 0 );
263291 if (dedicated)
264292 {
265293 return add_object_new (device, tid, memoryTypeIndex, s, flags, tiling, dedicated, allocflags);
266294 }
267295 for (heap& h : heaps)
268296 {
269- VkMemoryPropertyFlags f = memory_properties.memoryTypes [h.memoryTypeIndex ].propertyFlags ;
270297 // this is a safe time to actually delete things
271298 if (!h.deletes .empty ())
272299 {
@@ -287,7 +314,7 @@ suballoc_location suballocator_private::add_object(VkDevice device, uint16_t tid
287314 h.deletes .clear ();
288315 }
289316 // find suballocation
290- if (h.tid == tid && (flags & f ) == flags && h.free >= s.size && h.memoryTypeIndex == memoryTypeIndex && (h.tiling == tiling || allow_mixed_tiling))
317+ if (h.tid == tid && (flags & h. flags ) == flags && h.free >= s.size && h.memoryTypeIndex == memoryTypeIndex && (h.tiling == tiling || allow_mixed_tiling))
291318 {
292319 // First case: nothing allocated in heap. In this case, we do not care about alignment, because according to the spec:
293320 // "Allocations returned by vkAllocateMemory are guaranteed to meet any alignment requirement of the implementation."
@@ -398,6 +425,7 @@ suballoc_location suballocator::add_image(uint16_t tid, VkDevice device, VkImage
398425
399426suballoc_location suballocator::add_trackedobject (uint16_t tid, VkDevice device, const memory_requirements& reqs, uint64_t native, const trackedobject& data)
400427{
428+ assert (reqs.requirements .alignment != 0 ); // not properly initialized!
401429 const VkMemoryPropertyFlags memory_flags = prune_memory_flags (data.memory_flags );
402430 const uint32_t memoryTypeIndex = priv->get_device_memory_type (reqs.requirements .memoryTypeBits , memory_flags);
403431 suballocation s;
0 commit comments