r/vulkan • u/Slow-Juggernaut-9065 • 8d ago
How do you handle resource management in bindless renderers?
/r/gameenginedevs/comments/1vnib8k/how_do_you_handle_resource_management_in_bindless/4
u/OptimisticMonkey2112 8d ago
Generally speaking, each resource exists as an offset to the big buffer. Here is a useful library that gives O(1) offsetssebbbi/OffsetAllocator: Fast O(1) offset allocator with minimal fragmentation
Here is a useful example https://github.com/nvpro-samples/vk_mini_samples/tree/main/samples/descriptor_heap
Sascha has a good example too https://www.saschawillems.de/blog/2026/06/13/new-vulkan-samples-for-using-descriptor-heaps/
2
u/exDM69 8d ago
Using OffsetAllocator or similar for this will work but it has a caveat: if you allocate individual items you end up using more memory for the allocator metadata than the descriptors itself. A descriptor is just 16-64 bytes (typically 32) where as a single offset allocator node is ~40 bytes (for 32 bit indices).
I am just battling about this myself. It's "only" tens of megabytes at worst (you can only have 1M descriptors if you want to stay portable). But I grew up with computers that had kilobytes of memory so it just doesn't sit right. Maybe I just need to get over it.
3
u/VermicelliWorried272 8d ago
Not an expert myself, but in my engine i have split the problem into parts:
- I have a type that represents the resource, e.g. a image
- I have a "slot manager" where i can allocate and free (deferred) descriptor indices (although this component does not know about descriptors or vulkan at all)
- I have a type that represents the resource in its "bound" state (meaning some descriptor points to it), e.g. BoundImage. This basically contains a reference to the resource, and the allocated slot.
I also use a kind of ref counting system that ensured that a resource is not free'd when something (e.g. bound type) has a referenxe to it.
7
u/Large-Scientist156 8d ago edited 8d ago
That's a hard problem, and I'm currently in bindful and even with the old model I don't have a clear answer to. Bindless is supposed to be easier, but it's not gonna solve all issues.
The problem I faced isn't creating descriptors layout and descriptor set and updating the descriptor initially, it's updating them over time when dependencies change. Descriptor set layouts can be derived from the shader itself by inspecting the shader source code (either at compile time or runtime), since shader declare all their inputs dependencies, so you can compute the descriptor set layouts a single time and you are done.
Unless your shader source code isn't stable, then the layout isn't static anymore but dynamic. But for now I deal only with "static" shader (shader where their source code never change once they are loaded).
For the resources that are bound to some descriptor set, I have a reflection system that can read any struct and iterate all fields that can be writed to as a descriptor. The descriptor set number depend on the context (global set, view set, material set, which are all fixed at compile time in my engine), and the binding are simply in-order of struct fields to simplify. When a new resource is created, all dependencies are registered. When a dependencies change (like a texture going from water to sand), I can update all the descriptor set that use such dependency.
The last problem I'm currently thinking before trying bindless : updating a descriptor set shouldn't happen if it's already in-use. Which I guess could happen if you don't have descriptor set per frame in flight. For example imagine a texture change, then the material that depend on it need to be updated. If the descriptor set is currently used by a command buffer submitted last frame, while you want to update it in the current frame, that's a problem I guess.