diff --git a/src/app/animation/foldhaus_animation.h b/src/app/animation/foldhaus_animation.h index c5b0434..a63e3d1 100644 --- a/src/app/animation/foldhaus_animation.h +++ b/src/app/animation/foldhaus_animation.h @@ -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 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; diff --git a/src/app/assembly_parser.cpp b/src/app/assembly_parser.cpp index 5b6605a..4b06fc7 100644 --- a/src/app/assembly_parser.cpp +++ b/src/app/assembly_parser.cpp @@ -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 diff --git a/src/app/foldhaus_app.cpp b/src/app/foldhaus_app.cpp index 5684f52..afb801e 100644 --- a/src/app/foldhaus_app.cpp +++ b/src/app/foldhaus_app.cpp @@ -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); } } diff --git a/src/app/foldhaus_app.h b/src/app/foldhaus_app.h index 7a29134..0e08eb1 100644 --- a/src/app/foldhaus_app.h +++ b/src/app/foldhaus_app.h @@ -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 AssemblyList; - gs_list 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; } } diff --git a/src/app/foldhaus_assembly.cpp b/src/app/foldhaus_assembly.cpp index dd9223e..da5841e 100644 --- a/src/app/foldhaus_assembly.cpp +++ b/src/app/foldhaus_assembly.cpp @@ -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]; } diff --git a/src/app/foldhaus_assembly.h b/src/app/foldhaus_assembly.h index e414e7a..68c4f24 100644 --- a/src/app/foldhaus_assembly.h +++ b/src/app/foldhaus_assembly.h @@ -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 \ No newline at end of file diff --git a/src/app/foldhaus_platform.h b/src/app/foldhaus_platform.h index 725284b..93dfa64 100644 --- a/src/app/foldhaus_platform.h +++ b/src/app/foldhaus_platform.h @@ -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; diff --git a/src/app/panels/foldhaus_panel_hierarchy.h b/src/app/panels/foldhaus_panel_hierarchy.h index 7f27c94..c2d1ddb 100644 --- a/src/app/panels/foldhaus_panel_hierarchy.h +++ b/src/app/panels/foldhaus_panel_hierarchy.h @@ -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) diff --git a/src/app/panels/foldhaus_panel_sculpture_view.h b/src/app/panels/foldhaus_panel_sculpture_view.h index 880b2f8..4d239f3 100644 --- a/src/app/panels/foldhaus_panel_sculpture_view.h +++ b/src/app/panels/foldhaus_panel_sculpture_view.h @@ -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; diff --git a/src/app/win32_foldhaus.cpp b/src/app/win32_foldhaus.cpp index 3155e6b..88ff2d9 100644 --- a/src/app/win32_foldhaus.cpp +++ b/src/app/win32_foldhaus.cpp @@ -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; diff --git a/src/app/win32_foldhaus_fileio.h b/src/app/win32_foldhaus_fileio.h index 3a9a9aa..2240dbc 100644 --- a/src/app/win32_foldhaus_fileio.h +++ b/src/app/win32_foldhaus_fileio.h @@ -133,6 +133,8 @@ PLATFORM_GET_FILE_PATH(Win32SystemDialogueOpenFile) Result = GetOpenFileNameA (&OpenFileName); + PathBuffer->Length = CharArrayLength(PathBuffer->Memory); + return Result; } diff --git a/src/gs_libs/gs_memory_arena.h b/src/gs_libs/gs_memory_arena.h index 772d9e3..119656c 100644 --- a/src/gs_libs/gs_memory_arena.h +++ b/src/gs_libs/gs_memory_arena.h @@ -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 @@ -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);