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; 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; r32 HalfWidth = Data->LEDHalfWidth;
@ -235,7 +238,7 @@ DrawLEDsInBufferRangeJob (s32 ThreadID, void* JobData)
led* LED = Data->LEDs + Data->StartIndex; led* LED = Data->LEDs + Data->StartIndex;
for (s32 LEDIdx = 0; for (s32 LEDIdx = 0;
LEDIdx < DrawCommandsCount; LEDIdx < LEDCount;
LEDIdx++) LEDIdx++)
{ {
sacn_pixel SACNColor = Data->Colors[LED->Index]; sacn_pixel SACNColor = Data->Colors[LED->Index];
@ -248,9 +251,10 @@ DrawLEDsInBufferRangeJob (s32 ThreadID, void* JobData)
v4 P2 = P2_In + V4Position; v4 P2 = P2_In + V4Position;
v4 P3 = P3_In + V4Position; v4 P3 = P3_In + V4Position;
DEBUG_TRACK_SCOPE(PushLEDTris); SetTri3DInBatch(Data->Batch, BatchReservedRange.Start + TrisUsed++,
PushTri3DOnBatch(Data->Batch, P0, P1, P2, UV0, UV1, UV2, Color, Color, Color); 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, P2, P3, UV0, UV2, UV3, Color, Color, Color);
LED++; 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) UPDATE_AND_RENDER(UpdateAndRender)
{ {
DEBUG_TRACK_FUNCTION;
app_state* State = (app_state*)Context.MemoryBase; app_state* State = (app_state*)Context.MemoryBase;
// NOTE(Peter): We do this at the beginning because all the render commands are stored in Transient, // 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. // incorrect to clear the arena, and then access the memory later.
ClearArena(State->Transient); ClearArena(State->Transient);
{ HandleInput(State, InputQueue, Mouse);
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);
}
if (State->LEDBufferList) if (State->LEDBufferList)
{ {
@ -625,6 +622,7 @@ UPDATE_AND_RENDER(UpdateAndRender)
DEBUG_IF(GlobalDebugServices->Interface.RenderSculpture) // DebugServices RenderSculpture Toggle DEBUG_IF(GlobalDebugServices->Interface.RenderSculpture) // DebugServices RenderSculpture Toggle
{ {
DEBUG_TRACK_SCOPE(RenderSculpture);
s32 JobsNeeded = PLATFORM_THREAD_COUNT; s32 JobsNeeded = PLATFORM_THREAD_COUNT;
s32 LEDBufferSize = IntegerDivideRoundUp(State->TotalLEDsCount, JobsNeeded); s32 LEDBufferSize = IntegerDivideRoundUp(State->TotalLEDsCount, JobsNeeded);
@ -738,8 +736,6 @@ UPDATE_AND_RENDER(UpdateAndRender)
State->Interface, Context.WindowWidth, Context.WindowHeight - TopBarHeight, State->Interface, Context.WindowWidth, Context.WindowHeight - TopBarHeight,
Context.DeltaTime, State, State->Camera, Mouse, State->Transient); Context.DeltaTime, State, State->Camera, Mouse, State->Transient);
} }
EndDebugFrame(GlobalDebugServices);
} }
CLEANUP_APPLICATION(CleanupApplication) CLEANUP_APPLICATION(CleanupApplication)

View File

