From fceac54ecb8e7f3cb1d317c2f74dd208d3a8bd05 Mon Sep 17 00:00:00 2001 From: Doyle Thai Date: Fri, 26 May 2017 01:10:32 +1000 Subject: [PATCH] Add helper V4 functions, change allocate to push --- dqn.h | 64 +++++++++++++++++++++++++++++++---------------- dqn_unit_test.cpp | 26 +++++++++---------- 2 files changed, 55 insertions(+), 35 deletions(-) diff --git a/dqn.h b/dqn.h index 03d260e..8ecf064 100644 --- a/dqn.h +++ b/dqn.h @@ -20,6 +20,7 @@ #endif #include // For standard types +#include #define LOCAL_PERSIST static #define FILE_SCOPE static @@ -35,6 +36,8 @@ typedef int16_t i16; typedef double f64; typedef float f32; +#define DQN_F32_MIN -FLT_MAX + #define DQN_TERABYTE(val) (DQN_GIGABYTE(val) * 1024LL) #define DQN_GIGABYTE(val) (DQN_MEGABYTE(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 // 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 // optimal space usage. @@ -88,7 +91,7 @@ DQN_FILE_SCOPE void DqnMem_Free (void *memory); // - InitWithFixedSize() allows you to to disable dynamic allocations and // 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 // BeginTempRegion and EndTempRegion functions. Specifically freeing // individual items is typically not generalisable in this scheme. @@ -129,12 +132,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_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 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 bool DqnMemStack_FreeStackBlock (DqnMemStack *const stack, DqnMemStackBlock *block); // Frees the specified block, returns false if block doesn't belong -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_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 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_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 // 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 @@ -504,6 +507,8 @@ DQN_FILE_SCOPE inline bool operator==(DqnV2i a, DqnV2i b) { return DqnV typedef union DqnV3 { struct { f32 x, y, z; }; + DqnV2 xy; + struct { f32 r, g, b; }; f32 e[3]; } 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 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_Add (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 //////////////////////////////////////////////////////////////////////////////// typedef union DqnV4 { - struct { f32 x, y, z, w; }; + struct + { + f32 x, y, z, w; + }; DqnV3 xyz; + DqnV2 xy; struct { f32 r, g, b, a; }; DqnV3 rgb; @@ -571,17 +582,18 @@ DQN_FILE_SCOPE DqnV4 DqnV4_Hadamard(DqnV4 a, DqnV4 b); DQN_FILE_SCOPE f32 DqnV4_Dot (DqnV4 a, DqnV4 b); 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_Add (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, i32 b) { return DqnV4_Scalei (a, b); } -DQN_FILE_SCOPE inline DqnV4 &operator*=(DqnV4 &a, DqnV4 b) { return (a = DqnV4_Hadamard(a, b)); } -DQN_FILE_SCOPE inline DqnV4 &operator*=(DqnV4 &a, f32 b) { return (a = DqnV4_Scalef (a, b)); } -DQN_FILE_SCOPE inline DqnV4 &operator*=(DqnV4 &a, i32 b) { return (a = DqnV4_Scalei (a, b)); } -DQN_FILE_SCOPE inline DqnV4 &operator-=(DqnV4 &a, DqnV4 b) { return (a = DqnV4_Sub (a, b)); } -DQN_FILE_SCOPE inline DqnV4 &operator+=(DqnV4 &a, DqnV4 b) { return (a = DqnV4_Add (a, b)); } -DQN_FILE_SCOPE inline bool operator==(DqnV4 a, DqnV4 b) { return DqnV4_Equals (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, 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, 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, DqnV4 b) { return (a = DqnV4_Hadamard(a, b)); } +DQN_FILE_SCOPE inline DqnV4 &operator*=(DqnV4 &a, f32 b) { return (a = DqnV4_Scalef (a, b)); } +DQN_FILE_SCOPE inline DqnV4 &operator*=(DqnV4 &a, i32 b) { return (a = DqnV4_Scalei (a, b)); } +DQN_FILE_SCOPE inline DqnV4 &operator-=(DqnV4 &a, DqnV4 b) { return (a = DqnV4_Sub (a, b)); } +DQN_FILE_SCOPE inline DqnV4 &operator+=(DqnV4 &a, DqnV4 b) { return (a = DqnV4_Add (a, b)); } +DQN_FILE_SCOPE inline bool operator==(DqnV4 a, DqnV4 b) { return DqnV4_Equals (a, b); } //////////////////////////////////////////////////////////////////////////////// // 4D Matrix Mat4 @@ -754,7 +766,6 @@ DQN_FILE_SCOPE i32 DqnRnd_PCGRange(DqnRandPCGState *pcg, i32 min, i32 max); #define WIN32_LEAN_AND_MEAN #include - #define DQN_WIN32_ERROR_BOX(text, title) MessageBoxA(NULL, text, title, MB_OK); // Out is a pointer to the buffer to receive the characters. // outLen is the length/capacity of the out buffer @@ -1444,7 +1455,7 @@ DQN_FILE_SCOPE bool DqnMemStack_InitWithFixedSize(DqnMemStack *const stack, 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; @@ -2121,6 +2132,15 @@ DQN_FILE_SCOPE DqnV3 DqnV3_Cross(DqnV3 a, DqnV3 b) 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) { DqnV3i result = {x, y, z}; diff --git a/dqn_unit_test.cpp b/dqn_unit_test.cpp index 15d12d6..aa99da5 100644 --- a/dqn_unit_test.cpp +++ b/dqn_unit_test.cpp @@ -1052,7 +1052,7 @@ void MemStackTest() // Alocate A size_t sizeA = (size_t)(allocSize * 0.5f); - void *resultA = DqnMemStack_Allocate(&stack, sizeA); + void *resultA = DqnMemStack_Push(&stack, sizeA); u64 resultAddrA = *((u64 *)resultA); DQN_ASSERT(resultAddrA % ALIGNMENT == 0); DQN_ASSERT(stack.block && stack.block->memory); @@ -1068,7 +1068,7 @@ void MemStackTest() DqnMemStackBlock *blockA = stack.block; // Alocate B size_t sizeB = (size_t)(allocSize * 2.0f); - void *resultB = DqnMemStack_Allocate(&stack, sizeB); + void *resultB = DqnMemStack_Push(&stack, sizeB); u64 resultAddrB = *((u64 *)resultB); DQN_ASSERT(resultAddrB % ALIGNMENT == 0); DQN_ASSERT(stack.block && stack.block->memory); @@ -1094,7 +1094,7 @@ void MemStackTest() // Check temp regions work DqnTempMemStack tempBuffer = DqnMemStack_BeginTempRegion(&stack); size_t sizeC = 1024 + 1; - void *resultC = DqnMemStack_Allocate(tempBuffer.stack, sizeC); + void *resultC = DqnMemStack_Push(tempBuffer.stack, sizeC); u64 resultAddrC = *((u64 *)resultC); DQN_ASSERT(resultAddrC % ALIGNMENT == 0); DQN_ASSERT(stack.block != blockB && stack.block != blockA); @@ -1166,7 +1166,7 @@ void MemStackTest() DQN_ASSERT(stack.byteAlign == ALIGNMENT); // 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 DqnMemStack_Free(&stack); @@ -1190,11 +1190,11 @@ void MemStackTest() DQN_ASSERT(stack.block->used == 0); 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); // Allocating more should fail - DQN_ASSERT(!DqnMemStack_Allocate(&stack, allocSize)); + DQN_ASSERT(!DqnMemStack_Push(&stack, allocSize)); // Freeing should work DqnMemStack_Free(&stack); @@ -1212,7 +1212,7 @@ void MemStackTest() u8 *first = NULL; { 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 DQN_ASSERT(data); @@ -1232,7 +1232,7 @@ void MemStackTest() DQN_ASSERT(stack.block->size == firstBlockSize); // Reallocate the data - data = (u8 *)DqnMemStack_Allocate(&stack, firstBlockSize); + data = (u8 *)DqnMemStack_Push(&stack, firstBlockSize); DQN_ASSERT(stack.block->size == firstBlockSize); DQN_ASSERT((size_t)data % ALIGNMENT == 0); @@ -1253,7 +1253,7 @@ void MemStackTest() DQN_ASSERT(stack.block->size == firstBlockSize); // 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++) data[i] = 'c'; @@ -1262,19 +1262,19 @@ void MemStackTest() // Force it to allocate three new blocks and write out data to each size_t secondBlockSize = DQN_KILOBYTE(2); - u8 *second = (u8 *)DqnMemStack_Allocate(&stack, secondBlockSize); + u8 *second = (u8 *)DqnMemStack_Push(&stack, secondBlockSize); DqnMemStackBlock *secondBlock = stack.block; for (u32 i = 0; i < secondBlockSize; i++) second[i] = 'd'; size_t thirdBlockSize = DQN_KILOBYTE(3); - u8 *third = (u8 *)DqnMemStack_Allocate(&stack, thirdBlockSize); + u8 *third = (u8 *)DqnMemStack_Push(&stack, thirdBlockSize); DqnMemStackBlock *thirdBlock = stack.block; for (u32 i = 0; i < thirdBlockSize; i++) third[i] = 'e'; size_t fourthBlockSize = DQN_KILOBYTE(4); - u8 *fourth = (u8 *)DqnMemStack_Allocate(&stack, fourthBlockSize); + u8 *fourth = (u8 *)DqnMemStack_Push(&stack, fourthBlockSize); DqnMemStackBlock *fourthBlock = stack.block; for (u32 i = 0; i < fourthBlockSize; i++) fourth[i] = 'f'; @@ -1391,7 +1391,7 @@ void MemStackTest() DqnMemStack_Init(&stack, DQN_KILOBYTE(1), true); size_t allocSize = 512; - void *alloc = DqnMemStack_Allocate(&stack, allocSize); + void *alloc = DqnMemStack_Push(&stack, allocSize); DQN_ASSERT(stack.block->used == allocSize); DQN_ASSERT(DqnMemStack_Pop(&stack, alloc, allocSize));