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::Annotation)], "Annotation bucket");
236 showRenderList(context, renderer, renderList->buckets[size_t(BucketType::Overlay)], "Overlay bucket");
237 showRenderList(context, renderer, renderList->buckets[size_t(BucketType::Custom)], "Custombucket");
238 break;
239 }
240 case RenderResourceType::RenderTexture:
241 {
242 showRenderTexture(context, renderer, resource->renderTexure);
243 break;
244 }
245 case RenderResourceType::RenderBuffer:
246 case RenderResourceType::TaskResource:
247 default:
248 break;
249 }
250
251 ImGui::TreePop();
252 }
253
254 ImGui::PopID();
255 }
256
257 void showTaskInner(Context* /*context*/, Renderer* /*renderer*/, const GenerateListTask* task)
258 {
259 if (task == nullptr) return;
260
261 ImGui::Text("list obj buffer %u of %u, size=%zukb",
262 task->listObjectBuffer.fill,
263 task->listObjectBuffer.cpuCapacity,
264 ((size_t(task->listObjectBuffer.stride) * task->listObjectBuffer.gpuCapacity) + 1023) / 1024);
265 }
266
267 void showTaskInner(Context* /*context*/, Renderer* /*renderer*/, const ProcessTask* task)
268 {
269 if (task == nullptr) return;
270
271 }
272
273 void showTaskInner(Context* /*context*/, Renderer* /*renderer*/, const PostProcessTask* task)
274 {
275 if (task == nullptr) return;
276
277 }
278
279 void showTaskInner(Context* /*context*/, Renderer* renderer, const FilterListTask* task)
280 {
281 if (task == nullptr) return;
282
283 ImGui::Text("BucketMask");
284 ImGui::SameLine(250.f);
285 ImGui::Text("%s%s%s%s%s%s%s%s",
286 hasBucket(task->bucketMask, BucketType::Backdrop) ? "BucketBackdrop " : "",
287 hasBucket(task->bucketMask, BucketType::SolidOrderedBack) ? "SolidOrderedBack " : "",
288 hasBucket(task->bucketMask, BucketType::Solid) ? "Solid " : "",
289 hasBucket(task->bucketMask, BucketType::SolidOrderedFront) ? "SolidOrderedFront " : "",
290 hasBucket(task->bucketMask, BucketType::Transparent) ? "Transparent " : "",
291 hasBucket(task->bucketMask, BucketType::Annotation) ? "Annotation " : "",
292 hasBucket(task->bucketMask, BucketType::Overlay) ? "Overlay " : "",
293 hasBucket(task->bucketMask, BucketType::Custom) ? "Custom " : "");
294
295 ImGui::Text("Wireframe");
296 ImGui::SameLine(250.f);
297 ImGui::Text("%s", task->wireframe ? "yes" : "no");
298
299 ImGui::Text("RenderMask");
300 ImGui::SameLine(250.f);
301 ImGui::Text("%s%s%s%s",
302 ((task->renderMask & RenderLayers::Default) != RenderLayers::None) ? "Default " : "",
303 ((task->renderMask & RenderLayers::Ocean) != RenderLayers::None) ? "Ocean " : "",
304 ((task->renderMask & RenderLayers::Annotations) != RenderLayers::None) ? "Annotations " : "",
305 ((task->renderMask & RenderLayers::Sky) != RenderLayers::None) ? "Sky " : "");
306
307 ImGui::Text("Permutation");
308 ImGui::SameLine(250.f);
309 ImGui::Text("%s", renderer->getEnginePermutations().get(task->permutation)->getName().c_str());
310
311 }
312
313 void showTaskInner(Context* /*context*/, Renderer* renderer, const RenderListTask* task)
314 {
315 if (task == nullptr) return;
316
317 ImGui::Columns(2);
318 ImGui::TextUnformatted("Object buffer mode:");
319 ImGui::NextColumn();
320 switch (task->objectBufferMode) {
321 case RenderListTask::ObjectBufferMode::Single:
322 ImGui::TextUnformatted("Single");
323 break;
324 case RenderListTask::ObjectBufferMode::Batched:
325 ImGui::TextUnformatted("Batched");
326 break;
327 case RenderListTask::ObjectBufferMode::List:
328 ImGui::TextUnformatted("List");
329 break;
330 }
331 ImGui::NextColumn();
332
333 ImGui::TextUnformatted("Permutation index:");
334 ImGui::NextColumn();
335 ImGui::Text("%s (%zu)", renderer->getEnginePermutations().get(task->permutationIndex)->getName().c_str(), task->permutationIndex);
336 ImGui::NextColumn();
337
338 ImGui::TextUnformatted("Bucket mask:");
339 ImGui::NextColumn();
340 binaryNumber(uint32_t(task->bucketMask));
341 ImGui::NextColumn();
342
343 ImGui::TextUnformatted("State change mask:");
344 ImGui::NextColumn();
345 binaryNumber(uint32_t(task->stateChangeMask));
346 ImGui::NextColumn();
347
348 ImGui::TextUnformatted("Lighting layers:");
349 ImGui::NextColumn();
350 binaryNumber(uint32_t(task->lightingMask));
351 ImGui::NextColumn();
352
353 ImGui::TextUnformatted("Blend mode:");
354 ImGui::NextColumn();
355 ImGui::Text("%u", uint32_t(task->blendMode));
356 ImGui::NextColumn();
357
358 ImGui::TextUnformatted("Depth mode:");
359 ImGui::NextColumn();
360 ImGui::Text("%u", uint32_t(task->depthMode));
361 ImGui::NextColumn();
362
363 ImGui::TextUnformatted("Depth func:");
364 ImGui::NextColumn();
365 ImGui::Text("%u", uint32_t(task->depthFunc));
366 ImGui::NextColumn();
367
368 ImGui::TextUnformatted("Clear color:");
369 ImGui::NextColumn();
370 ImGui::TextUnformatted(task->colorClear ? "yes" : "no");
371 ImGui::NextColumn();
372
373 ImGui::TextUnformatted("Clear depth:");
374 ImGui::NextColumn();
375 ImGui::TextUnformatted(task->depthClear ? "yes" : "no");
376 ImGui::NextColumn();
377
378 ImGui::TextUnformatted("Depth write:");
379 ImGui::NextColumn();
380 ImGui::TextUnformatted(task->depthWrite ? "yes" : "no");
381 ImGui::NextColumn();
382
383 ImGui::TextUnformatted("Discard color:");
384 ImGui::NextColumn();
385 ImGui::TextUnformatted(task->discardColor ? "yes" : "no");
386 ImGui::NextColumn();
387
388 ImGui::TextUnformatted("Discard depth:");
389 ImGui::NextColumn();
390 ImGui::TextUnformatted(task->discardDepth ? "yes" : "no");
391 ImGui::NextColumn();
392
393 ImGui::TextUnformatted("Default viewport size:");
394 ImGui::NextColumn();
395 ImGui::Text("[%d x %d]", task->defaultViewportSize.x, task->defaultViewportSize.y);
396 ImGui::NextColumn();
397
398 ImGui::TextUnformatted("Viewport from target:");
399 ImGui::NextColumn();
400 ImGui::TextUnformatted(task->viewportFromTarget ? "yes" : "no");
401 ImGui::NextColumn();
402
403 ImGui::TextUnformatted("Temporal offsets:");
404 ImGui::NextColumn();
405 ImGui::TextUnformatted(task->temporalOffsets ? "yes" : "no");
406 ImGui::NextColumn();
407
408 }
409
410 void showTask(Context* context, Renderer* renderer, const RenderTask* task)
411 {
412 std::string id = std::to_string(reinterpret_cast<size_t>(task));
413 std::string name = task->name.empty() ? "<unnamed>" : task->name;
414
415 if (task->flags & RenderTaskFlags::Persistent) {
416 name += " [persistent]";
417 }
418
419 if (ImGui::TreeNode(id.c_str(), "%s", name.c_str())) {
420
421 if (!task->input.resources.empty()) {
422 if (ImGui::TreeNode("Inputs")) {
423 for (const auto & resource : task->input.resources) {
424 showResource(context, renderer, &resource);
425 }
426 ImGui::TreePop();
427 }
428 }
429
430 if (!task->output.resources.empty()) {
431 if (ImGui::TreeNode("Outputs")) {
432 for (const auto & resource : task->output.resources) {
433 showResource(context, renderer, &resource);
434 }
435 ImGui::TreePop();
436 }
437 }
438
439 if (!task->dependencies.empty()) {
440 if (ImGui::TreeNode("Dependencies")) {
441 for (auto & dependency : task->dependencies) {
442 ImGui::Text("%s", dependency.c_str());
443 }
444 ImGui::TreePop();
445 }
446 }
447
448 if (!task->options.empty()) {
449 if (ImGui::TreeNode("Options")) {
450 for (auto & option : task->options) {
451 ImGui::Text("%s=%s", option.first.c_str(), option.second.c_str());
452 }
453 ImGui::TreePop();
454 }
455 }
456
457 showTaskInner(context, renderer, dynamic_cast<const GenerateListTask*>(task));
458 showTaskInner(context, renderer, dynamic_cast<const ProcessTask*>(task));
459 showTaskInner(context, renderer, dynamic_cast<const PostProcessTask*>(task));
460 showTaskInner(context, renderer, dynamic_cast<const FilterListTask*>(task));
461 showTaskInner(context, renderer, dynamic_cast<const RenderListTask*>(task));
462
463 ImGui::TreePop();
464 }
465 }
466
467 void showTasks(Context* context, Renderer* renderer)
468 {
469 std::vector<const PipelineInstance *> instances;
470 instances.reserve(renderer->getPipelineManager()->getPipelineInstances().size());
471 for (auto & it : renderer->getPipelineManager()->getPipelineInstances()) {
472 instances.push_back(it.second.get());
473 }
474
475 std::sort(instances.begin(), instances.end(), [](const PipelineInstance * a, const PipelineInstance * b) { return a->priority < b->priority; });
476
477 if (ImGui::TreeNode("Global resources")) {
479 r.type = RenderResourceType::RenderList;
480 r.key = "";
481 r.renderList = const_cast<RenderList*>(renderer->getPipelineManager()->getMainRenderList());
482 showResource(context, renderer, &r);
483 ImGui::TreePop();
484 }
485
486 if (ImGui::TreeNode("Global tasks")) {
487 showTask(context, renderer, renderer->getPipelineManager()->getGenerateListTask());
488 ImGui::TreePop();
489 }
490
491 if (ImGui::TreeNode("Pipeline instance sequence")) {
492 uint32_t id = 0;
493 for (const auto instance : instances) {
494 std::string name = "Unknown";
495 if (!instance->name.empty()) {
496 name = instance->name;
497 }
498
499 RenderPipelineDefinition * def = nullptr;
500 if (instance->definitionKey != 0) {
501 def = &renderer->getPipelineManager()->definitionByKey(context, instance->definitionKey);
502 name += ", def=" + def->name;
503 }
504
505 ImGui::PushID(instance);
506 if (ImGui::TreeNode("Instance", "%d: %s", id++, name.c_str())) {
507
508 if (!instance->pipeline.updateResources.resources.empty()) {
509 if (ImGui::TreeNode("Update resources")) {
510 for (const auto & resource : instance->pipeline.updateResources.resources) {
511 showResource(context, renderer, &resource);
512 }
513 ImGui::TreePop();
514 }
515 }
516 if (!instance->pipeline.resources.resources.empty()) {
517 if (ImGui::TreeNode("Resources")) {
518 for (const auto & resource : instance->pipeline.resources.resources) {
519 showResource(context, renderer, &resource);
520 }
521 ImGui::TreePop();
522 }
523 }
524 if (!instance->pipeline.tasks.empty()) {
525 if (ImGui::TreeNode("Tasks")) {
526 for (const auto * task : instance->pipeline.tasks) {
527 showTask(context, renderer, task);
528 }
529 ImGui::TreePop();
530 }
531 }
532 ImGui::TreePop();
533 }
534 ImGui::PopID();
535 }
536
537 ImGui::TreePop();
538 }
539 }
540}
541
542void Cogs::Core::pipelineInspector(class Context * context, bool * show)
543{
544 if (!*show) return;
545
546 ImGui::SetNextWindowSize(ImVec2(600, 300), ImGuiCond_FirstUseEver);
547 ImGui::Begin("Pipeline", show, 0);
548
549 const char* tabs[2] = { "Pipeline Structure", "Settings" };
550
551 static int tab = 0;
552 ImGuiStyle & style = ImGui::GetStyle();
553 ImVec2 itemSpacing = style.ItemSpacing;
554 ImVec4 color = style.Colors[ImGuiCol_Button];
555 ImVec4 colorActive = style.Colors[ImGuiCol_ButtonActive];
556 ImVec4 colorHover = style.Colors[ImGuiCol_ButtonHovered];
557
558 style.ItemSpacing.x = 1;
559 style.ItemSpacing.y = 0;
560
561 for (int i = 0; i < static_cast<int>(sizeof(tabs) / sizeof(const char*)); i++) {
562 if (i != 0) ImGui::SameLine();
563
564 if (i == tab) {
565 style.Colors[ImGuiCol_Button] = colorActive;
566 style.Colors[ImGuiCol_ButtonActive] = colorActive;
567 style.Colors[ImGuiCol_ButtonHovered] = colorActive;
568 }
569 if (ImGui::Button(tabs[i])) tab = i;
570 if (i == tab) {
571 style.Colors[ImGuiCol_Button] = color;
572 style.Colors[ImGuiCol_ButtonActive] = colorActive;
573 style.Colors[ImGuiCol_ButtonHovered] = colorHover;
574 }
575 }
576
577 style.ItemSpacing = itemSpacing;
578 ImGui::Separator();
579
580 switch (tab)
581 {
582 case 0:
583 {
584 Cogs::Core::Renderer* renderer = dynamic_cast<Cogs::Core::Renderer*>(context->renderer);
585 showTasks(context, renderer);
586 break;
587 }
588 case 1: break;
589 default:
590 break;
591 }
592
593 ImGui::End();
594}
595
596void Cogs::Core::permutationInspector(class Context * context, bool * show)
597{
598 if (!*show) return;
599
600 ImGui::Begin("Permutations", show);
601
602 for(size_t i=0, n= context->renderer->getEnginePermutations().size(); i<n; i++) {
603 EnginePermutation* permutation = context->renderer->getEnginePermutations().get(i);
604
605 ImGui::PushID(permutation);
606 if (ImGui::TreeNode(permutation->getName().c_str())) {
607 auto & properties = permutation->constantBuffers.variables;
608 if (!properties.empty()) {
609 if (ImGui::TreeNode("Properties")) {
610 for (auto & prop : properties) {
611 if (prop.type == MaterialDataType::Float) {
612 float value = 0;
613 if (ImGui::SliderFloat(prop.name.c_str(), &value, 0.0f, 2.0f)) {
614 permutation->constantBuffers.buffers[prop.buffer].setValue(prop.descriptor.offset, value);
615 }
616 } else if (prop.type == MaterialDataType::Float4) {
617 glm::vec4 value(0);
618 if (ImGui::DragFloat4(prop.name.c_str(), glm::value_ptr(value), 0.01f, 0.0f, 2.0f)) {
619 permutation->constantBuffers.buffers[prop.buffer].setValue(prop.descriptor.offset, value);
620 }
621 }
622 }
623
624 ImGui::TreePop();
625 }
626 }
627
628 ImGui::TreePop();
629 }
630 ImGui::PopID();
631 }
632
633
634 ImGui::End();
635}
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:180
handle_type handle
Internal resource handle.
Definition: Common.h:75