一:概述
我们现在的顶点缓冲区工作正常,但顶点缓冲区的内存类型可能不是最优内的存类型,最优的内存类型应该允许从图形卡内存中读取,而不是从CPU访问的内存。最优的内存类型具有VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT标志,通常在专用显卡上无法被CPU访问。在本章中,我们将创建两个顶点缓冲区。一个是在CPU可访问内存中的暂存缓冲区,用于将数据上传到顶点数组,另一个是在设备本地内存中的顶点缓冲区。然后,我们将使用缓冲区复制命令将数据从暂存缓冲区移动到实际的顶点缓冲区。
更多内容请参考 一文带你了解GPU编程从入门到精通-CSDN博客
二:数据传输队列
缓冲区复制命令需要支持传输操作的队列族,这通过 VK_QUEUE_TRANSFER_BIT 指示。好消息是,任何具有 VK_QUEUE_GRAPHICS_BIT 或 VK_QUEUE_COMPUTE_BIT 功能的队列族已经隐式支持 VK_QUEUE_TRANSFER_BIT 操作。在这些情况下,实现并不要求在 queueFlags 中明确列出它。
如果你喜欢挑战,你仍然可以尝试使用不同的队列族专门进行传输操作。这将要求你对程序进行以下修改:
1. 修改 QueueFamilyIndices 和 findQueueFamilies,以显式查找具有 VK_QUEUE_TRANSFER_BIT 位的队列族,但不包括 VK_QUEUE_GRAPHICS_BIT。
2. 修改 createLogicalDevice,以请求传输队列的句柄。
3. 为在传输队列族上提交的命令缓冲区创建第二个命令池。
4. 将资源的 sharingMode 更改为 VK_SHARING_MODE_CONCURRENT,并指定图形和传输队列族。
5. 将任何传输命令(如 vkCmdCopyBuffer,本文中将使用)提交到传输队列,而不是图形队列。
这有点工作量,但它会让你深入了解资源在队列族之间是如何共享的。
三:创建抽象缓冲区
因为我们将在本章中创建多个缓冲区,所以将缓冲区的创建转移到辅助函数是一个好主意。创建一个新函数CreateBuffer,并将CreateVertexBuffer中的代码(映缓冲区射除外)移动到该函数中。
void createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer& buffer, VkDeviceMemory& bufferMemory) {
VkBufferCreateInfo bufferInfo{};
bufferInf