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 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))) 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); assembly_token CountToken = ParseToken(Tokenizer);
if (CountToken.Type == AssemblyToken_Number) if (CountToken.Type == AssemblyToken_Number)
{ {
Definition->LEDStripSize = ParseSignedIntUnsafe(CountToken.Token).SignedIntValue; Assembly->LEDStripSize = ParseSignedIntUnsafe(CountToken.Token).SignedIntValue;
} }
else else
{ {
@ -103,9 +103,11 @@ ParseAssemblyFileHeader (tokenizer* Tokenizer, assembly_definition* Definition)
} }
internal void internal void
ParseLEDStrip (tokenizer* Tokenizer, assembly_definition* Assembly) ParseLEDStrip (assembly_definition* Assembly, tokenizer* Tokenizer)
{ {
led_strip_definition* LEDStripDef = Assembly->LEDStrips + Assembly->LEDStripCount; led_strip_definition* LEDStripDef = Assembly->LEDStrips + Assembly->LEDStripCount;
Assert(Assembly->LEDStripCount < Assembly->LEDStripSize);
Assembly->LEDStripCount++; Assembly->LEDStripCount++;
// Control Box Index // Control Box Index
@ -163,24 +165,15 @@ ParseLEDStrip (tokenizer* Tokenizer, assembly_definition* Assembly)
EatWhitespace(Tokenizer); EatWhitespace(Tokenizer);
} }
internal assembly_definition internal void
ParseAssemblyFile (char* File, memory_arena* Storage) ParseAssemblyFileBody (assembly_definition* Assembly, tokenizer* Tokenizer)
{ {
assembly_definition Result = {}; EatWhitespace(Tokenizer);
tokenizer Tokenizer = {}; while(*Tokenizer->At)
Tokenizer.At = File;
ParseAssemblyFileHeader(&Tokenizer, &Result);
Result.LEDStrips = PushArray(Storage, led_strip_definition,
Result.LEDStripSize);
EatWhitespace(&Tokenizer);
while(*Tokenizer.At)
{ {
EatWhitespace(&Tokenizer); EatWhitespace(Tokenizer);
assembly_token Token = ParseToken(&Tokenizer); assembly_token Token = ParseToken(Tokenizer);
if (Token.Type != AssemblyToken_EndOfFile) if (Token.Type != AssemblyToken_EndOfFile)
{ {
@ -188,13 +181,12 @@ ParseAssemblyFile (char* File, memory_arena* Storage)
{ {
case AssemblyToken_LEDStrip: case AssemblyToken_LEDStrip:
{ {
ParseLEDStrip(&Tokenizer, &Result); ParseLEDStrip(Assembly, Tokenizer);
} break; } break;
default: // TODO(Peter): Other cases? What else would need to be in the assembly body?
{
InvalidCodePath; InvalidDefaultCase;
} break;
} }
} }
else else
@ -202,5 +194,9 @@ ParseAssemblyFile (char* File, memory_arena* Storage)
break; 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 internal void
LoadAssembly (app_state* State, context Context, char* Path) LoadAssembly (app_state* State, context Context, char* Path)
{ {
assembly_definition AssemblyDefinition = {};
arena_snapshot TempMemorySnapshot = TakeSnapshotOfArena(*State->Transient);
platform_memory_result TestAssemblyFile = Context.PlatformReadEntireFile(Path); 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); Context.PlatformFree(TestAssemblyFile.Base, TestAssemblyFile.Size);
string PathString = MakeStringLiteral(Path); string PathString = MakeStringLiteral(Path);
@ -297,6 +309,8 @@ LoadAssembly (app_state* State, context Context, char* Path)
r32 Scale = 100; r32 Scale = 100;
ConstructAssemblyFromDefinition(AssemblyDefinition, FileName, v3{0, 0, 0}, Scale, Context, State); ConstructAssemblyFromDefinition(AssemblyDefinition, FileName, v3{0, 0, 0}, Scale, Context, State);
ClearArenaToSnapshot(State->Transient, TempMemorySnapshot);
} }
internal void internal void
@ -517,7 +531,7 @@ INITIALIZE_APPLICATION(InitializeApplication)
State->NodeRenderSettings.PortColors[MemberType_v4] = BlueV4; State->NodeRenderSettings.PortColors[MemberType_v4] = BlueV4;
State->NodeRenderSettings.Font = State->Font; 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); ReloadStaticData(Context, GlobalDebugServices);
} }
@ -526,6 +540,12 @@ UPDATE_AND_RENDER(UpdateAndRender)
{ {
app_state* State = (app_state*)Context.MemoryBase; 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); ExecuteAllRegisteredCommands(&State->InputCommandRegistry, Input, State);
UpdateOutputNodeCalculations(State->OutputNode, State->NodeList, State->Transient, UpdateOutputNodeCalculations(State->OutputNode, State->NodeList, State->Transient,
@ -533,13 +553,7 @@ UPDATE_AND_RENDER(UpdateAndRender)
State->LEDBufferList->Colors, State->LEDBufferList->Colors,
State->LEDBufferList->Count); State->LEDBufferList->Count);
/* ClearTransientNodeColorBuffers(State->NodeList);
patterns_update_list Temp_PatternsNeedUpdate = UpdateAllChannels(&State->ChannelSystem,
Context.DeltaTime,
State->Transient);
UpdateAllPatterns(&Temp_PatternsNeedUpdate, &State->PatternSystem, State->LEDBufferList, Context.DeltaTime, State->Transient);
*/
{ {
// NOTE(Peter): We know that these two lists should be maintained together. Each element in the list is one sculpture's worth of // 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); Context.DeltaTime, State->Camera, Input, State->Transient);
} }
ClearArena(State->Transient);
EndDebugFrame(GlobalDebugServices); EndDebugFrame(GlobalDebugServices);
} }

