2
\$\begingroup\$

I am trying to create a Vulkan Storage Space Buffer Object which contains an array of structs for use in my vertex shader. I believe I'm missing something fundamental here because the 1st struct in the array works but all others give garbage data. Heres what I'm doing:

C++ I've got a simple struct defined:

struct InstanceData {
    glm::mat4 model;
};

Later on I have a vector of these structs which I push data into:

std::vector<InstanceData> instanceData;
instanceData.push_back(InstanceData());
instanceData.push_back(InstanceData());

And finally memcpy the data from our vector into our VkBuffer (managed by VMA):

memcpy(instanceStorageSpaceAllocations[currentImage]->GetMappedData(), instanceData.data(), sizeof(InstanceData) * instanceData.size());

In our vertex shader, I am attempting to access this data like so:

layout(std140, binding = 0) readonly buffer InstanceData {
    mat4 model;
} ssbo[];

void main() {
    gl_Position = PushConstants.view_proj * ssbo[gl_InstanceIndex].model * inPosition;
}

Back in C++, we VkCmdDrawIndexed with the amount of instances currently in our instanceData vector:

vkCmdDrawIndexed(CmdBuffer, static_cast<uint32_t>(_GLTF->Indices.size()), 1, instanceData.size()-1, 0, 0);

So, however many instances of InstanceData we push into our instanceData vector will be drawn by the GPU.

When setting up our SSBO descriptor we do like so:

VkDescriptorBufferInfo bufferInfo = {};
    bufferInfo.buffer = StorageBuffers[i];
    bufferInfo.offset = 0;
    bufferInfo.range = VK_WHOLE_SIZE;

VK_WHOLE_SIZE is used here so it uses the entire size of the VkBuffer (because we will resize the buffer when it becomes to small to hold all our InstanceData objects).

So this works for the 1st instanced draw (when instanceData.size() == 1), but any after results in garbage data when accessing the SSBO from within our shader.

Any ideas about what I'm doing wrong here..?

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

I was doing 3 things wrong here.

First, the parameters of my VkDrawIndexed call were swapped:

vkCmdDrawIndexed(CmdBuffer, static_cast<uint32_t>(_GLTF->Indices.size()), instanceData.size(), 0, 0, 0);

Second, my shader was incorrectly accessing the data:

layout(std140, binding = 0) readonly buffer InstanceData {
    mat4 model[];
} ssbo;

void main() {
    gl_Position = PushConstants.view_proj * ssbo.model[gl_InstanceIndex] * inPosition;
}

Third, even though I was using VK_WHOLE_SIZE when setting up the SSBO Descriptor, I needed to call VkUpdateDescriptorSets again after every time that I increase the size of the SSBO VkBuffer.

All works as expected now.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .