218 std::vector<MetricIndex>& visibleMetricsIndex,
219 std::vector<MetricDisplayState>& metricDisplayStates,
222 static bool locked =
false;
223 ImGui::Checkbox(
"Lock scrolling", &locked);
224 ImGui::BeginTable(
"##sparks table", 3, ImGuiTableFlags_Resizable | ImGuiTableFlags_ScrollY, ImVec2{-1, -1});
225 ImGui::TableSetupColumn(
"##close button", ImGuiTableColumnFlags_NoResize | ImGuiTableColumnFlags_WidthFixed, 25);
226 ImGui::TableSetupColumn(
"##plot name", ImGuiTableColumnFlags_WidthFixed, 200);
227 ImGui::TableSetupColumn(
"##plot", ImGuiTableColumnFlags_WidthFixed, 0);
228 ImGui::TableSetupScrollFreeze(2, 0);
229 for (
size_t i = 0;
i < visibleMetricsIndex.size(); ++
i) {
230 auto&
index = visibleMetricsIndex[
i];
231 auto& metricsInfos = metricStore.
metrics[
index.storeIndex];
232 auto& metricsInfo = metricsInfos[
index.deviceIndex];
233 auto& metric = metricsInfo.metrics[
index.metricIndex];
234 auto&
state = metricDisplayStates[
index.stateIndex];
236 ImGui::TableNextColumn();
237 ImGui::PushID(
index.stateIndex);
238 state.visible = !ImGui::Button(
"-");
240 ImGui::TableNextColumn();
241 ImGui::TextUnformatted(
state.legend.c_str());
242 ImGui::TableNextColumn();
243 static ImPlotAxisFlags rtx_axis = ImPlotAxisFlags_NoTickLabels | ImPlotAxisFlags_NoLabel | ImPlotAxisFlags_NoTickMarks;
244 static ImPlotAxisFlags rty_axis = ImPlotAxisFlags_NoTickLabels | ImPlotAxisFlags_NoLabel | ImPlotAxisFlags_NoTickMarks;
245 ImGui::PushID(
index.stateIndex);
249 data.size = metric.filledMetrics;
253 ImPlot::SetNextAxisLimits(ImAxis_X1, (startTime + ImGui::GetTime() - 100) * 1000, (startTime + ImGui::GetTime()) * 1000, ImGuiCond_Always);
254 ImPlot::SetNextAxisLimits(ImAxis_Y1, metricsInfo.min[
index.metricIndex], metricsInfo.max[
index.metricIndex] * 1.1, ImGuiCond_Always);
255 rty_axis |= ImPlotAxisFlags_LockMin;
257 if (ImPlot::BeginPlot(
"##sparks", ImVec2(700, 100), 0)) {
258 ImPlot::SetupAxes(
"time",
"value", rtx_axis, rty_axis);
259 ImPlot::SetAxis(
state.axis);
260 switch (metric.type) {
261 case MetricType::Enum: {
262 data.points = (
void*)metricsInfo.enumMetrics[metric.storeIdx].data();
263 data.time = metricsInfo.enumTimestamps[metric.storeIdx].data();
265 auto getter = [](
int idx,
void* hData) -> ImPlotPoint {
266 auto histoData =
reinterpret_cast<HistoData*
>(hData);
267 size_t pos = (histoData->first +
static_cast<size_t>(idx)) % histoData->
mod;
269 return ImPlotPoint(histoData->time[
pos], ((int8_t*)(histoData->points))[
pos]);
271 ImPlot::PlotLineG(
"##plot", getter, &
data,
data.mod);
273 case MetricType::Int: {
274 data.points = (
void*)metricsInfo.intMetrics[metric.storeIdx].data();
275 data.time = metricsInfo.intTimestamps[metric.storeIdx].data();
277 auto getter = [](
int idx,
void* hData) -> ImPlotPoint {
278 auto histoData =
reinterpret_cast<HistoData*
>(hData);
279 size_t pos = (histoData->first +
static_cast<size_t>(idx)) % histoData->
mod;
281 return ImPlotPoint(histoData->time[
pos], ((
int*)(histoData->points))[
pos]);
283 ImPlot::PlotLineG(
"##plot", getter, &
data,
data.mod);
285 case MetricType::Uint64: {
286 data.points = (
void*)metricsInfo.uint64Metrics[metric.storeIdx].data();
287 data.time = metricsInfo.uint64Timestamps[metric.storeIdx].data();
289 auto getter = [](
int idx,
void* hData) -> ImPlotPoint {
290 auto histoData =
reinterpret_cast<HistoData*
>(hData);
291 size_t pos = (histoData->first +
static_cast<size_t>(idx)) % histoData->
mod;
293 return ImPlotPoint(histoData->time[
pos], ((uint64_t*)histoData->points)[
pos]);
295 ImPlot::PlotLineG(
"##plot", getter, &
data,
data.mod, 0);
297 case MetricType::Float: {
298 data.points = (
void*)metricsInfo.floatMetrics[metric.storeIdx].data();
299 data.time = metricsInfo.floatTimestamps[metric.storeIdx].data();
301 auto getter = [](
int idx,
void* hData) -> ImPlotPoint {
302 auto histoData =
reinterpret_cast<HistoData*
>(hData);
303 size_t pos = (histoData->first +
static_cast<size_t>(idx)) % histoData->
mod;
305 return ImPlotPoint(histoData->time[
pos], ((
float*)histoData->points)[
pos]);
307 ImPlot::PlotLineG(
"##plot", getter, &
data,
data.mod, 0);
357 std::vector<MetricDisplayState>& state,
359 DriverInfo
const& driverInfo)
361 std::vector<void*> metricsToDisplay;
362 std::vector<const char*> deviceNames;
363 std::vector<MultiplotData> userData;
366 assert(metricsStore.metrics[si].size() == metricStore.
specs[si].size());
369 float maxValue[3] = {std::numeric_limits<float>::lowest(), std::numeric_limits<float>::lowest(), std::numeric_limits<float>::lowest()};
370 float minValue[3] = {0, 0, 0};
371 size_t maxDomain = std::numeric_limits<size_t>::lowest();
372 size_t minDomain = std::numeric_limits<size_t>::max();
375 ImPlotAxisFlags axisFlags = 0;
378 std::span<DeviceMetricsInfo const> metricsInfos = metricStore.
metrics[si];
379 std::span<TopologyNodeInfo const> specs = metricStore.
specs[si];
380 for (
int di = 0;
di < metricsInfos.size(); ++
di) {
381 for (
size_t mi = 0; mi < metricsInfos[
di].metrics.size(); ++mi) {
382 if (
state[gmi].visible ==
false) {
386 auto& metric = metricsInfos[
di].metrics[mi];
387 deviceNames.push_back(specs[
di].
label.c_str());
391 data.type = metric.type;
393 minValue[
data.axis] = std::min(minValue[
data.axis], metricsInfos[
di].min[mi]);
394 maxValue[
data.axis] = std::max(maxValue[
data.axis], metricsInfos[
di].max[mi]);
395 minDomain = std::min(minDomain, metricsInfos[
di].minDomain[mi]);
396 maxDomain = std::max(maxDomain, metricsInfos[
di].maxDomain[mi]);
397 axisFlags |=
data.axis == 1 ? (ImPlotFlags_)ImPlotFlags_YAxis2 : ImPlotFlags_None;
398 axisFlags |=
data.axis == 2 ? (ImPlotFlags_)ImPlotFlags_YAxis3 : ImPlotFlags_None;
399 switch (metric.type) {
400 case MetricType::Int: {
401 data.Y = metricsInfos[
di].intMetrics[metric.storeIdx].data();
402 auto& timestamps = metricsInfos[
di].intTimestamps[metric.storeIdx];
403 data.mod = std::min(metric.filledMetrics, timestamps.size());
405 data.X = timestamps.data();
407 case MetricType::Enum: {
408 data.Y = metricsInfos[
di].enumMetrics[metric.storeIdx].data();
409 auto& timestamps = metricsInfos[
di].enumTimestamps[metric.storeIdx];
410 data.mod = std::min(metric.filledMetrics, timestamps.size());
412 data.X = timestamps.data();
414 case MetricType::Uint64: {
415 data.Y = metricsInfos[
di].uint64Metrics[metric.storeIdx].data();
416 auto& timestamps = metricsInfos[
di].uint64Timestamps[metric.storeIdx];
417 data.mod = std::min(metric.filledMetrics, timestamps.size());
419 data.X = timestamps.data();
421 case MetricType::Float: {
422 data.Y = metricsInfos[
di].floatMetrics[metric.storeIdx].data();
423 auto& timestamps = metricsInfos[
di].floatTimestamps[metric.storeIdx];
424 data.mod = std::min(metric.filledMetrics, timestamps.size());
426 data.X = timestamps.data();
428 case MetricType::Unknown:
429 case MetricType::String: {
431 data.type = MetricType::String;
435 userData.emplace_back(
data);
441 maxDomain = std::max(minDomain + 1024, maxDomain);
442 for (
size_t ai = 0; ai < 3; ++ai) {
443 maxValue[ai] = std::max(minValue[ai] + 1.f, maxValue[ai]);
447 if (userData.empty()) {
450 for (
size_t ui = 0; ui < userData.size(); ++ui) {
451 metricsToDisplay.push_back(&(userData[ui]));
454 auto getterXY = [](
int idx,
void* hData) -> ImPlotPoint {
455 auto histoData =
reinterpret_cast<const MultiplotData*
>(hData);
456 size_t pos = (histoData->first +
static_cast<size_t>(idx)) % histoData->
mod;
457 double x =
static_cast<const size_t*
>(histoData->X)[
pos];
459 if (histoData->type == MetricType::Int) {
460 y =
static_cast<const int*
>(histoData->Y)[
pos];
461 }
else if (histoData->type == MetricType::Uint64) {
462 y =
static_cast<const uint64_t*
>(histoData->Y)[
pos];
463 }
else if (histoData->type == MetricType::Float) {
464 y =
static_cast<const float*
>(histoData->Y)[
pos];
465 }
else if (histoData->type == MetricType::Enum) {
466 y =
static_cast<const int8_t*
>(histoData->Y)[
pos];
468 auto point = ImPlotPoint{
x,
y};
471 static bool logScale =
false;
472 ImGui::Checkbox(
"Log scale", &logScale);
474 ImPlot::SetNextAxisLimits(ImAxis_X1, minDomain, maxDomain, ImGuiCond_Once);
476 auto axisPadding = 0.;
477 if (displayType == MetricsDisplayStyle::Lines) {
481 ImPlot::SetNextAxisLimits(ImAxis_Y1, minValue[0] - (maxValue[0] - minValue[0]) * axisPadding,
482 maxValue[0] * (1. + axisPadding), ImGuiCond_Always);
483 ImPlot::SetNextAxisLimits(ImAxis_Y2, minValue[1] - (maxValue[1] - minValue[1]) * axisPadding,
484 maxValue[1] * (1. + axisPadding), ImGuiCond_Always);
485 ImPlot::SetNextAxisLimits(ImAxis_Y3, minValue[2] - (maxValue[2] - minValue[2]) * axisPadding,
486 maxValue[2] * (1. + axisPadding), ImGuiCond_Always);
488 switch (displayType) {
489 case MetricsDisplayStyle::Histos:
490 if (ImPlot::BeginPlot(
"##Some plot")) {
491 ImPlot::SetupAxes(
"time",
"value");
492 ImPlot::SetupAxisFormat(ImAxis_Y1,
formatSI,
nullptr);
493 ImPlot::SetupAxisFormat(ImAxis_Y2,
formatSI,
nullptr);
494 ImPlot::SetupAxisFormat(ImAxis_Y3,
formatSI,
nullptr);
495 ImPlot::SetupAxisFormat(ImAxis_X1,
formatTimeSinceStart, (
void*)&driverInfo.startTimeMsFromEpoch);
496 for (
size_t pi = 0; pi < metricsToDisplay.size(); ++pi) {
500 ImPlot::PlotBarsG(
label, getterXY, metricsToDisplay[pi],
data->mod, 1, 0);
507 case MetricsDisplayStyle::Lines: {
508 auto xAxisFlags = ImPlotAxisFlags_None;
509 auto yAxisFlags = ImPlotAxisFlags_LockMin;
511 if (ImPlot::BeginPlot(
"##Some plot", {-1, -1}, axisFlags)) {
512 ImPlot::SetupAxes(
"time",
"value", xAxisFlags, yAxisFlags);
513 ImPlot::SetupAxisFormat(ImAxis_Y1,
formatSI,
nullptr);
514 ImPlot::SetupAxisFormat(ImAxis_Y2,
formatSI,
nullptr);
515 ImPlot::SetupAxisFormat(ImAxis_Y3,
formatSI,
nullptr);
516 ImPlot::SetupAxisFormat(ImAxis_X1,
formatTimeSinceStart, (
void*)&driverInfo.startTimeMsFromEpoch);
517 for (
size_t pi = 0; pi < metricsToDisplay.size(); ++pi) {
520 ImPlot::SetAxis(
data->axis);
521 ImPlot::PlotLineG(
data->legend, getterXY, metricsToDisplay[pi],
data->mod, 0);
527 case MetricsDisplayStyle::Stems:
528 if (ImPlot::BeginPlot(
"##Some plot")) {
529 ImPlot::SetupAxes(
"time",
"value");
530 for (
size_t pi = 0; pi < userData.size(); ++pi) {
533 if (
data->type == MetricType::Uint64) {
535 ImPlot::PlotScatterG(((
MultiplotData*)metricsToDisplay[pi])->legend, getterXY, metricsToDisplay[pi],
data->mod, 0);
625 DriverInfo
const& driverInfo,
626 std::vector<DeviceInfo>
const& infos,
627 std::vector<DataProcessorInfo>
const& metadata,
628 std::vector<DeviceControl>& controls,
631 if (
state.bottomPaneVisible ==
false) {
634 auto metricDisplayPos = 0;
635 static bool metricSelectorVisible =
true;
636 static std::vector<MetricDisplayState> metricDisplayState;
641 constexpr size_t MAX_QUERY_SIZE = 256;
642 static char query[MAX_QUERY_SIZE];
643 static char lastSelectedQuery[MAX_QUERY_SIZE];
645 size_t totalMetrics = 0;
646 for (
auto& metricsInfos : metricsStore.
metrics) {
647 for (
auto& metricInfo : metricsInfos) {
648 totalMetrics += metricInfo.metrics.size();
652 if (totalMetrics != metricDisplayState.size() || strcmp(lastSelectedQuery, query)) {
654 std::vector<MetricDisplayState> newMetricDisplayStates;
655 newMetricDisplayStates.resize(totalMetrics);
656 static std::vector<int> order;
657 order.resize(metricDisplayState.size());
658 std::iota(order.begin(), order.end(), 0);
659 std::sort(order.begin(), order.end(), [](
int a,
int b) {
660 return metricDisplayState[a].legend < metricDisplayState[b].legend;
664 auto& metricsInfos = metricsStore.
metrics[si];
665 auto& specs = metricsStore.
specs[si];
666 for (
size_t di = 0;
di < metricsInfos.size(); ++
di) {
667 auto& metricInfo = metricsInfos[
di];
668 auto& spec = specs[
di];
669 for (
size_t li = 0; li != metricInfo.metricLabels.size(); ++li) {
670 char const* metricLabel = metricInfo.metricLabels[li].label;
672 auto low = std::lower_bound(order.begin(), order.end(), spec.label, [](
int a, std::string
const&
b) {
673 return metricDisplayState[a].legend < b;
675 auto up = std::upper_bound(low, order.end(), spec.label, [](std::string
const&
a,
int b) {
676 return a < metricDisplayState[b].legend;
678 std::string legend = fmt::format(
"{}/{}", spec.label, metricLabel);
679 auto old = std::lower_bound(low, up, legend, [](
int a, std::string
const&
b) {
680 return metricDisplayState[
a].legend <
b;
682 if (old != order.end() && metricDisplayState[*old].legend == legend) {
683 newMetricDisplayStates[gmi].visible = metricDisplayState[*old].visible;
684 newMetricDisplayStates[gmi].axis = metricDisplayState[*old].axis;
686 newMetricDisplayStates[gmi].visible =
false;
689 newMetricDisplayStates[gmi].selected =
hasAll(metricLabel, query);
690 newMetricDisplayStates[gmi].legend = legend;
695 metricDisplayState.swap(newMetricDisplayStates);
696 strcpy(lastSelectedQuery, query);
699 static std::vector<MetricIndex> selectedMetricIndex;
701 if (metricSelectorVisible) {
702 selectedMetricIndex.clear();
705 auto& metricsInfos = metricsStore.
metrics[si];
707 for (
size_t di = 0;
di < metricsInfos.size(); ++
di) {
708 auto& metricInfo = metricsInfos[
di];
709 for (
size_t li = 0; li != metricInfo.metricLabels.size(); ++li) {
710 auto&
state = metricDisplayState[gmi];
711 if (
state.selected) {
712 selectedMetricIndex.emplace_back(
MetricIndex{si,
di, li, gmi});
719 metricDisplayPos = ImGui::GetIO().DisplaySize.x / 4;
720 ImGui::SetNextWindowPos(ImVec2(0, ImGui::GetIO().DisplaySize.y -
state.bottomPaneSize), 0);
721 ImGui::SetNextWindowSize(ImVec2(metricDisplayPos,
state.bottomPaneSize), 0);
722 ImGui::Begin(
"Available metrics",
nullptr, ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize);
724 ImGui::Text(ICON_FA_FILTER);
726 ImGui::InputText(
"##query-metrics", query, MAX_QUERY_SIZE);
727 size_t metricSize = 0;
728 for (
auto deviceMetrics : metricsStore.
metrics) {
729 metricSize += DeviceMetricsInfoHelpers::metricsStorageSize(deviceMetrics);
732 ImGui::Text(
"%zu/%zu matching", selectedMetricIndex.size(), totalMetrics);
734 static const char* possibleAxis[] = {
739 if (ImGui::BeginTable(
"##metrics-table", 3, ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY, ImVec2{-1, -1})) {
740 ImGui::TableSetupColumn(
"##close button", ImGuiTableColumnFlags_NoResize | ImGuiTableColumnFlags_WidthFixed, 20);
741 ImGui::TableSetupColumn(
"##axis kind", ImGuiTableColumnFlags_NoResize | ImGuiTableColumnFlags_WidthFixed, 30);
742 ImGui::TableSetupScrollFreeze(1, 0);
743 ImGuiListClipper clipper;
744 clipper.Begin(selectedMetricIndex.size());
745 while (clipper.Step()) {
746 for (
size_t i = clipper.DisplayStart;
i < clipper.DisplayEnd; ++
i) {
747 auto&
index = selectedMetricIndex[
i];
748 auto& metricsInfos = metricsStore.
metrics[
index.storeIndex];
750 auto& metricInfo = metricsInfos[
index.deviceIndex];
752 auto&
label = metricInfo.metricLabels[
index.metricIndex];
753 ImGui::PushID(
index.stateIndex);
754 ImGui::TableNextRow();
755 ImGui::TableNextColumn();
756 ImGui::Checkbox(
"##checkbox", &metricDisplayState[
index.stateIndex].visible);
757 ImGui::TableNextColumn();
758 if (metricDisplayState[
index.stateIndex].visible) {
759 if (ImGui::BeginCombo(
"##Select style", possibleAxis[metricDisplayState[
index.stateIndex].axis], ImGuiComboFlags_NoArrowButton)) {
760 for (
int n = 0;
n < IM_ARRAYSIZE(possibleAxis);
n++) {
761 bool is_selected = (metricDisplayState[
index.stateIndex].axis ==
n);
762 if (ImGui::Selectable(possibleAxis[
n], is_selected)) {
763 metricDisplayState[
index.stateIndex].axis =
n;
766 ImGui::SetItemDefaultFocus();
772 ImGui::TableNextColumn();
773 ImGui::Text(
"%s/%s", node.label.c_str(),
label.label);
781 ImGui::SetNextWindowPos(ImVec2(metricDisplayPos, ImGui::GetIO().DisplaySize.y -
state.bottomPaneSize), 0);
782 ImGui::SetNextWindowSize(ImVec2(ImGui::GetIO().DisplaySize.x - metricDisplayPos,
state.bottomPaneSize), 0);
784 ImGui::Begin(
"Devices",
nullptr, ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize);
786 if (!metricSelectorVisible) {
787 metricSelectorVisible = ImGui::Button(ICON_FA_CHEVRON_RIGHT
"Show metric selector");
789 metricSelectorVisible = !ImGui::Button(ICON_FA_CHEVRON_LEFT
"Hide metric selector");
791 static char const* plotStyles[] = {
799 static char const* currentStyleStr = plotStyles[0];
800 ImGui::TextUnformatted(
"Metric display style:");
802 ImGui::PushItemWidth(100);
803 if (ImGui::BeginCombo(
"##Select style", currentStyleStr)) {
804 for (
int n = 0;
n < IM_ARRAYSIZE(plotStyles);
n++) {
805 bool is_selected = (currentStyleStr == plotStyles[
n]);
806 if (ImGui::Selectable(plotStyles[
n], is_selected)) {
807 currentStyleStr = plotStyles[
n];
811 ImGui::SetItemDefaultFocus();
816 ImGui::PopItemWidth();
819 int visibleMetrics = 0;
820 static std::vector<int> visibleDevicesIndex;
821 static std::vector<MetricIndex> visibleMetricsIndex;
823 visibleDevicesIndex.reserve(totalMetrics);
824 visibleDevicesIndex.clear();
825 visibleMetricsIndex.clear();
828 auto& metricsInfos = metricsStore.
metrics[si];
829 for (
size_t di = 0;
di < metricsInfos.size(); ++
di) {
830 auto& metricInfo = metricsInfos[
di];
831 bool deviceVisible =
false;
832 for (
size_t mi = 0; mi < metricInfo.metrics.size(); ++mi) {
833 auto&
state = metricDisplayState[gmi];
835 deviceVisible =
true;
837 auto& metric = metricInfo.metrics[mi];
838 size_t const* timestamps =
nullptr;
839 switch (metric.type) {
840 case MetricType::Int:
841 timestamps = metricInfo.intTimestamps[metric.storeIdx].data();
843 case MetricType::Float:
844 timestamps = metricInfo.floatTimestamps[metric.storeIdx].data();
846 case MetricType::String:
847 timestamps = metricInfo.stringTimestamps[metric.storeIdx].data();
849 case MetricType::Uint64:
850 timestamps = metricInfo.uint64Timestamps[metric.storeIdx].data();
852 case MetricType::Enum:
853 timestamps = metricInfo.enumTimestamps[metric.storeIdx].data();
856 throw std::runtime_error(
"Unknown metric type");
861 size_t curMinTime = timestamps[minRangePos];
862 if (curMinTime == 0) {
865 minTime = minTime < curMinTime ? minTime : curMinTime;
866 if (minTime != 0 && minTime != -1) {
871 size_t curMaxTime = timestamps[maxRangePos];
872 maxTime = std::max(maxTime, curMaxTime);
878 visibleDevicesIndex.push_back(
di);
882 if (visibleMetricsIndex.empty()) {
888 switch (currentStyle) {
889 case MetricsDisplayStyle::Stems:
890 case MetricsDisplayStyle::Histos:
891 case MetricsDisplayStyle::Lines: {
893 minTime, maxTime, 1024,
894 currentStyle, metricDisplayState, metricsStore, driverInfo);
896 case MetricsDisplayStyle::Sparks: {
897 displaySparks(
state.startTime, visibleMetricsIndex, metricDisplayState, metricsStore);
899 case MetricsDisplayStyle::Table: {
900 static std::vector<float> visibleDevicesOffsets;
901 visibleDevicesOffsets.clear();
902 visibleDevicesOffsets.resize(visibleDevicesIndex.size());
904 size_t lastDevice = -1;
905 int visibleDeviceCount = -1;
907 for (
auto index : visibleMetricsIndex) {
908 auto& metricsInfos = metricsStore.
metrics[
index.storeIndex];
909 if (lastDevice !=
index.deviceIndex) {
910 visibleDeviceCount++;
911 lastDevice =
index.deviceIndex;
913 auto label = metricsInfos[
index.deviceIndex].metricLabels[
index.metricIndex].label;
914 visibleDevicesOffsets[visibleDeviceCount] += ImGui::CalcTextSize(
label,
nullptr,
true).x;
917 if (ImGui::BeginTable(
"##metrics-table", visibleMetricsIndex.size() + 1, ImGuiTableFlags_Resizable | ImGuiTableFlags_ScrollY | ImGuiTableFlags_ScrollX, ImVec2{-1, -1})) {
918 ImGui::TableSetupColumn(
"##close button", ImGuiTableColumnFlags_NoResize | ImGuiTableColumnFlags_WidthFixed, 20);
919 for (
int i = 0;
i < visibleMetricsIndex.size(); ++
i) {
920 ImGui::TableSetupColumn(
"##device-header", ImGuiTableColumnFlags_WidthFixed, 100);
922 ImGui::TableSetupScrollFreeze(1, 2);
923 ImGui::TableNextRow();
924 ImGui::TableNextColumn();
925 ImGui::TextUnformatted(
"");
926 visibleDeviceCount = -1;
928 for (
auto index : visibleMetricsIndex) {
929 ImGui::TableNextColumn();
930 auto& devices = metricsStore.
specs[
index.storeIndex];
931 if (lastDevice ==
index.deviceIndex) {
934 visibleDeviceCount++;
935 lastDevice =
index.deviceIndex;
936 auto& spec = devices[
index.deviceIndex];
938 ImGui::TextUnformatted(spec.label.c_str());
942 ImGui::TableNextRow();
943 ImGui::TableNextColumn();
944 ImGui::TextUnformatted(
"#");
946 for (
auto index : visibleMetricsIndex) {
947 ImGui::TableNextColumn();
948 auto& metricsInfos = metricsStore.
metrics[
index.storeIndex];
949 auto& metric = metricsInfos[
index.deviceIndex];
950 auto label = metricsInfos[
index.deviceIndex].metricLabels[
index.metricIndex].label;
951 ImGui::Text(
"%s (%" PRIu64
")",
label, (uint64_t)metric.metrics[
index.metricIndex].filledMetrics);
955 ImGuiListClipper clipper;
959 while (clipper.Step()) {
960 for (
size_t i = clipper.DisplayStart;
i < clipper.DisplayEnd; ++
i) {
961 ImGui::TableNextRow();
975 ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 4.);
976 if (info.
active ==
false) {
977 ImGui::PushStyleColor(ImGuiCol_TitleBg, PaletteHelpers::DARK_RED);
978 ImGui::PushStyleColor(ImGuiCol_TitleBgActive, PaletteHelpers::RED);
979 ImGui::PushStyleColor(ImGuiCol_TitleBgCollapsed, PaletteHelpers::RED);
983 case LogLevel::Critical:
984 ImGui::PushStyleColor(ImGuiCol_TitleBg, PaletteHelpers::SHADED_RED);
985 ImGui::PushStyleColor(ImGuiCol_TitleBgActive, PaletteHelpers::RED);
986 ImGui::PushStyleColor(ImGuiCol_TitleBgCollapsed, PaletteHelpers::SHADED_RED);
988 case LogLevel::Error:
989 ImGui::PushStyleColor(ImGuiCol_TitleBg, PaletteHelpers::SHADED_RED);
990 ImGui::PushStyleColor(ImGuiCol_TitleBgActive, PaletteHelpers::RED);
991 ImGui::PushStyleColor(ImGuiCol_TitleBgCollapsed, PaletteHelpers::SHADED_RED);
993 case LogLevel::Alarm:
994 ImGui::PushStyleColor(ImGuiCol_TitleBg, PaletteHelpers::SHADED_YELLOW);
995 ImGui::PushStyleColor(ImGuiCol_TitleBgActive, PaletteHelpers::YELLOW);
996 ImGui::PushStyleColor(ImGuiCol_TitleBgCollapsed, PaletteHelpers::SHADED_YELLOW);
998 case LogLevel::Warning:
999 ImGui::PushStyleColor(ImGuiCol_TitleBg, PaletteHelpers::SHADED_YELLOW);
1000 ImGui::PushStyleColor(ImGuiCol_TitleBgActive, PaletteHelpers::YELLOW);
1001 ImGui::PushStyleColor(ImGuiCol_TitleBgCollapsed, PaletteHelpers::SHADED_YELLOW);
1003 case LogLevel::Info:
1004 ImGui::PushStyleColor(ImGuiCol_TitleBg, PaletteHelpers::SHADED_GREEN);
1005 ImGui::PushStyleColor(ImGuiCol_TitleBgActive, PaletteHelpers::GREEN);
1006 ImGui::PushStyleColor(ImGuiCol_TitleBgCollapsed, PaletteHelpers::SHADED_GREEN);
1009 ImGui::PushStyleColor(ImGuiCol_TitleBg, PaletteHelpers::SHADED_BLUE);
1010 ImGui::PushStyleColor(ImGuiCol_TitleBgActive, PaletteHelpers::BLUE);
1011 ImGui::PushStyleColor(ImGuiCol_TitleBgCollapsed, PaletteHelpers::SHADED_BLUE);
1129 std::vector<DeviceSpec>
const& devices,
1130 std::vector<DataProcessingStates>
const& allStates,
1131 std::vector<DataProcessorInfo>
const& metadata,
1132 std::vector<DeviceMetricsInfo>
const& metricsInfos,
1133 DriverInfo
const& driverInfo,
1134 std::vector<DeviceControl>& controls,
1143 guiState.
devices.resize(infos.size());
1144 for (
size_t i = 0;
i < guiState.
devices.size(); ++
i) {
1157 clock_gettime(CLOCK_REALTIME, &now);
1158 guiState.
startTime = now.tv_sec - ImGui::GetTime();
1159 std::vector<TopologyNodeInfo> deviceNodesInfos;
1160 for (
auto& device : devices) {
1163 std::vector<TopologyNodeInfo> driverNodesInfos;
1166 return [&infos, &devices, &allStates, &metadata, &controls, &metricsInfos, &driverInfo, &driverControl, deviceNodesInfos, driverNodesInfos]() {
1167 ImGuiStyle& style = ImGui::GetStyle();
1168 style.FrameRounding = 0.;
1169 style.WindowRounding = 0.;
1170 style.Colors[ImGuiCol_WindowBg] = ImVec4(0x1b / 255.f, 0x1b / 255.f, 0x1b / 255.f, 1.00f);
1171 style.Colors[ImGuiCol_ScrollbarBg] = ImVec4(0x1b / 255.f, 0x1b / 255.f, 0x1b / 255.f, 1.00f);
1181 displayMetrics(guiState, driverInfo, infos, metadata, controls, metricsStore);
1184 int windowPosStepping = (ImGui::GetIO().DisplaySize.y - 500) / guiState.
devices.size();
1186 for (
size_t i = 0;
i < guiState.
devices.size(); ++
i) {
1188 assert(
i < infos.size());
1189 assert(
i < devices.size());
1192 assert(controls.size() == devices.size());
1197 ImGui::SetNextWindowPos(ImVec2(ImGui::GetIO().DisplaySize.x / 3 * 2,
i * windowPosStepping), ImGuiCond_Once);
1198 ImGui::SetNextWindowSize(ImVec2(ImGui::GetIO().DisplaySize.x / 3, ImGui::GetIO().DisplaySize.y - 300),
1205 ImGui::Checkbox(
"Stop logging", &control.
quiet);
1208 control.
logLevel = LogParsingHelpers::LogLevel::Debug;
1210 ImGui::Combo(
"Log level",
reinterpret_cast<int*
>(&control.
logLevel), LogParsingHelpers::LOG_LEVELS,
1211 (
int)LogParsingHelpers::LogLevel::Size, 5);
1214 ImGui::BeginChild(
"ScrollingRegion", ImVec2(0, -ImGui::GetTextLineHeightWithSpacing()),
false,
1215 ImGuiWindowFlags_HorizontalScrollbar | ImGuiWindowFlags_NoMove);