vulkan计算管线描述符集创建

下面的示例是在Vulkan计算管线中创建描述符池和描述符集,并在计算管线中调用它们。首先创建两个描述符集合:

1. 描述符集0:包含两个绑定点,每个绑定点有3个描述符。
2. 描述符集1:包含一个绑定点,有4个描述符。

我们将在同一个计算管线中使用这些描述符。

1. 定义描述符布局

首先定义描述符布局,描述符布局将设定每个绑定点及其对应的描述符类型和数量。这里假设Set 0, Binding 0有三个UNIFORM_BUFFER描述符,Set 0, Binding 1有三个STORAGE_BUFFER描述符,Set 1, Binding 0有四个STORAGE_BUFFER描述符。代码如下:

VkDescriptorSetLayoutBinding bindings0[2];

// Set 0, Binding 0: uniform buffer with 3 descriptors
bindings0[0].binding = 0;
bindings0[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
bindings0[0].descriptorCount = 3;
bindings0[0].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
bindings0[0].pImmutableSamplers = nullptr;

// Set 0, Binding 1: storage buffer with 3 descriptors
bindings0[1].binding = 1;
bindings0[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
bindings0[1].descriptorCount = 3;
bindings0[1].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
bindings0[1].pImmutableSamplers = nullptr;

VkDescriptorSetLayoutCreateInfo layoutInfo0 = {};
layoutInfo0.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
layoutInfo0.bindingCount = 2;
layoutInfo0.pBindings = bindings0;

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

VkDescriptorSetLayoutBinding bindings1;

// Set 1, Binding 0: storage buffer with 4 descriptors
bindings1.binding = 0;
bindings1.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
bindings1.descriptorCount = 4;
bindings1.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
bindings1.pImmutableSamplers = nullptr;

VkDescriptorSetLayoutCreateInfo layoutInfo1 = {};
layoutInfo1.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
layoutInfo1.bindingCount = 1;
layoutInfo1.pBindings = &bindings1;

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

2. 创建描述符池

接下来创建描述符池。描述符池管理描述符集合的内存分配。

VkDescriptorPoolSize poolSizes[] = {
    { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 3 },
    { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 7 }
};

VkDescriptorPoolCreateInfo poolInfo = {};
poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
poolInfo.poolSizeCount = 2;
poolInfo.pPoolSizes = poolSizes;
poolInfo.maxSets = 2;

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

3. 分配描述符集

接下来,根据布局从描述符池中分配描述符集。

VkDescriptorSetLayout layouts[] = { setLayout0, setLayout1 };

VkDescriptorSetAllocateInfo allocInfo = {};
allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
allocInfo.descriptorPool = descriptorPool;
allocInfo.descriptorSetCount = 2;
allocInfo.pSetLayouts = layouts;

VkDescriptorSet descriptorSets[2];
if (vkAllocateDescriptorSets(device, &allocInfo, descriptorSets) != VK_SUCCESS) {
    throw std::runtime_error("failed to allocate descriptor sets!");
}

4. 更新描述符集

将实际的buffer绑定到描述符集合中。

VkDescriptorBufferInfo bufferInfos0[3];
bufferInfos0[0] = { buffer0, 0, VK_WHOLE_SIZE };
bufferInfos0[1] = { buffer1, 0, VK_WHOLE_SIZE };
bufferInfos0[2] = { buffer2, 0, VK_WHOLE_SIZE };

VkDescriptorBufferInfo bufferInfos1_0[3];
bufferInfos1_0[0] = { buffer3, 0, VK_WHOLE_SIZE };
bufferInfos1_0[1] = { buffer4, 0, VK_WHOLE_SIZE };
bufferInfos1_0[2] = { buffer5, 0, VK_WHOLE_SIZE };

VkDescriptorBufferInfo bufferInfos2[4];
bufferInfos2[0] = { buffer6, 0, VK_WHOLE_SIZE };
bufferInfos2[1] = { buffer7, 0, VK_WHOLE_SIZE };
bufferInfos2[2] = { buffer8, 0, VK_WHOLE_SIZE };
bufferInfos2[3] = { buffer9, 0, VK_WHOLE_SIZE };

VkWriteDescriptorSet descriptorWrites[3];

// Set 0, Binding 0: uniform buffers
descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrites[0].dstSet = descriptorSets[0];
descriptorWrites[0].dstBinding = 0;
descriptorWrites[0].dstArrayElement = 0;
descriptorWrites[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
descriptorWrites[0].descriptorCount = 3;
descriptorWrites[0].pBufferInfo = bufferInfos0;

// Set 0, Binding 1: storage buffers
descriptorWrites[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrites[1].dstSet = descriptorSets[0];
descriptorWrites[1].dstBinding = 1;
descriptorWrites[1].dstArrayElement = 0;
descriptorWrites[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
descriptorWrites[1].descriptorCount = 3;
descriptorWrites[1].pBufferInfo = bufferInfos1_0;

// Set 1, Binding 0: storage buffers
descriptorWrites[2].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrites[2].dstSet = descriptorSets[1];
descriptorWrites[2].dstBinding = 0;
descriptorWrites[2].dstArrayElement = 0;
descriptorWrites[2].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
descriptorWrites[2].descriptorCount = 4;
descriptorWrites[2].pBufferInfo = bufferInfos2;

vkUpdateDescriptorSets(device, 3, descriptorWrites, 0, nullptr);

5. 创建计算管线

接下来,我们将创建计算管线,并绑定描述符集。

VkPipelineLayout pipelineLayout;

VkPipelineLayoutCreateInfo pipelineLayoutInfo = {};
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipelineLayoutInfo.setLayoutCount = 2;
VkDescriptorSetLayout setLayouts[] = { setLayout0, setLayout1 };
pipelineLayoutInfo.pSetLayouts = setLayouts;

if (vkCreatePipelineLayout(device, &pipelineLayoutInfo, nullptr, &pipelineLayout) != VK_SUCCESS) {
    throw std::runtime_error("failed to create pipeline layout!");
}

VkPipeline computePipeline;
VkComputePipelineCreateInfo pipelineInfo = {};
pipelineInfo.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
pipelineInfo.stage = computeShaderStageInfo; // Assume computeShaderStageInfo is already defined
pipelineInfo.layout = pipelineLayout;

if (vkCreateComputePipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &computePipeline) != VK_SUCCESS) {
    throw std::runtime_error("failed to create compute pipeline!");
}

6. 绑定描述符集并调度计算管线

最后,我们将绑定描述符集,并调度计算管线。

VkCommandBufferBeginInfo beginInfo = {};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;

vkBeginCommandBuffer(commandBuffer, &beginInfo);
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, computePipeline);
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0, 2, descriptorSets, 0, nullptr);
vkCmdDispatch(commandBuffer, 1, 1, 1);

if (vkEndCommandBuffer(commandBuffer) != VK_SUCCESS) {
    throw std::runtime_error("failed to record command buffer!");
}

到这里就完成Vulkan计算管线创建并配置复杂的描述符池和描述符集,并在计算管线中调用。

  • 8
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值