Pulled the leds out of assemblies and into their own subsystem.

This commit is contained in:
Peter Slattery 2020-06-15 15:36:50 -07:00
parent bfd9d6671c
commit 69db4b436c
12 changed files with 390 additions and 313 deletions

View File

@ -5,7 +5,7 @@
//
#ifndef FOLDHAUS_ANIMATION
#define ANIMATION_PROC(name) void name(assembly_led_buffer* Assembly, r32 Time)
#define ANIMATION_PROC(name) void name(led_buffer* Assembly, r32 Time)
typedef ANIMATION_PROC(animation_proc);
struct frame_range
@ -39,7 +39,7 @@ struct anim_layer
#define ANIMATION_SYSTEM_BLOCKS_MAX 128
struct animation_system
{
memory_arena Storage;
memory_arena* Storage;
gs_list<animation_block> Blocks;
anim_layer* Layers;
@ -94,7 +94,7 @@ PercentToFrameInRange(r32 Percent, frame_range Range)
return Result;
}
internal s32
internal s32
ClampFrameToRange(s32 Frame, frame_range Range)
{
s32 Result = Frame;
@ -135,7 +135,7 @@ RemoveAnimationBlock(gs_list_handle AnimationBlockHandle, animation_system* Anim
internal u32
AddLayer (string Name, animation_system* AnimationSystem, blend_mode BlendMode = BlendMode_Overwrite)
{
// TODO(Peter): If this assert fires its time to make the layer buffer system
// TODO(Peter): If this assert fires its time to make the layer buffer system
// resizable.
Assert(AnimationSystem->LayersCount < AnimationSystem->LayersMax);
@ -143,7 +143,7 @@ AddLayer (string Name, animation_system* AnimationSystem, blend_mode BlendMode =
Result = AnimationSystem->LayersCount++;
anim_layer* NewLayer = AnimationSystem->Layers + Result;
*NewLayer = {0};
NewLayer->Name = MakeString(PushArray(&AnimationSystem->Storage, char, Name.Length), Name.Length);
NewLayer->Name = MakeString(PushArray(AnimationSystem->Storage, char, Name.Length), Name.Length);
CopyStringTo(Name, &NewLayer->Name);
NewLayer->BlendMode = BlendMode;
return Result;

View File

@ -58,6 +58,8 @@ struct assembly_tokenizer
char* At;
u32 LineNumber;
bool ParsingIsValid;
};
internal bool
@ -128,12 +130,12 @@ ReadFieldIdentifier(assembly_field Field, assembly_tokenizer* T)
}
else
{
// TODO(Peter): Error
T->ParsingIsValid = false;
}
}
else
{
// TODO(Peter): Error
T->ParsingIsValid = false;
}
return Result;
}
@ -148,7 +150,7 @@ ReadFieldEnd(assembly_tokenizer* T)
}
else
{
// TODO(Peter): Error
T->ParsingIsValid = false;
}
return Result;
}
@ -228,7 +230,7 @@ ReadStringField(assembly_field Field, assembly_tokenizer* T, memory_arena* Arena
}
else
{
// TODO(Peter): Error
T->ParsingIsValid = false;
}
}
return Result;
@ -243,7 +245,7 @@ ReadFloatField(assembly_field Field, assembly_tokenizer* T)
Result = ReadFloat(T);
if (!ReadFieldEnd(T))
{
// TODO(Peter): Error
T->ParsingIsValid = false;
}
}
return Result;
@ -258,7 +260,7 @@ ReadIntField(assembly_field Field, assembly_tokenizer* T)
Result = ReadInt(T);
if (!ReadFieldEnd(T))
{
// TODO(Peter): Error
T->ParsingIsValid = false;
}
}
return Result;
@ -279,16 +281,31 @@ ReadV3Field(assembly_field Field, assembly_tokenizer* T)
if (AdvanceIfTokenEquals(T, ","))
{
Result.z = ReadFloat(T);
if (AdvanceIfTokenEquals(T, ")"))
{
if (!ReadFieldEnd(T))
{
// TODO(Peter): Error
T->ParsingIsValid = false;
}
}
else
{
T->ParsingIsValid = false;
}
}
else
{
T->ParsingIsValid = false;
}
}
else
{
T->ParsingIsValid = false;
}
}
else
{
T->ParsingIsValid = false;
}
}
return Result;
@ -315,15 +332,15 @@ ReadStructClosing(assembly_tokenizer* T)
return Result;
}
internal void
internal bool
ParseAssemblyFile(assembly* Assembly, string FileText, memory_arena* Transient)
{
Assert(Assembly->Arena.Alloc != 0);
Assembly->LedCountTotal = 0;
assembly_tokenizer Tokenizer = {};
Tokenizer.Text = FileText;
Tokenizer.At = Tokenizer.Text.Memory;
Tokenizer.ParsingIsValid = true;
Assembly->Name = ReadStringField(AssemblyField_AssemblyName, &Tokenizer, &Assembly->Arena);
Assembly->Scale = ReadFloatField(AssemblyField_AssemblyScale, &Tokenizer);
@ -349,8 +366,7 @@ ParseAssemblyFile(assembly* Assembly, string FileText, memory_arena* Transient)
StripAt->EndPosition = ReadV3Field(AssemblyField_End, &Tokenizer);
if (!ReadStructClosing(&Tokenizer))
{
// TODO(Peter): Error
InvalidCodePath;
Tokenizer.ParsingIsValid = false;
}
}
@ -372,19 +388,27 @@ ParseAssemblyFile(assembly* Assembly, string FileText, memory_arena* Transient)
TagAt->ValueHash = HashString(TagValue);
if (!ReadStructClosing(&Tokenizer))
{
// TODO(Peter): Error
InvalidCodePath;
Tokenizer.ParsingIsValid = false;
}
}
else
{
Tokenizer.ParsingIsValid = false;
}
}
if (!ReadStructClosing(&Tokenizer))
{
// TODO(Peter): Error
InvalidCodePath;
Tokenizer.ParsingIsValid = false;
}
}
else
{
Tokenizer.ParsingIsValid = false;
}
}
return Tokenizer.ParsingIsValid;
}
#define ASSEMBLY_PARSER_CPP

View File

