fix memory arena alloc

This commit is contained in:
Till Wübbers
2025-04-28 10:03:09 +02:00
parent 32d89d8f77
commit 171e25ac76
8 changed files with 40 additions and 29 deletions

View File

@@ -98,8 +98,9 @@ struct SharedDevData
struct MemoryArena struct MemoryArena
{ {
uint8_t* Ptr = nullptr; uint8_t* Base = nullptr;
uint64_t Size = 0; uint64_t Used = 0;
uint64_t MaxSize = 0;
uint64_t LastAllocSize = 0; uint64_t LastAllocSize = 0;
}; };

View File

@@ -266,9 +266,10 @@ bool ReloadDLL()
void InitMemoryArena(MemoryArena& arena, uint64_t size) void InitMemoryArena(MemoryArena& arena, uint64_t size)
{ {
arena.Size = size; arena.MaxSize = size;
arena.Ptr = reinterpret_cast<uint8_t*>( arena.Base = reinterpret_cast<uint8_t*>(
VirtualAllocEx(GetCurrentProcess(), NULL, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE)); VirtualAllocEx(GetCurrentProcess(), NULL, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE));
arena.Used = 0;
arena.LastAllocSize = 0; arena.LastAllocSize = 0;
} }

View File

@@ -37,21 +37,20 @@ namespace Game
GameInst = &instance; GameInst = &instance;
} }
uint8_t* AllocateScratch(size_t byteCount, size_t align) uint8_t* AllocateScratch(uint64_t byteCount, uint32_t align)
{ {
size_t offset = GetInstance().UsedScratchAmount; assert(align <= 64); // The alignment of the arena limits the alignment that can be specified here!
uint8_t* base = GetShared().Game.TransientArena.Ptr; auto& arena = GetShared().Game.TransientArena;
uint8_t* current = base + offset; uint64_t offsetAligned = ((arena.Used + align - 1) / align) * align;
size_t offsetAligned = ((offset + align - 1) / align) * align; uint8_t* ptrAligned = arena.Base + offsetAligned;
uint8_t* ptrAligned = base + offsetAligned; uint64_t newOffset = offsetAligned + byteCount;
size_t newOffset = offsetAligned + byteCount; if (newOffset > arena.MaxSize) return nullptr;
if (newOffset > GetShared().Game.TransientArena.Size) return nullptr; arena.Used = newOffset;
GetInstance().UsedScratchAmount = newOffset; arena.LastAllocSize = byteCount;
GetShared().Game.TransientArena.LastAllocSize = byteCount;
return ptrAligned; return ptrAligned;
} }
bool ResizeLastScratchAlloc(size_t newByteCount) bool ResizeLastScratchAlloc(uint64_t newByteCount)
{ {
auto& arena = GetShared().Game.TransientArena; auto& arena = GetShared().Game.TransientArena;
if (newByteCount > arena.LastAllocSize) if (newByteCount > arena.LastAllocSize)
@@ -59,8 +58,17 @@ namespace Game
LOG_ERROR("Can't resize to more than previous size!"); LOG_ERROR("Can't resize to more than previous size!");
return false; return false;
} }
arena.Ptr -= arena.LastAllocSize; LOG("Resizing last allocation from %llu to %llu", arena.LastAllocSize, newByteCount);
arena.Ptr += newByteCount; arena.Used -= arena.LastAllocSize;
arena.Used += newByteCount;
LOG("New total: %llu", arena.Used);
return true; return true;
} }
void ResetScratch()
{
auto& arena = GetShared().Game.TransientArena;
arena.Used = 0;
arena.LastAllocSize = 0;
}
} // namespace Game } // namespace Game

View File

@@ -33,6 +33,7 @@ namespace Game
void SetShared(SharedData& instance); void SetShared(SharedData& instance);
GameInstance& GetInstance(); GameInstance& GetInstance();
void SetInstance(GameInstance& instance); void SetInstance(GameInstance& instance);
uint8_t* AllocateScratch(size_t byteCount, size_t align = 16); uint8_t* AllocateScratch(uint64_t byteCount, uint32_t align = 16);
bool ResizeLastScratchAlloc(size_t newByteCount); bool ResizeLastScratchAlloc(uint64_t newByteCount);
void ResetScratch();
} // namespace Game } // namespace Game

