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

如何指定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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 08:57:14