Add asset array memory api stubs

This commit is contained in:
Doyle Thai 2017-05-26 13:31:01 +10:00
parent f89b3ff706
commit 96ac39724d
6 changed files with 190 additions and 75 deletions

View File

@ -962,33 +962,35 @@ extern "C" void DTR_Update(PlatformRenderBuffer *const platformRenderBuffer,
DTRAsset_InitGlobalState(); DTRAsset_InitGlobalState();
memory->isInit = true; memory->isInit = true;
memory->context = DqnMemStack_Push(&memory->permMemStack, sizeof(DTRState)); memory->context = DqnMemStack_Push(&memory->mainStack, sizeof(DTRState));
DQN_ASSERT(memory->context);
DqnMemStack *const assetStack = &memory->assetStack;
DqnMemStack *const tempStack = &memory->tempStack;
DQN_ASSERT(memory->context);
state = (DTRState *)memory->context; state = (DTRState *)memory->context;
DTRAsset_FontToBitmapLoad(input->api, memory, &state->font, "Roboto-bold.ttf", DTRAsset_FontToBitmapLoad(input->api, memory, &state->font, "Roboto-bold.ttf",
DqnV2i_2i(256, 256), DqnV2i_2i(' ', '~'), 12); DqnV2i_2i(256, 256), DqnV2i_2i(' ', '~'), 12);
DTRAsset_BitmapLoad(input->api, &memory->permMemStack, DTRAsset_BitmapLoad(input->api, assetStack,
&memory->transMemStack, &state->bitmap, "tree00.bmp"); tempStack, &state->bitmap, "tree00.bmp");
if (DTR_DEBUG) if (DTR_DEBUG)
{ {
DTRBitmap test = {}; DTRBitmap test = {};
DqnTempMemStack tmp = DqnMemStack_BeginTempRegion(&memory->transMemStack); DqnTempMemStack tmp = DqnMemStack_BeginTempRegion(&memory->tempStack);
DTRAsset_BitmapLoad(input->api, &memory->permMemStack, &memory->transMemStack, &test, "byte_read_check.bmp"); DTRAsset_BitmapLoad(input->api, assetStack, &memory->tempStack, &test, "byte_read_check.bmp");
DqnMemStack_EndTempRegion(tmp); DqnMemStack_EndTempRegion(tmp);
} }
if (DTRAsset_WavefModelLoad(input->api, memory, &state->obj, "african_head.obj")) if (DTRAsset_WavefModelLoad(input->api, memory, &state->obj, "african_head.obj"))
{ {
DTRAsset_BitmapLoad(input->api, &memory->permMemStack, &memory->transMemStack, DTRAsset_BitmapLoad(input->api, assetStack, tempStack, &state->objTex,
&state->objTex, "african_head_diffuse.tga"); "african_head_diffuse.tga");
} }
DTRDebug_TestWavefFaceAndVertexParser(&state->obj); DTRDebug_TestWavefFaceAndVertexParser(&state->obj);
} }
DqnTempMemStack transMemTmpRegion = DqnMemStack_BeginTempRegion(&memory->transMemStack); DqnTempMemStack transMemTmpRegion = DqnMemStack_BeginTempRegion(&memory->tempStack);
DTRRenderBuffer renderBuffer = {}; DTRRenderBuffer renderBuffer = {};
renderBuffer.width = platformRenderBuffer->width; renderBuffer.width = platformRenderBuffer->width;
@ -997,7 +999,7 @@ extern "C" void DTR_Update(PlatformRenderBuffer *const platformRenderBuffer,
renderBuffer.memory = (u8 *)platformRenderBuffer->memory; renderBuffer.memory = (u8 *)platformRenderBuffer->memory;
u32 zBufferSize = platformRenderBuffer->width * platformRenderBuffer->height; u32 zBufferSize = platformRenderBuffer->width * platformRenderBuffer->height;
renderBuffer.zBuffer = (f32 *)DqnMemStack_Push(&memory->transMemStack, renderBuffer.zBuffer = (f32 *)DqnMemStack_Push(&memory->tempStack,
zBufferSize * sizeof(*renderBuffer.zBuffer)); zBufferSize * sizeof(*renderBuffer.zBuffer));
for (u32 i = 0; i < zBufferSize; i++) renderBuffer.zBuffer[i] = DQN_F32_MIN; for (u32 i = 0; i < zBufferSize; i++) renderBuffer.zBuffer[i] = DQN_F32_MIN;
@ -1153,8 +1155,8 @@ extern "C" void DTR_Update(PlatformRenderBuffer *const platformRenderBuffer,
// End Update // End Update
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
DqnMemStack_EndTempRegion(transMemTmpRegion); DqnMemStack_EndTempRegion(transMemTmpRegion);
DqnMemStack_ClearCurrBlock(&memory->transMemStack, true); DqnMemStack_ClearCurrBlock(&memory->tempStack, true);
DQN_ASSERT(memory->transMemStack.tempStackCount == 0); DQN_ASSERT(memory->tempStack.tempStackCount == 0);
DQN_ASSERT(memory->permMemStack.tempStackCount == 0); DQN_ASSERT(memory->mainStack.tempStackCount == 0);
} }

