Cogs.Core
InspectorGuiRenderer.cpp
1#include "InspectorGuiRenderer.h"
2
3#include "imgui.h"
4#include "imgui_internal.h"
5
6#include "Context.h"
7#include "Engine.h"
8
9#include "Renderer/IRenderer.h"
10
11#include "Editor/IEditor.h"
12
13#include "InspectorGuiHelper.h"
14#include "EntityInspector.h"
15#include "Inspectors.h"
16#include "Platform/Instrumentation.h"
17#include "Services/QualityService.h"
18
19#ifdef COGS_USE_MICROPROFILE
20#include <microprofileui.h>
21#endif
22
23void Cogs::Core::InspectorGuiRenderer::initialize(Context * /*context*/, IRenderer* renderer)
24{
25 imguiRenderer = renderer->getGuiRenderer();
26 imguiContext = imguiRenderer->createGuiContext();
27
28#ifdef COGS_USE_MICROPROFILE
29 MicroProfileInitUI();
30
31 auto & profiler = *MicroProfileGet();
32 profiler.nDisplay = MP_DRAW_DETAILED;
33 profiler.nAllGroupsWanted = 1;
34#endif
35}
36
37void Cogs::Core::InspectorGuiRenderer::registerInspector(const std::string& name, Inspector inspector)
38{
39 inspectors.emplace_back(RegisteredInspector{ name, inspector, false });
40}
41
42void Cogs::Core::InspectorGuiRenderer::beginRender(Context* context, IRenderer* renderer)
43{
44 RenderInstrumentationScope(renderer->getDevice()->getImmediateContext(), SCOPE_RENDERING, "GuiRenderer::beginRender");
45
46 imguiRenderer->frame(imguiContext, *context->getDefaultView());
47 imguiRenderer->style();
48}
49
50void Cogs::Core::InspectorGuiRenderer::renderTimes(Context * context)
51{
52 QualityService* quality = context->qualityService.get();
53
54 // double n = nowToSeconds(Cogs::now()-nowReference());
55 // double c = currentTimeToSeconds(Cogs::currentTime()-currentTimeReference());
56 // ImGui::Text("now %f currentTime %f", n, c);
57
58 size_t timesCount = quality->TIMES_COUNT;
59
60 ImU32 CpuTimeColor = IM_COL32(255, 50, 50, 255);
61 ImU32 PreRenderColor = IM_COL32(0, 128, 0, 255);
62 ImU32 PresentColor = IM_COL32(255, 255, 50, 255);
63 ImU32 IdleColor = IM_COL32(0, 127, 255, 255);
64
65 float dt = static_cast<float>(delta_timer.elapsedSeconds());
66 delta_timer = Timer::startNew();
67 delta_akk += dt;
68 if(delta_akk > delta_update){
69 cogsTime = quality->getMetric(MetricType::Frame)*1000.0f;
70 idleTime = quality->getMetric(MetricType::Idle)*1000.0f;
71 frameTime = cogsTime+idleTime;
72 preRenderTime = quality->getMetric(MetricType::PreRender)*1000.0f;
73 presentTime = quality->getMetric(MetricType::Present)*1000.0f;
74 cpuTime = cogsTime-presentTime;
75 cogsFPS = 1000.0f/cogsTime;
76 frameFPS = 1000.0f/frameTime;
77 cpuFps = 1000.0f/cpuTime;
78 delta_akk = 0.0f;
79 }
80
81 frameMax = std::max(frameMax, frameTime);
82 frameMin = std::min(frameMin, frameTime);
83
84 cogsMax = std::max(cogsMax, cogsTime);
85 cogsMin = std::min(cogsMin, cogsTime);
86
87 static std::vector<float> scales = { 10.0f, 16.67f, 33.33f, 100.0f };
88
89 float scale = scales.front();
90 for (auto & s : scales) {
91 if (frameMax < scale) {
92 break;
93 } else if (frameMax > scale && frameMax < s) {
94 scale = s;
95 break;
96 } else {
97 scale = s;
98 }
99 }
100 scale /= 1000.0f;
101
102 ImGui::Text("Frame: %.3fms Max: %.3fms (%.2f FPS)", frameTime, frameMax, frameFPS);
103 ImGui::Text("Cogs: %.3fms Max: %.3fms (%.2f FPS)", cogsTime, cogsMax, cogsFPS);
104 ImGui::TextColored(ImColor(PreRenderColor), "PreRender: %.3fms", preRenderTime);
105 ImGui::SameLine();
106 ImGui::TextColored(ImColor(CpuTimeColor), "CPU: %.3fms (%.2f FPS)", cpuTime, cpuFps);
107 ImGui::TextColored(ImColor(PresentColor), "Present: %.3fms", presentTime);
108 ImGui::SameLine();
109 ImGui::TextColored(ImColor(IdleColor), "Idle: %.3fms", idleTime);
110
111 {
112 ImVec2 canvas_p0 = ImGui::GetCursorScreenPos();
113 ImVec2 canvas_sz = ImGui::GetContentRegionAvail();
114 if (canvas_sz.x < 50.0f) canvas_sz.x = 50.0f;
115 canvas_sz.y = 140.0f;
116 ImVec2 canvas_p1 = ImVec2(canvas_p0.x + canvas_sz.x, canvas_p0.y + canvas_sz.y);
117
118 ImGui::PushClipRect(canvas_p0, canvas_p1, true);
119
120 ImDrawList *draw_list = ImGui::GetWindowDrawList();
121 draw_list->AddRectFilled(canvas_p0, canvas_p1, IM_COL32(50, 50, 50, 255));
122
123 ImGui::InvisibleButton("canvas", canvas_sz, ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight);
124 // const bool is_hovered = ImGui::IsItemHovered(); // Hovered
125 // Cpu Time
126 for(size_t i=0; i<timesCount; i++){
127 size_t idx = (quality->times_idx+quality->TIMES_COUNT-i)%quality->TIMES_COUNT;
128 float x0 = (float)i/timesCount;
129 float x1 = (float)(i+1)/timesCount;
130 float y0 = quality->times[idx][(size_t)MetricType::Frame]/scale;
131 ImVec2 pos0(canvas_p0.x+x0*canvas_sz.x, canvas_p0.y+canvas_sz.y*(1.0f-y0));
132 ImVec2 pos1(canvas_p0.x+x1*canvas_sz.x, canvas_p1.y);
133 draw_list->AddRectFilled(pos0, pos1, CpuTimeColor);
134 }
135 // Pre-Render
136 for(size_t i=0; i<timesCount; i++){
137 size_t idx = (quality->times_idx+quality->TIMES_COUNT-i)%quality->TIMES_COUNT;
138 float x0 = (float)i/timesCount;
139 float x1 = (float)(i+1)/timesCount;
140 float y0 = quality->times[idx][(size_t)MetricType::PreRender]/scale;
141 float y1 = 0.0f;
142 ImVec2 pos0(canvas_p0.x+x0*canvas_sz.x, canvas_p0.y+canvas_sz.y*(1.0f-y0));
143 ImVec2 pos1(canvas_p0.x+x1*canvas_sz.x, canvas_p0.y+canvas_sz.y*(1.0f-y1));
144 draw_list->AddRectFilled(pos0, pos1, PreRenderColor);
145 }
146 // Present
147 for(size_t i=0; i<timesCount; i++){
148 size_t idx = (quality->times_idx+quality->TIMES_COUNT-i)%quality->TIMES_COUNT;
149 float x0 = (float)i/timesCount;
150 float x1 = (float)(i+1)/timesCount;
151 float y0 = quality->times[idx][(size_t)MetricType::Frame]/scale;
152 float y1 = (quality->times[idx][(size_t)MetricType::Frame]-quality->times[idx][(size_t)MetricType::Present])/scale;
153 ImVec2 pos0(canvas_p0.x+x0*canvas_sz.x, canvas_p0.y+canvas_sz.y*(1.0f-y0));
154 ImVec2 pos1(canvas_p0.x+x1*canvas_sz.x, canvas_p0.y+canvas_sz.y*(1.0f-y1));
155 draw_list->AddRectFilled(pos0, pos1, PresentColor);
156 }
157 // Idle
158 for(size_t i=0; i<timesCount; i++){
159 size_t idx = (quality->times_idx+quality->TIMES_COUNT-i)%quality->TIMES_COUNT;
160 float x0 = (float)i/timesCount;
161 float x1 = (float)(i+1)/timesCount;
162 float y0 = (quality->times[idx][(size_t)MetricType::Frame]+quality->times[idx][(size_t)MetricType::Idle])/scale;
163 float y1 = quality->times[idx][(size_t)MetricType::Frame]/scale;
164 ImVec2 pos0(canvas_p0.x+x0*canvas_sz.x, canvas_p0.y+canvas_sz.y*(1.0f-y0));
165 ImVec2 pos1(canvas_p0.x+x1*canvas_sz.x, canvas_p0.y+canvas_sz.y*(1.0f-y1));
166 draw_list->AddRectFilled(pos0, pos1, IdleColor);
167 }
168 if (ImGui::IsItemHovered()) {
169 ImGui::SetNextWindowBgAlpha(0.7f);
170 ImGui::BeginTooltip();
171 ImVec2 cpos =ImGui::GetMousePos();
172 ImVec2 rpos = cpos - canvas_p0;
173 ImVec2 npos = rpos / canvas_sz;
174 int i = (int)(npos.x * timesCount);
175 i = std::max(i, 0);
176 i = std::min(i, (int)timesCount-1);
177 size_t idx = (quality->times_idx+quality->TIMES_COUNT-i)%quality->TIMES_COUNT;
178 ImGui::Text("(%d, %.3fms)", i, (1.0f-npos.y)*scale);
179 ImGui::Text("%.3fms", quality->times[idx][(size_t)MetricType::Frame]*1000);
180
181 ImGui::TextColored(ImColor(PreRenderColor), "%.3fms", quality->times[idx][(size_t)MetricType::PreRender]*1000);
182 ImGui::SameLine();
183 ImGui::TextColored(ImColor(CpuTimeColor), "%.3fms", (quality->times[idx][(size_t)MetricType::Frame]-
184 quality->times[idx][(size_t)MetricType::Present])*1000);
185 ImGui::TextColored(ImColor(PresentColor), "%.3fms", quality->times[idx][(size_t)MetricType::Present]*1000);
186 ImGui::SameLine();
187 ImGui::TextColored(ImColor(IdleColor), "%.3fms", quality->times[idx][(size_t)MetricType::Idle]*1000);
188 ImGui::EndTooltip();
189 }
190
191 ImGui::PopClipRect();
192 }
193
194 // Upload statistics
195 if(ImGui::TreeNode("Upload Statistics")){
196 ImGui::BeginGroup();
197 ImGui::Unindent();
198 ImU32 BufferUploadColor = IM_COL32(0, 128, 0, 255);
199 ImU32 TextureUploadColor = IM_COL32(255, 255, 50, 255);
200
201 ImGui::TextColored(ImColor(BufferUploadColor), "Buffer Upload: %zu", quality->bufferUploadSize[(quality->times_idx+timesCount-1)%timesCount]);
202 ImGui::SameLine();
203 ImGui::TextColored(ImColor(TextureUploadColor), "Texture Upload: %zu", quality->textureUploadSize[(quality->times_idx+timesCount-1)%timesCount]);
204
205 ImVec2 canvas_p0 = ImGui::GetCursorScreenPos();
206 ImVec2 canvas_sz = ImGui::GetContentRegionAvail();
207 if (canvas_sz.x < 50.0f) canvas_sz.x = 50.0f;
208 canvas_sz.y = 140.0f;
209 ImVec2 canvas_p1 = ImVec2(canvas_p0.x + canvas_sz.x, canvas_p0.y + canvas_sz.y);
210 ImGui::PushClipRect(canvas_p0, canvas_p1, true);
211
212 ImDrawList *draw_list = ImGui::GetWindowDrawList();
213 draw_list->AddRectFilled(canvas_p0, canvas_p1, IM_COL32(50, 50, 50, 255));
214
215 ImGui::InvisibleButton("canvas2", canvas_sz, ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight);
216
217 float upload_scale = 1.0f/(1024.0f*1024.0f*64.0f);
218
219 // Buffer Upload
220 for(size_t i=0; i<timesCount; i++){
221 size_t idx = (quality->times_idx+quality->TIMES_COUNT-i)%quality->TIMES_COUNT;
222 float x0 = (float)i/timesCount;
223 float x1 = (float)(i+1)/timesCount;
224 float y0 = quality->bufferUploadSize[idx]*upload_scale;
225 float y1 = 0.0f;
226 ImVec2 pos0(canvas_p0.x+x0*canvas_sz.x, canvas_p0.y+canvas_sz.y*(1.0f-y0));
227 ImVec2 pos1(canvas_p0.x+x1*canvas_sz.x, canvas_p0.y+canvas_sz.y*(1.0f-y1));
228 draw_list->AddRectFilled(pos0, pos1, BufferUploadColor);
229 }
230 // Texture Upload
231 for(size_t i=0; i<timesCount; i++){
232 size_t idx = (quality->times_idx+quality->TIMES_COUNT-i)%quality->TIMES_COUNT;
233 float x0 = (float)i/timesCount;
234 float x1 = (float)(i+1)/timesCount;
235 float y0 = (quality->bufferUploadSize[idx]+quality->textureUploadSize[idx])*upload_scale;
236 float y1 = quality->bufferUploadSize[idx]*upload_scale;
237 ImVec2 pos0(canvas_p0.x+x0*canvas_sz.x, canvas_p0.y+canvas_sz.y*(1.0f-y0));
238 ImVec2 pos1(canvas_p0.x+x1*canvas_sz.x, canvas_p0.y+canvas_sz.y*(1.0f-y1));
239 draw_list->AddRectFilled(pos0, pos1, TextureUploadColor);
240 }
241
242 if (ImGui::IsItemHovered()) {
243 ImGui::SetNextWindowBgAlpha(0.7f);
244 ImGui::BeginTooltip();
245 ImVec2 cpos =ImGui::GetMousePos();
246 ImVec2 rpos = cpos - canvas_p0;
247 ImVec2 npos = rpos / canvas_sz;
248 int i = (int)(npos.x * timesCount);
249 i = std::max(i, 0);
250 i = std::min(i, (int)timesCount-1);
251 size_t idx = (quality->times_idx+quality->TIMES_COUNT-i)%quality->TIMES_COUNT;
252 ImGui::TextColored(ImColor(BufferUploadColor), "%zu", quality->bufferUploadSize[idx]);
253 ImGui::TextColored(ImColor(TextureUploadColor), "%zu", quality->textureUploadSize[idx]);
254 ImGui::EndTooltip();
255 }
256
257 ImGui::PopClipRect();
258 ImGui::EndGroup();
259 ImGui::TreePop();
260 }
261
262 ImVec2 buttonSize(96, 24);
263
264 if (ImGui::Button("Reset", buttonSize)) {
265 frameMax = 0;
266 frameMin = 10000;
267 cogsMax = 0;
268 cogsMin = 10000;
269 }
270 ImGui::SameLine();
271 bool vSync = context->variables->get("renderer.vSync", false);
272 if(ImGui::Checkbox("vSync", &vSync)){
273 context->variables->set("renderer.vSync", vSync);
274 }
275 ImGui::SameLine();
276 ImGui::Text("Scale Y %.3f", scale);
277}
278void Cogs::Core::InspectorGuiRenderer::render(Context * context, IRenderer * renderer)
279{
280 if (context->engine->getEditor() && context->engine->getEditor()->isActive()) {
281 context->engine->getEditor()->show();
282 }
283
284 if (!context->variables->get("gui.enabled", false)) return;
285
286 context->engine->triggerUpdate();
287
288 RenderInstrumentationScope(renderer->getDevice()->getImmediateContext(), SCOPE_RENDERING, "GuiRenderer::render");
289
290 struct VariableMap {
291 StringView name;
292 bool& toggle;
293 } variableMapping[] = {
294 { "gui.aboutCogs", showAboutCogs },
295 { "gui.renderingStatsInspector", showRenderingStatsInspector },
296 { "gui.textureInspector", showTextureInspector },
297 { "gui.shadowMapInspector", showShadowMapInspector },
298 { "gui.entityInspector", showEntityInspector },
299 { "gui.fontInspector", showFontInspector },
300 { "gui.variableInspector", showVariableInspector },
301 { "gui.inputInspector", showInputInspector },
302 { "gui.modelInspector", showModelInspector },
303 { "gui.meshInspector", showMeshInspector },
304 { "gui.materialInspector", showMaterialInspector },
305 { "gui.materialInstanceInspector", showMaterialInstanceInspector },
306 { "gui.resourceInspector", showResourceInspector },
307 { "gui.scriptInspector", showScriptInspector },
308 { "gui.scriptConsole", showScriptConsole },
309 { "gui.profiler", showProfiler },
310 { "gui.pipelineInspector", showPipelineInspector },
311 { "gui.permutationInspector", showPermutationInspector },
312 { "gui.assetInspector", showAssetInspector },
313 { "gui.assetQueueInspector", showAssetQueueInspector },
314 { "gui.boundsInspector", showBoundsInspector },
315 { "gui.bufferInspector", showBufferInspector },
316 { "gui.engineInspector", showEngineInspector },
317 { "gui.exampleGui", showExampleGui },
318 { "gui.gammaDebugger", showGammaDebugger },
319 { "gui.showWebGPUCountersInspector", showWebGPUCountersInspector }
320 };
321
322 for (const VariableMap variableMap : variableMapping) {
323 if (Variable* var = context->variables->getIfExists(variableMap.name); var != nullptr && !var->isEmpty()) {
324 variableMap.toggle = var->getBool();
325 }
326 }
327
328 bool show = true;
329 if(ImGui::Begin("Engine", &show, ImGuiWindowFlags_MenuBar)){
330 // MenuBar
331 if (ImGui::BeginMenuBar()) {
332 if (ImGui::BeginMenu("View")) {
333 struct Button
334 {
335 const char * title;
336 bool & toggle;
337 } buttons[] = {
338 { "Asset Queue", showAssetQueueInspector },
339 { "Assets", showAssetInspector },
340 { "Buffers", showBufferInspector },
341 { "Console", showScriptConsole },
342 { "Entities", showEntityInspector },
343 { "Fonts", showFontInspector },
344 { "Inputs", showInputInspector },
345 { "Materials", showMaterialInspector },
346 { "Material Instances", showMaterialInstanceInspector },
347 { "Meshes", showMeshInspector},
348 { "Models", showModelInspector},
349 { "Render Pipeline", showPipelineInspector },
350 { "Permutations", showPermutationInspector },
351 { "Resources", showResourceInspector },
352 { "Textures", showTextureInspector },
353 { "Variables", showVariableInspector },
354 { "ImGui Examples", showExampleGui},
355 //{ nullptr, none },
356 };
357 for (size_t i = 0; i < glm::countof(buttons); ++i) {
358 if (!buttons[i].title) continue;
359 if (ImGui::MenuItem(buttons[i].title)) {
360 buttons[i].toggle = !buttons[i].toggle;
361 }
362 }
363 ImGui::EndMenu();
364 }
365 if (ImGui::BeginMenu("Debuggers")) {
366 struct Button
367 {
368 const char * title;
369 bool & toggle;
370 } buttons[] = {
371 { "Bounds", showBoundsInspector },
372 { "Engine Statistics", showEngineInspector },
373 { "Task Manager Statistics", showTaskManagerInspector },
374 { "GammaDebugger", showGammaDebugger },
375 { "Performance", showRenderingStatsInspector },
376 { "Profiler", showProfiler },
377 { "Shadow maps", showShadowMapInspector },
378 { "WebGPU Counters", showWebGPUCountersInspector }
379 //{ nullptr, none },
380 };
381 for (size_t i = 0; i < glm::countof(buttons); ++i) {
382 if (!buttons[i].title) continue;
383 if (ImGui::MenuItem(buttons[i].title)) {
384 buttons[i].toggle = !buttons[i].toggle;
385 }
386 }
387 ImGui::EndMenu();
388 }
389 if (inspectors.size() && ImGui::BeginMenu("Extensions")) {
390 for (auto & inspector : inspectors) {
391 if (ImGui::MenuItem(inspector.name.c_str())) {
392 inspector.show = !inspector.show;
393 }
394 }
395 ImGui::EndMenu();
396 }
397 if (ImGui::BeginMenu("Help")) {
398 struct Button
399 {
400 const char * title;
401 bool & toggle;
402 } buttons[] = {
403 { "About", showAboutCogs },
404 //{ nullptr, none },
405 };
406 for (size_t i = 0; i < glm::countof(buttons); ++i) {
407 if (!buttons[i].title) continue;
408 if (ImGui::MenuItem(buttons[i].title)) {
409 buttons[i].toggle = !buttons[i].toggle;
410 }
411 }
412 ImGui::EndMenu();
413 }
414 ImGui::EndMenuBar();
415 }
416
417 renderTimes(context);
418
419 // Combo box with various visualization modes
420 {
421 struct {
422 const char* name;
423 const char* pipeline;
424 } visualizationModes[] = {
425 { "No visualizer", "" },
426 { "Show normals", "Pipelines/DebugView/ShowNormals.pipeline" },
427 { "Show draw calls", "Pipelines/DebugView/ShowDrawCalls.pipeline" },
428 { "Show object IDs", "Pipelines/DebugView/ShowObjectIDs.pipeline" },
429 { "Show triangle size", "Pipelines/DebugView/ShowTriangleSizes.pipeline" },
430 { "Show shadow cascades", "Pipelines/DebugView/ShowShadowCascades.pipeline" }
431 };
432 if (ImGui::BeginCombo("##combo", visualizationModes[visualizationMode].name)) {
433 for (size_t i = 0; i < IM_ARRAYSIZE(visualizationModes); i++) {
434 bool selected = i == visualizationMode;
435 if (ImGui::Selectable(visualizationModes[i].name, selected)) {
436 visualizationMode = static_cast<uint8_t>(i);
437 context->variables->set("renderer.pipeline.override", visualizationModes[i].pipeline);
438 }
439 if (selected) {
440 ImGui::SetItemDefaultFocus();
441 }
442 }
443 ImGui::EndCombo();
444 }
445
446 // Options for all visualizers
447 if (visualizationMode != 0) {
448 float edge = std::pow(context->variables->get("debugView.edge", 0.5f), 2.2f);
449 if (ImGui::SliderFloat("Wireframe", &edge, 0.f, 1.f, "%.3f")) {
450 context->variables->set("debugView.edge", std::pow(edge, 1.f / 2.2f));
451 }
452 float outline = std::pow(context->variables->get("debugView.outline", 1.0f), 2.2f);
453 if (ImGui::SliderFloat("Outline", &outline, 0.f, 1.f, "%.3f")) {
454 context->variables->set("debugView.outline", std::pow(outline, 1.f / 2.2f));
455 }
456 }
457
458 // Options for triangle size
459 if (visualizationMode == 4) {
460 float lo = context->variables->get("debugView.triangleSize.lo", 10.f);
461 float hi = context->variables->get("debugView.triangleSize.hi", 100.f);
462 bool update = false;
463 if (ImGui::SliderFloat("Yellow size", &lo, 1.f, 100.f, "%.1f")) {
464 update = true;
465 }
466 if (ImGui::SliderFloat("Green size", &hi, 1.f, 100.f, "%.1f")) {
467 lo = std::max(1.f, std::min(lo, hi - 1.f));
468 update = true;
469 }
470 hi = std::max(lo + 1.f, hi);
471 if (update) {
472 context->variables->set("debugView.triangleSize.lo", lo);
473 context->variables->set("debugView.triangleSize.hi", hi);
474 }
475 }
476 }
477
478 {
479 QualityService* quality = context->qualityService.get();
480 float qualitySetting = context->variables->get("quality.setting", 100.f);
481 if (ImGui::SliderFloat("##Quality", &qualitySetting, 0.f, 200.f, "quality %.0f%%")) {
482 context->variables->set("quality.setting", qualitySetting);
483 }
484 ImGui::Text("Current quality: %.2f, AssetSystem: %.2f",
485 quality->currentQuality,
486 quality->assetSystemToleranceScale);
487 ImGui::Text("PoTreeSystem: %.2f/%.2f, 3DTilesSystem: %.2f/%.2f",
488 quality->potreeSystemToleranceScale,
489 quality->potreeSystemChunkCountScale,
490 quality->ogc3DTilesSystemCacheControl,
491 quality->ogc3DTilesSystemToleranceScale);
492 }
493 ImGui::Spacing();
494
495 struct Button
496 {
497 const char * title;
498 bool & toggle;
499 } buttons[] = {
500 { "Entities", showEntityInspector },
501 { "Variables", showVariableInspector },
502 };
503 ImVec2 buttonSize(96, 24);
504
505 for (size_t i = 0; i < glm::countof(buttons); ++i) {
506 if (!buttons[i].title) continue;
507
508 if (i % 2 != 0) ImGui::SameLine();
509
510 if (ImGui::Button(buttons[i].title, buttonSize)) {
511 buttons[i].toggle = !buttons[i].toggle;
512 }
513 }
514 }
515 ImGui::End();
516
517 for (const VariableMap& variableMap : variableMapping) {
518 if (Variable* var = context->variables->getIfExists(variableMap.name); var != nullptr && !var->isEmpty()) {
519 var->setBool(variableMap.toggle);
520 }
521 }
522
523 for (auto & inspector : inspectors) {
524 inspector.inspector(context, &inspector.show);
525 }
526
527 aboutCogs(context, &showAboutCogs);
528 textureInspector(context, &showTextureInspector);
529 shadowMapInspector(context, &showShadowMapInspector);
530 entityInspector(context, &showEntityInspector);
531 variableInspector(context, &showVariableInspector);
532 modelInspector(context, &showModelInspector);
533 meshInspector(context, &showMeshInspector);
534 materialInspector(context, &showMaterialInspector);
535 materialInstanceInspector(context, &showMaterialInstanceInspector);
536 fontInspector(context, &showFontInspector);
537 inputInspector(context, &showInputInspector);
538 resourceStoreInspector(context, &showResourceInspector);
539 scriptInspector(context, &showScriptInspector);
540 scriptConsole(context, &showScriptConsole);
541 profileInspector(context, &showProfiler);
542 renderingStatsInspector(context, &showRenderingStatsInspector);
543 pipelineInspector(context, &showPipelineInspector);
544 permutationInspector(context, &showPermutationInspector);
545 assetInspector(context, &showAssetInspector);
546 assetQueueInspector(context, &showAssetQueueInspector);
547 boundsInspector(context, &showBoundsInspector);
548 bufferInspector(context, &showBufferInspector);
549 engineInspector(context, &showEngineInspector);
550 gammaDebugger(context, &showGammaDebugger);
551 taskManagerInspector(context, &showTaskManagerInspector);
552 if(renderer->getDevice()->getType() == GraphicsDeviceType::WebGPU){
553 webgpuCountersInspector(context, renderer, &showWebGPUCountersInspector);
554 }
555
556 if(showExampleGui) {
557 ImGui::ShowDemoWindow(&showExampleGui);
558 }
559
560 if(!show){
561 context->variables->set("gui.enabled", false);
562 }
563}
564
565void Cogs::Core::InspectorGuiRenderer::endRender(Context * /*context*/, IRenderer * renderer)
566{
567 RenderInstrumentationScope(renderer->getDevice()->getImmediateContext(), SCOPE_RENDERING, "GuiRenderer::endRender");
568
569 imguiRenderer->render();
570}
571
572void Cogs::Core::InspectorGuiRenderer::cleanup(Context * /*context*/, IRenderer * /*renderer*/)
573{
574 if (imguiContext) {
575 imguiRenderer->deleteGuiContext(imguiContext);
576 imguiContext = nullptr;
577 }
578}
@ WebGPU
Graphics device using the WebGPU API Backend.