On allocator size management

Hi!
I’m writing a memory allocation library and I’d like to include support for vulkan. Unfortunately the functions of VkAllocationsCallbacks expect you to track the size of each block, which is something I’m trying to avoid. Is there any way that in the future we’ll get something like VkAllocationCallbacks2 where you don’t have to do that?

Someone has to keep track of the allocation size; it’s either going to be the allocator or the Vulkan implementation. Making the implementation do it potentially imposes a burden on every implementation. Making the allocator do it only imposes a burden on allocators that require size tracking for correctly freeing memory. Which not all of them do.

If someone has to do it, it’s better for the allocator to do it, since it knows the best place to store that kind of information.

I don’t get what you’re saying.
When you request memory to the allocator you must store the size information somehow: either you explicitly store it as the length of an array or implicitly via the size of the type. That is, it’s not really a burden for the implementation since it keeps this information anyway, it’s a burden for the allocator since now it has to either overallocate to store headers or use an associative data structure to remember the sizes.

Are you sure about that?

Let’s say you’re writing the implementation for a descriptor pool. The pool was created with some fixed, maximum number of descriptor sets. So for you implementation, upon creating the descriptor pool, you request from the provided allocator a block of memory sufficient to store that many sets plus additional space for tracking which descriptor sets in this block are allocated.

But because Vulkan is not a safe API, you don’t have to remember the maximum number of sets; if the user over-allocates, that’s on them. So you don’t store the number of sets in your data storage and you don’t do bounds checking.

At the time of allocation, you could compute an allocation size based on the number of sets. But at deallocation time, you no longer have the information needed to compute the size to deallocate.

I’m not complaining that Vulkan doesn’t track allocation sizes. My issue is with forcing the allocator implementation to do it. In your descriptor pool example, I agree it shouldn’t have to know the maximum number of descriptor sets. But you can always make the user store the size (which they’re probably already doing) and have them pass the size to the corresponding vkDestroy* call.

PS: Sorry for the late reply!

I never said that it shouldn’t have to know that, and I very much disagree with not telling it how many sets to allocate from. Descriptor allocation being fixed allows the system to allocate all of the memory from the allocator immediately, then divvy it up as you request it.

But the “user” of a Vulkan allocator is the Vulkan implementation, not the person making the vkDestroy* call. If I call vkCreateGraphicsPipeline, I have no idea how much memory the implementation needed to allocate from the allocator. As such, I cannot possibly provide a value to “the corresponding vkDestroy* call”.

Only the implementation knows that because it’s the implementation that causes allocation.

At the end of the day, the allocator implementation is the only code that undeniably:

  1. Knows that its implementation requires knowing the size of an allocation in order to deallocate it. Not every allocator needs this information.

  2. Knows the size of every allocation it makes (since it was given that size when it allocated the memory).

The Vulkan implementation doesn’t know #1. The Vulkan user doesn’t know #2. Only the allocator knows both.

1 Like