@ -1,21 +1,75 @@
#define SCOPE_NAME_LENGTH 256 #define SCOPE_NAME_LENGTH 256
struct scope_time_record struct scope_record
{ {
char ScopeName_[SCOPE_NAME_LENGTH]; u32 NameHash;
string ScopeName; s64 StartCycles;
s64 EndCycles;
u32 Duration_Cycles; 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 struct debug_interface
{ {
b32 ShowCameraMouse; b32 ShowCameraMouse;
b32 ShowTrackedScopes; b32 ShowTrackedScopes;
b32 RenderSculpture; b32 RenderSculpture;
b32 SendSACNData; b32 SendSACNData;
s32 FrameView;
}; };
typedef s32 debug_get_thread_id();
typedef s64 debug_timing_proc(); 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 #define HISTOGRAM_DEPTH 10
struct debug_histogram_entry struct debug_histogram_entry
@ -34,34 +88,101 @@ struct debug_histogram_entry
u32 Total_CallCount; u32 Total_CallCount;
}; };
#define SCOPE_HISTOGRAM_SIZE 512 #define DEBUG_FRAME_COUNT 128
struct debug_services struct debug_services
{ {
s32 TrackedScopesCount;
s32 TrackedScopesMax;
scope_time_record* TrackedScopes;
s64 PerformanceCountFrequency; s64 PerformanceCountFrequency;
memory_arena DebugStorage;
b32 RecordFrames;
s32 CurrentDebugFrame;
debug_frame Frames[DEBUG_FRAME_COUNT];
debug_interface Interface; debug_interface Interface;
debug_get_thread_id* GetThreadId;
debug_timing_proc* GetWallClock; debug_timing_proc* GetWallClock;
debug_alloc* Alloc;
debug_histogram_entry* ScopeHistogramUnsorted; debug_realloc* Realloc;
debug_histogram_entry* ScopeHistogramSorted;
s32 ScopeHistogramUsed;
}; };
internal void 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; // NOTE(Peter): We use the same size as scope names because we're only storing a single instance
Services->TrackedScopesMax = TrackedScopesMax; // per scope. If ScopeNamesMax can't hold all the scopes, this will never get filled and
Services->TrackedScopes = PushArray(&Services->DebugStorage, scope_time_record, TrackedScopesMax); // 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; Services->Interface.RenderSculpture = true;
@ -71,182 +192,197 @@ InitDebugServices (debug_services* Services, u8* Memory, s32 MemorySize, s32 Tra
Services->Interface.ShowTrackedScopes = false; Services->Interface.ShowTrackedScopes = false;
Services->Interface.RenderSculpture = true; Services->Interface.RenderSculpture = true;
Services->Interface.SendSACNData = false; 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)
Services->ScopeHistogramUsed = 0; {
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 internal s32
DEBUGFindScopeHistogram (debug_services* Services, string Name) GetIndexForNameHash(debug_frame* Frame, u32 NameHash)
{ {
s32 Result = -1; 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; 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; return Result;
} }
internal s32 internal debug_scope_record_list*
DEBUGAddScopeHistogram (debug_services* Services, scope_time_record Record) GetScopeListForThreadInFrame(debug_services* Services, debug_frame* Frame)
{ {
Assert(Services->ScopeHistogramUsed < SCOPE_HISTOGRAM_SIZE); debug_scope_record_list* List = 0;
s32 Result = Services->ScopeHistogramUsed++; s32 CurrentThreadId = Services->GetThreadId();
for (s32 Offset = 0; Offset < Frame->ThreadCount; Offset++)
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)
{ {
Entry->PerFrame_Cycles[FrameIndex] += Record.Duration_Cycles; s32 Index = (CurrentThreadId + Offset) % Frame->ThreadCount;
Entry->PerFrame_CallCount[FrameIndex]++; if (Frame->ThreadCalls[Index].ThreadId == CurrentThreadId)
}
}
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 CurrentFrame1 = DestList[i].CurrentFrame; List = Frame->ThreadCalls + Index;
s32 V1 = DestList[i].Average_Cycles; //PerFrame_Cycles[CurrentFrame1]; break;
if (V0 < V1) }
{ else if (Frame->ThreadCalls[Index].ThreadId == 0)
DestList[i + 1] = Source; {
break; Frame->ThreadCalls[Index].ThreadId = CurrentThreadId;
} List = Frame->ThreadCalls + Index;
else break;
{
DestList[i + 1] = DestList[i];
}
} }
} }
else
{ Assert(List);
DestList[0] = Source; return List;
}
} }
internal void 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 if (CollatedRecord->NameHash != Record.NameHash)
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)
{ {
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 internal void
EndDebugFrame (debug_services* Services) 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); s64 FrameTotalCycles = ClosingFrame->FrameEndCycles - ClosingFrame->FrameStartCycles;
Services->TrackedScopesCount = 0;
for (s32 i = 0; i < Services->ScopeHistogramUsed; i++) for (s32 t = 0; t < ClosingFrame->ThreadCount; t++)
{ {
s32 NewFrame = Services->ScopeHistogramUnsorted[i].CurrentFrame + 1; CollateThreadScopeCalls(ClosingFrame->ThreadCalls + t, ClosingFrame);
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;
} }
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* internal u32
PushScopeRecord(string ScopeName, debug_services* Services) 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); for (s32 Offset = 0; Offset < Frame->ScopeNamesMax; Offset++)
Assert(OnePastIndex <= Services->TrackedScopesMax); {
Result = Services->TrackedScopes + OnePastIndex - 1; u32 Index = (NameHash + Offset) % Frame->ScopeNamesMax;
if ((Frame->ScopeNamesHash[Index].Hash == 0) || (Frame->ScopeNamesHash[Index].Hash == NameHash))
Result->ScopeName = MakeString(Result->ScopeName_, SCOPE_NAME_LENGTH); {
CopyStringTo(ScopeName, &Result->ScopeName); Result = Frame->ScopeNamesHash + Index;
break;
}
}
return Result; return Result;
} }
internal void internal u32
LogScopeTime (debug_services* Services, string ScopeName, u64 CyclesElapsed) BeginTrackingScopeAndGetNameHash (debug_services* Services, char* ScopeName)
{ {
scope_time_record* Record = PushScopeRecord(ScopeName, Services); debug_frame* CurrentFrame = GetCurrentDebugFrame(Services);
Record->Duration_Cycles = CyclesElapsed; 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) internal r32 DEBUGGetSecondsElapsed (s64 Start, s64 End, r32 PerformanceCountFrequency)
@ -255,7 +391,7 @@ internal r32 DEBUGGetSecondsElapsed (s64 Start, s64 End, r32 PerformanceCountFre
return Result; return Result;
} }
#if 1 #ifdef DEBUG
#define DEBUG_TRACK_FUNCTION scope_tracker ScopeTracker (__FUNCTION__, GlobalDebugServices) #define DEBUG_TRACK_FUNCTION scope_tracker ScopeTracker (__FUNCTION__, GlobalDebugServices)
#define DEBUG_TRACK_SCOPE(name) scope_tracker ScopeTracker_##name (#name, GlobalDebugServices) #define DEBUG_TRACK_SCOPE(name) scope_tracker ScopeTracker_##name (#name, GlobalDebugServices)
#else #else
@ -265,27 +401,29 @@ internal r32 DEBUGGetSecondsElapsed (s64 Start, s64 End, r32 PerformanceCountFre
struct scope_tracker struct scope_tracker
{ {
s64 ScopeStart; s64 ScopeStart;
u32 ScopeNameHash;
char ScopeName_[SCOPE_NAME_LENGTH];
string ScopeName;
debug_services* DebugServices; debug_services* DebugServices;
scope_tracker(char* ScopeName, debug_services* DebugServices) scope_tracker(char* ScopeName, debug_services* DebugServices)
{ {
this->ScopeName = MakeString(this->ScopeName_, SCOPE_NAME_LENGTH); if (DebugServices->RecordFrames)
CopyCharArrayToString(ScopeName, &this->ScopeName); {
this->ScopeStart = DebugServices->GetWallClock(); this->ScopeNameHash = BeginTrackingScopeAndGetNameHash(DebugServices, ScopeName);
this->DebugServices = DebugServices; this->ScopeStart = DebugServices->GetWallClock();
this->DebugServices = DebugServices;
}
else
{
this->DebugServices = 0;
}
} }
~scope_tracker() ~scope_tracker()
{ {
s64 ScopeEnd = DebugServices->GetWallClock(); if (this->DebugServices) // NOTE(Peter): If DebugServices == 0, then we werent' recording this frame
u32 CyclesElapsed = (u32)(ScopeEnd - this->ScopeStart); {
#if 0 s64 ScopeEnd = this->DebugServices->GetWallClock();
r32 SecondsElapsed = DEBUGGetSecondsElapsed(this->ScopeStart, ScopeEnd, DebugServices->PerformanceCountFrequency); PushScopeTimeOnFrame(this->DebugServices, this->ScopeNameHash, this->ScopeStart, ScopeEnd);
#endif }
LogScopeTime(DebugServices, ScopeName, CyclesElapsed);
} }
}; };

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 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) 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); string DebugString = InitializeEmptyString(PushArray(Transient, char, 256), 256);
if (GlobalDebugServices->Interface.ShowCameraMouse || GlobalDebugServices->Interface.ShowTrackedScopes) if (GlobalDebugServices->Interface.ShowCameraMouse)
{ {
PushRenderQuad2D(RenderBuffer, PushRenderQuad2D(RenderBuffer,
v2{TopOfDebugView.x, TopOfDebugView.y - 500}, 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}); DrawString(RenderBuffer, DebugString, Interface.Font, TopOfScreenLinePos, v4{1.0f, 1.0f, 1.0f, 1.0f});
TopOfScreenLinePos.y -= NewLineYOffset(*Interface.Font); TopOfScreenLinePos.y -= NewLineYOffset(*Interface.Font);
b32 LeftButtonIsDown = (Mouse.LeftButtonState & KeyState_IsDown) > 0;
b32 LeftButtonWasDown = (Mouse.LeftButtonState & KeyState_WasDown) > 0;
s32 MousePrecision = 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.x,
MousePrecision, Mouse.Pos.y, MousePrecision, Mouse.Pos.y,
MousePrecision, Mouse.DownPos.x, 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, DrawString(RenderBuffer, DebugString, Interface.Font,
TopOfScreenLinePos, WhiteV4); TopOfScreenLinePos, WhiteV4);
TopOfScreenLinePos.y -= NewLineYOffset(*Interface.Font); TopOfScreenLinePos.y -= NewLineYOffset(*Interface.Font);
@ -116,12 +312,24 @@ DrawDebugInterface (render_command_buffer* RenderBuffer, r32 StartX, interface_c
DrawString(RenderBuffer, DebugString, Interface.Font, DrawString(RenderBuffer, DebugString, Interface.Font,
TopOfScreenLinePos, WhiteV4); TopOfScreenLinePos, WhiteV4);
TopOfScreenLinePos.y -= NewLineYOffset(*Interface.Font); 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) 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++) for (s32 i = 0; i < GlobalDebugServices->ScopeHistogramUsed; i++)
{ {
v2 Register = v2{ColumnsStartX, TopOfScreenLinePos.y}; v2 Register = v2{ColumnsStartX, TopOfScreenLinePos.y};
@ -161,6 +369,7 @@ DrawDebugInterface (render_command_buffer* RenderBuffer, r32 StartX, interface_c
} }
#endif
} }
ZeroArenaToSnapshot(Transient, StartTempMemory); ZeroArenaToSnapshot(Transient, StartTempMemory);

