简体   繁体   中英

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.

I currently know of only 2 ways of rendering a lot of (identical) objects:

1) Multiple DescriptorSets;

2) Single DescriptorSet with Dynamic Uniforms / dynamic offsets;

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:

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.

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; However, I still need (with little modifications) the same 2 'Cmd' calls for each cube:

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.

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? Thanks.

You set one of the vertex attributes to have 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.

in your code:

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

  • instance_count: number of instances to draw
  • instance_first_index: first instance will have this id

in your vertex shader you can then use variable gl_InstanceIndex which contains the instance id starting with instance_first_index

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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