Vulkan内存失效与刷新的正确操作及对齐相关问题咨询
问题1:将刷新范围向上取整到128字节、超出分配的20字节内存边界是否合规?
不合规,这属于未定义行为。
Vulkan规范明确要求 vkFlushMappedMemoryRanges/vkInvalidateMappedMemoryRanges 传入的内存范围(offset, offset + size)必须完全落在对应已分配VkDeviceMemory的地址范围内,超出边界的操作轻则触发验证层报错,重则导致内存数据损坏、驱动崩溃。
该问题本质是内存分配阶段的遗漏:当分配的内存需要用于非一致性主机映射的手动刷新/失效操作时,不能仅按照VkMemoryRequirements::size的值分配,需要额外将分配大小向上取整到nonCoherentAtomSize的倍数,这是应用层需要自行处理的逻辑,驱动不会自动做该对齐处理。
对应示例场景,需要分配的内存大小应为align_up(20, 128) = 128字节,此时刷新时将20字节向上取整到128字节,刚好落在分配的内存范围内,操作合法。
问题2:vkAllocateMemory返回的内存是否保证对齐到nonCoherentAtomSize?
是,Vulkan规范强制要求所有通过vkAllocateMemory分配的设备内存块,其起始偏移(内存块自身的偏移0)天然满足所有设备支持的对齐要求,包括但不限于nonCoherentAtomSize、缓冲区/图像的对齐要求、稀疏内存页对齐要求。
因此对内存块内的偏移做向下取整到nonCoherentAtomSize的操作时,只要原始偏移本身在分配的内存范围内,取整后的结果一定不会小于0、也不会超出内存块的起始边界,不会出现刷新内存块外数据的问题。
补充优化方案
如果不想额外占用更多内存,可以直接选择带VK_MEMORY_PROPERTY_HOST_COHERENT_BIT标记的内存类型,这类内存是自动一致性的,不需要手动调用刷新/失效接口,自然也不需要处理nonCoherentAtomSize对齐要求,仅在对主机端内存写入性能要求极高的场景下才需要考虑非一致性内存。
内容的提问来源于stack exchange,提问作者Zebrafish

