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
					
				
							
								
								
									
										111
									
								
								dqn.h
									
									
									
									
									
								
							
							
						
						
									
										111
									
								
								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; } | ||||
| @ -588,7 +591,7 @@ typedef struct DqnMemBuffer | ||||
| 
 | ||||
| 	u32 flags; | ||||
| 	i32 tempBufferCount; | ||||
| 	size_t alignment; | ||||
| 	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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user