如何指定VMA从Vulkan内存堆0分配大纹理内存?
问题描述
系统Vulkan内存堆信息
memoryHeaps[0]: size = 8589934592 (0x200000000) (8.00 GiB) budget = 7826571264 (0x1d2800000) (7.29 GiB) usage = 0 (0x00000000) (0.00 B) flags: count = 1 MEMORY_HEAP_DEVICE_LOCAL_BIT memoryHeaps[1]: size = 12453414912 (0x2e6480800) (11.60 GiB) budget = 12453414912 (0x2e6480800) (11.60 GiB) usage = 0 (0x00000000) (0.00 B) flags: None memoryHeaps[2]: size = 257949696 (0x0f600000) (246.00 MiB) budget = 251068416 (0x0ef70000) (239.44 MiB) usage = 6881280 (0x00690000) (6.56 MiB) flags: count = 1 MEMORY_HEAP_DEVICE_LOCAL_BIT
堆0空间充足,堆2剩余空间不足,分配大纹理时触发如下错误:
Message: Validation Error: [ VUID-vkAllocateMemory-pAllocateInfo-01713 ] Object 0: handle = 0x5562fe1c6760, 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
当前分配代码:
vk::Device& device = h_interface->GetDevice(); const bool is_3D_image = depth > 0; // Set image creation information. vk::ImageCreateInfo image_info = {}; image_info.imageType = is_3D_image ? vk::ImageType::e3D : vk::ImageType::e2D; image_info.format = format; image_info.extent = vk::Extent3D(width, height, max(uint32_t(1), depth)); image_info.mipLevels = 1; image_info.arrayLayers = 1; image_info.samples = vk::SampleCountFlagBits::e1; image_info.tiling = tiling; image_info.usage = usage; image_info.sharingMode = vk::SharingMode::eExclusive; image_info.initialLayout = initial_layout; VmaAllocationCreateInfo allocation_info = {}; allocation_info.usage = VMA_MEMORY_USAGE_AUTO; uint32_t memoryTypeIndex = 0; allocation_info.memoryTypeBits = 0u << memoryTypeIndex; VmaAllocation allocation; vk::Image image; VkResult result = vmaCreateImage( vma_allocator, (VkImageCreateInfo*)&image_info, &allocation_info, (VkImage*)&image, &allocation, nullptr);
尝试修改allocation_info.usage、memoryTypeBits及VMA初始化参数均无效,需指导如何强制VMA从堆0分配内存。
解决方案
获取堆0对应的内存类型掩码
调用vkGetPhysicalDeviceMemoryProperties获取物理设备内存属性,遍历memoryTypes数组,把所有属于堆0(heapIndex == 0)的内存类型索引对应的位掩码合并:VkPhysicalDeviceMemoryProperties memProps; vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memProps); uint32_t heap0MemoryMask = 0; for(uint32_t i = 0; i < memProps.memoryTypeCount; ++i) { if(memProps.memoryTypes[i].heapIndex == 0) { heap0MemoryMask |= (1u << i); } }修改VMA分配参数
把allocation_info.memoryTypeBits设置为上面得到的掩码,同时根据纹理的访问需求设置合适的usage,并可添加标志强制VMA遵循指定范围:VmaAllocationCreateInfo allocation_info = {}; // 若纹理仅GPU访问,用GPU_ONLY;若需要CPU访问则选对应的类型 allocation_info.usage = VMA_MEMORY_USAGE_GPU_ONLY; // 限制仅从堆0的内存类型中分配 allocation_info.memoryTypeBits = heap0MemoryMask; // 可选:强制VMA优先选择满足条件的内存类型,不做自动策略调整 allocation_info.flags |= VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT;关键注意点
- 不能硬编码内存类型索引,不同GPU的内存类型分配差异很大,必须动态获取。
- 确保选中的内存类型和图像的
tiling(如OPTIMAL或LINEAR)、usage属性兼容,否则会分配失败。
内容的提问来源于stack exchange,提问作者Makogan
相关产品推荐
相关产品推荐