View File

@@ -75,7 +75,6 @@ namespace Game
{ {
bool IsInitialized = false; bool IsInitialized = false;
uint64_t Size = sizeof(GameInstance); uint64_t Size = sizeof(GameInstance);
uint64_t UsedScratchAmount = 0;
Time Time; Time Time;
PlayerData Player; PlayerData Player;
Level GameLevel; Level GameLevel;

View File

@@ -102,7 +102,7 @@ namespace Game
void Level::Setup(GameData& data) void Level::Setup(GameData& data)
{ {
LOG("Level setup"); LOG("Level setup");
uint8_t* storagePtr = data.EntityArena.Ptr; uint8_t* storagePtr = data.EntityArena.Base;
bool needReset = false; bool needReset = false;
needReset |= Cubes.Setup(storagePtr, needReset); needReset |= Cubes.Setup(storagePtr, needReset);
needReset |= Tests.Setup(storagePtr, needReset); needReset |= Tests.Setup(storagePtr, needReset);

View File

@@ -33,30 +33,30 @@ namespace Game
tracy::StartupProfiler(); tracy::StartupProfiler();
#endif #endif
if (shared.Game.PermanentArena.Ptr == nullptr) if (shared.Game.PermanentArena.Base == nullptr)
{ {
LOG_ERROR("Game memory not initialized!!"); LOG_ERROR("Game memory not initialized!!");
return; return;
} }
if (shared.Game.EntityArena.Ptr == nullptr) if (shared.Game.EntityArena.Base == nullptr)
{ {
LOG_ERROR("Entity memory not initialized!"); LOG_ERROR("Entity memory not initialized!");
return; return;
} }
if (shared.Game.PermanentArena.Size < sizeof(GameInstance)) if (shared.Game.PermanentArena.MaxSize < sizeof(GameInstance))
{ {
LOG_ERROR("Game memory too small! %u < %u", shared.Game.PermanentArena.Size, sizeof(GameInstance)); LOG_ERROR("Game memory too small! %u < %u", shared.Game.PermanentArena.MaxSize, sizeof(GameInstance));
return; return;
} }
GameInstance& instance = *reinterpret_cast<GameInstance*>(shared.Game.PermanentArena.Ptr); GameInstance& instance = *reinterpret_cast<GameInstance*>(shared.Game.PermanentArena.Base);
if (sizeof(GameInstance) != instance.Size) if (sizeof(GameInstance) != instance.Size)
{ {
LOG_WARN("Game instance size changed, resetting!"); LOG_WARN("Game instance size changed, resetting!");
instance = {}; instance = {};
} }
instance.UsedScratchAmount = 0;
SetShared(shared); SetShared(shared);
SetInstance(instance); SetInstance(instance);
ResetScratch();
Puzzle::LoadStaticPuzzleData(); Puzzle::LoadStaticPuzzleData();
SetupInstance.Rendering.Setup(); SetupInstance.Rendering.Setup();
instance.GameLevel.Setup(shared.Game); instance.GameLevel.Setup(shared.Game);

View File

@@ -36,13 +36,14 @@ namespace Game
constexpr size_t MaxFileSize = ChunkSize * 1024 * 1024; constexpr size_t MaxFileSize = ChunkSize * 1024 * 1024;
constexpr size_t MaxChunkCount = MaxFileSize / ChunkSize; constexpr size_t MaxChunkCount = MaxFileSize / ChunkSize;
bool BufferedFileRead(FILE* file, uint8_t* writePtr, size_t& totalReadCount) bool BufferedFileRead(FILE* const file, uint8_t* const writePtrIn, size_t& outTotalReadCount)
{ {
uint8_t* writePtr = writePtrIn;
for (int32_t i = 0; i < MaxChunkCount; ++i) for (int32_t i = 0; i < MaxChunkCount; ++i)
{ {
size_t readCount = std::fread(writePtr, 1, ChunkSize, file); size_t readCount = std::fread(writePtr, 1, ChunkSize, file);
writePtr += readCount; writePtr += readCount;
totalReadCount += readCount; outTotalReadCount += readCount;
if (readCount != ChunkSize) if (readCount != ChunkSize)
{ {