是否有可能通过重写PFN_vkAllocationFunction并将回调传递给Vulkan函数来分配主机内存?<



我实现了一个自定义分配器来跟踪由vkAllocateMemory分配的内存。我也研究了关于这个主题的官方Khronos文档,但我找不到以下问题的答案:

  1. size参数PFN_vkAllocationFunction实际是什么?我已经发现,显然它不是我们想要分配内存的实际缓冲区的大小。我怀疑这是Vulkan结构或任何其他Vulkan内部缓冲区的大小。无论我想分配多大的内存块,它的大小总是设置为200(它是机器/GPU/驱动程序依赖的值,但它是一个常数值)。出于测试目的,我使用了来自:https://github.com/SaschaWillems/Vulkan的三角形和来自类似问题的分配器:Vulkan's VkAllocationCallbacks使用malloc/free()
  2. 实现
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调用是不同的,如vkCreateRenderPassvkCreateImageView

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 
  1. 是否可以使用这些回调来分配主机可见内存?我想模仿VK_EXT_external_memory_host,VK_KHR_external_memory_fdVK_EXT_external_memory_dma_buf的行为,但我不知道这种方法(即实现自己的分配器)是否对它有用。

要了解发生了什么,您需要了解VkAllocationCallbacks的作用。让我们开始吧。

当你调用vkCreateDevice时,Vulkan实现需要返回一个VkDevice句柄。这无疑是一个指向对象的指针。所以…它的记忆从何而来?必须有一些内部的、实现定义的数据结构在起作用。这可能需要分配堆。

然而,对于低级系统,在不知情或未经使用该系统的应用程序同意的情况下任意分配堆内存通常被认为是不礼貌的。由于各种原因,较大的应用程序可能想要预先分配一堆内存,专门用于Vulkan实现的使用。

要做到这一点,需要能够用自己的替换Vulkan实现的堆分配函数。这就是VkAllocationCallbacks的作用:允许您的程序为Vulkan实现提供堆分配服务,Vulkan实现将它们用于自己的内部数据结构。最后一点很重要:这些分配是供内部使用的。

vkAllocateMemory是分配设备可访问内存的函数。是的,根据所使用的内存类型,它可以从与cpu可访问内存相同的内存池中进行分配。但是vkAllocateMemory分配的内存不是为Vulkan实现使用的;它是为了你的应用程序的使用,通过Vulkan API调解。

上面我说了"在特定的上下文中"。当您使用VkAllocationCallbacks创建设备时,回调将用于为使用该设备的任何Vulkan函数分配实现内存。这就是这些回调的上下文。其他函数有自己的上下文。例如,当你调用vkCreateDescriptorPool时,你也给它回调。如果指定了这些回调函数,它们将用于描述符池使用的任何分配。

现在,如上所述,vkAllocateMemory分配设备可访问内存。但是,它还创建了一个表示此存储的VkDeviceMemory对象。这个对象存在于CPU空间中,因此它一定是从CPU存储中分配的。

这就是您看到的200字节所代表的:不是设备内存分配本身,而是用于管理设备内存的CPU存储分配。您可以说,由VkDeviceMemory表示的内部实现对象占用200字节。

总的来说,您无法通过一个旨在为您提供访问Vulkan分配了多少cpu可访问内存的系统来跟踪设备可访问的分配。

最新更新