Created basic scope list view

This commit is contained in:
Peter Slattery 2019-11-11 12:02:24 -08:00
parent 59cac0f435
commit dba7b1a250
14 changed files with 819 additions and 324 deletions

View File

@ -219,7 +219,10 @@ DrawLEDsInBufferRangeJob (s32 ThreadID, void* JobData)
draw_leds_job_data* Data = (draw_leds_job_data*)JobData;
s32 DrawCommandsCount = Data->OnePastLastIndex - Data->StartIndex;
s32 LEDCount = Data->OnePastLastIndex - Data->StartIndex;
quad_batch_constructor_reserved_range BatchReservedRange = ThreadSafeReserveRangeInQuadConstructor(Data->Batch, LEDCount * 2);
s32 TrisUsed = 0;
r32 HalfWidth = Data->LEDHalfWidth;
@ -235,7 +238,7 @@ DrawLEDsInBufferRangeJob (s32 ThreadID, void* JobData)
led* LED = Data->LEDs + Data->StartIndex;
for (s32 LEDIdx = 0;
LEDIdx < DrawCommandsCount;
LEDIdx < LEDCount;
LEDIdx++)
{
sacn_pixel SACNColor = Data->Colors[LED->Index];
@ -248,9 +251,10 @@ DrawLEDsInBufferRangeJob (s32 ThreadID, void* JobData)
v4 P2 = P2_In + V4Position;
v4 P3 = P3_In + V4Position;
DEBUG_TRACK_SCOPE(PushLEDTris);
PushTri3DOnBatch(Data->Batch, P0, P1, P2, UV0, UV1, UV2, Color, Color, Color);
PushTri3DOnBatch(Data->Batch, P0, P2, P3, UV0, UV2, UV3, Color, Color, Color);
SetTri3DInBatch(Data->Batch, BatchReservedRange.Start + TrisUsed++,
P0, P1, P2, UV0, UV1, UV2, Color, Color, Color);
SetTri3DInBatch(Data->Batch, BatchReservedRange.Start + TrisUsed++,
P0, P2, P3, UV0, UV2, UV3, Color, Color, Color);
LED++;
}
@ -476,8 +480,53 @@ INITIALIZE_APPLICATION(InitializeApplication)
}
}
internal void
HandleInput (app_state* State, input_queue InputQueue, mouse_state Mouse)
{
DEBUG_TRACK_FUNCTION;
input_command_registry ActiveCommands = State->DefaultInputCommandRegistry;
if (State->Modes.ActiveModesCount > 0)
{
ActiveCommands = State->Modes.ActiveModes[State->Modes.ActiveModesCount - 1].Commands;
}
for (s32 EventIdx = 0; EventIdx < InputQueue.QueueUsed; EventIdx++)
{
input_entry Event = InputQueue.Entries[EventIdx];
// NOTE(Peter): These are in the order Down, Up, Held because we want to privalege
// Down and Up over Held. In other words, we don't want to call a Held command on the
// frame when the button was released, even if the command is registered to both events
if (KeyTransitionedDown(Event))
{
FindAndPushExistingCommand(ActiveCommands, Event, Command_Began, &State->CommandQueue);
}
else if (KeyTransitionedUp(Event))
{
FindAndPushExistingCommand(ActiveCommands, Event, Command_Ended, &State->CommandQueue);
}
else if (KeyHeldDown(Event))
{
FindAndPushExistingCommand(ActiveCommands, Event, Command_Held, &State->CommandQueue);
}
}
// Execute all commands in CommandQueue
for (s32 CommandIdx = State->CommandQueue.Used - 1; CommandIdx >= 0; CommandIdx--)
{
command_queue_entry* Entry = &State->CommandQueue.Commands[CommandIdx];
Entry->Command.Proc(State, Entry->Event, Mouse);
}
ClearCommandQueue(&State->CommandQueue);
}
UPDATE_AND_RENDER(UpdateAndRender)
{
DEBUG_TRACK_FUNCTION;
app_state* State = (app_state*)Context.MemoryBase;
// NOTE(Peter): We do this at the beginning because all the render commands are stored in Transient,
@ -486,59 +535,7 @@ UPDATE_AND_RENDER(UpdateAndRender)
// incorrect to clear the arena, and then access the memory later.
ClearArena(State->Transient);
{
input_command_registry ActiveCommands = State->DefaultInputCommandRegistry;
if (State->Modes.ActiveModesCount > 0)
{
ActiveCommands = State->Modes.ActiveModes[State->Modes.ActiveModesCount - 1].Commands;
}
for (s32 EventIdx = 0; EventIdx < InputQueue.QueueUsed; EventIdx++)
{
input_entry Event = InputQueue.Entries[EventIdx];
// NOTE(Peter): These are in the order Down, Up, Held because we want to privalege
// Down and Up over Held. In other words, we don't want to call a Held command on the
// frame when the button was released, even if the command is registered to both events
if (KeyTransitionedDown(Event))
{
FindAndPushExistingCommand(ActiveCommands, Event, Command_Began, &State->CommandQueue);
}
else if (KeyTransitionedUp(Event))
{
FindAndPushExistingCommand(ActiveCommands, Event, Command_Ended, &State->CommandQueue);
}
else if (KeyHeldDown(Event))
{
FindAndPushExistingCommand(ActiveCommands, Event, Command_Held, &State->CommandQueue);
}
if (Event.Key == KeyCode_MouseLeftButton)
{
Mouse.LeftButtonTransitionedDown = KeyTransitionedDown(Event);
Mouse.LeftButtonTransitionedUp = KeyTransitionedUp(Event);
}
else if (Event.Key == KeyCode_MouseMiddleButton)
{
Mouse.MiddleButtonTransitionedDown = KeyTransitionedDown(Event);
Mouse.MiddleButtonTransitionedUp = KeyTransitionedUp(Event);
}
else if (Event.Key == KeyCode_MouseRightButton)
{
Mouse.RightButtonTransitionedDown = KeyTransitionedDown(Event);
Mouse.RightButtonTransitionedUp = KeyTransitionedUp(Event);
}
}
// Execute all commands in CommandQueue
for (s32 CommandIdx = State->CommandQueue.Used - 1; CommandIdx >= 0; CommandIdx--)
{
command_queue_entry* Entry = &State->CommandQueue.Commands[CommandIdx];
Entry->Command.Proc(State, Entry->Event, Mouse);
}
ClearCommandQueue(&State->CommandQueue);
}
HandleInput(State, InputQueue, Mouse);
if (State->LEDBufferList)
{
@ -625,6 +622,7 @@ UPDATE_AND_RENDER(UpdateAndRender)
DEBUG_IF(GlobalDebugServices->Interface.RenderSculpture) // DebugServices RenderSculpture Toggle
{
DEBUG_TRACK_SCOPE(RenderSculpture);
s32 JobsNeeded = PLATFORM_THREAD_COUNT;
s32 LEDBufferSize = IntegerDivideRoundUp(State->TotalLEDsCount, JobsNeeded);
@ -738,8 +736,6 @@ UPDATE_AND_RENDER(UpdateAndRender)
State->Interface, Context.WindowWidth, Context.WindowHeight - TopBarHeight,
Context.DeltaTime, State, State->Camera, Mouse, State->Transient);
}
EndDebugFrame(GlobalDebugServices);
}
CLEANUP_APPLICATION(CleanupApplication)

View File

