简体   繁体   English

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

[英]What's the correct way to implement "Instanced rendering" in Vulkan?

I'm currently trying to render multiple cubes efficiently, so I'd like to know how to use this "Instanced Rendering" in Vulkan.我目前正在尝试有效地渲染多个立方体,所以我想知道如何在 Vulkan 中使用这种“实例化渲染”。

I currently know of only 2 ways of rendering a lot of (identical) objects:我目前只知道 2 种渲染大量(相同)对象的方法:

1) Multiple DescriptorSets; 1) 多个描述符集;

2) Single DescriptorSet with Dynamic Uniforms / dynamic offsets; 2) 具有动态统一/动态偏移的单个 DescriptorSet;

In the first case, a lot of memory is wasted because the cubes only need a different model matrix each, but still using an entire DescriptorSet each: also, because I'm registering a new command buffer each frame, every cube cost me 2 'Cmd' calls:在第一种情况下,大量内存被浪费了,因为每个立方体只需要一个不同的模型矩阵,但每个立方体仍然使用整个 DescriptorSet:此外,因为我每帧都注册一个新的命令缓冲区,每个立方体花费了我 2 ' Cmd' 调用:

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

But, for a lot of cubes, this results in a not insignificant CPU load, and a waste of memory.但是,对于很多多维数据集来说,这会导致 CPU 负载相当大,并且会浪费内存。

In the second case, I only need a single DescriptorSet, registering the model matrix as a Dynamic Uniform and filling it with all the model matrices;在第二种情况下,我只需要一个 DescriptorSet,将模型矩阵注册为动态统一并用所有模型矩阵填充它; However, I still need (with little modifications) the same 2 'Cmd' calls for each cube:但是,我仍然需要(稍加修改)对每个多维数据集进行相同的 2 个“Cmd”调用:

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

As before, for a lot of cubes, despite the huge memory save for using a unique DescriptorSet, the CPU load still bothers me.和以前一样,对于很多多维数据集,尽管使用独特的 DescriptorSet 节省了大量内存,但 CPU 负载仍然困扰着我。

So I heard about this "Instanced rendering", that should somehow tell with a single command to draw all the cubes, providing it a collection of model matrices (Probably still a Buffer).所以我听说过这个“实例化渲染”,它应该以某种方式告诉一个命令来绘制所有的立方体,为它提供一个模型矩阵的集合(可能仍然是一个缓冲区)。

How to do this, preventing my program to register thousands of 'Cmd' in a single command buffer, using a single call?如何做到这一点,防止我的程序使用单个调用在单个命令缓冲区中注册数千个“Cmd”? Thanks.谢谢。

You set one of the vertex attributes to have VkVertexInputBindingDescription::inputRate == VK_VERTEX_INPUT_RATE_INSTANCE .您将顶点属性之一设置为VkVertexInputBindingDescription::inputRate == VK_VERTEX_INPUT_RATE_INSTANCE Then you put the necessary data to offset and rotate into the attibute.然后你把必要的数据来偏移和旋转到属性中。

Another option is to use the vertex shader built in variable which indicates which instance that is being processed.另一种选择是使用内置变量的顶点着色器,该变量指示正在处理的实例。 You can use that to index into a SSBO or UBO to get the data you need.您可以使用它来索引 SSBO 或 UBO 以获取您需要的数据。

in your code:在您的代码中:

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

  • instance_count: number of instances to draw instance_count:要绘制的实例数
  • instance_first_index: first instance will have this id instance_first_index:第一个实例将具有此 ID

in your vertex shader you can then use variable gl_InstanceIndex which contains the instance id starting with instance_first_index在你的顶点着色器就可以使用可变gl_InstanceIndex其中包含实例ID开始instance_first_index

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM