Cogs.Core
PipelineInspector.cpp
1#include "Inspectors.h"
2
3#include "InspectorGuiHelper.h"
4#include "Context.h"
5
6#include "Services/Variables.h"
7
8#include "Renderer/Renderer.h"
9#include "Renderer/RenderPipelineManager.h"
10#include "Renderer/RenderTexture.h"
11#include "Renderer/RenderList.h"
12#include "Renderer/RenderTarget.h"
13#include "Renderer/RenderBuffer.h"
14#include "Renderer/RenderMaterialInstance.h"
15
16#include "Renderer/Tasks/GenerateListTask.h"
17#include "Renderer/Tasks/ProcessTask.h"
18#include "Renderer/Tasks/PostProcessTask.h"
19#include "Renderer/Tasks/FilterListTask.h"
20#include "Renderer/Tasks/RenderListTask.h"
21
22#include "Resources/TextureManager.h"
23
24#include "Foundation/Reflection/TypeDatabase.h"
25
26
27using namespace Cogs::Reflection;
28
29namespace {
30 using namespace Cogs::Core;
31
32 void binaryNumber(uint32_t number)
33 {
34 ImGui::Text("0b_%u%u%u%u_%u%u%u%u_%u%u%u%u_%u%u%u%u_%u%u%u%u_%u%u%u%u_%u%u%u%u_%u%u%u%u",
35 (number & (1 << 31)) ? 1 : 0,
36 (number & (1 << 30)) ? 1 : 0,
37 (number & (1 << 29)) ? 1 : 0,
38 (number & (1 << 28)) ? 1 : 0,
39 (number & (1 << 27)) ? 1 : 0,
40 (number & (1 << 26)) ? 1 : 0,
41 (number & (1 << 25)) ? 1 : 0,
42 (number & (1 << 24)) ? 1 : 0,
43 (number & (1 << 23)) ? 1 : 0,
44 (number & (1 << 22)) ? 1 : 0,
45 (number & (1 << 21)) ? 1 : 0,
46 (number & (1 << 20)) ? 1 : 0,
47 (number & (1 << 19)) ? 1 : 0,
48 (number & (1 << 18)) ? 1 : 0,
49 (number & (1 << 17)) ? 1 : 0,
50 (number & (1 << 16)) ? 1 : 0,
51 (number & (1 << 15)) ? 1 : 0,
52 (number & (1 << 14)) ? 1 : 0,
53 (number & (1 << 13)) ? 1 : 0,
54 (number & (1 << 12)) ? 1 : 0,
55 (number & (1 << 11)) ? 1 : 0,
56 (number & (1 << 10)) ? 1 : 0,
57 (number & (1 << 9)) ? 1 : 0,
58 (number & (1 << 8)) ? 1 : 0,
59 (number & (1 << 7)) ? 1 : 0,
60 (number & (1 << 6)) ? 1 : 0,
61 (number & (1 << 5)) ? 1 : 0,
62 (number & (1 << 4)) ? 1 : 0,
63 (number & (1 << 3)) ? 1 : 0,
64 (number & (1 << 2)) ? 1 : 0,
65 (number & (1 << 1)) ? 1 : 0,
66 (number & (1 << 0)) ? 1 : 0);
67 }
68
69 void showRenderItem(Context* /*context*/, Renderer* renderer, const RenderItem & item, size_t ix)
70 {
71 std::string header = "Item " + std::to_string(ix);
72 if ((item.stateChanges & StateChangeFlags::ChangeAll) == StateChangeFlags::ChangeAll) {
73 header += " All";
74 } else {
75 if ((item.stateChanges & StateChangeFlags::ChangeTransform) != 0) {
76 header += " Tr";
77 }
78 if ((item.stateChanges & StateChangeFlags::ChangeMesh) != 0) {
79 header += " Msh";
80 }
81 if ((item.stateChanges & StateChangeFlags::ChangeMaterialInstance) != 0) {
82 header += " MatI";
83 }
84 if ((item.stateChanges & StateChangeFlags::ChangeMaterialVariant) != 0) {
85 header += " MatV";
86 }
87 if ((item.stateChanges & StateChangeFlags::ChangeRasterizerState) != 0) {
88 header += " Ras";
89 }
90 if ((item.stateChanges & StateChangeFlags::ChangeBlendState) != 0) {
91 header += " Bld";
92 }
93 if ((item.stateChanges & StateChangeFlags::ChangeDepthStencilState) != 0) {
94 header += " Dpt";
95 }
96 if ((item.stateChanges & StateChangeFlags::ChangeLayer) != 0) {
97 header += " Lay";
98 }
99 if ((item.stateChanges & StateChangeFlags::ChangeViewport) != 0) {
100 header += " VPort";
101 }
102 }
103 if (item.materialInstance && item.materialInstance->material) {
104 header.append(" mat=");
105 header.append(item.materialInstance->material->definition.name);
106 RenderMaterialInstance * renderMaterialInstance = renderer->getRenderResources().getRenderMaterialInstance(item.materialInstance);
107 if (!renderMaterialInstance) {
108 header.append("(no render material)");
109 }
110 else {
111 header.append("(");
112 if (renderMaterialInstance->loadedBindings.empty()) {
113 header.append("no bindings");
114 }
115 else {
116 for (auto & binding : renderMaterialInstance->loadedBindings) {
117 if (binding.enginePermutation) {
118 header.append(binding.enginePermutation->getName());
119 }
120 else {
121 header.append("<no engine perm>");
122 }
123 header.append(": ");
124 if (binding.binding) {
125 if (binding.binding->renderEffect) {
126 header.append("has renderEffect");
127 }
128 else {
129 header.append("<no renderEffect>");
130 }
131 }
132 else {
133 header.append("<no binding>");
134 }
135 }
136 }
137 header.append(")");
138 }
139 }
140 ImGui::Text("%s", header.c_str());
141 }
142
143 void showRenderList(Context* context, Renderer* renderer, const RenderBatch& batch, const std::string& name)
144 {
145 if (batch.empty()) return;
146
147 if (ImGui::TreeNode(name.c_str(), "%s (%zu items)", name.c_str(), batch.size())) {
148 for (size_t i = 0; i < batch.size(); i++) {
149 showRenderItem(context, renderer, batch[i], i);
150 }
151 ImGui::TreePop();
152 }
153 }
154 void showRenderList(Context* context, Renderer* renderer, const RenderItems& items, const std::string& name)
155 {
156 if (items.empty()) return;
157
158 if (ImGui::TreeNode(name.c_str(), "%s (%zu items)", name.c_str(), items.size())) {
159 for (size_t i = 0; i < items.size(); i++) {
160 showRenderItem(context, renderer, items[i], i);
161 }
162 ImGui::TreePop();
163 }
164 }
165
166 void showRenderTarget(Context* /*context*/, Renderer* /*renderer*/, const RenderTarget * renderTarget)
167 {
168 ImGui::Text("Width"); ImGui::SameLine(250.f); ImGui::Text("%u", renderTarget->width);
169 ImGui::Text("Height"); ImGui::SameLine(250.f); ImGui::Text("%u", renderTarget->height);
170 ImGui::Text("Subresource index"); ImGui::SameLine(250.f); ImGui::Text("%u", renderTarget->subresourceIndex);
171 ImGui::Text("Depth layer index"); ImGui::SameLine(250.f); ImGui::Text("%u", renderTarget->depthLayerIndex);
172 ImGui::Text("Level views"); ImGui::SameLine(250.f); ImGui::Text("%zu", renderTarget->mipLevelViews.size());
173
174 auto size = ImVec2(128, 128);
175 float aspectRatio = 1;
176 if (renderTarget->width > 0 && renderTarget->height > 0) {
177 aspectRatio = static_cast<float>(renderTarget->width) / static_cast<float>(renderTarget->height);
178 }
179
180 if (aspectRatio < 1) {
181 size.x *= aspectRatio;
182 } else {
183 size.y /= aspectRatio;
184 }
185
186 ImGui::BeginGroup();
187
188 for (size_t i = 0; i < renderTarget->textures.size(); i++) {
189 if (i != 0) ImGui::SameLine(100 + i*150.f);
190 ImGui::Text(" Tex %zu", i);
191 }
192 for (size_t i = 0; i < renderTarget->textures.size(); i++) {
193 if (i != 0) ImGui::SameLine(100 + i*150.f);
194 ImGui::Image(ImTextureID(renderTarget->textures[i]->textureHandle.handle), size);
195 }
196
197 if (renderTarget->depth) {
198 ImGui::Text(" Depth");
199 ImGui::Image(ImTextureID(renderTarget->depth->textureHandle.handle), size);
200 }
201
202 ImGui::EndGroup();
203 }
204
205 void showResource(Context* context, Renderer* renderer, const RenderTaskResource* resource)
206 {
207 constexpr char const * fmtTitle[] = {
208 "Unknown",
209 "%s [TaskResource@0x%p]",
210 "%s [RenderTarget@0x%p]",
211 "%s [RenderList@0x%p]",
212 "%s [RenderBuffer@0x%p]",
213 "%s [RenderTexture@0x%p]",
214 "Error",
215 };
216
217 ImGui::PushID(resource);
218 if (ImGui::TreeNode("RenderResource", fmtTitle[static_cast<int>(resource->type)], std::string(resource->resource->getName()).c_str(), resource->resource)) {
219 switch (resource->type)
220 {
221 case RenderResourceType::RenderTarget:
222 {
223 showRenderTarget(context, renderer, resource->renderTarget);
224 break;
225 }
226 case RenderResourceType::RenderList:
227 {
228 auto renderList = resource->renderList;
229 showRenderList(context, renderer, renderList->batch, "All items");
230 showRenderList(context, renderer, renderList->buckets[size_t(BucketType::Backdrop)], "Backdrop bucket");
231 showRenderList(context, renderer, renderList->buckets[size_t(BucketType::SolidOrderedBack)], "Solid ordered back bucket");
232 showRenderList(context, renderer, renderList->buckets[size_t(BucketType::Solid)], "Solid bucket");
233 showRenderList(context, renderer, renderList->buckets[size_t(BucketType::SolidOrderedFront)], "Solid ordered front bucket");
234 showRenderList(context, renderer, renderList->buckets[size_t(BucketType::Transparent)], "Transparent bucket");
235 showRenderList(context, renderer, renderList->buckets[size_t(BucketType::Overlay)], "Overlay bucket");
236 showRenderList(context, renderer, renderList->buckets[size_t(BucketType::Custom)], "Custombucket");
237 break;
238 }
239 case RenderResourceType::RenderTexture:
240 {
241 showRenderTexture(context, renderer, resource->renderTexure);
242 break;
243 }
244 case RenderResourceType::RenderBuffer:
245 case RenderResourceType::TaskResource:
246 default:
247 break;
248 }
249
250 ImGui::TreePop();
251 }
252
253 ImGui::PopID();
254 }
255
256 void showTaskInner(Context* /*context*/, Renderer* /*renderer*/, const GenerateListTask* task)
257 {
258 if (task == nullptr) return;
259
260 ImGui::Text("list obj buffer %u of %u, size=%zukb",
261 task->listObjectBuffer.fill,
262 task->listObjectBuffer.cpuCapacity,
263 ((size_t(task->listObjectBuffer.stride) * task->listObjectBuffer.gpuCapacity) + 1023) / 1024);
264 }
265
266 void showTaskInner(Context* /*context*/, Renderer* /*renderer*/, const ProcessTask* task)
267 {
268 if (task == nullptr) return;
269
270 }
271
272 void showTaskInner(Context* /*context*/, Renderer* /*renderer*/, const PostProcessTask* task)
273 {
274 if (task == nullptr) return;
275
276 }
277
278 void showTaskInner(Context* /*context*/, Renderer* renderer, const FilterListTask* task)
279 {
280 if (task == nullptr) return;
281
282 ImGui::Text("BucketMask");
283 ImGui::SameLine(250.f);
284 ImGui::Text("%s%s%s%s%s%s%s",
285 hasBucket(task->bucketMask, BucketType::Backdrop) ? "BucketBackdrop " : "",
286 hasBucket(task->bucketMask, BucketType::SolidOrderedBack) ? "SolidOrderedBack " : "",
287 hasBucket(task->bucketMask, BucketType::Solid) ? "Solid " : "",
288 hasBucket(task->bucketMask, BucketType::SolidOrderedFront) ? "SolidOrderedFront " : "",
289 hasBucket(task->bucketMask, BucketType::Transparent) ? "Transparent " : "",
290 hasBucket(task->bucketMask, BucketType::Overlay) ? "Overlay " : "",
291 hasBucket(task->bucketMask, BucketType::Custom) ? "Custom " : "");
292
293 ImGui::Text("Wireframe");
294 ImGui::SameLine(250.f);
295 ImGui::Text("%s", task->wireframe ? "yes" : "no");
296
297 ImGui::Text("RenderMask");
298 ImGui::SameLine(250.f);
299 ImGui::Text("%s%s%s%s",
300 ((task->renderMask & RenderLayers::Default) != RenderLayers::None) ? "Default " : "",
301 ((task->renderMask & RenderLayers::Ocean) != RenderLayers::None) ? "Ocean " : "",
302 ((task->renderMask & RenderLayers::Annotations) != RenderLayers::None) ? "Annotations " : "",
303 ((task->renderMask & RenderLayers::Sky) != RenderLayers::None) ? "Sky " : "");
304
305 ImGui::Text("Permutation");
306 ImGui::SameLine(250.f);
307 ImGui::Text("%s", renderer->getEnginePermutations().get(task->permutation)->getName().c_str());
308
309 }
310
311 void showTaskInner(Context* /*context*/, Renderer* renderer, const RenderListTask* task)
312 {
313 if (task == nullptr) return;
314
315 ImGui::Columns(2);
316 ImGui::TextUnformatted("Object buffer mode:");
317 ImGui::NextColumn();
318 switch (task->objectBufferMode) {
319 case RenderListTask::ObjectBufferMode::Single:
320 ImGui::TextUnformatted("Single");
321 break;
322 case RenderListTask::ObjectBufferMode::Batched:
323 ImGui::TextUnformatted("Batched");
324 break;
325 case RenderListTask::ObjectBufferMode::List:
326 ImGui::TextUnformatted("List");
327 break;
328 }
329 ImGui::NextColumn();
330
331 ImGui::TextUnformatted("Permutation index:");
332 ImGui::NextColumn();
333 ImGui::Text("%s (%zu)", renderer->getEnginePermutations().get(task->permutationIndex)->getName().c_str(), task->permutationIndex);
334 ImGui::NextColumn();
335
336 ImGui::TextUnformatted("Bucket mask:");
337 ImGui::NextColumn();
338 binaryNumber(uint32_t(task->bucketMask));
339 ImGui::NextColumn();
340
341 ImGui::TextUnformatted("State change mask:");
342 ImGui::NextColumn();
343 binaryNumber(uint32_t(task->stateChangeMask));
344 ImGui::NextColumn();
345
346 ImGui::TextUnformatted("Lighting layers:");
347 ImGui::NextColumn();
348 binaryNumber(uint32_t(task->lightingMask));
349 ImGui::NextColumn();
350
351 ImGui::TextUnformatted("Blend mode:");
352 ImGui::NextColumn();
353 ImGui::Text("%u", uint32_t(task->blendMode));
354 ImGui::NextColumn();
355
356 ImGui::TextUnformatted("Depth mode:");
357 ImGui::NextColumn();
358 ImGui::Text("%u", uint32_t(task->depthMode));
359 ImGui::NextColumn();
360
361 ImGui::TextUnformatted("Depth func:");
362 ImGui::NextColumn();
363 ImGui::Text("%u", uint32_t(task->depthFunc));
364 ImGui::NextColumn();
365
366 ImGui::TextUnformatted("Clear color:");
367 ImGui::NextColumn();
368 ImGui::TextUnformatted(task->colorClear ? "yes" : "no");
369 ImGui::NextColumn();
370
371 ImGui::TextUnformatted("Clear depth:");
372 ImGui::NextColumn();
373 ImGui::TextUnformatted(task->depthClear ? "yes" : "no");
374 ImGui::NextColumn();
375
376 ImGui::TextUnformatted("Depth write:");
377 ImGui::NextColumn();
378 ImGui::TextUnformatted(task->depthWrite ? "yes" : "no");
379 ImGui::NextColumn();
380
381 ImGui::TextUnformatted("Discard color:");
382 ImGui::NextColumn();
383 ImGui::TextUnformatted(task->discardColor ? "yes" : "no");
384 ImGui::NextColumn();
385
386 ImGui::TextUnformatted("Discard depth:");
387 ImGui::NextColumn();
388 ImGui::TextUnformatted(task->discardDepth ? "yes" : "no");
389 ImGui::NextColumn();
390
391 ImGui::TextUnformatted("Default viewport size:");
392 ImGui::NextColumn();
393 ImGui::Text("[%d x %d]", task->defaultViewportSize.x, task->defaultViewportSize.y);
394 ImGui::NextColumn();
395
396 ImGui::TextUnformatted("Viewport from target:");
397 ImGui::NextColumn();
398 ImGui::TextUnformatted(task->viewportFromTarget ? "yes" : "no");
399 ImGui::NextColumn();
400
401 ImGui::TextUnformatted("Temporal offsets:");
402 ImGui::NextColumn();
403 ImGui::TextUnformatted(task->temporalOffsets ? "yes" : "no");
404 ImGui::NextColumn();
405
406 }
407
408 void showTask(Context* context, Renderer* renderer, const RenderTask* task)
409 {
410 std::string id = std::to_string(reinterpret_cast<size_t>(task));
411 std::string name = task->name.empty() ? "<unnamed>" : task->name;
412
413 if (task->flags & RenderTaskFlags::Persistent) {
414 name += " [persistent]";
415 }
416
417 if (ImGui::TreeNode(id.c_str(), "%s", name.c_str())) {
418
419 if (!task->input.resources.empty()) {
420 if (ImGui::TreeNode("Inputs")) {
421 for (const auto & resource : task->input.resources) {
422 showResource(context, renderer, &resource);
423 }
424 ImGui::TreePop();
425 }
426 }
427
428 if (!task->output.resources.empty()) {
429 if (ImGui::TreeNode("Outputs")) {
430 for (const auto & resource : task->output.resources) {
431 showResource(context, renderer, &resource);
432 }
433 ImGui::TreePop();
434 }
435 }
436
437 if (!task->dependencies.empty()) {
438 if (ImGui::TreeNode("Dependencies")) {
439 for (auto & dependency : task->dependencies) {
440 ImGui::Text("%s", dependency.c_str());
441 }
442 ImGui::TreePop();
443 }
444 }
445
446 if (!task->options.empty()) {
447 if (ImGui::TreeNode("Options")) {
448 for (auto & option : task->options) {
449 ImGui::Text("%s=%s", option.first.c_str(), option.second.c_str());
450 }
451 ImGui::TreePop();
452 }
453 }
454
455 showTaskInner(context, renderer, dynamic_cast<const GenerateListTask*>(task));
456 showTaskInner(context, renderer, dynamic_cast<const ProcessTask*>(task));
457 showTaskInner(context, renderer, dynamic_cast<const PostProcessTask*>(task));
458 showTaskInner(context, renderer, dynamic_cast<const FilterListTask*>(task));
459 showTaskInner(context, renderer, dynamic_cast<const RenderListTask*>(task));
460
461 ImGui::TreePop();
462 }
463 }
464
465 void showTasks(Context* context, Renderer* renderer)
466 {
467 std::vector<const PipelineInstance *> instances;
468 instances.reserve(renderer->getPipelineManager()->getPipelineInstances().size());
469 for (auto & it : renderer->getPipelineManager()->getPipelineInstances()) {
470 instances.push_back(it.second.get());
471 }
472
473 std::sort(instances.begin(), instances.end(), [](const PipelineInstance * a, const PipelineInstance * b) { return a->priority < b->priority; });
474
475 if (ImGui::TreeNode("Global resources")) {
477 r.type = RenderResourceType::RenderList;
478 r.key = "";
479 r.renderList = const_cast<RenderList*>(renderer->getPipelineManager()->getMainRenderList());
480 showResource(context, renderer, &r);
481 ImGui::TreePop();
482 }
483
484 if (ImGui::TreeNode("Global tasks")) {
485 showTask(context, renderer, renderer->getPipelineManager()->getGenerateListTask());
486 ImGui::TreePop();
487 }
488
489 if (ImGui::TreeNode("Pipeline instance sequence")) {
490 uint32_t id = 0;
491 for (const auto instance : instances) {
492 std::string name = "Unknown";
493 if (!instance->name.empty()) {
494 name = instance->name;
495 }
496
497 RenderPipelineDefinition * def = nullptr;
498 if (instance->definitionKey != 0) {
499 def = &renderer->getPipelineManager()->definitionByKey(context, instance->definitionKey);
500 name += ", def=" + def->name;
501 }
502
503 ImGui::PushID(instance);
504 if (ImGui::TreeNode("Instance", "%d: %s", id++, name.c_str())) {
505
506 if (!instance->pipeline.updateResources.resources.empty()) {
507 if (ImGui::TreeNode("Update resources")) {
508 for (const auto & resource : instance->pipeline.updateResources.resources) {
509 showResource(context, renderer, &resource);
510 }
511 ImGui::TreePop();
512 }
513 }
514 if (!instance->pipeline.resources.resources.empty()) {
515 if (ImGui::TreeNode("Resources")) {
516 for (const auto & resource : instance->pipeline.resources.resources) {
517 showResource(context, renderer, &resource);
518 }
519 ImGui::TreePop();
520 }
521 }
522 if (!instance->pipeline.tasks.empty()) {
523 if (ImGui::TreeNode("Tasks")) {
524 for (const auto * task : instance->pipeline.tasks) {
525 showTask(context, renderer, task);
526 }
527 ImGui::TreePop();
528 }
529 }
530 ImGui::TreePop();
531 }
532 ImGui::PopID();
533 }
534
535 ImGui::TreePop();
536 }
537 }
538}
539
540void Cogs::Core::pipelineInspector(class Context * context, bool * show)
541{
542 if (!*show) return;
543
544 ImGui::SetNextWindowSize(ImVec2(600, 300), ImGuiCond_FirstUseEver);
545 ImGui::Begin("Pipeline", show, 0);
546
547 const char* tabs[2] = { "Pipeline Structure", "Settings" };
548
549 static int tab = 0;
550 ImGuiStyle & style = ImGui::GetStyle();
551 ImVec2 itemSpacing = style.ItemSpacing;
552 ImVec4 color = style.Colors[ImGuiCol_Button];
553 ImVec4 colorActive = style.Colors[ImGuiCol_ButtonActive];
554 ImVec4 colorHover = style.Colors[ImGuiCol_ButtonHovered];
555
556 style.ItemSpacing.x = 1;
557 style.ItemSpacing.y = 0;
558
559 for (int i = 0; i < static_cast<int>(sizeof(tabs) / sizeof(const char*)); i++) {
560 if (i != 0) ImGui::SameLine();
561
562 if (i == tab) {
563 style.Colors[ImGuiCol_Button] = colorActive;
564 style.Colors[ImGuiCol_ButtonActive] = colorActive;
565 style.Colors[ImGuiCol_ButtonHovered] = colorActive;
566 }
567 if (ImGui::Button(tabs[i])) tab = i;
568 if (i == tab) {
569 style.Colors[ImGuiCol_Button] = color;
570 style.Colors[ImGuiCol_ButtonActive] = colorActive;
571 style.Colors[ImGuiCol_ButtonHovered] = colorHover;
572 }
573 }
574
575 style.ItemSpacing = itemSpacing;
576 ImGui::Separator();
577
578 switch (tab)
579 {
580 case 0:
581 {
582 Cogs::Core::Renderer* renderer = dynamic_cast<Cogs::Core::Renderer*>(context->renderer);
583 showTasks(context, renderer);
584 break;
585 }
586 case 1: break;
587 default:
588 break;
589 }
590
591 ImGui::End();
592}
593
594void Cogs::Core::permutationInspector(class Context * context, bool * show)
595{
596 if (!*show) return;
597
598 ImGui::Begin("Permutations", show);
599
600 for(size_t i=0, n= context->renderer->getEnginePermutations().size(); i<n; i++) {
601 EnginePermutation* permutation = context->renderer->getEnginePermutations().get(i);
602
603 ImGui::PushID(permutation);
604 if (ImGui::TreeNode(permutation->getName().c_str())) {
605 auto & properties = permutation->constantBuffers.variables;
606 if (!properties.empty()) {
607 if (ImGui::TreeNode("Properties")) {
608 for (auto & prop : properties) {
609 if (prop.type == MaterialDataType::Float) {
610 float value = 0;
611 if (ImGui::SliderFloat(prop.name.c_str(), &value, 0.0f, 2.0f)) {
612 permutation->constantBuffers.buffers[prop.buffer].setValue(prop.descriptor.offset, value);
613 }
614 } else if (prop.type == MaterialDataType::Float4) {
615 glm::vec4 value(0);
616 if (ImGui::DragFloat4(prop.name.c_str(), glm::value_ptr(value), 0.01f, 0.0f, 2.0f)) {
617 permutation->constantBuffers.buffers[prop.buffer].setValue(prop.descriptor.offset, value);
618 }
619 }
620 }
621
622 ImGui::TreePop();
623 }
624 }
625
626 ImGui::TreePop();
627 }
628 ImGui::PopID();
629 }
630
631
632 ImGui::End();
633}
A Context instance contains all the services, systems and runtime components needed to use Cogs.
Definition: Context.h:83
class IRenderer * renderer
Renderer.
Definition: Context.h:228
virtual EnginePermutations & getEnginePermutations()=0
Get the reference to the EnginePermutations structure.
Core renderer system.
Definition: Renderer.h:28
EnginePermutations & getEnginePermutations() override
Get the reference to the EnginePermutations structure.
Definition: Renderer.h:76
Contains the Engine, Renderer, resource managers and other systems needed to run Cogs....
Contains reflection support.
Definition: Component.h:11
std::vector< MaterialPropertyBuffer > buffers
Constant buffer instances.
std::vector< MaterialProperty > variables
Individual variables from all buffer instances.
Material * material
Material resource this MaterialInstance is created from.
StateChangeFlags stateChanges
Encodes what state changed from previous item, updated by FilterListTask.
Definition: RenderList.h:178
handle_type handle
Internal resource handle.
Definition: Common.h:74