diff --git a/src/btop.cpp b/src/btop.cpp index ce4e5c7..5001126 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -683,10 +683,7 @@ namespace Runner { "box"_a = "box", "collect"_a = "collect", "draw"_a = "draw", "post"_a = Theme::c("main_fg") + Fx::ub ); -<<<<<<< HEAD static auto loc = std::locale(std::locale::classic(), new MyNumPunct); -======= ->>>>>>> 48c3392 (Merged changes from main) for (const string name : {"cpu", "mem", "net", "proc", "gpu", "total"}) { if (not debug_times.contains(name)) debug_times[name] = {0,0}; const auto& [time_collect, time_draw] = debug_times.at(name); diff --git a/src/btop_config.cpp b/src/btop_config.cpp index 4f7bb3e..4c29af6 100644 --- a/src/btop_config.cpp +++ b/src/btop_config.cpp @@ -72,6 +72,8 @@ namespace Config { {"graph_symbol_cpu", "# Graph symbol to use for graphs in cpu box, \"default\", \"braille\", \"block\" or \"tty\"."}, + {"graph_symbol_gpu", "# Graph symbol to use for graphs in gpu box, \"default\", \"braille\", \"block\" or \"tty\"."}, + {"graph_symbol_mem", "# Graph symbol to use for graphs in cpu box, \"default\", \"braille\", \"block\" or \"tty\"."}, {"graph_symbol_net", "# Graph symbol to use for graphs in cpu box, \"default\", \"braille\", \"block\" or \"tty\"."}, @@ -190,7 +192,19 @@ namespace Config { {"selected_battery", "#* Which battery to use if multiple are present. \"Auto\" for auto detection."}, {"log_level", "#* Set loglevel for \"~/.config/btop/btop.log\" levels are: \"ERROR\" \"WARNING\" \"INFO\" \"DEBUG\".\n" - "#* The level set includes all lower levels, i.e. \"DEBUG\" will show all logging info."} + "#* The level set includes all lower levels, i.e. \"DEBUG\" will show all logging info."}, + + {"nvml_measure_pcie_speeds", + "#* Measure PCIe throughput on NVIDIA cards, may impact performance on certain cards."}, + + {"gpu_mirror_graph", "#* Horizontally mirror the GPU graph."}, + + {"custom_gpu_name0", "#* Custom gpu0 model name, empty string to disable."}, + {"custom_gpu_name1", "#* Custom gpu1 model name, empty string to disable."}, + {"custom_gpu_name2", "#* Custom gpu2 model name, empty string to disable."}, + {"custom_gpu_name3", "#* Custom gpu3 model name, empty string to disable."}, + {"custom_gpu_name4", "#* Custom gpu4 model name, empty string to disable."}, + {"custom_gpu_name5", "#* Custom gpu5 model name, empty string to disable."}, }; unordered_flat_map strings = { @@ -199,6 +213,7 @@ namespace Config { {"graph_symbol", "braille"}, {"presets", "cpu:1:default,proc:0:default cpu:0:default,mem:0:default,net:0:default cpu:0:block,net:0:tty"}, {"graph_symbol_cpu", "default"}, + {"graph_symbol_gpu", "default"}, {"graph_symbol_mem", "default"}, {"graph_symbol_net", "default"}, {"graph_symbol_proc", "default"}, @@ -218,6 +233,12 @@ namespace Config { {"proc_filter", ""}, {"proc_command", ""}, {"selected_name", ""}, + {"custom_gpu_name0", ""}, + {"custom_gpu_name1", ""}, + {"custom_gpu_name2", ""}, + {"custom_gpu_name3", ""}, + {"custom_gpu_name4", ""}, + {"custom_gpu_name5", ""}, }; unordered_flat_map stringsTmp; @@ -266,6 +287,8 @@ namespace Config { {"lowcolor", false}, {"show_detailed", false}, {"proc_filtering", false}, + {"nvml_measure_pcie_speeds", true}, + {"gpu_mirror_graph", true}, }; unordered_flat_map boolsTmp; diff --git a/src/btop_draw.cpp b/src/btop_draw.cpp index 9ebd40c..b049f1c 100644 --- a/src/btop_draw.cpp +++ b/src/btop_draw.cpp @@ -29,6 +29,7 @@ tab-size = 4 #include #include #include +#include using std::array; using std::clamp; @@ -862,7 +863,7 @@ namespace Gpu { vector x_vec = {}, y_vec = {}, b_height_vec = {}; int b_width; vector b_x_vec = {}, b_y_vec = {}; - vector redraw = {}, mid_line = {}; + vector redraw = {}; int shown = 0; vector shown_panels = {}; int graph_up_height; @@ -893,16 +894,16 @@ namespace Gpu { bool show_temps = gpu.supported_functions.temp_info and (Config::getB("check_temp")); auto tty_mode = Config::getB("tty_mode"); auto& temp_scale = Config::getS("temp_scale"); - auto& graph_symbol = (tty_mode ? "tty" : Config::getS("graph_symbol_cpu")); // TODO graph_symbol_gpu + auto& graph_symbol = (tty_mode ? "tty" : Config::getS("graph_symbol_gpu")); auto& graph_bg = Symbols::graph_symbols.at((graph_symbol == "default" ? Config::getS("graph_symbol") + "_up" : graph_symbol + "_up")).at(6); - auto single_graph = Config::getB("cpu_single_graph"); + auto single_graph = !Config::getB("gpu_mirror_graph"); string out; out.reserve(width * height); //* Redraw elements not needed to be updated every cycle if (redraw[index]) { graph_up_height = single_graph ? height - 2 : ceil((double)(height - 2) / 2); - const int graph_low_height = height - 2 - graph_up_height - (mid_line[index] ? 1 : 0); + const int graph_low_height = height - 2 - graph_up_height; out += box[index]; if (gpu.supported_functions.gpu_utilization) { @@ -935,7 +936,7 @@ namespace Gpu { if (gpu.supported_functions.gpu_utilization) { out += Fx::ub + Mv::to(y + 1, x + 1) + graph_upper(gpu.gpu_percent.at("gpu-totals"), (data_same or redraw[index])); if (not single_graph) - out += Mv::to(y + graph_up_height + 1 + mid_line[index], x + 1) + graph_lower(gpu.gpu_percent.at("gpu-totals"), (data_same or redraw[index])); + out += Mv::to(y + graph_up_height + 1, x + 1) + graph_lower(gpu.gpu_percent.at("gpu-totals"), (data_same or redraw[index])); out += Mv::to(b_y + 1, b_x + 1) + Theme::c("main_fg") + Fx::b + "GPU " + gpu_meter(gpu.gpu_percent.at("gpu-totals").back()) + Theme::g("cpu").at(gpu.gpu_percent.at("gpu-totals").back()) + rjust(to_string(gpu.gpu_percent.at("gpu-totals").back()), 4) + Theme::c("main_fg") + '%'; @@ -950,7 +951,7 @@ namespace Gpu { out += Theme::c("div_line") + Symbols::v_line; } - if (gpu.supported_functions.gpu_clock and Config::getB("show_cpu_freq")) { // TODO show_gpu_freq + if (gpu.supported_functions.gpu_clock) { string clock_speed_string = to_string(gpu.gpu_clock_speed); out += Mv::to(b_y, b_x + b_width - 12) + Theme::c("div_line") + Symbols::h_line*(5-clock_speed_string.size()) + Symbols::title_left + Fx::b + Theme::c("title") + clock_speed_string + " Mhz" + Fx::ub + Theme::c("div_line") + Symbols::title_right; @@ -988,19 +989,18 @@ namespace Gpu { + Mv::l(b_width/2-1) + Mv::u(1) + rjust(to_string(gpu.mem_utilization_percent.back()), 3) + '%'; //? Memory clock speed - if (gpu.supported_functions.mem_clock and Config::getB("show_cpu_freq")) { // TODO show_gpu_freq + if (gpu.supported_functions.mem_clock) { string clock_speed_string = to_string(gpu.mem_clock_speed); out += Mv::to(b_y + 3, b_x + b_width/2 - 11) + Theme::c("div_line") + Symbols::h_line*(5-clock_speed_string.size()) + Symbols::title_left + Fx::b + Theme::c("title") + clock_speed_string + " Mhz" + Fx::ub + Theme::c("div_line") + Symbols::title_right; } } else { out += Theme::c("main_fg") + Mv::r(1); - bool clock_shown = gpu.supported_functions.mem_clock and Config::getB("show_cpu_freq"); // TODO show_gpu_freq if (gpu.supported_functions.mem_total) - out += "VRAM total:" + rjust(floating_humanizer(gpu.mem_total), b_width/(1 + clock_shown)-14); - else out += "VRAM usage:" + rjust(floating_humanizer(gpu.mem_used), b_width/(1 + clock_shown)-14); + out += "VRAM total:" + rjust(floating_humanizer(gpu.mem_total), b_width/(1 + gpu.supported_functions.mem_clock)-14); + else out += "VRAM usage:" + rjust(floating_humanizer(gpu.mem_used), b_width/(1 + gpu.supported_functions.mem_clock)-14); - if (clock_shown) + if (gpu.supported_functions.mem_clock) out += " VRAM clock:" + rjust(to_string(gpu.mem_clock_speed) + " Mhz", b_width/2-13); } } @@ -1010,7 +1010,7 @@ namespace Gpu { // + Symbols::title_right + Symbols::h_line*(b_width/2-12) + Symbols::div_down + Symbols::h_line*(b_width/2-2) + Symbols::div_right; //? PCIe link throughput - if (gpu.supported_functions.pcie_txrx) { + if (gpu.supported_functions.pcie_txrx and Config::getB("nvml_measure_pcie_speeds")) { string tx_string = floating_humanizer(gpu.pcie_tx, 0, 1, 0, 1); string rx_string = floating_humanizer(gpu.pcie_rx, 0, 1, 0, 1); out += Mv::to(b_y + b_height_vec[index] - 1, b_x+2) + Theme::c("div_line") @@ -1988,7 +1988,6 @@ namespace Draw { gpu_meter_vec.resize(shown); pwr_meter_vec.resize(shown); redraw.resize(shown); - mid_line.resize(shown); for (auto i = 0; i < shown; ++i) { redraw[i] = true; @@ -2014,7 +2013,10 @@ namespace Draw { b_x_vec[i] = x_vec[i] + width - b_width - 1; b_y_vec[i] = y_vec[i] + ceil((double)(height - 2) / 2) - ceil((double)(b_height_vec[i]) / 2) + 1; - box[i] += createBox(b_x_vec[i], b_y_vec[i], b_width, b_height_vec[i], "", false, gpu_names[shown_panels[i]].substr(0, b_width-5)); + string name = Config::getS(std::string("custom_gpu_name") + (char)(shown_panels[i]+'0')); + if (name.empty()) name = gpu_names[shown_panels[i]]; + + box[i] += createBox(b_x_vec[i], b_y_vec[i], b_width, b_height_vec[i], "", false, name.substr(0, b_width-5)); } } diff --git a/src/btop_menu.cpp b/src/btop_menu.cpp index 343fbca..7bc2b0a 100644 --- a/src/btop_menu.cpp +++ b/src/btop_menu.cpp @@ -319,23 +319,43 @@ namespace Menu { {"cpu_graph_upper", "Cpu upper graph.", "", - "Sets the CPU stat shown in upper half of", + "Sets the CPU/GPU stat shown in upper half of", "the CPU graph.", "", + "CPU:", "\"total\" = Total cpu usage.", "\"user\" = User mode cpu usage.", "\"system\" = Kernel mode cpu usage.", - "+ more depending on kernel."}, + "+ more depending on kernel.", + "", + "GPU:", + "\"gpu-totals\" = GPU usage split by device.", + "\"gpu-vram-totals\" = VRAM usage split by GPU.", + "\"gpu-pwr-totals\" = Power usage split by GPU.", + "\"gpu-average\" = Avg usage of all GPUs.", + "\"gpu-vram-total\" = VRAM usage of all GPUs.", + "\"gpu-pwr-total\" = Power usage of all GPUs.", + "Not all stats are supported on all devices."}, {"cpu_graph_lower", "Cpu lower graph.", "", - "Sets the CPU stat shown in lower half of", + "Sets the CPU/GPU stat shown in lower half of", "the CPU graph.", "", + "CPU:", "\"total\" = Total cpu usage.", "\"user\" = User mode cpu usage.", "\"system\" = Kernel mode cpu usage.", - "+ more depending on kernel."}, + "+ more depending on kernel.", + "", + "GPU:", + "\"gpu-totals\" = GPU usage split by device.", + "\"gpu-vram-totals\" = VRAM usage split by GPU.", + "\"gpu-pwr-totals\" = Power usage split by GPU.", + "\"gpu-average\" = Avg usage of all GPUs.", + "\"gpu-vram-total\" = VRAM usage of all GPUs.", + "\"gpu-pwr-total\" = Power usage of all GPUs.", + "Not all stats are supported on all devices."}, {"cpu_invert_lower", "Toggles orientation of the lower CPU graph.", "", @@ -352,7 +372,7 @@ namespace Menu { "", "True or False."}, {"cpu_sensor", - "Cpu temperature sensor", + "Cpu temperature sensor.", "", "Select the sensor that corresponds to", "your cpu temperature.", @@ -392,7 +412,7 @@ namespace Menu { "Rankine, 0 = abosulte zero, 1 degree change", "equals 1 degree change in Fahrenheit."}, {"show_cpu_freq", - "Show CPU frequency", + "Show CPU frequency.", "", "Can cause slowdowns on systems with many", "cores and certain kernel versions."}, @@ -408,6 +428,48 @@ namespace Menu { "", "True or False."}, }, + { + {"nvml_measure_pcie_speeds", + "Measure PCIe throughput on NVIDIA cards.", + "", + "May impact performance on certain cards.", + "", + "True or False."}, + {"graph_symbol_gpu", + "Graph symbol to use for graphs in gpu box.", + "", + "\"default\", \"braille\", \"block\" or \"tty\".", + "", + "\"default\" for the general default symbol.",}, + {"gpu_mirror_graph", + "Horizontally mirror the GPU graph.", + "", + "True or False."}, + {"custom_gpu_name0", + "Custom gpu0 model name in gpu stats box.", + "", + "Empty string to disable."}, + {"custom_gpu_name1", + "Custom gpu1 model name in gpu stats box.", + "", + "Empty string to disable."}, + {"custom_gpu_name2", + "Custom gpu2 model name in gpu stats box.", + "", + "Empty string to disable."}, + {"custom_gpu_name3", + "Custom gpu3 model name in gpu stats box.", + "", + "Empty string to disable."}, + {"custom_gpu_name4", + "Custom gpu4 model name in gpu stats box.", + "", + "Empty string to disable."}, + {"custom_gpu_name5", + "Custom gpu5 model name in gpu stats box.", + "", + "Empty string to disable."}, + }, { {"mem_below_net", "Mem box location.", @@ -1027,6 +1089,7 @@ namespace Menu { {"proc_sorting", std::cref(Proc::sort_vector)}, {"graph_symbol", std::cref(Config::valid_graph_symbols)}, {"graph_symbol_cpu", std::cref(Config::valid_graph_symbols_def)}, + {"graph_symbol_gpu", std::cref(Config::valid_graph_symbols_def)}, {"graph_symbol_mem", std::cref(Config::valid_graph_symbols_def)}, {"graph_symbol_net", std::cref(Config::valid_graph_symbols_def)}, {"graph_symbol_proc", std::cref(Config::valid_graph_symbols_def)}, @@ -1085,7 +1148,8 @@ namespace Menu { const auto& option = categories[selected_cat][item_height * page + selected][0]; if (selPred.test(isString) and Config::stringValid(option, editor.text)) { Config::set(option, editor.text); - if (option == "custom_cpu_name") screen_redraw = true; + if (option == "custom_cpu_name" or option.rfind("custom_gpu_name", 0) == 0) + screen_redraw = true; else if (is_in(option, "shown_boxes", "presets")) { screen_redraw = true; Config::current_preset = -1; @@ -1166,7 +1230,7 @@ namespace Menu { if (--selected_cat < 0) selected_cat = (int)categories.size() - 1; page = selected = 0; } - else if (is_in(key, "1", "2", "3", "4", "5") or key.starts_with("select_cat_")) { + else if (is_in(key, "1", "2", "3", "4", "5", "6") or key.starts_with("select_cat_")) { selected_cat = key.back() - '0' - 1; page = selected = 0; } @@ -1264,11 +1328,11 @@ namespace Menu { //? Category buttons out += Mv::to(y+7, x+4); - for (int i = 0; const auto& m : {"general", "cpu", "mem", "net", "proc"}) { + for (int i = 0; const auto& m : {"general", "cpu", "gpu", "mem", "net", "proc"}) { out += Fx::b + (i == selected_cat ? Theme::c("hi_fg") + '[' + Theme::c("title") + m + Theme::c("hi_fg") + ']' : Theme::c("hi_fg") + to_string(i + 1) + Theme::c("title") + m + ' ') - + Mv::r(10); + + Mv::r(7); if (string button_name = "select_cat_" + to_string(i + 1); not editing and not mouse_mappings.contains(button_name)) mouse_mappings[button_name] = {y+6, x+2 + 15*i, 3, 15}; i++; diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index 6692923..26b576c 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -1071,7 +1071,7 @@ namespace Gpu { } //? PCIe link speeds, the data collection takes >=20ms each call so they run on separate threads - if (gpus_slice[i].supported_functions.pcie_txrx) { + if (gpus_slice[i].supported_functions.pcie_txrx and (Config::getB("nvml_measure_pcie_speeds") or is_init)) { pcie_tx_thread = std::thread([gpus_slice, i]() { unsigned int tx; nvmlReturn_t result = nvmlDeviceGetPcieThroughput(devices[i], NVML_PCIE_UTIL_TX_BYTES, &tx); @@ -1196,7 +1196,7 @@ namespace Gpu { if constexpr(is_init) { // there doesn't seem to be a better way to do this, but this should be fine considering it's just 2 lines pcie_tx_thread.join(); pcie_rx_thread.join(); - } else if (gpus_slice[i].supported_functions.pcie_txrx) { + } else if (gpus_slice[i].supported_functions.pcie_txrx and Config::getB("nvml_measure_pcie_speeds")) { pcie_tx_thread.join(); pcie_rx_thread.join(); }