Issues with vertex input attributes

Hi everyone,

I’m rendering points, and I have some issues with vertex attribute data being random where it shouldn’t. I’m using a single binding for 2 attributes (vec4), and I don’t want the attributes to be interleaved. That’s why I’m using a single buffer of size 2N split in two, with the data of attribute 0 in [0, N) and the data of attribute 1 in [N,2N). I double checked how I created the buffer and memory, and the data I wrote is correct.

Here is my code :


// Buffer update
vkMapMemory(device, hostMemory, 0, 2*sizeof(glm::vec4)*n, 0, &data);
memcpy(data, ....);
vkUnmapMemory(device, hostMemory);

// Vertex Input State
std::vector<VkVertexInputBindingDescription> bindings = {
	{0, sizeof(glm::vec4), VK_VERTEX_INPUT_RATE_VERTEX},
};
std::vector<VkVertexInputAttributeDescription> attributes = {
	{0, 0, VK_FORMAT_R32G32B32A32_SFLOAT, 0}, 
	{1, 0, VK_FORMAT_R32G32B32A32_SFLOAT, sizeof(glm::vec4)*n}
};

// Vertex buffer bind
VkDeviceSize offsets[] = {0};
vkCmdBindVertexBuffers(cb, 0, 1, &hostBuffer, offsets);

// Draw 
vkCmdDraw(cb, n, 1, 0, 0);

Is my understanding of binding and attributes wrong? Or did I miss something?

Thank you for your time.

[QUOTE=PLeLuron;41462]Hi everyone,

I’m rendering points, and I have some issues with vertex attribute data being random where it shouldn’t. I’m using a single binding for 2 attributes (vec4), and I don’t want the attributes to be interleaved.[/quote]

Then you should treat them, within your input code, as two separate bindings.

You can only have two attributes use the same bindings if those attributes are interleaved. This is because the per-attribute offset, VkVertexInputAttributeDescription::offset, is restricted to being no greater than VkPhysicalDeviceLimits:: maxVertexInputAttributeOffset. And the smallest that can be is 2047.

So you should give each attribute needs to use a separate binding:


VkVertexInputBindingDescription bindings[] = {
  {0, sizeof(glm::vec4), VK_VERTEX_INPUT_RATE_VERTEX},
  {1, sizeof(glm::vec4), VK_VERTEX_INPUT_RATE_VERTEX},
};

VkVertexInputAttributeDescription> attributes[] = {
  {0, 0, VK_FORMAT_R32G32B32A32_SFLOAT, 0}, 
  {1, 1, VK_FORMAT_R32G32B32A32_SFLOAT, 0}, //zero offset from the beginning of the second binding.
};

...


VkDeviceSize offsets[] = {0, n * sizeof(glm::vec4)};
VkBuffer buffers[] = {hostBuffer, hostBuffer}; //Both bindings use the same buffer object. That's fine.
vkCmdBindVertexBuffers(cb, 0, std::size(offsets), buffers, offsets);

doing 1 attribute works? And if you test only the second attribute?

Also is the VkPhysicalDeviceLimits.maxVertexInputAttributeOffset high enough that your sizeof(glm::vec4)*n is still less than it? By default it’s 2047

The maxOffset is too small then you will need separate bindings for the attributes.

Thank you, this solves it.