JayEff
JayEff

Reputation: 143

Vulkan: Dynamic buffer size for building/updating acceleration structures (for VK_KHR_ray_tracing)

I'm working on a Vulkan application which should benchmark a few algorithms. For this purpose I want to implement a relatively low performance algorithm as well - but still as optimal as possible of course.

The algorithm tessellates some basic geometry (currently on the CPU, a version using compute shaders is also planned). I may need to update the size of a vertex- and index buffer, unfortunately I don't really have any good metrics to guess the size yet, so I wanted to simply double the allocated memory whenever the required size is larger than the current size (or half it if that becomes viable). This should reasonably minimize memory allocations.

My plan for this is to have the VkDeviceMemory be of the current maximum size (i.e. power of 2) and then bind that to a potentially smaller buffer (of a size matching the actual vertex/index count)... But that doesn't seem feasible, since to query for required memory size, I need to pass an already created VkBuffer to vkGetBufferMemoryRequirements. I could, of course, create both buffer and device memory with the current maximum size and tell whatever is using them the actual size, but this is where it gets a little complicated:

My application uses raytracing (specifically the KHR extension), meaning these buffers will be passed to the acceleration structure build system of vulkan and I'm not entirely sure how to tell this system what part of the buffer to use. Here's how the acceleration structure is being built: (link to NVIDIA's tutorial) (Naturally I will have to modify this to allow updating the acceleration structure, not just creating it...). My guess is that I can pass this number via VkAccelerationStructureCreateGeometryTypeInfoKHR::maxVertexCount and maxPrimitiveCount, but the vulkan specs state:

maxPrimitiveCount describes the maximum number of primitives that can be built into an acceleration structure geometry. maxVertexCount describes the maximum vertex count that can be used to build an acceleration structure geometry when geometryType is VK_GEOMETRY_TYPE_TRIANGLES_KHR.

Unfortunately I'm not quite clear on whether that's what I'm looking for or not. Other than that, the buffers are passed to the build system directly via a VkDeviceAddress and I don't see another way to influence the number of vertices to be read from the buffer.

Is there a sensible way to do what I want to do, or will it be best to simply create a new buffer and allocate new memory (each of the actual size) every time my requirements change? How bad would that be for the performance?

Upvotes: 0

Views: 1322

Answers (1)

Amin
Amin

Reputation: 553

Unfortunately, i don't have much experience with the ray-tracing extension, but two things comes to my mind that may prove to be helpful:

First, from what i understand of the situation, you can pre-allocate a number of large buffers like a pool of them. They can increase in size by power of 2 for example. this way you do not have to allocate extra buffers in middle of the test again.

Second, you can use dynamic uniform buffers. Just make the biggest one possible, and then bind the descriptor set by a offset inside that buffer. If the uniform buffer maximum size was not big enough for the job, you can move to storage buffers; they have dynamic versions too.

Here are some specifications links to start off from:

Upvotes: 1

Related Questions