GPUOpen-LibrariesAndSDKs / VulkanMemoryAllocator

Easy to integrate Vulkan memory allocation library
MIT License
2.63k stars 359 forks source link

Opaque buffer sub-allocation #258

Open kvark opened 2 years ago

kvark commented 2 years ago

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.

adam-sawicki-a commented 2 years ago

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 commented 1 year ago

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:

adam-sawicki-a commented 1 year ago

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.

Neo-Zhixing commented 1 year ago

@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.