Did an audit of the transient arena's usage, cleaned up the assembly parsing to control allocations, removed stb_truetype (again?) and fixed the memory problems the node system was having.

This commit is contained in:
Peter Slattery 2019-08-03 15:08:19 -07:00
parent 808453b867
commit 40d9e0b83e
8 changed files with 118 additions and 4918 deletions

View File

@ -77,7 +77,7 @@ ParseAssemblyVector (char* String)
}
internal void
ParseAssemblyFileHeader (tokenizer* Tokenizer, assembly_definition* Definition)
ParseAssemblyFileHeader (assembly_definition* Assembly, tokenizer* Tokenizer)
{
if (CharArraysEqualUpToLength(Tokenizer->At, LED_STRIP_COUNT_IDENTIFIER, CharArrayLength(LED_STRIP_COUNT_IDENTIFIER)))
{
@ -86,7 +86,7 @@ ParseAssemblyFileHeader (tokenizer* Tokenizer, assembly_definition* Definition)
assembly_token CountToken = ParseToken(Tokenizer);
if (CountToken.Type == AssemblyToken_Number)
{
Definition->LEDStripSize = ParseSignedIntUnsafe(CountToken.Token).SignedIntValue;
Assembly->LEDStripSize = ParseSignedIntUnsafe(CountToken.Token).SignedIntValue;
}
else
{
@ -103,9 +103,11 @@ ParseAssemblyFileHeader (tokenizer* Tokenizer, assembly_definition* Definition)
}
internal void
ParseLEDStrip (tokenizer* Tokenizer, assembly_definition* Assembly)
ParseLEDStrip (assembly_definition* Assembly, tokenizer* Tokenizer)
{
led_strip_definition* LEDStripDef = Assembly->LEDStrips + Assembly->LEDStripCount;
Assert(Assembly->LEDStripCount < Assembly->LEDStripSize);
Assembly->LEDStripCount++;
// Control Box Index
@ -163,24 +165,15 @@ ParseLEDStrip (tokenizer* Tokenizer, assembly_definition* Assembly)
EatWhitespace(Tokenizer);
}
internal assembly_definition
ParseAssemblyFile (char* File, memory_arena* Storage)
internal void
ParseAssemblyFileBody (assembly_definition* Assembly, tokenizer* Tokenizer)
{
assembly_definition Result = {};
EatWhitespace(Tokenizer);
tokenizer Tokenizer = {};
Tokenizer.At = File;
ParseAssemblyFileHeader(&Tokenizer, &Result);
Result.LEDStrips = PushArray(Storage, led_strip_definition,
Result.LEDStripSize);
EatWhitespace(&Tokenizer);
while(*Tokenizer.At)
while(*Tokenizer->At)
{
EatWhitespace(&Tokenizer);
assembly_token Token = ParseToken(&Tokenizer);
EatWhitespace(Tokenizer);
assembly_token Token = ParseToken(Tokenizer);
if (Token.Type != AssemblyToken_EndOfFile)
{
@ -188,13 +181,12 @@ ParseAssemblyFile (char* File, memory_arena* Storage)
{
case AssemblyToken_LEDStrip:
{
ParseLEDStrip(&Tokenizer, &Result);
ParseLEDStrip(Assembly, Tokenizer);
} break;
default:
{
InvalidCodePath;
} break;
// TODO(Peter): Other cases? What else would need to be in the assembly body?
InvalidDefaultCase;
}
}
else
@ -202,5 +194,9 @@ ParseAssemblyFile (char* File, memory_arena* Storage)
break;
}
}
return Result;
// NOTE(Peter): Ensure the validity of the assembly file. We probably don't want an assert here,
// more likely we want to load a valid assembly anyways, and just raise this as an error to the user
// so they can fix it.
Assert(Assembly->LEDStripCount == Assembly->LEDStripSize);
}

View File

@ -283,12 +283,24 @@ SendSACNBufferData (s32 ThreadID, void* JobData)
internal void
LoadAssembly (app_state* State, context Context, char* Path)
{
assembly_definition AssemblyDefinition = {};
arena_snapshot TempMemorySnapshot = TakeSnapshotOfArena(*State->Transient);
platform_memory_result TestAssemblyFile = Context.PlatformReadEntireFile(Path);
if (TestAssemblyFile.Size <= 0)
Assert(TestAssemblyFile.Size > 0);
{
InvalidCodePath;
tokenizer AssemblyFileTokenizer = {};
AssemblyFileTokenizer.At = (char*)TestAssemblyFile.Base;
AssemblyFileTokenizer.Memory = (char*)TestAssemblyFile.Base;
AssemblyFileTokenizer.MemoryLength = TestAssemblyFile.Size;
ParseAssemblyFileHeader(&AssemblyDefinition, &AssemblyFileTokenizer);
AssemblyDefinition.LEDStrips = PushArray(State->Transient, led_strip_definition, AssemblyDefinition.LEDStripSize);
ParseAssemblyFileBody(&AssemblyDefinition, &AssemblyFileTokenizer);
}
assembly_definition AssemblyDefinition = ParseAssemblyFile((char*)TestAssemblyFile.Base, State->Transient);
Context.PlatformFree(TestAssemblyFile.Base, TestAssemblyFile.Size);
string PathString = MakeStringLiteral(Path);
@ -297,6 +309,8 @@ LoadAssembly (app_state* State, context Context, char* Path)
r32 Scale = 100;
ConstructAssemblyFromDefinition(AssemblyDefinition, FileName, v3{0, 0, 0}, Scale, Context, State);
ClearArenaToSnapshot(State->Transient, TempMemorySnapshot);
}
internal void
@ -517,7 +531,7 @@ INITIALIZE_APPLICATION(InitializeApplication)
State->NodeRenderSettings.PortColors[MemberType_v4] = BlueV4;
State->NodeRenderSettings.Font = State->Font;
State->OutputNode = PushOutputNodeOnList(State->NodeList, v2{500, 250}, State->Transient);
State->OutputNode = PushOutputNodeOnList(State->NodeList, v2{500, 250}, State->Permanent);
ReloadStaticData(Context, GlobalDebugServices);
}
@ -526,6 +540,12 @@ UPDATE_AND_RENDER(UpdateAndRender)
{
app_state* State = (app_state*)Context.MemoryBase;
// NOTE(Peter): We do this at the beginning because all the render commands are stored in Transient,
// and need to persist beyond the end of the UpdateAndRender call. In the release version, we won't
// zero the Transient arena when we clear it so it wouldn't be a problem, but it is technically
// incorrect to clear the arena, and then access the memory later.
ClearArena(State->Transient);
ExecuteAllRegisteredCommands(&State->InputCommandRegistry, Input, State);
UpdateOutputNodeCalculations(State->OutputNode, State->NodeList, State->Transient,
@ -533,13 +553,7 @@ UPDATE_AND_RENDER(UpdateAndRender)
State->LEDBufferList->Colors,
State->LEDBufferList->Count);
/*
patterns_update_list Temp_PatternsNeedUpdate = UpdateAllChannels(&State->ChannelSystem,
Context.DeltaTime,
State->Transient);
UpdateAllPatterns(&Temp_PatternsNeedUpdate, &State->PatternSystem, State->LEDBufferList, Context.DeltaTime, State->Transient);
*/
ClearTransientNodeColorBuffers(State->NodeList);
{
// NOTE(Peter): We know that these two lists should be maintained together. Each element in the list is one sculpture's worth of
@ -907,7 +921,6 @@ UPDATE_AND_RENDER(UpdateAndRender)
Context.DeltaTime, State->Camera, Input, State->Transient);
}
ClearArena(State->Transient);
EndDebugFrame(GlobalDebugServices);
}

