是否可以通过覆盖 PFN_vkAllocationFunction 并将回调传递给 Vulkan 函数来分配主机内存
Is it possible to allocate host memory by overriding PFN_vkAllocationFunction and passing the callback to a Vulkan function
我实现了自定义分配器来跟踪 vkAllocateMemory
分配的内存。
我还研究了有关此主题的官方 Khronos 文档,但我找不到以下问题的答案:
size
参数 PFN_vkAllocationFunction
实际上是什么?我发现这显然不是我们要为其分配内存的实际缓冲区的大小。我怀疑这是 Vulkan 结构或任何其他 Vulkan 内部缓冲区的大小。无论我想分配多大的内存块,它的大小总是设置为 200
(它是 machine/GPU/driver 相关值,但它是一个常量值)。
出于测试目的,我使用了三角形:https://github.com/SaschaWillems/Vulkan and an allocator from a similar question:
triangle before vkAllocateMemory: memAlloc.allocationSize: 7864320 sizeof(memAlloc): 32
triangle after vkAllocateMemory: memAlloc.allocationSize: 7864320
pAllocator's allocationFunction: <Memory>, size: 200, alignment: 8, allocationScope: 1, return ptr* : 0x0x5564ac917b20
我还发现对于其他调用,此 size
对于不同的 vulkan 调用是不同的,例如 vkCreateRenderPass
或 vkCreateImageView
。
pAllocator's allocationFunction: <ImageView>, size: 160, alignment: 8, allocationScope: 1, return ptr* : 0x0x5564acdf8390
pAllocator's allocationFunction: <ImageView>, size: 824, alignment: 8, allocationScope: 1, return ptr* : 0x0x5564acdf8440
pAllocator's allocationFunction: <RenderPass>, size: 200, alignment: 8, allocationScope: 1, return ptr* : 0x0x5564ac950ee0
pAllocator's allocationFunction: <RenderPass>, size: 88, alignment: 8, allocationScope: 1, return ptr* : 0x0x5564acdf8780
pAllocator's allocationFunction: <RenderPass>, size: 56, alignment: 8, allocationScope: 1, return ptr* : 0x0x5564acdf7a00
pAllocator's allocationFunction: <RenderPass>, size: 344, alignment: 8, allocationScope: 1, return ptr* : 0x0x5564ac6a07c0
pAllocator's allocationFunction: <RenderPass>, size: 8, alignment: 8, allocationScope: 1, return ptr* : 0x0x5564acdf87e0
- 是否可以使用这些回调分配主机可见内存?我想模仿
VK_EXT_external_memory_host
、VK_KHR_external_memory_fd
或 VK_EXT_external_memory_dma_buf
的行为,但我不知道这种方法(即实现自己的分配器)是否对它有用。
要了解发生了什么,您需要了解 VkAllocationCallbacks
的用途。让我们开始吧。
例如,当您调用 vkCreateDevice
时,Vulkan 实现需要 return 一个 VkDevice
句柄。这无疑是一个指向对象的指针。那么……它的记忆是从哪里来的?必须有一些内部的、实现定义的数据结构在起作用。这可能需要堆分配。
然而,对于低级系统,在使用该系统的应用程序不知情或不同意的情况下,任意分配堆内存通常被认为是不礼貌的。出于各种原因,较大的应用程序可能希望专门为 Vulkan 实现预分配一堆内存。
要做到这一点,需要能够替换 Vulkan 实现的堆分配函数为您自己的。这就是 VkAllocationCallbacks
的用途:允许您的程序向 Vulkan 实现提供堆分配服务,Vulkan 实现会将它们用于自己的内部数据结构。最后一部分很重要:这些分配供内部使用。
vkAllocateMemory
是分配设备可访问内存的函数。现在是的,根据所使用的内存类型,它可能会从与 CPU 可访问内存相同的内存池中分配。但是分配的内存 vkAllocateMemory
不是供 Vulkan 实现使用的;它用于 您的应用程序 的使用,通过 Vulkan API.
现在,上面我说了“在某些情况下”。当您使用 VkAllocationCallbacks
创建设备时,回调将用于为使用该设备的任何 Vulkan 函数分配实现内存。这就是那些回调的上下文。其他功能有自己的上下文。例如,当你调用 vkCreateDescriptorPool
时,你也给它回调。这些回调(如果指定)将用于任何分配用于描述符池。
现在,如上所述,vkAllocateMemory
分配设备可访问的内存。但是,它还会创建一个代表此存储的 VkDeviceMemory
对象。此对象位于 CPU space 中,因此它必须是从 CPU 存储中分配的。
这就是您看到的 200 个字节所代表的含义:不是设备内存分配本身,而是用于管理 设备内存的 CPU 存储分配。可以说VkDeviceMemory
表示的内部实现对象占了200字节。
总的来说,您无法通过系统跟踪设备可访问分配,该系统旨在为您提供 Vulkan 分配的 CPU 可访问内存的访问权限。
我实现了自定义分配器来跟踪 vkAllocateMemory
分配的内存。
我还研究了有关此主题的官方 Khronos 文档,但我找不到以下问题的答案:
size
参数PFN_vkAllocationFunction
实际上是什么?我发现这显然不是我们要为其分配内存的实际缓冲区的大小。我怀疑这是 Vulkan 结构或任何其他 Vulkan 内部缓冲区的大小。无论我想分配多大的内存块,它的大小总是设置为200
(它是 machine/GPU/driver 相关值,但它是一个常量值)。 出于测试目的,我使用了三角形:https://github.com/SaschaWillems/Vulkan and an allocator from a similar question:
triangle before vkAllocateMemory: memAlloc.allocationSize: 7864320 sizeof(memAlloc): 32
triangle after vkAllocateMemory: memAlloc.allocationSize: 7864320
pAllocator's allocationFunction: <Memory>, size: 200, alignment: 8, allocationScope: 1, return ptr* : 0x0x5564ac917b20
我还发现对于其他调用,此 size
对于不同的 vulkan 调用是不同的,例如 vkCreateRenderPass
或 vkCreateImageView
。
pAllocator's allocationFunction: <ImageView>, size: 160, alignment: 8, allocationScope: 1, return ptr* : 0x0x5564acdf8390
pAllocator's allocationFunction: <ImageView>, size: 824, alignment: 8, allocationScope: 1, return ptr* : 0x0x5564acdf8440
pAllocator's allocationFunction: <RenderPass>, size: 200, alignment: 8, allocationScope: 1, return ptr* : 0x0x5564ac950ee0
pAllocator's allocationFunction: <RenderPass>, size: 88, alignment: 8, allocationScope: 1, return ptr* : 0x0x5564acdf8780
pAllocator's allocationFunction: <RenderPass>, size: 56, alignment: 8, allocationScope: 1, return ptr* : 0x0x5564acdf7a00
pAllocator's allocationFunction: <RenderPass>, size: 344, alignment: 8, allocationScope: 1, return ptr* : 0x0x5564ac6a07c0
pAllocator's allocationFunction: <RenderPass>, size: 8, alignment: 8, allocationScope: 1, return ptr* : 0x0x5564acdf87e0
- 是否可以使用这些回调分配主机可见内存?我想模仿
VK_EXT_external_memory_host
、VK_KHR_external_memory_fd
或VK_EXT_external_memory_dma_buf
的行为,但我不知道这种方法(即实现自己的分配器)是否对它有用。
要了解发生了什么,您需要了解 VkAllocationCallbacks
的用途。让我们开始吧。
例如,当您调用 vkCreateDevice
时,Vulkan 实现需要 return 一个 VkDevice
句柄。这无疑是一个指向对象的指针。那么……它的记忆是从哪里来的?必须有一些内部的、实现定义的数据结构在起作用。这可能需要堆分配。
然而,对于低级系统,在使用该系统的应用程序不知情或不同意的情况下,任意分配堆内存通常被认为是不礼貌的。出于各种原因,较大的应用程序可能希望专门为 Vulkan 实现预分配一堆内存。
要做到这一点,需要能够替换 Vulkan 实现的堆分配函数为您自己的。这就是 VkAllocationCallbacks
的用途:允许您的程序向 Vulkan 实现提供堆分配服务,Vulkan 实现会将它们用于自己的内部数据结构。最后一部分很重要:这些分配供内部使用。
vkAllocateMemory
是分配设备可访问内存的函数。现在是的,根据所使用的内存类型,它可能会从与 CPU 可访问内存相同的内存池中分配。但是分配的内存 vkAllocateMemory
不是供 Vulkan 实现使用的;它用于 您的应用程序 的使用,通过 Vulkan API.
现在,上面我说了“在某些情况下”。当您使用 VkAllocationCallbacks
创建设备时,回调将用于为使用该设备的任何 Vulkan 函数分配实现内存。这就是那些回调的上下文。其他功能有自己的上下文。例如,当你调用 vkCreateDescriptorPool
时,你也给它回调。这些回调(如果指定)将用于任何分配用于描述符池。
现在,如上所述,vkAllocateMemory
分配设备可访问的内存。但是,它还会创建一个代表此存储的 VkDeviceMemory
对象。此对象位于 CPU space 中,因此它必须是从 CPU 存储中分配的。
这就是您看到的 200 个字节所代表的含义:不是设备内存分配本身,而是用于管理 设备内存的 CPU 存储分配。可以说VkDeviceMemory
表示的内部实现对象占了200字节。
总的来说,您无法通过系统跟踪设备可访问分配,该系统旨在为您提供 Vulkan 分配的 CPU 可访问内存的访问权限。