Created an initial version of a standard array template and swapped it in for the assembly array structure.

This commit is contained in:
Peter Slattery 2019-11-28 21:12:57 -08:00
parent da76bb46f5
commit a77d97a31f
7 changed files with 268 additions and 23 deletions

View File

@ -0,0 +1,11 @@
struct animation_block
{
r32 StartTime;
r32 EndTime;
animation_block* Next;
};
struct animation_layer
{
animation_block* Blocks;
};

View File

@ -137,7 +137,6 @@ LoadAssembly (app_state* State, context Context, char* Path)
string FileName = Substring(PathString, IndexOfLastSlash + 1); string FileName = Substring(PathString, IndexOfLastSlash + 1);
r32 Scale = 100; r32 Scale = 100;
Assert(State->AssembliesCount < ASSEMBLY_LIST_LENGTH);
s32 AssemblyMemorySize = GetAssemblyMemorySizeFromDefinition(AssemblyDefinition, FileName); s32 AssemblyMemorySize = GetAssemblyMemorySizeFromDefinition(AssemblyDefinition, FileName);
u8* AssemblyMemory = Context.PlatformAlloc(AssemblyMemorySize); u8* AssemblyMemory = Context.PlatformAlloc(AssemblyMemorySize);
@ -147,7 +146,9 @@ LoadAssembly (app_state* State, context Context, char* Path)
Scale, Scale,
AssemblyMemory, AssemblyMemory,
AssemblyMemorySize); AssemblyMemorySize);
State->AssemblyList[State->AssembliesCount++] = NewAssembly; array_entry_handle NewAssemblyHandle = PushElement(NewAssembly, &State->AssemblyList);
PushElement(NewAssemblyHandle, &State->ActiveAssemblyIndecies);
State->TotalLEDsCount += NewAssembly.LEDCount; State->TotalLEDsCount += NewAssembly.LEDCount;
ClearArenaToSnapshot(State->Transient, TempMemorySnapshot); ClearArenaToSnapshot(State->Transient, TempMemorySnapshot);
@ -156,19 +157,20 @@ LoadAssembly (app_state* State, context Context, char* Path)
internal void internal void
UnloadAssembly (s32 AssemblyIndex, app_state* State, context Context) UnloadAssembly (s32 AssemblyIndex, app_state* State, context Context)
{ {
assembly* Assembly = State->AssemblyList + AssemblyIndex; assembly* Assembly = GetElementAtIndex(AssemblyIndex, State->AssemblyList);
State->TotalLEDsCount -= Assembly->LEDCount; State->TotalLEDsCount -= Assembly->LEDCount;
Context.PlatformFree(Assembly->Arena.Base, Assembly->Arena.Size); Context.PlatformFree(Assembly->Arena.Base, Assembly->Arena.Size);
if (AssemblyIndex != (State->AssembliesCount - 1)) RemoveElementAtIndex(AssemblyIndex, &State->AssemblyList);
for (s32 i = 0; i < State->ActiveAssemblyIndecies.Used; i++)
{ {
State->AssemblyList[AssemblyIndex] = State->AssemblyList[State->AssembliesCount - 1]; array_entry_handle Handle = *GetElementAtIndex(i, State->ActiveAssemblyIndecies);
} if (Handle.Index == AssemblyIndex)
else
{ {
*Assembly = {}; RemoveElementAtIndex(i, &State->ActiveAssemblyIndecies);
break;
}
} }
State->AssembliesCount -= 1;
} }
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
@ -287,6 +289,9 @@ INITIALIZE_APPLICATION(InitializeApplication)
State->Camera.Position = v3{0, 0, -250}; State->Camera.Position = v3{0, 0, -250};
State->Camera.LookAt = v3{0, 0, 0}; State->Camera.LookAt = v3{0, 0, 0};
State->AssemblyList.BucketSize = 32;
State->AssemblyList.FreeList.Next = &State->AssemblyList.FreeList;
State->ActiveAssemblyIndecies.BucketSize = 32;
#if 1 #if 1
char Path[] = "radialumia.fold"; char Path[] = "radialumia.fold";
LoadAssembly(State, Context, Path); LoadAssembly(State, Context, Path);
@ -409,9 +414,10 @@ UPDATE_AND_RENDER(UpdateAndRender)
s32 HeaderSize = State->NetworkProtocolHeaderSize; s32 HeaderSize = State->NetworkProtocolHeaderSize;
dmx_buffer_list* DMXBuffers = 0; dmx_buffer_list* DMXBuffers = 0;
for (s32 i = 0; i < State->AssembliesCount; i++) for (s32 i = 0; i < State->ActiveAssemblyIndecies.Used; i++)
{ {
assembly Assembly = State->AssemblyList[i]; array_entry_handle AssemblyHandle = *GetElementAtIndex(i, State->ActiveAssemblyIndecies);
assembly Assembly = *GetElementWithHandle(AssemblyHandle, State->AssemblyList);
dmx_buffer_list* NewDMXBuffers = CreateDMXBuffers(Assembly, HeaderSize, State->Transient); dmx_buffer_list* NewDMXBuffers = CreateDMXBuffers(Assembly, HeaderSize, State->Transient);
DMXBuffers = DMXBufferListAppend(DMXBuffers, NewDMXBuffers); DMXBuffers = DMXBufferListAppend(DMXBuffers, NewDMXBuffers);
} }
@ -475,9 +481,10 @@ UPDATE_AND_RENDER(UpdateAndRender)
s32 MaxLEDsPerJob = 2048; s32 MaxLEDsPerJob = 2048;
render_quad_batch_constructor RenderLEDsBatch = PushRenderQuad3DBatch(RenderBuffer, State->TotalLEDsCount); render_quad_batch_constructor RenderLEDsBatch = PushRenderQuad3DBatch(RenderBuffer, State->TotalLEDsCount);
for (s32 AssemblyIdx = 0; AssemblyIdx < State->AssembliesCount; AssemblyIdx++) for (s32 i = 0; i < State->ActiveAssemblyIndecies.Used; i++)
{ {
assembly Assembly = State->AssemblyList[AssemblyIdx]; array_entry_handle AssemblyHandle = *GetElementAtIndex(i, State->ActiveAssemblyIndecies);
assembly Assembly = *GetElementWithHandle(AssemblyHandle, State->AssemblyList);
s32 JobsNeeded = IntegerDivideRoundUp(Assembly.LEDCount, MaxLEDsPerJob); s32 JobsNeeded = IntegerDivideRoundUp(Assembly.LEDCount, MaxLEDsPerJob);
for (s32 Job = 0; Job < JobsNeeded; Job++) for (s32 Job = 0; Job < JobsNeeded; Job++)
@ -529,9 +536,11 @@ UPDATE_AND_RENDER(UpdateAndRender)
State->Interface, Mouse); State->Interface, Mouse);
string InterfaceString = MakeString(PushArray(State->Transient, char, 256), 256); string InterfaceString = MakeString(PushArray(State->Transient, char, 256), 256);
for (int i = 0; i < State->AssembliesCount; i++) for (s32 i = 0; i < State->ActiveAssemblyIndecies.Used; i++)
{ {
PrintF(&InterfaceString, "Unload %.*s", State->AssemblyList[i].Name.Length, State->AssemblyList[i].Name.Memory); array_entry_handle AssemblyHandle = *GetElementAtIndex(i, State->ActiveAssemblyIndecies);
assembly Assembly = *GetElementWithHandle(AssemblyHandle, State->AssemblyList);
PrintF(&InterfaceString, "Unload %.*s", Assembly.Name.Length, Assembly.Name.Memory);
ButtonPos.x += ButtonDim.x + 10; ButtonPos.x += ButtonDim.x + 10;
button_result UnloadAssemblyBtn = EvaluateButton(RenderBuffer, ButtonPos, ButtonPos + ButtonDim, button_result UnloadAssemblyBtn = EvaluateButton(RenderBuffer, ButtonPos, ButtonPos + ButtonDim,

View File

@ -46,12 +46,8 @@ struct app_state
s32 TotalLEDsCount; s32 TotalLEDsCount;
// TODO(Peter): Make this dynamic. We want them contiguous in memory since we'll be accessing them assembly_array AssemblyList;
// mostly by looping through them. On the other hand, I don't expect there to ever be more than 100 array_entry_handle_contiguous_array ActiveAssemblyIndecies;
// of them at once.
#define ASSEMBLY_LIST_LENGTH 32
assembly AssemblyList[ASSEMBLY_LIST_LENGTH];
s32 AssembliesCount;
camera Camera; camera Camera;
r32 PixelsToWorldScale; r32 PixelsToWorldScale;

View File

@ -36,3 +36,5 @@ struct assembly
s32 LEDUniverseMapCount; s32 LEDUniverseMapCount;
leds_in_universe_range* LEDUniverseMap; leds_in_universe_range* LEDUniverseMap;
}; };
TYPEDEF_ARRAY(assembly);

View File

@ -211,7 +211,7 @@ DrawDebugInterface (render_command_buffer* RenderBuffer, r32 StartX, interface_c
r32 FramesPerSecond = 1.0f / DeltaTime; r32 FramesPerSecond = 1.0f / DeltaTime;
PrintF(&DebugString, "Framerate: %.*f s %d fps | Modes: %d Memory Used: %d / %d | Commands: %d", PrintF(&DebugString, "Framerate: %.*f s %d fps | Modes: %d Memory Used: %d / %d | Commands: %d | HI SAM!!!! ",
5, DeltaTime, 5, DeltaTime,
(u32)FramesPerSecond, (u32)FramesPerSecond,
State->Modes.ActiveModesCount, State->Modes.ActiveModesCount,

View File

@ -1,5 +1,6 @@
#include "gs_language.h" #include "gs_language.h"
#include "gs_platform.h" #include "gs_platform.h"
#include "gs_array.h"
#include "foldhaus_memory.h" #include "foldhaus_memory.h"
#include "gs_string.h" #include "gs_string.h"

226
src/gs_array.h Normal file
View File

@ -0,0 +1,226 @@
struct free_list
{
free_list* Next;
s32 Index;
};
struct bucket_index
{
s32 Bucket;
s32 IndexInBucket;
};
inline bucket_index
GetBucketIndexForIndex (s32 Index, s32 BucketSize)
{
bucket_index Result = {};
Result.Bucket = Index / BucketSize;
Result.IndexInBucket = Index % BucketSize;
return Result;
};
struct array_entry_handle
{
s32 Generation;
s32 Index;
};
// NOTE(Peter): This is a total bastardization of the preprocessor but it works and is
// easier than writing a metaprogramming system at the moment.
// TODO(Peter): Write a metaprogramming version of this that is actually easy to debug
#define TYPEDEF_ARRAY(element_type) \
struct element_type##_array_entry { \
s32 Generation; \
union \
{ \
element_type Entry; \
free_list Free; \
}; \
}; \
\
struct element_type##_array \
{ \
element_type##_array_entry** Buckets; \
s32 BucketSize; \
s32 BucketCount; \
s32 Used; \
free_list FreeList; \
}; \
\
internal void \
GrowBuffer(element_type##_array* Buffer) \
{ \
s32 NewBucketSize = sizeof(element_type##_array_entry) * Buffer->BucketSize; \
element_type##_array_entry* NewBucket = (element_type##_array_entry*)malloc(NewBucketSize); \
GSZeroMemory((u8*)NewBucket, NewBucketSize); \
\
s32 NewBucketIndex = Buffer->BucketCount++; \
if (!Buffer->Buckets) \
{ \
Buffer->Buckets = (element_type##_array_entry**)malloc(sizeof(element_type##_array_entry*)); \
} \
else \
{ \
Buffer->Buckets = (element_type##_array_entry**)realloc(Buffer->Buckets, sizeof(element_type##_array_entry*) * Buffer->BucketCount); \
} \
Buffer->Buckets[NewBucketIndex] = NewBucket; \
} \
\
internal element_type##_array_entry* \
GetEntryAtIndex (s32 Index, element_type##_array Buffer) \
{ \
bucket_index BucketIndex = GetBucketIndexForIndex(Index, Buffer.BucketSize); \
element_type##_array_entry* Entry = Buffer.Buckets[BucketIndex.Bucket] + BucketIndex.IndexInBucket; \
return Entry; \
} \
\
internal array_entry_handle \
PushElement (element_type Data, element_type##_array* Buffer) \
{ \
array_entry_handle Result = {}; \
\
if (Buffer->FreeList.Next != &Buffer->FreeList) \
{ \
free_list* FreeList = Buffer->FreeList.Next; \
element_type##_array_entry* Entry = GetEntryAtIndex(FreeList->Index, *Buffer); \
Buffer->FreeList.Next = Entry->Free.Next; \
\
Result.Index = Entry->Free.Index; \
Result.Generation = Entry->Generation; \
Entry->Entry = Data; \
\
++Buffer->Used; \
} \
else \
{ \
if (Buffer->Used >= Buffer->BucketSize * Buffer->BucketCount) \
{ \
GrowBuffer(Buffer); \
} \
\
s32 Index = Buffer->Used++; \
s32 BucketIndex = Index / Buffer->BucketSize; \
s32 IndexInBucket = Index % Buffer->BucketSize; \
\
Buffer->Buckets[BucketIndex][IndexInBucket].Entry = Data; \
Result.Index = Index; \
Result.Generation = Buffer->Buckets[BucketIndex][IndexInBucket].Generation; \
} \
\
return Result; \
} \
\
internal element_type* \
GetElementAtIndex (s32 Index, element_type##_array Buffer) \
{ \
Assert(Index < Buffer.Used); \
element_type##_array_entry* Entry = GetEntryAtIndex(Index, Buffer); \
element_type* Result = &Entry->Entry; \
return Result; \
} \
\
internal element_type* \
GetElementWithHandle (array_entry_handle Handle, element_type##_array Buffer) \
{ \
element_type* Result = 0; \
\
element_type##_array_entry* Entry = GetEntryAtIndex(Handle.Index, Buffer); \
\
if (Entry->Generation == Handle.Generation) \
{ \
Result = &Entry->Entry; \
} \
\
return Result; \
} \
\
internal void \
RemoveElementAtIndex (s32 Index, element_type##_array* Buffer) \
{ \
Assert(Index < Buffer->Used); \
\
element_type##_array_entry* Entry = GetEntryAtIndex(Index, *Buffer); \
++Entry->Generation; \
Entry->Free.Index = Index; \
\
Entry->Free.Next = Buffer->FreeList.Next; \
Buffer->FreeList.Next = &Entry->Free; \
\
--Buffer->Used; \
} \
// END OF CRAZY MACRO
#define TYPEDEF_CONTIGUOUS_ARRAY(element_type) \
struct element_type##_contiguous_array \
{ \
element_type** Buckets; \
s32 BucketSize; \
s32 BucketCount; \
s32 Used; \
}; \
\
internal void \
GrowBuffer(element_type##_contiguous_array* Buffer) \
{ \
s32 NewBucketSize = sizeof(element_type) * Buffer->BucketSize; \
element_type* NewBucket = (element_type*)malloc(NewBucketSize); \
GSZeroMemory((u8*)NewBucket, NewBucketSize); \
\
s32 NewBucketIndex = Buffer->BucketCount++; \
if (!Buffer->Buckets) \
{ \
Buffer->Buckets = (element_type**)malloc(sizeof(element_type*)); \
} \
else \
{ \
Buffer->Buckets = (element_type**)realloc(Buffer->Buckets, sizeof(element_type*) * Buffer->BucketCount); \
} \
Buffer->Buckets[NewBucketIndex] = NewBucket; \
} \
\
internal element_type* \
GetElementAtIndex (s32 Index, element_type##_contiguous_array Buffer) \
{ \
bucket_index BucketIndex = GetBucketIndexForIndex(Index, Buffer.BucketSize); \
element_type* Entry = Buffer.Buckets[BucketIndex.Bucket] + BucketIndex.IndexInBucket; \
return Entry; \
} \
\
internal s32 \
PushElement (element_type Data, element_type##_contiguous_array* Buffer) \
{ \
s32 Result = -1; \
\
if (Buffer->Used >= Buffer->BucketSize * Buffer->BucketCount) \
{ \
GrowBuffer(Buffer); \
} \
\
s32 Index = Buffer->Used++; \
s32 BucketIndex = Index / Buffer->BucketSize; \
s32 IndexInBucket = Index % Buffer->BucketSize; \
\
Buffer->Buckets[BucketIndex][IndexInBucket] = Data; \
Result = Index; \
return Result; \
} \
\
internal void \
RemoveElementAtIndex (s32 Index, element_type##_contiguous_array* Buffer) \
{ \
Assert(Index < Buffer->Used); \
\
bucket_index IndexToRemove = GetBucketIndexForIndex(Index, Buffer->BucketSize); \
bucket_index LastIndex = GetBucketIndexForIndex(Buffer->Used - 1, Buffer->BucketSize); \
element_type ValueAtLastIndex = Buffer->Buckets[LastIndex.Bucket][LastIndex.IndexInBucket]; \
Buffer->Buckets[IndexToRemove.Bucket][IndexToRemove.IndexInBucket] = ValueAtLastIndex; \
--Buffer->Used; \
} \
// END OF CRAZY MACRO
TYPEDEF_ARRAY(array_entry_handle);
TYPEDEF_CONTIGUOUS_ARRAY(array_entry_handle);