View File

@ -40,7 +40,6 @@ struct assembly
};
#include "assembly_parser.h"
//#include "foldhaus_environment.h"
// TODO(Peter): remove this, and get pattern_system.h outta here!!
typedef struct led_pattern led_pattern;

View File

@ -187,6 +187,12 @@ AllocateNonGrowableArenaWithSpace(platform_alloc* PlatformAlloc, s32 SizeNeeded)
static void
ClearMemoryRegion (memory_region* Region)
{
#if 0
// NOTE(Peter): Turn this on occasionally. This is a big time sink but it forces us into
// correct memory usage since there's no error reporting for accessing memory the arena thinks
// is unused. At least now, it'll be zero's.
GSMemSet(Region->Base, 0, Region->Size);
#endif
Region->Used = 0;
}

View File

@ -156,7 +156,7 @@ PushOutputNodeOnList (node_list* List, v2 Min, memory_arena* Storage)
OutputNodeName.Length,
1,
Min,
v2{125, 150},
DEFAULT_NODE_DIMENSION,
Storage);
Node->Type = NodeType_OutputNode;
CopyStringTo(OutputNodeName, &Node->Name);
@ -841,45 +841,44 @@ UpdateNodeCalculation (interface_node* Node, node_list* NodeList, memory_arena*
for (s32 ConnectionIdx = 0; ConnectionIdx < Node->ConnectionsCount; ConnectionIdx++)
{
node_connection* Connection = 0;
node_connection Connection = Node->Connections[ConnectionIdx];
// TODO(Peter): We're currently passing in a pointer to the leds array for every single
// NODE_COLOR_BUFFER. We shouldn't do that, and just require each data structure that
// needs the leds to request that as its own member/parameter.
if (ConnectionIsInput(Node->Connections[ConnectionIdx]) ||
Connection->Type == MemberType_NODE_COLOR_BUFFER)
if (Connection.Type == MemberType_NODE_COLOR_BUFFER)
{
Connection = Node->Connections + ConnectionIdx;
switch (Connection->Type)
node_led_color_connection* ColorConnection = (node_led_color_connection*)(NodeData + MemberList[ConnectionIdx].Offset);
ColorConnection->LEDs = LEDs;
ColorConnection->LEDCount = LEDCount;
ColorConnection->Colors = Connection.LEDsValue.Colors;
if (!ColorConnection->Colors)
{
sacn_pixel* ColorsCopy = PushArray(Transient, sacn_pixel, LEDCount);
GSMemSet((u8*)ColorsCopy, 0, sizeof(sacn_pixel) * LEDCount);
ColorConnection->Colors = ColorsCopy;
}
}
else if (ConnectionIsInput(Connection))
{
Assert(Connection.Type != MemberType_NODE_COLOR_BUFFER);
switch (Connection.Type)
{
case MemberType_s32:
{
GSMemCopy(&Connection->S32Value, (NodeData + MemberList[ConnectionIdx].Offset), sizeof(s32));
GSMemCopy(&Connection.S32Value, (NodeData + MemberList[ConnectionIdx].Offset), sizeof(s32));
}break;
case MemberType_r32:
{
GSMemCopy(&Connection->R32Value, (NodeData + MemberList[ConnectionIdx].Offset), sizeof(r32));
GSMemCopy(&Connection.R32Value, (NodeData + MemberList[ConnectionIdx].Offset), sizeof(r32));
}break;
case MemberType_v4:
{
GSMemCopy(&Connection->V4Value, (NodeData + MemberList[ConnectionIdx].Offset), sizeof(v4));
}break;
case MemberType_NODE_COLOR_BUFFER:
{
Connection->LEDsValue.LEDs = LEDs;
Connection->LEDsValue.LEDCount = LEDCount;
if (Connection->LEDsValue.Colors == 0)
{
sacn_pixel* ColorsCopy = PushArray(Transient, sacn_pixel, LEDCount);
GSMemCopy(ColorsInit, ColorsCopy, sizeof(sacn_pixel) * LEDCount);
Connection->LEDsValue.Colors = ColorsCopy;
}
GSMemCopy(&Connection->LEDsValue, (NodeData + MemberList[ConnectionIdx].Offset), sizeof(node_led_color_connection));
GSMemCopy(&Connection.V4Value, (NodeData + MemberList[ConnectionIdx].Offset), sizeof(v4));
}break;
InvalidDefaultCase;
@ -921,6 +920,7 @@ UpdateNodeCalculation (interface_node* Node, node_list* NodeList, memory_arena*
case MemberType_NODE_COLOR_BUFFER:
{
node_led_color_connection* Value = (node_led_color_connection*)(NodeData + MemberList[ConnectionIdx].Offset);
Connection->LEDsValue.Colors = Value->Colors;
}break;
InvalidDefaultCase;
@ -937,7 +937,12 @@ UpdateOutputNodeCalculations (interface_node* OutputNode, node_list* NodeList, m
node_connection ColorsConnection = OutputNode->Connections[0];
if (ColorsConnection.LEDsValue.Colors)
{
GSMemCopy(ColorsConnection.LEDsValue.Colors, Colors, sizeof(sacn_pixel) * LEDCount);
sacn_pixel* DestPixel = Colors;
sacn_pixel* SourcePixel = ColorsConnection.LEDsValue.Colors;
for (s32 i = 0; i < LEDCount; i++)
{
*DestPixel++ = *SourcePixel++;
}
}
}
@ -956,6 +961,25 @@ UpdateAllNodeCalculations (node_list* NodeList, memory_arena* Transient, led* LE
}
}
internal void
ClearTransientNodeColorBuffers (node_list* NodeList)
{
node_list_iterator NodeIter = GetNodeListIterator(*NodeList);
while (NodeIteratorIsValid(NodeIter))
{
interface_node* Node = NodeIter.At;
for (s32 ConnectionIdx = 0; ConnectionIdx < Node->ConnectionsCount; ConnectionIdx++)
{
node_connection* Connection = Node->Connections + ConnectionIdx;
if (Connection->Type == MemberType_NODE_COLOR_BUFFER)
{
Connection->LEDsValue.Colors = 0;
}
}
Next(&NodeIter);
}
}
internal void
DrawValueDisplay (render_command_buffer* RenderBuffer, rect Bounds, node_connection Value, bitmap_font* Font)
{

View File

@ -3,6 +3,8 @@ typedef enum node_type node_type;
#define IsInputMember 1 << 0
#define IsOutputMember 1 << 1
#define DEFAULT_NODE_DIMENSION v2{125, 150}
#define NODE_COLOR_BUFFER \
led* LEDs; \
sacn_pixel* Colors; \

File diff suppressed because it is too large Load Diff

View File

@ -47,9 +47,22 @@ NODE_PROC(MultiplyPatterns, multiply_patterns_data)
{
Assert(LED->Index >= 0 && LED->Index < Data->ResultLEDCount);
Data->ResultColors[LED->Index].R = (Data->AColors[LED->Index].R + Data->BColors[LED->Index].R) / 2;
Data->ResultColors[LED->Index].G = (Data->AColors[LED->Index].G + Data->BColors[LED->Index].G) / 2;
Data->ResultColors[LED->Index].B = (Data->AColors[LED->Index].B + Data->BColors[LED->Index].B) / 2;
r32 AR = (r32)Data->AColors[LED->Index].R / 255.f;
r32 AG = (r32)Data->AColors[LED->Index].G / 255.f;
r32 AB = (r32)Data->AColors[LED->Index].B / 255.f;
r32 BR = (r32)Data->BColors[LED->Index].R / 255.f;
r32 BG = (r32)Data->BColors[LED->Index].G / 255.f;
r32 BB = (r32)Data->BColors[LED->Index].B / 255.f;
r32 RCombined = AR * BR;
r32 GCombined = AG * BG;
r32 BCombined = AB * BB;
Data->ResultColors[LED->Index].R = (u8)(GSClamp01(RCombined) * 255);
Data->ResultColors[LED->Index].G = (u8)(GSClamp01(GCombined) * 255);
Data->ResultColors[LED->Index].B = (u8)(GSClamp01(BCombined) * 255);
LED++;
}
}