Vulkan 暂存缓冲区
顶点缓冲区现在已经可以正常工作,但相比于显卡内部读取数据,单纯从CPU访问内存数据的方式性能不是最佳的。最佳的方式是采用VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT标志位,通常来说用在专用的图形卡,CPU是无法访问的。在本章节我们创建两个顶点缓冲区。一个缓冲区提供给CPU-HOST内存访问使用,用于从顶点数组中提交数据,另一个顶点缓冲区用于设备local内存。我们将会使用缓冲区拷贝的命令将数据从暂存缓冲区拷贝到实际的图形卡内存中。

一、传输队列
缓冲区拷贝的命令需要队列簇支持传输操作,可以通过VK_QUEUE_TRANSFER_BIT标志位指定。好消息是任何支持VK_QUEUE_GRAPHICS_BIT 或者 VK_QUEUE_COMPUTE_BIT标志位功能的队列簇都默认支持VK_QUEUE_TRANSFER_BIT操作。这部分的实现不需要在queueFlags显示的列出。
如果需要明确化,甚至可以尝试为不同的队列簇指定具体的传输操作。这部分实现需要对代码做出如下修改:
- 修改QueueFamilyIndices和findQueueFamilies,明确指定队列簇需要具备VK_QUEUE_TRANSFER标志位,而不是VK_QUEUE_GRAPHICS_BIT。
- 修改createLogicalDevice函数,请求一个传输队列句柄。
- 创建两个命令对象池分配命令缓冲区,用于向传输队列簇提交命令。
- 修改资源的sharingMode为VK_SHARING_MODE_CONCURRENT,并指定为graphics和transfer队列簇。
- 提交任何传输命令,诸如vkCmdCopyBuffer(本章节使用)到传输队列,而不是图形队列。
需要一些额外的工作,但是它我们更清楚的了解资源在不同队列簇如何共享的。
二、创建临时缓冲区
考虑到我们在本章节需要创建多个缓冲区,比较理想的是创建辅助函数来完成。新增函数createBuffer并将createVertexBuffer中的部分代码(不包括映射)移入该函数。
void createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer& buffer, VkDeviceMemory& bufferMemory) {
VkBufferCreateInfo bufferInfo = {
};
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
bufferInfo.size = size;
bufferInfo.usage = usage;
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
if (vkCreateBuffer(device, &bufferInfo, nullptr, &buffer) != VK_SUCCESS) {
throw std::runtime_error("failed to create buffer!");
}
VkMemoryRequirements memRequirements;
vkGetBufferMemoryRequirements(device, buffer, &memRequirements);
VkMemoryAllocateInfo allocInfo = {
};
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocInfo.allocationSize = memRequirements.size;
all

本文介绍Vulkan图形编程中使用暂存缓冲区提高性能的方法。通过创建两个顶点缓冲区,一个用于CPU访问,另一个用于图形卡设备local内存。利用缓冲区拷贝命令,将数据从暂存缓冲区高效传输到设备内存,实现图形数据的快速加载。
最低0.47元/天 解锁文章
1230

被折叠的 条评论
为什么被折叠?



