Add helper V4 functions, change allocate to push
This commit is contained in:
parent
25744855ee
commit
fceac54ecb
32
dqn.h
32
dqn.h
@ -20,6 +20,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdint.h> // For standard types
|
#include <stdint.h> // For standard types
|
||||||
|
#include <float.h>
|
||||||
#define LOCAL_PERSIST static
|
#define LOCAL_PERSIST static
|
||||||
#define FILE_SCOPE static
|
#define FILE_SCOPE static
|
||||||
|
|
||||||
@ -35,6 +36,8 @@ typedef int16_t i16;
|
|||||||
typedef double f64;
|
typedef double f64;
|
||||||
typedef float f32;
|
typedef float f32;
|
||||||
|
|
||||||
|
#define DQN_F32_MIN -FLT_MAX
|
||||||
|
|
||||||
#define DQN_TERABYTE(val) (DQN_GIGABYTE(val) * 1024LL)
|
#define DQN_TERABYTE(val) (DQN_GIGABYTE(val) * 1024LL)
|
||||||
#define DQN_GIGABYTE(val) (DQN_MEGABYTE(val) * 1024LL)
|
#define DQN_GIGABYTE(val) (DQN_MEGABYTE(val) * 1024LL)
|
||||||
#define DQN_MEGABYTE(val) (DQN_KILOBYTE(val) * 1024LL)
|
#define DQN_MEGABYTE(val) (DQN_KILOBYTE(val) * 1024LL)
|
||||||
@ -75,7 +78,7 @@ DQN_FILE_SCOPE void DqnMem_Free (void *memory);
|
|||||||
|
|
||||||
// When an allocation requires a larger amount of memory than available in the
|
// When an allocation requires a larger amount of memory than available in the
|
||||||
// block then the MemStack will allocate a new block of sufficient size for
|
// block then the MemStack will allocate a new block of sufficient size for
|
||||||
// you in DqnMemStack_Allocate(..). This _DOES_ mean that there will be wasted
|
// you in DqnMemStack_Push(..). This _DOES_ mean that there will be wasted
|
||||||
// space at the end of each block and is a tradeoff for memory locality against
|
// space at the end of each block and is a tradeoff for memory locality against
|
||||||
// optimal space usage.
|
// optimal space usage.
|
||||||
|
|
||||||
@ -88,7 +91,7 @@ DQN_FILE_SCOPE void DqnMem_Free (void *memory);
|
|||||||
// - InitWithFixedSize() allows you to to disable dynamic allocations and
|
// - InitWithFixedSize() allows you to to disable dynamic allocations and
|
||||||
// sub-allocate from the initial MemStack allocation size only.
|
// sub-allocate from the initial MemStack allocation size only.
|
||||||
|
|
||||||
// 2. Use DqnMemStack_Allocate(..) to allocate memory for use.
|
// 2. Use DqnMemStack_Push(..) to allocate memory for use.
|
||||||
// - "Freeing" memory is dealt by creating temporary MemStacks or using the
|
// - "Freeing" memory is dealt by creating temporary MemStacks or using the
|
||||||
// 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.
|
||||||
@ -129,7 +132,7 @@ 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_Allocate (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
|
||||||
@ -504,6 +507,8 @@ DQN_FILE_SCOPE inline bool operator==(DqnV2i a, DqnV2i b) { return DqnV
|
|||||||
typedef union DqnV3
|
typedef union DqnV3
|
||||||
{
|
{
|
||||||
struct { f32 x, y, z; };
|
struct { f32 x, y, z; };
|
||||||
|
DqnV2 xy;
|
||||||
|
|
||||||
struct { f32 r, g, b; };
|
struct { f32 r, g, b; };
|
||||||
f32 e[3];
|
f32 e[3];
|
||||||
} DqnV3;
|
} DqnV3;
|
||||||
@ -528,6 +533,8 @@ DQN_FILE_SCOPE f32 DqnV3_Dot (DqnV3 a, DqnV3 b);
|
|||||||
DQN_FILE_SCOPE bool DqnV3_Equals (DqnV3 a, DqnV3 b);
|
DQN_FILE_SCOPE bool DqnV3_Equals (DqnV3 a, DqnV3 b);
|
||||||
DQN_FILE_SCOPE DqnV3 DqnV3_Cross (DqnV3 a, DqnV3 b);
|
DQN_FILE_SCOPE DqnV3 DqnV3_Cross (DqnV3 a, DqnV3 b);
|
||||||
|
|
||||||
|
DQN_FILE_SCOPE DqnV3 DqnV3_Normalise(DqnV3 a);
|
||||||
|
|
||||||
DQN_FILE_SCOPE inline DqnV3 operator- (DqnV3 a, DqnV3 b) { return DqnV3_Sub (a, b); }
|
DQN_FILE_SCOPE inline DqnV3 operator- (DqnV3 a, DqnV3 b) { return DqnV3_Sub (a, b); }
|
||||||
DQN_FILE_SCOPE inline DqnV3 operator+ (DqnV3 a, DqnV3 b) { return DqnV3_Add (a, b); }
|
DQN_FILE_SCOPE inline DqnV3 operator+ (DqnV3 a, DqnV3 b) { return DqnV3_Add (a, b); }
|
||||||
DQN_FILE_SCOPE inline DqnV3 operator* (DqnV3 a, DqnV3 b) { return DqnV3_Hadamard(a, b); }
|
DQN_FILE_SCOPE inline DqnV3 operator* (DqnV3 a, DqnV3 b) { return DqnV3_Hadamard(a, b); }
|
||||||
@ -548,8 +555,12 @@ DQN_FILE_SCOPE DqnV3i DqnV3i_3f(f32 x, f32 y, f32 z);
|
|||||||
// Vec4
|
// Vec4
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
typedef union DqnV4 {
|
typedef union DqnV4 {
|
||||||
struct { f32 x, y, z, w; };
|
struct
|
||||||
|
{
|
||||||
|
f32 x, y, z, w;
|
||||||
|
};
|
||||||
DqnV3 xyz;
|
DqnV3 xyz;
|
||||||
|
DqnV2 xy;
|
||||||
|
|
||||||
struct { f32 r, g, b, a; };
|
struct { f32 r, g, b, a; };
|
||||||
DqnV3 rgb;
|
DqnV3 rgb;
|
||||||
@ -573,6 +584,7 @@ DQN_FILE_SCOPE bool DqnV4_Equals (DqnV4 a, DqnV4 b);
|
|||||||
|
|
||||||
DQN_FILE_SCOPE inline DqnV4 operator- (DqnV4 a, DqnV4 b) { return DqnV4_Sub (a, b); }
|
DQN_FILE_SCOPE inline DqnV4 operator- (DqnV4 a, DqnV4 b) { return DqnV4_Sub (a, b); }
|
||||||
DQN_FILE_SCOPE inline DqnV4 operator+ (DqnV4 a, DqnV4 b) { return DqnV4_Add (a, b); }
|
DQN_FILE_SCOPE inline DqnV4 operator+ (DqnV4 a, DqnV4 b) { return DqnV4_Add (a, b); }
|
||||||
|
DQN_FILE_SCOPE inline DqnV4 operator+ (DqnV4 a, f32 b) { return DqnV4_Add (a, DqnV4_1f(b)); }
|
||||||
DQN_FILE_SCOPE inline DqnV4 operator* (DqnV4 a, DqnV4 b) { return DqnV4_Hadamard(a, b); }
|
DQN_FILE_SCOPE inline DqnV4 operator* (DqnV4 a, DqnV4 b) { return DqnV4_Hadamard(a, b); }
|
||||||
DQN_FILE_SCOPE inline DqnV4 operator* (DqnV4 a, f32 b) { return DqnV4_Scalef (a, b); }
|
DQN_FILE_SCOPE inline DqnV4 operator* (DqnV4 a, f32 b) { return DqnV4_Scalef (a, b); }
|
||||||
DQN_FILE_SCOPE inline DqnV4 operator* (DqnV4 a, i32 b) { return DqnV4_Scalei (a, b); }
|
DQN_FILE_SCOPE inline DqnV4 operator* (DqnV4 a, i32 b) { return DqnV4_Scalei (a, b); }
|
||||||
@ -754,7 +766,6 @@ DQN_FILE_SCOPE i32 DqnRnd_PCGRange(DqnRandPCGState *pcg, i32 min, i32 max);
|
|||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
|
||||||
|
|
||||||
#define DQN_WIN32_ERROR_BOX(text, title) MessageBoxA(NULL, text, title, MB_OK);
|
#define DQN_WIN32_ERROR_BOX(text, title) MessageBoxA(NULL, text, title, MB_OK);
|
||||||
// Out is a pointer to the buffer to receive the characters.
|
// Out is a pointer to the buffer to receive the characters.
|
||||||
// outLen is the length/capacity of the out buffer
|
// outLen is the length/capacity of the out buffer
|
||||||
@ -1444,7 +1455,7 @@ DQN_FILE_SCOPE bool DqnMemStack_InitWithFixedSize(DqnMemStack *const stack,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
DQN_FILE_SCOPE void *DqnMemStack_Allocate(DqnMemStack *const stack, size_t size)
|
DQN_FILE_SCOPE void *DqnMemStack_Push(DqnMemStack *const stack, size_t size)
|
||||||
{
|
{
|
||||||
if (!stack || size == 0) return NULL;
|
if (!stack || size == 0) return NULL;
|
||||||
|
|
||||||
@ -2121,6 +2132,15 @@ DQN_FILE_SCOPE DqnV3 DqnV3_Cross(DqnV3 a, DqnV3 b)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DQN_FILE_SCOPE DqnV3 DqnV3_Normalise(DqnV3 a)
|
||||||
|
{
|
||||||
|
f32 length = DqnMath_Sqrtf(DQN_SQUARED(a.x) + DQN_SQUARED(a.y) + DQN_SQUARED(a.z));
|
||||||
|
f32 invLength = 1 / length;
|
||||||
|
DqnV3 result = a * invLength;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
DQN_FILE_SCOPE DqnV3i DqnV3i_3i(i32 x, i32 y, i32 z)
|
DQN_FILE_SCOPE DqnV3i DqnV3i_3i(i32 x, i32 y, i32 z)
|
||||||
{
|
{
|
||||||
DqnV3i result = {x, y, z};
|
DqnV3i result = {x, y, z};
|
||||||
|
@ -1052,7 +1052,7 @@ void MemStackTest()
|
|||||||
|
|
||||||
// Alocate A
|
// Alocate A
|
||||||
size_t sizeA = (size_t)(allocSize * 0.5f);
|
size_t sizeA = (size_t)(allocSize * 0.5f);
|
||||||
void *resultA = DqnMemStack_Allocate(&stack, sizeA);
|
void *resultA = DqnMemStack_Push(&stack, sizeA);
|
||||||
u64 resultAddrA = *((u64 *)resultA);
|
u64 resultAddrA = *((u64 *)resultA);
|
||||||
DQN_ASSERT(resultAddrA % ALIGNMENT == 0);
|
DQN_ASSERT(resultAddrA % ALIGNMENT == 0);
|
||||||
DQN_ASSERT(stack.block && stack.block->memory);
|
DQN_ASSERT(stack.block && stack.block->memory);
|
||||||
@ -1068,7 +1068,7 @@ void MemStackTest()
|
|||||||
DqnMemStackBlock *blockA = stack.block;
|
DqnMemStackBlock *blockA = stack.block;
|
||||||
// Alocate B
|
// Alocate B
|
||||||
size_t sizeB = (size_t)(allocSize * 2.0f);
|
size_t sizeB = (size_t)(allocSize * 2.0f);
|
||||||
void *resultB = DqnMemStack_Allocate(&stack, sizeB);
|
void *resultB = DqnMemStack_Push(&stack, sizeB);
|
||||||
u64 resultAddrB = *((u64 *)resultB);
|
u64 resultAddrB = *((u64 *)resultB);
|
||||||
DQN_ASSERT(resultAddrB % ALIGNMENT == 0);
|
DQN_ASSERT(resultAddrB % ALIGNMENT == 0);
|
||||||
DQN_ASSERT(stack.block && stack.block->memory);
|
DQN_ASSERT(stack.block && stack.block->memory);
|
||||||
@ -1094,7 +1094,7 @@ void MemStackTest()
|
|||||||
// Check temp regions work
|
// Check temp regions work
|
||||||
DqnTempMemStack tempBuffer = DqnMemStack_BeginTempRegion(&stack);
|
DqnTempMemStack tempBuffer = DqnMemStack_BeginTempRegion(&stack);
|
||||||
size_t sizeC = 1024 + 1;
|
size_t sizeC = 1024 + 1;
|
||||||
void *resultC = DqnMemStack_Allocate(tempBuffer.stack, sizeC);
|
void *resultC = DqnMemStack_Push(tempBuffer.stack, sizeC);
|
||||||
u64 resultAddrC = *((u64 *)resultC);
|
u64 resultAddrC = *((u64 *)resultC);
|
||||||
DQN_ASSERT(resultAddrC % ALIGNMENT == 0);
|
DQN_ASSERT(resultAddrC % ALIGNMENT == 0);
|
||||||
DQN_ASSERT(stack.block != blockB && stack.block != blockA);
|
DQN_ASSERT(stack.block != blockB && stack.block != blockA);
|
||||||
@ -1166,7 +1166,7 @@ void MemStackTest()
|
|||||||
DQN_ASSERT(stack.byteAlign == ALIGNMENT);
|
DQN_ASSERT(stack.byteAlign == ALIGNMENT);
|
||||||
|
|
||||||
// Allocation larger than stack mem size should fail
|
// Allocation larger than stack mem size should fail
|
||||||
DQN_ASSERT(!DqnMemStack_Allocate(&stack, DQN_ARRAY_COUNT(memory) * 2));
|
DQN_ASSERT(!DqnMemStack_Push(&stack, DQN_ARRAY_COUNT(memory) * 2));
|
||||||
|
|
||||||
// Check free does nothing
|
// Check free does nothing
|
||||||
DqnMemStack_Free(&stack);
|
DqnMemStack_Free(&stack);
|
||||||
@ -1190,11 +1190,11 @@ void MemStackTest()
|
|||||||
DQN_ASSERT(stack.block->used == 0);
|
DQN_ASSERT(stack.block->used == 0);
|
||||||
DQN_ASSERT(stack.byteAlign == ALIGNMENT);
|
DQN_ASSERT(stack.byteAlign == ALIGNMENT);
|
||||||
|
|
||||||
void *result = DqnMemStack_Allocate(&stack, (size_t)(0.5f * allocSize));
|
void *result = DqnMemStack_Push(&stack, (size_t)(0.5f * allocSize));
|
||||||
DQN_ASSERT(result);
|
DQN_ASSERT(result);
|
||||||
|
|
||||||
// Allocating more should fail
|
// Allocating more should fail
|
||||||
DQN_ASSERT(!DqnMemStack_Allocate(&stack, allocSize));
|
DQN_ASSERT(!DqnMemStack_Push(&stack, allocSize));
|
||||||
|
|
||||||
// Freeing should work
|
// Freeing should work
|
||||||
DqnMemStack_Free(&stack);
|
DqnMemStack_Free(&stack);
|
||||||
@ -1212,7 +1212,7 @@ void MemStackTest()
|
|||||||
u8 *first = NULL;
|
u8 *first = NULL;
|
||||||
{
|
{
|
||||||
u32 allocate40Bytes = 40;
|
u32 allocate40Bytes = 40;
|
||||||
u8 *data = (u8 *)DqnMemStack_Allocate(&stack, allocate40Bytes);
|
u8 *data = (u8 *)DqnMemStack_Push(&stack, allocate40Bytes);
|
||||||
|
|
||||||
// Test that the allocation got aligned to 16 byte boundary
|
// Test that the allocation got aligned to 16 byte boundary
|
||||||
DQN_ASSERT(data);
|
DQN_ASSERT(data);
|
||||||
@ -1232,7 +1232,7 @@ void MemStackTest()
|
|||||||
DQN_ASSERT(stack.block->size == firstBlockSize);
|
DQN_ASSERT(stack.block->size == firstBlockSize);
|
||||||
|
|
||||||
// Reallocate the data
|
// Reallocate the data
|
||||||
data = (u8 *)DqnMemStack_Allocate(&stack, firstBlockSize);
|
data = (u8 *)DqnMemStack_Push(&stack, firstBlockSize);
|
||||||
DQN_ASSERT(stack.block->size == firstBlockSize);
|
DQN_ASSERT(stack.block->size == firstBlockSize);
|
||||||
DQN_ASSERT((size_t)data % ALIGNMENT == 0);
|
DQN_ASSERT((size_t)data % ALIGNMENT == 0);
|
||||||
|
|
||||||
@ -1253,7 +1253,7 @@ void MemStackTest()
|
|||||||
DQN_ASSERT(stack.block->size == firstBlockSize);
|
DQN_ASSERT(stack.block->size == firstBlockSize);
|
||||||
|
|
||||||
// Write out data to current block
|
// Write out data to current block
|
||||||
data = (u8 *)DqnMemStack_Allocate(&stack, firstBlockSize);
|
data = (u8 *)DqnMemStack_Push(&stack, firstBlockSize);
|
||||||
for (u32 i = 0; i < firstBlockSize; i++)
|
for (u32 i = 0; i < firstBlockSize; i++)
|
||||||
data[i] = 'c';
|
data[i] = 'c';
|
||||||
|
|
||||||
@ -1262,19 +1262,19 @@ void MemStackTest()
|
|||||||
|
|
||||||
// Force it to allocate three new blocks and write out data to each
|
// Force it to allocate three new blocks and write out data to each
|
||||||
size_t secondBlockSize = DQN_KILOBYTE(2);
|
size_t secondBlockSize = DQN_KILOBYTE(2);
|
||||||
u8 *second = (u8 *)DqnMemStack_Allocate(&stack, secondBlockSize);
|
u8 *second = (u8 *)DqnMemStack_Push(&stack, secondBlockSize);
|
||||||
DqnMemStackBlock *secondBlock = stack.block;
|
DqnMemStackBlock *secondBlock = stack.block;
|
||||||
for (u32 i = 0; i < secondBlockSize; i++)
|
for (u32 i = 0; i < secondBlockSize; i++)
|
||||||
second[i] = 'd';
|
second[i] = 'd';
|
||||||
|
|
||||||
size_t thirdBlockSize = DQN_KILOBYTE(3);
|
size_t thirdBlockSize = DQN_KILOBYTE(3);
|
||||||
u8 *third = (u8 *)DqnMemStack_Allocate(&stack, thirdBlockSize);
|
u8 *third = (u8 *)DqnMemStack_Push(&stack, thirdBlockSize);
|
||||||
DqnMemStackBlock *thirdBlock = stack.block;
|
DqnMemStackBlock *thirdBlock = stack.block;
|
||||||
for (u32 i = 0; i < thirdBlockSize; i++)
|
for (u32 i = 0; i < thirdBlockSize; i++)
|
||||||
third[i] = 'e';
|
third[i] = 'e';
|
||||||
|
|
||||||
size_t fourthBlockSize = DQN_KILOBYTE(4);
|
size_t fourthBlockSize = DQN_KILOBYTE(4);
|
||||||
u8 *fourth = (u8 *)DqnMemStack_Allocate(&stack, fourthBlockSize);
|
u8 *fourth = (u8 *)DqnMemStack_Push(&stack, fourthBlockSize);
|
||||||
DqnMemStackBlock *fourthBlock = stack.block;
|
DqnMemStackBlock *fourthBlock = stack.block;
|
||||||
for (u32 i = 0; i < fourthBlockSize; i++)
|
for (u32 i = 0; i < fourthBlockSize; i++)
|
||||||
fourth[i] = 'f';
|
fourth[i] = 'f';
|
||||||
@ -1391,7 +1391,7 @@ void MemStackTest()
|
|||||||
DqnMemStack_Init(&stack, DQN_KILOBYTE(1), true);
|
DqnMemStack_Init(&stack, DQN_KILOBYTE(1), true);
|
||||||
|
|
||||||
size_t allocSize = 512;
|
size_t allocSize = 512;
|
||||||
void *alloc = DqnMemStack_Allocate(&stack, allocSize);
|
void *alloc = DqnMemStack_Push(&stack, allocSize);
|
||||||
DQN_ASSERT(stack.block->used == allocSize);
|
DQN_ASSERT(stack.block->used == allocSize);
|
||||||
|
|
||||||
DQN_ASSERT(DqnMemStack_Pop(&stack, alloc, allocSize));
|
DQN_ASSERT(DqnMemStack_Pop(&stack, alloc, allocSize));
|
||||||
|
Loading…
Reference in New Issue
Block a user