In this section, you will learn to use the vkCmdDrawIndexed()
draw command. This command is used for drawing the index geometry.The vkCmdDrawIndexed()
API is an index buffer's draw command. In an index buffer, each vertex is represented using an index number. This fashion of representing mesh data requires less memory and storage space to represent connected meshes when the mesh has shared vertices (such as enclosed shapes).
For example, a square geometry rendered using two triangles shares two common vertices as shown in the following example; as you can see, the first and third vertices are repeated:
static const VertexWithColor squareData[] =
{
{ -0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0 },
{ 0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0 },
{ 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0 },
{ -0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0 },
};
uint16_t squareIndices[] = { 0,3,1, 3,2,1 }; // 6 indices
In this section, we will use the geometry data and indices to demonstrate the use of the vkCmdDrawIndexed()
API. The following is the syntax:
void vkCmdDrawIndexed( VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance);
Let's take a look at the different fields used in this API and their respective descriptions:
Parameter |
Description |
|
This field specifies the command buffer object ( |
|
This is the total count of the index elements in the index list of the buffer resources that are intended to be drawn. |
|
This field indicates the total number of instances to be drawn using this command. |
|
This field specifies the first index (into the indices) from where the indices are read. |
|
This field specifies an offset value that will be added into the vertex index to produce a resultant index. This computed index then is used to read the vertex from the vertex buffer. |
|
This field specifies the very first instance ID into the instances to draw. |
The following are the steps to render an indexed draw:
squareData
and squareIndices
, create a buffer resource (VkBuffer
). Store VkBuffer's
handles in VertexBuffer::buf
and VertexIndex::idx
. For more information, please refer to the Indexed Draw example provided in this chapter.vkCmdBindVertexBuffers()
and pass VertexBuffer.buf
into it.VertexIndex.idx
) is bound using the vkCmdBindIndexBuffer()
API command. vkCmdDrawIndexed()
.
vkCmdDrawIndexed()
is used in conjunction with the vkCmdBindIndexBuffer()
API. Similar to vkCmdBindVertexBuffers()
, which binds the vertex buffer, this command binds the index buffer. The following is the syntax of this API; for more information on the vkCmdBindVertexBuffers()
API, please refer to the Specifying the drawing object geometry information
section.
void vkCmdBindIndexBuffer( VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkIndexType indexType);
Let's take a look at the different fields used in this API and their respective descriptions:
Parameter |
Description |
|
This specifies the command buffer object into which this command— |
|
This indicates the handle of the index buffer ( |
|
This is the starting offset specified in bytes in the index buffer that will be used for index buffer address calculation. |
|
This field indicates whether the indices are 16-bits or 32-bits wide.
This must be one of the
typedef enum VkIndexType { VK_INDEX_TYPE_UINT16 = 0, VK_INDEX_TYPE_UINT32 = 1, } VkIndexType;
|
Similar to the createVertexBuffer()
function, we have created a new function called createIndexBuffer()
; it creates the index buffer and stores the index buffer handle in VertexIndex.idx
. For a detailed implementation of this function, please refer to the accompanying source code. The implementation of createIndexBuffer()
is very similar to createVertexBuffer()
; for a detailed understanding on the implementation of this function, please refer to Implementing the buffer resource—creating the vertex buffer for the geometry in Chapter 7, Buffer Resource, Render Pass, Framebuffer, and Shaders with SPIR-V.
The following code demonstrates the rendering of the indexed geometry object:
// Local data structure in VulkanDrawable class // for storing vertex buffer and index buffer metadata struct { VkBuffer buf; VkDeviceMemory mem; VkDescriptorBufferInfo bufferInfo; } VertexBuffer; struct { VkBuffer idx; VkDeviceMemory mem; VkDescriptorBufferInfo bufferInfo; } VertexIndex; // Create the VkBuffer and store the handle in // VertexBuffer.buf and VertexIndex.idx . . . . // Bind the vertex buffer const VkDeviceSize offsets[1] = { 0 }; vkCmdBindVertexBuffers(*cmdDraw, 0, 1,&VertexBuffer.buf, offsets); // Bind the Index buffer vkCmdBindIndexBuffer(*cmdDraw, VertexIndex.idx, 0, VK_INDEX_TYPE_UINT16); // Draw the object vkCmdDrawIndexed(*cmdDraw, 6, 1, 0, 0, 0);
The output of the preceding geometry data will be displayed as follows; for detailed code, please refer to the Indexed Draw example in this chapter:
The vkCmdDrawIndirect
and vkCmdDrawIndexedIndirect
draw commands are very similar to vkCmdDraw
and vkCmdDrawIndexed
, except that the parameters here are read from the buffer memory. For more information on these APIs, please refer to the official Vulkan specification.
3.15.221.133