vulkan/descriptorSet
先说结论:
VkDescriptorSetLayout 与 VkDescriptorSet 不是一一对应,
VkDescriptorSetLayout 可以有很多,VkDescriptorSet 是一个对 VkDescriptorSetLayout 的任意组合
与 destr
参考Shader
layout(binding = 0) uniform UniformBufferObject { mat4 model; mat4 view; mat4 proj; } ubo; layout(location = 0) in vec2 inPosition; layout(location = 1) in vec3 inColor; layout(location = 2) in vec2 inTexCoord; layout(location = 0) out vec3 fragColor; layout(location = 1) out vec2 fragTexCoord; void main() { gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition, 0.0, 1.0); fragColor = inColor; fragTexCoord = inTexCoord; }
layout(location = 0) in vec2 fragTexCoord; layout(location = 0) out vec4 outColor; layout(binding = 1) uniform sampler2D texSampler; void main() { outColor = texture(texSampler, fragTexCoord); }
1. 是vs的uniform UniformBufferObject;需要vulkan传入对应的uniform buffer数据,
2. 是ps的uniform sampler2D texSampler,需要vulkan传入Sampler需要sample哪个image,以及sample的采样模式信息。
那么 vulkan 中需要对 uniform 进行抽象封装:
VkDescriptorSetLayoutBinding ubo = {}; ubo.binding = 0; ubo.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; ubo.descriptorCount = 1;
VkDescriptorSetLayoutBinding samplerLayoutBinding{}; samplerLayoutBinding.binding = 1; samplerLayoutBinding.descriptorCount = 1; samplerLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;//point out this descript type is sampler samplerLayoutBinding.pImmutableSamplers = nullptr; samplerLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
其中重要的信息点: binding 对应 layout(binding = ? )
- binding = 0 的 VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER 对象,只作用于vertex shader
- binding = 1 的 VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER对象,作用于fragment shader
将这两类descriptor type封装到各自的VkDescriptorSetLay
std::array<VkDescriptorSetLayoutBinding, 2> bindings = {ubo, samplerLayoutBinding}; VkDescriptorSetLayoutCreateInfo layoutInfo{}; layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; layoutInfo.bindingCount = 2; layoutInfo.pBindings = bindings.data(); if (vkCreateDescriptorSetLayout(vulkanDevice->device, &layoutInfo, nullptr, &descriptorSetLayout) != VK_SUCCESS) { throw std::runtime_error("failed to create descriptor set layout!"); }
这里需要是创建layout ,但是并没有给定数据,具体给什么数据,则由于 VkDescriptorSet 指定
std::vector<VkDescriptorSetLayout> layouts(MAX_FRAMES_IN_FLIGHT, descriptorSetLayout); VkDescriptorSetAllocateInfo allocInfo{}; allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; allocInfo.descriptorPool = descriptorPool; allocInfo.descriptorSetCount = static_cast<uint32_t>(MAX_FRAMES_IN_FLIGHT); allocInfo.pSetLayouts = layouts.data(); //layout has uniform format information(descriptorSetLayout) //create descrpitsets array descriptorSets.resize(MAX_FRAMES_IN_FLIGHT); if (vkAllocateDescriptorSets(vulkanDevice->device, &allocInfo, descriptorSets.data()) != VK_SUCCESS) { throw std::runtime_error("failed to allocate descriptor sets!"); }
数据上传:
for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { VkDescriptorBufferInfo bufferInfo{}; bufferInfo.buffer = uniformBuffers[i]; bufferInfo.offset = 0; bufferInfo.range = sizeof(UniformBufferObject); /*binding sampler and vkImage here*/ VkDescriptorImageInfo imageInfo{}; imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; imageInfo.imageView = textureImageView; imageInfo.sampler = textureSampler; //this struct link descript set we created before in this function and uniform buffer created before std::array<VkWriteDescriptorSet, 2> descriptorWrites{}; descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; descriptorWrites[0].dstSet = descriptorSets[i]; //get descriptor set object descriptorWrites[0].dstBinding = 0;//uniform buffer , now it is set as 0 in shader descriptorWrites[0].dstArrayElement = 0;//descriptor can be array so we specify 0 descriptorWrites[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;//descriptor type is uniform descriptorWrites[0].descriptorCount = 1;// descriptorWrites[0].pBufferInfo = &bufferInfo;//link uniform buffer descriptorWrites[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; descriptorWrites[1].dstSet = descriptorSets[i]; descriptorWrites[1].dstBinding = 1; //binding code relate to shader code : layout(binding = 1) uniform sampler2D texSampler; descriptorWrites[1].dstArrayElement = 0; descriptorWrites[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;//descriptor type is sampler descriptorWrites[1].descriptorCount = 1; descriptorWrites[1].pImageInfo = &imageInfo;//link image info with vkImage and sampler //link descript set(include descript layout (uniform data format)) and uniform buffer vkUpdateDescriptorSets(vulkanDevice->device, static_cast<uint32_t>(descriptorWrites.size()), descriptorWrites.data(), 0, nullptr); }