diff options
| -rw-r--r-- | src/asset-manager.cpp | 6 | ||||
| -rw-r--r-- | src/memory.cpp | 32 | ||||
| -rw-r--r-- | src/memory.hpp | 18 |
3 files changed, 36 insertions, 20 deletions
diff --git a/src/asset-manager.cpp b/src/asset-manager.cpp index d463cff..5ff25f3 100644 --- a/src/asset-manager.cpp +++ b/src/asset-manager.cpp @@ -31,11 +31,11 @@ AssetHandle AM_Register_Inner(const void *src, void *dst, int64_t size, const ch return AssetHandle{assetHandle_T}; } -AssetHandle AM_Register(const void *data, int64_t size, const char *key) { +AssetHandle AM_Register(const void *data, int64_t size, std::size_t alignment, const char *key) { assert(data != nullptr && "Attempt to register invalid asset data"); assert(data != CAFE_BABE(void) && "Attempt to register invalid asset data"); assert(size != 0 && "Attempt to register asset data of size 0"); - void *target = Pke_New(size); + void *target = Pke_New(size, alignment); return AM_Register_Inner(data, target, size, key); } @@ -45,7 +45,7 @@ AssetHandle AM_Register(const char *path) { throw "failed to open file"; } auto fileSize = (int64_t)file.tellg(); - void *target = Pke_New(fileSize); + void *target = Pke_New(fileSize, alignof(uint64_t)); int64_t pathLen = strlen(path); auto assetHandle = AM_Register_Inner(nullptr, target, 0, path + (pathLen > 16 ? pathLen - 16 : 0)); diff --git a/src/memory.cpp b/src/memory.cpp index 793c4d0..538ffd8 100644 --- a/src/memory.cpp +++ b/src/memory.cpp @@ -1,6 +1,9 @@ #include "memory.hpp" +const std::size_t MINIMUM_ALIGNMENT = 1; +const std::size_t MAXIMUM_ALIGNMENT = 64; + struct MemBlock { char *data; std::size_t size; @@ -52,12 +55,16 @@ void DestroyBucket(MemBucket *bkt) { bkt->transient = false; } -void *Pke_New(std::size_t sz, MemBucket *bkt) { +void *Pke_New(std::size_t sz, std::size_t alignment, MemBucket *bkt) { MemBlock *blocks = reinterpret_cast<MemBlock *>(bkt->blocks); + std::size_t calculatedAlignment = alignment < MINIMUM_ALIGNMENT ? MINIMUM_ALIGNMENT : alignment; int64_t availBlockIndex = -1; void *data = nullptr; for (int64_t i = 0; i <= bkt->lastEmptyBlockIndex; ++i) { auto blk = blocks[i]; + std::size_t misalignment = reinterpret_cast<std::size_t>(blk.data) % calculatedAlignment; + if (misalignment != 0) + continue; if (blk.size > sz) { availBlockIndex = i; break; @@ -77,24 +84,31 @@ void *Pke_New(std::size_t sz, MemBucket *bkt) { } } else { assert(bkt->head + sz <= bkt->size && "memory bucket specified, but full"); - data = bkt->ptr + bkt->head; - bkt->head += sz; + std::size_t misalignment = reinterpret_cast<std::size_t>(bkt->ptr + bkt->head) % calculatedAlignment; + std::size_t padding = calculatedAlignment - misalignment; + if (misalignment != 0) { + bkt->lastEmptyBlockIndex += 1; + blocks[bkt->lastEmptyBlockIndex].data = bkt->ptr + bkt->head; + blocks[bkt->lastEmptyBlockIndex].size = padding; + } + data = bkt->ptr + bkt->head + padding; + bkt->head += sz + padding; } bkt->allocs++; return data; } -void *Pke_New(std::size_t sz) { +void *Pke_New(std::size_t sz, std::size_t alignment) { MemBucket *bkt = nullptr; for (long i = 0; i < bucketHead; ++i) { - if (buckets[i].transient == false && buckets[i].size - buckets[i].head > sz) { + if (buckets[i].transient == false && buckets[i].size - buckets[i].head > sz + MAXIMUM_ALIGNMENT) { bkt = &buckets[i]; } } if (bkt == nullptr) { bkt = &buckets[InitNewBucket(DEFAULT_BUCKET_SIZE)]; } - return Pke_New(sz, bkt); + return Pke_New(sz, alignment, bkt); } void Pke_Delete(const void *ptr, std::size_t sz, MemBucket *bkt) { @@ -170,9 +184,11 @@ void Pke_MemoryFlush() { } } -uint64_t Buckets_NewHandle(std::size_t bucketBytes, uint64_t bucketItemCount, uint64_t &bucketIncrementer, uint64_t &bucketCounter, uint64_t &itemCounter, void*& buckets) { +uint64_t Buckets_NewHandle(std::size_t bucketBytes, std::size_t alignment, uint64_t bucketItemCount, uint64_t &bucketIncrementer, uint64_t &bucketCounter, uint64_t &itemCounter, void*& buckets) { uint64_t newHandle{itemCounter | bucketCounter}; + std::size_t calculatedAlignment = alignment < MINIMUM_ALIGNMENT ? MINIMUM_ALIGNMENT : alignment; + itemCounter += uint64_t{1ULL << 32}; if (itemCounter > uint64_t{(bucketItemCount - 1) << 32}) { itemCounter = 0ULL; @@ -180,7 +196,7 @@ uint64_t Buckets_NewHandle(std::size_t bucketBytes, uint64_t bucketItemCount, ui } if (bucketCounter > bucketIncrementer) { int64_t newIncrement = bucketIncrementer * 1.5; - char * newBuckets = reinterpret_cast<char *>(Pke_New(bucketBytes * newIncrement)); + char * newBuckets = reinterpret_cast<char *>(Pke_New(bucketBytes * newIncrement, calculatedAlignment)); std::memcpy(newBuckets, buckets, bucketBytes * bucketIncrementer); Pke_Delete(buckets, bucketBytes * bucketIncrementer); buckets = newBuckets; diff --git a/src/memory.hpp b/src/memory.hpp index b93890a..b76a72b 100644 --- a/src/memory.hpp +++ b/src/memory.hpp @@ -24,8 +24,8 @@ struct BucketContainer { T *buckets = nullptr; }; -void *Pke_New(std::size_t sz); -void *Pke_New(std::size_t sz, MemBucket *bkt); +void *Pke_New(std::size_t sz, std::size_t alignment); +void *Pke_New(std::size_t sz, std::size_t alignment, MemBucket *bkt); void Pke_Delete(const void *ptr, std::size_t sz); void Pke_Delete(const void *ptr, std::size_t sz, MemBucket *bkt); void Pke_DebugPrint(); @@ -38,9 +38,9 @@ template <typename T> inline T *Pke_New(MemBucket *bucket = nullptr) { void *ptr = nullptr; if (bucket) { - ptr = Pke_New(sizeof(T), bucket); + ptr = Pke_New(sizeof(T), alignof(T), bucket); } else { - ptr = Pke_New(sizeof(T)); + ptr = Pke_New(sizeof(T), alignof(T)); } if IS_CONSTRUCTIBLE(T) { return new (ptr) T{}; @@ -51,9 +51,9 @@ template <typename T> inline T *Pke_New(long count, MemBucket *bucket = nullptr) { char *ptr = nullptr; if (bucket) { - ptr = static_cast<char *>(Pke_New(sizeof(T) * count, bucket)); + ptr = static_cast<char *>(Pke_New(sizeof(T) * count, alignof(T), bucket)); } else { - ptr = static_cast<char *>(Pke_New(sizeof(T) * count)); + ptr = static_cast<char *>(Pke_New(sizeof(T) * count, alignof(T))); } if IS_CONSTRUCTIBLE(T) { for (long i = 0; i < count; ++i) { @@ -94,18 +94,18 @@ void Buckets_Init(BucketContainer<T, CT> &bktContainer) { bktContainer.buckets = Pke_New<T>(bktContainer.incrementer); } -uint64_t Buckets_NewHandle(std::size_t bucketBytes, uint64_t bucketItemCount, uint64_t &bucketIncrementer, uint64_t &bucketCounter, uint64_t &itemCounter, void*& buckets); +uint64_t Buckets_NewHandle(std::size_t bucketBytes, std::size_t alignment, uint64_t bucketItemCount, uint64_t &bucketIncrementer, uint64_t &bucketCounter, uint64_t &itemCounter, void*& buckets); template <typename T> inline uint64_t Buckets_NewHandle(uint64_t bucketItemCount, uint64_t &bucketIncrementer, uint64_t &bucketCounter, uint64_t &itemCounter, T*& buckets) { void *ptr = reinterpret_cast<void *>(buckets); - uint64_t handle = Buckets_NewHandle(sizeof(T), bucketItemCount, bucketIncrementer, bucketCounter, itemCounter, ptr); + uint64_t handle = Buckets_NewHandle(sizeof(T), alignof(T), bucketItemCount, bucketIncrementer, bucketCounter, itemCounter, ptr); buckets = reinterpret_cast<T *>(ptr); return handle; } template <typename T, typename CT> inline CT Buckets_NewHandle(uint64_t maxBucketItemCount, BucketContainer<T, CT> &bktContainer) { - return Buckets_NewHandle(maxBucketItemCount, bktContainer.incrementer, bktContainer.bucketCounter, bktContainer.itemCounter, bktContainer.buckets); + return Buckets_NewHandle<T>(maxBucketItemCount, bktContainer.incrementer, bktContainer.bucketCounter, bktContainer.itemCounter, bktContainer.buckets); } static inline constexpr uint64_t Buckets_GetBucketIndex(uint64_t handle) { |
