Add asset array memory api stubs
This commit is contained in:
parent
f89b3ff706
commit
96ac39724d
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
39
src/dqn.h
39
src/dqn.h
@ -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;
|
||||||
@ -123,7 +117,7 @@ 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.
|
||||||
|
Loading…
Reference in New Issue
Block a user