Hello, I am new with vulkan and trying to leasrn it with helping this tutorial vulkan-tutorial com.
Now I am trying to pass two uniform object in vertex shader.
#version 450
#extension GL_ARB_separate_shader_objects : enable
layout(binding = 0) uniform UniformBufferObject {
mat4 model;
mat4 view;
mat4 proj;
} ubo;
layout(binding = 1) uniform OffsetPosition {
vec2 off;
} offsetPosition;
layout(location = 0) in vec2 inPosition;
layout(location = 1) in vec3 inColor;
layout(location = 2) in uint vertexPosition;
layout(location = 0) out vec3 fragColor;
void main() {
//do something
}
Uniform buffers is same, except of one of them is struct and second vec2;
To achive that, I create one descriptorPool
void MainVulkan::createDescriptorPool() {
VkDescriptorPoolSize poolSize{};
poolSize.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
poolSize.descriptorCount = static_cast<uint32_t>(swapChainImages.size()*20);
VkDescriptorPoolCreateInfo poolInfo{};
poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
poolInfo.poolSizeCount = 1;
poolInfo.pPoolSizes = &poolSize;
poolInfo.maxSets = static_cast<uint32_t>(swapChainImages.size()*20);
if (vkCreateDescriptorPool(device, &poolInfo, nullptr, &descriptorPool) != VK_SUCCESS) {
throw std::runtime_error("failed to create descriptor pool!");
}
}
Then one DescriptorLayer
void MainVulkan::createDescriptorSetLayout() {
VkDescriptorSetLayoutBinding uboLayoutBinding{};
uboLayoutBinding.binding = 0;
uboLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
uboLayoutBinding.descriptorCount = 1;
uboLayoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
uboLayoutBinding.pImmutableSamplers = nullptr; // Optional
VkDescriptorSetLayoutBinding offsetBinding{};
offsetBinding.binding = 1;
offsetBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
offsetBinding.descriptorCount = 1;
offsetBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
offsetBinding.pImmutableSamplers = nullptr; // Optional
VkDescriptorSetLayoutCreateInfo layoutInfo{};
layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
layoutInfo.bindingCount = 2;
VkDescriptorSetLayoutBinding arrb[]= {uboLayoutBinding, offsetBinding};
VkDescriptorSetLayoutBinding* p =arrb;
layoutInfo.pBindings =p;
if (vkCreateDescriptorSetLayout(device, &layoutInfo, nullptr, &descriptorSetLayout) != VK_SUCCESS) {
throw std::runtime_error("failed to create descriptor set layout!");
}
}
Then I allocate descriptors.
I make two call of vkAllocateDescriptorSets
func, and then update descriptor set with
void MainVulkan::createDescriptorSets() {
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!");
}
descriptorSetsVec.resize(swapChainImages.size() );
if (vkAllocateDescriptorSets(device, &allocInfo,descriptorSetsVec.data()) != VK_SUCCESS) {
throw std::runtime_error("failed to allocate descriptor sets!");
}
for (size_t i = 0; i < swapChainImages.size(); i++) {
VkDescriptorBufferInfo bufferInfo{};
bufferInfo.buffer = uniformBuffers[i];
bufferInfo.offset = 0;
bufferInfo.range = sizeof(UniformBufferObject);
VkWriteDescriptorSet descriptorWrite{};
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrite.dstSet = descriptorSets[i];
descriptorWrite.dstBinding = 0;
descriptorWrite.dstArrayElement = 0;
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
descriptorWrite.descriptorCount = 1;
descriptorWrite.pBufferInfo = &bufferInfo;
vkUpdateDescriptorSets(device, 1, &descriptorWrite, 0, nullptr);
}
for (size_t i = 0; i < swapChainImages.size(); i++) {
VkDescriptorBufferInfo bufferInfo{};
bufferInfo.buffer = uniformBuffersVec[i];
bufferInfo.offset = 0;
bufferInfo.range = sizeof(glm::vec2);
VkWriteDescriptorSet descriptorWrite{};
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrite.dstSet = descriptorSetsVec[i];
descriptorWrite.dstBinding = 1;
descriptorWrite.dstArrayElement = 0;
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
descriptorWrite.descriptorCount = 1;
descriptorWrite.pBufferInfo = &bufferInfo;
vkUpdateDescriptorSets(device, 1, &descriptorWrite, 0, nullptr);
}
}
nd then I bind data to pipeline.
vkCmdBindDescriptorSets(commandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS,
pipelineLayout, 0, 1, &descriptorSetsVec[i], 0, nullptr);
vkCmdBindDescriptorSets(commandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS,
pipelineLayout, 0, 1, &descriptorSets[i], 0, nullptr);
But, when I run program I get validation error.
validation layer: Descriptor set 0x2b bound as set #0 encountered the following validation error at vkCmdDrawIndexed() time: Descriptor in binding #1 at global descriptor index 1 is being used in draw but has not been updated.
My program works because second buffer didnt used it shader. If I swap vkCmdBindDescriptorSets
calls, I get segfault. So, somehow last call of vkCmdBindDescriptorSets
overwrites first.
Where is my mistake?