1

I recently re-wrote some code to use Shader Storage Buffer Object in OpenGL, to send in dynamic sized arrays into GLSL, vastly increasing performance when drawing many procedurally generated objects.

What I have is a couple of thousand points, and for each point I render a procedurally generated circular billboard. Each one can in turn have different colors and radius, as well as a few other characteristics (represented as bools or enums)

I fill a vector with these positions, packed together with the radius and color. Then I upload it as a Shader Storage Buffer Object with dynamic size. I create a dummy VAO, containing 0 vbos, but call the draw command with the same amount of points that I have. Inside the shader, I then iterate through this array, using the gl_VertexID, and generate a quad (two triangles) with texture coordinates, for each point.

I'm looking for a way of doing the same in Vulkan. Is there some way in Vulkan, to pass a dynamic sized array into a shader? Reading about Shader Storage Buffer objects in Graham Seller's Vulkan book, it only mentions them being read-write, but not capable of dynamically sized arrays.

Edit: It seems that storage buffers are in fact capable of dynamic sized arrays, based on Sasha Willems particle example. Is there a way of doing the same thing via uniforms?

2
  • 1
    It sounds like you could use tesselation, instancing or the geometry shader to get the same effect and put the per-billboard data in a vertex attribute. Commented Aug 3, 2017 at 10:11
  • 1
    @ratchetfreak: Thanks, they're all three different possibilities of solving the same problem. I've also implemented it using geometry shaders and vertex attributes (but still generating the triangles in the vertex shader), and they were all fun ways of doing it! I was a bit hesitant to using geometry shaders though, since you see so many people complaining about their lack of performance. Commented Aug 3, 2017 at 20:23

1 Answer 1

3

I may be misunderstanding your question. SSBOs have identical behavior and functionality between the two APIs. That's why they're named the same. An unbounded array at the end of a storage block will have its length defined at runtime, based on what data you provide.

The size of a buffer descriptor is not hard coded into the descriptor set layout; it's something you set with VkWriteDescriptorSet. Now unlike the offset, you cannot change a descriptor set's size without changing the descriptor itself. That is, you don't have an equivalent to vkCmdBindDescriptorSets's pDynamicOffsets field. So you have to actually update the descriptor in-situ to change the length.

But that just requires double-buffering your descriptor set; it shouldn't be a problem.

Is there a way of doing the same thing via uniforms?

Again, the answer is the same for Vulkan as for OpenGL: no.

Sign up to request clarification or add additional context in comments.

1 Comment

Than you Nicol, I think that answers my question! Of course you are completely right that the SSBO is the same, I misunderstood the description in Seller's book, since he didn't specifically mention the wonderful ability of using unbounded arrays (as the last member of a storage block).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.