diff --git a/src/foldhaus_app.cpp b/src/foldhaus_app.cpp index 2875870..7733949 100644 --- a/src/foldhaus_app.cpp +++ b/src/foldhaus_app.cpp @@ -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) diff --git a/src/foldhaus_debug.h b/src/foldhaus_debug.h index 960cd23..d82b20f 100644 --- a/src/foldhaus_debug.h +++ b/src/foldhaus_debug.h @@ -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); - - Services->ScopeHistogramUsed = 0; +} + +internal debug_frame* +GetCurrentDebugFrame (debug_services* Services) +{ + debug_frame* Result = Services->Frames + Services->CurrentDebugFrame; + return Result; +} + +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); - } -} - -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) + scope_record Record = ThreadRecords->Calls[i]; + s32 Index = GetIndexForNameHash (Frame, Record.NameHash); + collated_scope_record* CollatedRecord = Frame->CollatedScopes + Index; + + 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; +} + +internal scope_name* +GetOrAddNameHashEntry(debug_frame* Frame, u32 NameHash) +{ + scope_name* Result = 0; - s32 OnePastIndex = InterlockedIncrement((long*)&Services->TrackedScopesCount); - Assert(OnePastIndex <= Services->TrackedScopesMax); - Result = Services->TrackedScopes + OnePastIndex - 1; - - 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); + } } }; diff --git a/src/foldhaus_debug_visuals.h b/src/foldhaus_debug_visuals.h index 3beb0bb..14e43e4 100644 --- a/src/foldhaus_debug_visuals.h +++ b/src/foldhaus_debug_visuals.h @@ -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); diff --git a/src/foldhaus_node.cpp b/src/foldhaus_node.cpp index 4484a10..f1de528 100644 --- a/src/foldhaus_node.cpp +++ b/src/foldhaus_node.cpp @@ -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)) { diff --git a/src/foldhaus_renderer.cpp b/src/foldhaus_renderer.cpp index 7968bea..dbec96d 100644 --- a/src/foldhaus_renderer.cpp +++ b/src/foldhaus_renderer.cpp @@ -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(); diff --git a/src/foldhaus_renderer.h b/src/foldhaus_renderer.h index b42c8d6..5de719a 100644 --- a/src/foldhaus_renderer.h +++ b/src/foldhaus_renderer.h @@ -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; diff --git a/src/generated/foldhaus_nodes_generated.cpp b/src/generated/foldhaus_nodes_generated.cpp index 5e9c930..a71dd2a 100644 --- a/src/generated/foldhaus_nodes_generated.cpp +++ b/src/generated/foldhaus_nodes_generated.cpp @@ -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; } } diff --git a/src/gs_input.h b/src/gs_input.h index 32c27b1..d77d12a 100644 --- a/src/gs_input.h +++ b/src/gs_input.h @@ -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)); } \ No newline at end of file diff --git a/src/gs_vector_matrix.h b/src/gs_vector_matrix.h index d127297..6e9ec29 100644 --- a/src/gs_vector_matrix.h +++ b/src/gs_vector_matrix.h @@ -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) { diff --git a/src/gs_win32.cpp b/src/gs_win32.cpp index e798741..7028457 100644 --- a/src/gs_win32.cpp +++ b/src/gs_win32.cpp @@ -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 } ///////////////////////////////////////// diff --git a/src/interface.h b/src/interface.h index 364f8cd..32acbae 100644 --- a/src/interface.h +++ b/src/interface.h @@ -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; } diff --git a/src/test_patterns.h b/src/test_patterns.h index 4c019a9..cf40866 100644 --- a/src/test_patterns.h +++ b/src/test_patterns.h @@ -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)) { @@ -103,28 +107,4 @@ 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++; - } -} +} \ No newline at end of file diff --git a/src/win32_foldhaus.cpp b/src/win32_foldhaus.cpp index 6f63d8b..422dd55 100644 --- a/src/win32_foldhaus.cpp +++ b/src/win32_foldhaus.cpp @@ -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); diff --git a/todo.txt b/todo.txt index 7cbe159..e410965 100644 --- a/todo.txt +++ b/todo.txt @@ -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