SpiecsEngine
 
Loading...
Searching...
No Matches
ImguiRendererProfilerHUD.cpp
Go to the documentation of this file.
1 /**
2* @file ImguiRendererProfilerHUD.cpp.
3* @brief The ImguiRendererProfilerHUD Class Implementation.
4* @author Spices.
5*/
6
7#include "Pchheader.h"
9#include "Render/Renderer/RendererManager.h"
10#include "Render/Renderer/Renderer.h"
11#include "Render/Renderer/RenderPassStatistics/RenderPassStatistics.h"
12#include "..\..\..\..\..\..\Render\Renderer\RenderPassStatistics\TimestampQuerier.h"
13#include "..\..\..\..\..\..\Render\Renderer\RenderPassStatistics\PipelineStatisticsQuerier.h"
14#include "Core/Container/Tree.h"
15
16namespace Spices {
17
19 const std::string& panelName ,
20 FrameInfo& frameInfo
21 )
22 : ImguiSlate(panelName, frameInfo)
23 {}
24
26 {
28
29 if (!m_IsSlateOn) return;
30
31 /**
32 * @brief Begin render RendererProfilerHUD.
33 */
34 Begin();
35 ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(2.0f, 4.0f));
36
37 /**
38 * @brief Search String.
39 */
40 static std::string searchString;
41 static bool isEnableSearch = false;
42
43 /**
44 * @brief Begin render Search Input Text.
45 */
46 {
47 SPICES_PROFILE_ZONEN("ImguiRendererProfilerHUD::Search");
48
49 ImGui::Spacing();
50 ImGui::PushItemWidth(m_PanelSize.x - ImGuiH::GetLineItemSize().x * 2.0f - ImGui::GetStyle().WindowPadding.x);
51 static char search[256] = {};
52 if (ImGui::InputTextWithHint("##", ICON_TEXT(ICON_MD_SEARCH, Search), search, 128))
53 {
54 searchString = std::string(search);
55 if (searchString.size() == 0) isEnableSearch = false;
56 else isEnableSearch = true;
57 }
58 ImGui::PopItemWidth();
59
60 ImGui::SameLine(m_PanelSize.x - ImGuiH::GetLineItemSize().x * 2.0f);
61 ImGui::Button(ICON_MD_FILTER_ALT, ImGuiH::GetLineItemSize());
62 ImGui::SameLine(m_PanelSize.x - ImGuiH::GetLineItemSize().x * 1.0f);
63 ImGui::Button(ICON_MD_REORDER, ImGuiH::GetLineItemSize());
64 ImGui::Spacing();
65 }
66
67 static int selectedStatistics = 0;
68 static int selectedChannel = 0;
69
70 ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0.196f, 0.204f, 0.2f, 1.0f));
71 ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(0.164f, 0.18f, 0.184f, 1.0f));
72 ImGui::PushStyleColor(ImGuiCol_HeaderActive, ImVec4(0.164f, 0.18f, 0.184f, 1.0f));
73 ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.196f, 0.204f, 0.2f, 1.0f));
74
75 /**
76 * @brief Render Datails.
77 */
78 {
79 SPICES_PROFILE_ZONEN("ImguiRendererProfilerHUD::Datails");
80
81 {
82 ImGui::PushID("ImguiRendererProfilerHUD::Statistics Type");
83 ImGui::Columns(2, 0, false);
84 ImGui::SetColumnWidth(0, ImGuiH::GetLineItemSize().x * 4.0f);
85 ImGui::Text("Statistics");
86 ImGui::NextColumn();
87
88 static const char* type[] = { " TimeStamp", " PipelineStatistics" };
89 ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
90 ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.6f, 0.6f, 0.6f, 1.0f));
91 ImGui::Combo("##", &selectedStatistics, type, _countof(type));
92 ImGui::PopStyleColor();
93 ImGui::PopItemWidth();
94
95 ImGui::Columns(1);
96 ImGui::PopID();
97 }
98
99 if (selectedStatistics == 1)
100 {
101 ImGui::PushID("ImguiRendererProfilerHUD::PipelineChannel");
102 ImGui::Columns(2, 0, false);
103 ImGui::SetColumnWidth(0, ImGuiH::GetLineItemSize().x * 4.0f);
104 ImGui::Text("Channel");
105 ImGui::NextColumn();
106
107 static const char* channel[] = {
108 " Input Assembly Vertices",
109 " Input Assembly Primitive",
110 " Vertex Shader Invocations",
111 " Geometry Shader Invocations",
112 " Geometry Shader Primitive",
113 " Clipping Invocations",
114 " Clipping Primitive",
115 " Fragment Shader Invocations",
116 " Tessellation Control Invocations",
117 " Tessellation Evaluation Invocations",
118 " Compute Shader Invocations",
119 " Task Shader Invocations",
120 " Mesh Shader Invocations"
121 };
122 ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
123 ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.6f, 0.6f, 0.6f, 1.0f));
124 ImGui::Combo("##", &selectedChannel, channel, _countof(channel));
125 ImGui::PopStyleColor();
126 ImGui::PopItemWidth();
127
128 ImGui::Columns(1);
129 ImGui::PopID();
130 }
131
132 {
133 ImGui::PushID("ImguiRendererProfilerHUD::Refresh");
134 ImGui::Columns(2, 0, false);
135 ImGui::SetColumnWidth(0, ImGuiH::GetLineItemSize().x * 4.0f);
136 ImGui::Text("Refresh");
137 ImGui::NextColumn();
138
139 static bool isChecked = false;
140 ImGuiH::Checkbox(&isChecked);
141
142 if (isChecked)
143 {
144 RENDERPASS_STATISTICS_CAPTUREFRAME
145 isChecked = false;
146 }
147
148 ImGui::Columns(1);
149 ImGui::PopID();
150 }
151 }
152
153 ImGui::PopStyleColor(4);
154
155 if (selectedStatistics == 0)
156 {
158 }
159 else if(selectedStatistics == 1)
160 {
161 DrawPipelineStatistics(selectedChannel);
162 }
163
164 /**
165 * @brief End render RendererProfilerHUD Visualizer.
166 */
167 ImGui::PopStyleVar();
168 End();
169 }
170
172 {
174
175 /**
176 * @brief Tree node.
177 */
178 struct TimestampResult
179 {
180 TimestampQuerier::Result result;
181 std::string name;
182 };
183
184 /**
185 * @brief Instance a Tree.
186 */
187 scl::tree<TimestampResult> totalResult;
188 totalResult.GetData().name = "Scene ( Viewport 0 )";
189
190 /**
191 * @brief Write scene data to tree.
192 */
193 {
194 SPICES_PROFILE_ZONEN("Fetch Statistics Caches");
195
196 RendererManager::IterRenderer([&](const std::string& rendererName, const std::shared_ptr<Renderer>& renderer) {
197
198 const auto rendererResult = totalResult.AddChild();
199 rendererResult->GetData().name = rendererName;
200
201 renderer->IterStatistics([&](const std::string& subPassName, const std::shared_ptr<RenderPassStatistics>& statistics) {
202
203 const auto subPassResult = rendererResult->AddChild();
204 subPassResult->GetData().name = subPassName;
205
206 statistics->IterStatisticsResult(Querier::Timestamp, [&](const Querier::StatisticsBits& type, std::shared_ptr<Querier::Result>& result) {
207
208 TimestampQuerier::Result* res = static_cast<TimestampQuerier::Result*>(result.get());
209 if (res->valid)
210 {
211 subPassResult->GetData().result = *res;
212
213 rendererResult->GetData().result.Combine(res);
214 rendererResult->GetData().result.valid = true;
215
216 totalResult.GetData().result.Combine(res);
217 totalResult.GetData().result.valid = true;
218 }
219 });
220
221 return false;
222 });
223
224 return false;
225 });
226 }
227
228 {
229 SPICES_PROFILE_ZONEN("Draw Statistics Caches");
230
231 static ImGuiTableFlags flags = ImGuiTableFlags_BordersV | ImGuiTableFlags_BordersOuterH | ImGuiTableFlags_Resizable | ImGuiTableFlags_NoBordersInBody |
232 ImGuiTableFlags_Sortable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_SortMulti | ImGuiTableFlags_Hideable |
233 ImGuiTableFlags_ScrollY | ImGuiTableFlags_SortTristate;
234 static ImGuiTreeNodeFlags tree_node_flags = ImGuiTreeNodeFlags_SpanAllColumns;
235
236 /**
237 * @brief 0: NoSort, 1: Ascending, 2: Descending.
238 */
239 static int sortState = 0;
240
241 /**
242 * @brief Function of quick sort to PipelineResult.
243 */
244 static auto SortTimestampTreeMethod = [](const void* lhs, const void* rhs) -> int {
245
246 const auto l = static_cast<const std::unique_ptr<scl::tree<TimestampResult>>*>(lhs);
247 const auto r = static_cast<const std::unique_ptr<scl::tree<TimestampResult>>*>(rhs);
248
249 ImGuiTableSortSpecs* sort_specs = ImGui::TableGetSortSpecs();
250 if (sortState == ImGuiSortDirection_Ascending)
251 {
252 return ((*l)->GetData().result.timeStamp - (*r)->GetData().result.timeStamp) * 1000;
253 }
254 else
255 {
256 return ((*r)->GetData().result.timeStamp - (*l)->GetData().result.timeStamp) * 1000;
257 }
258 };
259
260 /**
261 * @brief Function of sort whole tree.
262 */
263 static std::function<void(scl::tree<TimestampResult>*)> SortTimestampTree = [&](scl::tree<TimestampResult>* node) {
264
265 if (sortState == 0) return;
266
267 qsort((void*)node->GetChilds().data(), (size_t)node->GetChilds().size(), sizeof(node->GetChilds()[0]), SortTimestampTreeMethod);
268
269 for (auto& child : node->GetChilds())
270 {
271 SortTimestampTree(child.get());
272 }
273 };
274
275 /**
276 * @brief Function of draw whole tree.
277 */
278 static std::function<void(scl::tree<TimestampResult>*, uint32_t, scl::tree<TimestampResult>*)> DrawTimestampTree = [&](scl::tree<TimestampResult>* node, uint32_t depth, scl::tree<TimestampResult>* root) {
279
280 if (!node->GetData().result.valid) return;
281
282 ImGui::TableNextRow();
283 ImGui::TableNextColumn();
284
285 std::stringstream space;
286 for (uint32_t i = 0; i < depth; i++)
287 {
288 space << " ";
289 }
290
291 ImGui::Text(space.str().c_str());
292 ImGui::SameLine();
293
294 bool hasChild = node->GetChilds().size() > 0;
295 if (hasChild)
296 {
297 bool open = ImGui::TreeNodeEx(node->GetData().name.c_str(), tree_node_flags);
298 ImGui::TableNextColumn();
299
300 ImGui::PushStyleColor(ImGuiCol_PlotHistogram, ImVec4(0.0f, 0.8f, 0.0f, 1.0f));
301 ImGui::ProgressBar(root->GetData().result.timeStamp > 0 ? (node->GetData().result.timeStamp / root->GetData().result.timeStamp) : 0.0f, ImVec2(-FLT_MIN, 2.0f), "##");
302 ImGui::PopStyleColor();
303 ImGui::SameLine(0.05f);
304 ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.8f, 0.8f, 0.8f, 1.0f));
305 ImGui::Text("%.2f ms", node->GetData().result.timeStamp);
306 ImGui::PopStyleColor();
307 if (open)
308 {
309 for (auto& child : node->GetChilds())
310 {
311 DrawTimestampTree(child.get(), depth + 1, root);
312 }
313 ImGui::TreePop();
314 }
315 }
316 else
317 {
318 ImGui::TreeNodeEx(node->GetData().name.c_str(), tree_node_flags | ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen);
319 ImGui::TableNextColumn();
320
321 ImGui::PushStyleColor(ImGuiCol_PlotHistogram, ImVec4(0.0f, 0.8f, 0.0f, 1.0f));
322 ImGui::ProgressBar(root->GetData().result.timeStamp > 0 ? (node->GetData().result.timeStamp / root->GetData().result.timeStamp) : 0.0f, ImVec2(-FLT_MIN, 2.0f), "##");
323 ImGui::PopStyleColor();
324 ImGui::SameLine(0.05f);
325 ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.8f, 0.8f, 0.8f, 1.0f));
326 ImGui::Text("%.2f ms", node->GetData().result.timeStamp);
327 ImGui::PopStyleColor();
328 }
329 };
330
331 ImGui::PushStyleVar(ImGuiStyleVar_IndentSpacing, 0.0f);
332 ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0.196f, 0.204f, 0.2f, 1.0f));
333 ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(0.164f, 0.18f, 0.184f, 1.0f));
334 ImGui::PushStyleColor(ImGuiCol_HeaderActive, ImVec4(0.164f, 0.18f, 0.184f, 1.0f));
335 ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.196f, 0.204f, 0.2f, 1.0f));
336
337 if (ImGui::BeginTable("timestampTree", 2, flags))
338 {
339 // The first column will use the default _WidthStretch when ScrollX is Off and _WidthFixed when ScrollX is On
340 ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_NoHide);
341 ImGui::TableSetupColumn("TimeCost", ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_PreferSortDescending, ImGuiH::GetLineItemSize().x * 3.0f);
342 ImGui::TableHeadersRow();
343
344 // Sort our data if sort specs have been changed!
345 if (ImGuiTableSortSpecs* sort_specs = ImGui::TableGetSortSpecs())
346 {
347 // State changed since last frame.
348 if (sort_specs->SpecsDirty)
349 {
350 sortState = 0;
351
352 // Need sort this frame.
353 if (sort_specs->SpecsCount > 0)
354 {
355 sortState = sort_specs->Specs->SortDirection;
356 }
357
358 sort_specs->SpecsDirty = false;
359 }
360 }
361
362 SortTimestampTree(&totalResult);
363 DrawTimestampTree(&totalResult, 0, &totalResult);
364
365 ImGui::EndTable();
366 }
367 ImGui::PopStyleColor(4);
368 ImGui::PopStyleVar();
369 }
370 }
371
373 {
375
376 /**
377 * @brief Store bit as static variable.
378 */
379 static int selectBit;
380 selectBit = bit;
381
382 /**
383 * @brief Tree node.
384 */
385 struct PipelineResult
386 {
387 PipelineStatisticsQuerier::Result result;
388 std::string name;
389 };
390
391 /**
392 * @brief Instance a Tree.
393 */
394 scl::tree<PipelineResult> totalResult;
395 totalResult.GetData().name = "Scene ( Viewport 0 )";
396
397 /**
398 * @brief Write scene data to tree.
399 */
400 {
401 SPICES_PROFILE_ZONEN("Fetch Statistics Caches");
402
403 RendererManager::IterRenderer([&](const std::string& rendererName, const std::shared_ptr<Renderer>& renderer) {
404
405 auto rendererResult = totalResult.AddChild();
406 rendererResult->GetData().name = rendererName;
407
408 renderer->IterStatistics([&](const std::string& subPassName, const std::shared_ptr<RenderPassStatistics>& statistics) {
409
410 auto subPassResult = rendererResult->AddChild();
411 subPassResult->GetData().name = subPassName;
412
413 statistics->IterStatisticsResult(Querier::Pipeline, [&](const Querier::StatisticsBits& type, std::shared_ptr<Querier::Result>& result) {
414
415 PipelineStatisticsQuerier::Result* res = static_cast<PipelineStatisticsQuerier::Result*>(result.get());
416 if (res->valid)
417 {
418 subPassResult->GetData().result = *res;
419
420 rendererResult->GetData().result.Combine(res);
421 rendererResult->GetData().result.valid = true;
422
423 totalResult.GetData().result.Combine(res);
424 totalResult.GetData().result.valid = true;
425 }
426 });
427
428 return false;
429 });
430
431 return false;
432 });
433 }
434
435 {
436 SPICES_PROFILE_ZONEN("Draw Statistics Caches");
437
438 static ImGuiTableFlags flags = ImGuiTableFlags_BordersV | ImGuiTableFlags_BordersOuterH | ImGuiTableFlags_Resizable | ImGuiTableFlags_NoBordersInBody |
439 ImGuiTableFlags_Sortable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_SortMulti | ImGuiTableFlags_Hideable |
440 ImGuiTableFlags_ScrollY | ImGuiTableFlags_SortTristate;
441 static ImGuiTreeNodeFlags tree_node_flags = ImGuiTreeNodeFlags_SpanAllColumns;
442
443 /**
444 * @brief 0: NoSort, 1: Ascending, 2: Descending.
445 */
446 static int sortState = 0;
447
448 /**
449 * @brief Function of quick sort to PipelineResult.
450 */
451 static auto SortTimestampTreeMethod = [](const void* lhs, const void* rhs) -> int {
452
453 const auto l = static_cast<const std::unique_ptr<scl::tree<PipelineResult>>*>(lhs);
454 const auto r = static_cast<const std::unique_ptr<scl::tree<PipelineResult>>*>(rhs);
455
456 ImGuiTableSortSpecs* sort_specs = ImGui::TableGetSortSpecs();
457 if (sortState == ImGuiSortDirection_Ascending)
458 {
459 return (*l)->GetData().result.statistics[selectBit] - (*r)->GetData().result.statistics[selectBit];
460 }
461 else
462 {
463 return (*r)->GetData().result.statistics[selectBit] - (*l)->GetData().result.statistics[selectBit];
464 }
465 };
466
467 /**
468 * @brief Function of sort whole tree.
469 */
470 static std::function<void(scl::tree<PipelineResult>*)> SortTimestampTree = [&](scl::tree<PipelineResult>* node) {
471
472 if (sortState == 0) return;
473
474 qsort((void*)node->GetChilds().data(), (size_t)node->GetChilds().size(), sizeof(node->GetChilds()[0]), SortTimestampTreeMethod);
475
476 for (auto& child : node->GetChilds())
477 {
478 SortTimestampTree(child.get());
479 }
480 };
481
482 /**
483 * @brief Function of draw whole tree.
484 */
485 static std::function<void(scl::tree<PipelineResult>*, uint32_t depth, scl::tree<PipelineResult>*)> DrawTimestampTree = [&](scl::tree<PipelineResult>* node, uint32_t depth, scl::tree<PipelineResult>* root) {
486
487 if (!node->GetData().result.valid) return;
488
489 ImGui::TableNextRow();
490 ImGui::TableNextColumn();
491
492 std::stringstream space;
493 for (uint32_t i = 0; i < depth; i++)
494 {
495 space << " ";
496 }
497
498 ImGui::Text(space.str().c_str());
499 ImGui::SameLine();
500
501 bool hasChild = node->GetChilds().size() > 0;
502 if (hasChild)
503 {
504 bool open = ImGui::TreeNodeEx(node->GetData().name.c_str(), tree_node_flags);
505 ImGui::TableNextColumn();
506
507 ImGui::PushStyleColor(ImGuiCol_PlotHistogram, ImVec4(0.0f, 0.8f, 0.0f, 1.0f));
508 ImGui::ProgressBar(root->GetData().result.statistics[bit] > 0 ? (node->GetData().result.statistics[bit] / float(root->GetData().result.statistics[bit])) : 0.0f, ImVec2(-FLT_MIN, 2.0f), "##");
509 ImGui::PopStyleColor();
510 ImGui::SameLine(0.05f);
511 ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.8f, 0.8f, 0.8f, 1.0f));
512 ImGui::Text("%d", node->GetData().result.statistics[bit]);
513 ImGui::PopStyleColor();
514 if (open)
515 {
516 for (auto& child : node->GetChilds())
517 {
518 DrawTimestampTree(child.get(), depth + 1, root);
519 }
520 ImGui::TreePop();
521 }
522 }
523 else
524 {
525 ImGui::TreeNodeEx(node->GetData().name.c_str(), tree_node_flags | ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen);
526 ImGui::TableNextColumn();
527
528 ImGui::PushStyleColor(ImGuiCol_PlotHistogram, ImVec4(0.0f, 0.8f, 0.0f, 1.0f));
529 ImGui::ProgressBar(root->GetData().result.statistics[bit] > 0 ? (node->GetData().result.statistics[bit] / float(root->GetData().result.statistics[bit])) : 0.0f, ImVec2(-FLT_MIN, 2.0f), "##");
530 ImGui::PopStyleColor();
531 ImGui::SameLine(0.05f);
532 ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.8f, 0.8f, 0.8f, 1.0f));
533 ImGui::Text("%d", node->GetData().result.statistics[bit]);
534 ImGui::PopStyleColor();
535 }
536 };
537
538 ImGui::PushStyleVar(ImGuiStyleVar_IndentSpacing, 0.0f);
539 ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0.196f, 0.204f, 0.2f, 1.0f));
540 ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(0.164f, 0.18f, 0.184f, 1.0f));
541 ImGui::PushStyleColor(ImGuiCol_HeaderActive, ImVec4(0.164f, 0.18f, 0.184f, 1.0f));
542 ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.196f, 0.204f, 0.2f, 1.0f));
543
544 if (ImGui::BeginTable("pipelineTree", 2, flags))
545 {
546 // The first column will use the default _WidthStretch when ScrollX is Off and _WidthFixed when ScrollX is On
547 ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_NoSort | ImGuiTableColumnFlags_NoHide);
548 ImGui::TableSetupColumn("Invocation Count", ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_PreferSortDescending, ImGuiH::GetLineItemSize().x * 3.0f);
549 ImGui::TableSetupScrollFreeze(0, 1);
550 ImGui::TableHeadersRow();
551
552 // Sort our data if sort specs have been changed!
553 if (ImGuiTableSortSpecs* sort_specs = ImGui::TableGetSortSpecs())
554 {
555 // State changed since last frame.
556 if (sort_specs->SpecsDirty)
557 {
558 sortState = 0;
559
560 // Need sort this frame.
561 if (sort_specs->SpecsCount > 0)
562 {
563 sortState = sort_specs->Specs->SortDirection;
564 }
565
566 sort_specs->SpecsDirty = false;
567 }
568 }
569
570 SortTimestampTree(&totalResult);
571 DrawTimestampTree(&totalResult, 0, &totalResult);
572
573 ImGui::EndTable();
574 }
575 ImGui::PopStyleColor(4);
576 ImGui::PopStyleVar();
577 }
578 }
579}
#define ICON_TEXT(icon, text)
Definition ImguiHelper.h:24
#define SPICES_PROFILE_ZONEN(...)
#define SPICES_PROFILE_ZONE
FrameInfo Class. This class defines the FrameInfo data.
Definition FrameInfo.h:32
static void Checkbox(bool *isChecked)
ImGuiHelper Style Checkbox.
The ImGuiH Class. This class defines helper function for slate render.
Definition ImguiHelper.h:61
virtual void OnRender() override
This interface is called On SlateRenderer Render.
ImguiRendererProfilerHUD(const std::string &panelName, FrameInfo &frameInfo)
Constructor Function.
void End()
End a slate.
ImguiSlate(const std::string &panelName, FrameInfo &frameInfo)
Constructor Function. Init with Slate's name.
Definition ImguiUtils.h:35
This Class defines the basic behaves of specific slate. When we add an new Slate, we need inherit fro...
Definition ImguiUtils.h:27
RendererManager Class. This class Manages all renderer.
Renderer Class. This class defines the basic behaves of renderer. When we add an new Renderer,...
Definition Renderer.h:57
simple tree.
Definition Tree.h:18