View File

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

View File

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

View File

@ -186,12 +186,18 @@ struct render_command_set_render_mode
b32 UseDepthBuffer; b32 UseDepthBuffer;
}; };
typedef u8* renderer_realloc(u8* Base, s32 CurrentSize, s32 NewSize);
#define COMMAND_BUFFER_MIN_GROW_SIZE Megabytes(2)
struct render_command_buffer struct render_command_buffer
{ {
u8* CommandMemory; u8* CommandMemory;
s32 CommandMemoryUsed; s32 CommandMemoryUsed;
s32 CommandMemorySize; s32 CommandMemorySize;
renderer_realloc* Realloc;
s32 ViewWidth; s32 ViewWidth;
s32 ViewHeight; s32 ViewHeight;
}; };
@ -230,15 +236,29 @@ PackColorStructR32 (r32 In_R, r32 In_G, r32 In_B, r32 In_A)
return Result; 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 // Batch
internal s32 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->Max = TriCount;
Constructor->Count = 0; Constructor->Count = 0;
@ -251,15 +271,13 @@ PushQuad3DBatch (render_command_buffer* Buffer, render_quad_batch_constructor* C
} }
internal s32 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); GSZeroMemory(MemStart, DataSize);
Constructor->Max = QuadCount; Constructor->Max = QuadCount;
Constructor->Count = 0; Constructor->Count = 0;
Constructor->Vertecies = (v4*)(MemStart + BATCH_2D_VERTECIES_OFFSET(QuadCount)); Constructor->Vertecies = (v4*)(MemStart + BATCH_2D_VERTECIES_OFFSET(QuadCount));
Constructor->UVs = (v2*)(MemStart + BATCH_2D_UVS_OFFSET(QuadCount)); Constructor->UVs = (v2*)(MemStart + BATCH_2D_UVS_OFFSET(QuadCount));
Constructor->ColorsV = (v4*)(MemStart + BATCH_2D_COLORS_OFFSET(QuadCount)); Constructor->ColorsV = (v4*)(MemStart + BATCH_2D_COLORS_OFFSET(QuadCount));
@ -280,31 +298,58 @@ ThreadSafeIncrementQuadConstructorCount (render_quad_batch_constructor* Construc
return Result; 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 inline void
PushTri3DOnBatch (render_quad_batch_constructor* Constructor, PushTri3DOnBatch (render_quad_batch_constructor* Constructor,
v4 P0, v4 P1, v4 P2, v4 P0, v4 P1, v4 P2,
v2 UV0, v2 UV1, v2 UV2, v2 UV0, v2 UV1, v2 UV2,
v4 C0, v4 C1, v4 C2) v4 C0, v4 C1, v4 C2)
{ {
DEBUG_TRACK_FUNCTION;
s32 Tri = ThreadSafeIncrementQuadConstructorCount(Constructor); s32 Tri = ThreadSafeIncrementQuadConstructorCount(Constructor);
// Vertecies SetTri3DInBatch(Constructor, Tri, P0, P1, P2, UV0, UV1, UV2, C0, C1, C2);
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;
}; };
internal void internal void
PushQuad3DOnBatch (render_quad_batch_constructor* Constructor, v4 P0, v4 P1, v4 P2, v4 P3, v2 UVMin, v2 UVMax, v4 Color) 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, 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); 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, v2 UV0, v2 UV1, v2 UV2, v2 UV3,
v4 C0, v4 C1, v4 C2, v4 C3) v4 C0, v4 C1, v4 C2, v4 C3)
{ {
DEBUG_TRACK_FUNCTION;
s32 Quad = ThreadSafeIncrementQuadConstructorCount(Constructor); s32 Quad = ThreadSafeIncrementQuadConstructorCount(Constructor);
v2* Vertecies = (v2*)Constructor->Vertecies; v2* Vertecies = (v2*)Constructor->Vertecies;
@ -367,6 +414,8 @@ PushQuad2DOnBatch (render_quad_batch_constructor* Constructor,
internal void internal void
PushQuad2DOnBatch (render_quad_batch_constructor* Constructor, v2 P0, v2 P1, v2 P2, v2 P3, v2 UVMin, v2 UVMax, v4 Color) 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); s32 Quad = ThreadSafeIncrementQuadConstructorCount(Constructor);
v2* Vertecies = (v2*)Constructor->Vertecies; v2* Vertecies = (v2*)Constructor->Vertecies;
@ -422,6 +471,7 @@ PushLine2DOnBatch (render_quad_batch_constructor* Constructor, v2 P0, v2 P1, r32
internal u8* internal u8*
PushRenderCommand_ (render_command_buffer* CommandBuffer, render_command_type CommandType, s32 CommandSize) PushRenderCommand_ (render_command_buffer* CommandBuffer, render_command_type CommandType, s32 CommandSize)
{ {
ResizeBufferIfNecessary(CommandBuffer, CommandSize);
Assert(CommandBuffer->CommandMemoryUsed + CommandSize <= CommandBuffer->CommandMemorySize); Assert(CommandBuffer->CommandMemoryUsed + CommandSize <= CommandBuffer->CommandMemorySize);
render_command_header* Header = (render_command_header*)(CommandBuffer->CommandMemory + CommandBuffer->CommandMemoryUsed); 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 internal render_quad_batch_constructor
PushRenderQuad2DBatch(render_command_buffer* Buffer, s32 QuadCount) 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_quad_batch_constructor Result = {};
render_batch_command_quad_2d* Command = PushRenderCommand(Buffer, render_batch_command_quad_2d); render_batch_command_quad_2d* Command = PushRenderCommand(Buffer, render_batch_command_quad_2d);
Command->QuadCount = QuadCount; Command->QuadCount = QuadCount;
Command->DataSize = PushQuad2DBatch(Buffer, &Result, QuadCount, (u8*)(Command + 1)); Command->DataSize = PushQuad2DBatch(Buffer, &Result, QuadCount, DataSize, (u8*)(Command + 1));
return Result; return Result;
} }
@ -515,11 +569,16 @@ PushRenderLine2D (render_command_buffer* Buffer, v2 P0, v2 P1, r32 Thickness, v4
internal render_quad_batch_constructor internal render_quad_batch_constructor
PushRenderQuad3DBatch(render_command_buffer* Buffer, s32 QuadCount) 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_quad_batch_constructor Result = {};
render_batch_command_quad_3d* Command = PushRenderCommand(Buffer, render_batch_command_quad_3d); render_batch_command_quad_3d* Command = PushRenderCommand(Buffer, render_batch_command_quad_3d);
Command->QuadCount = QuadCount; Command->QuadCount = QuadCount;
Command->DataSize = PushQuad3DBatch(Buffer, &Result, QuadCount, (u8*)(Command + 1)); Command->DataSize = PushQuad3DBatch(Buffer, &Result, (u8*)(Command + 1), TriCount, DataSize);
return Result; return Result;
} }
@ -547,11 +606,15 @@ internal render_quad_batch_constructor
PushRenderTexture2DBatch(render_command_buffer* Buffer, s32 QuadCount, PushRenderTexture2DBatch(render_command_buffer* Buffer, s32 QuadCount,
render_texture Texture) render_texture Texture)
{ {
s32 DataSize = BATCH_2D_SIZE(QuadCount);
ResizeBufferIfNecessary(Buffer, DataSize);
Assert(Buffer->CommandMemoryUsed + DataSize <= Buffer->CommandMemorySize);
render_quad_batch_constructor Result = {}; render_quad_batch_constructor Result = {};
render_batch_command_texture_2d* Command = PushRenderCommand(Buffer, render_batch_command_texture_2d); render_batch_command_texture_2d* Command = PushRenderCommand(Buffer, render_batch_command_texture_2d);
Command->QuadCount = QuadCount; 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; Command->Texture = Texture;
return Result; return Result;

View File

@ -11,7 +11,6 @@ NodeType_SwdColorProc,
NodeType_SolidColorProc, NodeType_SolidColorProc,
NodeType_VerticalColorFadeProc, NodeType_VerticalColorFadeProc,
NodeType_RevolvingDiscs, NodeType_RevolvingDiscs,
NodeType_MichelleColorProc,
NodeType_Count, NodeType_Count,
}; };
@ -61,7 +60,7 @@ node_struct_member MemberList_swd_color_data[] = {
node_struct_member MemberList_solid_color_data[] = { node_struct_member MemberList_solid_color_data[] = {
{ MemberType_v4, "Color", (u64)&((solid_color_data*)0)->Color, IsInputMember }, { 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[] = { 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}, { 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[] = { node_specification NodeSpecifications[] = {
{ NodeType_FloatValue, "FloatValue", 10, MemberList_float_value_data, 8, 2, false}, { NodeType_FloatValue, "FloatValue", 10, MemberList_float_value_data, 8, 2, false},
{ NodeType_VectorValue, "VectorValue", 11, MemberList_vector_data, 32, 5, 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_SolidColorProc, "SolidColorProc", 14, MemberList_solid_color_data, 36, 2, false},
{ NodeType_VerticalColorFadeProc, "VerticalColorFadeProc", 21, MemberList_vertical_color_fade_data, 44, 4, 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_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) 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_SolidColorProc: { SolidColorProc((solid_color_data*)Data, DeltaTime); } break;
case NodeType_VerticalColorFadeProc: { VerticalColorFadeProc((vertical_color_fade_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_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, KeyState_IsDown = 1 << 1,
}; };
#define KeyWasDown(event) ((event.State & KeyState_WasDown) > 0) #define KeyWasDown(event) ((event & KeyState_WasDown) > 0)
#define KeyIsDown(event) ((event.State & KeyState_IsDown) > 0) #define KeyIsDown(event) ((event & KeyState_IsDown) > 0)
struct input_entry struct input_entry
{ {
@ -30,12 +30,9 @@ struct mouse_state
v2 DeltaPos; v2 DeltaPos;
v2 DownPos; v2 DownPos;
b32 LeftButtonTransitionedDown; b32 LeftButtonState;
b32 LeftButtonTransitionedUp; b32 MiddleButtonState;
b32 MiddleButtonTransitionedDown; b32 RightButtonState;
b32 MiddleButtonTransitionedUp;
b32 RightButtonTransitionedDown;
b32 RightButtonTransitionedUp;
}; };
internal input_queue internal input_queue
@ -78,17 +75,35 @@ AddInputEventEntry (input_queue* Queue, key_code Key,
internal b32 internal b32
KeyTransitionedDown (input_entry Entry) KeyTransitionedDown (input_entry Entry)
{ {
return (!KeyWasDown(Entry) && KeyIsDown(Entry)); return (!KeyWasDown(Entry.State) && KeyIsDown(Entry.State));
} }
internal b32 internal b32
KeyTransitionedUp (input_entry Entry) KeyTransitionedUp (input_entry Entry)
{ {
return (KeyWasDown(Entry) && !KeyIsDown(Entry)); return (KeyWasDown(Entry.State) && !KeyIsDown(Entry.State));
} }
internal b32 internal b32
KeyHeldDown (input_entry Entry) 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); _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 inline v2
PointToPercentRange (v2 P, v2 Min, v2 Max) PointToPercentRange (v2 P, v2 Min, v2 Max)
{ {

View File

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

View File

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

View File

@ -2,7 +2,7 @@
NODE_STRUCT(solid_color_data) NODE_STRUCT(solid_color_data)
{ {
NODE_IN(v4, Color); NODE_IN(v4, Color);
NODE_COLOR_BUFFER_INOUT; NODE_COLOR_BUFFER_OUT(Result);
}; };
NODE_PROC(SolidColorProc, solid_color_data) 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 G = (u8)GSClamp(0.f, (Data->Color.g * 255), 255.f);
u8 B = (u8)GSClamp(0.f, (Data->Color.b * 255), 255.f); u8 B = (u8)GSClamp(0.f, (Data->Color.b * 255), 255.f);
led* LED = Data->LEDs; led* LED = Data->ResultLEDs;
for (s32 l = 0; l < Data->LEDCount; l++) 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->ResultColors[LED->Index].R = R;
Data->Colors[LED->Index].G = G; Data->ResultColors[LED->Index].G = G;
Data->Colors[LED->Index].B = B; Data->ResultColors[LED->Index].B = B;
LED++; LED++;
} }
} }
@ -69,23 +69,27 @@ NODE_STRUCT(revolving_discs_data)
NODE_PROC(RevolvingDiscs, 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); sacn_pixel Color = PackFloatsToSACNPixel(Data->Color.r, Data->Color.g, Data->Color.b);
v4 Center = v4{0, 0, 0, 1}; 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 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}); v4 Right = Cross(Normal, v4{0, 1, 0, 0});
//Normal = RotateAround(Data->ThetaY, Right);
v4 FrontCenter = Center + (Normal * Data->DiscWidth); v4 FrontCenter = Center + (Normal * Data->DiscWidth);
v4 BackCenter = 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; led* LED = Data->ResultLEDs;
for (s32 l = 0; l < Data->ResultLEDCount; l++) for (s32 l = 0; l < Data->ResultLEDCount; l++)
{ {
v4 Position = LED->Position; v4 Position = LED->Position;
v4 ToFront = Normalize(Position + FrontCenter); v4 ToFront = Position + FrontCenter;
v4 ToBack = Normalize(Position + BackCenter); v4 ToBack = Position + BackCenter;
r32 ToFrontDotNormal = Dot(ToFront, Normal); r32 ToFrontDotNormal = Dot(ToFront, Normal);
r32 ToBackDotNormal = Dot(ToBack, Normal); r32 ToBackDotNormal = Dot(ToBack, Normal);
@ -93,8 +97,8 @@ NODE_PROC(RevolvingDiscs, revolving_discs_data)
ToFrontDotNormal = GSClamp01(ToFrontDotNormal * 1000); ToFrontDotNormal = GSClamp01(ToFrontDotNormal * 1000);
ToBackDotNormal = GSClamp01(ToBackDotNormal * 1000); ToBackDotNormal = GSClamp01(ToBackDotNormal * 1000);
r32 DistToCenter = Mag(Position); r32 SqDistToCenter = MagSqr(Position);
if (DistToCenter < Data->OuterRadius && DistToCenter > Data->InnerRadius) if (SqDistToCenter < OuterRadiusSquared && SqDistToCenter > InnerRadiusSquared)
{ {
if (XOR(ToFrontDotNormal > 0, ToBackDotNormal > 0)) if (XOR(ToFrontDotNormal > 0, ToBackDotNormal > 0))
{ {
@ -103,28 +107,4 @@ NODE_PROC(RevolvingDiscs, revolving_discs_data)
} }
LED++; 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, AddInputEventEntry(InputQueue, KeyCode_MouseLeftButton, false, true,
ShiftDown, AltDown, CtrlDown, false); ShiftDown, AltDown, CtrlDown, false);
Mouse->LeftButtonState = KeyState_IsDown & ~KeyState_WasDown;
Mouse->DownPos = Mouse->Pos; Mouse->DownPos = Mouse->Pos;
}break; }break;
@ -391,6 +392,7 @@ HandleWindowMessage (MSG Message, window* Window, input_queue* InputQueue, mouse
AddInputEventEntry(InputQueue, KeyCode_MouseMiddleButton, false, true, AddInputEventEntry(InputQueue, KeyCode_MouseMiddleButton, false, true,
ShiftDown, AltDown, CtrlDown, false); ShiftDown, AltDown, CtrlDown, false);
Mouse->MiddleButtonState = KeyState_IsDown & ~KeyState_WasDown;
}break; }break;
case WM_RBUTTONDOWN: case WM_RBUTTONDOWN:
@ -401,6 +403,7 @@ HandleWindowMessage (MSG Message, window* Window, input_queue* InputQueue, mouse
AddInputEventEntry(InputQueue, KeyCode_MouseRightButton, false, true, AddInputEventEntry(InputQueue, KeyCode_MouseRightButton, false, true,
ShiftDown, AltDown, CtrlDown, false); ShiftDown, AltDown, CtrlDown, false);
Mouse->RightButtonState = KeyState_IsDown & ~KeyState_WasDown;
}break; }break;
case WM_LBUTTONUP: case WM_LBUTTONUP:
@ -411,6 +414,7 @@ HandleWindowMessage (MSG Message, window* Window, input_queue* InputQueue, mouse
AddInputEventEntry(InputQueue, KeyCode_MouseLeftButton, true, false, AddInputEventEntry(InputQueue, KeyCode_MouseLeftButton, true, false,
ShiftDown, AltDown, CtrlDown, false); ShiftDown, AltDown, CtrlDown, false);
Mouse->LeftButtonState = ~KeyState_IsDown & KeyState_WasDown;
}break; }break;
case WM_MBUTTONUP: case WM_MBUTTONUP:
@ -421,6 +425,7 @@ HandleWindowMessage (MSG Message, window* Window, input_queue* InputQueue, mouse
AddInputEventEntry(InputQueue, KeyCode_MouseMiddleButton, true, false, AddInputEventEntry(InputQueue, KeyCode_MouseMiddleButton, true, false,
ShiftDown, AltDown, CtrlDown, false); ShiftDown, AltDown, CtrlDown, false);
Mouse->MiddleButtonState = ~KeyState_IsDown & KeyState_WasDown;
}break; }break;
case WM_RBUTTONUP: case WM_RBUTTONUP:
@ -431,6 +436,7 @@ HandleWindowMessage (MSG Message, window* Window, input_queue* InputQueue, mouse
AddInputEventEntry(InputQueue, KeyCode_MouseRightButton, true, false, AddInputEventEntry(InputQueue, KeyCode_MouseRightButton, true, false,
ShiftDown, AltDown, CtrlDown, false); ShiftDown, AltDown, CtrlDown, false);
Mouse->RightButtonState = ~KeyState_IsDown & KeyState_WasDown;
}break; }break;
case WM_SYSKEYDOWN: 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 int WINAPI
WinMain ( WinMain (
HINSTANCE HInstance, HINSTANCE HInstance,
@ -516,8 +543,14 @@ INT NCmdShow
r32 LastFrameSecondsElapsed = 0.0f; r32 LastFrameSecondsElapsed = 0.0f;
GlobalDebugServices = (debug_services*)malloc(sizeof(debug_services)); GlobalDebugServices = (debug_services*)malloc(sizeof(debug_services));
InitDebugServices(GlobalDebugServices, (u8*)malloc(Megabytes(8)), Megabytes(16), 32000, PerformanceCountFrequency); s32 DebugThreadCount = PLATFORM_THREAD_COUNT + 1;
GlobalDebugServices->GetWallClock = GetWallClock; InitDebugServices(GlobalDebugServices,
PerformanceCountFrequency,
DEBUGAlloc,
Win32Realloc,
GetWallClock,
Win32GetThreadId,
DebugThreadCount);
mouse_state Mouse; mouse_state Mouse;
input_queue InputQueue; input_queue InputQueue;
@ -592,8 +625,8 @@ INT NCmdShow
WSADATA WSAData; WSADATA WSAData;
WSAStartup(MAKEWORD(2, 2), &WSAData); WSAStartup(MAKEWORD(2, 2), &WSAData);
platform_memory_result RenderMemory = Win32Alloc(Megabytes(32)); platform_memory_result RenderMemory = Win32Alloc(Megabytes(12));
render_command_buffer RenderBuffer = AllocateRenderCommandBuffer(RenderMemory.Base, RenderMemory.Size); render_command_buffer RenderBuffer = AllocateRenderCommandBuffer(RenderMemory.Base, RenderMemory.Size, Win32Realloc);
Context.InitializeApplication(Context); Context.InitializeApplication(Context);
@ -601,6 +634,10 @@ INT NCmdShow
Context.WindowIsVisible = true; Context.WindowIsVisible = true;
while (Running) while (Running)
{ {
if (GlobalDebugServices->RecordFrames)
{
EndDebugFrame(GlobalDebugServices);
}
DEBUG_TRACK_SCOPE(MainLoop); DEBUG_TRACK_SCOPE(MainLoop);
ResetInputQueue(&InputQueue); ResetInputQueue(&InputQueue);
@ -624,6 +661,7 @@ INT NCmdShow
MSG Message; MSG Message;
while (PeekMessageA(&Message, MainWindow.Handle, 0, 0, PM_REMOVE)) while (PeekMessageA(&Message, MainWindow.Handle, 0, 0, PM_REMOVE))
{ {
DEBUG_TRACK_SCOPE(PeekWindowsMessages);
HandleWindowMessage(Message, &MainWindow, &InputQueue, &Mouse); HandleWindowMessage(Message, &MainWindow, &InputQueue, &Mouse);
} }
@ -641,6 +679,35 @@ INT NCmdShow
RenderCommandBuffer(RenderBuffer); RenderCommandBuffer(RenderBuffer);
ClearRenderBuffer(&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 // Finish Up
////////////////////////////////// //////////////////////////////////
@ -654,6 +721,7 @@ INT NCmdShow
while (SecondsElapsed < TargetSecondsPerFrame) while (SecondsElapsed < TargetSecondsPerFrame)
{ {
DEBUG_TRACK_SCOPE(UnusedTime);
u32 SleepTime = 1000.0f * (TargetSecondsPerFrame - SecondsElapsed); u32 SleepTime = 1000.0f * (TargetSecondsPerFrame - SecondsElapsed);
Sleep(SleepTime); Sleep(SleepTime);
SecondsElapsed = GetSecondsElapsed(LastFrameEnd, GetWallClock(), PerformanceCountFrequency); SecondsElapsed = GetSecondsElapsed(LastFrameEnd, GetWallClock(), PerformanceCountFrequency);

View File

@ -1,5 +1,10 @@
TODO FOLDHAUS 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 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. - 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 - motion
Renderer Renderer
- Render layers
- Mouse Picking - point at a led and see info about it - Mouse Picking - point at a led and see info about it
- Camera: pan - Camera: pan
- Camera: zoom - Camera: zoom
@ -78,6 +84,8 @@ Command Line
- select a channel/pattern - select a channel/pattern
Optimization 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 - patterns are asking to be multithreaded
- probably want to convert as much color functions to use u32 Packed Colors - 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 - - Probably want to think about this more. What about supporting different color depths