@@ -62,7 +62,6 @@ RecursiveDrawScope(const Profiling::ProfilingScope& scope, Profiler::HighLightRe
6262 const uint32_t numColors = sizeof (colors) / sizeof (ImU32);
6363 uint32_t colorIndex = scope.category .HashCode () % numColors;
6464
65- // convert to milliseconds
6665 const float frameTime = endTime - startTime;
6766
6867 // deal with clipping
@@ -93,15 +92,13 @@ RecursiveDrawScope(const Profiling::ProfilingScope& scope, Profiler::HighLightRe
9392 drawList->AddText (ImVec2 (startX + TextPad, pos.y ), IM_COL32_BLACK, text.AsCharPtr ());
9493 drawList->PopClipRect ();
9594
96- if (ImGui::IsMouseHoveringRect (bbMin, bbMax))
95+ if (ImGui::IsMouseHoveringRect (bbMin, bbMax) && ! ImGui::GetIO (). KeyShift )
9796 {
9897 // record double-clicked region on the profiler
9998 if (ImGui::IsMouseDoubleClicked (ImGuiMouseButton_Left))
10099 {
101- float normStart = (bbMin.x - start.x ) / canvas.x ;
102- float normEnd = (bbMax.x - start.x ) / canvas.x ;
103- highlightRegion.start = Math::clamp (normStart, 0 .0f , 1 .0f );
104- highlightRegion.end = Math::clamp (normEnd, 0 .0f , 1 .0f );
100+ highlightRegion.start = scope.start / fullFrameTime;
101+ highlightRegion.duration = scope.duration / fullFrameTime;
105102 }
106103
107104 ImGui::BeginTooltip ();
@@ -132,16 +129,34 @@ RecursiveDrawScope(const Profiling::ProfilingScope& scope, Profiler::HighLightRe
132129/* *
133130*/
134131int
135- RecursiveDrawGpuMarker (const CoreGraphics::FrameProfilingMarker& marker, ImDrawList* drawList, const ImVec2 start, const ImVec2 fullSize, ImVec2 pos, const ImVec2 canvas, const float frameTime , const int level)
132+ RecursiveDrawGpuMarker (const CoreGraphics::FrameProfilingMarker& marker, Profiler::HighLightRegion& highlightRegion, ImDrawList* drawList, const ImVec2 start, const ImVec2 fullSize, ImVec2 pos, const ImVec2 canvas, const float fullFrameTime, const float startSection, const float endSection , const int level)
136133{
137- static const float YPad = ImGui::GetTextLineHeight ();
138- static const float TextPad = 5 .0f ;
139-
140134 // convert to milliseconds
141135 float begin = marker.start / 1000000000 .0f ;
142136 float duration = marker.duration / 1000000000 .0f ;
143- float startX = pos.x + begin / frameTime * canvas.x ;
144- float stopX = startX + Math::max (duration / frameTime * canvas.x , 1 .0f );
137+
138+ const float startTime = startSection * fullFrameTime;
139+ const float endTime = endSection * fullFrameTime;
140+
141+ if (begin + duration < startTime || begin > endTime)
142+ {
143+ return level;
144+ }
145+
146+ static const float YPad = ImGui::GetTextLineHeight ();
147+ static const float TextPad = 5 .0f ;
148+
149+ const float frameTime = endTime - startTime;
150+
151+ // deal with clipping
152+ if (begin < startTime)
153+ {
154+ duration -= startTime - begin;
155+ begin = startTime;
156+ }
157+
158+ float startX = pos.x + (Math::max (0 .0f , (begin - startTime)) / frameTime) * canvas.x ;
159+ float stopX = startX + Math::max ((duration / frameTime) * canvas.x , 1 .0f );
145160 float startY = pos.y ;
146161 float stopY = startY + YPad;
147162
@@ -161,6 +176,12 @@ RecursiveDrawGpuMarker(const CoreGraphics::FrameProfilingMarker& marker, ImDrawL
161176
162177 if (ImGui::IsMouseHoveringRect (bbMin, bbMax) && !ImGui::GetIO ().KeyShift ) // show tooltip only when not panning
163178 {
179+ // record double-clicked region on the profiler
180+ if (ImGui::IsMouseDoubleClicked (ImGuiMouseButton_Left))
181+ {
182+ highlightRegion.start = begin / fullFrameTime;
183+ highlightRegion.duration = duration / fullFrameTime;
184+ }
164185 ImGui::BeginTooltip ();
165186 Util::String text = Util::String::Sprintf (" %s (%4.4f ms)" , marker.name .AsCharPtr (), duration * 1000 );
166187 ImGui::Text (text.AsCharPtr ());
@@ -172,7 +193,7 @@ RecursiveDrawGpuMarker(const CoreGraphics::FrameProfilingMarker& marker, ImDrawL
172193 int deepest = level + 1 ;
173194 for (IndexT i = 0 ; i < marker.children .Size (); i++)
174195 {
175- int childLevel = RecursiveDrawGpuMarker (marker.children [i], drawList, start, fullSize, pos, canvas, frameTime , level + 1 );
196+ int childLevel = RecursiveDrawGpuMarker (marker.children [i], highlightRegion, drawList, start, fullSize, pos, canvas, fullFrameTime, startSection, endSection , level + 1 );
176197 deepest = Math::max (deepest, childLevel);
177198 }
178199 return deepest;
@@ -259,7 +280,6 @@ Profiler::Run(SaveMode save)
259280 ImDrawList* drawList = ImGui::GetWindowDrawList ();
260281 ImVec2 start = ImGui::GetCursorScreenPos ();
261282 ImVec2 fullSize = ImVec2 (ImGui::GetWindowPos ().x + ImGui::GetWindowSize ().x , ImGui::GetWindowPos ().y + ImGui::GetWindowSize ().y );
262- static float timeWindow = 1 .0f ;
263283 ImGui::DragFloatRange2 (" Time range" , &this ->timeStart , &this ->timeEnd , 0 .01f , 0 .0f , 1 .0f , " %.3f" , " %.3f" , ImGuiSliderFlags_AlwaysClamp);
264284
265285 // Handle mouse scroll for timeline zoom
@@ -269,24 +289,23 @@ Profiler::Run(SaveMode save)
269289 {
270290 ImGui::SetMouseCursor (ImGuiMouseCursor_Hand);
271291 }
292+ float zoomRange = this ->timeEnd - this ->timeStart ;
272293 if (mouseWheel != 0 .0f && ImGui::IsWindowHovered () && io.KeyShift )
273294 {
274- float range = this ->timeEnd - this ->timeStart ;
275-
276295 // Get normalized mouse position within the timeline area (0 to 1)
277296 ImVec2 mousePos = ImGui::GetMousePos ();
278297 float canvasWidth = fullSize.x - start.x ;
279298 float mouseNormalizedX = Math::clamp ((mousePos.x - start.x ) / canvasWidth, 0 .0f , 1 .0f );
280299
281300 // Calculate the time value at mouse position
282- float mouseTimeValue = this ->timeStart + (mouseNormalizedX * range );
301+ float mouseTimeValue = this ->timeStart + (mouseNormalizedX * zoomRange );
283302
284303 // Calculate zoom factor (positive mouseWheel = zoom in, negative = zoom out)
285304 float zoomFactor = 1 .0f - (mouseWheel * 0 .1f ); // Adjust 0.1 for sensitivity
286305 zoomFactor = Math::clamp (zoomFactor, 0 .1f , 10 .0f );
287306
288307 // Calculate new range
289- float newRange = range * zoomFactor;
308+ float newRange = zoomRange * zoomFactor;
290309 newRange = Math::clamp (newRange, 0 .01f , 1 .0f );
291310
292311 // Recalculate start and end to keep mouse position fixed
@@ -306,28 +325,27 @@ Profiler::Run(SaveMode save)
306325 }
307326
308327 // Handle shift + left-drag for panning the timeline
309- if (io.KeyShift // && ImGui::IsWindowHovered()
328+ if (io.KeyShift && ImGui::IsWindowHovered ()
310329 && ImGui::IsMouseDragging (ImGuiMouseButton_Left))
311330 {
312331 ImVec2 dragDelta = ImGui::GetMouseDragDelta (ImGuiMouseButton_Left, 0 .0f );
313- float canvasWidth = ImGui::GetContentRegionAvail ().x * timeWindow;
314- float range = this ->timeEnd - this ->timeStart ;
315- if (canvasWidth > 0 .0f && range > 0 .0f )
332+ float canvasWidth = ImGui::GetContentRegionAvail ().x ;
333+ if (canvasWidth > 0 .0f && zoomRange > 0 .0f )
316334 {
317335 float deltaNormalized = dragDelta.x / canvasWidth;
318- float timeShift = -deltaNormalized * range ;
336+ float timeShift = -deltaNormalized * zoomRange ;
319337 this ->timeStart += timeShift;
320338 this ->timeEnd += timeShift;
321339
322340 if (this ->timeStart < 0 .0f )
323341 {
324342 this ->timeStart = 0 .0f ;
325- this ->timeEnd = Math::min (this ->timeStart + range , 1 .0f );
343+ this ->timeEnd = Math::min (this ->timeStart + zoomRange , 1 .0f );
326344 }
327345 if (this ->timeEnd > 1 .0f )
328346 {
329347 this ->timeEnd = 1 .0f ;
330- this ->timeStart = Math::max (0 .0f , this ->timeEnd - range );
348+ this ->timeStart = Math::max (0 .0f , this ->timeEnd - zoomRange );
331349 }
332350 }
333351 ImGui::ResetMouseDragDelta (ImGuiMouseButton_Left);
@@ -336,13 +354,14 @@ Profiler::Run(SaveMode save)
336354 for (const Profiling::ProfilingContext& ctx : this ->ProfilingContexts )
337355 {
338356 if (hideEmptyThreads && ctx.topLevelScopes .Size () == 0 )
357+ {
339358 continue ;
359+ }
340360 if (ImGui::CollapsingHeader (ctx.threadName .Value (), ctx.topLevelScopes .Size () > 0 ? ImGuiTreeNodeFlags_DefaultOpen : ImGuiTreeNodeFlags_OpenOnArrow))
341361 {
342362 ImGui::PushFont (Dynui::ImguiSmallFont);
343363
344364 ImVec2 canvasSize = ImGui::GetContentRegionAvail ();
345- canvasSize.x *= timeWindow;
346365 ImVec2 pos = ImGui::GetCursorScreenPos ();
347366 int levels = 0 ;
348367 if (ctx.topLevelScopes .Size () > 0 ) for (IndexT i = 0 ; i < ctx.topLevelScopes .Size (); i++)
@@ -369,12 +388,16 @@ Profiler::Run(SaveMode save)
369388 }
370389
371390 // draw highlight overlay/lines if user double-clicked a scope
372- if (this ->highlightRegion .start >= 0 .0f && this ->highlightRegion .end > this ->highlightRegion .start )
391+ if (this ->pauseProfiling && this -> highlightRegion .start >= 0 .0f && this ->highlightRegion .start + this -> highlightRegion . duration > this ->highlightRegion .start )
373392 {
393+ // highlightRange is normalized to the current frame time range, adjust it the current zoom level
394+ float highlightRange = this ->highlightRegion .duration / zoomRange;
395+ float regionStartTime = (this ->highlightRegion .start - this ->timeStart ) / zoomRange;
396+ float regionEndTime = regionStartTime + highlightRange;
397+
374398 ImVec2 canvasSize = ImGui::GetContentRegionAvail ();
375- canvasSize.x *= timeWindow;
376- float x0 = start.x + this ->highlightRegion .start * canvasSize.x ;
377- float x1 = start.x + this ->highlightRegion .end * canvasSize.x ;
399+ float x0 = start.x + regionStartTime * canvasSize.x ;
400+ float x1 = start.x + regionEndTime * canvasSize.x ;
378401 ImU32 overlayCol = IM_COL32 (255 , 255 , 0 , 60 ); // translucent yellow
379402 drawList->AddRectFilled (ImVec2 (x0, start.y ), ImVec2 (x1, fullSize.y ), overlayCol);
380403 drawList->AddLine (ImVec2 (x0, start.y ), ImVec2 (x0, fullSize.y ), IM_COL32_WHITE, 1 .0f );
@@ -384,11 +407,12 @@ Profiler::Run(SaveMode save)
384407 {
385408 ImVec2 mp = ImGui::GetMousePos ();
386409 float relX = (mp.x - start.x ) / canvasSize.x ;
387- if (relX >= this -> highlightRegion . start && relX <= this -> highlightRegion . end )
410+ if (relX >= regionStartTime && relX <= regionEndTime )
388411 {
389- this ->highlightRegion .start = this ->highlightRegion .end = -1 .0f ;
412+ this ->highlightRegion .start = this ->highlightRegion .duration = -1 .0f ;
390413 }
391- } }
414+ }
415+ }
392416
393417 if (ImGui::CollapsingHeader (" GPU" ))
394418 {
@@ -407,7 +431,7 @@ Profiler::Run(SaveMode save)
407431 const CoreGraphics::FrameProfilingMarker& marker = frameMarkers[i];
408432 if (marker.queue != CoreGraphics::GraphicsQueueType)
409433 continue ;
410- int level = RecursiveDrawGpuMarker (marker, drawList, start, fullSize, pos, canvasSize, this ->currentFrameTime , 0 );
434+ int level = RecursiveDrawGpuMarker (marker, this -> highlightRegion , drawList, start, fullSize, pos, canvasSize, this ->currentFrameTime , this -> timeStart , this -> timeEnd , 0 );
411435 levels = Math::max (levels, level);
412436 }
413437
@@ -424,7 +448,7 @@ Profiler::Run(SaveMode save)
424448 const CoreGraphics::FrameProfilingMarker& marker = frameMarkers[i];
425449 if (marker.queue != CoreGraphics::ComputeQueueType)
426450 continue ;
427- int level = RecursiveDrawGpuMarker (marker, drawList, start, fullSize, pos, canvasSize, this ->currentFrameTime , 0 );
451+ int level = RecursiveDrawGpuMarker (marker, this -> highlightRegion , drawList, start, fullSize, pos, canvasSize, this ->currentFrameTime , this -> timeStart , this -> timeEnd , 0 );
428452 levels = Math::max (levels, level);
429453 }
430454
0 commit comments