Memory Vulkan';用malloc/free()实现的VkAllocationCallbacks

Memory Vulkan';用malloc/free()实现的VkAllocationCallbacks,memory,memory-management,vulkan,Memory,Memory Management,Vulkan,我正在阅读,似乎VkAllocationCallbacks可以使用简单的malloc/realloc/free函数实现 typedef struct VkAllocationCallbacks { void* pUserData; PFN_vkAllocationFunction pfnAllocation; PFN_vkReallocationFunction

我正在阅读,似乎VkAllocationCallbacks可以使用简单的malloc/realloc/free函数实现

typedef struct VkAllocationCallbacks {
   void*                                   pUserData;
   PFN_vkAllocationFunction                pfnAllocation;
   PFN_vkReallocationFunction              pfnReallocation;
   PFN_vkFreeFunction                      pfnFree;
   PFN_vkInternalAllocationNotification    pfnInternalAllocation;
   PFN_vkInternalFreeNotification          pfnInternalFree;
} VkAllocationCallbacks;
但我认为实现自己的vkAllocationCallback只有两个可能的原因:

  • 通过Vulkan API记录和跟踪内存使用情况
  • 实现一种堆内存管理,它是一个大的内存块,可以反复使用和重用。显然,这可能是一种过激行为,并且会遇到与托管内存(如Java JVM)相同的问题
我是不是遗漏了什么? 什么样的应用程序值得实现vkAllocationCallbacks

来自规范:“由于大多数内存分配都脱离了关键路径,这并不意味着性能特性。相反,这对于某些嵌入式系统、调试目的(例如,在所有主机分配之后放置保护页)或内存分配日志记录都很有用。”

对于嵌入式系统,您可能一开始就占用了所有内存,因此您不希望驱动程序调用malloc,因为水箱中可能什么都没有了。保护页和内存日志(仅用于调试构建)对于谨慎/好奇的用户可能有用

我在某个地方的幻灯片上读到(对不起,我记不起在哪里)您绝对不应该实施只反馈到malloc/realloc/free的分配回调,因为您通常可以假设驱动程序做得比这好得多(例如,将少量分配整合到池中)

我认为,如果您不确定是否应该实现分配回调,那么就不需要实现分配回调,也不需要担心可能应该实现分配回调


我认为它们是为那些特定的用例和那些真正想掌控一切的人而存在的。

我使用纯C的malloc()/realloc()/free()实现了我自己的VkalLocator回调。这是一个幼稚的实现,完全忽略了对齐参数。考虑到64位操作系统中的malloc总是返回16(!)字节对齐的指针,这是相当大的对齐,这在我的测试中不是问题。看

为了信息完整性,16字节的对齐方式也是8/4/2字节对齐

我的代码如下:

  /**
   * PFN_vkAllocationFunction implementation
   */
  void*  allocationFunction(void* pUserData, size_t  size,  size_t  alignment, VkSystemAllocationScope allocationScope){

    printf("pAllocator's allocationFunction: <%s>, size: %u, alignment: %u, allocationScope: %d",
        (USER_TYPE)pUserData, size, alignment, allocationScope);
   // the allocation itself - ignore alignment, for while
   void* ptr = malloc(size);//_aligned_malloc(size, alignment);
   memset(ptr, 0, size);
   printf(", return ptr* : 0x%p \n", ptr);
   return ptr;  
}

/**
 * The PFN_vkFreeFunction implementation
 */
void freeFunction(void*   pUserData, void*   pMemory){
    printf("pAllocator's freeFunction: <%s> ptr: 0x%p\n",
    (USER_TYPE)pUserData, pMemory);
    // now, the free operation !    
    free(pMemory);
 }

/**
 * The PFN_vkReallocationFunction implementation
 */
void* reallocationFunction(void*   pUserData,   void*   pOriginal,  size_t  size, size_t  alignment,  VkSystemAllocationScope allocationScope){
    printf("pAllocator's REallocationFunction: <%s>, size %u, alignment %u, allocationScope %d \n",
    (USER_TYPE)pUserData, size, alignment, allocationScope);       
    return realloc(pOriginal, size);
 }

/**
 * PFN_vkInternalAllocationNotification implementation
 */
void internalAllocationNotification(void*   pUserData,  size_t  size,   VkInternalAllocationType allocationType, VkSystemAllocationScope                     allocationScope){
  printf("pAllocator's internalAllocationNotification: <%s>, size %uz, alignment %uz, allocationType %uz, allocationScope %s \n",
    (USER_TYPE)pUserData, 
    size, 
    allocationType, 
    allocationScope);

}

/**
 * PFN_vkInternalFreeNotification implementation
 **/
void internalFreeNotification(void*   pUserData, size_t  size,  VkInternalAllocationType  allocationType, VkSystemAllocationScope                     allocationScope){
    printf("pAllocator's internalFreeNotification: <%s>, size %uz, alignment %uz, allocationType %d, allocationScope %s \n",
            (USER_TYPE)pUserData, size, allocationType, allocationScope);
}



 /**
  * Create Pallocator
  * @param info - String for tracking Allocator usage
  */
