Add comments, make alignment function to macro
Alignment function becomes macro so that we can pass around alignment as a u32 instead of size_t.
This commit is contained in:
parent
fef763aaff
commit
2203e9b4f2
115
dqn.h
115
dqn.h
@ -50,6 +50,9 @@ typedef float f32;
|
||||
#define DQN_MEGABYTE(val) (DQN_KILOBYTE(val) * 1024LL)
|
||||
#define DQN_KILOBYTE(val) ((val) * 1024LL)
|
||||
|
||||
#define DQN_ALIGN_POW_N(val, align) ((((size_t)val) + ((size_t)align-1)) & (~(size_t)(align-1)))
|
||||
#define DQN_ALIGN_POW_4(val) DQN_ALIGN_POW_N(val, 4)
|
||||
|
||||
#define DQN_INVALID_CODE_PATH 0
|
||||
#define DQN_ARRAY_COUNT(array) (sizeof(array) / sizeof(array[0]))
|
||||
#define DQN_ASSERT(expr) if (!(expr)) { (*((i32 *)0)) = 0; }
|
||||
@ -586,9 +589,9 @@ typedef struct DqnMemBuffer
|
||||
{
|
||||
DqnMemBufferBlock *block;
|
||||
|
||||
u32 flags;
|
||||
i32 tempBufferCount;
|
||||
size_t alignment;
|
||||
u32 flags;
|
||||
i32 tempBufferCount;
|
||||
u32 byteAlign;
|
||||
} DqnMemBuffer;
|
||||
|
||||
typedef struct DqnTempBuffer
|
||||
@ -599,18 +602,21 @@ typedef struct DqnTempBuffer
|
||||
|
||||
} DqnTempBuffer;
|
||||
|
||||
// NOTE: InitWithFixedMem() is for giving the MemBuffer a pre-allocated block AND the buffer WILL NOT allocate new blocks.
|
||||
// Memory from user given memory is required for MemBufferBlock metadata which is equal to sizeof(DqnMemBufferBlock)
|
||||
// InitWithFixedSize() will incur one allocation from the platform and WILL NOT allocate any more blocks after that
|
||||
DQN_FILE_SCOPE bool DqnMemBuffer_InitWithFixedMem (DqnMemBuffer *const buffer, u8* mem, size_t memSize, const size_t alignment = 4);
|
||||
DQN_FILE_SCOPE bool DqnMemBuffer_InitWithFixedSize(DqnMemBuffer *const buffer, size_t size, const size_t alignment = 4);
|
||||
DQN_FILE_SCOPE bool DqnMemBuffer_Init (DqnMemBuffer *const buffer, size_t size, const size_t alignment = 4);
|
||||
DQN_FILE_SCOPE bool DqnMemBuffer_InitWithFixedMem (DqnMemBuffer *const buffer, u8 *const mem, const size_t memSize, const u32 byteAlign = 4); // Use preallocated memory, no further allocations, returns NULL on allocate if out of space
|
||||
DQN_FILE_SCOPE bool DqnMemBuffer_InitWithFixedSize(DqnMemBuffer *const buffer, size_t size, const bool clearToZero, const u32 byteAlign = 4); // Single allocation from platform, no further allocations, returns NULL of allocate if out of space
|
||||
DQN_FILE_SCOPE bool DqnMemBuffer_Init (DqnMemBuffer *const buffer, size_t size, const bool clearToZero, const u32 byteAlign = 4); // Allocates from platform dynamically as space runs out
|
||||
|
||||
DQN_FILE_SCOPE void *DqnMemBuffer_Allocate (DqnMemBuffer *const buffer, size_t size);
|
||||
DQN_FILE_SCOPE void DqnMemBuffer_FreeLastBuffer(DqnMemBuffer *const buffer);
|
||||
DQN_FILE_SCOPE void DqnMemBuffer_Free (DqnMemBuffer *const buffer);
|
||||
DQN_FILE_SCOPE void DqnMemBuffer_ClearCurrBlock(DqnMemBuffer *const buffer, const bool clearToZero);
|
||||
DQN_FILE_SCOPE void *DqnMemBuffer_Allocate (DqnMemBuffer *const buffer, size_t size); // Returns NULL if out of space, or platform allocation fails, or buffer is using fixed memory/size
|
||||
DQN_FILE_SCOPE void DqnMemBuffer_FreeLastBuffer(DqnMemBuffer *const buffer); // Frees the last-most block to the buffer, if it's the only block, the buffer will free that block then, next allocate with attach a block.
|
||||
DQN_FILE_SCOPE void DqnMemBuffer_Free (DqnMemBuffer *const buffer); // Frees all blocks belonging to this buffer
|
||||
DQN_FILE_SCOPE void DqnMemBuffer_ClearCurrBlock(DqnMemBuffer *const buffer, const bool clearToZero); // Reset the current blocks usage ptr to 0
|
||||
|
||||
|
||||
// TempBuffer is only required for the function. Once BeginTempRegion() is called, subsequent allocation calls can be made using the original buffer.
|
||||
// Upon EndTempRegion() the original buffer will free any additional blocks it allocated during the temp region and revert to the original
|
||||
// state before BeginTempRegion() was called.
|
||||
// WARNING: Any calls to Free/Clear functions in a TempRegion will invalidate and trash the buffer structure.
|
||||
// TODO(doyle): Look into a way of disallowing calls to free/clear in temp regions
|
||||
DQN_FILE_SCOPE DqnTempBuffer DqnMemBuffer_BeginTempRegion(DqnMemBuffer *const buffer);
|
||||
DQN_FILE_SCOPE void DqnMemBuffer_EndTempRegion (DqnTempBuffer tempBuffer);
|
||||
|
||||
@ -2785,16 +2791,10 @@ DQN_FILE_SCOPE i32 DqnRnd_PCGRange(DqnRandPCGState *pcg, i32 min, i32 max)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// DqnMemBuffer Header
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
FILE_SCOPE size_t Dqn_SizeAlignmentInternal(size_t alignment, size_t size)
|
||||
{
|
||||
size_t result = ((size + (alignment-1)) & (size_t)(~(alignment-1)));
|
||||
return result;
|
||||
}
|
||||
|
||||
FILE_SCOPE DqnMemBufferBlock *
|
||||
DqnMemBuffer_AllocBlockInternal(size_t alignment, size_t size)
|
||||
DqnMemBuffer_AllocBlockInternal(u32 byteAlign, size_t size)
|
||||
{
|
||||
size_t alignedSize = Dqn_SizeAlignmentInternal(alignment, size);
|
||||
size_t alignedSize = DQN_ALIGN_POW_N(size, byteAlign);
|
||||
size_t totalSize = alignedSize + sizeof(DqnMemBufferBlock);
|
||||
|
||||
DqnMemBufferBlock *result = (DqnMemBufferBlock *)Dqn_MemAllocInternal(totalSize, true);
|
||||
@ -2806,38 +2806,10 @@ DqnMemBuffer_AllocBlockInternal(size_t alignment, size_t size)
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_FILE_SCOPE bool DqnMemBuffer_Init(DqnMemBuffer *const buffer, size_t size,
|
||||
const size_t alignment)
|
||||
{
|
||||
if (!buffer || size <= 0) return false;
|
||||
DQN_ASSERT(!buffer->block);
|
||||
|
||||
buffer->block = DqnMemBuffer_AllocBlockInternal(alignment, size);
|
||||
if (!buffer->block) return false;
|
||||
|
||||
buffer->tempBufferCount = 0;
|
||||
buffer->alignment = alignment;
|
||||
buffer->flags = DqnMemBufferFlag_IsExpandable;
|
||||
return true;
|
||||
}
|
||||
|
||||
DQN_FILE_SCOPE bool DqnMemBuffer_InitWithFixedSize(DqnMemBuffer *const buffer,
|
||||
size_t size,
|
||||
const size_t alignment)
|
||||
{
|
||||
bool result = DqnMemBuffer_Init(buffer, size, alignment);
|
||||
if (result)
|
||||
{
|
||||
buffer->flags = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
DQN_FILE_SCOPE bool DqnMemBuffer_InitWithFixedMem(DqnMemBuffer *const buffer,
|
||||
u8 *mem, size_t memSize,
|
||||
const size_t alignment)
|
||||
u8 *const mem,
|
||||
const size_t memSize,
|
||||
const u32 byteAlign)
|
||||
{
|
||||
if (!buffer || !mem) return false;
|
||||
DQN_ASSERT(!buffer->block);
|
||||
@ -2854,15 +2826,46 @@ DQN_FILE_SCOPE bool DqnMemBuffer_InitWithFixedMem(DqnMemBuffer *const buffer,
|
||||
|
||||
const u32 DEFAULT_ALIGNMENT = 4;
|
||||
buffer->tempBufferCount = 0;
|
||||
buffer->alignment = (alignment == 0) ? DEFAULT_ALIGNMENT : alignment;
|
||||
buffer->byteAlign = (byteAlign == 0) ? DEFAULT_ALIGNMENT : byteAlign;
|
||||
return true;
|
||||
}
|
||||
|
||||
DQN_FILE_SCOPE bool DqnMemBuffer_Init(DqnMemBuffer *const buffer, size_t size,
|
||||
const bool clearToZero,
|
||||
const u32 byteAlign)
|
||||
{
|
||||
if (!buffer || size <= 0) return false;
|
||||
DQN_ASSERT(!buffer->block);
|
||||
|
||||
buffer->block = DqnMemBuffer_AllocBlockInternal(byteAlign, size);
|
||||
if (!buffer->block) return false;
|
||||
|
||||
buffer->tempBufferCount = 0;
|
||||
buffer->byteAlign = byteAlign;
|
||||
buffer->flags = DqnMemBufferFlag_IsExpandable;
|
||||
return true;
|
||||
}
|
||||
|
||||
DQN_FILE_SCOPE bool DqnMemBuffer_InitWithFixedSize(DqnMemBuffer *const buffer,
|
||||
size_t size,
|
||||
const bool clearToZero,
|
||||
const u32 byteAlign)
|
||||
{
|
||||
bool result = DqnMemBuffer_Init(buffer, size, byteAlign);
|
||||
if (result)
|
||||
{
|
||||
buffer->flags = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
DQN_FILE_SCOPE void *DqnMemBuffer_Allocate(DqnMemBuffer *const buffer, size_t size)
|
||||
{
|
||||
if (!buffer || size == 0) return NULL;
|
||||
|
||||
size_t alignedSize = Dqn_SizeAlignmentInternal(buffer->alignment, size);
|
||||
size_t alignedSize = DQN_ALIGN_POW_N(size, buffer->byteAlign);
|
||||
if (!buffer->block ||
|
||||
(buffer->block->used + alignedSize) > buffer->block->size)
|
||||
{
|
||||
@ -2873,7 +2876,7 @@ DQN_FILE_SCOPE void *DqnMemBuffer_Allocate(DqnMemBuffer *const buffer, size_t si
|
||||
{
|
||||
size_t newBlockSize = DQN_MAX(alignedSize, buffer->block->size);
|
||||
DqnMemBufferBlock *newBlock = DqnMemBuffer_AllocBlockInternal(
|
||||
buffer->alignment, newBlockSize);
|
||||
buffer->byteAlign, newBlockSize);
|
||||
if (!newBlock) return NULL;
|
||||
|
||||
newBlock->prevBlock = buffer->block;
|
||||
@ -2886,7 +2889,7 @@ DQN_FILE_SCOPE void *DqnMemBuffer_Allocate(DqnMemBuffer *const buffer, size_t si
|
||||
}
|
||||
|
||||
u8 *currPointer = buffer->block->memory + buffer->block->used;
|
||||
u8 *alignedResult = (u8 *)Dqn_SizeAlignmentInternal(buffer->alignment, (size_t)currPointer);
|
||||
u8 *alignedResult = (u8 *)DQN_ALIGN_POW_N(currPointer, buffer->byteAlign);
|
||||
size_t alignmentOffset = (size_t)(alignedResult - currPointer);
|
||||
|
||||
void *result = alignedResult;
|
||||
|
@ -904,7 +904,7 @@ void MemBufferTest()
|
||||
DQN_ASSERT(buffer.block && buffer.block->memory);
|
||||
DQN_ASSERT(buffer.block->size == allocSize);
|
||||
DQN_ASSERT(buffer.block->used == 0);
|
||||
DQN_ASSERT(buffer.alignment == ALIGNMENT);
|
||||
DQN_ASSERT(buffer.byteAlign == ALIGNMENT);
|
||||
|
||||
// Alocate A
|
||||
size_t sizeA = (size_t)(allocSize * 0.5f);
|
||||
@ -915,7 +915,7 @@ void MemBufferTest()
|
||||
DQN_ASSERT(buffer.block->size == allocSize);
|
||||
DQN_ASSERT(buffer.block->used >= sizeA + 0 &&
|
||||
buffer.block->used <= sizeA + 3);
|
||||
DQN_ASSERT(buffer.alignment == ALIGNMENT);
|
||||
DQN_ASSERT(buffer.byteAlign == ALIGNMENT);
|
||||
DQN_ASSERT(resultA);
|
||||
u8 *ptrA = (u8 *)resultA;
|
||||
for (u32 i = 0; i < sizeA; i++)
|
||||
@ -945,7 +945,7 @@ void MemBufferTest()
|
||||
// Check that a new block was created since there wasn't enough space
|
||||
DQN_ASSERT(buffer.block->prevBlock == blockA);
|
||||
DQN_ASSERT(buffer.block != blockA);
|
||||
DQN_ASSERT(buffer.alignment == ALIGNMENT);
|
||||
DQN_ASSERT(buffer.byteAlign == ALIGNMENT);
|
||||
DQN_ASSERT(blockA->used == sizeA);
|
||||
DqnMemBufferBlock *blockB = buffer.block;
|
||||
|
||||
@ -959,7 +959,7 @@ void MemBufferTest()
|
||||
DQN_ASSERT(buffer.block->used >= sizeC + 0 &&
|
||||
buffer.block->used <= sizeC + 3);
|
||||
DQN_ASSERT(buffer.tempBufferCount == 1);
|
||||
DQN_ASSERT(buffer.alignment == ALIGNMENT);
|
||||
DQN_ASSERT(buffer.byteAlign == ALIGNMENT);
|
||||
|
||||
// NOTE: Allocation should be aligned to 4 byte boundary
|
||||
DQN_ASSERT(tempBuffer.buffer->block->size == 2048);
|
||||
@ -970,7 +970,7 @@ void MemBufferTest()
|
||||
// Check that a new block was created since there wasn't enough space
|
||||
DQN_ASSERT(buffer.block->prevBlock == blockB);
|
||||
DQN_ASSERT(buffer.block != blockB);
|
||||
DQN_ASSERT(buffer.alignment == ALIGNMENT);
|
||||
DQN_ASSERT(buffer.byteAlign == ALIGNMENT);
|
||||
|
||||
for (u32 i = 0; i < sizeA; i++)
|
||||
DQN_ASSERT(ptrA[i] == 1);
|
||||
@ -991,7 +991,7 @@ void MemBufferTest()
|
||||
DQN_ASSERT(buffer.block->prevBlock == blockA);
|
||||
DQN_ASSERT(buffer.block != blockA);
|
||||
DQN_ASSERT(blockA->used == sizeA);
|
||||
DQN_ASSERT(buffer.alignment == ALIGNMENT);
|
||||
DQN_ASSERT(buffer.byteAlign == ALIGNMENT);
|
||||
|
||||
// Release the last linked buffer from the push buffer
|
||||
DqnMemBuffer_FreeLastBuffer(&buffer);
|
||||
@ -1001,12 +1001,12 @@ void MemBufferTest()
|
||||
DQN_ASSERT(buffer.block->memory);
|
||||
DQN_ASSERT(buffer.block->size == allocSize);
|
||||
DQN_ASSERT(buffer.block->used == sizeA);
|
||||
DQN_ASSERT(buffer.alignment == ALIGNMENT);
|
||||
DQN_ASSERT(buffer.byteAlign == ALIGNMENT);
|
||||
|
||||
// Free once more to release buffer A memory
|
||||
DqnMemBuffer_FreeLastBuffer(&buffer);
|
||||
DQN_ASSERT(!buffer.block);
|
||||
DQN_ASSERT(buffer.alignment == ALIGNMENT);
|
||||
DQN_ASSERT(buffer.byteAlign == ALIGNMENT);
|
||||
DQN_ASSERT(buffer.tempBufferCount == 0);
|
||||
}
|
||||
|
||||
@ -1021,7 +1021,7 @@ void MemBufferTest()
|
||||
DQN_ASSERT(buffer.block->size ==
|
||||
DQN_ARRAY_COUNT(memory) - sizeof(DqnMemBufferBlock));
|
||||
DQN_ASSERT(buffer.block->used == 0);
|
||||
DQN_ASSERT(buffer.alignment == ALIGNMENT);
|
||||
DQN_ASSERT(buffer.byteAlign == ALIGNMENT);
|
||||
|
||||
// Allocation larger than stack mem size should fail
|
||||
DQN_ASSERT(!DqnMemBuffer_Allocate(&buffer, DQN_ARRAY_COUNT(memory) * 2));
|
||||
@ -1033,7 +1033,7 @@ void MemBufferTest()
|
||||
DQN_ASSERT(buffer.block->size ==
|
||||
DQN_ARRAY_COUNT(memory) - sizeof(DqnMemBufferBlock));
|
||||
DQN_ASSERT(buffer.block->used == 0);
|
||||
DQN_ASSERT(buffer.alignment == ALIGNMENT);
|
||||
DQN_ASSERT(buffer.byteAlign == ALIGNMENT);
|
||||
}
|
||||
|
||||
// Test buffer with fixed size, allocates once from platform but does not
|
||||
@ -1046,7 +1046,7 @@ void MemBufferTest()
|
||||
DQN_ASSERT(buffer.block && buffer.block->memory);
|
||||
DQN_ASSERT(buffer.block->size == allocSize);
|
||||
DQN_ASSERT(buffer.block->used == 0);
|
||||
DQN_ASSERT(buffer.alignment == ALIGNMENT);
|
||||
DQN_ASSERT(buffer.byteAlign == ALIGNMENT);
|
||||
|
||||
void *result = DqnMemBuffer_Allocate(&buffer, (size_t)(0.5f * allocSize));
|
||||
DQN_ASSERT(result);
|
||||
|
Loading…
Reference in New Issue
Block a user