创建索引缓冲
在本章节我们通过绘制矩形来演示索引缓冲的使用。修改顶点数据定义矩形的4个顶点:
const std::vector<Vertex> vertices = {
{{-0.5f, -0.5f}, {1.0f, 0.0f, 0.0f}},
{{0.5f, -0.5f}, {0.0f, 1.0f, 0.0f}},
{{0.5f, 0.5f}, {0.0f, 0.0f, 1.0f}},
{{-0.5f, 0.5f}, {1.0f, 1.0f, 1.0f}}
};
代码中,我们将矩形左上角的顶点设置为红色,右上角的顶点设置为绿色,右下角的顶点设置蓝色,左下角的顶点设置为白色。我们添加一个新的数组indices来存储索引数据:
const std::vector<uint16_t> indices = {
0, 1, 2, 2, 3, 0
};
我们可以使用uint16_t或uint32_t变量类型作为索引的类型,对于不重复的顶点数据小于65535的情况,使用uint16_t变量类型作为索引类型可以节约一半的内存空间。
和顶点数据一样,我们需要将索引数据加载到一个VkBuffer来让GPU可以访问它。我们定义了两个类成员变量来存储索引缓冲对象:
VkBuffer vertexBuffer;
VkDeviceMemory vertexBufferMemory;
VkBuffer indexBuffer;
VkDeviceMemory indexBufferMemory;
添加createIndexBuffer函数用于索引缓冲创建,它和内容和createVertexBuffer函数的内容几乎一样:
void initVulkan() {
...
createVertexBuffer();
createIndexBuffer();
...
}
void createIndexBuffer() {
VkDeviceSize bufferSize = sizeof(indices[0]) * indices.size();
VkBuffer stagingBuffer;
VkDeviceMemory stagingBufferMemory;
createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, stagingBuffer, stagingBufferMemory);
void* data;
vkMapMemory(device, stagingBufferMemory, 0, bufferSize, 0, &data);
memcpy(data, indices.data(), (size_t) bufferSize);
vkUnmapMemory(device, stagingBufferMemory);
createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, indexBuffer, indexBufferMemory);
copyBuffer(stagingBuffer, indexBuffer, bufferSize);
vkDestroyBuffer(device, stagingBuffer, nullptr);
vkFreeMemory(device, stagingBufferMemory, nullptr);
}
和createVertexBuffer函数相比,只有两处明显的不同。bufferSize现在的值为顶点索引个数乘以索引变量类型所占字节大小。indexBuffer的用法标记为VK_BUFFER_USAGE_INDEX_BUFFER_BIT。除此之外的处理和顶点缓冲的创建是相同的。我们也需要创建一个暂存缓冲来存储indices数组中的索引数据,然后复制暂存缓冲中的索引数据到GPU能够快速访问的缓冲中。
应用程序退出前,我们需要清除创建的索引缓冲对象:
void cleanup() {
cleanupSwapChain();
vkDestroyBuffer(device, indexBuffer, nullptr);
vkFreeMemory(device, indexBufferMemory, nullptr);
vkDestroyBuffer(device, vertexBuffer, nullptr);
vkFreeMemory(device, vertexBufferMemory, nullptr);
...
}