GPU创建8kx8k大图像遇Vulkan内存分配错误,求解决方案
问题
在GPU上创建8kx8k图像并使用本地数据填充时,创建缓冲区出现以下内存分配错误:
Message: Validation Error: [ VUID-vkAllocateMemory-pAllocateInfo-01713 ] Object 0: handle = 0x5555560fd9f0, name = Logical device: NVIDIA GeForce GTX 1070, type = VK_OBJECT_TYPE_DEVICE; | MessageID = 0xe9a2b96f | vkAllocateMemory: attempting to allocate 268435456 bytes from heap 2,but size of that heap is only 257949696 bytes. The Vulkan spec states: pAllocateInfo->allocationSize must be less than or equal to VkPhysicalDeviceMemoryProperties::memoryHeaps[memindex].size where memindex = VkPhysicalDeviceMemoryProperties::memoryTypes[pAllocateInfo->memoryTypeIndex].heapIndex as returned by vkGetPhysicalDeviceMemoryProperties for the VkPhysicalDevice that device was created from Severity: VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT
推测原因是使用了VMA_MEMORY_USAGE_CPU_TO_GPU标志,但仅有的主机可见内存堆(堆2)容量不足。
解决方案
分批上传数据到GPU本地内存
放弃创建超大CPU可见缓冲区,改为:- 创建GPU本地的8kx8k目标图像,使用
VMA_MEMORY_USAGE_GPU_ONLY分配内存,这类内存通常来自容量更大的设备本地堆。 - 将本地数据分割为若干小块(比如每块64MB,适配CPU可见堆的剩余容量),创建对应大小的临时CPU可见缓冲区(
VMA_MEMORY_USAGE_CPU_TO_GPU)。 - 逐块将本地数据写入临时缓冲区,再通过
vkCmdCopyBufferToImage命令将数据复制到目标图像的对应区域,完成后销毁临时缓冲区。
- 创建GPU本地的8kx8k目标图像,使用
排查其他主机可见内存类型
调用vkGetPhysicalDeviceMemoryProperties遍历所有内存类型,确认是否存在其他**主机可见(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)**且属于更大内存堆的类型。如果有,调整VMA分配参数,优先选择这些内存类型,避免局限在堆2。使用VMA分段分配特性
若必须使用CPU可见内存承载完整数据,可在分配时添加VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT标志,并配置VMA内存池,让VMA自动将大缓冲区拆分为多个小内存块,逻辑上保持连续访问。但这种方式的读写性能通常不如分批上传到GPU本地内存。
内容的提问来源于stack exchange,提问作者Makogan
相关产品推荐
相关产品推荐