@ -1,21 +1,75 @@
#define SCOPE_NAME_LENGTH 256
struct scope_time_record
struct scope_record
{
char ScopeName_[SCOPE_NAME_LENGTH];
string ScopeName;
u32 Duration_Cycles;
u32 NameHash;
s64 StartCycles;
s64 EndCycles;
s32 CallDepth;
};
struct collated_scope_record
{
u32 NameHash;
s64 TotalCycles;
s32 CallCount;
r32 PercentFrameTime;
r32 TotalSeconds;
r32 AverageSecondsPerCall;
};
#define SCOPE_NAME_BUFFER_LENGTH 128
struct scope_name
{
u32 Hash;
string Name;
char Buffer[SCOPE_NAME_BUFFER_LENGTH];
};
struct debug_scope_record_list
{
s32 ThreadId;
s32 Max;
s32 Count;
scope_record* Calls;
s32 CurrentScopeCallDepth;
};
#define DEBUG_FRAME_GROW_SIZE 8102
struct debug_frame
{
s64 FrameStartCycles;
s64 FrameEndCycles;
s32 ScopeNamesMax;
scope_name* ScopeNamesHash;
s32 ThreadCount;
debug_scope_record_list* ThreadCalls;
s32 CollatedScopesMax;
collated_scope_record* CollatedScopes;
};
#define FRAME_VIEW_PROFILER 0
#define FRAME_VIEW_SCOPE_LIST 1
struct debug_interface
{
b32 ShowCameraMouse;
b32 ShowTrackedScopes;
b32 RenderSculpture;
b32 SendSACNData;
s32 FrameView;
};
typedef s32 debug_get_thread_id();
typedef s64 debug_timing_proc();
typedef u8* debug_alloc(s32 ElementSize, s32 ElementCount);
typedef u8* debug_realloc(u8* Memory, s32 OldSize, s32 NewSize);
#define HISTOGRAM_DEPTH 10
struct debug_histogram_entry
@ -34,34 +88,101 @@ struct debug_histogram_entry
u32 Total_CallCount;
};
#define SCOPE_HISTOGRAM_SIZE 512
#define DEBUG_FRAME_COUNT 128
struct debug_services
{
s32 TrackedScopesCount;
s32 TrackedScopesMax;
scope_time_record* TrackedScopes;
s64 PerformanceCountFrequency;
memory_arena DebugStorage;
b32 RecordFrames;
s32 CurrentDebugFrame;
debug_frame Frames[DEBUG_FRAME_COUNT];
debug_interface Interface;
debug_get_thread_id* GetThreadId;
debug_timing_proc* GetWallClock;
debug_histogram_entry* ScopeHistogramUnsorted;
debug_histogram_entry* ScopeHistogramSorted;
s32 ScopeHistogramUsed;
debug_alloc* Alloc;
debug_realloc* Realloc;
};
internal void
InitDebugServices (debug_services* Services, u8* Memory, s32 MemorySize, s32 TrackedScopesMax, s64 PerformanceCountFrequency)
InitializeDebugFrame (debug_frame* Frame, s32 NameHashMax, s32 ThreadCount, s32 ScopeCallsMax, debug_services* Services)
{
InitMemoryArena(&Services->DebugStorage, Memory, MemorySize, 0);
Frame->ScopeNamesMax = NameHashMax;
Frame->ScopeNamesHash = (scope_name*)Services->Alloc(sizeof(scope_name), NameHashMax);
Services->TrackedScopesCount = 0;
Services->TrackedScopesMax = TrackedScopesMax;
Services->TrackedScopes = PushArray(&Services->DebugStorage, scope_time_record, TrackedScopesMax);
// NOTE(Peter): We use the same size as scope names because we're only storing a single instance
// per scope. If ScopeNamesMax can't hold all the scopes, this will never get filled and
// we should assert and recompile with a resized NameHashMax
Frame->CollatedScopesMax = NameHashMax;
Frame->CollatedScopes = (collated_scope_record*)Services->Alloc(sizeof(collated_scope_record), NameHashMax);
for (s32 i = 0; i < Frame->ScopeNamesMax; i++)
{
scope_name* Entry = Frame->ScopeNamesHash + i;
Entry->Name = MakeString(Entry->Buffer, 0, SCOPE_NAME_BUFFER_LENGTH);
}
Frame->ThreadCount = ThreadCount;
Frame->ThreadCalls = (debug_scope_record_list*)Services->Alloc(sizeof(debug_scope_record_list),
ThreadCount);
for (s32 i = 0; i < ThreadCount; i++)
{
Frame->ThreadCalls[i].Max = ScopeCallsMax;
Frame->ThreadCalls[i].Count = 0;
Frame->ThreadCalls[i].Calls = (scope_record*)Services->Alloc(sizeof(scope_record), ScopeCallsMax);
Frame->ThreadCalls[i].CurrentScopeCallDepth = 0;
Frame->ThreadCalls[i].ThreadId = 0;
}
for (s32 c = 0; c < Frame->CollatedScopesMax; c++)
{
Frame->CollatedScopes[c].NameHash = 0;
}
}
internal void
StartDebugFrame(debug_frame* Frame, debug_services* Services)
{
Frame->FrameStartCycles = Services->GetWallClock();
for (s32 i = 0; i < Frame->ThreadCount; i++)
{
Frame->ThreadCalls[i].Count = 0;
Frame->ThreadCalls[i].CurrentScopeCallDepth = 0;
}
for (s32 c = 0; c < Frame->CollatedScopesMax; c++)
{
s32 Hash = Frame->CollatedScopes[c].NameHash;
Frame->CollatedScopes[c] = {};
Frame->CollatedScopes[c].NameHash = Hash;
}
}
internal void
InitDebugServices (debug_services* Services,
s64 PerformanceCountFrequency,
debug_alloc* Alloc,
debug_realloc* Realloc,
debug_timing_proc* GetWallClock,
debug_get_thread_id* GetThreadId,
s32 ThreadCount)
{
Services->Alloc = Alloc;
Services->Realloc = Realloc;
Services->GetWallClock = GetWallClock;
Services->GetThreadId = GetThreadId;
Services->RecordFrames = true;
Services->CurrentDebugFrame = 0;
s32 NameHashMax = 4096;
s32 ScopeCallsMax = 4096;
for (s32 i = 0; i < DEBUG_FRAME_COUNT; i++)
{
InitializeDebugFrame(&Services->Frames[i], NameHashMax, ThreadCount, ScopeCallsMax, Services);
}
Services->Interface.RenderSculpture = true;
@ -71,182 +192,197 @@ InitDebugServices (debug_services* Services, u8* Memory, s32 MemorySize, s32 Tra
Services->Interface.ShowTrackedScopes = false;
Services->Interface.RenderSculpture = true;
Services->Interface.SendSACNData = false;
}
Services->ScopeHistogramUnsorted = PushArray(&Services->DebugStorage, debug_histogram_entry, SCOPE_HISTOGRAM_SIZE);
Services->ScopeHistogramSorted = PushArray(&Services->DebugStorage, debug_histogram_entry, SCOPE_HISTOGRAM_SIZE);
internal debug_frame*
GetCurrentDebugFrame (debug_services* Services)
{
debug_frame* Result = Services->Frames + Services->CurrentDebugFrame;
return Result;
}
Services->ScopeHistogramUsed = 0;
internal debug_frame*
GetLastDebugFrame(debug_services* Services)
{
s32 Index = (Services->CurrentDebugFrame - 1);
if (Index < 0) { Index += DEBUG_FRAME_COUNT; }
debug_frame* Result = Services->Frames + Index;
return Result;
}
internal s32
DEBUGFindScopeHistogram (debug_services* Services, string Name)
GetIndexForNameHash(debug_frame* Frame, u32 NameHash)
{
s32 Result = -1;
for (s32 i = 0; i < SCOPE_HISTOGRAM_SIZE; i++)
for (s32 Offset = 0; Offset < Frame->ScopeNamesMax; Offset++)
{
if (StringsEqual(Services->ScopeHistogramUnsorted[i].ScopeName, Name))
u32 Index = (NameHash + Offset) % Frame->ScopeNamesMax;
if ((Frame->ScopeNamesHash[Index].Hash == NameHash))
{
Result = i;
Result = Index;
break;
}
}
// NOTE(Peter): Its not technically wrong to return a -1 here, just means we didn't find it.
// At the time of writing however, this function is only being called in contexts where we
// know there should be an entry in the Name table, so a -1 actually indicates a problem.
Assert(Result >= 0);
return Result;
}
internal s32
DEBUGAddScopeHistogram (debug_services* Services, scope_time_record Record)
internal debug_scope_record_list*
GetScopeListForThreadInFrame(debug_services* Services, debug_frame* Frame)
{
Assert(Services->ScopeHistogramUsed < SCOPE_HISTOGRAM_SIZE);
debug_scope_record_list* List = 0;
s32 Result = Services->ScopeHistogramUsed++;
debug_histogram_entry* Entry = Services->ScopeHistogramUnsorted + Result;
Entry->ScopeName = MakeString(Entry->ScopeName_, 256);
Entry->CurrentFrame = 0;
Entry->Average_Cycles = 0;
Entry->Average_CallCount = 0;
Entry->Total_Cycles = 0;
Entry->Total_CallCount = 0;
CopyStringTo(Record.ScopeName, &Entry->ScopeName);
return Result;
}
internal void
DEBUGRecordScopeInHistogram (debug_services* Services, s32 Index, scope_time_record Record)
{
debug_histogram_entry* Entry = Services->ScopeHistogramUnsorted + Index;
s32 FrameIndex = Entry->CurrentFrame;
if (FrameIndex >= 0 && FrameIndex < HISTOGRAM_DEPTH)
s32 CurrentThreadId = Services->GetThreadId();
for (s32 Offset = 0; Offset < Frame->ThreadCount; Offset++)
{
Entry->PerFrame_Cycles[FrameIndex] += Record.Duration_Cycles;
Entry->PerFrame_CallCount[FrameIndex]++;
}
}
internal void
DEBUGCacheScopeHistogramValues (debug_histogram_entry* Histogram)
{
Histogram->Total_Cycles = 0;
Histogram->Total_CallCount = 0;
// TODO(Peter): This doesn't account for the first frames when the histogram isn't full
for (s32 i = 0; i < HISTOGRAM_DEPTH; i++)
{
Histogram->Total_Cycles += Histogram->PerFrame_Cycles[i];
Histogram->Total_CallCount += Histogram->PerFrame_CallCount[i];
}
Histogram->Average_Cycles = (Histogram->Total_Cycles / HISTOGRAM_DEPTH);
Histogram->Average_CallCount = (Histogram->Total_CallCount / HISTOGRAM_DEPTH);
}
internal void
DEBUGSortedHistogramInsert(debug_histogram_entry Source, debug_histogram_entry* DestList, s32 DestCount, s32 Max)
{
s32 CurrentFrame0 = Source.CurrentFrame;
s32 V0 = Source.Average_Cycles; //PerFrame_Cycles[CurrentFrame0];
if (DestCount > 0)
{
for (s32 i = DestCount - 1; i >= 0; i--)
s32 Index = (CurrentThreadId + Offset) % Frame->ThreadCount;
if (Frame->ThreadCalls[Index].ThreadId == CurrentThreadId)
{
s32 CurrentFrame1 = DestList[i].CurrentFrame;
s32 V1 = DestList[i].Average_Cycles; //PerFrame_Cycles[CurrentFrame1];
if (V0 < V1)
{
DestList[i + 1] = Source;
break;
}
else
{
DestList[i + 1] = DestList[i];
}
List = Frame->ThreadCalls + Index;
break;
}
else if (Frame->ThreadCalls[Index].ThreadId == 0)
{
Frame->ThreadCalls[Index].ThreadId = CurrentThreadId;
List = Frame->ThreadCalls + Index;
break;
}
}
else
{
DestList[0] = Source;
}
Assert(List);
return List;
}
internal void
DEBUGSortHistogram(debug_histogram_entry* Source, debug_histogram_entry* Dest, s32 Count, s32 Max)
CollateThreadScopeCalls (debug_scope_record_list* ThreadRecords, debug_frame* Frame)
{
for (s32 i = 0; i < Count; i++)
for (s32 i = 0; i < ThreadRecords->Count; i++)
{
DEBUGSortedHistogramInsert(Source[i], Dest, i, Max);
}
}
scope_record Record = ThreadRecords->Calls[i];
s32 Index = GetIndexForNameHash (Frame, Record.NameHash);
collated_scope_record* CollatedRecord = Frame->CollatedScopes + Index;
internal void
DEBUGCollateScopeRecords (debug_services* Services)
{
for (s32 i = 0; i < Services->TrackedScopesCount; i++)
{
scope_time_record Record = Services->TrackedScopes[i];
s32 Index = DEBUGFindScopeHistogram(Services, Record.ScopeName);
if (Index < 0)
if (CollatedRecord->NameHash != Record.NameHash)
{
Index = DEBUGAddScopeHistogram(Services, Record);
CollatedRecord->NameHash = Record.NameHash;
CollatedRecord->TotalCycles = 0;
CollatedRecord->CallCount = 0;
}
DEBUGRecordScopeInHistogram(Services, Index, Record);
CollatedRecord->TotalCycles += Record.EndCycles - Record.StartCycles;
CollatedRecord->CallCount += 1;
}
for (s32 h = 0; h < Services->ScopeHistogramUsed; h++)
{
DEBUGCacheScopeHistogramValues(Services->ScopeHistogramUnsorted + h);
}
DEBUGSortHistogram(Services->ScopeHistogramUnsorted,
Services->ScopeHistogramSorted,
Services->ScopeHistogramUsed,
SCOPE_HISTOGRAM_SIZE);
}
internal void
EndDebugFrame (debug_services* Services)
{
DEBUGCollateScopeRecords(Services);
debug_frame* ClosingFrame = GetCurrentDebugFrame(Services);
ClosingFrame->FrameEndCycles = Services->GetWallClock();
GSZeroMemory((u8*)Services->TrackedScopes, sizeof(scope_time_record) * Services->TrackedScopesMax);
Services->TrackedScopesCount = 0;
s64 FrameTotalCycles = ClosingFrame->FrameEndCycles - ClosingFrame->FrameStartCycles;
for (s32 i = 0; i < Services->ScopeHistogramUsed; i++)
for (s32 t = 0; t < ClosingFrame->ThreadCount; t++)
{
s32 NewFrame = Services->ScopeHistogramUnsorted[i].CurrentFrame + 1;
if (NewFrame >= HISTOGRAM_DEPTH)
{
NewFrame = 0;
}
Services->ScopeHistogramUnsorted[i].CurrentFrame = NewFrame;
Services->ScopeHistogramUnsorted[i].PerFrame_Cycles[NewFrame] = 0;
Services->ScopeHistogramUnsorted[i].PerFrame_CallCount[NewFrame] = 0;
CollateThreadScopeCalls(ClosingFrame->ThreadCalls + t, ClosingFrame);
}
for (s32 n = 0; n < ClosingFrame->ScopeNamesMax; n++)
{
if (ClosingFrame->ScopeNamesHash[n].Hash != 0)
{
collated_scope_record* CollatedRecord = ClosingFrame->CollatedScopes + n;
CollatedRecord->TotalSeconds = (r32)CollatedRecord->TotalCycles / (r32)Services->PerformanceCountFrequency;
CollatedRecord->PercentFrameTime = (r32)CollatedRecord->TotalCycles / (r32)FrameTotalCycles;
CollatedRecord->AverageSecondsPerCall = CollatedRecord->TotalSeconds / CollatedRecord->CallCount;
}
}
Services->CurrentDebugFrame = (Services->CurrentDebugFrame + 1) % DEBUG_FRAME_COUNT;
StartDebugFrame(&Services->Frames[Services->CurrentDebugFrame], Services);
}
internal scope_time_record*
PushScopeRecord(string ScopeName, debug_services* Services)
internal u32
HashScopeName (char* ScopeName)
{
scope_time_record* Result = 0;
// djb2 hash
u32 Hash = 5381;
char* C = ScopeName;
while(*C)
{
Hash = ((Hash << 5) + Hash) + *C;
C++;
}
return Hash;
}
s32 OnePastIndex = InterlockedIncrement((long*)&Services->TrackedScopesCount);
Assert(OnePastIndex <= Services->TrackedScopesMax);
Result = Services->TrackedScopes + OnePastIndex - 1;
internal scope_name*
GetOrAddNameHashEntry(debug_frame* Frame, u32 NameHash)
{
scope_name* Result = 0;
Result->ScopeName = MakeString(Result->ScopeName_, SCOPE_NAME_LENGTH);
CopyStringTo(ScopeName, &Result->ScopeName);
for (s32 Offset = 0; Offset < Frame->ScopeNamesMax; Offset++)
{
u32 Index = (NameHash + Offset) % Frame->ScopeNamesMax;
if ((Frame->ScopeNamesHash[Index].Hash == 0) || (Frame->ScopeNamesHash[Index].Hash == NameHash))
{
Result = Frame->ScopeNamesHash + Index;
break;
}
}
return Result;
}
internal void
LogScopeTime (debug_services* Services, string ScopeName, u64 CyclesElapsed)
internal u32
BeginTrackingScopeAndGetNameHash (debug_services* Services, char* ScopeName)
{
scope_time_record* Record = PushScopeRecord(ScopeName, Services);
Record->Duration_Cycles = CyclesElapsed;
debug_frame* CurrentFrame = GetCurrentDebugFrame(Services);
debug_scope_record_list* ThreadList = GetScopeListForThreadInFrame(Services, CurrentFrame);
ThreadList->CurrentScopeCallDepth++;
u32 NameHash = HashScopeName(ScopeName);
scope_name* Entry = GetOrAddNameHashEntry(CurrentFrame, NameHash);
if (Entry->Hash == 0) // If its new
{
Entry->Hash = NameHash;
// TODO(Peter): need to initialize all entry name strings to point at the buffer
// This will break eventually. when it does, do this ^^^^ when on startup
CopyCharArrayToString(ScopeName, &Entry->Name);
}
return NameHash;
}
internal void
PushScopeTimeOnFrame (debug_services* Services, s32 NameHash, u64 StartCycles, u64 EndCycles)
{
debug_frame* CurrentFrame = GetCurrentDebugFrame(Services);
debug_scope_record_list* ThreadList = GetScopeListForThreadInFrame(Services, CurrentFrame);
if (ThreadList->Count >= ThreadList->Max)
{
s32 CurrentSize = ThreadList->Max * sizeof(scope_record);
s32 NewMax = (ThreadList->Max + DEBUG_FRAME_GROW_SIZE);
s32 NewSize = NewMax * sizeof(scope_record);
ThreadList->Calls = (scope_record*)Services->Realloc((u8*)ThreadList->Calls, CurrentSize, NewSize);
ThreadList->Max = NewMax;
}
Assert(ThreadList->Count < ThreadList->Max);
s32 EntryIndex = ThreadList->Count++;
scope_record* Record = ThreadList->Calls + EntryIndex;
Record->NameHash = NameHash;
Record->StartCycles = StartCycles;
Record->EndCycles = EndCycles;
Record->CallDepth = --ThreadList->CurrentScopeCallDepth;
}
internal r32 DEBUGGetSecondsElapsed (s64 Start, s64 End, r32 PerformanceCountFrequency)
@ -255,7 +391,7 @@ internal r32 DEBUGGetSecondsElapsed (s64 Start, s64 End, r32 PerformanceCountFre
return Result;
}
#if 1
#ifdef DEBUG
#define DEBUG_TRACK_FUNCTION scope_tracker ScopeTracker (__FUNCTION__, GlobalDebugServices)
#define DEBUG_TRACK_SCOPE(name) scope_tracker ScopeTracker_##name (#name, GlobalDebugServices)
#else
@ -265,27 +401,29 @@ internal r32 DEBUGGetSecondsElapsed (s64 Start, s64 End, r32 PerformanceCountFre
struct scope_tracker
{
s64 ScopeStart;
char ScopeName_[SCOPE_NAME_LENGTH];
string ScopeName;
u32 ScopeNameHash;
debug_services* DebugServices;
scope_tracker(char* ScopeName, debug_services* DebugServices)
{
this->ScopeName = MakeString(this->ScopeName_, SCOPE_NAME_LENGTH);
CopyCharArrayToString(ScopeName, &this->ScopeName);
this->ScopeStart = DebugServices->GetWallClock();
this->DebugServices = DebugServices;
if (DebugServices->RecordFrames)
{
this->ScopeNameHash = BeginTrackingScopeAndGetNameHash(DebugServices, ScopeName);
this->ScopeStart = DebugServices->GetWallClock();
this->DebugServices = DebugServices;
}
else
{
this->DebugServices = 0;
}
}
~scope_tracker()
{
s64 ScopeEnd = DebugServices->GetWallClock();
u32 CyclesElapsed = (u32)(ScopeEnd - this->ScopeStart);
#if 0
r32 SecondsElapsed = DEBUGGetSecondsElapsed(this->ScopeStart, ScopeEnd, DebugServices->PerformanceCountFrequency);
#endif
LogScopeTime(DebugServices, ScopeName, CyclesElapsed);
if (this->DebugServices) // NOTE(Peter): If DebugServices == 0, then we werent' recording this frame
{
s64 ScopeEnd = this->DebugServices->GetWallClock();
PushScopeTimeOnFrame(this->DebugServices, this->ScopeNameHash, this->ScopeStart, ScopeEnd);
}
}
};

View File

@ -1,3 +1,194 @@
internal void
RenderProfiler_ScopeVisualization(render_command_buffer* RenderBuffer,
interface_config Interface, mouse_state Mouse,
v2 Min, v2 Max,
debug_frame* VisibleFrame, memory_arena* Memory)
{
v4 ThreadColors[] = {
v4{.73f, .33f, .83f, 1},
v4{0, .50f, .50f, 1},
v4{.83f, 0, 0, 1},
v4{.33f, .49f, .83f, 1},
v4{.74f, .40f, .25f, 1},
};
r32 Width = Max.x - Min.x;
r32 DepthHeight = 64;
s64 FrameStartCycles = VisibleFrame->FrameStartCycles;
s64 FrameTotalCycles = VisibleFrame->FrameEndCycles - VisibleFrame->FrameStartCycles;
debug_scope_record_list* ThreadScopeCalls = GetScopeListForThreadInFrame(GlobalDebugServices,
VisibleFrame);
MakeStringBuffer(String, 256);
for (s32 i = 0; i < ThreadScopeCalls->Count; i++)
{
scope_record* Record = ThreadScopeCalls->Calls + i;
scope_name* Name = GetOrAddNameHashEntry(VisibleFrame, Record->NameHash);
r32 PercentStart = (r32)(Record->StartCycles - FrameStartCycles) / (r32)FrameTotalCycles;
r32 PercentEnd = (r32)(Record->EndCycles - FrameStartCycles) / (r32)FrameTotalCycles;
v2 ScopeMin = v2{Min.x + (Width * PercentStart), Max.y - ((Record->CallDepth + 1) * DepthHeight)};
v2 ScopeMax = v2{Min.x + (Width * PercentEnd), ScopeMin.y + (DepthHeight - 4)};
if ((ScopeMax.x - ScopeMin.x) >= 1)
{
v4 Color = ThreadColors[0];
if (PointIsInRange(Mouse.Pos, ScopeMin, ScopeMax))
{
Color = GreenV4;
}
PushRenderQuad2D(RenderBuffer, ScopeMin, ScopeMax, Color);
PushRenderBoundingBox2D(RenderBuffer, ScopeMin, ScopeMax, 1, BlackV4);
if (PointIsInRange(Mouse.Pos, ScopeMin, ScopeMax))
{
PushRenderQuad2D(RenderBuffer, Mouse.Pos, Mouse.Pos + v2{256, 32}, BlackV4);
PrintF(&String, "%.*s : %d - %d", Name->Name.Length, Name->Name.Memory, Record->StartCycles, Record->EndCycles);
DrawString(RenderBuffer, String, Interface.Font, Mouse.Pos, WhiteV4);
}
}
}
}
internal void
RenderProfiler_ListVisualization(render_command_buffer* RenderBuffer,
interface_config Interface, mouse_state Mouse,
v2 Min, v2 Max,
debug_frame* VisibleFrame, memory_arena* Memory)
{
MakeStringBuffer(String, 256);
r32 YAt = Max.y - Interface.Font->PixelHeight;
r32 Column0X = Min.x;
r32 Column1X = Column0X + 256;
r32 Column2X = Column1X + 128;
r32 Column3X = Column2X + 128;
r32 Column4X = Column3X + 100;
for (s32 n = 0; n < VisibleFrame->ScopeNamesMax; n++)
{
scope_name NameEntry = VisibleFrame->ScopeNamesHash[n];
if (NameEntry.Hash != 0)
{
collated_scope_record* CollatedRecord = VisibleFrame->CollatedScopes + n;
PrintF(&String, "%.*s", NameEntry.Name.Length, NameEntry.Name.Memory);
DrawString(RenderBuffer, String, Interface.Font, v2{Column0X, YAt}, WhiteV4);
PrintF(&String, "%f", CollatedRecord->PercentFrameTime);
DrawString(RenderBuffer, String, Interface.Font, v2{Column1X, YAt}, WhiteV4);
PrintF(&String, "%fs", CollatedRecord->TotalSeconds);
DrawString(RenderBuffer, String, Interface.Font, v2{Column2X, YAt}, WhiteV4);
PrintF(&String, "%dcy", CollatedRecord->TotalCycles);
DrawString(RenderBuffer, String, Interface.Font, v2{Column3X, YAt}, WhiteV4);
PrintF(&String, "%d calls", CollatedRecord->CallCount);
DrawString(RenderBuffer, String, Interface.Font, v2{Column4X, YAt}, WhiteV4);
YAt -= Interface.Font->PixelHeight + 4;
if (YAt < Min.y) { break; }
}
}
}
internal void
DrawDebugFrameList (render_command_buffer* RenderBuffer, interface_config Interface, mouse_state Mouse, v2 BoundsMin, v2 BoundsMax, memory_arena* Memory)
{
string String = InitializeEmptyString(PushArray(Memory, char, 256), 256);
v4 FrameColors[] = { GreenV4, YellowV4, RedV4, WhiteV4 };
r32 FrameListHeight = 64;
v2 FrameListMin = v2{BoundsMin.x + 16, BoundsMax.y - (16 + FrameListHeight)};
v2 FrameListMax = v2{BoundsMax.x - 16, BoundsMax.y - 16};
r32 FrameListPadding = 4;
r32 FrameListInnerWidth = (FrameListMax.x - FrameListMin.x) - (FrameListPadding * 2);
r32 SingleFrameStep = FrameListInnerWidth / DEBUG_FRAME_COUNT;
r32 SingleFrameWidth = (r32)((s32)SingleFrameStep - 2);
PushRenderBoundingBox2D(RenderBuffer, FrameListMin, FrameListMax, 2, WhiteV4);
if (PointIsInRange(Mouse.Pos, FrameListMin, FrameListMax) &&
MouseButtonHeldDown(Mouse.LeftButtonState))
{
r32 LocalMouseX = (Mouse.Pos.x - FrameListMin.x) + FrameListPadding;
s32 ClosestFrameIndex = (LocalMouseX / SingleFrameStep);
if (ClosestFrameIndex >= 0 && ClosestFrameIndex < DEBUG_FRAME_COUNT)
{
GlobalDebugServices->RecordFrames = false;
GlobalDebugServices->CurrentDebugFrame = ClosestFrameIndex;
}
}
for (s32 F = 0; F < DEBUG_FRAME_COUNT; F++)
{
v2 Min = v2{FrameListMin.x + FrameListPadding + (F * SingleFrameStep), FrameListMin.y + 4};
v2 Max = v2{Min.x + SingleFrameWidth, FrameListMax.y - 4};
s32 FramesAgo = (GlobalDebugServices->CurrentDebugFrame - F);
if (FramesAgo < 0) { FramesAgo += DEBUG_FRAME_COUNT; }
v4 Color = FrameColors[GSClamp(0, FramesAgo, 3)];
PushRenderQuad2D(RenderBuffer, Min, Max, Color);
}
debug_frame* VisibleFrame = GetLastDebugFrame(GlobalDebugServices);
s64 FrameStartCycles = VisibleFrame->FrameStartCycles;
s64 FrameTotalCycles = VisibleFrame->FrameEndCycles - VisibleFrame->FrameStartCycles;
PrintF(&String, "Frame %d - Total Cycles: %lld",
GlobalDebugServices->CurrentDebugFrame - 1,
FrameTotalCycles);
DrawString(RenderBuffer, String, Interface.Font, FrameListMin - v2{0, 32}, WhiteV4);
v2 ButtonMin = v2{FrameListMax.x - 128, FrameListMin.y - 32};
v2 ButtonMax = ButtonMin + v2{128, 28};
button_result ShouldResumeRecording = EvaluateButton(RenderBuffer, ButtonMin, ButtonMax,
MakeString("Resume Recording"), Interface, Mouse);
if (ShouldResumeRecording.Pressed)
{
GlobalDebugServices->RecordFrames = true;
}
ButtonMin = v2{FrameListMin.x, FrameListMin.y - 60};
ButtonMax = v2{FrameListMin.x + 128, FrameListMin.y - 42};
button_result ActivateScopeView = EvaluateButton(RenderBuffer, ButtonMin, ButtonMax,
MakeString("Scope View"), Interface, Mouse);
ButtonMin.x += 152;
ButtonMax.x += 152;
button_result ActivateListView = EvaluateButton(RenderBuffer, ButtonMin, ButtonMax,
MakeString("List View"), Interface, Mouse);
if (ActivateScopeView.Pressed) { GlobalDebugServices->Interface.FrameView = FRAME_VIEW_PROFILER; }
if (ActivateListView.Pressed) { GlobalDebugServices->Interface.FrameView = FRAME_VIEW_SCOPE_LIST; }
v2 ViewModeMin = v2{FrameListMin.x, BoundsMin.y};
v2 ViewModeMax = v2{FrameListMax.x, FrameListMin.y - 96};
if (GlobalDebugServices->Interface.FrameView == FRAME_VIEW_PROFILER)
{
RenderProfiler_ScopeVisualization(RenderBuffer, Interface, Mouse,
ViewModeMin, ViewModeMax,
VisibleFrame, Memory);
}
else
{
RenderProfiler_ListVisualization(RenderBuffer, Interface, Mouse,
ViewModeMin, ViewModeMax,
VisibleFrame, Memory);
}
}
internal void
DrawDebugInterface (render_command_buffer* RenderBuffer, r32 StartX, interface_config Interface, r32 WindowWidth, r32 WindowHeight, r32 DeltaTime, app_state* State, camera Camera, mouse_state Mouse, memory_arena* Transient)
{
@ -10,7 +201,7 @@ DrawDebugInterface (render_command_buffer* RenderBuffer, r32 StartX, interface_c
string DebugString = InitializeEmptyString(PushArray(Transient, char, 256), 256);
if (GlobalDebugServices->Interface.ShowCameraMouse || GlobalDebugServices->Interface.ShowTrackedScopes)
if (GlobalDebugServices->Interface.ShowCameraMouse)
{
PushRenderQuad2D(RenderBuffer,
v2{TopOfDebugView.x, TopOfDebugView.y - 500},
@ -100,12 +291,17 @@ DrawDebugInterface (render_command_buffer* RenderBuffer, r32 StartX, interface_c
DrawString(RenderBuffer, DebugString, Interface.Font, TopOfScreenLinePos, v4{1.0f, 1.0f, 1.0f, 1.0f});
TopOfScreenLinePos.y -= NewLineYOffset(*Interface.Font);
b32 LeftButtonIsDown = (Mouse.LeftButtonState & KeyState_IsDown) > 0;
b32 LeftButtonWasDown = (Mouse.LeftButtonState & KeyState_WasDown) > 0;
s32 MousePrecision = 0;
PrintF(&DebugString, "Mouse Pos: (%.*f, %.*f) Down: (%.*f, %.*f)",
PrintF(&DebugString, "Mouse Pos: (%.*f, %.*f) Down: (%.*f, %.*f) State: %s %s",
MousePrecision, Mouse.Pos.x,
MousePrecision, Mouse.Pos.y,
MousePrecision, Mouse.DownPos.x,
MousePrecision, Mouse.DownPos.y);
MousePrecision, Mouse.DownPos.y,
(LeftButtonIsDown ? "Is Down" : "Is Not Down"),
(LeftButtonWasDown ? "Was Down" : "Was Not Down"));
DrawString(RenderBuffer, DebugString, Interface.Font,
TopOfScreenLinePos, WhiteV4);
TopOfScreenLinePos.y -= NewLineYOffset(*Interface.Font);
@ -116,12 +312,24 @@ DrawDebugInterface (render_command_buffer* RenderBuffer, r32 StartX, interface_c
DrawString(RenderBuffer, DebugString, Interface.Font,
TopOfScreenLinePos, WhiteV4);
TopOfScreenLinePos.y -= NewLineYOffset(*Interface.Font);
PrintF(&DebugString, "Render Buffer: %d / %d (at this point)",
RenderBuffer->CommandMemoryUsed,
RenderBuffer->CommandMemorySize);
DrawString(RenderBuffer, DebugString, Interface.Font,
TopOfScreenLinePos, WhiteV4);
TopOfScreenLinePos.y -= NewLineYOffset(*Interface.Font);
}
if (GlobalDebugServices->Interface.ShowTrackedScopes)
{
r32 ColumnsStartX = TopOfScreenLinePos.x;
v2 ProfilerMin = v2{TopOfDebugView.x, TopOfDebugView.y - 500};
v2 ProfilerMax = v2{TopOfDebugView.x + 700, TopOfDebugView.y - 64};
PushRenderQuad2D(RenderBuffer, ProfilerMin, ProfilerMax, v4{0, 0, 0, .8f});
DrawDebugFrameList(RenderBuffer, Interface, Mouse, ProfilerMin, ProfilerMax, Transient);
#if 0
r32 ColumnsStartX = TopOfScreenLinePos.x;
for (s32 i = 0; i < GlobalDebugServices->ScopeHistogramUsed; i++)
{
v2 Register = v2{ColumnsStartX, TopOfScreenLinePos.y};
@ -161,6 +369,7 @@ DrawDebugInterface (render_command_buffer* RenderBuffer, r32 StartX, interface_c
}
#endif
}
ZeroArenaToSnapshot(Transient, StartTempMemory);

View File

@ -520,10 +520,11 @@ ConnectNodes(node_list* NodeList,
s32 UpstreamNodeHandle, s32 UpstreamNodePort,
s32 DownstreamNodeHandle, s32 DownstreamNodePort)
{
interface_node* UpstreamNode = 0;
interface_node* DownstreamNode = GetNodeWithHandle(NodeList, DownstreamNodeHandle);
if (!CheckForRecursionWithHandle(NodeList, UpstreamNodeHandle, DownstreamNode))
{
interface_node* UpstreamNode = GetNodeWithHandle(NodeList, UpstreamNodeHandle);
UpstreamNode = GetNodeWithHandle(NodeList, UpstreamNodeHandle);
if (PortTypesMatch(UpstreamNode, UpstreamNodePort,
DownstreamNode, DownstreamNodePort))
{

View File

@ -1,10 +1,11 @@
internal render_command_buffer
AllocateRenderCommandBuffer (u8* Memory, s32 Size)
AllocateRenderCommandBuffer (u8* Memory, s32 Size, renderer_realloc* Realloc)
{
render_command_buffer Result = {};
Result.CommandMemory = Memory;
Result.CommandMemoryUsed = 0;
Result.CommandMemorySize = Size;
Result.CommandMemoryUsed = 0;
Result.Realloc = Realloc;
return Result;
}
@ -95,6 +96,8 @@ RenderCommandBuffer (render_command_buffer CommandBuffer)
{
case RenderCommand_render_command_set_render_mode:
{
DEBUG_TRACK_SCOPE(SetRenderMode);
render_command_set_render_mode* Command = (render_command_set_render_mode*)(CommandHeader + 1);
glViewport(Command->ViewOffsetX, Command->ViewOffsetY,
@ -118,6 +121,8 @@ RenderCommandBuffer (render_command_buffer CommandBuffer)
case RenderCommand_render_command_clear_screen:
{
DEBUG_TRACK_SCOPE(RendererClearScreen);
render_command_clear_screen* Command = (render_command_clear_screen*)(CommandHeader + 1);
ClearRenderBuffer();

View File

@ -186,12 +186,18 @@ struct render_command_set_render_mode
b32 UseDepthBuffer;
};
typedef u8* renderer_realloc(u8* Base, s32 CurrentSize, s32 NewSize);
#define COMMAND_BUFFER_MIN_GROW_SIZE Megabytes(2)
struct render_command_buffer
{
u8* CommandMemory;
s32 CommandMemoryUsed;
s32 CommandMemorySize;
renderer_realloc* Realloc;
s32 ViewWidth;
s32 ViewHeight;
};
@ -230,15 +236,29 @@ PackColorStructR32 (r32 In_R, r32 In_G, r32 In_B, r32 In_A)
return Result;
}
internal void
ResizeBufferIfNecessary(render_command_buffer* Buffer, s32 DataSize)
{
if (Buffer->CommandMemoryUsed + DataSize > Buffer->CommandMemorySize)
{
// NOTE(Peter): If this becomes a problem just go back to the original solution of
// NewSize = Buffer->CommandMemorySize + (2 * DataSize);
s32 SpaceAvailable = Buffer->CommandMemorySize - Buffer->CommandMemoryUsed;
s32 SpaceNeeded = DataSize - SpaceAvailable; // This is known to be positive at this point
s32 AdditionSize = GSMax(SpaceNeeded, COMMAND_BUFFER_MIN_GROW_SIZE);
s32 NewSize = Buffer->CommandMemorySize + AdditionSize;
Buffer->CommandMemory = Buffer->Realloc(Buffer->CommandMemory,
Buffer->CommandMemorySize,
NewSize);
Buffer->CommandMemorySize = NewSize;
}
}
// Batch
internal s32
PushQuad3DBatch (render_command_buffer* Buffer, render_quad_batch_constructor* Constructor, s32 QuadCount, u8* MemStart, b32 UseIntegerColor = false)
PushQuad3DBatch (render_command_buffer* Buffer, render_quad_batch_constructor* Constructor, u8* MemStart, s32 TriCount, s32 DataSize, b32 UseIntegerColor = false)
{
s32 TriCount = QuadCount * 2;
s32 DataSize = BATCH_3D_SIZE(TriCount);
Assert(Buffer->CommandMemoryUsed + DataSize <= Buffer->CommandMemorySize);
Constructor->Max = TriCount;
Constructor->Count = 0;
@ -251,15 +271,13 @@ PushQuad3DBatch (render_command_buffer* Buffer, render_quad_batch_constructor* C
}
internal s32
PushQuad2DBatch (render_command_buffer* Buffer, render_quad_batch_constructor* Constructor, s32 QuadCount, u8* MemStart)
PushQuad2DBatch (render_command_buffer* Buffer, render_quad_batch_constructor* Constructor, s32 QuadCount, s32 DataSize, u8* MemStart)
{
s32 DataSize = BATCH_2D_SIZE(QuadCount);
Assert(Buffer->CommandMemoryUsed + DataSize <= Buffer->CommandMemorySize);
GSZeroMemory(MemStart, DataSize);
Constructor->Max = QuadCount;
Constructor->Count = 0;
Constructor->Vertecies = (v4*)(MemStart + BATCH_2D_VERTECIES_OFFSET(QuadCount));
Constructor->UVs = (v2*)(MemStart + BATCH_2D_UVS_OFFSET(QuadCount));
Constructor->ColorsV = (v4*)(MemStart + BATCH_2D_COLORS_OFFSET(QuadCount));
@ -280,31 +298,58 @@ ThreadSafeIncrementQuadConstructorCount (render_quad_batch_constructor* Construc
return Result;
}
struct quad_batch_constructor_reserved_range
{
s32 Start;
s32 OnePastLast;
};
internal quad_batch_constructor_reserved_range
ThreadSafeReserveRangeInQuadConstructor(render_quad_batch_constructor* Constructor, s32 TrisNeeded)
{
quad_batch_constructor_reserved_range Result = {};
Result.OnePastLast = InterlockedAdd((long*)&Constructor->Count, TrisNeeded);
Result.Start = Result.OnePastLast - TrisNeeded;
return Result;
}
inline void
SetTri3DInBatch (render_quad_batch_constructor* Constructor, s32 TriIndex,
v4 P0, v4 P1, v4 P2,
v2 UV0, v2 UV1, v2 UV2,
v4 C0, v4 C1, v4 C2)
{
// Vertecies
Constructor->Vertecies[BATCH_3D_VERTEX_INDEX(TriIndex, 0)] = P0;
Constructor->Vertecies[BATCH_3D_VERTEX_INDEX(TriIndex, 1)] = P1;
Constructor->Vertecies[BATCH_3D_VERTEX_INDEX(TriIndex, 2)] = P2;
// UVs
Constructor->UVs[BATCH_3D_UV_INDEX(TriIndex, 0)] = UV0;
Constructor->UVs[BATCH_3D_UV_INDEX(TriIndex, 1)] = UV1;
Constructor->UVs[BATCH_3D_UV_INDEX(TriIndex, 2)] = UV1;
// Color V0
Constructor->ColorsV[BATCH_3D_COLOR_INDEX(TriIndex, 0)] = C0;
Constructor->ColorsV[BATCH_3D_COLOR_INDEX(TriIndex, 1)] = C1;
Constructor->ColorsV[BATCH_3D_COLOR_INDEX(TriIndex, 2)] = C2;
}
inline void
PushTri3DOnBatch (render_quad_batch_constructor* Constructor,
v4 P0, v4 P1, v4 P2,
v2 UV0, v2 UV1, v2 UV2,
v4 C0, v4 C1, v4 C2)
{
DEBUG_TRACK_FUNCTION;
s32 Tri = ThreadSafeIncrementQuadConstructorCount(Constructor);
// Vertecies
Constructor->Vertecies[BATCH_3D_VERTEX_INDEX(Tri, 0)] = P0;
Constructor->Vertecies[BATCH_3D_VERTEX_INDEX(Tri, 1)] = P1;
Constructor->Vertecies[BATCH_3D_VERTEX_INDEX(Tri, 2)] = P2;
// UVs
Constructor->UVs[BATCH_3D_UV_INDEX(Tri, 0)] = UV0;
Constructor->UVs[BATCH_3D_UV_INDEX(Tri, 1)] = UV1;
Constructor->UVs[BATCH_3D_UV_INDEX(Tri, 2)] = UV1;
// Color V0
Constructor->ColorsV[BATCH_3D_COLOR_INDEX(Tri, 0)] = C0;
Constructor->ColorsV[BATCH_3D_COLOR_INDEX(Tri, 1)] = C1;
Constructor->ColorsV[BATCH_3D_COLOR_INDEX(Tri, 2)] = C2;
SetTri3DInBatch(Constructor, Tri, P0, P1, P2, UV0, UV1, UV2, C0, C1, C2);
};
internal void
PushQuad3DOnBatch (render_quad_batch_constructor* Constructor, v4 P0, v4 P1, v4 P2, v4 P3, v2 UVMin, v2 UVMax, v4 Color)
{
Assert(Constructor->Count < Constructor->Max);
Assert(Constructor->Count + 2 < Constructor->Max);
PushTri3DOnBatch(Constructor, P0, P1, P2, UVMin, v2{UVMax.x, UVMin.y}, UVMax, Color, Color, Color);
PushTri3DOnBatch(Constructor, P0, P2, P3, UVMin, UVMax, v2{UVMin.x, UVMax.y}, Color, Color, Color);
}
@ -332,6 +377,8 @@ PushQuad2DOnBatch (render_quad_batch_constructor* Constructor,
v2 UV0, v2 UV1, v2 UV2, v2 UV3,
v4 C0, v4 C1, v4 C2, v4 C3)
{
DEBUG_TRACK_FUNCTION;
s32 Quad = ThreadSafeIncrementQuadConstructorCount(Constructor);
v2* Vertecies = (v2*)Constructor->Vertecies;
@ -367,6 +414,8 @@ PushQuad2DOnBatch (render_quad_batch_constructor* Constructor,
internal void
PushQuad2DOnBatch (render_quad_batch_constructor* Constructor, v2 P0, v2 P1, v2 P2, v2 P3, v2 UVMin, v2 UVMax, v4 Color)
{
DEBUG_TRACK_FUNCTION;
s32 Quad = ThreadSafeIncrementQuadConstructorCount(Constructor);
v2* Vertecies = (v2*)Constructor->Vertecies;
@ -422,6 +471,7 @@ PushLine2DOnBatch (render_quad_batch_constructor* Constructor, v2 P0, v2 P1, r32
internal u8*
PushRenderCommand_ (render_command_buffer* CommandBuffer, render_command_type CommandType, s32 CommandSize)
{
ResizeBufferIfNecessary(CommandBuffer, CommandSize);
Assert(CommandBuffer->CommandMemoryUsed + CommandSize <= CommandBuffer->CommandMemorySize);
render_command_header* Header = (render_command_header*)(CommandBuffer->CommandMemory + CommandBuffer->CommandMemoryUsed);
@ -488,11 +538,15 @@ PushRenderClearScreen (render_command_buffer* Buffer)
internal render_quad_batch_constructor
PushRenderQuad2DBatch(render_command_buffer* Buffer, s32 QuadCount)
{
s32 DataSize = BATCH_2D_SIZE(QuadCount);
ResizeBufferIfNecessary(Buffer, DataSize + sizeof(render_batch_command_quad_2d));
Assert(Buffer->CommandMemoryUsed + DataSize <= Buffer->CommandMemorySize);
render_quad_batch_constructor Result = {};
render_batch_command_quad_2d* Command = PushRenderCommand(Buffer, render_batch_command_quad_2d);
Command->QuadCount = QuadCount;
Command->DataSize = PushQuad2DBatch(Buffer, &Result, QuadCount, (u8*)(Command + 1));
Command->DataSize = PushQuad2DBatch(Buffer, &Result, QuadCount, DataSize, (u8*)(Command + 1));
return Result;
}
@ -515,11 +569,16 @@ PushRenderLine2D (render_command_buffer* Buffer, v2 P0, v2 P1, r32 Thickness, v4
internal render_quad_batch_constructor
PushRenderQuad3DBatch(render_command_buffer* Buffer, s32 QuadCount)
{
s32 TriCount = QuadCount * 2;
s32 DataSize = BATCH_3D_SIZE(TriCount);
ResizeBufferIfNecessary(Buffer, DataSize + sizeof(render_batch_command_quad_3d));
Assert(Buffer->CommandMemoryUsed + DataSize <= Buffer->CommandMemorySize);
render_quad_batch_constructor Result = {};
render_batch_command_quad_3d* Command = PushRenderCommand(Buffer, render_batch_command_quad_3d);
Command->QuadCount = QuadCount;
Command->DataSize = PushQuad3DBatch(Buffer, &Result, QuadCount, (u8*)(Command + 1));
Command->DataSize = PushQuad3DBatch(Buffer, &Result, (u8*)(Command + 1), TriCount, DataSize);
return Result;
}
@ -547,11 +606,15 @@ internal render_quad_batch_constructor
PushRenderTexture2DBatch(render_command_buffer* Buffer, s32 QuadCount,
render_texture Texture)
{
s32 DataSize = BATCH_2D_SIZE(QuadCount);
ResizeBufferIfNecessary(Buffer, DataSize);
Assert(Buffer->CommandMemoryUsed + DataSize <= Buffer->CommandMemorySize);
render_quad_batch_constructor Result = {};
render_batch_command_texture_2d* Command = PushRenderCommand(Buffer, render_batch_command_texture_2d);
Command->QuadCount = QuadCount;
Command->DataSize = PushQuad2DBatch(Buffer, &Result, QuadCount, (u8*)(Command + 1));
Command->DataSize = PushQuad2DBatch(Buffer, &Result, QuadCount, DataSize, (u8*)(Command + 1));
Command->Texture = Texture;
return Result;

View File

@ -11,7 +11,6 @@ NodeType_SwdColorProc,
NodeType_SolidColorProc,
NodeType_VerticalColorFadeProc,
NodeType_RevolvingDiscs,
NodeType_MichelleColorProc,
NodeType_Count,
};
@ -61,7 +60,7 @@ node_struct_member MemberList_swd_color_data[] = {
node_struct_member MemberList_solid_color_data[] = {
{ MemberType_v4, "Color", (u64)&((solid_color_data*)0)->Color, IsInputMember },
{ MemberType_NODE_COLOR_BUFFER, "LEDs", (u64)&((solid_color_data*)0)->LEDs, IsInputMember | IsOutputMember},
{ MemberType_NODE_COLOR_BUFFER, "ResultLEDs", (u64)&((solid_color_data*)0)->ResultLEDs, IsOutputMember},
};
node_struct_member MemberList_vertical_color_fade_data[] = {
@ -82,11 +81,6 @@ node_struct_member MemberList_revolving_discs_data[] = {
{ MemberType_NODE_COLOR_BUFFER, "ResultLEDs", (u64)&((revolving_discs_data*)0)->ResultLEDs, IsOutputMember},
};
node_struct_member MemberList_michelle_data[] = {
{ MemberType_v4, "Color", (u64)&((michelle_data*)0)->Color, IsInputMember },
{ MemberType_NODE_COLOR_BUFFER, "LEDs", (u64)&((michelle_data*)0)->LEDs, IsInputMember | IsOutputMember},
};
node_specification NodeSpecifications[] = {
{ NodeType_FloatValue, "FloatValue", 10, MemberList_float_value_data, 8, 2, false},
{ NodeType_VectorValue, "VectorValue", 11, MemberList_vector_data, 32, 5, false},
@ -98,9 +92,8 @@ node_specification NodeSpecifications[] = {
{ NodeType_SolidColorProc, "SolidColorProc", 14, MemberList_solid_color_data, 36, 2, false},
{ NodeType_VerticalColorFadeProc, "VerticalColorFadeProc", 21, MemberList_vertical_color_fade_data, 44, 4, false},
{ NodeType_RevolvingDiscs, "RevolvingDiscs", 14, MemberList_revolving_discs_data, 60, 8, false},
{ NodeType_MichelleColorProc, "MichelleColorProc", 17, MemberList_michelle_data, 36, 2, false},
};
s32 NodeSpecificationsCount = 11;
s32 NodeSpecificationsCount = 10;
internal void CallNodeProc(interface_node* Node, u8* Data, led* LEDs, s32 LEDsCount, r32 DeltaTime)
{
@ -116,6 +109,5 @@ case NodeType_SwdColorProc: { SwdColorProc((swd_color_data*)Data, DeltaTime); }
case NodeType_SolidColorProc: { SolidColorProc((solid_color_data*)Data, DeltaTime); } break;
case NodeType_VerticalColorFadeProc: { VerticalColorFadeProc((vertical_color_fade_data*)Data, DeltaTime); } break;
case NodeType_RevolvingDiscs: { RevolvingDiscs((revolving_discs_data*)Data, DeltaTime); } break;
case NodeType_MichelleColorProc: { MichelleColorProc((michelle_data*)Data, DeltaTime); } break;
}
}

View File

@ -4,8 +4,8 @@ enum key_state_flags
KeyState_IsDown = 1 << 1,
};
#define KeyWasDown(event) ((event.State & KeyState_WasDown) > 0)
#define KeyIsDown(event) ((event.State & KeyState_IsDown) > 0)
#define KeyWasDown(event) ((event & KeyState_WasDown) > 0)
#define KeyIsDown(event) ((event & KeyState_IsDown) > 0)
struct input_entry
{
@ -30,12 +30,9 @@ struct mouse_state
v2 DeltaPos;
v2 DownPos;
b32 LeftButtonTransitionedDown;
b32 LeftButtonTransitionedUp;
b32 MiddleButtonTransitionedDown;
b32 MiddleButtonTransitionedUp;
b32 RightButtonTransitionedDown;
b32 RightButtonTransitionedUp;
b32 LeftButtonState;
b32 MiddleButtonState;
b32 RightButtonState;
};
internal input_queue
@ -78,17 +75,35 @@ AddInputEventEntry (input_queue* Queue, key_code Key,
internal b32
KeyTransitionedDown (input_entry Entry)
{
return (!KeyWasDown(Entry) && KeyIsDown(Entry));
return (!KeyWasDown(Entry.State) && KeyIsDown(Entry.State));
}
internal b32
KeyTransitionedUp (input_entry Entry)
{
return (KeyWasDown(Entry) && !KeyIsDown(Entry));
return (KeyWasDown(Entry.State) && !KeyIsDown(Entry.State));
}
internal b32
KeyHeldDown (input_entry Entry)
{
return (KeyWasDown(Entry) && KeyIsDown(Entry));
return (KeyWasDown(Entry.State) && KeyIsDown(Entry.State));
}
internal b32
MouseButtonTransitionedDown (b32 MouseButtonState)
{
return (!KeyWasDown(MouseButtonState) && KeyIsDown(MouseButtonState));
}
internal b32
MouseButtonTransitionedUp (b32 MouseButtonState)
{
return (KeyWasDown(MouseButtonState) && !KeyIsDown(MouseButtonState));
}
internal b32
MouseButtonHeldDown (b32 MouseButtonState)
{
return (KeyWasDown(MouseButtonState) && KeyIsDown(MouseButtonState));
}

View File

@ -624,6 +624,21 @@ v2 _Min, v2 _Max
_P.y >= _Min.y && _P.y <= _Max.y);
}
static bool
PointIsInRangeSafe (
v2 _P,
v2 _Min, v2 _Max
)
{
s32 MinX = GSMin(_Min.x, _Max.x);
s32 MinY = GSMin(_Min.y, _Max.y);
s32 MaxX = GSMax(_Min.x, _Max.x);
s32 MaxY = GSMax(_Min.y, _Max.y);
return (_P.x >= MinX && _P.x <= MaxX &&
_P.y >= MinY && _P.y <= MaxY);
}
inline v2
PointToPercentRange (v2 P, v2 Min, v2 Max)
{

View File

@ -871,6 +871,10 @@ GetPerformanceFrequency ()
internal s64
GetWallClock ()
{
#if 0
s64 Result = __rdtsc();
return Result;
#else
LARGE_INTEGER Time;
if (!QueryPerformanceCounter(&Time))
{
@ -878,6 +882,7 @@ GetWallClock ()
InvalidCodePath;
}
return (s64)Time.QuadPart;
#endif
}
/////////////////////////////////////////

View File

@ -207,7 +207,7 @@ EvaluateButton (render_command_buffer* RenderBuffer,
if (PointIsInRange(Mouse.Pos, Min, Max))
{
if (Mouse.LeftButtonTransitionedDown)
if (MouseButtonTransitionedDown(Mouse.LeftButtonState))
{
Result.Pressed = true;
}
@ -350,7 +350,7 @@ EvaluateSlider (render_command_buffer* RenderBuffer, v2 Min, v2 Max, string Labe
BGColor = Config.ButtonColor_Active;
}
if (Mouse.LeftButtonTransitionedDown)
if (MouseButtonTransitionedDown(Mouse.LeftButtonState))
{
if (PointIsInRange(Mouse.DownPos, Min, Max))
{
@ -581,7 +581,7 @@ EvaluateColorChannelSlider (render_command_buffer* RenderBuffer, v4 ChannelMask,
v2{0, 0}, v2{1, 0}, v2{1, 1}, v2{0, 1},
LeftColor, RightColor, RightColor, LeftColor);
if (Mouse.LeftButtonTransitionedDown)
if (MouseButtonTransitionedDown(Mouse.LeftButtonState))
{
if (PointIsInRange(Mouse.DownPos, Min, Max))
{
@ -605,7 +605,7 @@ EvaluateColorPicker (render_command_buffer* RenderBuffer, v4* Value, v2 PanelMin
b32 ShouldClose = false;
v2 PanelMax = v2{400, 500};
if (Mouse.LeftButtonTransitionedDown && !PointIsInRange(Mouse.Pos, PanelMin, PanelMax))
if (MouseButtonTransitionedDown(Mouse.LeftButtonState) && !PointIsInRange(Mouse.Pos, PanelMin, PanelMax))
{
ShouldClose = true;
}

View File

@ -2,7 +2,7 @@
NODE_STRUCT(solid_color_data)
{
NODE_IN(v4, Color);
NODE_COLOR_BUFFER_INOUT;
NODE_COLOR_BUFFER_OUT(Result);
};
NODE_PROC(SolidColorProc, solid_color_data)
@ -11,14 +11,14 @@ NODE_PROC(SolidColorProc, solid_color_data)
u8 G = (u8)GSClamp(0.f, (Data->Color.g * 255), 255.f);
u8 B = (u8)GSClamp(0.f, (Data->Color.b * 255), 255.f);
led* LED = Data->LEDs;
for (s32 l = 0; l < Data->LEDCount; l++)
led* LED = Data->ResultLEDs;
for (s32 l = 0; l < Data->ResultLEDCount; l++)
{
Assert(LED->Index >= 0 && LED->Index < Data->LEDCount);
Assert(LED->Index >= 0 && LED->Index < Data->ResultLEDCount);
Data->Colors[LED->Index].R = R;
Data->Colors[LED->Index].G = G;
Data->Colors[LED->Index].B = B;
Data->ResultColors[LED->Index].R = R;
Data->ResultColors[LED->Index].G = G;
Data->ResultColors[LED->Index].B = B;
LED++;
}
}
@ -69,23 +69,27 @@ NODE_STRUCT(revolving_discs_data)
NODE_PROC(RevolvingDiscs, revolving_discs_data)
{
DEBUG_TRACK_FUNCTION;
sacn_pixel Color = PackFloatsToSACNPixel(Data->Color.r, Data->Color.g, Data->Color.b);
v4 Center = v4{0, 0, 0, 1};
v4 Normal = v4{GSCos(Data->ThetaZ), 0, GSSin(Data->ThetaZ), 0}; // NOTE(Peter): dont' need to normalize. Should always be 1
v4 Right = Cross(Normal, v4{0, 1, 0, 0});
//Normal = RotateAround(Data->ThetaY, Right);
v4 FrontCenter = Center + (Normal * Data->DiscWidth);
v4 BackCenter = Center - (Normal * Data->DiscWidth);
r32 OuterRadiusSquared = Data->OuterRadius * Data->OuterRadius;
r32 InnerRadiusSquared = Data->InnerRadius * Data->InnerRadius;
led* LED = Data->ResultLEDs;
for (s32 l = 0; l < Data->ResultLEDCount; l++)
{
v4 Position = LED->Position;
v4 ToFront = Normalize(Position + FrontCenter);
v4 ToBack = Normalize(Position + BackCenter);
v4 ToFront = Position + FrontCenter;
v4 ToBack = Position + BackCenter;
r32 ToFrontDotNormal = Dot(ToFront, Normal);
r32 ToBackDotNormal = Dot(ToBack, Normal);
@ -93,8 +97,8 @@ NODE_PROC(RevolvingDiscs, revolving_discs_data)
ToFrontDotNormal = GSClamp01(ToFrontDotNormal * 1000);
ToBackDotNormal = GSClamp01(ToBackDotNormal * 1000);
r32 DistToCenter = Mag(Position);
if (DistToCenter < Data->OuterRadius && DistToCenter > Data->InnerRadius)
r32 SqDistToCenter = MagSqr(Position);
if (SqDistToCenter < OuterRadiusSquared && SqDistToCenter > InnerRadiusSquared)
{
if (XOR(ToFrontDotNormal > 0, ToBackDotNormal > 0))
{
@ -104,27 +108,3 @@ NODE_PROC(RevolvingDiscs, revolving_discs_data)
LED++;
}
}
NODE_STRUCT(michelle_data)
{
NODE_IN(v4, Color);
NODE_COLOR_BUFFER_INOUT;
};
NODE_PROC(MichelleColorProc, michelle_data)
{
u8 R = (u8)GSClamp(0.f, (Data->Color.r * 255), 255.f);
u8 G = (u8)GSClamp(0.f, (Data->Color.g * 255), 255.f);
u8 B = (u8)GSClamp(0.f, (Data->Color.b * 255), 255.f);
led* LED = Data->LEDs;
for (s32 l = 0; l < Data->LEDCount; l++)
{
Assert(LED->Index >= 0 && LED->Index < Data->LEDCount);
Data->Colors[LED->Index].R = R;
Data->Colors[LED->Index].G = G;
Data->Colors[LED->Index].B = B;
LED++;
}
}

View File

@ -380,6 +380,7 @@ HandleWindowMessage (MSG Message, window* Window, input_queue* InputQueue, mouse
AddInputEventEntry(InputQueue, KeyCode_MouseLeftButton, false, true,
ShiftDown, AltDown, CtrlDown, false);
Mouse->LeftButtonState = KeyState_IsDown & ~KeyState_WasDown;
Mouse->DownPos = Mouse->Pos;
}break;
@ -391,6 +392,7 @@ HandleWindowMessage (MSG Message, window* Window, input_queue* InputQueue, mouse
AddInputEventEntry(InputQueue, KeyCode_MouseMiddleButton, false, true,
ShiftDown, AltDown, CtrlDown, false);
Mouse->MiddleButtonState = KeyState_IsDown & ~KeyState_WasDown;
}break;
case WM_RBUTTONDOWN:
@ -401,6 +403,7 @@ HandleWindowMessage (MSG Message, window* Window, input_queue* InputQueue, mouse
AddInputEventEntry(InputQueue, KeyCode_MouseRightButton, false, true,
ShiftDown, AltDown, CtrlDown, false);
Mouse->RightButtonState = KeyState_IsDown & ~KeyState_WasDown;
}break;
case WM_LBUTTONUP:
@ -411,6 +414,7 @@ HandleWindowMessage (MSG Message, window* Window, input_queue* InputQueue, mouse
AddInputEventEntry(InputQueue, KeyCode_MouseLeftButton, true, false,
ShiftDown, AltDown, CtrlDown, false);
Mouse->LeftButtonState = ~KeyState_IsDown & KeyState_WasDown;
}break;
case WM_MBUTTONUP:
@ -421,6 +425,7 @@ HandleWindowMessage (MSG Message, window* Window, input_queue* InputQueue, mouse
AddInputEventEntry(InputQueue, KeyCode_MouseMiddleButton, true, false,
ShiftDown, AltDown, CtrlDown, false);
Mouse->MiddleButtonState = ~KeyState_IsDown & KeyState_WasDown;
}break;
case WM_RBUTTONUP:
@ -431,6 +436,7 @@ HandleWindowMessage (MSG Message, window* Window, input_queue* InputQueue, mouse
AddInputEventEntry(InputQueue, KeyCode_MouseRightButton, true, false,
ShiftDown, AltDown, CtrlDown, false);
Mouse->RightButtonState = ~KeyState_IsDown & KeyState_WasDown;
}break;
case WM_SYSKEYDOWN:
@ -493,6 +499,27 @@ SetApplicationLinks (context* Context, win32_dll_refresh DLL, work_queue* WorkQu
}
}
internal u8*
DEBUGAlloc(s32 ElementSize, s32 ElementCount)
{
return Win32BasicAlloc(ElementSize * ElementCount);
}
internal u8*
Win32Realloc(u8* Buf, s32 OldSize, s32 NewSize)
{
u8* NewMemory = Win32BasicAlloc(NewSize);
GSMemCopy(Buf, NewMemory, OldSize);
return NewMemory;
}
internal s32
Win32GetThreadId()
{
s32 Result = GetCurrentThreadId();
return Result;
}
int WINAPI
WinMain (
HINSTANCE HInstance,
@ -516,8 +543,14 @@ INT NCmdShow
r32 LastFrameSecondsElapsed = 0.0f;
GlobalDebugServices = (debug_services*)malloc(sizeof(debug_services));
InitDebugServices(GlobalDebugServices, (u8*)malloc(Megabytes(8)), Megabytes(16), 32000, PerformanceCountFrequency);
GlobalDebugServices->GetWallClock = GetWallClock;
s32 DebugThreadCount = PLATFORM_THREAD_COUNT + 1;
InitDebugServices(GlobalDebugServices,
PerformanceCountFrequency,
DEBUGAlloc,
Win32Realloc,
GetWallClock,
Win32GetThreadId,
DebugThreadCount);
mouse_state Mouse;
input_queue InputQueue;
@ -592,8 +625,8 @@ INT NCmdShow
WSADATA WSAData;
WSAStartup(MAKEWORD(2, 2), &WSAData);
platform_memory_result RenderMemory = Win32Alloc(Megabytes(32));
render_command_buffer RenderBuffer = AllocateRenderCommandBuffer(RenderMemory.Base, RenderMemory.Size);
platform_memory_result RenderMemory = Win32Alloc(Megabytes(12));
render_command_buffer RenderBuffer = AllocateRenderCommandBuffer(RenderMemory.Base, RenderMemory.Size, Win32Realloc);
Context.InitializeApplication(Context);
@ -601,6 +634,10 @@ INT NCmdShow
Context.WindowIsVisible = true;
while (Running)
{
if (GlobalDebugServices->RecordFrames)
{
EndDebugFrame(GlobalDebugServices);
}
DEBUG_TRACK_SCOPE(MainLoop);
ResetInputQueue(&InputQueue);
@ -624,6 +661,7 @@ INT NCmdShow
MSG Message;
while (PeekMessageA(&Message, MainWindow.Handle, 0, 0, PM_REMOVE))
{
DEBUG_TRACK_SCOPE(PeekWindowsMessages);
HandleWindowMessage(Message, &MainWindow, &InputQueue, &Mouse);
}
@ -641,6 +679,35 @@ INT NCmdShow
RenderCommandBuffer(RenderBuffer);
ClearRenderBuffer(&RenderBuffer);
if (Mouse.LeftButtonState & KeyState_WasDown &&
!((Mouse.LeftButtonState & KeyState_IsDown) > 0))
{
Mouse.LeftButtonState = 0;
} else if (Mouse.LeftButtonState & KeyState_IsDown)
{
Mouse.LeftButtonState |= KeyState_WasDown;
}
if (Mouse.MiddleButtonState & KeyState_WasDown &&
!((Mouse.LeftButtonState & KeyState_IsDown) > 0))
{
Mouse.MiddleButtonState = 0;
} else if (Mouse.MiddleButtonState & KeyState_IsDown)
{
Mouse.MiddleButtonState |= KeyState_WasDown;
}
if (Mouse.RightButtonState & KeyState_WasDown &&
!((Mouse.LeftButtonState & KeyState_IsDown) > 0))
{
Mouse.RightButtonState = 0;
} else if (Mouse.RightButtonState & KeyState_IsDown)
{
Mouse.RightButtonState |= KeyState_WasDown;
}
///////////////////////////////////
// Finish Up
//////////////////////////////////
@ -654,6 +721,7 @@ INT NCmdShow
while (SecondsElapsed < TargetSecondsPerFrame)
{
DEBUG_TRACK_SCOPE(UnusedTime);
u32 SleepTime = 1000.0f * (TargetSecondsPerFrame - SecondsElapsed);
Sleep(SleepTime);
SecondsElapsed = GetSecondsElapsed(LastFrameEnd, GetWallClock(), PerformanceCountFrequency);

View File

@ -1,5 +1,10 @@
TODO FOLDHAUS
YOU WERE IN THE MIDDLE OF
You just got the profiler view rudimentarily working and were about to start to reimplement the
scope list view. You need to start tracking debug interface state somehow, and it would be good
to separate that out from global debug state
BUGS
- Typing a period into a float value doesn't register. Problem here is that we arent' translating key presses into characters at the win32 layer. Need to do that.
@ -56,6 +61,7 @@ Structure
- motion
Renderer
- Render layers
- Mouse Picking - point at a led and see info about it
- Camera: pan
- Camera: zoom
@ -78,6 +84,8 @@ Command Line
- select a channel/pattern
Optimization
- investigate the memory access pattern of the SACN / LED systems. Guessing they are very slow
- look into why debug logging functions seems to incur a large hit on framrate
- patterns are asking to be multithreaded
- probably want to convert as much color functions to use u32 Packed Colors
- - Probably want to think about this more. What about supporting different color depths