Compute Shader Reduction

I am trying to implement efficient reduction of arrays in Vulkan and I am running into an issue with the shader module and dynamic buffer sizes.

For my first attempt, I am just writing a shader in SPIR-V assembly to sum a vector of integers. My approach is to do multiple shader dispatches on the vector where each unit takes two sequential numbers in the vector, adds them, and then writes them into an output vector. So, each pass, half of the vector is reduced, and the process is repeated until a scalar value is left. The descriptor set layout is one descriptor set with two bindings, one for the input vector, and one for the output. The descriptor sets are defined for each pass of the shader and point to different offsets in the same buffer. For each pass, the command buffer is written to bind the descriptor set for the pass and then dispatch the pass based on the input size. The issue I have is I’m not certain how to write a SPIR-V shader to work with this. I can’t figure out how to define the size of the input and output buffers dynamically for each pass. I tried doing it with pointer math only to realize that the required capabilities aren’t supported by Vulkan (Kernel, Addressing). Is there a way to do this other than creating a specialization constant and creating a pipeline for each pass of the shader module?

Could you not simply use an unbounded array and pass the size as a push_constant?

Push constants look like they should do the trick. Sorry for the silly question. I am new to Vulkan, and this was an important piece of resource management I was still missing in my understanding.

Thank you very much. I will report back once I change the code and retry.

Actually, I’m a little confused about how I can specify unbounded arrays in SPIR-V. Looking through the Specification, OpTypeRuntimeArray seems to be the only array type that doesn’t require a length, but it’s poorly documented and sounds as if it needs to be encoded with a length (an assumption I make from the existence of the OpArrayLength, but maybe I’m just misunderstanding something). It would be great if I could just index off of a pointer and trust that the math is correct, I just don’t understand how to without the Addressing capability.

Sorry for my noob questions. I haven’t been able to find any solid examples around this kind of usage of SPIR-V directly. Thank you in advance.

There’s nothing in OpTypeRuntimeArray that requires it “to be encoded with a length”. OpArrayLength computes the length of the array, based on the size of the VkBuffer you attach to that resource, the size of each element of the array, and the number of other variables sharing that buffer.

That’s what the Addressing capability is for: to let you know when you can and cannot do precisely that. And when writing shaders, you cannot.

That’s because most people don’t use SPIR-V directly. It’s an intermediate representation; it’s not really meant to be used directly.

Thank you for helping me with that bit of information. I got my program working now.