21#include "../src/WorkflowHelpers.h"
22#include "DebugGUI/imgui.h"
23#include <DebugGUI/icons_font_awesome.h>
33#pragma GCC diagnostic push
34#pragma GCC diagnostic ignored "-Wpedantic"
35static inline ImVec2
operator+(
const ImVec2& lhs,
const ImVec2& rhs) {
return ImVec2(
lhs.x +
rhs.x,
lhs.y +
rhs.y); }
36static inline ImVec2
operator-(
const ImVec2& lhs,
const ImVec2& rhs) {
return ImVec2(
lhs.x -
rhs.x,
lhs.y -
rhs.y); }
37static inline ImVec2
operator*(
const ImVec2& lhs,
float rhs) {
return ImVec2(
lhs.x * rhs,
lhs.y * rhs); }
38static inline ImVec2 operator/(
const ImVec2& lhs,
float rhs) {
return ImVec2(
lhs.x / rhs,
lhs.y / rhs); }
51NodeColor decideColorForNode(
const DeviceInfo& info,
bool lightMode)
55 if (
info.active ==
false) {
57 .normal = ImVec4(0xb5 / 255.f, 0x26 / 255.f, 0x18 / 255.f, 1),
58 .hovered = ImVec4(0xc2 / 255.f, 0x2d / 255.f, 0x1d / 255.f, 1)};
60 switch (
info.streamingState) {
63 .normal = ImVec4(0x8c / 255.f, 0x6c / 255.f, 0x00 / 255.f, 1),
64 .hovered = ImVec4(0x9e / 255.f, 0x7a / 255.f, 0x00 / 255.f, 1),
65 .title = ImVec4(0x6e / 255.f, 0x54 / 255.f, 0x00 / 255.f, 1),
66 .title_hovered = ImVec4(0x5a / 255.f, 0x44 / 255.f, 0x00 / 255.f, 1)};
69 .normal = ImVec4(0x1a / 255.f, 0x80 / 255.f, 0x40 / 255.f, 1),
70 .hovered = ImVec4(0x22 / 255.f, 0x8b / 255.f, 0x47 / 255.f, 1),
71 .title = ImVec4(0x11 / 255.f, 0x60 / 255.f, 0x2e / 255.f, 1),
72 .title_hovered = ImVec4(0x0a / 255.f, 0x4d / 255.f, 0x23 / 255.f, 1)};
76 .normal = ImVec4(0x3a / 255.f, 0x3a / 255.f, 0x3c / 255.f, 1),
77 .hovered = ImVec4(0x48 / 255.f, 0x48 / 255.f, 0x4a / 255.f, 1),
78 .title = ImVec4(0x2c / 255.f, 0x2c / 255.f, 0x2e / 255.f, 1),
79 .title_hovered = ImVec4(0x1c / 255.f, 0x1c / 255.f, 0x1e / 255.f, 1)};
82 if (
info.active ==
false) {
87 switch (
info.streamingState) {
111const static ImColor INPUT_SLOT_COLOR = {150, 150, 150, 150};
112const static ImColor OUTPUT_SLOT_COLOR = {150, 150, 150, 150};
113const static ImColor NODE_LABEL_BACKGROUND_COLOR = {45, 45, 45, 255};
114const static ImColor NODE_LABEL_TEXT_COLOR = {244, 244, 244, 255};
117const static ImColor ARROW_BACKGROUND_COLOR = {100, 100, 0};
118const static ImColor ARROW_HALFGROUND_COLOR = {170, 170, 70};
119const static ImColor ARROW_COLOR = {200, 200, 100};
120const static ImColor ARROW_SELECTED_COLOR = {200, 0, 100};
121const static ImU32 GRID_COLOR = ImColor(150, 150, 150, 80);
122const static ImColor NODE_BORDER_COLOR = {100, 100, 100};
123const static ImColor LEGEND_COLOR = {100, 100, 100};
126const static float GRID_SZ = 64.0f;
127const static float ARROW_BACKGROUND_THICKNESS = 1.f;
128const static float ARROW_HALFGROUND_THICKNESS = 2.f;
129const static float ARROW_THICKNESS = 3.f;
130const static float NODE_BORDER_THICKNESS = 4.f;
131const static ImVec4 LEGEND_BACKGROUND_COLOR = {0.125, 0.180, 0.196, 1};
133const static ImVec4 SLOT_EMPTY_COLOR = {0.275, 0.275, 0.275, 1.};
139const float NODE_SLOT_RADIUS = 4.0f;
140const ImVec2 NODE_WINDOW_PADDING(8.0f, 8.0f);
143float clampZoom(
float zoom)
145 return std::clamp(zoom, 0.15f, 2.50f);
148ImVec2 graphToScreen(ImVec2 graphPos, ImVec2 canvasOrigin, ImVec2 scrolling,
float zoom)
150 return canvasOrigin + (graphPos - scrolling) * zoom;
153void displayGrid(
bool show_grid, ImVec2 scrolling,
float zoom, ImDrawList* draw_list)
155 if (show_grid ==
false) {
158 ImVec2 win_pos = ImGui::GetCursorScreenPos();
159 ImVec2 canvas_sz = ImGui::GetWindowSize();
160 float gridSize = GRID_SZ * zoom;
161 for (
float x = fmodf(-scrolling.x * zoom, gridSize);
x < canvas_sz.x;
x += gridSize) {
162 draw_list->AddLine(ImVec2(
x, 0.0f) + win_pos, ImVec2(
x, canvas_sz.y) + win_pos, GRID_COLOR);
164 for (
float y = fmodf(-scrolling.y * zoom, gridSize);
y < canvas_sz.y;
y += gridSize) {
165 draw_list->AddLine(ImVec2(0.0f,
y) + win_pos, ImVec2(canvas_sz.x,
y) + win_pos, GRID_COLOR);
169void displayLegend(
bool show_legend, ImVec2
offset, ImDrawList* draw_list)
171 if (show_legend ==
false) {
178 static auto legend = {
179 LegendItem{
" Slot empty", SLOT_EMPTY_COLOR},
180 LegendItem{
" Slot pending", SLOT_PENDING_COLOR},
181 LegendItem{
" Slot dispatched", SLOT_DISPATCHED_COLOR},
182 LegendItem{
" Slot done", SLOT_DONE_COLOR},
184 ImGui::PushStyleColor(ImGuiCol_WindowBg, LEGEND_BACKGROUND_COLOR);
185 ImGui::PushStyleColor(ImGuiCol_TitleBg, LEGEND_BACKGROUND_COLOR);
186 ImGui::PushStyleColor(ImGuiCol_ResizeGrip, 0);
188 ImGui::Begin(
"Legend");
189 ImGui::Dummy(ImVec2(0.0f, 10.0f));
191 ImVec2 vMin = ImGui::GetWindowPos() + ImGui::GetCursorPos() + ImVec2(9, 0);
192 ImVec2 vMax = vMin + ImGui::CalcTextSize(
" ");
193 ImGui::PushStyleColor(ImGuiCol_ChildBg,
color);
194 ImGui::GetWindowDrawList()->AddRectFilled(vMin, vMax, ImColor(
color));
195 ImGui::GetWindowDrawList()->AddRect(vMin, vMax, GRID_COLOR);
196 ImGui::Text(
"%s",
label.data());
197 ImGui::PopStyleColor();
200 ImGui::PopStyleColor(3);
203#define MAX_GROUP_NAME_SIZE 128
210 Group(
int id,
char const*
n,
size_t mid)
219constexpr int MAX_SLOTS = 512;
220constexpr int MAX_INPUT_VALUE_SIZE = 24;
222struct OldestPossibleInput {
224 char buffer[MAX_INPUT_VALUE_SIZE] =
"unknown";
225 float textSize = ImGui::CalcTextSize(
"unknown").x;
228struct OldestPossibleOutput {
230 char buffer[MAX_INPUT_VALUE_SIZE] =
"unknown";
231 float textSize = ImGui::CalcTextSize(
"unknown").x;
242 int InputsCount, OutputsCount;
243 OldestPossibleInput oldestPossibleInput[MAX_SLOTS];
244 OldestPossibleOutput oldestPossibleOutput[MAX_SLOTS];
246 Node(
int id,
int groupID,
char const*
name,
float value,
const ImVec4&
color,
int inputs_count,
int outputs_count)
250 strncpy(Name,
name, 63);
252 Size = ImVec2(150.f, 128.f);
255 InputsCount = inputs_count;
256 OutputsCount = outputs_count;
263 static ImVec2 GetInputSlotPos(ImVector<Node>
const& infos, ImVector<NodePos>
const& positions,
int nodeId,
int slot_no)
265 ImVec2
const&
pos = positions[nodeId].pos;
266 ImVec2
const&
size = infos[nodeId].Size;
267 float inputsCount = infos[nodeId].InputsCount;
268 return ImVec2(
pos.x,
pos.y +
size.y * ((
float)slot_no + 1) / (inputsCount + 1));
270 static ImVec2 GetOutputSlotPos(ImVector<Node>
const& infos, ImVector<NodePos>
const& positions,
int nodeId,
int slot_no)
272 ImVec2
const&
pos = positions[nodeId].pos;
273 ImVec2
const&
size = infos[nodeId].Size;
274 float outputsCount = infos[nodeId].OutputsCount;
275 return ImVec2(
pos.x +
size.x,
pos.y +
size.y * ((
float)slot_no + 1) / (outputsCount + 1));
281 int InputIdx, InputSlot, OutputIdx, OutputSlot;
283 NodeLink(
int input_idx,
int input_slot,
int output_idx,
int output_slot)
285 InputIdx = input_idx;
286 InputSlot = input_slot;
287 OutputIdx = output_idx;
288 OutputSlot = output_slot;
292std::string xmlEscape(
const char* text)
295 for (
char c :
std::string_view{text}) {
320std::string dotEscape(
const char* text)
323 for (
char c :
std::string_view{text}) {
324 if (
c ==
'"' ||
c ==
'\\') {
332std::string colorToHex(ImVec4
color)
335 return std::clamp(
static_cast<int>(std::round(
value * 255.f)), 0, 255);
337 std::ostringstream out;
338 out <<
"#" << std::hex << std::setfill(
'0') << std::setw(2) <<
component(
color.x)
344bool topologyBounds(ImVector<Node>
const&
nodes, ImVector<NodePos>
const& positions, ImVec2& minPos, ImVec2& maxPos)
346 if (
nodes.Size == 0 || positions.Size == 0) {
349 minPos = positions[0].pos;
350 maxPos = positions[0].pos +
nodes[0].Size;
351 for (
int i = 1;
i <
nodes.Size; ++
i) {
352 minPos.x = std::min(minPos.x, positions[
i].pos.x);
353 minPos.y = std::min(minPos.y, positions[
i].pos.y);
354 maxPos.x = std::max(maxPos.x, positions[
i].pos.x +
nodes[
i].Size.x);
355 maxPos.y = std::max(maxPos.y, positions[
i].pos.y +
nodes[
i].Size.y);
360bool exportTopologySVG(
const char*
filename,
361 ImVector<Node>
const&
nodes,
362 ImVector<NodePos>
const& positions,
363 ImVector<NodeLink>
const& links,
364 std::vector<DeviceInfo>
const& infos,
369 if (!topologyBounds(
nodes, positions, minPos, maxPos)) {
372 constexpr float MARGIN = 80.f;
373 auto toSVG = [minPos](ImVec2
p) {
374 return p - minPos + ImVec2(80.f, 80.f);
376 ImVec2 canvasSize = maxPos - minPos + ImVec2(2.f * MARGIN, 2.f * MARGIN);
379 if (!out.is_open()) {
382 out << std::fixed << std::setprecision(2);
383 out << R
"(<?xml version="1.0" encoding="UTF-8"?>)" << "\n";
384 out << R
"(<svg xmlns="http://www.w3.org/2000/svg" width=")" << canvasSize.x << "\" height=\"" << canvasSize.y
385 <<
"\" viewBox=\"0 0 " << canvasSize.x <<
" " << canvasSize.y <<
"\">\n";
387 out <<
" <marker id=\"arrow\" viewBox=\"0 0 10 10\" refX=\"9\" refY=\"5\" markerWidth=\"6\" markerHeight=\"6\" orient=\"auto-start-reverse\">\n";
388 out <<
" <path d=\"M 0 0 L 10 5 L 0 10 z\" fill=\"#c8c864\"/>\n";
389 out <<
" </marker>\n";
391 out << R
"( <rect width="100%" height="100%" fill=")" << (lightMode ? "#fafafc" :
"#2c2c2e") <<
"\"/>\n";
392 out <<
" <g id=\"links\" fill=\"none\" stroke=\"#c8c864\" stroke-width=\"3\" marker-end=\"url(#arrow)\">\n";
393 for (
int i = 0;
i <
links.Size; ++
i) {
395 ImVec2
p1 = toSVG(NodePos::GetOutputSlotPos(
nodes, positions,
link.InputIdx,
link.InputSlot));
396 ImVec2
p2 = toSVG(NodePos::GetInputSlotPos(
nodes, positions,
link.OutputIdx,
link.OutputSlot) + ImVec2(-3 * NODE_SLOT_RADIUS, 0));
397 out <<
" <path id=\"edge-" <<
i <<
"\" d=\"M " <<
p1.x <<
" " <<
p1.y
398 <<
" C " <<
p1.x + 50.f <<
" " <<
p1.y <<
", " <<
p2.x - 50.f <<
" " <<
p2.y
399 <<
", " <<
p2.x <<
" " <<
p2.y <<
"\"/>\n";
402 out <<
" <g id=\"nodes\" font-family=\"sans-serif\" font-size=\"13\" fill=\"#f4f4f4\">\n";
403 for (
int i = 0;
i <
nodes.Size; ++
i) {
405 if (
i >= infos.size()) {
408 auto const&
info = infos[
i];
409 auto colors = decideColorForNode(info, lightMode);
410 auto titleColor = colors.title.w == 0.f ? colors.normal : colors.title;
411 ImVec2
p = toSVG(positions[
i].
pos);
412 out <<
" <g id=\"node-" <<
i <<
"\" data-label=\"" << xmlEscape(
node.Name) <<
"\">\n";
413 out <<
" <rect x=\"" <<
p.x + 3.f <<
"\" y=\"" <<
p.y + 3.f <<
"\" width=\"" <<
node.Size.x
414 <<
"\" height=\"" <<
node.Size.y <<
"\" rx=\"4\" fill=\"#000000\" opacity=\"0.28\"/>\n";
415 out <<
" <rect x=\"" <<
p.x <<
"\" y=\"" <<
p.y <<
"\" width=\"" <<
node.Size.x
416 <<
"\" height=\"" <<
node.Size.y << R
"(" rx="4" fill=")" << colorToHex(colors.normal)
417 << "\" stroke=\"#646464\" stroke-width=\"4\"/>\n";
418 out <<
" <rect x=\"" <<
p.x <<
"\" y=\"" <<
p.y <<
"\" width=\"" <<
node.Size.x
419 << R
"(" height="24" rx="4" fill=")" << colorToHex(titleColor) << "\"/>\n";
420 out <<
" <text x=\"" <<
p.x + NODE_WINDOW_PADDING.x <<
"\" y=\"" <<
p.y + 17.f <<
"\">"
421 << xmlEscape(
node.Name) <<
"</text>\n";
422 for (
int slot = 0; slot <
node.InputsCount; ++slot) {
423 ImVec2 slotPos = toSVG(NodePos::GetInputSlotPos(
nodes, positions,
i, slot));
424 out <<
" <circle cx=\"" << slotPos.x <<
"\" cy=\"" << slotPos.y <<
"\" r=\"" << NODE_SLOT_RADIUS <<
"\" fill=\"#969696\" opacity=\"0.6\"/>\n";
426 for (
int slot = 0; slot <
node.OutputsCount; ++slot) {
427 ImVec2 slotPos = toSVG(NodePos::GetOutputSlotPos(
nodes, positions,
i, slot));
428 out <<
" <circle cx=\"" << slotPos.x <<
"\" cy=\"" << slotPos.y <<
"\" r=\"" << NODE_SLOT_RADIUS <<
"\" fill=\"#969696\" opacity=\"0.6\"/>\n";
437bool exportTopologyDOT(
const char*
filename,
438 ImVector<Node>
const&
nodes,
439 ImVector<NodePos>
const& positions,
440 ImVector<NodeLink>
const& links,
441 std::vector<DeviceInfo>
const& infos,
445 if (!out.is_open()) {
448 out <<
"digraph dpl_topology {\n";
449 out <<
" graph [rankdir=LR, splines=curved, outputorder=edgesfirst];\n";
450 out <<
" node [shape=box, style=\"rounded,filled\", fontname=\"Helvetica\", fontsize=10];\n";
451 out <<
" edge [color=\"#c8c864\"];\n";
452 for (
int i = 0;
i <
nodes.Size; ++
i) {
453 if (
i >= infos.size()) {
456 auto colors = decideColorForNode(infos[
i], lightMode);
457 out <<
" n" <<
i <<
" [label=\"" << dotEscape(
nodes[
i].Name)
458 <<
"\", fillcolor=\"" << colorToHex(colors.normal)
459 << R
"(", fontcolor="white", pos=")" << positions[i].pos.x / 72.f << "," << -positions[
i].pos.y / 72.f <<
"!\"];\n";
461 for (
int i = 0;
i <
links.Size; ++
i) {
462 out <<
" n" <<
links[
i].InputIdx <<
" -> n" <<
links[
i].OutputIdx <<
";\n";
469template <
typename RECORD,
typename ITEM,
typename CONTEXT>
470struct MetricsPainter {
471 using NumRecordsCallback = std::function<size_t(
void)>;
472 using RecordCallback = std::function<RECORD(
size_t)>;
473 using NumItemsCallback = std::function<size_t(RECORD
const&)>;
474 using ItemCallback = std::function<ITEM
const&(RECORD
const&, size_t)>;
475 using ValueCallback = std::function<
int(ITEM
const&)>;
476 using ColorCallback = std::function<ImU32(
int value)>;
477 using ContextCallback = std::function<CONTEXT&()>;
478 using PaintCallback = std::function<
void(
int row,
int column,
int value, ImU32
color, CONTEXT
const& context)>;
480 static void draw(
const char*
name,
482 ImVec2
const& sizeHint,
483 CONTEXT
const& context,
484 NumRecordsCallback
const& getNumRecords,
485 RecordCallback
const& getRecord,
486 NumItemsCallback
const& getNumItems,
487 ItemCallback
const& getItem,
489 ColorCallback
const& getColor,
490 PaintCallback
const& describeCell)
492 for (
size_t ri = 0; ri < getNumRecords(); ++ri) {
493 auto record = getRecord(ri);
494 for (
size_t ii = 0; ii < getNumItems(record); ++ii) {
495 auto item = getItem(record, ii);
498 ImVec2
pos = ImGui::GetCursorScreenPos();
504 static NumRecordsCallback metric1D()
506 return []() ->
size_t {
return 1UL; };
509 static NumRecordsCallback metric2D(Metric2DViewIndex& viewIndex)
511 return [&viewIndex]() ->
size_t {
512 if (viewIndex.isComplete()) {
519 static NumItemsCallback items1D()
521 return [](RECORD
const& record) ->
size_t {
return 1UL; };
524 static NumItemsCallback items2D(Metric2DViewIndex
const& viewIndex)
526 return [&viewIndex](
int record) ->
int {
527 if (viewIndex.isComplete()) {
534 template <
typename T>
535 static ItemCallback latestMetric(DeviceMetricsInfo
const&
metrics,
536 Metric2DViewIndex
const& viewIndex)
538 return [&
metrics, &viewIndex](RECORD
const& record,
size_t i) -> ITEM
const& {
540 auto idx = record * viewIndex.h +
i;
541 assert(viewIndex.indexes.size() > idx);
542 MetricInfo
const& metricInfo =
metrics.metrics[viewIndex.indexes[
idx]];
543 auto&
data = DeviceMetricsInfoHelpers::get<T, metricStorageSize<T>()>(
metrics, metricInfo.storeIdx);
544 return data[(metricInfo.pos - 1) %
data.size()];
548 template <
typename T>
549 static RecordCallback simpleRecord()
551 return [](
size_t i) ->
int {
556 template <
typename T>
557 static ValueCallback simpleValue()
559 return [](ITEM
const& item) -> T {
return item; };
562 static ColorCallback colorPalette(std::vector<ImU32>
const& colors,
int minValue,
int maxValue)
564 return [colors, minValue, maxValue](
int const&
value) -> ImU32 {
565 if (
value < minValue) {
567 }
else if (
value > maxValue) {
568 return colors[colors.size() - 1];
570 int idx = (
value - minValue) * (colors.size() - 1) / (maxValue - minValue);
578struct MetricLabelsContext {
579 ImVector<Node>*
nodes;
581 ImVector<NodePos>* positions;
582 ImDrawList* draw_list;
589 std::vector<DeviceInfo>
const& infos,
590 std::vector<DeviceSpec>
const& specs,
591 std::vector<DataProcessingStates>
const& allStates,
592 std::vector<DataProcessorInfo>
const& metadata,
593 std::vector<DeviceControl>& controls,
594 std::vector<DeviceMetricsInfo>
const& metricsInfos)
596 ImGui::SetNextWindowPos(ImVec2(0, 0), 0);
597 if (
state.bottomPaneVisible) {
598 ImGui::SetNextWindowSize(ImVec2(ImGui::GetIO().DisplaySize.x, ImGui::GetIO().DisplaySize.y -
state.bottomPaneSize), 0);
600 ImGui::SetNextWindowSize(ImVec2(ImGui::GetIO().DisplaySize.x, ImGui::GetIO().DisplaySize.y), 0);
603 ImGui::Begin(
"Physical topology view",
nullptr, ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize);
605 static ImVector<Node>
nodes;
606 static ImVector<Group>
groups;
607 static ImVector<NodeLink>
links;
608 static ImVector<NodePos> positions;
610 static bool inited =
false;
611 static ImVec2 scrolling = ImVec2(0.0f, 0.0f);
612 static float zoom = 1.0f;
613 static bool show_grid =
true;
614 static bool show_legend =
true;
615 static int node_selected = -1;
616 static char exportStatus[256] =
"";
617 bool fitRequested =
false;
619 auto prepareChannelView = [&specs, &metricsInfos, &metadata](ImVector<Node>& nodeList, ImVector<Group>& groupList) {
624 std::map<std::string, LinkInfo> linkToIndex;
625 for (
int si = 0; si < specs.size(); ++si) {
627 for (
auto&&
output : specs[si].outputChannels) {
628 linkToIndex.insert(std::make_pair(
output.name, LinkInfo{si, oi}));
633 std::string workflow =
"Ungrouped";
635 for (
size_t mi = 0; mi < metadata.size(); ++mi) {
636 auto const& metadatum = metadata[mi];
637 if (metadatum.executable == workflow) {
640 workflow = metadatum.executable;
641 char* groupBasename = strrchr(workflow.data(),
'/');
642 char const* groupName = groupBasename ? groupBasename + 1 : workflow.data();
643 bool hasDuplicate =
false;
644 for (
size_t gi = 0; gi < groupList.Size; ++gi) {
650 if (hasDuplicate ==
false) {
651 groupList.push_back(Group(groupId++, groupName, mi));
655 for (
int si = 0; si < specs.size(); ++si) {
656 auto& spec = specs[si];
659 auto metadatum = std::find_if(metadata.begin(), metadata.end(),
660 [&
name = spec.name](DataProcessorInfo
const& info) { return info.name == name; });
662 for (
size_t gi = 0; gi < groupList.Size; ++gi) {
663 if (metadatum == metadata.end()) {
666 const char* groupName = strrchr(metadatum->executable.data(),
'/');
667 if (strncmp(groupList[gi].
name, groupName ? groupName + 1 : metadatum->executable.
data(), 127) == 0) {
672 nodeList.push_back(
Node(si, groupId, spec.id.c_str(), 0.5f,
673 ImColor(255, 100, 100),
674 spec.inputChannels.size(),
675 spec.outputChannels.size()));
677 for (
auto& input : spec.inputChannels) {
678 auto const& outName = input.name;
679 auto const& out = linkToIndex.find(input.name);
680 if (out == linkToIndex.end()) {
681 LOG(error) <<
"Could not find suitable node for " << outName;
684 links.push_back(NodeLink{out->second.specId, out->second.outputId, si, ii});
691 std::vector<TopoIndexInfo> sortedNodes = {{0, 0}};
699 for (
auto di = 0;
di < specs.size(); ++
di) {
700 auto fn = std::find_if(sortedNodes.begin(), sortedNodes.end(), [
di](TopoIndexInfo
const& info) {
701 return di == info.index;
703 if (fn == sortedNodes.end()) {
704 sortedNodes.push_back({(
int)
di, 0});
707 assert(specs.size() == sortedNodes.size());
709 std::sort(sortedNodes.begin(), sortedNodes.end());
711 std::vector<int> layerEntries(1024, 0);
712 std::vector<int> layerMax(1024, 0);
713 for (
auto&
node : sortedNodes) {
714 layerMax[
node.layer < 1023 ?
node.layer : 1023] += 1;
719 for (
int si = 0; si < specs.size(); ++si) {
720 auto&
node = sortedNodes[si];
721 assert(
node.index == si);
722 int xpos = 40 + 240 *
node.layer;
723 int ypos = 300 + (std::max(600, 60 * (
int)layerMax[
node.layer]) / (layerMax[
node.layer] + 1)) * (layerEntries[
node.layer] - layerMax[
node.layer] / 2);
724 positions.push_back(NodePos{ImVec2(xpos, ypos)});
725 layerEntries[
node.layer] += 1;
736 ImGui::Checkbox(
"Show grid", &show_grid);
738 ImGui::Checkbox(
"Show legend", &show_legend);
740 ImGui::Checkbox(
"Light mode", &
state.topologyLightMode);
742 if (ImGui::Button(
"Center")) {
743 scrolling = ImVec2(0., 0.);
747 if (ImGui::Button(
"-")) {
748 zoom = clampZoom(zoom / 1.15f);
751 if (ImGui::Button(
"+")) {
752 zoom = clampZoom(zoom * 1.15f);
755 if (ImGui::Button(
"Fit")) {
759 ImGui::Text(
"%.0f%%", zoom * 100.f);
761 if (ImGui::Button(
"100%")) {
765 if (ImGui::Button(
"Export SVG")) {
766 if (exportTopologySVG(
"dpl-topology.svg",
nodes, positions, links, infos,
state.topologyLightMode)) {
767 snprintf(exportStatus,
sizeof(exportStatus),
"Exported dpl-topology.svg");
769 snprintf(exportStatus,
sizeof(exportStatus),
"Could not export dpl-topology.svg");
773 if (ImGui::Button(
"Export DOT")) {
774 if (exportTopologyDOT(
"dpl-topology.dot",
nodes, positions, links, infos,
state.topologyLightMode)) {
775 snprintf(exportStatus,
sizeof(exportStatus),
"Exported dpl-topology.dot");
777 snprintf(exportStatus,
sizeof(exportStatus),
"Could not export dpl-topology.dot");
780 if (exportStatus[0] !=
'\0') {
782 ImGui::TextUnformatted(exportStatus);
785 if (
state.leftPaneVisible ==
false && ImGui::Button(
"Show tree")) {
786 state.leftPaneVisible =
true;
788 if (
state.leftPaneVisible ==
true && ImGui::Button(
"Hide tree")) {
789 state.leftPaneVisible =
false;
792 if (
state.bottomPaneVisible ==
false && ImGui::Button(
"Show metrics")) {
793 state.bottomPaneVisible =
true;
795 if (
state.bottomPaneVisible ==
true && ImGui::Button(
"Hide metrics")) {
796 state.bottomPaneVisible =
false;
799 if (
state.rightPaneVisible ==
false && ImGui::Button(
"Show inspector")) {
800 state.rightPaneVisible =
true;
802 if (
state.rightPaneVisible ==
true && ImGui::Button(
"Hide inspector")) {
803 state.rightPaneVisible =
false;
807 auto toolbarSize = ImGui::GetItemRectSize();
809 bool open_context_menu =
false;
810 int node_hovered_in_list = -1;
811 int node_hovered_in_scene = -1;
812 if (
state.leftPaneVisible) {
813 ImGui::BeginChild(
"node_list", ImVec2(
state.leftPaneSize, 0));
814 ImGui::Text(
"Workflows %d",
groups.Size);
816 for (
int groupId = 0; groupId <
groups.Size; groupId++) {
818 if (ImGui::TreeNodeEx(
group->name, ImGuiTreeNodeFlags_DefaultOpen)) {
819 for (
int node_idx = 0; node_idx <
nodes.Size; node_idx++) {
821 if (
node->GroupID != groupId) {
825 ImGui::PushID(
node->ID);
826 if (ImGui::Selectable(
node->Name,
node->ID == node_selected)) {
827 if (ImGui::IsMouseDoubleClicked(0)) {
828 controls[node_selected].logVisible =
true;
830 node_selected =
node->ID;
832 if (ImGui::IsItemHovered()) {
833 node_hovered_in_list =
node->ID;
834 open_context_menu |= ImGui::IsMouseClicked(1);
848 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(1, 1));
849 ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
850 auto canvasBg =
state.topologyLightMode ? (ImU32)ImColor(250, 250, 252, 255) : (ImU32)ImColor(44, 44, 46, 255);
851 auto canvasText = (ImU32)ImColor(235, 235, 245, 255);
852 ImGui::PushStyleColor(ImGuiCol_ChildBg, canvasBg);
853 ImGui::PushStyleColor(ImGuiCol_Text, canvasText);
854 ImVec2 graphSize = ImGui::GetWindowSize();
855 if (
state.leftPaneVisible) {
856 graphSize.x -=
state.leftPaneSize;
858 if (
state.rightPaneVisible) {
859 graphSize.x -=
state.rightPaneSize;
861 graphSize.y -= toolbarSize.y + 20;
862 ImGui::BeginChild(
"scrolling_region", graphSize,
true, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollWithMouse);
863 ImGui::PushItemWidth(graphSize.x);
865 ImVec2 canvasOrigin = ImGui::GetCursorScreenPos();
866 ImDrawList* draw_list = ImGui::GetWindowDrawList();
867 ImGuiIO& io = ImGui::GetIO();
868 if (fitRequested &&
nodes.Size > 0) {
869 ImVec2 minPos(positions[0].
pos.x, positions[0].pos.y);
870 ImVec2 maxPos = positions[0].pos +
nodes[0].Size;
871 for (
int i = 1;
i <
nodes.Size; ++
i) {
872 minPos.x = std::min(minPos.x, positions[
i].pos.x);
873 minPos.y = std::min(minPos.y, positions[
i].pos.y);
874 maxPos.x = std::max(maxPos.x, positions[
i].pos.x +
nodes[
i].Size.x);
875 maxPos.y = std::max(maxPos.y, positions[
i].pos.y +
nodes[
i].Size.y);
877 ImVec2 graphBounds = maxPos - minPos;
878 constexpr float FIT_PADDING = 80.f;
879 float fitZoomX = graphSize.x / std::max(graphBounds.x + FIT_PADDING, 1.f);
880 float fitZoomY = graphSize.y / std::max(graphBounds.y + FIT_PADDING, 1.f);
881 zoom = clampZoom(std::min(fitZoomX, fitZoomY));
882 ImVec2 visibleGraphSize = graphSize / zoom;
883 scrolling = minPos - (visibleGraphSize - graphBounds) / 2.f;
885 if (ImGui::IsWindowHovered() && io.MouseWheel != 0.f) {
886 ImVec2 mouseGraphPos = scrolling + (io.MousePos - canvasOrigin) / zoom;
887 float newZoom = clampZoom(zoom * (io.MouseWheel > 0.f ? 1.12f : 1.f / 1.12f));
888 scrolling = mouseGraphPos - (io.MousePos - canvasOrigin) / newZoom;
891 ImVec2
offset = canvasOrigin - scrolling * zoom;
894 draw_list->ChannelsSplit((
nodes.Size + 2) * 2);
897 displayGrid(show_grid, scrolling, zoom, draw_list);
899 ImVec2 win_pos = ImGui::GetCursorScreenPos();
900 ImVec2 canvas_sz = ImGui::GetWindowSize();
903 const ImColor arrowBgColor =
state.topologyLightMode ? ImColor(140, 80, 0) : ARROW_BACKGROUND_COLOR;
904 const ImColor arrowHalfColor =
state.topologyLightMode ? ImColor(180, 110, 0) : ARROW_HALFGROUND_COLOR;
905 const ImColor arrowColor =
state.topologyLightMode ? ImColor(220, 140, 0) : ARROW_COLOR;
908 for (
int link_idx = 0; link_idx <
links.Size; link_idx++) {
911 ImVec2
p1 = graphToScreen(NodePos::GetOutputSlotPos(
nodes, positions,
link.InputIdx,
link.InputSlot), canvasOrigin, scrolling, zoom);
912 ImVec2
p2 = graphToScreen(NodePos::GetInputSlotPos(
nodes, positions,
link.OutputIdx,
link.OutputSlot) + ImVec2(-3 * NODE_SLOT_RADIUS, 0), canvasOrigin, scrolling, zoom);
914 if ((
p1.x > win_pos.x + canvas_sz.x + 50) && (
p2.x > win_pos.x + canvas_sz.x + 50)) {
918 if ((
p1.y > win_pos.y + canvas_sz.y + 50) && (
p2.y > win_pos.y + canvas_sz.y + 50)) {
922 if ((
p1.y < win_pos.y) && (
p2.y < win_pos.y)) {
926 if ((
p1.x < win_pos.x) && (
p2.x < win_pos.x)) {
929 draw_list->ChannelsSetCurrent(0);
930 auto color = arrowBgColor;
931 auto thickness = ARROW_BACKGROUND_THICKNESS;
933 bool p1Inside =
false;
934 bool p2Inside =
false;
935 if ((
p1.x > win_pos.x) && (
p1.x < (win_pos.x + canvas_sz.x)) && (
p1.y < (win_pos.y + canvas_sz.y)) && (
p1.y > win_pos.y)) {
939 if ((
p2.x > win_pos.x) && (
p2.x < (win_pos.x + canvas_sz.x)) && (
p2.y < (win_pos.y + canvas_sz.y)) && (
p2.y > win_pos.y)) {
943 if (p1Inside && p2Inside) {
945 draw_list->ChannelsSetCurrent(2);
948 }
else if (p1Inside || p2Inside) {
949 draw_list->ChannelsSetCurrent(1);
951 color = arrowHalfColor;
956 if (
link.InputIdx == node_selected ||
link.OutputIdx == node_selected) {
957 auto foregroundLayer = (
nodes.Size + 1) * 2 + 1;
958 draw_list->ChannelsSetCurrent(foregroundLayer);
959 color = ARROW_SELECTED_COLOR;
963 draw_list->AddBezierCurve(
p1,
p1 + ImVec2(+50 * zoom, 0),
p2 + ImVec2(-50 * zoom, 0),
p2,
color, std::max(thickness * zoom, 1.f));
966 auto fgDrawList = ImGui::GetForegroundDrawList();
968 for (
int node_idx = 0; node_idx <
nodes.Size; node_idx++) {
969 auto backgroundLayer = (node_idx + 1) * 2;
970 auto foregroundLayer = (node_idx + 1) * 2 + 1;
972 if (node_selected == node_idx) {
973 backgroundLayer = (
nodes.Size + 1) * 2;
974 foregroundLayer = (
nodes.Size + 1) * 2 + 1;
977 NodePos*
pos = &positions[node_idx];
978 const DeviceInfo&
info = infos[node_idx];
980 ImVec2 node_rect_min = graphToScreen(
pos->pos, canvasOrigin, scrolling, zoom);
983 if ((node_rect_min.x > ImGui::GetCursorScreenPos().x + ImGui::GetWindowSize().x + 50) ||
984 (node_rect_min.y > ImGui::GetCursorScreenPos().y + ImGui::GetWindowSize().y + 50)) {
988 ImGui::PushID(
node->ID);
991 draw_list->ChannelsSetCurrent(foregroundLayer);
992 bool old_any_active = ImGui::IsAnyItemActive();
993 ImGui::SetWindowFontScale(zoom);
994 ImGui::SetCursorScreenPos(node_rect_min + NODE_WINDOW_PADDING * zoom);
996 ImGui::TextUnformatted(
node->Name);
997 switch (
info.maxLogLevel) {
998 case LogLevel::Critical:
1000 ImGui::TextColored(ERROR_MESSAGE_COLOR,
"%s", ICON_FA_EXCLAMATION_CIRCLE);
1002 case LogLevel::Error:
1004 ImGui::TextColored(ERROR_MESSAGE_COLOR,
"%s", ICON_FA_EXCLAMATION_CIRCLE);
1006 case LogLevel::Alarm:
1008 ImGui::TextColored(WARNING_MESSAGE_COLOR,
"%s", ICON_FA_EXCLAMATION_TRIANGLE);
1010 case LogLevel::Warning:
1012 ImGui::TextColored(WARNING_MESSAGE_COLOR,
"%s", ICON_FA_EXCLAMATION_TRIANGLE);
1022 bool node_widgets_active = (!old_any_active && ImGui::IsAnyItemActive());
1023 float attemptX = std::max(ImGui::GetItemRectSize().
x / zoom, 150.f);
1024 float attemptY = std::min(ImGui::GetItemRectSize().
y / zoom, 128.f);
1025 node->Size = ImVec2(attemptX, attemptY) + NODE_WINDOW_PADDING + NODE_WINDOW_PADDING;
1026 ImVec2 node_screen_size =
node->Size * zoom;
1027 ImVec2 node_rect_max = node_rect_min + node_screen_size;
1028 ImVec2 node_rect_title = node_rect_min + ImVec2(node_screen_size.x, 24 * zoom);
1030 if (node_rect_min.x > 20 + 2 * NODE_WINDOW_PADDING.x +
state.leftPaneSize + graphSize.x) {
1034 if (node_rect_min.y > 20 + 2 * NODE_WINDOW_PADDING.y + toolbarSize.y + graphSize.y) {
1040 draw_list->ChannelsSetCurrent(backgroundLayer);
1041 ImGui::SetCursorScreenPos(node_rect_min);
1042 ImGui::InvisibleButton(
"node", node_screen_size);
1043 if (ImGui::IsItemHovered()) {
1044 node_hovered_in_scene =
node->ID;
1045 open_context_menu |= ImGui::IsMouseClicked(1);
1046 if (ImGui::IsMouseDoubleClicked(0)) {
1047 controls[
node->ID].logVisible =
true;
1050 bool node_moving_active = ImGui::IsItemActive();
1051 if (node_widgets_active || node_moving_active) {
1052 node_selected =
node->ID;
1054 if (node_moving_active && ImGui::IsMouseDragging(0)) {
1055 pos->pos =
pos->pos + ImGui::GetIO().MouseDelta / zoom;
1057 if (ImGui::IsWindowHovered() && !node_moving_active && ImGui::IsMouseDragging(0)) {
1058 scrolling = scrolling - ImVec2(ImGui::GetIO().MouseDelta.x / 4.f, ImGui::GetIO().MouseDelta.y / 4.f) / zoom;
1061 auto nodeBg = decideColorForNode(info,
state.topologyLightMode);
1063 auto hovered = (node_hovered_in_list ==
node->ID || node_hovered_in_scene ==
node->ID || (node_hovered_in_list == -1 && node_selected ==
node->ID));
1064 ImVec4 nodeBgColor = hovered ? nodeBg.hovered : nodeBg.normal;
1065 ImVec4 nodeTitleColor = hovered ? nodeBg.title_hovered : nodeBg.title;
1066 ImU32 node_bg_color = ImGui::ColorConvertFloat4ToU32(nodeBgColor);
1067 ImU32 node_title_color = ImGui::ColorConvertFloat4ToU32(nodeTitleColor);
1069 draw_list->AddRectFilled(node_rect_min + ImVec2(3.f, 3.f) * zoom, node_rect_max + ImVec2(3.f, 3.f) * zoom, ImColor(0, 0, 0, 70), 4.0f * zoom);
1070 draw_list->AddRectFilled(node_rect_min, node_rect_max, node_bg_color, 4.0f * zoom);
1071 draw_list->AddRectFilled(node_rect_min, node_rect_title, node_title_color, 4.0f * zoom);
1072 draw_list->AddRect(node_rect_min, node_rect_max, NODE_BORDER_COLOR, 4.0f * zoom, 0, std::max(NODE_BORDER_THICKNESS * zoom, 1.f));
1074 for (
int slot_idx = 0; slot_idx <
node->InputsCount; slot_idx++) {
1075 draw_list->ChannelsSetCurrent(backgroundLayer);
1076 ImVec2
p1(-3 * NODE_SLOT_RADIUS, NODE_SLOT_RADIUS),
p2(-3 * NODE_SLOT_RADIUS, -NODE_SLOT_RADIUS),
p3(0, 0);
1077 auto slotPos = NodePos::GetInputSlotPos(
nodes, positions, node_idx, slot_idx);
1078 auto slotScreenPos = graphToScreen(slotPos, canvasOrigin, scrolling, zoom);
1079 auto pp1 =
p1 * zoom + slotScreenPos;
1080 auto pp2 =
p2 * zoom + slotScreenPos;
1081 auto pp3 =
p3 * zoom + slotScreenPos;
1082 auto color = arrowColor;
1083 if (node_idx == node_selected) {
1084 color = ARROW_SELECTED_COLOR;
1086 draw_list->AddTriangleFilled(pp1, pp2, pp3,
color);
1087 draw_list->AddCircleFilled(slotScreenPos, NODE_SLOT_RADIUS * zoom, INPUT_SLOT_COLOR);
1090 draw_list->ChannelsSetCurrent(foregroundLayer);
1091 MetricLabelsContext context{&
nodes, node_idx, &positions, draw_list, canvasOrigin, scrolling, zoom};
1093 MetricsPainter<int, uint64_t, MetricLabelsContext>::draw(
1096 ImVec2{
node->Size.x,
node->Size.y},
1098 MetricsPainter<int, uint64_t, MetricLabelsContext>::metric1D(),
1099 MetricsPainter<int, uint64_t, MetricLabelsContext>::simpleRecord<int>(),
1100 MetricsPainter<int, uint64_t, MetricLabelsContext>::items2D(
info.inputChannelMetricsViewIndex),
1101 MetricsPainter<int, uint64_t, MetricLabelsContext>::latestMetric<uint64_t>(metricsInfos[
node->ID],
info.inputChannelMetricsViewIndex),
1102 MetricsPainter<int, uint64_t, MetricLabelsContext>::simpleValue<uint64_t>(),
1103 MetricsPainter<int, uint64_t, MetricLabelsContext>::colorPalette(std::vector<ImU32>{{ImColor(0, 100, 0, 255), ImColor(0, 0, 100, 255), ImColor(100, 0, 0, 255)}}, 0, 3),
1104 [](
int,
int item,
int value, ImU32
color, MetricLabelsContext
const& context) {
1105 auto draw_list = context.draw_list;
1106 auto&
nodes = *context.nodes;
1107 auto& positions = *context.positions;
1108 auto slotPos = NodePos::GetInputSlotPos(
nodes, positions, context.nodeIdx, item);
1109 auto slotScreenPos = graphToScreen(slotPos, context.canvasOrigin, context.scrolling, context.zoom);
1111 auto&
label =
node->oldestPossibleInput[item];
1117 label.textSize = ImGui::CalcTextSize(
label.buffer).x;
1118 draw_list->AddRectFilled(slotScreenPos - ImVec2{
node->oldestPossibleInput[item].textSize + 5.f * NODE_SLOT_RADIUS * context.zoom, 2 * NODE_SLOT_RADIUS * context.zoom},
1119 slotScreenPos + ImVec2{-4.5f * NODE_SLOT_RADIUS * context.zoom, 2 * NODE_SLOT_RADIUS * context.zoom}, NODE_LABEL_BACKGROUND_COLOR, 2.f * context.zoom, ImDrawFlags_RoundCornersAll);
1120 draw_list->AddText(
nullptr, 12 * context.zoom,
1121 slotScreenPos - ImVec2{node->oldestPossibleInput[item].textSize + 4.5f * NODE_SLOT_RADIUS * context.zoom, 2 * NODE_SLOT_RADIUS * context.zoom},
1122 NODE_LABEL_TEXT_COLOR,
1123 node->oldestPossibleInput[item].buffer);
1126 for (
int slot_idx = 0; slot_idx <
node->OutputsCount; slot_idx++) {
1127 draw_list->AddCircleFilled(graphToScreen(NodePos::GetOutputSlotPos(
nodes, positions, node_idx, slot_idx), canvasOrigin, scrolling, zoom), NODE_SLOT_RADIUS * zoom, OUTPUT_SLOT_COLOR);
1130 MetricsPainter<int, uint64_t, MetricLabelsContext>::draw(
1133 ImVec2{
node->Size.x,
node->Size.y},
1135 MetricsPainter<int, uint64_t, MetricLabelsContext>::metric1D(),
1136 MetricsPainter<int, uint64_t, MetricLabelsContext>::simpleRecord<int>(),
1137 MetricsPainter<int, uint64_t, MetricLabelsContext>::items2D(
info.outputChannelMetricsViewIndex),
1138 MetricsPainter<int, uint64_t, MetricLabelsContext>::latestMetric<uint64_t>(metricsInfos[
node->ID],
info.outputChannelMetricsViewIndex),
1139 MetricsPainter<int, uint64_t, MetricLabelsContext>::simpleValue<uint64_t>(),
1140 MetricsPainter<int, uint64_t, MetricLabelsContext>::colorPalette(std::vector<ImU32>{{ImColor(0, 100, 0, 255), ImColor(0, 0, 100, 255), ImColor(100, 0, 0, 255)}}, 0, 3),
1141 [](
int,
int item,
int value, ImU32
color, MetricLabelsContext
const& context) {
1142 auto draw_list = context.draw_list;
1143 auto&
nodes = *context.nodes;
1144 auto& positions = *context.positions;
1145 auto slotPos = NodePos::GetOutputSlotPos(
nodes, positions, context.nodeIdx, item);
1146 auto slotScreenPos = graphToScreen(slotPos, context.canvasOrigin, context.scrolling, context.zoom);
1148 auto&
label =
node->oldestPossibleOutput[item];
1154 label.textSize = ImGui::CalcTextSize(
label.buffer).x;
1155 auto rectTL = ImVec2{4.5f * NODE_SLOT_RADIUS * context.zoom, -2 * NODE_SLOT_RADIUS * context.zoom};
1156 auto rectBR = ImVec2{
node->oldestPossibleOutput[item].textSize + 5.f * NODE_SLOT_RADIUS * context.zoom, 2 * NODE_SLOT_RADIUS * context.zoom};
1157 draw_list->AddRectFilled(slotScreenPos + rectTL,
1158 slotScreenPos + rectBR, NODE_LABEL_BACKGROUND_COLOR, 2.f * context.zoom, ImDrawFlags_RoundCornersAll);
1159 draw_list->AddText(
nullptr, 12 * context.zoom,
1160 slotScreenPos + rectTL,
1161 NODE_LABEL_TEXT_COLOR,
1162 node->oldestPossibleOutput[item].buffer);
1167 ImGui::SetWindowFontScale(1.0f);
1168 draw_list->ChannelsMerge();
1169 displayLegend(show_legend,
offset, draw_list);
1172 if (!ImGui::IsAnyItemHovered() && ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow) && ImGui::IsMouseClicked(1)) {
1173 node_selected = node_hovered_in_list = node_hovered_in_scene = -1;
1174 open_context_menu =
true;
1176 if (open_context_menu) {
1177 ImGui::OpenPopup(
"context_menu");
1178 if (node_hovered_in_list != -1) {
1179 node_selected = node_hovered_in_list;
1181 if (node_hovered_in_scene != -1) {
1182 node_selected = node_hovered_in_scene;
1190 ImGui::PopItemWidth();
1192 ImGui::PopStyleColor(2);
1193 ImGui::PopStyleVar(2);
1196 if (
state.rightPaneVisible) {
1198 ImGui::BeginGroup();
1199 ImGui::BeginChild(
"inspector");
1200 ImGui::TextUnformatted(
"Device Inspector");
1202 if (node_selected != -1) {
1204 auto& spec = specs[node_selected];
1205 auto&
states = allStates[node_selected];
1206 auto& control = controls[node_selected];
1207 auto&
info = infos[node_selected];
1208 auto&
metrics = metricsInfos[node_selected];
1210 auto& metadatum = metadata[
group.metadataId];
1212 if (
state.rightPaneVisible) {
1216 ImGui::TextWrapped(
"Select a node in the topology to display information about it");
1225#pragma GGC diagnostic pop
o2::monitoring::tags::Value Value
std::unique_ptr< expressions::Node > node
#define MAX_GROUP_NAME_SIZE
constexpr int p1()
constexpr to accelerate the coordinates changing
GLuint const GLchar * name
GLsizei GLenum const void GLuint GLsizei GLfloat * metrics
GLsizei const GLfloat * value
GLuint GLsizei const GLchar * label
typedef void(APIENTRYP PFNGLCULLFACEPROC)(GLenum mode)
Vec3 operator-(const Vec3 &firstVector, const Vec3 &secondVector)
double component(const Vec3 &vector, int dimension)
const GBTLinkAttributes links[kNGBTLinks]
std::variant< OriginValueMatcher, DescriptionValueMatcher, SubSpecificationTypeValueMatcher, std::unique_ptr< DataDescriptorMatcher >, ConstantValueMatcher, StartTimeValueMatcher > Node
State for the main GUI window.
void showTopologyNodeGraph(WorkspaceGUIState &state, std::vector< DeviceInfo > const &infos, std::vector< DeviceSpec > const &specs, std::vector< DataProcessingStates > const &allStates, std::vector< DataProcessorInfo > const &metadata, std::vector< DeviceControl > &controls, std::vector< DeviceMetricsInfo > const &metricsInfos)
void displayDeviceInspector(DeviceSpec const &spec, DeviceInfo const &info, DataProcessingStates const &states, DeviceMetricsInfo const &metrics, DataProcessorInfo const &metadata, DeviceControl &control)
Helper to display information about a device.
void displayDataRelayer(DeviceMetricsInfo const &, DeviceInfo const &, DeviceSpec const &spec, DataProcessingStates const &states, ImVec2 const &size, int &v)
View of the DataRelayer metrics for a given DeviceInfo.
@ EndOfStreaming
End of streaming requested, but not notified.
@ Streaming
Data is being processed.
@ Idle
End of streaming notified.
o2::framework::LogParsingHelpers::LogLevel LogLevel
D const SVectorGPU< T, D > & rhs
MultPolicyGPU< T, R1, R2 >::RepType operator*(const SMatrixGPU< T, D1, D, R1 > &lhs, const SMatrixGPU< T, D, D2, R2 > &rhs)
constexpr double thickness
BinCenterView< AxisIterator > operator+(BinCenterView< AxisIterator > lhs, int n)
double getValue(DPVAL dp)
LogLevel
Possible log levels for device log entries.
static const ImVec4 SHADED_GREEN
static const ImVec4 YELLOW
static const ImVec4 DARK_GREEN
static const ImVec4 SHADED_YELLOW
static const ImVec4 GREEN
static const ImVec4 SHADED_RED
static const ImVec4 LIGHT_GRAY
static const ImVec4 BLACK
static const ImVec4 DARK_YELLOW
static std::vector< TopoIndexInfo > topologicalSort(size_t nodeCount, int const *edgeIn, int const *edgeOut, size_t byteStride, size_t edgesCount)
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"