Newbie question re descriptor pools

So I understand memory management for vertex buffers should be different from uniform buffers: Object vertices are read into the GPU and then stay mostly static, while uniforms containing, e.g., MVP matrices, can change every frame. Makes sense.

Next, I understand descriptor sets are allocated from descriptor pools because “pooling the allocations used to store memory allows drivers to make efficient use of memory” (to quote the Vulkan Programming Guide). Again makes sense.

But here’s where I am confused. We ourselves allocate for each descriptor set a buffer and the memory that backs it with VkWriteDescriptorSet -> VkDescriptorBufferInfo etc. So if we are doing this ourselves, what’s the point of the descriptor pool to begin with? One would think once the descriptor sets are assigned from a pool, the driver would find the right size/type of memory (like the Guide suggests above). But instead it’s us (the programmer) going in to assign each descriptor set’s memory anyway.

Thanks for your help.

[QUOTE=theDancer;42233]So I understand memory management for vertex buffers should be different from uniform buffers: Object vertices are read into the GPU and then stay mostly static, while uniforms containing, e.g., MVP matrices, can change every frame. Makes sense.

Next, I understand descriptor sets are allocated from descriptor pools because “pooling the allocations used to store memory allows drivers to make efficient use of memory” (to quote the Vulkan Programming Guide). Again makes sense.

But here’s where I am confused. We ourselves allocate for each descriptor set a buffer and the memory that backs it with VkWriteDescriptorSet -> VkDescriptorBufferInfo etc. So if we are doing this ourselves, what’s the point of the descriptor pool to begin with? One would think once the descriptor sets are assigned from a pool, the driver would find the right size/type of memory (like the Guide suggests above). But instead it’s us (the programmer) going in to assign each descriptor set’s memory anyway.[/QUOTE]

Think of it like a C/C++ pointer. Pointers point to memory. But the pointer itself also takes up memory: 4 or 8 bytes, depending on your compiler and settings. The memory a pointer points to does not provide storage for the pointer itself. That storage still has to come from somewhere.

In this analogy, a descriptor is a pointer. A descriptor set is basically a struct that contains a bunch of pointers. The descriptor pool therefore allocates space for these pointers and structs of pointers. You still need to allocate the storage for what will be pointed to by those pointers.


using BufferDescriptor = Buffer*;
using ImageDescriptor = Image*;

struct DescriptorSetLayout
{
  BufferDescriptor buffers[3];
  ImageDescritpor images[5];
};

DescriptorSetLayout *descriptorSet = AllocateFromPool<DescriptorSetLayout>(pool);

This code allocates storage for a struct containing a bunch of pointers. That’s the equivalent of vkAllocateDescriptorSets. But it doens’t allocate the memory to be pointed to.

To get that, you need to allocate the actual Buffer or Image objects that a particular set will point to, and fill in those pointers in that set. This is the purpose of the GPU memory allocation and VkWriteDescritporSet calls, respectively.

Thanks mucho, Alfonse. It’ll take a bit to seep into my mildly thick head but it’ll get there eventually.

Regarding the descriptors i’d like some help as well. I’ve allocated 2 big buffers, one UniformBufferDynamic (UBD) for MVP matrices and one UniformBuffer (UB) for shader paramaters. MVP matrices works fine since all i have to do is specify the dynamic offset when call vkCmdBindDescriptorSets, the problem is with shader paramaters. For example in standard color graphics pipeline. What i’m doing right now is allocate new descriptor set (vkAllocateDescriptorSet) and write update (vkUpdateDescriptorSets) everytime i create a new object using that pipeline because i want those objects have different color. Yes it works, but i’m not really sure if it’s the right way to do it. Because that means if i have thousands of object i have to allocate thousands of descriptor sets from the pool. Do we have more effective and more efficient ways?

Thank’s for your help