在Vulkan中实现“实例渲染”的正确方法是什么?

时间:2019-02-10 18:15:40

标签: c++ instance vulkan

我目前正在尝试有效地渲染多个多维数据集,所以我想知道如何在Vulkan中使用此“实例渲染”。

我目前仅知道两种渲染大量(相同)对象的方法:

1)多个描述符集;

2)具有动态统一/动态偏移量的单个描述符集;

在第一种情况下,浪费了很多内存,因为每个多维数据集只需要一个不同的模型矩阵,但是每个多维数据集仍使用整个DescriptorSet:而且,因为我在每个帧上都注册了一个新的命令缓冲区,所以每个多维数据集都需要花费我2个“ Cmd”电话:

vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, descriptorSet, 0, nullptr);
vkCmdDraw(commandBuffer, numberOfVertices, 1, 0, 0);

但是,对于许多多维数据集,这将导致不小的CPU负载和内存浪费。

在第二种情况下,我只需要一个DescriptorSet,就可以将模型矩阵注册为动态制服,并用所有模型矩阵填充它; 但是,对于每个多维数据集,我仍然需要(只需进行少量修改)相同的2个“ Cmd”调用:

vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, descriptorSet, 1, index);
vkCmdDraw(commandBuffer, numberOfVertices, 1, 0, 0);

像以前一样,对于许多多维数据集,尽管使用唯一的DescriptorSet节省了大量内存,但CPU负载仍然困扰着我。

所以我听说了这种“实例化渲染”,应该以一个命令以某种方式告诉它绘制所有多维数据集,并为其提供模型矩阵的集合(可能仍然是一个缓冲区)。

如何执行此操作,从而阻止我的程序使用单个调用在单个命令缓冲区中注册成千上万个“ Cmd”?谢谢。

2 个答案:

答案 0 :(得分:3)

您将一个顶点属性设置为具有VkVertexInputBindingDescription::inputRate == VK_VERTEX_INPUT_RATE_INSTANCE。然后,您将必要的数据进行偏移并旋转到装箱中。

另一个选择是使用内置变量的顶点着色器,该变量指示正在处理的实例。您可以使用它索引到SSBO或UBO中以获取所需的数据。

答案 1 :(得分:0)

在您的代码中:

vkCmdDrawIndexed(command_buffer, indices_size, instance_count, 0, 0, instance_first_index);

  • instance_count:要绘制的实例数
  • instance_first_index:第一个实例将具有此ID

然后在您的顶点着色器中使用变量 gl_InstanceIndex ,该变量包含以 instance_first_index

开头的实例ID。

[1] https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/vkCmdDrawIndexed.html