static VkAllocationCallbacks* createPAllocator(const char* info){
    VkAllocationCallbacks* m_allocator =     (VkAllocationCallbacks*)malloc(sizeof(VkAllocationCallbacks));
    memset(m_allocator, 0, sizeof(VkAllocationCallbacks));
    m_allocator->pUserData = (void*)info;
    m_allocator->pfnAllocation = (PFN_vkAllocationFunction)(&allocationFunction);
    m_allocator->pfnReallocation = (PFN_vkReallocationFunction)(&reallocationFunction);
    m_allocator->pfnFree = (PFN_vkFreeFunction)&freeFunction;
    m_allocator->pfnInternalAllocation = (PFN_vkInternalAllocationNotification)&internalAllocationNotification;
    m_allocator->pfnInternalFree = (PFN_vkInternalFreeNotification)&internalFreeNotification;
   // storePAllocator(m_allocator);
   return m_allocator;
  }
/**
*PFN_vkAllocationFunction实现
*/
void*allocationFunction(void*pUserData、size\u t size、size\u t alignment、vksystemaallocationscope allocationScope){
printf(“定位器的分配函数:,大小:%u,对齐:%u,分配范围:%d”,
(用户类型)数据、大小、对齐、分配范围);
//分配本身-暂时忽略对齐
void*ptr=malloc(尺寸);//_-aligned_-malloc(尺寸、对齐);
memset(ptr,0,大小);
printf(“,返回ptr*:0x%p\n”,ptr);
返回ptr;
}
/**
*PFN_vkfree函数的实现
*/
void freeffunction(void*pUserData,void*pMemory){
printf(“pAllocator的自由函数:ptr:0x%p\n”,
(用户类型)pUserData,pMemory);
//现在,自由操作!
免费(pMemory);
}
/**
*PFN_vkReallocationFunction的实现
*/
void*reallocationFunction(void*pUserData,void*pOriginal,size\u t size,size\u t alignment,VkSystemAllocationScope allocationScope allocationScope){
printf(“定位器的重新定位函数:,大小%u,对齐%u,分配范围%d\n”,
(用户类型)数据、大小、对齐、分配范围);
返回realloc(原始,大小);
}
/**
*PFN_vkInternalAllocationNotification实现
*/
void internalAllocationNotification(void*pUserData,size\u t size,VkInternalAllocationType allocationType,vksystemaallocationscope allocationScope){
printf(“pAllocator的内部分配通知:,大小%uz,对齐方式%uz,分配类型%uz,分配范围%s\n”,
(用户类型)pUserData,
大小,
分配类型,
分配范围);
}
/**
*PFN_vkinternal重新通知实施
**/
void internalfree通知(void*pUserData,size\u t size,VkInternalAllocationType allocationType,vksystemaallocationscope allocationScope){
printf(“pAllocator的内部自由通知:,大小%uz,对齐%uz,分配类型%d,分配范围%s\n”,
(用户类型)pUserData、size、allocationType、allocationScope);
}
/**
*创建Pallocator
*@param info-用于跟踪分配器使用情况的字符串
*/
静态VkAllocationCallbacks*createPAllocator(const char*info){
VkAllocationCallbacks*m_分配器=(VkAllocationCallbacks*)malloc(sizeof(VkAllocationCallbacks));
memset(m_分配器,0,sizeof(VkAllocationCallbacks));
m_分配器->pUserData=(void*)信息;
m_分配器->pfnAllocation=(PFN_vkAllocationFunction)(&allocationFunction);
m_分配器->pfnrelocation=(PFN_vkReallocationFunction)(&reallocationFunction);
m_分配器->pfnFree=(PFN_vkfreeffunction)&freeffunction;
m_分配器->PFN内部分配=(PFN_vkInternalAllocationNotification)和内部分配通知;
m_分配器->PFN内部自由=(PFN_内部再通知)和内部自由通知;
//storePAllocator(m_分配器);
返回m_分配器;
}
`

我使用VulkanSDK中的Cube.c示例来测试我的代码和假设。此处提供修改版本

输出示例:

pAllocator's allocationFunction: <Device>, size: 800, alignment: 8, allocationScope: 1, return ptr* : 0x00000000061ECE40 
pAllocator's allocationFunction: <RenderPass>, size: 128, alignment: 8, allocationScope: 1, return ptr* : 0x000000000623FAB0 
pAllocator's allocationFunction: <ShaderModule>, size: 96, alignment: 8, allocationScope: 1, return ptr* : 0x00000000061F2C30 
pAllocator's allocationFunction: <ShaderModule>, size: 96, alignment: 8, allocationScope: 1, return ptr* : 0x00000000061F8790 
pAllocator's allocationFunction: <PipelineCache>, size: 152, alignment: 8, allocationScope: 1, return ptr* : 0x00000000061F2590 
pAllocator's allocationFunction: <Device>, size: 424, alignment: 8, allocationScope: 1, return ptr* : 0x00000000061F8EB0 
pAllocator's freeFunction: <ShaderModule> ptr: 0x00000000061F8790
pAllocator's freeFunction: <ShaderModule> ptr: 0x00000000061F2C30
pAllocator's allocationFunction: <Device>, size: 3448, alignment: 8, allocationScope: 1, return ptr* : 0x000000000624D260 
pAllocator's allocationFunction: <Device>, size: 3448, alignment: 8, allocationScope: 1, return ptr* : 0x0000000006249A80 
palocator的分配函数:,大小:800,对齐:8,分配范围:1,返回ptr*:0x0000000006140
pAllocator的分配函数:,大小:128,对齐:8,分配范围:1,返回ptr*:0x000000000623FAB0
pAllocator的分配函数:,大小:96,对齐:8,分配范围:1,返回ptr*:0x00000000061F2C30
pAllocator的分配函数:,大小:96,对齐:8,分配范围:1,返回ptr*:0x00000000061F8790
pAllocator的allocationFunction:,大小:152,对齐:8,allocationScope:1,re