看到參考Vk實現的內存分配器中調用到的幾個對齊內存分配函數還蠻有興趣的,於是自己嘗試實現了一下
有一個比較大的問題是不知道std裏的_aligned_realloc具體是怎樣實現的,自己用先free再malloc的方法亂寫了一個,但是發現在簡單測試下和調用std中的函數結果是相似的。。。?都能做到不改變指針的值,還請了解這方面的先輩指導一下…
順便,jetbrain系的某些代碼強制格式實在不太好受,,
//
// Created by LCBHSStudent on 2020/1/30.
//
#include <malloc.h>
#include <myusing/myusing.h>
void* aligned_malloc(size_t size, size_t alignment) {
if(alignment & (alignment - 1)) {
return nullptr;
}
//維護FreeBlock(void)指針佔用的內存大小-----用sizeof獲取
int pSize = sizeof (void*);
// 求得讓FreeBlock
// 內存對齊所需要的內存大小
unsigned requestedSize = size + alignment - 1 + pSize;
// 分配的大小
void* rawMemory = malloc(requestedSize);
// 實際分配的內存地址(差不多就是指針運算數字形式)
uintptr_t start = (uintptr_t )rawMemory + pSize;
// 此處的 & 能高位保留,是由於~導致其他位無關位都變成了1
void* aligned = (void*)((start + alignment - 1) & ~(alignment-1));
// 維護一個指向malloc()真正分配的內存的指針
*(void**) ((uintptr_t) aligned - pSize) = rawMemory;
return aligned; //因爲做了向上的舍入,所以不需要多餘的清理操作
// 這樣分配出的內存,對齊填充位於最前,後面緊跟維護指針,再後就是對象的chain
}
void aligned_free(void* aligned) {
void* rawMemory = *(void**) ((uintptr_t)aligned - sizeof(void*));
free(rawMemory);
}
bool isAligned(void* data, unsigned alignment) {
return ((uintptr_t) data & (alignment - 1)) == 0;
}
void* aligned_realloc(void* data, size_t size, size_t alignment) {
if(isAligned(data,
static_cast<int> (alignment)
)) {
aligned_free(data);
return aligned_malloc(size, alignment);
} else {
return nullptr;
}
}
下面是簡單實現的vkAllocator
//
// Created by LCBHSStudent on 2020/1/29.
//
#ifndef VULKANDEMO_VKALLOCATOR_H
#define VULKANDEMO_VKALLOCATOR_H
#include <myusing/myusing.h>
#include <vulkan/vulkan.h>
class VkAllocator {
public:
inline explicit operator VkAllocationCallbacks () const {
VkAllocationCallbacks result;
{
result.pUserData = (void*) this;
result.pfnAllocation = &Allocation;
result.pfnReallocation = &ReAllocation;
result.pfnFree = &Free;
result.pfnInternalAllocation = nullptr;
result.pfnInternalFree = nullptr;
}
return result;
}
private:
static void* VKAPI_CALL Allocation(
void* pUserData,
size_t size,
size_t alignment,
VkSystemAllocationScope allocationScope);
static void* VKAPI_CALL ReAllocation(
void* pUserData,
void* pOriginal,
size_t size,
size_t alignment,
VkSystemAllocationScope allocationScope);
static void VKAPI_CALL Free(
void* pUserData,
void* pMemory);
void* Allocation(
size_t size,
size_t alignment,
VkSystemAllocationScope allocationScope);
void* ReAllocation(
void* pOriginal,
size_t size,
size_t alignment,
VkSystemAllocationScope allocationScope);
void Free(void* pMemory);
};
#endif //VULKANDEMO_VKALLOCATOR_H
//
// Created by LCBHSStudent on 2020/1/29.
//
#include <cassert>
#include "VkAllocator.h"
void* VkAllocator::Allocation(size_t size,
size_t alignment,
VkSystemAllocationScope allocationScope
)
{
auto ret = aligned_malloc(size, alignment);
assert(ret == nullptr);
return ret;
}
void* VKAPI_CALL VkAllocator::Allocation(
void* pUserData,
size_t size,
size_t alignment,
VkSystemAllocationScope allocationScope)
{
return static_cast<VkAllocator*>(pUserData)->Allocation(size,
alignment,
allocationScope);
}
void* VkAllocator::ReAllocation(
void* pOriginal,
size_t size,
size_t alignment,
VkSystemAllocationScope allocationScope)
{
return aligned_realloc(pOriginal, size, alignment);
}
void* VKAPI_CALL VkAllocator::ReAllocation(
void* pUserData,
void* pOriginal,
size_t size,
size_t alignment,
VkSystemAllocationScope allocationScope)
{
return static_cast<VkAllocator*>(pUserData)->ReAllocation(
pOriginal, size, alignment, allocationScope);
}
void VkAllocator::Free(void *pMemory) {
aligned_free(pMemory);
}
void VKAPI_CALL VkAllocator::Free(
void* pUserData,
void* pMemory)
{
return static_cast<VkAllocator*>(pUserData)->Free(pMemory);
}