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.