This commit is contained in:
Till Wübbers
2025-04-27 12:00:22 +02:00
parent d75e5627f9
commit 4cdd80977c
8 changed files with 148 additions and 34 deletions

View File

@@ -96,16 +96,18 @@ struct SharedDevData
char ShaderLog[2048]{0};
};
struct MemoryArena
{
uint8_t* Ptr = nullptr;
uint64_t Size = 0;
uint64_t LastAllocSize = 0;
};
struct GameData
{
void* PermanentStorage = nullptr;
uint64_t PermanentStorageSize = 0;
void* EntityStorage = nullptr;
uint64_t EntityStorageSize = 0;
void* TransientStorage = nullptr;
uint64_t TransientStorageSize = 0;
MemoryArena PermanentArena;
MemoryArena EntityArena;
MemoryArena TransientArena;
};
struct SharedData

View File

@@ -23,6 +23,10 @@ constexpr const char* DLLPath = "libPuzGame.dll";
constexpr const wchar_t* DLLWatch = L"libPuzGame2.dll";
#endif
constexpr uint64_t KB = 1024LLU;
constexpr uint64_t MB = 1024LLU * 1024LLU;
constexpr uint64_t GB = 1024LLU * 1024LLU * 1024LLU;
namespace
{
bx::AllocatorI* defaultAllocator = new bx::DefaultAllocator{};
@@ -260,6 +264,14 @@ bool ReloadDLL()
return true;
}
void InitMemoryArena(MemoryArena& arena, uint64_t size)
{
arena.Size = size;
arena.Ptr = reinterpret_cast<uint8_t*>(
VirtualAllocEx(GetCurrentProcess(), NULL, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE));
arena.LastAllocSize = 0;
}
int main()
{
char PathBuf[512]{0};
@@ -301,15 +313,9 @@ int main()
HANDLE compiledShaderThread =
CreateThread(NULL, 0, FileWatcherThread, &DevData.FileWatcher.CompiledShaderWatcher, 0, &fileWatcherThreadId);
Shared.Game.PermanentStorageSize = 1024 * 1024;
Shared.Game.PermanentStorage = VirtualAllocEx(
GetCurrentProcess(), NULL, Shared.Game.PermanentStorageSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
Shared.Game.EntityStorageSize = 1024 * 1024;
Shared.Game.EntityStorage = VirtualAllocEx(
GetCurrentProcess(), NULL, Shared.Game.EntityStorageSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
Shared.Game.TransientStorageSize = 1024 * 1024 * 1024;
Shared.Game.TransientStorage = VirtualAllocEx(
GetCurrentProcess(), NULL, Shared.Game.TransientStorageSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
InitMemoryArena(Shared.Game.PermanentArena, MB);
InitMemoryArena(Shared.Game.EntityArena, MB);
InitMemoryArena(Shared.Game.TransientArena, 2 * GB);
StartupFunc(Shared);
bool isRunning = true;

View File

@@ -37,16 +37,30 @@ namespace Game
GameInst = &instance;
}
void* AllocateScratch(size_t byteCount, size_t align)
uint8_t* AllocateScratch(size_t byteCount, size_t align)
{
size_t offset = GetInstance().UsedScratchAmount;
uint8_t* base = static_cast<uint8_t*>(GetShared().Game.TransientStorage);
uint8_t* base = GetShared().Game.TransientArena.Ptr;
uint8_t* current = base + offset;
size_t offsetAligned = ((offset + align - 1) / align) * align;
uint8_t* ptrAligned = base + offsetAligned;
size_t newOffset = offsetAligned + byteCount;
if (newOffset > GetShared().Game.TransientStorageSize) return nullptr;
if (newOffset > GetShared().Game.TransientArena.Size) return nullptr;
GetInstance().UsedScratchAmount = newOffset;
return reinterpret_cast<void*>(ptrAligned);
GetShared().Game.TransientArena.LastAllocSize = byteCount;
return ptrAligned;
}
bool ResizeLastScratchAlloc(size_t newByteCount)
{
auto& arena = GetShared().Game.TransientArena;
if (newByteCount > arena.LastAllocSize)
{
LOG_ERROR("Can't resize to more than previous size!");
return false;
}
arena.Ptr -= arena.LastAllocSize;
arena.Ptr += newByteCount;
return true;
}
} // namespace Game

View File

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

View File

@@ -102,7 +102,7 @@ namespace Game
void Level::Setup(GameData& data)
{
LOG("Level setup");
void* storagePtr = data.EntityStorage;
uint8_t* storagePtr = data.EntityArena.Ptr;
bool needReset = false;
needReset |= Cubes.Setup(storagePtr, needReset);
needReset |= Tests.Setup(storagePtr, needReset);
@@ -419,6 +419,7 @@ namespace Game
UpdateMatrix(camTransform);
Vec3 cameraPos = camTransform.Position;
// TODO: disable warning & check if parentheses make sense like this
Vec2 uiOffset = Vec2{static_cast<float>(Data.WidthTiles / Puzzle::Config::CardSize - 1),
static_cast<float>(Data.HeightTiles / Puzzle::Config::CardSize) - 1};
uiOffset *= -UICardOffset * 0.5f;

View File

@@ -72,7 +72,7 @@ namespace Game
class IEntityManager
{
public:
virtual bool Setup(void*& ptr, bool forceReset) = 0;
virtual bool Setup(uint8_t*& ptr, bool forceReset) = 0;
};
template <typename T, typename HandleT, uint32_t C> class EntityManager : public IEntityManager
@@ -86,7 +86,7 @@ namespace Game
public:
// Returns true if size changed
bool Setup(void*& ptr, bool forceReset)
bool Setup(uint8_t*& ptr, bool forceReset)
{
bool changed = false;
if (EntitySize != sizeof(T) || forceReset)
@@ -96,7 +96,7 @@ namespace Game
}
EntitySize = sizeof(T);
Data = reinterpret_cast<T*>(ptr);
ptr = (uint8_t*)ptr + (C * EntitySize);
ptr += C * EntitySize;
return changed;
}

View File

@@ -33,22 +33,22 @@ namespace Game
tracy::StartupProfiler();
#endif
if (shared.Game.PermanentStorage == nullptr)
if (shared.Game.PermanentArena.Ptr == nullptr)
{
LOG_ERROR("Game memory not initialized!!");
return;
}
if (shared.Game.EntityStorage == nullptr)
if (shared.Game.EntityArena.Ptr == nullptr)
{
LOG_ERROR("Entity memory not initialized!");
return;
}
if (shared.Game.PermanentStorageSize < sizeof(GameInstance))
if (shared.Game.PermanentArena.Size < sizeof(GameInstance))
{
LOG_ERROR("Game memory too small! %u < %u", shared.Game.PermanentStorageSize, sizeof(GameInstance));
LOG_ERROR("Game memory too small! %u < %u", shared.Game.PermanentArena.Size, sizeof(GameInstance));
return;
}
GameInstance& instance = *reinterpret_cast<GameInstance*>(shared.Game.PermanentStorage);
GameInstance& instance = *reinterpret_cast<GameInstance*>(shared.Game.PermanentArena.Ptr);
if (sizeof(GameInstance) != instance.Size)
{
LOG_WARN("Game instance size changed, resetting!");

View File

@@ -32,15 +32,104 @@ namespace Game
{
namespace
{
constexpr size_t ChunkSize = 1024;
constexpr size_t MaxFileSize = ChunkSize * 1024 * 1024;
constexpr size_t MaxChunkCount = MaxFileSize / ChunkSize;
bool BufferedFileRead(FILE* file, uint8_t* writePtr, size_t& totalReadCount)
{
for (int32_t i = 0; i < MaxChunkCount; ++i)
{
size_t readCount = std::fread(writePtr, 1, ChunkSize, file);
writePtr += readCount;
totalReadCount += readCount;
if (readCount != ChunkSize)
{
if (std::feof(file))
{
return true;
}
int err = std::ferror(file);
if (err != 0)
{
LOG_ERROR("Error reading file: %i", err);
return false;
}
LOG_ERROR("This should never happen!");
return false;
}
}
if (!std::feof(file))
{
LOG_ERROR("File too big to be read!");
return false;
}
return true;
}
const bgfx::Memory* LoadBinaryFile(const char* path, int32_t retryCount = 1)
{
FILE* file = nullptr;
for (int32_t i = 0; i < retryCount; ++i)
{
file = std::fopen(path, "rb");
if (file == nullptr)
{
if (i < retryCount - 1)
{
std::this_thread::sleep_for(100ms);
LOG_WARN("Failed to open file, retrying...");
break;
}
else
{
LOG_ERROR("Failed to open file!");
return nullptr;
}
}
}
uint8_t* dataPtr = AllocateScratch(MaxFileSize);
if (dataPtr == nullptr)
{
LOG_ERROR("Failed to load file, exceeded scratch memory! %s", path);
return nullptr;
}
uint64_t totalReadCount = 0;
bool success = BufferedFileRead(file, dataPtr, totalReadCount);
std::fclose(file);
if (!success)
{
LOG_ERROR("Failed to read file %s", path);
ResizeLastScratchAlloc(0);
return nullptr;
}
if (!ResizeLastScratchAlloc(totalReadCount))
{
LOG_ERROR("This should never happen!");
return nullptr;
}
return bgfx::makeRef(dataPtr, totalReadCount);
}
const bgfx::Memory* loadFile(const char* path, bool appendZero = false, int32_t retryCount = 1)
{
FILE* file;
for (int32_t i = 0; i < retryCount; ++i)
{
file = fopen(path, "rb");
file = std::fopen(path, "rb");
if (file == nullptr && i < retryCount - 1)
{
std::this_thread::sleep_for(100ms);
LOG_WARN("Failed to open file, retrying...");
break;
}
@@ -48,11 +137,12 @@ namespace Game
long fileSize = ftell(file);
fseek(file, 0, SEEK_SET);
long fileSizeX = appendZero ? fileSize + 1 : fileSize;
long fileSizeX = appendZero ? (fileSize + 1) : fileSize;
void* rawMem = AllocateScratch(fileSizeX);
if (rawMem == nullptr)
{
LOG_ERROR("Failed to load file, exceeded scratch memory! %s", path);
return nullptr;
}
const bgfx::Memory* mem = bgfx::makeRef(rawMem, fileSizeX);
fread(mem->data, 1, fileSize, file);
@@ -127,7 +217,7 @@ namespace Game
bgfx::TextureHandle handle = BGFX_INVALID_HANDLE;
bx::Error err;
const bgfx::Memory* data = loadFile(_filePath.getCPtr());
const bgfx::Memory* data = LoadBinaryFile(_filePath.getCPtr());
if (data == nullptr || data->data == nullptr || data->size == 0)
{
LOG_WARN("Failed to find image %s", _filePath.getCPtr());