返回
如何在 Vulkan 中从 DMA-buf 导入外部内存?
Linux
2024-03-06 15:21:14
从 DMA-buf 导入 Vulkan 中
导入 DMA-buf 到 Vulkan
DMA-buf(直接内存访问缓冲区)是一种跨平台协议,用于在应用程序和内核驱动程序之间共享内存缓冲区。在 Vulkan 中,我们可以利用这种协议,通过将 DMA-buf 导入到 Vulkan 中,实现对外部内存的访问和使用。
步骤
1. 创建外部内存缓冲区信息结构**
VkExternalMemoryBufferCreateInfo extMemBufInfo;
extMemBufInfo.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO;
extMemBufInfo.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
extMemBufInfo.pNext = NULL;
2. 设置缓冲区创建信息**
VkBufferCreateInfo bufferInfo;
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
bufferInfo.size = size; // DMA-buf 的大小
bufferInfo.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
bufferInfo.flags = 0;
bufferInfo.pNext = &extMemBufInfo;
3. 创建缓冲区**
if (vkCreateBuffer(device, &bufferInfo, nullptr, &fdBuffer) != VK_SUCCESS) {
qDebug("failed to create buffer!");
}
4. 获取缓冲区内存需求**
VkMemoryRequirements memRequirements;
vkGetBufferMemoryRequirements(device, fdBuffer, &memRequirements);
5. 设置专用内存分配信息**
VkMemoryDedicatedAllocateInfo memDedAllocInfo;
memset(&memDedAllocInfo, 0, sizeof(memDedAllocInfo));
memDedAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO;
memDedAllocInfo.buffer = fdBuffer;
6. 设置导入内存 FD 信息**
VkImportMemoryFdInfoKHR importInfo;
memset(&importInfo, 0, sizeof(importInfo));
importInfo.fd = dmafd;
importInfo.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR;
importInfo.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
importInfo.pNext = &memDedAllocInfo;
7. 设置内存分配信息**
VkMemoryAllocateInfo allocInfo;
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocInfo.allocationSize = memRequirements.size;
allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
allocInfo.pNext = &importInfo;
8. 分配内存**
if (vkAllocateMemory(device, &allocInfo, nullptr, &fdBufferMemory) != VK_SUCCESS) {
qDebug("failed to allocate image memory!");
}
9. 绑定缓冲区内存**
if (vkBindBufferMemory(device, fdBuffer, fdBufferMemory, 0) != VK_SUCCESS) {
qDebug() << "vkBindBufferMemory failed: " << strerror(errno);
}
其他提示
- 确保 DMA-buf 是在 /cma-uncached 内存中。
- DMA-buf 的文件符已附加到 VkDeviceMemory。
- 验证层未报告任何问题。
- 使用 vkMapMemory 检查 VkBuffer 是否包含 DMA-buf 中的数据。
常见问题解答
1. 为什么使用 DMA-buf 导入 Vulkan?
DMA-buf 允许在不同 API 和应用程序之间共享内存,从而提高性能并减少数据复制。
2. DMA-buf 导入 Vulkan 的局限性是什么?
DMA-buf 导入到 Vulkan 仅适用于特定类型的内存类型,并且可能需要特定的驱动程序支持。
3. 如何确定 DMA-buf 是否适用于我的场景?
如果你的应用程序需要跨不同应用程序或 API 共享数据,并且性能至关重要,那么 DMA-buf 导入可能是合适的。
4. DMA-buf 导入 Vulkan 的替代方案是什么?
替代方案包括使用 VK_KHR_external_memory 扩展或使用自有实现的跨进程共享内存机制。
5. 如何调试 DMA-buf 导入 Vulkan 的问题?
检查验证层错误消息,使用 vkMapMemory 检查缓冲区内容,并确保满足所有先决条件,例如 DMA-buf 在 /cma-uncached 内存中。