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:
parent
808453b867
commit
40d9e0b83e
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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; \
|
||||
|
|
4853
stb/stb_truetype.h
4853
stb/stb_truetype.h
File diff suppressed because it is too large
Load Diff
|
@ -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++;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue