VulkanMemoryAllocator icon indicating copy to clipboard operation
VulkanMemoryAllocator copied to clipboard

Opaque buffer sub-allocation

Open kvark opened this issue 3 years ago • 6 comments

This is a follow-up from #88 I believe the API needs more work. If I understand correctly, the solution to #88 is the "Virtual allocator" (unfortunately no commits/PRs are linked from the closed issue). It's definitely a useful feature, and it could be used for buffer sub-allocation in the following way:

  1. I setup VMA to get large chunks of memory for buffers
  2. I sub-allocate within the chunks using the virtual allocator

The problem here is that it forces me to figure out the chunk size, and it requires a lot of boilerplate to do something that VMA is already meant to be doing anyway. Instead, here is what it could (or likely - should) look like:

struct VmaVirtualBuffer {
  VkBuffer buffer;
  VkDeviceSize offset;
};

VkResult vmaCreateBuffer(..., VmaVirtualBuffer* pVirtualBuffer, VmaAllocation*, pAllocationInfo*) {...}

So instead of having separate memory allocation and buffer sub-allocation, it all should happen inside vmaCreateBuffer. The only difference to the user is that in addition to VkBuffer it gets the offset within this buffer. Internally, VMA would create a VkBuffer spanning the whole allocation (basically doing a dedicated allocation) and return parts of it.

kvark avatar Apr 18 '22 17:04 kvark

Thank you for the suggestion. I agree this could be useful. Documentation chapter "Virtual allocator" says:

The "virtual allocator" functionality is implemented on a level of individual memory blocks. Keeping track of a whole collection of blocks, allocating new ones when out of free space, deleting empty ones, and deciding which one to try first for a new allocation must be implemented by the user.

Support for such sub-allocated buffers would likely be a new API implemented on top of the current functionality and as such could even be a new library on top of VMA. We might implement it in the future.

adam-sawicki-a avatar Apr 19 '22 09:04 adam-sawicki-a

I finally started implementing this feature on a branch. So far I defined initial version of the API. Please take a look and let me know what you think. https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator/compare/feature-buffer-suballocation?expand=1#diff-c6a5f3b7d318258297b6925f3dcb93e9720b5f30c08a0405ff6bd7ee6304b976

Would that meet your needs? Is it OK if the new VmaBufferAllocator object under the hood manages a collection of implicitly created { VmaAllocation + VkBuffer + VmaVirtualBlock }?

I'm also still thinking about the name. Some proposals:

  • BufferAllocator + BufferSuballocation <-- so far I used this one
  • BufferAllocator + BufferSubAllocation
  • BufferAllocator + BufferAllocation
  • SubBufferPool + SubBuffer
  • SubbufferPool + Subbuffer
  • BufferPool + BufferPoolAllocation
  • ImplicitBufferPool + ImplicitBuffer
  • AutoBufferPool + AutoBuffer
  • ?? + BufferPart / BufferRegion

adam-sawicki-a avatar Jan 27 '23 17:01 adam-sawicki-a

I filled in initial implementation and a test.

Every suballocation has a separate buffer for now, but otherwise entire API is implemented, except not all creation structure parameters and flags are respected yet.

adam-sawicki-a avatar Jan 31 '23 16:01 adam-sawicki-a

@adam-sawicki-a Any updates on this? If it's in a reviewable state, I'd appreciate it if you could create a draft PR.

As a side note - preferably this features would be utilizing the existing BlockVector so that users can create suballocated buffers without worrying about running out of remaining buffer space. Can just be an option that we can turn on when creating a VmaPool, and if it's on, the allocator creates and binds a buffer whenever a new block was created. On allocation, the allocator returns the buffer alongside all existing information.

PixelDust22 avatar Jul 03 '23 10:07 PixelDust22