当前位置: 首页> 文旅> 旅游 > Vulkan描述符、描述符Pool、Layout概念

Vulkan描述符、描述符Pool、Layout概念

时间:2025/8/25 18:17:25来源:https://blog.csdn.net/zxbcollegestudent/article/details/141969758 浏览次数:0次

  1、DescriptorSetLayout为了组织和管理着色器资源(如缓冲区、纹理、采样器等),多个相同类型的Descriptor放在一个Layout中以优化GPU对资源的访问

  //DescriptorSetLayout定义了哪些描述符Descriptor类型(Buffers、Textures、Samplers)可以包含在其中

VkDescriptorSetLayoutBinding layoutBinding = {
        0, // binding
        VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,//DescriptorSetLayout布局中的描述符类型,表明只有UNIFORM Buffer才能包含在下面创建的DescriptorSetLayout中
        1,//descriptorCount
        VK_SHADER_STAGE_VERTEX_BIT,//stageFlags
        nullptr
    };
 
    VkDescriptorSetLayoutCreateInfo descLayoutInfo{};
    descLayoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
    descLayoutInfo.bindingCount = 1;
    descLayoutInfo.pBindings = &layoutBinding;

    err = m_devFuncs->vkCreateDescriptorSetLayout(dev, &descLayoutInfo, nullptr, &m_descSetLayout);
    if (err != VK_SUCCESS)
        qFatal("Failed to create descriptor set layout: %d", err);

 2、DescriptorPool

    //每种类型的 Descriptor,如 Uniform Buffers、Sampled Images、Storage Buffers、Textures 等,每个Descriptor包含了指向实际资源的引用。
    VkDescriptorPoolSize descPoolSizes{};  //也可以声明为vector<VkDescriptorPoolSize>以指定多种 Descriptor 类型
    descPoolSizes.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;//描述符类型
    descPoolSizes.descriptorCount = static_cast<uint32_t>(concurrentFrameCount); //UNIFORM缓冲的数量
    
    VkDescriptorPoolCreateInfo poolInfo{};
    poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
    poolInfo.pNext = nullptr;
    poolInfo.maxSets = static_cast<uint32_t>(concurrentFrameCount);
    poolInfo.poolSizeCount = 1;
    poolInfo.pPoolSizes = &descPoolSizes;
    if (m_devFuncs->vkCreateDescriptorPool(dev, &poolInfo, nullptr, &m_descPool) != VK_SUCCESS)
    {
        throw std::runtime_error("echec de la creation de la pool de descripteurs!");
    }

用于分配描述符DescriptorSet的DescriptorPool和用于组织和管理描述符Descriptor的DescriptorSetLayout都已经准备好了,接下来就是创建DescriptorSet了,只要完成了这一步,后面就可以把创建的Descriptor写入DescriptorSet中了

 3、DescriptorSet

     std::vector<VkDescriptorSetLayout> layouts(concurrentFrameCount, m_descSetLayout);
    VkDescriptorSetAllocateInfo allocInfo{};
    allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
    allocInfo.pNext = nullptr;
    allocInfo.descriptorPool = m_descPool;
    allocInfo.descriptorSetCount = static_cast<uint32_t>(concurrentFrameCount);
    allocInfo.pSetLayouts = layouts.data();
    //Descriptor Set(描述符集)是一组Descriptor的集合
    m_descriptorSets.resize(concurrentFrameCount);
    if (m_devFuncs->vkAllocateDescriptorSets(dev, &allocInfo, m_descriptorSets.data()) != VK_SUCCESS)
    {
        throw std::runtime_error("echec de l'allocation d'un set de descripteurs!");
    }

 DescriptorSet现在已经在DescriptorSetLayout中了。

 最开始创建的Uniform Buffers描述符:

    VkDeviceSize bufferSize = sizeof(UniformBufferObject);
    m_uniformBuffers.resize(concurrentFrameCount); // concurrentFrameCount correspond à swapchainimages.size()
    m_uniformBuffersMemory.resize(concurrentFrameCount);
    for (size_t i = 0; i < concurrentFrameCount; i++)
    {
        createBuffer(bufferSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, 
            VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
            m_uniformBuffers[i], 
            m_uniformBuffersMemory[i]);
    }

 4、接下来把描述符 m_uniformBuffers 写入DescriptorSet中

void Renderer::flushTexToDescriptorSet(VkDevice dev, int concurrentFrameCount)
{
    for (int i = 0; i < concurrentFrameCount; ++i) {

        VkDescriptorBufferInfo uniformBufferInfo{};
        uniformBufferInfo.buffer = m_uniformBuffers[i];//创建的VkBuffer描述符类型
        uniformBufferInfo.offset = 0;
        uniformBufferInfo.range = sizeof(UniformBufferObject);

        VkWriteDescriptorSet descriptorWrite{};
        descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
        descriptorWrite.pNext = NULL;
        descriptorWrite.dstSet = m_descriptorSets[i];//写入到索引i的DescriptorSet中
        descriptorWrite.dstBinding = 0;
        descriptorWrite.dstArrayElement = 0;
        descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
        descriptorWrite.descriptorCount = 1;
        descriptorWrite.pBufferInfo = &uniformBufferInfo;
        descriptorWrite.pImageInfo = nullptr; // Optionnel
        descriptorWrite.pTexelBufferView = nullptr; // Optionnel

        m_devFuncs->vkUpdateDescriptorSets(dev, 1, &descriptorWrite, 0, nullptr);//写入
    }
}

5、渲染管线VkPipeline ,定义了渲染各个阶段配置,如下图整个渲染大致流程。

    pipelineInfo.layout = m_pipelineLayout;
    pipelineInfo.renderPass = m_window->defaultRenderPass();

    err = m_devFuncs->vkCreateGraphicsPipelines(dev, m_pipelineCache, 1, &pipelineInfo, nullptr, &m_pipeline);
    if (err != VK_SUCCESS)
        qFatal("Failed to create graphics pipeline: %d", err);

所有工作准备好了,接下来Start frame render

    VkCommandBuffer cmdBuf = m_window->currentCommandBuffer();

//开始render
    m_devFuncs->vkCmdBeginRenderPass(cmdBuf, &rpBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
.................

//本次渲染使用的管线配置

    m_devFuncs->vkCmdBindPipeline(cb, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline);
................

//本次渲染使用的描述符资源DescriptorSet

    m_devFuncs->vkCmdBindDescriptorSets(cb, VK_PIPELINE_BIND_POINT_GRAPHICS,
        m_pipelineLayout, 
        0, 
        1, 
        &m_descriptorSets[currFrameIdx], 
        0, 
        nullptr);

............

//录制命令

m_devFuncs->vkCmdDrawIndexed(cb, indices.size(), 1, 0, 0, 0);

//结束render

m_devFuncs->vkCmdEndRenderPass(cmdBuf);

 参考:Vulkan的DescriptorSet理解_vkallocatedescriptorsets-CSDN博客

关键字:Vulkan描述符、描述符Pool、Layout概念

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: