記憶體分類
Vulkan 的記憶體分為兩類: 主控端記憶體 和 裝置記憶體。
兩種記憶體的特點:
- 主控端記憶體 通路速度慢 ,但可配置設定空間大。
- 裝置記憶體 直接對裝置可見的,可配置設定空間小,但通路速度快。
主控端記憶體
Vulkan 通過主控端記憶體來存儲API 的内部資料結構, Vulkan 允許程式控制主控端端的記憶體配置設定,主控端的記憶體管理通過以下資料結構來完成:
typedef struct VkAllocationCallbacks {
Void* pUserData;
PFN_vkAllocationFunction pfnAllocation;
PFN_vkReallocationFunction pfnReallocation;
PFN_vkFreeFunction pfnFree;
PFN_vkInternalAllocationNotification pfnInternalAlloc;
PFN_vkInternalFreeNotification pfnInternalFree;
} VkAllocationCallbacks ;
裝置記憶體
裝置記憶體, 即GPU 記憶體,它對于實體裝置是直接可見的, 實體裝置可以直接讀取其中的記憶體區塊。圖像對象,緩存對象,以及一緻變量的緩存對象都是在裝置記憶體端配置設定的。
單一裝置可能有多種記憶體類型,根據堆類型以及屬性的不同還可以進一步細分。
查詢記憶體堆和屬性的函數:
void vkGetPhysicalDeviceMemoryProperties(
VkPhysicalDevice physicalDevice,
VkPhysicalDeviceMemoryProperties* pMemoryProperties
);
typedef struct VkPhysicalDeviceMemoryProperties {
Uint32_t memoryTypeCount;
VkMemoryType memoryTypes[VK_MAX_MEMORY_TYPES];
Uint32_t memoryHeapCount;
VkMemoryHeap memoryHeaps[VK_MAX_MEMORY_HEAPS];
} VkPhysicalDeviceMemoryProperties;
- 記憶體類型
typedef struct VkMomoryType {
VkMemoryPropteryFlags propertyFlags; // 屬性
uint32_t heapIndex; // 堆索引号
} VkMemoryType;
注意 HOST_COHERENT_BIT , HOST_CACHED_BIT 和 LAZILY_ALLOCATED_BIT 的用法。
LAZILY_ALLOCATED_BIT 隻能被裝置端通路,與HOST_PROPERTY_HOST_VISIBLE_BIT 和 HOST_COHERENT_BIT 條件排斥。
- 記憶體堆
typedef struct VkMemoryHeap {
VkDeviceSize size; //堆的大小
VkMemoryHeapFlags flags; //堆的屬性
} VkMemoryHeap;
typedef enum VkMemoryHeapFlagBits {
VK_MEMORY_HEAP_DEVICE_LOCAL_BIT = 0x00000001,
VK_MEMORY_HEAP_MULTI_INSTANCE_BIT = 0x00000002,
VK_MEMORY_HEAP_MULTI_INSTANCE_BIT_KHR = VK_MEMORY_HEAP_MULTI_INSTANCE_BIT,
VK_MEMORY_HEAP_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkMemoryHeapFlagBits;
配置設定記憶體
VkResult vkAllocateMemory (
VkDevice device;
const VkMemoryAllocateInfo* allocateInfo,
const VkAllocationCallbacks* allocator,
VkDeviceMemory* memory
);
typedef struct VkMemoryAllocateInfo {
VkStructureType type;
Const void* pNext;
VkDeviceSize allocationSize;
uint32_t momoryTypeIndex; // 記憶體類型索引
} VkMemoryAllocateInfo;
注意: 實體裝置記憶體端的可配置設定對象的數量是有限的,可以通過 VkPhysicalDeviceLimits 成員的 maxMemoryAllocationCount 查詢 (4096 )。
釋放記憶體
Void VkFreeMemory (
VkDevice device,
VkDeviceMemory memory,
const VkAllocationCallbacks* allocator
);
從主控端通路裝置記憶體
主控端隻能通路那些支援映射的記憶體類型 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,通過 vkMapMemory() 來實作主控端對裝置記憶體的映射通路。
VkResult vkMapMemory (
VkDevice device;
VkDeviceMemory memory,
VkDeviceSize offset,
VkDeviceSize size,
VkMemoryMapFlags flags,
Void** ppData
);
注意 :函數 VkMapMemory 不會檢查記憶體區域是否被映射過,應用程式需要管理映射記憶體對象,通路已經映射的記憶體可能會導緻無法預測的行為,甚至導緻驅動程式當機。
當更新完内容後,通過結束映射使裝置修改的内容反射回裝置端。
當更新完内容後,通過結束映射使裝置修改的内容反射回裝置端。
Void vkUnMapMemory( VkDevice device, VkDeviceMemory memory);