You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

i.MX8M Plus平台DMA-buf导入Vulkan后映射无原数据问题求助

问题分析与解决方案

在i.MX8M Plus平台上,将/cma-uncached区域的DMA-buf导入Vulkan后,vkMapMemory无法读取原始数据(验证层无报错),核心问题集中在内存类型匹配错误、外部内存导入参数误用两个方面,以下是具体分析和修复方案:

关键问题点

1. 错误的内存类型选择

导入外部DMA-buf时,不能直接指定VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT来筛选内存类型。DMA-buf的内存属性由其创建时的内存区域(/cma-uncached)决定,必须选择驱动认可的、支持VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT导入的内存类型,而非自定义组合属性。

2. 不必要的VkMemoryDedicatedAllocateInfo

导入已存在的外部内存时,无需指定VkMemoryDedicatedAllocateInfo——该结构用于驱动分配全新的专用内存,而DMA-buf是预先分配好的内存,强行添加会干扰驱动对外部内存的关联逻辑。

3. 驱动扩展验证缺失

需确保已启用VK_KHR_external_memory_fd和VK_EXT_external_memory_dma_buf扩展,这是DMA-buf导入Vulkan的必要前提。

修复后的代码示例

// 确保已启用VK_KHR_external_memory_fd和VK_EXT_external_memory_dma_buf扩展
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 = nullptr;

int FD_width = widthVIV;
int FD_height = heightVIV;
int size = FD_width * FD_height * 2;

VkBufferCreateInfo bufferInfo{};
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
bufferInfo.size = size;
bufferInfo.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
bufferInfo.pNext = &extMemBufInfo;

if (vkCreateBuffer(device, &bufferInfo, nullptr, &fdBuffer) != VK_SUCCESS) {
    qDebug("failed to create buffer!");
}

VkMemoryRequirements memRequirements;
vkGetBufferMemoryRequirements(device, fdBuffer, &memRequirements);

// 移除VkMemoryDedicatedAllocateInfo
VkImportMemoryFdInfoKHR importInfo{};
importInfo.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR;
importInfo.fd = dmafd;
importInfo.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
importInfo.pNext = nullptr;

// 修改内存类型查找逻辑:筛选支持DMA-buf导入的内存类型
uint32_t findExternalMemoryType(VkPhysicalDevice physicalDevice, uint32_t memoryTypeBits, VkExternalMemoryHandleTypeFlagBitsEXT handleType) {
    VkPhysicalDeviceMemoryProperties memProps;
    vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memProps);
    
    for (uint32_t i = 0; i < memProps.memoryTypeCount; i++) {
        if (!(memoryTypeBits & (1 << i))) continue;
        
        VkExternalMemoryPropertiesKHR extMemProps{};
        extMemProps.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_PROPERTIES_KHR;
        
        VkPhysicalDeviceExternalMemoryInfoKHR extMemInfo{};
        extMemInfo.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_INFO_KHR;
        extMemInfo.handleType = handleType;
        
        vkGetPhysicalDeviceExternalMemoryPropertiesKHR(physicalDevice, &extMemInfo, &extMemProps);
        
        if (extMemProps.externalMemoryFeatures & VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR) {
            return i;
        }
    }
    return UINT32_MAX;
}

uint32_t memTypeIndex = findExternalMemoryType(physicalDevice, memRequirements.memoryTypeBits, VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
if (memTypeIndex == UINT32_MAX) {
    qDebug("failed to find compatible external memory type!");
}

VkMemoryAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocInfo.allocationSize = memRequirements.size;
allocInfo.memoryTypeIndex = memTypeIndex;
allocInfo.pNext = &importInfo;

if (vkAllocateMemory(device, &allocInfo, nullptr, &fdBufferMemory) != VK_SUCCESS) {
    qDebug("failed to allocate image memory!");
}

if(vkBindBufferMemory(device, fdBuffer, fdBufferMemory, 0) != VK_SUCCESS) {
      qDebug() << "vkBindBufferMemory failed: " << strerror(errno);
}

额外验证步骤

  • 确认dmafd未被提前关闭,且与mmap使用的是同一个文件描述符;
  • 映射内存后,检查指针偏移:由于DMA-buf可能存在硬件对齐要求,需确认vkMapMemory返回的指针与DMA-buf实际起始地址的偏移是否为0;
  • 若仍存在问题,可通过vkGetDeviceMemoryOpaqueCaptureAddressKHR获取内存地址,与DMA-buf的物理地址对比,验证是否正确关联。

内容的提问来源于stack exchange,提问作者AB2

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 20:39:57