博客
关于我
Vulkan临时缓冲区
阅读量:208 次
发布时间:2019-02-28

本文共 3925 字,大约阅读时间需要 13 分钟。

相比于显卡内部读取数据,单纯从CPU访问内存数据的方式性能并不理想。最佳的做法是使用VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT标志位,这种方式通常用于专用图形卡,因为这样可以确保CPU无法访问这些内存,从而提高性能。

创建临时缓冲区的最佳实现方式是通过辅助函数来完成。以下是一个常用的方法,涉及创建缓冲区和顶点缓冲区的实现:

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;    allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, properties);    if (vkAllocateMemory(device, &allocInfo, nullptr, &bufferMemory) != VK_SUCCESS) {        throw std::runtime_error("failed to allocate buffer memory!");    }    vkBindBufferMemory(device, buffer, bufferMemory, 0);}

这个函数需要传递缓冲区大小、内存属性和使用标志,以创建不同类型的缓冲区。最后两个参数用于存储输出的句柄。

以下是创建顶点缓冲区的实现:

void createVertexBuffer() {    VkDeviceSize bufferSize = sizeof(vertices[0]) * vertices.size();    createBuffer(bufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, vertexBuffer, vertexBufferMemory);}

为了实现临时缓冲区的使用,我们可以修改顶点缓冲区的创建方法:

void createVertexBuffer() {    VkDeviceSize bufferSize = sizeof(vertices[0]) * vertices.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, vertices.data(), bufferSize);    vkUnmapMemory(device, stagingBufferMemory);    createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, vertexBuffer, vertexBufferMemory);}

在这个实现中,stagingBuffer用于临时存储顶点数据,然后通过copyBuffer函数将其复制到设备缓冲区中。

为了实现内存传输操作,我们需要使用命令缓冲区。以下是一个常用的方法:

void copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size) {    VkCommandBufferAllocateInfo allocInfo = {};    allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;    allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;    allocInfo.commandPool = commandPool;    allocInfo.commandBufferCount = 1;    if (vkAllocateCommandBuffers(device, &allocInfo, &commandBuffer) != VK_SUCCESS) {        throw std::runtime_error("failed to allocate command buffer!");    }}void copyBuffer() {    VkCommandBufferBeginInfo beginInfo = {};    beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;    beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;    if (vkBeginCommandBuffer(commandBuffer, &beginInfo) != VK_SUCCESS) {        throw std::runtime_error("failed to begin command buffer!");    }    VkBufferCopy copyRegion = {};    copyRegion.srcOffset = 0;    copyRegion.dstOffset = 0;    copyRegion.size = size;    if (vkCmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, 1, copyRegion) != VK_SUCCESS) {        throw std::runtime_error("failed to copy buffers!");    }    if (vkEndCommandBuffer(commandBuffer) != VK_SUCCESS) {        throw std::runtime_error("failed to end command buffer!");    }}

copyBuffer函数中,可以通过命令缓冲区执行内存传输操作。为了优化命令缓冲区的内存使用,可以为短期命令缓冲区分配内存,并使用VK_COMMAND_POOL_CREATE_TRANSIENT_BIT标志位。

最后,确保在完成内存传输后清理临时缓冲区:

void clearStagingBuffer() {    vkDestroyBuffer(device, stagingBuffer, nullptr);    vkFreeMemory(device, stagingBufferMemory, nullptr);}

通过上述方法,可以实现对顶点数据的高效内存传输和缓冲区管理。

转载地址:http://hpnp.baihongyu.com/

你可能感兴趣的文章
Mysql中使用存储过程插入decimal和时间数据递增的模拟数据
查看>>
MySql中关于geometry类型的数据_空的时候如何插入处理_需用null_空字符串插入会报错_Cannot get geometry object from dat---MySql工作笔记003
查看>>
mysql中出现Incorrect DECIMAL value: '0' for column '' at row -1错误解决方案
查看>>
mysql中出现Unit mysql.service could not be found 的解决方法
查看>>
mysql中出现update-alternatives: 错误: 候选项路径 /etc/mysql/mysql.cnf 不存在 dpkg: 处理软件包 mysql-server-8.0的解决方法(全)
查看>>
Mysql中各类锁的机制图文详细解析(全)
查看>>
MySQL中地理位置数据扩展geometry的使用心得
查看>>
Mysql中存储引擎简介、修改、查询、选择
查看>>
Mysql中存储过程、存储函数、自定义函数、变量、流程控制语句、光标/游标、定义条件和处理程序的使用示例
查看>>
mysql中实现rownum,对结果进行排序
查看>>
mysql中对于数据库的基本操作
查看>>
Mysql中常用函数的使用示例
查看>>
MySql中怎样使用case-when实现判断查询结果返回
查看>>
Mysql中怎样使用update更新某列的数据减去指定值
查看>>
Mysql中怎样设置指定ip远程访问连接
查看>>
mysql中数据表的基本操作很难嘛,由这个实验来带你从头走一遍
查看>>
Mysql中文乱码问题完美解决方案
查看>>
mysql中的 +号 和 CONCAT(str1,str2,...)
查看>>
Mysql中的 IFNULL 函数的详解
查看>>
mysql中的collate关键字是什么意思?
查看>>