Trying to bind two uniform buffers to vertex shader but failed without validation error

Here is a picture illustrates what I want to do:

And code snippet to implement it:
create set layout:

std::vector<VkDescriptorSetLayoutBinding> uboLayoutBinding;
	uboLayoutBinding.resize(2);

	uboLayoutBinding[0].binding = 0; //index 
	uboLayoutBinding[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
	uboLayoutBinding[0].descriptorCount = 1;
	uboLayoutBinding[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
	uboLayoutBinding[0].pImmutableSamplers = nullptr; // Optional

	uboLayoutBinding[1].binding = 1; //index 
	uboLayoutBinding[1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
	uboLayoutBinding[1].descriptorCount = 1;
	uboLayoutBinding[1].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
	uboLayoutBinding[1].pImmutableSamplers = nullptr; // Optional

	VkDescriptorSetLayoutCreateInfo layoutInfo{};
	layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
	layoutInfo.bindingCount = 2;  //the amount of VkDescriptorSetLayoutBinding
	layoutInfo.pBindings = uboLayoutBinding.data();


	if (vkCreateDescriptorSetLayout(device, &layoutInfo, nullptr, &descriptorSetLayout) != VK_SUCCESS) {
		throw std::runtime_error("failed to create descriptor set layout!");
	}

create descriptor pool:

VkDescriptorPoolSize poolSize{};
	poolSize.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
	poolSize.descriptorCount = static_cast<uint32_t>(swapChainImages.size()) * 2; 

	

	VkDescriptorPoolCreateInfo poolInfo{};
	poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
	poolInfo.poolSizeCount = 1;   //poolsize的数量
	poolInfo.pPoolSizes = &poolSize; //poolsize数组
	poolInfo.maxSets = static_cast<uint32_t>(swapChainImages.size());

	if (vkCreateDescriptorPool(device, &poolInfo, nullptr, &descriptorPool) != VK_SUCCESS) {
		throw std::runtime_error("failed to create descriptor pool!");
	}

createDescriptorSets:

VkDescriptorPoolSize poolSize{};
	poolSize.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
	poolSize.descriptorCount = static_cast<uint32_t>(swapChainImages.size());  //这是pool里面存储的descriptor总量?

	VkDescriptorPoolCreateInfo poolInfo{};
	poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
	poolInfo.poolSizeCount = 1;   //poolsize的数量
	poolInfo.pPoolSizes = &poolSize; //poolsize数组
	poolInfo.maxSets = static_cast<uint32_t>(swapChainImages.size());



	std::vector<VkDescriptorSetLayout> layouts(swapChainImages.size(), descriptorSetLayout);
	VkDescriptorSetAllocateInfo allocInfo{};
	allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
	allocInfo.descriptorPool = descriptorPool;
	allocInfo.descriptorSetCount = static_cast<uint32_t>(swapChainImages.size()) ;
	allocInfo.pSetLayouts = layouts.data();




	descriptorSets.resize(swapChainImages.size());
	if (vkAllocateDescriptorSets(device, &allocInfo, descriptorSets.data()) != VK_SUCCESS) {
		throw std::runtime_error("failed to allocate descriptor sets!");
	}


	for (size_t i = 0; i < swapChainImages.size(); i++) {
		VkDescriptorBufferInfo bufferInfo0{};
		bufferInfo0.buffer = uniformBuffers[i];
		bufferInfo0.offset = 0;
		bufferInfo0.range = sizeof(UniformBufferObject);

		VkDescriptorBufferInfo bufferInfo1{};
		bufferInfo1.buffer = uniformBuffersTest[i];
		bufferInfo1.offset = 0;
		bufferInfo1.range = sizeof(UniformBufferObjectTest);


		VkDescriptorBufferInfo descriptorBufferInfo[2] = { bufferInfo0 ,bufferInfo1 };

		VkWriteDescriptorSet descriptorWrite0{};
		descriptorWrite0.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
		descriptorWrite0.dstSet = descriptorSets[i];     //注意这里的联系把 descriptorWrite和descriptorSet联系起来了
		descriptorWrite0.dstBinding = 0;
		descriptorWrite0.dstArrayElement = 0;
		descriptorWrite0.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
		descriptorWrite0.descriptorCount = 2;
		descriptorWrite0.pBufferInfo = descriptorBufferInfo;//pBufferInfo is a pointer to an array of VkDescriptorBufferInfo structures or is ignored, as described below.
		descriptorWrite0.pImageInfo = nullptr; // Optional
		descriptorWrite0.pTexelBufferView = nullptr; // Optional



		vkUpdateDescriptorSets(device, 1, &descriptorWrite0, 0, nullptr);

	}

updateUniformBuffer every frame:

static auto startTime = std::chrono::high_resolution_clock::now();

	auto currentTime = std::chrono::high_resolution_clock::now();
	float time = std::chrono::duration<float, std::chrono::seconds::period>(currentTime - startTime).count();

	UniformBufferObject ubo{};
	//ubo.model = glm::rotate(glm::mat4(1.0f), time * glm::radians(90.0f), glm::vec3(0.0f, 0.0f, 1.0f));
	ubo.model = glm::mat4(1.0f);
	ubo.view = glm::lookAtRH(glm::vec3(0.f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, -1.0f), glm::vec3(0.0f, 1.0f, 0.0f));
	ubo.proj = glm::perspectiveRH_ZO(glm::radians(90.f), swapChainExtent.width / (float)swapChainExtent.height, 3.f, 9.0f);

	UniformBufferObjectTest ubo0{};
	//ubo.model = glm::rotate(glm::mat4(1.0f), time * glm::radians(90.0f), glm::vec3(0.0f, 0.0f, 1.0f));
	ubo0.model = glm::mat4(1.0f);
	ubo0.view = glm::lookAtRH(glm::vec3(0.f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, -1.0f), glm::vec3(0.0f, 1.0f, 0.0f));
	


	void* data;
	vkMapMemory(device, uniformBuffersMemory[currentImage], 0, sizeof(ubo), 0, &data);
	memcpy(data, &ubo, sizeof(UniformBufferObjectTest));
	vkUnmapMemory(device, uniformBuffersMemory[currentImage]);



	void* data0;
	vkMapMemory(device, uniformBuffersMemoryTest[currentImage], 0, sizeof(ubo0), 0, &data0);
	memcpy(data0, &ubo0, sizeof(UniformBufferObjectTest));
	vkUnmapMemory(device, uniformBuffersMemoryTest[currentImage]);

vertex shader:

#version 460
#extension GL_ARB_separate_shader_objects : enable

//#extension GL_KHR_vulkan_glsl : enable

#extension GL_EXT_debug_printf : enable


layout(binding = 0) uniform UniformBufferObject {
    mat4 model;
    mat4 view;
    mat4 proj;
} ubo;


layout(binding = 1) uniform UniformBufferObjectTest {
    mat4 model;
    mat4 view;

} uboShit;






layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec3 inColor;
layout(location = 2) in mat4 instanceMatrix;

layout(location = 0) out vec3 fragColor;

void main() 
{

//        debugPrintfEXT("Here are two float values \n");
//
//       debugPrintfEXT("Here's a smaller float value \n");
//
//      debugPrintfEXT("Here's an float %f with text before and after it\n",  uboShit.model[0][0]);
//
  
    gl_Position = ubo.proj * ubo.view * instanceMatrix * vec4(inPosition, 1.0);


    fragColor = inColor;
}

running without trigering any errors at validation level,renderDoc suggests that slot 1 of uniform buffer hasn’t been bound.Only one buffer is bound.

only one buffer bound

I found a link on how to bind two buffers:


And I realize my problem is caused by forgetting to create another vkwritedescriptorSet.

Sometimes you’d better distinguish layout sets so if you want to separate the sets,
you need to specify the set on the shader like this:

layout(set = 0, binding = 0) …
layout(set = 1, binding = 0) …

also, you should distinguish two different VkDescriptorSets when you make VkWriteDescriptorSet object.
finally, you need to specify the index of the set on fourth parameter when you call vkCmdBindDescriptorSets. This is important.

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.