From eb5f9f6643e0729d35f705c8a7b7b46cb5874a6a Mon Sep 17 00:00:00 2001 From: Paul Oliver Date: Sat, 30 May 2026 23:07:06 +0200 Subject: Adds v1 population charts --- core/client.cpp | 423 ++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 275 insertions(+), 148 deletions(-) (limited to 'core/client.cpp') diff --git a/core/client.cpp b/core/client.cpp index 227ebaa..1c63540 100644 --- a/core/client.cpp +++ b/core/client.cpp @@ -3,15 +3,14 @@ #include #include #include +#include #include -#include #include #include #include -#include #include -#include +#include #include #include "logger.c" @@ -21,7 +20,6 @@ // ---------------------------------------------------------------------------- #define COLOR_BLACK ImVec4(0.f, 0.f, 0.f, 1.f) #define FONT_SIZE 12.f -#define FONT_SOURCE "/usr/share/fonts/droid/DroidSansMono.ttf" #define GLSL_VERSION "#version 130" #define PLOT_MAX_COLS 8 #define PLOT_MIN_COLS 1 @@ -54,16 +52,37 @@ enum Status { STATUS_STOPPING, }; -struct CompString { - bool operator()(const char *a, const char *b) const { - return strcmp(a, b) < 0; - } +template struct Trace : public std::vector { + Trace(); + T *start(); + void trim(); + +#if !defined(NDEBUG) + T &operator[](size_t n); +#endif +}; + +template struct TraceNamed : public Trace { + std::string m_name; + std::string m_name_fmt; + TraceNamed(std::string name, std::string name_fmt); }; struct Plot { - const char *name; - const char *section; - std::vector traces; + std::string m_name; + std::string m_section; + std::vector m_trace_keys; + Plot(std::string name, std::string section, std::vector trace_keys); + virtual ~Plot(); + virtual void render(); +}; + +struct PlotStacked : public Plot { + std::vector m_totals; + std::vector m_old_trace; + std::vector m_new_trace; + PlotStacked(std::string name, std::string section, std::vector trace_keys); + void render(); }; // ---------------------------------------------------------------------------- @@ -71,34 +90,26 @@ struct Plot { // ---------------------------------------------------------------------------- #include "arch_plots.cpp" -template -std::array merge_array(const std::array &first, const std::array &second) { - std::array result{}; - for (size_t i = 0; i < N; i++) result[i] = first[i]; - for (size_t i = 0; i < M; i++) result[N + i] = second[i]; - return result; -} - -std::array g_core_traces = std::to_array({ - "rowid", - "step", +std::vector> g_core_traces = { + {"rowid", "rowid"}, + {"step", "step"}, #define FOR_CORE(i) \ - "cycl_" #i, \ - "mall_" #i, \ - "pnum_" #i, \ - "pfst_" #i, \ - "plst_" #i, \ - "amb0_" #i, \ - "amb1_" #i, \ - "emb0_" #i, \ - "emb1_" #i, \ - "eliv_" #i, \ - "edea_" #i, + {"cycl_" #i, "cycl_" #i}, \ + {"mall_" #i, "mall_" #i}, \ + {"pnum_" #i, "pnum_" #i}, \ + {"pfst_" #i, "pfst_" #i}, \ + {"plst_" #i, "plst_" #i}, \ + {"amb0_" #i, "amb0_" #i}, \ + {"amb1_" #i, "amb1_" #i}, \ + {"emb0_" #i, "emb0_" #i}, \ + {"emb1_" #i, "emb1_" #i}, \ + {"eliv_" #i, "eliv_" #i}, \ + {"edea_" #i, "edea_" #i}, FOR_CORES #undef FOR_CORE -}); +}; -std::array g_core_plots = std::to_array({ +std::vector g_core_plots = { {"cycl", "general", { #define FOR_CORE(i) "cycl_" #i, FOR_CORES @@ -129,14 +140,7 @@ std::array g_core_plots = std::to_array({ FOR_CORES #undef FOR_CORE }}, -}); - -std::map, CompString> g_trace_map; -std::array g_traces = merge_array(g_core_traces, g_arch_traces); -std::array g_plots = merge_array(g_core_plots, g_arch_plots); - -#define TRACE_COUNT g_traces.size() -#define PLOT_COUNT g_plots.size() +}; // ---------------------------------------------------------------------------- // Globals @@ -146,7 +150,8 @@ ImGuiIO *g_imgui_io; ImGuiStyle *g_imgui_style; ImPlotStyle *g_implot_style; -const char *g_x_axes[] = { +// Data +std::vector g_x_axes = { "rowid", "step", #define FOR_CORE(i) "cycl_" #i, @@ -162,29 +167,121 @@ int64_t g_x_low = DEFVAL_X_LOW; int64_t g_x_high = DEFVAL_X_HIGH; int64_t g_hm_left = DEFVAL_HM_LEFT; int64_t g_hm_pixel_count = DEFVAL_HM_PIXEL_COUNT; -int64_t g_hm_pixel_pow; // calculate on startup +int64_t g_hm_pixel_pow; // calculate on init int64_t g_x_current = -1l; -thrd_t g_fetching_thread; -mtx_t g_fetching_mutex; int g_trace_len; int g_trace_offset; -// Layout globals +thrd_t g_fetching_thread; +mtx_t g_fetching_mutex; + +// Layout bool g_data_col_visible = true; bool g_plot_maximized; bool g_plot_scroll; float g_plot_scroll_current; float g_plot_scroll_to; float g_data_col_width; -float g_plot_cells_top[PLOT_MAX_COLS][PLOT_COUNT]; -float g_plot_cells_bottom[PLOT_MAX_COLS][PLOT_COUNT]; -Plot *g_plot_cells[PLOT_MAX_COLS][PLOT_COUNT]; -Plot *g_plot_selected = &g_plots[0]; +std::vector g_plot_cells; +std::vector g_plot_cells_top; +std::vector g_plot_cells_bottom; +std::vector g_plots_covered; +Plot *g_plot_selected; int g_plot_cols = 2; int g_plot_col_selected; int g_plot_row_selected; +// Plots +std::map *> g_trace_map; +std::vector *> g_traces; +std::vector g_plots; +Trace g_x_axis_normal; + +// ---------------------------------------------------------------------------- +// Trace definitions +// ---------------------------------------------------------------------------- +template Trace::Trace() : std::vector() {} + +template T *Trace::start() { + return this->size() ? &this->operator[](g_trace_offset) : nullptr; +} + +template void Trace::trim() { + assert((int64_t)this->size() >= g_entries * 2); + this->erase(this->begin(), this->end() - g_entries); +} + +#if !defined(NDEBUG) +template T &Trace::operator[](size_t n) { + return this->at(n); +} +#endif + +// ---------------------------------------------------------------------------- +// TraceNamed definitions +// ---------------------------------------------------------------------------- +template TraceNamed::TraceNamed(std::string name, std::string name_fmt) : m_name(name), m_name_fmt(name_fmt) {} + +// ---------------------------------------------------------------------------- +// Plot definitions +// ---------------------------------------------------------------------------- +Plot::Plot(std::string name, std::string section, std::vector trace_keys) : m_name(name), m_section(section), m_trace_keys(trace_keys) {} + +Plot::~Plot() {} + +void Plot::render() { + ImS64 *x = g_trace_map[g_x_axes[g_x_axis]]->start(); + + for (auto &trace : m_trace_keys) { + TraceNamed *trace_obj = g_trace_map[trace]; + ImS64 *y = trace_obj->start(); + ImPlot::PlotLine(trace_obj->m_name_fmt.c_str(), x, y, g_trace_len); + } +} + +// ---------------------------------------------------------------------------- +// PlotStacked definitions +// ---------------------------------------------------------------------------- +PlotStacked::PlotStacked(std::string name, std::string section, std::vector trace_keys) : Plot(name, section, trace_keys) {} + +void PlotStacked::render() { + m_totals.resize(g_trace_len); + m_old_trace.resize(g_trace_len); + m_new_trace.resize(g_trace_len); + + for (size_t i = 0; i < m_trace_keys.size(); i++) { + ImPlot::PlotDummy(g_trace_map[m_trace_keys[i]]->m_name_fmt.c_str()); + } + + for (int i = 0; i < (int)m_trace_keys.size(); i++) { + if (GImPlot->CurrentPlot->Items.GetLegendItem(i)->Show) { + for (int j = 0; j < g_trace_len; j++) { + m_totals[j] += g_trace_map[m_trace_keys[i]]->start()[j]; + } + } + } + + for (int i = 0; i < (int)m_trace_keys.size(); i++) { + if (GImPlot->CurrentPlot->Items.GetLegendItem(i)->Show) { + ImPlotSpec spec = ImPlotSpec(ImPlotProp_FillAlpha, GImPlot->CurrentPlot->Items.GetLegendItem(i)->LegendHovered ? 0.9f : 0.7f); + + for (int j = 0; j < g_trace_len; j++) { + m_new_trace[j] = m_totals[j] ? (m_old_trace[j] + (double)g_trace_map[m_trace_keys[i]]->start()[j] / (double)m_totals[j]) : 0.; + } + + ImPlot::PlotShaded(g_trace_map[m_trace_keys[i]]->m_name_fmt.c_str(), g_x_axis_normal.start(), m_old_trace.data(), m_new_trace.data(), g_trace_len, spec); + ImPlot::PlotLine(g_trace_map[m_trace_keys[i]]->m_name_fmt.c_str(), g_x_axis_normal.start(), m_old_trace.data(), g_trace_len); + ImPlot::PlotLine(g_trace_map[m_trace_keys[i]]->m_name_fmt.c_str(), g_x_axis_normal.start(), m_new_trace.data(), g_trace_len); + std::swap(m_old_trace, m_new_trace); + } + } + + m_totals.clear(); + m_old_trace.clear(); + m_new_trace.clear(); +} + // ---------------------------------------------------------------------------- // Data functions // ---------------------------------------------------------------------------- @@ -197,17 +294,18 @@ void data_on_field_change(void) { g_nth = std::clamp(g_nth, DEFVAL_NTH, INT64_MAX); g_x_low = std::clamp(g_x_low, DEFVAL_X_LOW, INT64_MAX); g_x_high = std::clamp(g_x_high, g_x_low + 1l, DEFVAL_X_HIGH); - #if !defined(MVEC_LOOP) +#if !defined(MVEC_LOOP) g_hm_left = std::clamp(g_hm_left, DEFVAL_HM_LEFT, (int64_t)MVEC_SIZE); - #endif +#endif g_hm_pixel_count = std::clamp(g_hm_pixel_count, 1l, DEFVAL_HM_PIXEL_COUNT); g_hm_pixel_pow = std::clamp(g_hm_pixel_pow, 0l, data_max_hm_pixel_pow()); - g_x_current = -1l; - for (auto &trace : g_trace_map) { - trace.second.clear(); - } + g_trace_len = 0; + g_trace_offset = 0; + + for (auto &trace : g_traces) trace->clear(); + g_x_axis_normal.clear(); } void data_reset_fields(void) { @@ -220,46 +318,49 @@ void data_reset_fields(void) { g_hm_pixel_count = DEFVAL_HM_PIXEL_COUNT; g_hm_pixel_pow = data_max_hm_pixel_pow(); - g_trace_len = 0; - g_trace_offset = 0; - data_on_field_change(); } void data_reset_plot_cells(void) { - memset(g_plot_cells, 0, PLOT_MAX_COLS * PLOT_COUNT * sizeof(nullptr)); - memset(g_plot_cells_top, 0, PLOT_MAX_COLS * PLOT_COUNT * sizeof(float)); - memset(g_plot_cells_bottom, 0, PLOT_MAX_COLS * PLOT_COUNT * sizeof(float)); + std::fill(g_plot_cells.begin(), g_plot_cells.end(), nullptr); + std::fill(g_plot_cells_top.begin(), g_plot_cells_top.end(), 0.f); + std::fill(g_plot_cells_bottom.begin(), g_plot_cells_bottom.end(), 0.f); } +#if !defined(NDEBUG) +void data_validate_traces(void) { + for (auto &trace : g_traces) assert(trace->size() == g_traces[0]->size()); +} +#endif + void data_fetch(void) { - struct json_object *request = json_object_new_object(); + json_object *request = json_object_new_object(); json_object_object_add(request, "request", json_object_new_string("data")); json_object_object_add(request, "entries", json_object_new_int64(g_entries)); json_object_object_add(request, "nth", json_object_new_int64(g_nth)); - json_object_object_add(request, "x-axis", json_object_new_string(g_x_axes[g_x_axis])); + json_object_object_add(request, "x-axis", json_object_new_string(g_x_axes[g_x_axis].c_str())); json_object_object_add(request, "x-low", json_object_new_int64(g_x_low)); json_object_object_add(request, "x-high", json_object_new_int64(g_x_high)); json_object_object_add(request, "hm-left", json_object_new_int64(g_hm_left)); json_object_object_add(request, "hm-pixel-count", json_object_new_int64(g_hm_pixel_count)); json_object_object_add(request, "hm-pixel-pow", json_object_new_int64(g_hm_pixel_pow)); json_object_object_add(request, "x-current", json_object_new_int64(g_x_current)); - const char *request_str = json_object_to_json_string(request); + std::string request_str = json_object_to_json_string(request); - log_info("Sending request to server: %s", request_str); + log_info("Sending request to server: %s", request_str.c_str()); int socket_fd = socket(AF_INET, SOCK_STREAM, 0); - struct sockaddr_in socket_addr; - memset(&socket_addr, 0, sizeof(struct sockaddr_in)); + sockaddr_in socket_addr; + memset(&socket_addr, 0, sizeof(sockaddr_in)); socket_addr.sin_family = AF_INET; socket_addr.sin_port = htons(PORT); inet_pton(AF_INET, IP, &socket_addr.sin_addr); - if (connect(socket_fd, (struct sockaddr *)&socket_addr, sizeof(struct sockaddr_in))) assert(false); + if (connect(socket_fd, (sockaddr *)&socket_addr, sizeof(sockaddr_in))) assert(false); json_object_to_fd(socket_fd, request, 0); shutdown(socket_fd, SHUT_WR); - struct json_object *response = json_object_from_fd(socket_fd); - const char *response_str = json_object_to_json_string(response); - log_info("Server responded with: %s", response_str); + json_object *response = json_object_from_fd(socket_fd); + std::string response_str = json_object_to_json_string(response); + log_info("Server responded with: %s", response_str.c_str()); mtx_lock(&g_fetching_mutex); @@ -267,31 +368,38 @@ void data_fetch(void) { if (g_trace_map.contains(key)) { for (size_t i = 0; i < json_object_array_length(value); i++) { ImS64 point = json_object_get_int64(json_object_array_get_idx(value, i)); - g_trace_map.at(key).push_back(point); + g_trace_map[key]->push_back(point); + } + } + + if (std::string(key) == g_x_axes[g_x_axis]) { + for (size_t i = 0; i < json_object_array_length(value); i++) { + ImS64 point = json_object_get_int64(json_object_array_get_idx(value, i)); + g_x_axis_normal.push_back((double)point); } } } - g_x_current = g_trace_map.at(g_x_axes[g_x_axis]).back(); + g_x_current = g_trace_map[g_x_axes[g_x_axis]]->back(); json_object_put(request); json_object_put(response); - g_trace_len = g_trace_map.at("rowid").size(); - - if (g_trace_len >= g_entries * 2) { - for (auto &trace : g_trace_map) { - trace.second.erase(trace.second.begin(), trace.second.end() - g_entries); - } +#if !defined(NDEBUG) + data_validate_traces(); +#endif - g_trace_len = g_trace_map.at("rowid").size(); + if ((int64_t)g_traces[0]->size() >= g_entries * 2) { + for (auto &trace : g_traces) trace->trim(); + g_x_axis_normal.trim(); } - g_trace_offset = 0; +#if !defined(NDEBUG) + data_validate_traces(); +#endif - if (g_trace_len > g_entries) { - g_trace_offset = g_trace_len - g_entries; - g_trace_len = g_entries; - } + int64_t current_size = g_traces[0]->size(); + g_trace_len = std::min(current_size, g_entries); + g_trace_offset = current_size > g_entries ? current_size - g_entries : 0l; mtx_unlock(&g_fetching_mutex); } @@ -331,11 +439,10 @@ void data_stop_fetching(void) { // ---------------------------------------------------------------------------- // GUI functions // ---------------------------------------------------------------------------- -void gui_render_data_input(const char *label, int64_t *target) { - assert(label); +void gui_render_data_input(std::string label, int64_t *target) { assert(target); - if (ImGui::InputScalar(label, ImGuiDataType_U64, target, nullptr, nullptr, "%#lx")) { + if (ImGui::InputScalar(label.c_str(), ImGuiDataType_U64, target, nullptr, nullptr, "%#lx")) { data_on_field_change(); } } @@ -371,9 +478,9 @@ void gui_render_data_col(void) { gui_render_data_input("entries", &g_entries); gui_render_data_input("nth", &g_nth); - if (ImGui::BeginCombo("x-axis", g_x_axes[g_x_axis])) { + if (ImGui::BeginCombo("x-axis", g_x_axes[g_x_axis].c_str())) { for (int i = 0; i < CORES + 2; i++) { - if (ImGui::Selectable(g_x_axes[i], g_x_axis == i)) { + if (ImGui::Selectable(g_x_axes[i].c_str(), g_x_axis == i)) { data_reset_fields(); g_x_axis = i; } @@ -392,7 +499,7 @@ void gui_render_data_col(void) { case STATUS_STOPPING: ImGui::LabelText("entries", "%#lx", g_entries); ImGui::LabelText("nth", "%#lx", g_nth); - ImGui::LabelText("x-axis", "%s", g_x_axes[g_x_axis]); + ImGui::LabelText("x-axis", "%s", g_x_axes[g_x_axis].c_str()); ImGui::LabelText("x-low", "%#lx", g_x_low); ImGui::LabelText("x-high", "%#lx", g_x_high); ImGui::LabelText("hm-left", "%#lx", g_hm_left); @@ -428,7 +535,17 @@ void gui_render_data_col(void) { ImGui::End(); } -void gui_render_plot(const Plot *plot, const ImVec2 &frame_size=ImVec2(-1.f, 0.f)) { +int gui_plot_cell_index(int col, int row) { + int index = col * PLOT_MAX_COLS + row; + assert(index < (int)g_plot_cells.size()); + assert(index < (int)g_plot_cells_top.size()); + assert(index < (int)g_plot_cells_bottom.size()); + return index; +} + +void gui_render_plot(Plot *plot, const ImVec2 &frame_size=ImVec2(-1.f, 0.f)) { + assert(plot); + int plot_flags = ImPlotFlags_NoMenus; int axis_flags = ImPlotAxisFlags_NoMenus; @@ -438,23 +555,19 @@ void gui_render_plot(const Plot *plot, const ImVec2 &frame_size=ImVec2(-1.f, 0.f axis_flags |= ImPlotAxisFlags_NoHighlight; } - if (ImPlot::BeginPlot(plot->name, frame_size, plot_flags)) { + if (ImPlot::BeginPlot(plot->m_name.c_str(), frame_size, plot_flags)) { ImPlot::SetupAxes(nullptr, nullptr, axis_flags, axis_flags); - ImS64 *x = g_trace_map.at(g_x_axes[g_x_axis]).data() + g_trace_offset; - - for (auto &trace : plot->traces) { - ImS64 *y = g_trace_map.at(trace).data() + g_trace_offset; - ImPlot::PlotLine(trace, x, y, g_trace_len); - } - + plot->render(); ImPlot::EndPlot(); } } void gui_render_plots(void) { - const char *section_current = g_plots[0].section; - const char *section_next = nullptr; - bool plots_covered[PLOT_COUNT] = { 0 }; + std::string section_current = g_plots[0]->m_section; + std::string section_next; + + g_plots_covered.clear(); + g_plots_covered.resize(g_plots.size(), false); const ImGuiViewport *viewport = ImGui::GetMainViewport(); const ImVec2 win_pos = g_data_col_visible ? ImVec2(g_data_col_width, viewport->Pos.y) : viewport->Pos; @@ -476,40 +589,40 @@ void gui_render_plots(void) { mtx_lock(&g_fetching_mutex); - while (section_current) { - ImGui::SeparatorText(section_current); + while (section_current.length()) { + ImGui::SeparatorText(section_current.c_str()); ImGui::BeginTable("plots-table", g_plot_cols); - for (size_t i = 0; i < PLOT_COUNT; i++) { - if (g_plots[i].section != section_current) { - section_next = (!section_next && !plots_covered[i]) ? g_plots[i].section : section_next; + for (size_t i = 0; i < g_plots.size(); i++) { + if (g_plots[i]->m_section != section_current) { + section_next = (!section_next.length() && !g_plots_covered[i]) ? g_plots[i]->m_section : section_next; continue; } ImGui::TableNextColumn(); - g_plot_cells[col][row] = &g_plots[i]; - g_plot_cells_top[col][row] = ImGui::GetCursorPosY(); + g_plot_cells[gui_plot_cell_index(col, row)] = g_plots[i]; + g_plot_cells_top[gui_plot_cell_index(col, row)] = ImGui::GetCursorPosY(); - if (&g_plots[i] == g_plot_selected) { + if (g_plots[i] == g_plot_selected) { g_plot_col_selected = col; g_plot_row_selected = row; g_implot_style->Colors[ImPlotCol_FrameBg] = g_imgui_style->Colors[ImGuiCol_FrameBg]; } - gui_render_plot(&g_plots[i]); + gui_render_plot(g_plots[i]); - if (&g_plots[i] == g_plot_selected) { + if (g_plots[i] == g_plot_selected) { g_implot_style->Colors[ImPlotCol_FrameBg] = COLOR_BLACK; } - g_plot_cells_bottom[col][row] = ImGui::GetCursorPosY(); + g_plot_cells_bottom[gui_plot_cell_index(col, row)] = ImGui::GetCursorPosY(); col = (col + 1) % g_plot_cols; row += col ? 0 : 1; - plots_covered[i] = true; + g_plots_covered[i] = true; } section_current = section_next; - section_next = nullptr; + section_next = std::string(); ImGui::EndTable(); row += col ? 1 : 0; col = 0; @@ -533,8 +646,8 @@ void gui_render_plot_maximized(void) { void gui_plot_queue_scroll(int col_selected, int row_selected) { const ImGuiViewport *viewport = ImGui::GetMainViewport(); - float plot_top = g_plot_cells_top[col_selected][row_selected]; - float plot_bottom = g_plot_cells_bottom[col_selected][row_selected]; + float plot_top = g_plot_cells_top[gui_plot_cell_index(col_selected, row_selected)]; + float plot_bottom = g_plot_cells_bottom[gui_plot_cell_index(col_selected, row_selected)]; float win_top = g_plot_scroll_current; float win_bottom = win_top + viewport->Size.y; @@ -555,17 +668,14 @@ void gui_render(void) { return; } - if (g_data_col_visible) { - gui_render_data_col(); - } - + if (g_data_col_visible) gui_render_data_col(); gui_render_plots(); } // ---------------------------------------------------------------------------- // Main functions // ---------------------------------------------------------------------------- -void win_sig_handler(int signo) { +void app_sig_handler(int signo) { (void)signo; log_warn("Signal received, will stop SALIS data client..."); @@ -577,11 +687,11 @@ void win_sig_handler(int signo) { glfwSetWindowShouldClose(g_window, GLFW_TRUE); } -void win_error_callback(int error, const char* description) { +void app_error_callback(int error, const char* description) { log_warn("GLFW error %d: %s", error, description); } -void win_key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) { +void app_key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) { (void)window; (void)scancode; @@ -626,20 +736,20 @@ void win_key_callback(GLFWwindow* window, int key, int scancode, int action, int switch (key) { case GLFW_KEY_LEFT: g_plot_col_selected -= g_plot_col_selected ? 1 : 0; - g_plot_selected = g_plot_cells[g_plot_col_selected][g_plot_row_selected]; + g_plot_selected = g_plot_cells[gui_plot_cell_index(g_plot_col_selected, g_plot_row_selected)]; break; case GLFW_KEY_RIGHT: - g_plot_col_selected += (g_plot_col_selected < PLOT_MAX_COLS - 1 && g_plot_cells[g_plot_col_selected + 1][g_plot_row_selected]) ? 1 : 0; - g_plot_selected = g_plot_cells[g_plot_col_selected][g_plot_row_selected]; + g_plot_col_selected += (g_plot_col_selected < PLOT_MAX_COLS - 1 && g_plot_cells[gui_plot_cell_index(g_plot_col_selected + 1, g_plot_row_selected)]) ? 1 : 0; + g_plot_selected = g_plot_cells[gui_plot_cell_index(g_plot_col_selected, g_plot_row_selected)]; break; case GLFW_KEY_UP: - g_plot_row_selected -= g_plot_row_selected ? 1 : 0; - g_plot_selected = g_plot_cells[g_plot_col_selected][g_plot_row_selected]; + g_plot_row_selected -= (g_plot_row_selected && g_plot_cells[gui_plot_cell_index(g_plot_col_selected, g_plot_row_selected - 1)]) ? 1 : 0; + g_plot_selected = g_plot_cells[gui_plot_cell_index(g_plot_col_selected, g_plot_row_selected)]; gui_plot_queue_scroll(g_plot_col_selected, g_plot_row_selected); break; case GLFW_KEY_DOWN: - g_plot_row_selected += (g_plot_row_selected < (int)PLOT_COUNT - 1 && g_plot_cells[g_plot_col_selected][g_plot_row_selected + 1]) ? 1 : 0; - g_plot_selected = g_plot_cells[g_plot_col_selected][g_plot_row_selected]; + g_plot_row_selected += (g_plot_row_selected < (int)g_plots.size() - 1 && g_plot_cells[gui_plot_cell_index(g_plot_col_selected, g_plot_row_selected + 1)]) ? 1 : 0; + g_plot_selected = g_plot_cells[gui_plot_cell_index(g_plot_col_selected, g_plot_row_selected)]; gui_plot_queue_scroll(g_plot_col_selected, g_plot_row_selected); break; case GLFW_KEY_F: @@ -662,24 +772,21 @@ void win_key_callback(GLFWwindow* window, int key, int scancode, int action, int } } -int main(int argc, char **argv) { - (void)argc; - (void)argv; - - signal(SIGINT, win_sig_handler); - signal(SIGTERM, win_sig_handler); +void init() { + signal(SIGINT, app_sig_handler); + signal(SIGTERM, app_sig_handler); log_info("Starting SALIS data client"); log_info("Initializing GLFW"); - glfwSetErrorCallback(win_error_callback); + glfwSetErrorCallback(app_error_callback); glfwInitHint(GLFW_WAYLAND_LIBDECOR, GLFW_WAYLAND_DISABLE_LIBDECOR); if (!glfwInit()) assert(false); float scale = ImGui_ImplGlfw_GetContentScaleForMonitor(glfwGetPrimaryMonitor()); g_window = glfwCreateWindow((int)(800 * scale), (int)(600 * scale), "SALIS data client", nullptr, nullptr); assert(g_window); - glfwSetKeyCallback(g_window, win_key_callback); + glfwSetKeyCallback(g_window, app_key_callback); glfwMakeContextCurrent(g_window); glfwSwapInterval(1); // enable vsync @@ -689,7 +796,7 @@ int main(int argc, char **argv) { ImPlot::CreateContext(); g_imgui_io = &ImGui::GetIO(); - g_imgui_io->Fonts->AddFontFromFileTTF(FONT_SOURCE); + g_imgui_io->Fonts->AddFontDefaultVector(); g_imgui_io->IniFilename = nullptr; g_imgui_style = &ImGui::GetStyle(); @@ -705,15 +812,24 @@ int main(int argc, char **argv) { ImGui_ImplGlfw_InitForOpenGL(g_window, true); ImGui_ImplOpenGL3_Init(GLSL_VERSION); - for (auto &i : g_traces) { - g_trace_map[i] = {}; - g_trace_map[i].reserve(g_entries); - } + for (auto &trace : g_core_traces) g_traces.push_back(&trace); + for (auto &trace : g_arch_traces) g_traces.push_back(&trace); + for (auto &plot : g_core_plots) g_plots.push_back(&plot); + for (auto &plot : g_arch_plots) g_plots.push_back(&plot); + for (auto &plot : g_arch_plots_stacked) g_plots.push_back(&plot); + for (auto &i : g_traces) g_trace_map[i->m_name] = i; + + g_plot_cells = std::vector(g_plots.size() * PLOT_MAX_COLS); + g_plot_cells_top = std::vector(g_plots.size() * PLOT_MAX_COLS); + g_plot_cells_bottom = std::vector(g_plots.size() * PLOT_MAX_COLS); + g_plot_selected = g_plots[0]; g_hm_pixel_pow = data_max_hm_pixel_pow(); mtx_init(&g_fetching_mutex, mtx_plain); +} +void exec() { while (!glfwWindowShouldClose(g_window)) { glfwPollEvents(); @@ -733,7 +849,9 @@ int main(int argc, char **argv) { ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); glfwSwapBuffers(g_window); } +} +void quit() { mtx_destroy(&g_fetching_mutex); ImGui_ImplOpenGL3_Shutdown(); @@ -744,6 +862,15 @@ int main(int argc, char **argv) { log_info("Stopping SALIS data client"); glfwDestroyWindow(g_window); glfwTerminate(); +} + +int main(int argc, char **argv) { + (void)argc; + (void)argv; + + init(); + exec(); + quit(); return 0; } -- cgit v1.2.1