3#include "InspectorGuiHelper.h"
6#include "Services/Variables.h"
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"
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"
22#include "Resources/TextureManager.h"
24#include "Foundation/Reflection/TypeDatabase.h"
32 void binaryNumber(uint32_t number)
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);
71 std::string header =
"Item " + std::to_string(ix);
72 if ((item.
stateChanges & StateChangeFlags::ChangeAll) == StateChangeFlags::ChangeAll) {
75 if ((item.
stateChanges & StateChangeFlags::ChangeTransform) != 0) {
78 if ((item.
stateChanges & StateChangeFlags::ChangeMesh) != 0) {
81 if ((item.
stateChanges & StateChangeFlags::ChangeMaterialInstance) != 0) {
84 if ((item.
stateChanges & StateChangeFlags::ChangeMaterialVariant) != 0) {
87 if ((item.
stateChanges & StateChangeFlags::ChangeRasterizerState) != 0) {
90 if ((item.
stateChanges & StateChangeFlags::ChangeBlendState) != 0) {
93 if ((item.
stateChanges & StateChangeFlags::ChangeDepthStencilState) != 0) {
96 if ((item.
stateChanges & StateChangeFlags::ChangeLayer) != 0) {
99 if ((item.
stateChanges & StateChangeFlags::ChangeViewport) != 0) {
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)");
112 if (renderMaterialInstance->loadedBindings.empty()) {
113 header.append(
"no bindings");
116 for (
auto & binding : renderMaterialInstance->loadedBindings) {
117 if (binding.enginePermutation) {
118 header.append(binding.enginePermutation->getName());
121 header.append(
"<no engine perm>");
124 if (binding.binding) {
125 if (binding.binding->renderEffect) {
126 header.append(
"has renderEffect");
129 header.append(
"<no renderEffect>");
133 header.append(
"<no binding>");
140 ImGui::Text(
"%s", header.c_str());
145 if (batch.empty())
return;
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);
154 void showRenderList(
Context* context,
Renderer* renderer,
const RenderItems& items,
const std::string& name)
156 if (items.empty())
return;
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);
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());
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);
180 if (aspectRatio < 1) {
181 size.x *= aspectRatio;
183 size.y /= aspectRatio;
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);
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);
197 if (renderTarget->depth) {
198 ImGui::Text(
" Depth");
199 ImGui::Image(ImTextureID(renderTarget->depth->textureHandle.
handle), size);
207 constexpr char const * fmtTitle[] = {
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]",
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)
221 case RenderResourceType::RenderTarget:
223 showRenderTarget(context, renderer, resource->renderTarget);
226 case RenderResourceType::RenderList:
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");
239 case RenderResourceType::RenderTexture:
241 showRenderTexture(context, renderer, resource->renderTexure);
244 case RenderResourceType::RenderBuffer:
245 case RenderResourceType::TaskResource:
258 if (task ==
nullptr)
return;
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);
268 if (task ==
nullptr)
return;
274 if (task ==
nullptr)
return;
280 if (task ==
nullptr)
return;
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 " :
"");
293 ImGui::Text(
"Wireframe");
294 ImGui::SameLine(250.f);
295 ImGui::Text(
"%s", task->wireframe ?
"yes" :
"no");
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 " :
"");
305 ImGui::Text(
"Permutation");
306 ImGui::SameLine(250.f);
313 if (task ==
nullptr)
return;
316 ImGui::TextUnformatted(
"Object buffer mode:");
318 switch (task->objectBufferMode) {
319 case RenderListTask::ObjectBufferMode::Single:
320 ImGui::TextUnformatted(
"Single");
322 case RenderListTask::ObjectBufferMode::Batched:
323 ImGui::TextUnformatted(
"Batched");
325 case RenderListTask::ObjectBufferMode::List:
326 ImGui::TextUnformatted(
"List");
331 ImGui::TextUnformatted(
"Permutation index:");
333 ImGui::Text(
"%s (%zu)", renderer->
getEnginePermutations().get(task->permutationIndex)->getName().c_str(), task->permutationIndex);
336 ImGui::TextUnformatted(
"Bucket mask:");
338 binaryNumber(uint32_t(task->bucketMask));
341 ImGui::TextUnformatted(
"State change mask:");
343 binaryNumber(uint32_t(task->stateChangeMask));
346 ImGui::TextUnformatted(
"Lighting layers:");
348 binaryNumber(uint32_t(task->lightingMask));
351 ImGui::TextUnformatted(
"Blend mode:");
353 ImGui::Text(
"%u", uint32_t(task->blendMode));
356 ImGui::TextUnformatted(
"Depth mode:");
358 ImGui::Text(
"%u", uint32_t(task->depthMode));
361 ImGui::TextUnformatted(
"Depth func:");
363 ImGui::Text(
"%u", uint32_t(task->depthFunc));
366 ImGui::TextUnformatted(
"Clear color:");
368 ImGui::TextUnformatted(task->colorClear ?
"yes" :
"no");
371 ImGui::TextUnformatted(
"Clear depth:");
373 ImGui::TextUnformatted(task->depthClear ?
"yes" :
"no");
376 ImGui::TextUnformatted(
"Depth write:");
378 ImGui::TextUnformatted(task->depthWrite ?
"yes" :
"no");
381 ImGui::TextUnformatted(
"Discard color:");
383 ImGui::TextUnformatted(task->discardColor ?
"yes" :
"no");
386 ImGui::TextUnformatted(
"Discard depth:");
388 ImGui::TextUnformatted(task->discardDepth ?
"yes" :
"no");
391 ImGui::TextUnformatted(
"Default viewport size:");
393 ImGui::Text(
"[%d x %d]", task->defaultViewportSize.x, task->defaultViewportSize.y);
396 ImGui::TextUnformatted(
"Viewport from target:");
398 ImGui::TextUnformatted(task->viewportFromTarget ?
"yes" :
"no");
401 ImGui::TextUnformatted(
"Temporal offsets:");
403 ImGui::TextUnformatted(task->temporalOffsets ?
"yes" :
"no");
410 std::string
id = std::to_string(
reinterpret_cast<size_t>(task));
411 std::string name = task->name.empty() ?
"<unnamed>" : task->name;
413 if (task->flags & RenderTaskFlags::Persistent) {
414 name +=
" [persistent]";
417 if (ImGui::TreeNode(
id.c_str(),
"%s", name.c_str())) {
419 if (!task->input.resources.empty()) {
420 if (ImGui::TreeNode(
"Inputs")) {
421 for (
const auto & resource : task->input.resources) {
422 showResource(context, renderer, &resource);
428 if (!task->output.resources.empty()) {
429 if (ImGui::TreeNode(
"Outputs")) {
430 for (
const auto & resource : task->output.resources) {
431 showResource(context, renderer, &resource);
437 if (!task->dependencies.empty()) {
438 if (ImGui::TreeNode(
"Dependencies")) {
439 for (
auto & dependency : task->dependencies) {
440 ImGui::Text(
"%s", dependency.c_str());
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());
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));
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());
475 if (ImGui::TreeNode(
"Global resources")) {
477 r.type = RenderResourceType::RenderList;
479 r.renderList =
const_cast<RenderList*
>(renderer->getPipelineManager()->getMainRenderList());
480 showResource(context, renderer, &r);
484 if (ImGui::TreeNode(
"Global tasks")) {
485 showTask(context, renderer, renderer->getPipelineManager()->getGenerateListTask());
489 if (ImGui::TreeNode(
"Pipeline instance sequence")) {
491 for (
const auto instance : instances) {
492 std::string name =
"Unknown";
493 if (!instance->name.empty()) {
494 name = instance->name;
498 if (instance->definitionKey != 0) {
499 def = &renderer->getPipelineManager()->definitionByKey(context, instance->definitionKey);
500 name +=
", def=" + def->name;
503 ImGui::PushID(instance);
504 if (ImGui::TreeNode(
"Instance",
"%d: %s",
id++, name.c_str())) {
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);
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);
522 if (!instance->pipeline.tasks.empty()) {
523 if (ImGui::TreeNode(
"Tasks")) {
524 for (
const auto * task : instance->pipeline.tasks) {
525 showTask(context, renderer, task);
540void Cogs::Core::pipelineInspector(
class Context * context,
bool * show)
544 ImGui::SetNextWindowSize(ImVec2(600, 300), ImGuiCond_FirstUseEver);
545 ImGui::Begin(
"Pipeline", show, 0);
547 const char* tabs[2] = {
"Pipeline Structure",
"Settings" };
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];
556 style.ItemSpacing.x = 1;
557 style.ItemSpacing.y = 0;
559 for (
int i = 0; i < static_cast<int>(
sizeof(tabs) /
sizeof(
const char*)); i++) {
560 if (i != 0) ImGui::SameLine();
563 style.Colors[ImGuiCol_Button] = colorActive;
564 style.Colors[ImGuiCol_ButtonActive] = colorActive;
565 style.Colors[ImGuiCol_ButtonHovered] = colorActive;
567 if (ImGui::Button(tabs[i])) tab = i;
569 style.Colors[ImGuiCol_Button] = color;
570 style.Colors[ImGuiCol_ButtonActive] = colorActive;
571 style.Colors[ImGuiCol_ButtonHovered] = colorHover;
575 style.ItemSpacing = itemSpacing;
583 showTasks(context, renderer);
594void Cogs::Core::permutationInspector(
class Context * context,
bool * show)
598 ImGui::Begin(
"Permutations", show);
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) {
611 if (ImGui::SliderFloat(prop.name.c_str(), &value, 0.0f, 2.0f)) {
612 permutation->constantBuffers.
buffers[prop.buffer].setValue(prop.descriptor.offset, value);
614 }
else if (prop.type == MaterialDataType::Float4) {
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);
A Context instance contains all the services, systems and runtime components needed to use Cogs.
class IRenderer * renderer
Renderer.
virtual EnginePermutations & getEnginePermutations()=0
Get the reference to the EnginePermutations structure.
EnginePermutations & getEnginePermutations() override
Get the reference to the EnginePermutations structure.
Contains the Engine, Renderer, resource managers and other systems needed to run Cogs....
Contains reflection support.
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.
handle_type handle
Internal resource handle.