Overview
Vulkan 将内存管理的工作交给了开发者自己负责,如何分配内存,如何指定内存策略都是由开发者自己决定的,当然出了问题也是由开发者自己负责的
Vulkan 将内存划分为两大类:主机内存(Host Memory) 和设备内存(Device Memory)
在移动设备上,主机内存就是 CPU 内存,设备内存就是GPU 显存,在此基础上,每种内存类型还可以按照属性进一步划分
Vulkan 提供了一种透明的机制来显示内存的细节和相关属性,这样做在 opengl-es 中是完全不可能的,后者不允许应用程序显式的控制内存区域和布局

Vulkan 中系统的内存有四种类型(并不是所有设备都支持这个四种类型):
Host Local Memory,只对Host可见的内存,通常称之为普通内存(可以理解为操作系统的内存)Device Local Memory,只对Device可见的内存,通常称之为显存(可以理解为显卡上的显存)Host Local Device Memory,由Host管理的,对Device可见的内存Device Local Host Memory,由Device管理的,对Host可见的内存
对比这两种内存类型,主机内存(Host)比设备内存(Device)更慢,但是Host Memory 通常容量更大(也就是一般显存速度更快,但是容量更小)
设备内存,它对物理设备是直接可见的,物理设备可以直接读取其中的内存区块,设备内存和物理设备之间的关系十分紧密,因此它的性能比宿主机内存更高
VkImage,VkBuffer,以及一致性的缓存对象Uniform Buffer都是从设备内存端分配的
单一的物理设备可能有多种类型的内存,根据它们的堆类型以及属性的不同还可能进一步细分
枚举内存信息
使用 vkGetPhysicalDeviceMemoryProperties 获取设备的内存信息,其函数定义如下:
VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMemoryProperties(
VkPhysicalDevice physicalDevice,
VkPhysicalDeviceMemoryProperties* pMemoryProperties);
其中 physicalDevice 就是创建的物理设备,VkPhysicalDeviceMemoryProperties 定义如下:
typedef struct VkPhysicalDeviceMemoryProperties {
// 内存类型数量和信息
uint32_t memoryTypeCount;
VkMemoryType memoryTypes[VK_MAX_MEMORY_TYPES];
// 内存堆数量和信息
uint32_t memoryHeapCount;
VkMemoryHeap memoryHeaps[VK_MAX_MEMORY_HEAPS];
} VkPhysicalDeviceMemoryProperties;
memoryTypeCount表示支持的内存类型数量memoryTypes有效元素个数为memoryTypeCount的内存类型信息数组memoryHeapCount表示支持的内存堆数量memoryHeaps有效元素是memoryHeapCount内存堆信息数组
其中 VkMemoryType 类型定义:
typedef struct VkMemoryType {
VkMemoryPropertyFlags propertyFlags;
uint32_t heapIndex;
} VkMemoryType;
propertyFlags内存类型标志位。heapIndex对应的memoryHeaps堆索引。
中 propertyFlags 有效值被定义在了 VkMemoryPropertyFlagBits 枚举中,其定义如下:
typedef enum VkMemoryPropertyFlagBits {
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT = 0x00000001,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT = 0x00000002,
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT = 0x00000004,
VK_MEMORY_PROPERTY_HOST_CACHED_BIT = 0x00000008,
VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT = 0x00000010,
VK_MEMORY_PROPERTY_PROTECTED_BIT = 0x00000020,
VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD = 0x00000040,
VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD = 0x00000080,
VK_MEMORY_PROPERTY_RDMA_CAPABLE_BIT_NV = 0x00000100,
VK_MEMORY_PROPERTY_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkMemoryPropertyFlagBits;
typedef VkFlags VkMemoryPropertyFlags;
-
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT表示该内存设备上分配的内存可以被物理设备高效访问,只有对应的堆为VK_MEMORY_HEAP_DEVICE_LOCAL_BIT才会有该内存类型(Device内存) -
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT表示该内存设备上分配的内存将自动进行同步,不需要手动调用vkFlushMappedMemoryRanges和vkInvalidateMappedMemoryRanges来进行内存同步 -
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT表示在此内存类型上分配的内存可被 Host 端通过vkMapMemory函数进行映射,进而进行访问 -
VK_MEMORY_PROPERTY_HOST_CACHED_BIT表示该内存类型上分配的内存为缓存类型,Host端访问缓存的内存类型会比较快,但是非缓存内存总是同步内存(VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) -
VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT表示在此内存类型上分配的内存只有物理设备可访问
内存类型不能同时为VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT和VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
下图表示了 memory_type 和 相应的标志位之间的关系:

另外的 VkMemoryHeap 的类型定义如下图所示:
typedef struct VkMemoryHeap {
VkDeviceSize size

最低0.47元/天 解锁文章
774

被折叠的 条评论
为什么被折叠?