View File

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

View File

@ -187,6 +187,12 @@ AllocateNonGrowableArenaWithSpace(platform_alloc* PlatformAlloc, s32 SizeNeeded)
static void static void
ClearMemoryRegion (memory_region* Region) 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; Region->Used = 0;
} }

View File

@ -156,7 +156,7 @@ PushOutputNodeOnList (node_list* List, v2 Min, memory_arena* Storage)
OutputNodeName.Length, OutputNodeName.Length,
1, 1,
Min, Min,
v2{125, 150}, DEFAULT_NODE_DIMENSION,
Storage); Storage);
Node->Type = NodeType_OutputNode; Node->Type = NodeType_OutputNode;
CopyStringTo(OutputNodeName, &Node->Name); 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++) 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 // 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 // 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. // needs the leds to request that as its own member/parameter.
if (ConnectionIsInput(Node->Connections[ConnectionIdx]) || if (Connection.Type == MemberType_NODE_COLOR_BUFFER)
Connection->Type == MemberType_NODE_COLOR_BUFFER)
{ {
Connection = Node->Connections + ConnectionIdx; node_led_color_connection* ColorConnection = (node_led_color_connection*)(NodeData + MemberList[ConnectionIdx].Offset);
switch (Connection->Type)
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: case MemberType_s32:
{ {
GSMemCopy(&Connection->S32Value, (NodeData + MemberList[ConnectionIdx].Offset), sizeof(s32)); GSMemCopy(&Connection.S32Value, (NodeData + MemberList[ConnectionIdx].Offset), sizeof(s32));
}break; }break;
case MemberType_r32: case MemberType_r32:
{ {
GSMemCopy(&Connection->R32Value, (NodeData + MemberList[ConnectionIdx].Offset), sizeof(r32)); GSMemCopy(&Connection.R32Value, (NodeData + MemberList[ConnectionIdx].Offset), sizeof(r32));
}break; }break;
case MemberType_v4: case MemberType_v4:
{ {
GSMemCopy(&Connection->V4Value, (NodeData + MemberList[ConnectionIdx].Offset), sizeof(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));
}break; }break;
InvalidDefaultCase; InvalidDefaultCase;
@ -921,6 +920,7 @@ UpdateNodeCalculation (interface_node* Node, node_list* NodeList, memory_arena*
case MemberType_NODE_COLOR_BUFFER: case MemberType_NODE_COLOR_BUFFER:
{ {
node_led_color_connection* Value = (node_led_color_connection*)(NodeData + MemberList[ConnectionIdx].Offset); node_led_color_connection* Value = (node_led_color_connection*)(NodeData + MemberList[ConnectionIdx].Offset);
Connection->LEDsValue.Colors = Value->Colors;
}break; }break;
InvalidDefaultCase; InvalidDefaultCase;
@ -937,7 +937,12 @@ UpdateOutputNodeCalculations (interface_node* OutputNode, node_list* NodeList, m
node_connection ColorsConnection = OutputNode->Connections[0]; node_connection ColorsConnection = OutputNode->Connections[0];
if (ColorsConnection.LEDsValue.Colors) 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 internal void
DrawValueDisplay (render_command_buffer* RenderBuffer, rect Bounds, node_connection Value, bitmap_font* Font) 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 IsInputMember 1 << 0
#define IsOutputMember 1 << 1 #define IsOutputMember 1 << 1
#define DEFAULT_NODE_DIMENSION v2{125, 150}
#define NODE_COLOR_BUFFER \ #define NODE_COLOR_BUFFER \
led* LEDs; \ led* LEDs; \
sacn_pixel* Colors; \ 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); Assert(LED->Index >= 0 && LED->Index < Data->ResultLEDCount);
Data->ResultColors[LED->Index].R = (Data->AColors[LED->Index].R + Data->BColors[LED->Index].R) / 2; r32 AR = (r32)Data->AColors[LED->Index].R / 255.f;
Data->ResultColors[LED->Index].G = (Data->AColors[LED->Index].G + Data->BColors[LED->Index].G) / 2; r32 AG = (r32)Data->AColors[LED->Index].G / 255.f;
Data->ResultColors[LED->Index].B = (Data->AColors[LED->Index].B + Data->BColors[LED->Index].B) / 2; 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++; LED++;
} }
} }