@ -70,13 +70,16 @@ RELOAD_STATIC_DATA(ReloadStaticData)
INITIALIZE_APPLICATION(InitializeApplication)
{
app_state* State = (app_state*)Context.MemoryBase;
*State = {};
State->Permanent = {};
State->Permanent.Alloc = (gs_memory_alloc*)Context.PlatformAlloc;
State->Permanent.Realloc = (gs_memory_realloc*)Context.PlatformRealloc;
State->Permanent.PlatformMemory = Context.PlatformMemory;
State->Transient = {};
State->Transient.FindAddressRule = FindAddress_InLastBufferOnly;
State->Transient.Alloc = (gs_memory_alloc*)Context.PlatformAlloc;
State->Transient.Realloc = (gs_memory_realloc*)Context.PlatformRealloc;
State->Transient.PlatformMemory = Context.PlatformMemory;
State->Assemblies.CountMax = 8;
State->Assemblies.Values = PushArray(&State->Permanent, assembly, State->Assemblies.CountMax);
State->GlobalLog = PushStruct(&State->Transient, event_log);
*State->GlobalLog = {0};
@ -175,6 +178,8 @@ INITIALIZE_APPLICATION(InitializeApplication)
State->Camera.Position = v3{0, 0, -250};
State->Camera.LookAt = v3{0, 0, 0};
State->LedSystem = LedSystemInitialize(Context.PlatformMemory, 128);
#if 1
string SculpturePath = MakeStringLiteral("data/blumen_lumen_v2.fold");
LoadAssembly(State, Context, SculpturePath);
@ -189,12 +194,12 @@ INITIALIZE_APPLICATION(InitializeApplication)
// Setup Operation Modes
State->Modes.ActiveModesCount = 0;
State->Modes.Arena = {};
State->Modes.Arena.Alloc = (gs_memory_alloc*)Context.PlatformAlloc;
State->Modes.Arena.Realloc = (gs_memory_realloc*)Context.PlatformRealloc;
State->Modes.Arena.PlatformMemory = Context.PlatformMemory;
State->Modes.Arena.FindAddressRule = FindAddress_InLastBufferOnly;
{ // Animation PLAYGROUND
State->AnimationSystem = {};
State->AnimationSystem.Storage = &State->Permanent;
State->AnimationSystem.SecondsPerFrame = 1.f / 24.f;
State->AnimationSystem.PlayableRange.Min = 0;
State->AnimationSystem.PlayableRange.Max = SecondsToFrames(15, State->AnimationSystem);
@ -273,21 +278,24 @@ HandleInput (app_state* State, rect WindowBounds, input_queue InputQueue, mouse_
}
internal dmx_buffer_list*
CreateDMXBuffers(assembly Assembly, s32 BufferHeaderSize, memory_arena* Arena)
CreateDMXBuffers(assembly Assembly, led_system* LedSystem, s32 BufferHeaderSize, memory_arena* Arena)
{
DEBUG_TRACK_FUNCTION;
led_buffer* LedBuffer = LedSystemGetBuffer(LedSystem, Assembly.LedBufferIndex);
dmx_buffer_list* Result = 0;
dmx_buffer_list* Head = 0;
s32 BufferSize = BufferHeaderSize + 512;
for (u32 Range = 0; Range < Assembly.LEDUniverseMapCount; Range++)
for (u32 StripIndex = 0; StripIndex < Assembly.StripCount; StripIndex++)
{
leds_in_universe_range LEDUniverseRange = Assembly.LEDUniverseMap[Range];
v2_strip Strip = Assembly.Strips[StripIndex];
dmx_buffer_list* NewBuffer = PushStruct(Arena, dmx_buffer_list);
NewBuffer->Buffer.Universe = LEDUniverseRange.Universe;
NewBuffer->Buffer.Universe = Strip.StartUniverse;
NewBuffer->Buffer.Base = PushArray(Arena, u8, BufferSize);
NewBuffer->Buffer.TotalSize = BufferSize;
NewBuffer->Buffer.HeaderSize = BufferHeaderSize;
@ -302,13 +310,12 @@ CreateDMXBuffers(assembly Assembly, s32 BufferHeaderSize, memory_arena* Arena)
Head = NewBuffer;
u8* DestChannel = Head->Buffer.Base + BufferHeaderSize;
for (s32 LEDIdx = LEDUniverseRange.RangeStart;
LEDIdx < LEDUniverseRange.RangeOnePastLast;
LEDIdx++)
for (u32 i = 0; i < Strip.LedCount; i++)
{
led LED = Assembly.LEDBuffer.LEDs[LEDIdx];
pixel Color = Assembly.LEDBuffer.Colors[LED.Index];
u32 LedIndex = Strip.LedLUT[i];
led LED = LedBuffer->Leds[LedIndex];
pixel Color = LedBuffer->Colors[LED.Index];
DestChannel[0] = Color.R;
DestChannel[1] = Color.G;
@ -366,11 +373,11 @@ UPDATE_AND_RENDER(UpdateAndRender)
CurrentBlocks[Block.Layer] = Block;
}
assembly_led_buffer* LayerLEDBuffers = PushArray(&State->Transient, assembly_led_buffer, CurrentBlocksMax);
for (u32 AssemblyIndex = 0; AssemblyIndex < State->ActiveAssemblyIndecies.Used; AssemblyIndex++)
led_buffer* LayerLEDBuffers = PushArray(&State->Transient, led_buffer, CurrentBlocksMax);
for (u32 AssemblyIndex = 0; AssemblyIndex < State->Assemblies.Count; AssemblyIndex++)
{
gs_list_handle AssemblyHandle = *State->ActiveAssemblyIndecies.GetElementAtIndex(AssemblyIndex);
assembly* Assembly = State->AssemblyList.GetElementWithHandle(AssemblyHandle);
assembly* Assembly = &State->Assemblies.Values[AssemblyIndex];
led_buffer* AssemblyLedBuffer = LedSystemGetBuffer(&State->LedSystem, Assembly->LedBufferIndex);
arena_snapshot ResetAssemblyMemorySnapshot = TakeSnapshotOfArena(&State->Transient);
@ -380,8 +387,8 @@ UPDATE_AND_RENDER(UpdateAndRender)
animation_block Block = CurrentBlocks[Layer];
// Prep Temp Buffer
LayerLEDBuffers[Layer] = Assembly->LEDBuffer;
LayerLEDBuffers[Layer].Colors = PushArray(&State->Transient, pixel, Assembly->LEDBuffer.LEDCount);
LayerLEDBuffers[Layer] = *AssemblyLedBuffer;
LayerLEDBuffers[Layer].Colors = PushArray(&State->Transient, pixel, AssemblyLedBuffer->LedCount);
u32 FramesIntoBlock = CurrentFrame - Block.Range.Min;
r32 SecondsIntoBlock = FramesIntoBlock * State->AnimationSystem.SecondsPerFrame;
@ -418,41 +425,41 @@ UPDATE_AND_RENDER(UpdateAndRender)
{
case BlendMode_Overwrite:
{
for (u32 LED = 0; LED < Assembly->LEDBuffer.LEDCount; LED++)
for (u32 LED = 0; LED < AssemblyLedBuffer->LedCount; LED++)
{
Assembly->LEDBuffer.Colors[LED] = LayerLEDBuffers[Layer].Colors[LED];
AssemblyLedBuffer->Colors[LED] = LayerLEDBuffers[Layer].Colors[LED];
}
}break;
case BlendMode_Add:
{
for (u32 LED = 0; LED < Assembly->LEDBuffer.LEDCount; LED++)
for (u32 LED = 0; LED < AssemblyLedBuffer->LedCount; LED++)
{
u32 R = (u32)Assembly->LEDBuffer.Colors[LED].R + (u32)LayerLEDBuffers[Layer].Colors[LED].R;
u32 G = (u32)Assembly->LEDBuffer.Colors[LED].G + (u32)LayerLEDBuffers[Layer].Colors[LED].G;
u32 B = (u32)Assembly->LEDBuffer.Colors[LED].B + (u32)LayerLEDBuffers[Layer].Colors[LED].B;
u32 R = (u32)AssemblyLedBuffer->Colors[LED].R + (u32)LayerLEDBuffers[Layer].Colors[LED].R;
u32 G = (u32)AssemblyLedBuffer->Colors[LED].G + (u32)LayerLEDBuffers[Layer].Colors[LED].G;
u32 B = (u32)AssemblyLedBuffer->Colors[LED].B + (u32)LayerLEDBuffers[Layer].Colors[LED].B;
Assembly->LEDBuffer.Colors[LED].R = (u8)GSMin(R, (u32)255);
Assembly->LEDBuffer.Colors[LED].G = (u8)GSMin(G, (u32)255);
Assembly->LEDBuffer.Colors[LED].B = (u8)GSMin(B, (u32)255);
AssemblyLedBuffer->Colors[LED].R = (u8)GSMin(R, (u32)255);
AssemblyLedBuffer->Colors[LED].G = (u8)GSMin(G, (u32)255);
AssemblyLedBuffer->Colors[LED].B = (u8)GSMin(B, (u32)255);
}
}break;
case BlendMode_Multiply:
{
for (u32 LED = 0; LED < Assembly->LEDBuffer.LEDCount; LED++)
for (u32 LED = 0; LED < AssemblyLedBuffer->LedCount; LED++)
{
r32 DR = (r32)Assembly->LEDBuffer.Colors[LED].R / 255.f;
r32 DG = (r32)Assembly->LEDBuffer.Colors[LED].G / 255.f;
r32 DB = (r32)Assembly->LEDBuffer.Colors[LED].B / 255.f;
r32 DR = (r32)AssemblyLedBuffer->Colors[LED].R / 255.f;
r32 DG = (r32)AssemblyLedBuffer->Colors[LED].G / 255.f;
r32 DB = (r32)AssemblyLedBuffer->Colors[LED].B / 255.f;
r32 SR = (r32)LayerLEDBuffers[Layer].Colors[LED].R / 255.f;
r32 SG = (r32)LayerLEDBuffers[Layer].Colors[LED].G / 255.f;
r32 SB = (r32)LayerLEDBuffers[Layer].Colors[LED].B / 255.f;
Assembly->LEDBuffer.Colors[LED].R = (u8)((DR * SR) * 255.f);
Assembly->LEDBuffer.Colors[LED].G = (u8)((DG * SG) * 255.f);
Assembly->LEDBuffer.Colors[LED].B = (u8)((DB * SB) * 255.f);
AssemblyLedBuffer->Colors[LED].R = (u8)((DR * SR) * 255.f);
AssemblyLedBuffer->Colors[LED].G = (u8)((DG * SG) * 255.f);
AssemblyLedBuffer->Colors[LED].B = (u8)((DB * SB) * 255.f);
}
}break;
}
@ -464,17 +471,12 @@ UPDATE_AND_RENDER(UpdateAndRender)
s32 HeaderSize = State->NetworkProtocolHeaderSize;
dmx_buffer_list* DMXBuffers = 0;
// TODO(Peter): Come back and re add this in. It was tanking frame rate after
// updates to the assembly file format
#if 0
for (u32 i = 0; i < State->ActiveAssemblyIndecies.Used; i++)
for (u32 i = 0; i < State->Assemblies.Count; i++)
{
gs_list_handle AssemblyHandle = *State->ActiveAssemblyIndecies.GetElementAtIndex(i);
assembly* Assembly = State->AssemblyList.GetElementWithHandle(AssemblyHandle);
dmx_buffer_list* NewDMXBuffers = CreateDMXBuffers(*Assembly, HeaderSize, &State->Transient);
assembly* Assembly = &State->Assemblies.Values[i];
dmx_buffer_list* NewDMXBuffers = CreateDMXBuffers(*Assembly, &State->LedSystem, HeaderSize, &State->Transient);
DMXBuffers = DMXBufferListAppend(DMXBuffers, NewDMXBuffers);
}
#endif
//DEBUG_IF(GlobalDebugServices->Interface.SendSACNData)
{
@ -530,10 +532,9 @@ UPDATE_AND_RENDER(UpdateAndRender)
{
DEBUG_TRACK_SCOPE(OverflowChecks);
AssertAllocationsNoOverflow(State->Permanent);
for (u32 i = 0; i < State->ActiveAssemblyIndecies.Used; i++)
for (u32 i = 0; i < State->Assemblies.Count; i++)
{
gs_list_handle AssemblyHandle = *State->ActiveAssemblyIndecies.GetElementAtIndex(i);
assembly* Assembly = State->AssemblyList.GetElementWithHandle(AssemblyHandle);
assembly* Assembly = &State->Assemblies.Values[i];
AssertAllocationsNoOverflow(Assembly->Arena);
}
}

View File

@ -49,13 +49,6 @@ enum network_protocol
NetworkProtocol_Count,
};
struct led_buffer
{
led* Leds;
pixel* Colors;
led_buffer* Next;
};
struct app_state
{
rect WindowBounds;
@ -68,9 +61,8 @@ struct app_state
streaming_acn SACN;
s32 TotalLEDsCount;
gs_list<assembly> AssemblyList;
gs_list<gs_list_handle> ActiveAssemblyIndecies;
led_system LedSystem;
assembly_array Assemblies;
camera Camera;
r32 PixelsToWorldScale;
@ -98,28 +90,28 @@ internal void OpenColorPicker(app_state* State, v4* Address);
// BEGIN TEMPORARY PATTERNS
internal void
TestPatternOne(assembly_led_buffer* Assembly, r32 Time)
TestPatternOne(led_buffer* Assembly, r32 Time)
{
for (u32 LEDIdx = 0; LEDIdx < Assembly->LEDCount; LEDIdx++)
for (u32 LedIndex = 0; LedIndex < Assembly->LedCount; LedIndex++)
{
led LED = Assembly->LEDs[LEDIdx];
if (LED.Position.x < 0)
led Led = Assembly->Leds[LedIndex];
if (Led.Position.x < 0)
{
Assembly->Colors[LED.Index].R = 255;
Assembly->Colors[LED.Index].B = 255;
Assembly->Colors[LED.Index].G = 255;
Assembly->Colors[Led.Index].R = 255;
Assembly->Colors[Led.Index].B = 255;
Assembly->Colors[Led.Index].G = 255;
}
else
{
Assembly->Colors[LED.Index].R = 0;
Assembly->Colors[LED.Index].B = 0;
Assembly->Colors[LED.Index].G = 0;
Assembly->Colors[Led.Index].R = 0;
Assembly->Colors[Led.Index].B = 0;
Assembly->Colors[Led.Index].G = 0;
}
}
}
internal void
TestPatternTwo(assembly_led_buffer* Assembly, r32 Time)
TestPatternTwo(led_buffer* Assembly, r32 Time)
{
r32 PeriodicTime = (Time / PI) * 2;
@ -138,11 +130,11 @@ TestPatternTwo(assembly_led_buffer* Assembly, r32 Time)
r32 OuterRadiusSquared = 1000000;
r32 InnerRadiusSquared = 0;
for (u32 LEDIdx = 0; LEDIdx < Assembly->LEDCount; LEDIdx++)
for (u32 LedIndex = 0; LedIndex < Assembly->LedCount; LedIndex++)
{
led LED = Assembly->LEDs[LEDIdx];
led Led = Assembly->Leds[LedIndex];
v4 Position = LED.Position;
v4 Position = Led.Position;
v4 ToFront = Position + FrontCenter;
v4 ToBack = Position + BackCenter;
@ -158,22 +150,22 @@ TestPatternTwo(assembly_led_buffer* Assembly, r32 Time)
{
if (XOR(ToFrontDotNormal > 0, ToBackDotNormal > 0))
{
Assembly->Colors[LED.Index] = Color;
Assembly->Colors[Led.Index] = Color;
}
else
{
//Assembly->Colors[LED.Index] = {};
//Assembly->Colors[Led.Index] = {};
}
}
else
{
//Assembly->Colors[LED.Index] = {};
//Assembly->Colors[Led.Index] = {};
}
}
}
internal void
TestPatternThree(assembly_led_buffer* Assembly, r32 Time)
TestPatternThree(led_buffer* Assembly, r32 Time)
{
v4 GreenCenter = v4{0, 0, 150, 1};
r32 GreenRadius = GSAbs(GSSin(Time)) * 200;
@ -184,25 +176,25 @@ TestPatternThree(assembly_led_buffer* Assembly, r32 Time)
r32 FadeDist = 35;
for (u32 LEDIdx = 0; LEDIdx < Assembly->LEDCount; LEDIdx++)
for (u32 LedIndex = 0; LedIndex < Assembly->LedCount; LedIndex++)
{
led LED = Assembly->LEDs[LEDIdx];
led Led = Assembly->Leds[LedIndex];
u8 Red = 0;
u8 Green = 0;
u8 Blue = 0;
r32 GreenDist = GSAbs(Mag(LED.Position - GreenCenter) - GreenRadius);
r32 GreenDist = GSAbs(Mag(Led.Position - GreenCenter) - GreenRadius);
r32 GreenBrightness = GSClamp(0.f, FadeDist - GSAbs(GreenDist), FadeDist);
Green = (u8)(GreenBrightness * 255);
r32 TealDist = GSAbs(Mag(LED.Position - TealCenter) - TealRadius);
r32 TealDist = GSAbs(Mag(Led.Position - TealCenter) - TealRadius);
r32 TealBrightness = GSClamp(0.f, FadeDist - GSAbs(TealDist), FadeDist);
Red = (u8)(TealBrightness * 255);
Blue = (u8)(TealBrightness * 255);
Assembly->Colors[LED.Index].R = Red;
Assembly->Colors[LED.Index].B = Green;
Assembly->Colors[LED.Index].G = Green;
Assembly->Colors[Led.Index].R = Red;
Assembly->Colors[Led.Index].B = Green;
Assembly->Colors[Led.Index].G = Green;
}
}

View File

@ -5,38 +5,106 @@
//
#ifndef FOLDHAUS_ASSEMBLY_CPP
internal void
ConstructAssemblyFromDefinition (assembly* Assembly, string AssemblyName, v4 RootPosition)
// Led System
internal led_system
LedSystemInitialize(platform_memory_handler PlatformMemory, u32 BuffersMax)
{
Assembly->LEDBuffer.LEDCount = 0;
Assembly->LEDBuffer.Colors = PushArray(&Assembly->Arena, pixel, Assembly->LedCountTotal);
Assembly->LEDBuffer.LEDs = PushArray(&Assembly->Arena, led, Assembly->LedCountTotal);
Assembly->LEDUniverseMapCount = Assembly->LedCountTotal;
Assembly->LEDUniverseMap = PushArray(&Assembly->Arena, leds_in_universe_range, Assembly->LedCountTotal);
led_system Result = {};
Result.PlatformMemory = PlatformMemory;
// TODO(Peter): Since we have access to PlatformMemory, just realloc Buffers when we fill it up
Result.BuffersCountMax = BuffersMax;
Result.Buffers = PlatformAllocArray(PlatformMemory, led_buffer, Result.BuffersCountMax);
return Result;
}
internal u32
LedSystemTakeFreeBuffer(led_system* System, u32 LedCount)
{
s32 Result = -1;
// Add LEDs
if (System->BuffersCount < System->BuffersCountMax)
{
Result = System->BuffersCount++;
}
else
{
// NOTE(Peter): Look for a buffer that's flagged as empty
for (u32 i = 0; i < System->BuffersCount; i++)
{
if (System->Buffers[i].LedCount == 0
&& System->Buffers[i].Colors == 0
&& System->Buffers[i].Leds == 0)
{
Result = i;
break;
}
}
Assert(Result >= 0); // NOTE(Peter): We ran out of room for led buffers
}
led_buffer* Buffer = &System->Buffers[Result];
Buffer->LedCount = LedCount;
Buffer->Colors = PlatformAllocArray(System->PlatformMemory, pixel, Buffer->LedCount);
Buffer->Leds = PlatformAllocArray(System->PlatformMemory, led, Buffer->LedCount);
System->LedsCountTotal += LedCount;
return (u32)Result;
}
internal void
LedSystemFreeBuffer(led_system* System, u32 BufferIndex)
{
Assert(BufferIndex < System->BuffersCountMax);
led_buffer* Buffer = &System->Buffers[BufferIndex];
PlatformFreeArray(System->PlatformMemory, Buffer->Colors, pixel, Buffer->LedCount);
PlatformFreeArray(System->PlatformMemory, Buffer->Leds, led, Buffer->LedCount);
System->LedsCountTotal -= Buffer->LedCount;
*Buffer = {};
}
internal led_buffer*
LedSystemGetBuffer(led_system* System, u32 Index)
{
led_buffer* Result = &System->Buffers[Index];
return Result;
}
internal void
LedBufferSetLed(led_buffer* Buffer, u32 Led, v4 Position)
{
Assert(Led < Buffer->LedCount);
Buffer->Leds[Led].Position = Position;
Buffer->Leds[Led].Index = Led;
}
// Assembly
internal void
ConstructAssemblyFromDefinition (assembly* Assembly, string AssemblyName, v4 RootPosition, led_system* LedSystem)
{
Assembly->LedBufferIndex = LedSystemTakeFreeBuffer(LedSystem, Assembly->LedCountTotal);
led_buffer* LedBuffer = LedSystemGetBuffer(LedSystem, Assembly->LedBufferIndex);
// Add Leds
u32 LedsAdded = 0;
for (u32 StripIdx = 0; StripIdx < Assembly->StripCount; StripIdx++)
{
//led_strip_definition StripDef = Definition.LEDStrips[StripIdx];
//led_strip_definition StripDef = Definition.LedStrips[StripIdx];
v2_strip* StripAt = &Assembly->Strips[StripIdx];
leds_in_universe_range* LEDUniverseRange = &Assembly->LEDUniverseMap[StripIdx];
LEDUniverseRange->Universe = StripAt->StartUniverse;
LEDUniverseRange->RangeStart = Assembly->LEDBuffer.LEDCount;
LEDUniverseRange->RangeOnePastLast = Assembly->LEDBuffer.LEDCount + StripAt->LedCount;
StripAt->LedLUT = PushArray(&Assembly->Arena, u32, StripAt->LedCount);
v4 WS_StripStart = RootPosition + V4(StripAt->StartPosition * Assembly->Scale, 1);
v4 WS_StripEnd = RootPosition + V4(StripAt->EndPosition * Assembly->Scale, 1);
s32 LEDsInStripCount = StripAt->LedCount;
v4 SingleStep = (WS_StripEnd - WS_StripStart) / (r32)LEDsInStripCount;
for (s32 Step = 0; Step < LEDsInStripCount; Step++)
v4 SingleStep = (WS_StripEnd - WS_StripStart) / (r32)StripAt->LedCount;
for (u32 Step = 0; Step < StripAt->LedCount; Step++)
{
s32 LEDIndex = Assembly->LEDBuffer.LEDCount;
Assembly->LEDBuffer.LEDs[LEDIndex].Position = WS_StripStart + (SingleStep * Step);
Assembly->LEDBuffer.LEDs[LEDIndex].Index = LEDIndex;
Assembly->LEDBuffer.LEDCount += 1;
s32 LedIndex = LedsAdded++;
v4 LedPosition = WS_StripStart + (SingleStep * Step);
LedBufferSetLed(LedBuffer, LedIndex, LedPosition);
StripAt->LedLUT[Step] = LedIndex;
}
}
}
@ -47,30 +115,33 @@ ConstructAssemblyFromDefinition (assembly* Assembly, string AssemblyName, v4 Roo
static v4 TempAssemblyOffsets[] = { v4{0, 0, 0, 0}, v4{250, 0, 75, 0}, v4{-250, 0, 75, 0} };
s32 TempAssemblyOffsetsCount = 3;
// TODO(Peter): Don't reference State, pull back to the Led buffer and Assembly Array
internal void
LoadAssembly (app_state* State, context Context, string Path)
{
platform_memory_result AssemblyFile = ReadEntireFile(Context, Path);
if (AssemblyFile.Error == PlatformMemory_NoError)
if (AssemblyFile.Error == PlatformMemory_NoError && AssemblyFile.Size > 0)
{
string AssemblyFileText = MakeString((char*)AssemblyFile.Base);
Assert(State->Assemblies.Count < State->Assemblies.CountMax);
assembly* NewAssembly = &State->Assemblies.Values[State->Assemblies.Count++];
s32 IndexOfLastSlash = FastLastIndexOfCharInCharArray(Path.Memory, Path.Length, '\\');
string FileName = Substring(Path, IndexOfLastSlash + 1);
assembly NewAssembly = {};
NewAssembly.Arena.Alloc = (gs_memory_alloc*)Context.PlatformAlloc;
NewAssembly.Arena.Realloc = (gs_memory_realloc*)Context.PlatformRealloc;
ParseAssemblyFile(&NewAssembly, AssemblyFileText, &State->Transient);
v4 Offset = TempAssemblyOffsets[State->ActiveAssemblyIndecies.Used % TempAssemblyOffsetsCount];
ConstructAssemblyFromDefinition(&NewAssembly, FileName, Offset);
gs_list_handle NewAssemblyHandle = State->AssemblyList.PushElementOnList(NewAssembly);
State->ActiveAssemblyIndecies.PushElementOnList(NewAssemblyHandle);
State->TotalLEDsCount += NewAssembly.LEDBuffer.LEDCount;
Context.PlatformFree(AssemblyFile.Base, AssemblyFile.Size);
NewAssembly->Arena.PlatformMemory = Context.PlatformMemory;
if (ParseAssemblyFile(NewAssembly, AssemblyFileText, &State->Transient))
{
v4 Offset = TempAssemblyOffsets[State->Assemblies.Count % TempAssemblyOffsetsCount];
ConstructAssemblyFromDefinition(NewAssembly, FileName, Offset, &State->LedSystem);
PlatformFree(Context.PlatformMemory, AssemblyFile.Base, AssemblyFile.Size);
}
else
{
FreeMemoryArena(&NewAssembly->Arena);
State->Assemblies.Count -= 1;
}
}
else
{
@ -81,20 +152,12 @@ LoadAssembly (app_state* State, context Context, string Path)
internal void
UnloadAssembly (u32 AssemblyIndex, app_state* State, context Context)
{
assembly* Assembly = State->AssemblyList.GetElementAtIndex(AssemblyIndex);
State->TotalLEDsCount -= Assembly->LEDBuffer.LEDCount;
FreeMemoryArena(&Assembly->Arena, (gs_memory_free*)Context.PlatformFree);
State->AssemblyList.FreeElementAtIndex(AssemblyIndex);
for (u32 i = 0; i < State->ActiveAssemblyIndecies.Used; i++)
{
gs_list_handle Handle = *State->ActiveAssemblyIndecies.GetElementAtIndex(i);
if (Handle.Index == AssemblyIndex)
{
State->ActiveAssemblyIndecies.FreeElementAtIndex(i);
break;
}
}
Assert(AssemblyIndex < State->Assemblies.Count);
assembly* Assembly = &State->Assemblies.Values[AssemblyIndex];
LedSystemFreeBuffer(&State->LedSystem, Assembly->LedBufferIndex);
FreeMemoryArena(&Assembly->Arena);
u32 LastAssemblyIndex = --State->Assemblies.Count;
State->Assemblies.Values[AssemblyIndex] = State->Assemblies.Values[LastAssemblyIndex];
}

View File

@ -7,6 +7,7 @@
struct led
{
// TODO(Peter): Pretty sure we don't need this. led and pixel are always parallel arrays
s32 Index;
v4 Position;
};
@ -22,22 +23,22 @@ union pixel
u8 Channels[3];
};
// NOTE(Peter): This structure is so we can keep track of
// what LEDs output to which DMX universe. You don't need
// to use it anywhere else, as all the data for patterns,
// colors, and groups is/will be stored elsewhere.
struct leds_in_universe_range
struct led_buffer
{
s32 RangeStart;
s32 RangeOnePastLast;
s32 Universe;
u32 LedCount;
pixel* Colors;
led* Leds;
};
struct assembly_led_buffer
struct led_system
{
u32 LEDCount;
pixel* Colors;
led* LEDs;
platform_memory_handler PlatformMemory;
u32 BuffersCountMax;
u32 BuffersCount;
led_buffer* Buffers;
u32 LedsCountTotal;
};
struct v2_tag
@ -49,6 +50,7 @@ struct v2_tag
struct v2_strip
{
s32 ControlBoxID; // TODO(Peter): I don't think we need this anymore
// TODO(Peter): Add in info for Serial, ArtNet, etc.
s32 StartUniverse;
s32 StartChannel;
@ -72,17 +74,19 @@ struct assembly
string FilePath;
r32 Scale;
s32 LedCountTotal;
u32 LedBufferIndex;
u32 StripCount;
v2_strip* Strips;
s32 LedCountTotal;
assembly_led_buffer LEDBuffer;
u32 LEDUniverseMapCount;
leds_in_universe_range* LEDUniverseMap;
};
struct assembly_array
{
u32 CountMax;
u32 Count;
assembly* Values;
};
#define FOLDHAUS_ASSEMBLY_H
#endif // FOLDHAUS_ASSEMBLY_H

View File

@ -88,15 +88,6 @@ struct system_path
s32 IndexOfLastSlash;
};
#define PLATFORM_ALLOC(name) u8* name(s32 Size)
typedef PLATFORM_ALLOC(platform_alloc);
#define PLATFORM_FREE(name) b32 name(u8* Base, s32 Size)
typedef PLATFORM_FREE(platform_free);
#define PLATFORM_REALLOC(name) u8* name(u8* Base, u32 OldSize, u32 NewSize)
typedef PLATFORM_REALLOC(platform_realloc);
#define PLATFORM_READ_ENTIRE_FILE(name) platform_memory_result name(string Path)
typedef PLATFORM_READ_ENTIRE_FILE(platform_read_entire_file);
@ -264,10 +255,7 @@ struct context
// Platform Services
work_queue* GeneralWorkQueue;
platform_alloc* PlatformAlloc;
platform_free* PlatformFree;
platform_realloc* PlatformRealloc;
platform_memory_handler PlatformMemory;
platform_file_handler FileHandler;
platform_write_entire_file* PlatformWriteEntireFile;

View File

@ -37,14 +37,14 @@ HierarchyView_Render(panel Panel, rect PanelBounds, render_command_buffer* Rende
u32 LineCount = (u32)(gs_Height(PanelBounds) / Layout.RowHeight) + 1;
u32 LinesDrawn = 0;
u32 AssembliesToDraw = GSMin(LineCount, State->ActiveAssemblyIndecies.Used);
for (; LinesDrawn < AssembliesToDraw; LinesDrawn++)
u32 AssembliesToDraw = GSMin(LineCount, State->Assemblies.Count);
for (u32 AssemblyIndex = 0; AssemblyIndex < AssembliesToDraw; AssemblyIndex++)
{
rect Bounds = ui_ReserveElementBounds(&Layout);
v4 ListItemBGColor = ui_GetListItemBGColor(State->Interface_.Style, LinesDrawn);
v4 ListItemBGColor = ui_GetListItemBGColor(State->Interface_.Style, AssemblyIndex);
ui_FillRect(&State->Interface_, Bounds, ListItemBGColor);
gs_list_handle AssemblyHandle = *State->ActiveAssemblyIndecies.GetElementAtIndex(LinesDrawn);
assembly Assembly = *State->AssemblyList.GetElementWithHandle(AssemblyHandle);
assembly Assembly = State->Assemblies.Values[AssemblyIndex];
PrintF(&TempString, "%S", Assembly.Name);
ui_layout ItemLayout = ui_CreateLayout(State->Interface_, Bounds);
@ -53,10 +53,12 @@ HierarchyView_Render(panel Panel, rect PanelBounds, render_command_buffer* Rende
ui_LayoutDrawString(&State->Interface_, &ItemLayout, TempString, State->Interface_.Style.TextColor);
if (ui_LayoutButton(&State->Interface_, &ItemLayout, MakeStringLiteral("X"), ListItemBGColor, ListItemHover, ListItemSelected))
{
UnloadAssembly(AssemblyHandle.Index, State, Context);
UnloadAssembly(AssemblyIndex, State, Context);
}
}
ui_EndRow(&ItemLayout);
LinesDrawn += 1;
}
if (LinesDrawn < LineCount)

View File

@ -54,7 +54,7 @@ global_variable s32 SculptureView_CommandsCount = 1;
GSMetaTag(panel_init);
GSMetaTag(panel_type_sculpture_view);
internal void
internal void
SculptureView_Init(panel* Panel, app_state* State)
{
@ -62,7 +62,7 @@ SculptureView_Init(panel* Panel, app_state* State)
GSMetaTag(panel_cleanup);
GSMetaTag(panel_type_sculpture_view);
internal void
internal void
SculptureView_Cleanup(panel* Panel, app_state* State)
{
@ -133,7 +133,7 @@ DrawLEDsInBufferRangeJob (s32 ThreadID, void* JobData)
GSMetaTag(panel_render);
GSMetaTag(panel_type_sculpture_view);
internal void
internal void
SculptureView_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context, mouse_state Mouse)
{
DEBUG_TRACK_SCOPE(RenderSculpture);
@ -154,21 +154,21 @@ SculptureView_Render(panel Panel, rect PanelBounds, render_command_buffer* Rende
FaceCameraMatrix = FaceCameraMatrix;
u32 MaxLEDsPerJob = 2048;
render_quad_batch_constructor RenderLEDsBatch = PushRenderQuad3DBatch(RenderBuffer, State->TotalLEDsCount);
render_quad_batch_constructor RenderLEDsBatch = PushRenderQuad3DBatch(RenderBuffer, State->LedSystem.LedsCountTotal);
for (u32 i = 0; i < State->ActiveAssemblyIndecies.Used; i++)
for (u32 i = 0; i < State->Assemblies.Count; i++)
{
gs_list_handle AssemblyHandle = *State->ActiveAssemblyIndecies.GetElementAtIndex(i);
assembly Assembly = *State->AssemblyList.GetElementWithHandle(AssemblyHandle);
u32 JobsNeeded = IntegerDivideRoundUp(Assembly.LEDBuffer.LEDCount, MaxLEDsPerJob);
assembly Assembly = State->Assemblies.Values[i];
led_buffer* LedBuffer = LedSystemGetBuffer(&State->LedSystem, Assembly.LedBufferIndex);
u32 JobsNeeded = IntegerDivideRoundUp(LedBuffer->LedCount, MaxLEDsPerJob);
for (u32 Job = 0; Job < JobsNeeded; Job++)
{
draw_leds_job_data* JobData = PushStruct(&State->Transient, draw_leds_job_data);
JobData->LEDs = Assembly.LEDBuffer.LEDs;
JobData->Colors = Assembly.LEDBuffer.Colors;
JobData->LEDs = LedBuffer->Leds;
JobData->Colors = LedBuffer->Colors;
JobData->StartIndex = Job * MaxLEDsPerJob;
JobData->OnePastLastIndex = GSMin(JobData->StartIndex + MaxLEDsPerJob, Assembly.LEDBuffer.LEDCount);
JobData->OnePastLastIndex = GSMin(JobData->StartIndex + MaxLEDsPerJob, LedBuffer->LedCount);
JobData->Batch = &RenderLEDsBatch;
JobData->FaceCameraMatrix;
JobData->ModelViewMatrix = ModelViewMatrix;

View File

@ -663,9 +663,9 @@ WinMain (
// Platform functions
Context.GeneralWorkQueue = &WorkQueue;
Context.PlatformAlloc = Win32Alloc;
Context.PlatformFree = Win32Free;
Context.PlatformRealloc = Win32Realloc;
Context.PlatformMemory.Alloc = Win32Alloc;
Context.PlatformMemory.Free = Win32Free;
Context.PlatformMemory.Realloc = Win32Realloc;
Context.FileHandler.ReadEntireFile = Win32ReadEntireFile;
Context.FileHandler.WriteEntireFile = Win32WriteEntireFile;
Context.FileHandler.GetFilePath = Win32SystemDialogueOpenFile;

View File

@ -133,6 +133,8 @@ PLATFORM_GET_FILE_PATH(Win32SystemDialogueOpenFile)
Result = GetOpenFileNameA (&OpenFileName);
PathBuffer->Length = CharArrayLength(PathBuffer->Memory);
return Result;
}

View File

@ -2,8 +2,8 @@
// Description: Single header file library that defines a push-only memory arena
// Author: Peter Slattery
// Date Created: 2019-12-22
//
//
//
//
// -----------------
// Set Up
// -----------------
@ -16,26 +16,26 @@
// Simply create a memory_arena and use PushSize, PushStruct, or PushArray
// to allocate out of it.
// See Example Program below.
//
//
// While there are options you can set (see Options below), the library adheres
// to a 'zero-is-initialization' policy, that is, a memory_arena initialized to
// zero, under all default options, will 'just work'.
// zero, under all default options, will 'just work'.
//
// Alignment:
// By default, the Push functions use 4 byte alignment
// If you need to control the alignment of an allocation, there are variants of the
// If you need to control the alignment of an allocation, there are variants of the
// Push functions that allow for this: PushSizeAligned, PushStructAligned, and PushArrayAligned
// These functions simply take a final parameter which specifies the alignment.
// These functions simply take a final parameter which specifies the alignment.
// Note: Alignment must be a power of two
//
// -----------------
// Options
// -----------------
//
// DEBUG:
//
// DEBUG:
// Define DEBUG for debug functionality.
//
// To override the default assert function define GSMem_Assert(expression)
//
// To override the default assert function define GSMem_Assert(expression)
// before inluding this file.
//
// GS_MEMORY_NO_STD_LIBS:
@ -61,8 +61,8 @@
// this file
//
// GS_MEMORY_TRACK_ALLOCATIONS:
// If you want to keep records of each allocation performed in every arena, define
// GS_MEMORY_TRACK_ALLOCATIONS before including this file.
// If you want to keep records of each allocation performed in every arena, define
// GS_MEMORY_TRACK_ALLOCATIONS before including this file.
// When defined, memory arenas gain fields that allow them to keep a list of every
// allocation they contain. It also adds a footer on the end of each allocation that
// can be checked to ensure there are no writes to allocations that overflow their bounds
@ -78,8 +78,8 @@
// Places the characters 'gs' at the end of each allocation. This would allow for an external
// function to check that we haven't written past the end of an allocation
void* MallocWrapper(gs_mem_u32 Size)
{
void* MallocWrapper(gs_mem_u32 Size)
{
int SizeWithFooter = Size + (sizeof(char) * 2);
void* Result = malloc(SizeWithFooter);
char* Footer = (char*)(Result + Size);
@ -88,17 +88,17 @@ void* MallocWrapper(gs_mem_u32 Size)
return Result;
}
void* ReallocWrapper(void* Address, gs_mem_u32 Size)
{
return realloc(Address, Size);
void* ReallocWrapper(void* Address, gs_mem_u32 Size)
{
return realloc(Address, Size);
}
int
int
main(int ArgCount, char** Args)
{
memory_arena Arena = {};
// Uncomment these lines for an example of how you can implement custom allocation functions
// Arena.Alloc = MallocWrapper;
// Arena.Alloc = MallocWrapper;
// Arena.Realloc = ReallocWrapper;
int ArrayLength = 10;
@ -139,9 +139,9 @@ main(int ArgCount, char** Args)
#ifndef GS_MEMORY_NO_STD_LIBS
// NOTE(Peter): We use this so that we can fall back on malloc and realloc
// in the event that a memory_arena needs to grow but doesn't have a
// in the event that a memory_arena needs to grow but doesn't have a
// alloc or realloc function pointer assigned to it.
//
//
// See GrowArena to see where this is used
//
#include <stdlib.h>
@ -177,13 +177,13 @@ enum gs_memory_expansion_rule
// NOTE(Peter):
// This rule is only here to allow for taking arena snapshots. The problem this solves
// is if you take a snapshot while there are 'holes' in memory_buffers behind the
// is if you take a snapshot while there are 'holes' in memory_buffers behind the
// most recently added memory_buffer, take a snapshot of that arena, then push something
// on that fits in one of those holes, we will fill the hole and be unable to track/free
// that addition via the snapshot construct.
// that addition via the snapshot construct.
//
// By requiring that allocations in a buffer only come from the most recent memory_buffer
// we can very easily rewind the buffer to the correct location.
// we can very easily rewind the buffer to the correct location.
// Hence FindAddress_InLastBufferOnly
enum gs_memory_find_address_rule
{
@ -192,9 +192,21 @@ enum gs_memory_find_address_rule
FindAddress_Count,
};
typedef void* gs_memory_alloc(gs_mem_u32 Size);
typedef void* gs_memory_realloc(void* Address, gs_mem_u32 OldSize, gs_mem_u32 NewSize);
typedef void gs_memory_free(void* Address, gs_mem_u32 Size);
#define PLATFORM_ALLOC(name) u8* name(s32 Size)
typedef PLATFORM_ALLOC(platform_alloc);
#define PLATFORM_FREE(name) b32 name(u8* Base, s32 Size)
typedef PLATFORM_FREE(platform_free);
#define PLATFORM_REALLOC(name) u8* name(u8* Base, u32 OldSize, u32 NewSize)
typedef PLATFORM_REALLOC(platform_realloc);
struct platform_memory_handler
{
platform_alloc* Alloc;
platform_free* Free;
platform_realloc* Realloc;
};
#ifndef GS_MEMORY_BUFFER_SIZE
#define GS_MEMORY_BUFFER_SIZE 1024
@ -237,8 +249,8 @@ struct memory_arena
gs_memory_find_address_rule FindAddressRule;
gs_memory_expansion_rule ExpansionRule;
gs_memory_alloc* Alloc;
gs_memory_realloc* Realloc;
platform_memory_handler PlatformMemory;
#ifdef GS_MEMORY_TRACK_ALLOCATIONS
tracked_allocation_buffer** AllocationBuffers;
@ -266,31 +278,62 @@ struct arena_snapshot
#endif
};
#define PlatformFreeArray(platform, base, type, count) PlatformFree((platform), (gs_mem_u8*)(base), sizeof(type) * (count))
#define ArenaFree(arena, base, size) PlatformFree((arena).PlatformMemory, (gs_mem_u8*)(base), (gs_mem_u32)(size))
static void
FreeMemoryArena(memory_arena* Arena, gs_memory_free* Free = 0)
PlatformFree(platform_memory_handler Platform, gs_mem_u8* Base, gs_mem_u32 Size)
{
if (Free)
Assert(Platform.Free != 0);
Platform.Free(Base, Size);
}
#define PlatformAllocArray(platform, type, size) (type*)PlatformAlloc((platform), sizeof(type) * (size))
#define ArenaAlloc(arena, size) PlatformAlloc((arena).PlatformMemory, (gs_mem_u32)(size))
#define ArenaAllocStruct(arena, type) (type*)PlatformAlloc((arena).PlatformMemory, sizeof(type))
#define ArenaAllocArray(arena, type, size) (type*)PlatformAlloc((arena).PlatformMemory, sizeof(type) * (size))
static gs_mem_u8*
PlatformAlloc(platform_memory_handler Platform, gs_mem_u32 Size)
{
Assert(Platform.Alloc != 0);
gs_mem_u8* Result = Platform.Alloc(Size);
return Result;
}
#define ArenaRealloc(arena, base, oldSize, newSize) PlatformRealloc((arena).PlatformMemory, (gs_mem_u8*)(base), (gs_mem_u32)(oldSize), (gs_mem_u32)(newSize))
#define ArenaReallocArray(arena, base, type, oldCount, newCount) (type*)PlatformRealloc((arena).PlatformMemory, (gs_mem_u8*)(base), sizeof(type) * oldCount, sizeof(type) * newCount)
static gs_mem_u8*
PlatformRealloc(platform_memory_handler Platform, gs_mem_u8* Head, gs_mem_u32 OldSize, gs_mem_u32 NewSize)
{
gs_mem_u8* Result = 0;
if (Platform.Realloc != 0)
{
for (gs_mem_u32 i = 0; i < Arena->BuffersCount; i++)
Result = Platform.Realloc(Head, OldSize, NewSize);
}
else if (Platform.Alloc != 0 && Platform.Free != 0)
{
Result = PlatformAlloc(Platform, NewSize);
if (Head != 0 && OldSize != 0)
{
memory_buffer* Buffer = Arena->Buffers + i;
Free(Buffer->Buffer, Buffer->Size);
GSMemCopy(Head, Result, OldSize);
PlatformFree(Platform, Head, OldSize);
}
Free(Arena->Buffers, sizeof(memory_buffer) * Arena->BuffersCount);
}
else
{
#ifdef GS_MEMORY_NO_STD_LIBS
GSMem_Assert(0);
#else
for (gs_mem_u32 i = 0; i < Arena->BuffersCount; i++)
{
memory_buffer* Buffer = Arena->Buffers + i;
free(Buffer->Buffer);
}
free(Arena->Buffers);
#endif
InvalidCodePath;
}
return Result;
}
static void
FreeMemoryArena(memory_arena* Arena)
{
for (gs_mem_u32 i = 0; i < Arena->BuffersCount; i++)
{
memory_buffer* Buffer = Arena->Buffers + i;
PlatformFree(Arena->PlatformMemory, Buffer->Buffer, Buffer->Size);
}
PlatformFree(Arena->PlatformMemory, (u8*)Arena->Buffers, sizeof(memory_buffer) * Arena->BuffersCount);
}
#define IsPowerOfTwo(v) ((v != 0) && ((v & (v - 1)) == 0))
@ -340,53 +383,7 @@ FindAlignedAddressInBufferWithRoom(memory_arena* Arena, gs_mem_u32 Size, gs_mem_
Result = AddressInCurrentBuffer;
break;
}
}
return Result;
}
static gs_mem_u8*
ArenaAlloc(memory_arena* Arena, gs_mem_u32 Size)
{
gs_mem_u8* Result = 0;
if (Arena->Alloc)
{
Result = (gs_mem_u8*)Arena->Alloc(sizeof(gs_mem_u8) * Size);
}
else
{
#ifdef GS_MEMORY_NO_STD_LIBS
// NOTE(Peter): If you specify no std libs AND don't supply a allocation function
// we should assert as this is an invalid codepath
GSMem_Assert(0);
#else
Result = (gs_mem_u8*)malloc(sizeof(gs_mem_u8) * Size);
#endif
}
return Result;
}
static gs_mem_u8*
ArenaRealloc(memory_arena* Arena, gs_mem_u8* Head, gs_mem_u32 OldSize, gs_mem_u32 NewSize)
{
gs_mem_u8* Result = 0;
if (Arena->Realloc != 0)
{
Result = (gs_mem_u8*)Arena->Realloc(Head, OldSize, NewSize);
}
else
{
#ifdef GS_MEMORY_NO_STD_LIBS
// NOTE(Peter): If you specify no std libs AND don't supply a reallocation function
// we should assert as this is an invalid codepath
GSMem_Assert(0);
#else
Result = (gs_mem_u8*)realloc(Head, NewSize);
#endif
}
return Result;
}
@ -394,15 +391,13 @@ static memory_buffer*
GrowArena(memory_arena* Arena, gs_mem_u32 SizeNeeded)
{
GSMem_Assert(Arena->ExpansionRule != MemoryExpansion_Disallowed);
if (Arena->ExpansionRule == MemoryExpansion_OnlyIfFunctionsProvided)
{
GSMem_Assert((Arena->Alloc != 0) && (Arena->Realloc != 0));
}
gs_mem_u32 NewBuffersCount = (Arena->BuffersCount + 1);
#if 0
gs_mem_u32 OldBuffersSize = sizeof(memory_buffer) * Arena->BuffersCount;
gs_mem_u32 NewBuffersSize = sizeof(memory_buffer) * NewBuffersCount;
Arena->Buffers = (memory_buffer*)ArenaRealloc(Arena, (gs_mem_u8*)Arena->Buffers, OldBuffersSize, NewBuffersSize);
#endif
Arena->Buffers = ArenaReallocArray(*Arena, Arena->Buffers, memory_buffer, Arena->BuffersCount, NewBuffersCount);
Arena->BuffersCount = NewBuffersCount;
memory_buffer* NewBuffer = Arena->Buffers + (Arena->BuffersCount - 1);
@ -412,7 +407,7 @@ GrowArena(memory_arena* Arena, gs_mem_u32 SizeNeeded)
NewBuffer->Size = SizeNeeded;
}
NewBuffer->Buffer = ArenaAlloc(Arena, sizeof(gs_mem_u8) * NewBuffer->Size);
NewBuffer->Buffer = ArenaAllocArray(*Arena, gs_mem_u8, NewBuffer->Size);
NewBuffer->Used = 0;
Arena->TotalSize += NewBuffer->Size;
@ -433,14 +428,20 @@ TrackAllocation(memory_arena* Arena, gs_mem_u8* Head, gs_mem_u32 Size, char* Fil
if (Arena->AllocationsUsed >= AllocationsMax)
{
gs_mem_u32 NewAllocationBuffersCount = Arena->AllocationBuffersCount + 1;
Arena->AllocationBuffers = (tracked_allocation_buffer**)ArenaRealloc(Arena,
(gs_mem_u8*)Arena->AllocationBuffers,
Arena->AllocationBuffersCount * sizeof(void*),
NewAllocationBuffersCount * sizeof(void*));
#if 0
gs_mem_u32 OldSize = Arena->AllocationBuffersCount * sizeof(void*);
gs_mem_u32 NewSize = NewAllocationBuffersCount * sizeof(void*);
Arena->AllocationBuffers = (tracked_allocation_buffer**)PlatformRealloc(Arena->PlatformMemory,
(gs_mem_u8*)Arena->AllocationBuffers,
OldSize, NewSize);
#else
Arena->AllocationBuffers = ArenaReallocArray(*Arena, Arena->AllocationBuffers, tracked_allocation_buffer*, Arena->AllocationBuffersCount, NewAllocationBuffersCount);
#endif
Arena->AllocationBuffersCount = NewAllocationBuffersCount;
gs_mem_u32 NewBufferIndex = Arena->AllocationBuffersCount - 1;
Arena->AllocationBuffers[NewBufferIndex] = (tracked_allocation_buffer*)ArenaAlloc(Arena, sizeof(tracked_allocation_buffer));
Arena->AllocationBuffers[NewBufferIndex] = ArenaAllocStruct(*Arena, tracked_allocation_buffer);
}
gs_mem_u32 AllocationIndex = Arena->AllocationsUsed++;
@ -474,8 +475,8 @@ VerifyAllocationNoOverflow (tracked_allocation Allocation)
static void
AssertAllocationsNoOverflow (memory_arena Arena)
{
for (gs_mem_u32 AllocationIndex = 0;
AllocationIndex< Arena.AllocationsUsed;
for (gs_mem_u32 AllocationIndex = 0;
AllocationIndex< Arena.AllocationsUsed;
AllocationIndex++)
{
gs_mem_u32 BufferIndex = AllocationIndex / GS_MEM_TRACKED_ALLOCATION_BUFFER_SIZE;
@ -502,7 +503,7 @@ AssertAllocationsNoOverflow (memory_arena Arena)
#define ClearAllocationsUsed(arena)
#define ClearAllocationsUsedToSnapshot(arena, snapshot)
#define TrackAllocation(arena, head, size, filename, linenumber)
#define TrackAllocation(arena, head, size, filename, linenumber)
#define PushSize(arena, size) PushSize_((arena), (size))
#define PushArray(arena, type, length) (type*)PushSize_((arena), sizeof(type) * length)
@ -517,7 +518,7 @@ static gs_mem_u8*
PushSize_(memory_arena* Arena, gs_mem_u32 Size, gs_mem_u32 Alignment = 4, char* Filename = 0, gs_mem_u32 LineNumber = 0)
{
// ie. Alignment = 4 = 100 (binary)
// 4 - 1 = 3
// 4 - 1 = 3
// 100 - 1 = 011 which is a mask of the bits we don't want set in the start address
GSMem_Assert(IsPowerOfTwo(Alignment));
gs_mem_u32 AlignmentMask = Alignment - 1;
@ -560,7 +561,7 @@ ClearArena(memory_arena* Arena)
{
memory_buffer* At = Arena->Buffers + i;
At->Used = 0;
}
}
Arena->TotalUsed = 0;
ClearAllocationsUsed(Arena);