Skip to content

Commit 2e4d1ea

Browse files
committed
profiler:
- fix highlight zoom/pan - add highlight to gpu markers as well
1 parent c0ef897 commit 2e4d1ea

File tree

2 files changed

+60
-36
lines changed

2 files changed

+60
-36
lines changed

toolkit/editor/editor/ui/windows/profiler.cc

Lines changed: 59 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -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
*/
134131
int
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

toolkit/editor/editor/ui/windows/profiler.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class Profiler : public BaseWindow
2525
struct HighLightRegion
2626
{
2727
float start = -1.0f;
28-
float end = -1.0f;
28+
float duration = -1.0f;
2929
};
3030

3131
private:

0 commit comments

Comments
 (0)