View File

@ -17,17 +17,117 @@ void DTRAsset_InitGlobalState()
stbi_set_flip_vertically_on_load(true); stbi_set_flip_vertically_on_load(true);
} }
FILE_SCOPE bool WavefModelInit(DTRWavefModel *const obj, const i32 vertexInitCapacity = 100, FILE_SCOPE void MemcopyInternal(u8 *dest, u8 *src, size_t numBytes)
const i32 faceInitCapacity = 100) {
if (!dest || !src || numBytes == 0) return;
for (size_t i = 0; i < numBytes; i++)
dest[i] = src[i];
}
FILE_SCOPE void AssetDqnArrayMemAPICallback(DqnMemAPICallbackInfo info, DqnMemAPICallbackResult *result)
{
DQN_ASSERT(info.type != DqnMemAPICallbackType_Invalid);
DqnMemStack *stack = static_cast<DqnMemStack *>(info.userContext);
switch (info.type)
{
case DqnMemAPICallbackType_Alloc:
{
void *ptr = DqnMemStack_Push(stack, info.requestSize);
result->newMemPtr = ptr;
result->type = DqnMemAPICallbackType_Alloc;
}
break;
case DqnMemAPICallbackType_Free:
{
DqnMemStackBlock **blockPtr = &stack->block;
while (*blockPtr && (*blockPtr)->memory != info.ptrToFree)
{
// NOTE(doyle): Ensure that the base ptr of each block is always
// actually aligned so we don't ever miss finding the block if
// the allocator had to realign the pointer from the base
// address.
if (DTR_DEBUG)
{
size_t memBaseAddr = (size_t)((*blockPtr)->memory);
DQN_ASSERT(DQN_ALIGN_POW_N(memBaseAddr, stack->byteAlign) ==
memBaseAddr);
}
blockPtr = &((*blockPtr)->prevBlock);
}
DQN_ASSERT(*blockPtr && (*blockPtr)->memory == info.ptrToFree);
DqnMemStackBlock *blockToFree = *blockPtr;
*blockPtr = blockToFree->prevBlock;
DqnMem_Free(blockToFree);
}
break;
case DqnMemAPICallbackType_Realloc:
{
result->type = DqnMemAPICallbackType_Realloc;
// Check if the ptr is the last thing that was allocated. If so we
// can check if there's enough space in place for realloc and give
// them that.
u8 *currMemPtr = (u8 *)(stack->block->memory + stack->block->used);
u8 *checkPtr = currMemPtr - info.oldSize;
if (checkPtr == info.oldMemPtr)
{
if ((stack->block->used + info.newRequestSize) < stack->block->size)
{
stack->block->used += info.newRequestSize;
result->newMemPtr = info.oldMemPtr;
return;
}
// The allocation was the last one allocated, but there's not
// enough space to realloc in the block. For book-keeping,
// "deallocate" the old mem ptr by reverting the usage of the
// memory stack.
stack->block->used -= info.oldSize;
}
// NOTE(doyle): This leaves chunks of memory dead!!! But, we use
// this in our custom allocator, which its strategy is to load all
// the data, using as much re-allocations as required then after the
// fact, recompact the data by Memcopying the data together and free
// the extraneous blocks we've made.
// Otherwise, not enough space or, allocation is not the last
// allocated, so can't expand inplace.
DqnMemStackBlock *newBlock =
DqnMemStack_AllocateCompatibleBlock(stack, info.newRequestSize);
if (DqnMemStack_AttachBlock(stack, newBlock))
{
void *newPtr = DqnMemStack_Push(stack, info.newRequestSize);
MemcopyInternal((u8 *)newPtr, (u8 *)info.oldMemPtr, info.oldSize);
result->newMemPtr = newPtr;
}
else
{
// TODO(doyle): Die out of memory
DQN_ASSERT(DQN_INVALID_CODE_PATH);
}
}
break;
}
}
FILE_SCOPE bool WavefModelInit(DTRWavefModel *const obj,
DqnMemAPI memAPI = DqnMemAPI_DefaultUseCalloc(),
const i32 vertexInitCapacity = 100, const i32 faceInitCapacity = 100)
{ {
if (!obj) return false; if (!obj) return false;
bool initialised = false; bool initialised = false;
initialised |= DqnArray_Init(&obj->geometryArray, vertexInitCapacity); initialised |= DqnArray_Init(&obj->geometryArray, vertexInitCapacity, memAPI);
initialised |= DqnArray_Init(&obj->textureArray, vertexInitCapacity); initialised |= DqnArray_Init(&obj->textureArray, vertexInitCapacity, memAPI);
initialised |= DqnArray_Init(&obj->normalArray, vertexInitCapacity); initialised |= DqnArray_Init(&obj->normalArray, vertexInitCapacity, memAPI);
initialised |= DqnArray_Init(&obj->faces, faceInitCapacity); initialised |= DqnArray_Init(&obj->faces, faceInitCapacity, memAPI);
if (!initialised) if (!initialised)
{ {
@ -40,7 +140,8 @@ FILE_SCOPE bool WavefModelInit(DTRWavefModel *const obj, const i32 vertexInitCap
return initialised; return initialised;
} }
FILE_SCOPE inline DTRWavefModelFace WavefModelFaceInit(i32 capacity = 3) FILE_SCOPE inline DTRWavefModelFace
WavefModelFaceInit(i32 capacity = 3, DqnMemAPI memAPI = DqnMemAPI_DefaultUseCalloc())
{ {
DTRWavefModelFace result = {}; DTRWavefModelFace result = {};
DQN_ASSERT(DqnArray_Init(&result.vertexIndexArray, capacity)); DQN_ASSERT(DqnArray_Init(&result.vertexIndexArray, capacity));
@ -60,8 +161,8 @@ bool DTRAsset_WavefModelLoad(const PlatformAPI api, PlatformMemory *const memory
return false; // TODO(doyle): Logging return false; // TODO(doyle): Logging
// TODO(doyle): Make arrays use given memory not malloc // TODO(doyle): Make arrays use given memory not malloc
DqnTempMemStack tmpMemRegion = DqnMemStack_BeginTempRegion(&memory->transMemStack); DqnTempMemStack tmpMemRegion = DqnMemStack_BeginTempRegion(&memory->tempStack);
u8 *rawBytes = (u8 *)DqnMemStack_Push(&memory->transMemStack, file.size); u8 *rawBytes = (u8 *)DqnMemStack_Push(&memory->tempStack, file.size);
size_t bytesRead = api.FileRead(&file, rawBytes, file.size); size_t bytesRead = api.FileRead(&file, rawBytes, file.size);
size_t fileSize = file.size; size_t fileSize = file.size;
api.FileClose(&file); api.FileClose(&file);
@ -79,6 +180,10 @@ bool DTRAsset_WavefModelLoad(const PlatformAPI api, PlatformMemory *const memory
WavefVertexType_Normal, WavefVertexType_Normal,
}; };
DqnMemAPI memAPI = {};
memAPI.callback = AssetDqnArrayMemAPICallback;
memAPI.userContext = &memory->assetStack;
if (!WavefModelInit(obj)) if (!WavefModelInit(obj))
{ {
DqnMemStack_EndTempRegion(tmpMemRegion); DqnMemStack_EndTempRegion(tmpMemRegion);
@ -223,6 +328,9 @@ bool DTRAsset_WavefModelLoad(const PlatformAPI api, PlatformMemory *const memory
// so offset by -1 to make it zero-based indexes. // so offset by -1 to make it zero-based indexes.
i32 vertIndex = (i32)Dqn_StrToI64(numStartPtr, numLen) - 1; i32 vertIndex = (i32)Dqn_StrToI64(numStartPtr, numLen) - 1;
// TODO(doyle): Does not supprot relative vertexes yet
DQN_ASSERT(vertIndex >= 0);
if (type == WavefVertexType_Geometric) if (type == WavefVertexType_Geometric)
{ {
DQN_ASSERT(DqnArray_Push(&face.vertexIndexArray, vertIndex)); DQN_ASSERT(DqnArray_Push(&face.vertexIndexArray, vertIndex));
@ -288,7 +396,7 @@ bool DTRAsset_WavefModelLoad(const PlatformAPI api, PlatformMemory *const memory
DQN_ASSERT(!obj->groupName[obj->groupNameIndex]); DQN_ASSERT(!obj->groupName[obj->groupNameIndex]);
obj->groupName[obj->groupNameIndex++] = (char *)DqnMemStack_Push( obj->groupName[obj->groupNameIndex++] = (char *)DqnMemStack_Push(
&memory->permMemStack, (nameLen + 1) * sizeof(char)); &memory->mainStack, (nameLen + 1) * sizeof(char));
for (i32 i = 0; i < nameLen; i++) for (i32 i = 0; i < nameLen; i++)
obj->groupName[obj->groupNameIndex - 1][i] = namePtr[i]; obj->groupName[obj->groupNameIndex - 1][i] = namePtr[i];
@ -370,8 +478,8 @@ bool DTRAsset_FontToBitmapLoad(const PlatformAPI api, PlatformMemory *const memo
if (!api.FileOpen(path, &file, PlatformFilePermissionFlag_Read, PlatformFileAction_OpenOnly)) if (!api.FileOpen(path, &file, PlatformFilePermissionFlag_Read, PlatformFileAction_OpenOnly))
return false; // TODO(doyle): Logging return false; // TODO(doyle): Logging
DqnTempMemStack tmpMemRegion = DqnMemStack_BeginTempRegion(&memory->transMemStack); DqnTempMemStack tmpMemRegion = DqnMemStack_BeginTempRegion(&memory->tempStack);
u8 *fontBuf = (u8 *)DqnMemStack_Push(&memory->transMemStack, file.size); u8 *fontBuf = (u8 *)DqnMemStack_Push(&memory->tempStack, file.size);
size_t bytesRead = api.FileRead(&file, fontBuf, file.size); size_t bytesRead = api.FileRead(&file, fontBuf, file.size);
api.FileClose(&file); api.FileClose(&file);
if (bytesRead != file.size) if (bytesRead != file.size)
@ -393,7 +501,7 @@ bool DTRAsset_FontToBitmapLoad(const PlatformAPI api, PlatformMemory *const memo
// Pack font data to bitmap // Pack font data to bitmap
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
loadedFont.bitmap = (u8 *)DqnMemStack_Push( loadedFont.bitmap = (u8 *)DqnMemStack_Push(
&memory->permMemStack, &memory->mainStack,
(size_t)(loadedFont.bitmapDim.w * loadedFont.bitmapDim.h)); (size_t)(loadedFont.bitmapDim.w * loadedFont.bitmapDim.h));
stbtt_pack_context fontPackContext = {}; stbtt_pack_context fontPackContext = {};
@ -406,7 +514,7 @@ bool DTRAsset_FontToBitmapLoad(const PlatformAPI api, PlatformMemory *const memo
(i32)((codepointRange.max + 1) - codepointRange.min); (i32)((codepointRange.max + 1) - codepointRange.min);
loadedFont.atlas = (stbtt_packedchar *)DqnMemStack_Push( loadedFont.atlas = (stbtt_packedchar *)DqnMemStack_Push(
&memory->permMemStack, numCodepoints * sizeof(stbtt_packedchar)); &memory->mainStack, numCodepoints * sizeof(stbtt_packedchar));
stbtt_PackFontRange(&fontPackContext, fontBuf, 0, stbtt_PackFontRange(&fontPackContext, fontBuf, 0,
STBTT_POINT_SIZE(sizeInPt), (i32)codepointRange.min, STBTT_POINT_SIZE(sizeInPt), (i32)codepointRange.min,
numCodepoints, loadedFont.atlas); numCodepoints, loadedFont.atlas);
@ -456,13 +564,6 @@ bool DTRAsset_FontToBitmapLoad(const PlatformAPI api, PlatformMemory *const memo
// TODO(doyle): Not threadsafe // TODO(doyle): Not threadsafe
FILE_SCOPE DqnMemStack *globalSTBImageAllocator; FILE_SCOPE DqnMemStack *globalSTBImageAllocator;
FILE_SCOPE void MemcopyInternal(u8 *dest, u8 *src, size_t numBytes)
{
if (!dest || !src || numBytes == 0) return;
for (size_t i = 0; i < numBytes; i++)
dest[i] = src[i];
}
FILE_SCOPE void *STBImageReallocSized(void *ptr, size_t oldSize, size_t newSize) FILE_SCOPE void *STBImageReallocSized(void *ptr, size_t oldSize, size_t newSize)
{ {
// TODO(doyle): Implement when needed. There's no easy way using our stack // TODO(doyle): Implement when needed. There's no easy way using our stack
@ -506,18 +607,18 @@ FILE_SCOPE void *STBImageMalloc(size_t size)
// TODO(doyle): Uses malloc // TODO(doyle): Uses malloc
bool DTRAsset_BitmapLoad(const PlatformAPI api, DqnMemStack *const bitmapMemStack, bool DTRAsset_BitmapLoad(const PlatformAPI api, DqnMemStack *const bitmapMemStack,
DqnMemStack *const transMemStack, DTRBitmap *bitmap, DqnMemStack *const tempStack, DTRBitmap *bitmap,
const char *const path) const char *const path)
{ {
if (!bitmap || !bitmapMemStack || !transMemStack) return false; if (!bitmap || !bitmapMemStack || !tempStack) return false;
bool result = false; bool result = false;
PlatformFile file = {}; PlatformFile file = {};
if (!api.FileOpen(path, &file, PlatformFilePermissionFlag_Read, PlatformFileAction_OpenOnly)) if (!api.FileOpen(path, &file, PlatformFilePermissionFlag_Read, PlatformFileAction_OpenOnly))
return result; return result;
DqnTempMemStack tmpMemRegion = DqnMemStack_BeginTempRegion(transMemStack); DqnTempMemStack tmpMemRegion = DqnMemStack_BeginTempRegion(tempStack);
u8 *const rawData = (u8 *)DqnMemStack_Push (transMemStack, file.size); u8 *const rawData = (u8 *)DqnMemStack_Push (tempStack, file.size);
size_t bytesRead = api.FileRead (&file, rawData, file.size); size_t bytesRead = api.FileRead (&file, rawData, file.size);
if (bytesRead != file.size) goto cleanup; if (bytesRead != file.size) goto cleanup;

View File

@ -46,7 +46,7 @@ void DTRDebug_TestWavefFaceAndVertexParser(DTRWavefModel *const obj)
} }
} }
void DTRDebug_DumpZBuffer(DTRRenderBuffer *const renderBuffer, DqnMemStack *const transMemStack) void DTRDebug_DumpZBuffer(DTRRenderBuffer *const renderBuffer, DqnMemStack *const tempStack)
{ {
if (DTR_DEBUG) if (DTR_DEBUG)
{ {
@ -64,10 +64,10 @@ void DTRDebug_DumpZBuffer(DTRRenderBuffer *const renderBuffer, DqnMemStack *cons
} }
} }
DqnTempMemStack tmpMemRegion = DqnMemStack_BeginTempRegion(transMemStack); DqnTempMemStack tmpMemRegion = DqnMemStack_BeginTempRegion(tempStack);
size_t bufSize = DQN_MEGABYTE(16); size_t bufSize = DQN_MEGABYTE(16);
char *bufString = (char *)DqnMemStack_Push(transMemStack, bufSize); char *bufString = (char *)DqnMemStack_Push(tempStack, bufSize);
char *bufPtr = bufString; char *bufPtr = bufString;
for (i32 i = 0; i < renderBuffer->width * renderBuffer->height; i++) for (i32 i = 0; i < renderBuffer->width * renderBuffer->height; i++)
{ {
@ -149,6 +149,7 @@ FILE_SCOPE void PushMemStackText(const char *const name, const DqnMemStack *cons
i32 numBlocks = 0; i32 numBlocks = 0;
DqnMemStackBlock *blockPtr = stack->block; DqnMemStackBlock *blockPtr = stack->block;
size_t freeSizeOfCurrBlock = (blockPtr) ? blockPtr->size - blockPtr->used : 0;
while (blockPtr) while (blockPtr)
{ {
totalUsed += blockPtr->used; totalUsed += blockPtr->used;
@ -159,7 +160,7 @@ FILE_SCOPE void PushMemStackText(const char *const name, const DqnMemStack *cons
size_t totalUsedKb = totalUsed / 1024; size_t totalUsedKb = totalUsed / 1024;
size_t totalSizeKb = totalSize / 1024; size_t totalSizeKb = totalSize / 1024;
size_t totalWastedKb = totalWasted / 1024; size_t totalWastedKb = (totalSize - totalUsed - freeSizeOfCurrBlock) / 1024;
char str[128] = {}; char str[128] = {};
Dqn_sprintf(str, "%s: %d block(s): %_$lld/%_$lld: wasted: %_$lld", name, numBlocks, Dqn_sprintf(str, "%s: %d block(s): %_$lld/%_$lld: wasted: %_$lld", name, numBlocks,
@ -194,8 +195,9 @@ void DTRDebug_Update(DTRState *const state,
// memory // memory
{ {
PushMemStackText("PermBuffer", &memory->permMemStack); PushMemStackText("MainStack", &memory->mainStack);
PushMemStackText("TransBuffer", &memory->transMemStack); PushMemStackText("TempStack", &memory->tempStack);
PushMemStackText("AssetStack", &memory->assetStack);
} }
DTRDebug_PushText("Mouse: %d, %d", input->mouse.x, input->mouse.y); DTRDebug_PushText("Mouse: %d, %d", input->mouse.x, input->mouse.y);

View File

@ -128,8 +128,9 @@ typedef struct PlatformInput
typedef struct PlatformMemory typedef struct PlatformMemory
{ {
DqnMemStack permMemStack; DqnMemStack mainStack;
DqnMemStack transMemStack; DqnMemStack tempStack;
DqnMemStack assetStack;
bool isInit; bool isInit;
void *context; void *context;
} PlatformMemory; } PlatformMemory;

View File

@ -273,21 +273,21 @@ FILE_SCOPE void Win32HandleMenuMessages(HWND window, MSG msg,
case Win32Menu_FileFlushMemory: case Win32Menu_FileFlushMemory:
{ {
DqnMemStack permMemStack = globalPlatformMemory.permMemStack; DqnMemStack mainStack = globalPlatformMemory.mainStack;
DqnMemStack transMemStack = globalPlatformMemory.transMemStack; DqnMemStack tempStack = globalPlatformMemory.tempStack;
while (permMemStack.block->prevBlock) while (mainStack.block->prevBlock)
DqnMemStack_FreeLastBlock(&permMemStack); DqnMemStack_FreeLastBlock(&mainStack);
while (transMemStack.block->prevBlock) while (tempStack.block->prevBlock)
DqnMemStack_FreeLastBlock(&transMemStack); DqnMemStack_FreeLastBlock(&tempStack);
DqnMemStack_ClearCurrBlock(&transMemStack, true); DqnMemStack_ClearCurrBlock(&tempStack, true);
DqnMemStack_ClearCurrBlock(&permMemStack, true); DqnMemStack_ClearCurrBlock(&mainStack, true);
PlatformMemory empty = {}; PlatformMemory empty = {};
globalPlatformMemory = empty; globalPlatformMemory = empty;
globalPlatformMemory.permMemStack = permMemStack; globalPlatformMemory.mainStack = mainStack;
globalPlatformMemory.transMemStack = transMemStack; globalPlatformMemory.tempStack = tempStack;
} }
break; break;
@ -546,8 +546,10 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
// Platform Data Pre-amble // Platform Data Pre-amble
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
DQN_ASSERT(DqnMemStack_Init(&globalPlatformMemory.permMemStack, DQN_MEGABYTE(4), true, 4) && DQN_ASSERT(DqnMemStack_Init(&globalPlatformMemory.mainStack, DQN_MEGABYTE(4), true, 4) &&
DqnMemStack_Init(&globalPlatformMemory.transMemStack, DQN_MEGABYTE(4), true, 4)); DqnMemStack_Init(&globalPlatformMemory.tempStack, DQN_MEGABYTE(4), true, 4) &&
DqnMemStack_Init(&globalPlatformMemory.assetStack, DQN_MEGABYTE(4), true, 4)
);
PlatformAPI platformAPI = {}; PlatformAPI platformAPI = {};
platformAPI.FileOpen = Platform_FileOpen; platformAPI.FileOpen = Platform_FileOpen;

View File

@ -96,24 +96,18 @@ DQN_FILE_SCOPE void DqnMem_Free (void *memory);
// BeginTempRegion and EndTempRegion functions. Specifically freeing // BeginTempRegion and EndTempRegion functions. Specifically freeing
// individual items is typically not generalisable in this scheme. // individual items is typically not generalisable in this scheme.
typedef struct DqnMemStackBlock
{
u8 *memory;
size_t used;
size_t size;
DqnMemStackBlock *prevBlock;
} DqnMemStackBlock;
enum DqnMemStackFlag enum DqnMemStackFlag
{ {
DqnMemStackFlag_IsNotExpandable = (1 << 0), DqnMemStackFlag_IsNotExpandable = (1 << 0),
DqnMemStackFlag_IsFixedMemoryFromUser = (1 << 1), // NOTE(doyle): Required to indicate we CAN'T free this memory when free is called. DqnMemStackFlag_IsFixedMemoryFromUser = (1 << 1), // NOTE(doyle): Required to indicate we CAN'T free this memory when free is called.
}; };
////////////////////////////////////////////////////////////////////////////////
// Advanced API Structs
////////////////////////////////////////////////////////////////////////////////
typedef struct DqnMemStack typedef struct DqnMemStack
{ {
DqnMemStackBlock *block; struct DqnMemStackBlock *block;
u32 flags; u32 flags;
i32 tempStackCount; i32 tempStackCount;
@ -122,8 +116,8 @@ typedef struct DqnMemStack
typedef struct DqnTempMemStack typedef struct DqnTempMemStack
{ {
DqnMemStack *stack; DqnMemStack *stack;
DqnMemStackBlock *startingBlock; struct DqnMemStackBlock *startingBlock;
size_t used; size_t used;
} DqnTempMemStack; } DqnTempMemStack;
@ -132,12 +126,12 @@ DQN_FILE_SCOPE bool DqnMemStack_InitWithFixedMem (DqnMemStack *const stack, u8 *
DQN_FILE_SCOPE bool DqnMemStack_InitWithFixedSize(DqnMemStack *const stack, size_t size, const bool zeroClear, const u32 byteAlign = 4); // Single allocation from platform, no further allocations, returns NULL of allocate if out of space DQN_FILE_SCOPE bool DqnMemStack_InitWithFixedSize(DqnMemStack *const stack, size_t size, const bool zeroClear, const u32 byteAlign = 4); // Single allocation from platform, no further allocations, returns NULL of allocate if out of space
DQN_FILE_SCOPE bool DqnMemStack_Init (DqnMemStack *const stack, size_t size, const bool zeroClear, const u32 byteAlign = 4); // Allocates from platform dynamically as space runs out DQN_FILE_SCOPE bool DqnMemStack_Init (DqnMemStack *const stack, size_t size, const bool zeroClear, const u32 byteAlign = 4); // Allocates from platform dynamically as space runs out
DQN_FILE_SCOPE void *DqnMemStack_Push (DqnMemStack *const stack, size_t size); // Returns NULL if out of space and stack is using fixed memory/size, or platform allocation fails DQN_FILE_SCOPE void *DqnMemStack_Push (DqnMemStack *const stack, size_t size); // Returns NULL if out of space and stack is using fixed memory/size, or platform allocation fails.
DQN_FILE_SCOPE bool DqnMemStack_Pop (DqnMemStack *const stack, void *ptr, size_t size); // Frees the given ptr. It MUST be the last allocated item in the stack DQN_FILE_SCOPE bool DqnMemStack_Pop (DqnMemStack *const stack, void *ptr, size_t size); // Frees the given ptr. It MUST be the last allocated item in the stack.
DQN_FILE_SCOPE void DqnMemStack_Free (DqnMemStack *const stack); // Frees all blocks belonging to this stack DQN_FILE_SCOPE void DqnMemStack_Free (DqnMemStack *const stack); // Frees all blocks belonging to this stack.
DQN_FILE_SCOPE bool DqnMemStack_FreeStackBlock(DqnMemStack *const stack, DqnMemStackBlock *block); // Frees the specified block, returns false if block doesn't belong DQN_FILE_SCOPE bool DqnMemStack_FreeStackBlock(DqnMemStack *const stack, DqnMemStackBlock *block); // Frees the specified block, returns false if block doesn't belong, calls DqnMem_Free().
DQN_FILE_SCOPE bool DqnMemStack_FreeLastBlock (DqnMemStack *const stack); // Frees the last-most memory block. If last block, free that block, next allocate will attach a block. DQN_FILE_SCOPE bool DqnMemStack_FreeLastBlock (DqnMemStack *const stack); // Frees the last-most memory block. If last block, free that block, next allocate will attach a block.
DQN_FILE_SCOPE void DqnMemStack_ClearCurrBlock(DqnMemStack *const stack, const bool zeroClear); // Reset the current memory block usage to 0 DQN_FILE_SCOPE void DqnMemStack_ClearCurrBlock(DqnMemStack *const stack, const bool zeroClear); // Reset the current memory block usage to 0.
// TempMemStack is only required for the function. Once BeginTempRegion() is called, subsequent allocation calls can be made using the original stack. // TempMemStack is only required for the function. Once BeginTempRegion() is called, subsequent allocation calls can be made using the original stack.
// Upon EndTempRegion() the original stack will free any additional blocks it allocated during the temp region and revert to the original // Upon EndTempRegion() the original stack will free any additional blocks it allocated during the temp region and revert to the original
@ -147,7 +141,20 @@ DQN_FILE_SCOPE void DqnMemStack_ClearCurrBlock(DqnMemStack *const stack, const
DQN_FILE_SCOPE DqnTempMemStack DqnMemStack_BeginTempRegion(DqnMemStack *const stack); DQN_FILE_SCOPE DqnTempMemStack DqnMemStack_BeginTempRegion(DqnMemStack *const stack);
DQN_FILE_SCOPE void DqnMemStack_EndTempRegion (DqnTempMemStack tempstack); DQN_FILE_SCOPE void DqnMemStack_EndTempRegion (DqnTempMemStack tempstack);
////////////////////////////////////////////////////////////////////////////////
// (OPTIONAL) DqnMemStack Advanced API // (OPTIONAL) DqnMemStack Advanced API
// Blocks are freely modifiable if you want fine grained control. Size value and
// memory ptr should _NOT_ be modified directly, only indirectly through the
// regular API.
typedef struct DqnMemStackBlock
{
u8 *memory;
size_t size;
size_t used;
DqnMemStackBlock *prevBlock;
} DqnMemStackBlock;
// This is useful for forcing a new block to be used. AllocateCompatibleBlock // This is useful for forcing a new block to be used. AllocateCompatibleBlock
// will fail if the supplied stack has flags set such that the stack is not // will fail if the supplied stack has flags set such that the stack is not
// allowed to have new blocks. // allowed to have new blocks.