From bfb7316127eccdba3f768ac09798f5a5de698058 Mon Sep 17 00:00:00 2001 From: TheSovietPancakes Date: Tue, 25 Nov 2025 22:26:47 -0600 Subject: [PATCH 1/2] Fixed GPU rendering --- src/btop_draw.cpp | 62 ++++++++++++++++++++++++++++----------------- src/btop_shared.hpp | 2 +- src/btop_tools.cpp | 3 ++- 3 files changed, 42 insertions(+), 25 deletions(-) diff --git a/src/btop_draw.cpp b/src/btop_draw.cpp index 476eaf2e..b0c11506 100644 --- a/src/btop_draw.cpp +++ b/src/btop_draw.cpp @@ -971,8 +971,8 @@ namespace Cpu { #ifdef GPU_SUPPORT namespace Gpu { int width_p = 100, height_p = 32; - int min_width = 41, min_height = 11; - int width = 41, height; + int min_width = 41, min_height = 8; + int width = 41, total_height; vector x_vec = {}, y_vec = {}, b_height_vec = {}; int b_width; vector b_x_vec = {}, b_y_vec = {}; @@ -1014,14 +1014,16 @@ namespace 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("gpu_mirror_graph"); string out; + int height = gpu_b_height_offsets[index] + 4; 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; out += box[index]; + graph_up_height = single_graph ? b_height_vec[index] : max(0, b_y - y - 1); + const int graph_low_height = single_graph ? 0 : max(0, (y + b_height_vec[index] - 1) - (b_y + b_height_vec[index]) - 1); + if (gpu.supported_functions.gpu_utilization) { graph_upper = Draw::Graph{x + width - b_width - 3, graph_up_height, "cpu", safeVal(gpu.gpu_percent, "gpu-totals"s), graph_symbol, false, true}; // TODO cpu -> gpu if (not single_graph) { @@ -1049,14 +1051,14 @@ namespace Gpu { //* General GPU info - + int rows_used = 1; //? Gpu graph, meter & clock speed if (gpu.supported_functions.gpu_utilization) { - out += Fx::ub + Mv::to(y + 1, x + 1) + graph_upper(safeVal(gpu.gpu_percent, "gpu-totals"s), (data_same or redraw[index])); + out += Fx::ub + Mv::to(y + rows_used, x + 1) + graph_upper(safeVal(gpu.gpu_percent, "gpu-totals"s), (data_same or redraw[index])); if (not single_graph) out += Mv::to(y + graph_up_height + 1, x + 1) + graph_lower(safeVal(gpu.gpu_percent, "gpu-totals"s), (data_same or redraw[index])); - out += Mv::to(b_y + 1, b_x + 1) + Theme::c("main_fg") + Fx::b + "GPU " + gpu_meter(safeVal(gpu.gpu_percent, "gpu-totals"s).back()) + out += Mv::to(b_y + rows_used, b_x + 1) + Theme::c("main_fg") + Fx::b + "GPU " + gpu_meter(safeVal(gpu.gpu_percent, "gpu-totals"s).back()) + Theme::g("cpu").at(clamp(safeVal(gpu.gpu_percent, "gpu-totals"s).back(), 0ll, 100ll)) + rjust(to_string(safeVal(gpu.gpu_percent, "gpu-totals"s).back()), 5) + Theme::c("main_fg") + '%'; //? Temperature graph, I assume the device supports utilization if it supports temperature @@ -1067,6 +1069,7 @@ namespace Gpu { out += rjust(to_string(temp), 4) + Theme::c("main_fg") + unit; } out += Theme::c("div_line") + Symbols::v_line; + rows_used++; } if (gpu.supported_functions.gpu_clock) { @@ -1077,24 +1080,26 @@ namespace Gpu { //? Power usage meter, power state if (gpu.supported_functions.pwr_usage) { - out += Mv::to(b_y + 2, b_x + 1) + Theme::c("main_fg") + Fx::b + "PWR " + pwr_meter(safeVal(gpu.gpu_percent, "gpu-pwr-totals"s).back()) + out += Mv::to(b_y + rows_used, b_x + 1) + Theme::c("main_fg") + Fx::b + "PWR " + pwr_meter(safeVal(gpu.gpu_percent, "gpu-pwr-totals"s).back()) + Theme::g("cached").at(clamp(safeVal(gpu.gpu_percent, "gpu-pwr-totals"s).back(), 0ll, 100ll)) + fmt::format("{:>5.{}f}", gpu.pwr_usage / 1000.0, gpu.pwr_usage < 10'000 ? 2 : gpu.pwr_usage < 100'000 ? 1 : 0) + Theme::c("main_fg") + 'W'; if (gpu.supported_functions.pwr_state and gpu.pwr_state != 32) // NVML_PSTATE_UNKNOWN; unsupported or non-nvidia card out += std::string(" P-state: ") + (gpu.pwr_state > 9 ? "" : " ") + 'P' + Theme::g("cached").at(clamp(gpu.pwr_state, 0ll, 100ll)) + to_string(gpu.pwr_state); + rows_used++; } //? Encode and Decode meters bool drawnEncDec = gpu.supported_functions.encoder_utilization and gpu.supported_functions.decoder_utilization; if (drawnEncDec) { - out += Mv::to(b_y + 3, b_x +1) + Theme::c("main_fg") + Fx::b + "ENC " + enc_meter(gpu.encoder_utilization) + out += Mv::to(b_y + rows_used, b_x +1) + Theme::c("main_fg") + Fx::b + "ENC " + enc_meter(gpu.encoder_utilization) + Theme::g("cpu").at(clamp(gpu.encoder_utilization, 0ll, 100ll)) + rjust(to_string(gpu.encoder_utilization), 4) + Theme::c("main_fg") + '%' + Theme::c("div_line") + Symbols::v_line + Theme::c("main_fg") + Fx::b + "DEC " + enc_meter(gpu.decoder_utilization) + Theme::g("cpu").at(clamp(gpu.decoder_utilization, 0ll, 100ll)) + rjust(to_string(gpu.decoder_utilization), 4) + Theme::c("main_fg") + '%'; + rows_used++; } if (gpu.supported_functions.mem_total or gpu.supported_functions.mem_used) { - out += Mv::to(b_y + (drawnEncDec ? 4 : 3), b_x); + out += Mv::to(b_y + rows_used, b_x); if (gpu.supported_functions.mem_total and gpu.supported_functions.mem_used) { string used_memory_string = floating_humanizer(gpu.mem_used); @@ -1119,7 +1124,7 @@ namespace Gpu { //? Memory clock speed if (gpu.supported_functions.mem_clock) { string clock_speed_string = to_string(gpu.mem_clock_speed); - out += Mv::to(b_y + (drawnEncDec ? 4 : 3), b_x + b_width/2 - 11) + Theme::c("div_line") + Symbols::h_line*(5-clock_speed_string.size()) + out += Mv::to(b_y + rows_used, 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 { @@ -2093,6 +2098,13 @@ namespace Draw { } Gpu::shown = Gpu::shown_panels.size(); + // Calculate the minimum possible GPU height, store in total_height + // The actual total_height value will of course be overwritten later + Gpu::total_height = 0; + for (int i = 0; i < Gpu::shown; i++) { + using namespace Gpu; + total_height += 4 + gpu_b_height_offsets[shown_panels[i]]; + } #endif Mem::shown = boxes.contains("mem"); Net::shown = boxes.contains("net"); @@ -2102,6 +2114,7 @@ namespace Draw { if (Cpu::shown) { using namespace Cpu; #ifdef GPU_SUPPORT + // inline GPU information int gpus_extra_height = Config::getS("show_gpu_info") == "On" ? Gpu::count : Config::getS("show_gpu_info") == "Auto" ? Gpu::count - Gpu::shown @@ -2111,7 +2124,7 @@ namespace Draw { width = round((double)Term::width * width_p / 100); #ifdef GPU_SUPPORT if (Gpu::shown != 0 and not (Mem::shown or Net::shown or Proc::shown)) { - height = Term::height - Gpu::min_height*Gpu::shown - gpus_extra_height; + height = Term::height - Gpu::total_height - gpus_extra_height; } else { height = max(8, (int)ceil((double)Term::height * (trim(boxes) == "cpu" ? 100 : height_p/(Gpu::shown+1) + (Gpu::shown != 0)*5) / 100)); } @@ -2185,9 +2198,10 @@ namespace Draw { pwr_meter_vec.resize(shown); enc_meter_vec.resize(shown); redraw.resize(shown); + total_height = 0; for (auto i = 0; i < shown; ++i) { redraw[i] = true; - + int height = 0; width = Term::width; if (Cpu::shown) if (not (Mem::shown or Net::shown or Proc::shown)) @@ -2199,21 +2213,23 @@ namespace Draw { else height = max(min_height, (int)ceil((double)Term::height * height_p/Gpu::shown / 100)); + b_height_vec[i] = gpu_b_height_offsets[shown_panels[i]] + 2; height += (height+Cpu::height == Term::height-1); - x_vec[i] = 1; y_vec[i] = 1 + i*height + (not Config::getB("cpu_bottom"))*Cpu::shown*Cpu::height; + height = max(height, b_height_vec[i] + 2); + x_vec[i] = 1; y_vec[i] = 1 + total_height + (not Config::getB("cpu_bottom"))*Cpu::shown*Cpu::height; box[i] = createBox(x_vec[i], y_vec[i], width, height, Theme::c("cpu_box"), true, std::string("gpu") + (char)(shown_panels[i]+'0'), "", (shown_panels[i]+5)%10); // TODO gpu_box - - b_height_vec[i] = 2 + gpu_b_height_offsets[shown_panels[i]]; b_width = clamp(width/2, min_width, 65); + total_height += height; //? Main statistics box 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; + b_y_vec[i] = y_vec[i] + ceil((double)(height - 2) / 2) - ceil((double)b_height_vec[i] / 2) + 1; 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)); + b_height_vec[i] = height - 2; } } #endif @@ -2227,7 +2243,7 @@ namespace Draw { width = round((double)Term::width * (Proc::shown ? width_p : 100) / 100); #ifdef GPU_SUPPORT - height = ceil((double)Term::height * (100 - Net::height_p * Net::shown*4 / ((Gpu::shown != 0 and Cpu::shown) + 4)) / 100) - Cpu::height - Gpu::height*Gpu::shown; + height = ceil((double)Term::height * (100 - Net::height_p * Net::shown*4 / ((Gpu::shown != 0 and Cpu::shown) + 4)) / 100) - Cpu::height - Gpu::total_height; #else height = ceil((double)Term::height * (100 - Cpu::height_p * Cpu::shown - Net::height_p * Net::shown) / 100) + 1; #endif @@ -2236,7 +2252,7 @@ namespace Draw { #ifdef GPU_SUPPORT y = Term::height - height + 1 - (cpu_bottom ? Cpu::height : 0); else - y = (cpu_bottom ? 1 : Cpu::height + 1) + Gpu::height * Gpu::shown; + y = (cpu_bottom ? 1 : Cpu::height + 1) + Gpu::total_height; #else y = Term::height - height + 1 - (cpu_bottom ? Cpu::height : 0); else @@ -2291,14 +2307,14 @@ namespace Draw { using namespace Net; width = round((double)Term::width * (Proc::shown ? width_p : 100) / 100); #ifdef GPU_SUPPORT - height = Term::height - Cpu::height - Gpu::height*Gpu::shown - Mem::height; + height = Term::height - Cpu::height - Gpu::total_height - Mem::height; #else height = Term::height - Cpu::height - Mem::height; #endif x = (proc_left and Proc::shown) ? Term::width - width + 1 : 1; if (mem_below_net and Mem::shown) #ifdef GPU_SUPPORT - y = (cpu_bottom ? 1 : Cpu::height + 1) + Gpu::height * Gpu::shown; + y = (cpu_bottom ? 1 : Cpu::height + 1) + Gpu::total_height; #else y = cpu_bottom ? 1 : Cpu::height + 1; #endif @@ -2321,13 +2337,13 @@ namespace Draw { using namespace Proc; width = Term::width - (Mem::shown ? Mem::width : (Net::shown ? Net::width : 0)); #ifdef GPU_SUPPORT - height = Term::height - Cpu::height - Gpu::height*Gpu::shown; + height = Term::height - Cpu::height - Gpu::total_height; #else height = Term::height - Cpu::height; #endif x = proc_left ? 1 : Term::width - width + 1; #ifdef GPU_SUPPORT - y = ((cpu_bottom and Cpu::shown) ? 1 : Cpu::height + 1) + Gpu::height * Gpu::shown; + y = ((cpu_bottom and Cpu::shown) ? 1 : Cpu::height + 1) + Gpu::total_height; #else y = (cpu_bottom and Cpu::shown) ? 1 : Cpu::height + 1; #endif diff --git a/src/btop_shared.hpp b/src/btop_shared.hpp index 7260689f..80901b37 100644 --- a/src/btop_shared.hpp +++ b/src/btop_shared.hpp @@ -110,7 +110,7 @@ namespace Shared { namespace Gpu { #ifdef GPU_SUPPORT extern vector box; - extern int width, height, min_width, min_height; + extern int width, total_height, min_width, min_height; extern vector x_vec, y_vec; extern vector redraw; extern int shown; diff --git a/src/btop_tools.cpp b/src/btop_tools.cpp index ccccd8e5..6704c3d3 100644 --- a/src/btop_tools.cpp +++ b/src/btop_tools.cpp @@ -142,7 +142,8 @@ namespace Term { if (proc) height += Proc::min_height; else height += (mem ? Mem::min_height : 0) + (net ? Net::min_height : 0); #ifdef GPU_SUPPORT - height += Gpu::min_height*gpu; + for (int i = 0; i < gpu; i++) + height += Gpu::gpu_b_height_offsets[i] + 4; #endif return { width, height }; From 5332b1f0c9a9f0ea670fa0134099e2433d62396a Mon Sep 17 00:00:00 2001 From: TheSovietPancakes Date: Wed, 26 Nov 2025 01:39:11 -0600 Subject: [PATCH 2/2] Fixed GPU box positions in low height settings --- src/btop_draw.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/btop_draw.cpp b/src/btop_draw.cpp index b0c11506..474c3ada 100644 --- a/src/btop_draw.cpp +++ b/src/btop_draw.cpp @@ -1021,8 +1021,8 @@ namespace Gpu { if (redraw[index]) { out += box[index]; - graph_up_height = single_graph ? b_height_vec[index] : max(0, b_y - y - 1); - const int graph_low_height = single_graph ? 0 : max(0, (y + b_height_vec[index] - 1) - (b_y + b_height_vec[index]) - 1); + graph_up_height = single_graph ? b_height_vec[index] : (b_height_vec[index] + 1) / 2; + int graph_low_height = single_graph ? 0 : b_height_vec[index] - graph_up_height; if (gpu.supported_functions.gpu_utilization) { graph_upper = Draw::Graph{x + width - b_width - 3, graph_up_height, "cpu", safeVal(gpu.gpu_percent, "gpu-totals"s), graph_symbol, false, true}; // TODO cpu -> gpu @@ -1056,7 +1056,7 @@ namespace Gpu { if (gpu.supported_functions.gpu_utilization) { out += Fx::ub + Mv::to(y + rows_used, x + 1) + graph_upper(safeVal(gpu.gpu_percent, "gpu-totals"s), (data_same or redraw[index])); if (not single_graph) - out += Mv::to(y + graph_up_height + 1, x + 1) + graph_lower(safeVal(gpu.gpu_percent, "gpu-totals"s), (data_same or redraw[index])); + out += Mv::to(y + rows_used + graph_up_height, x + 1) + graph_lower(safeVal(gpu.gpu_percent, "gpu-totals"s), (data_same or redraw[index])); out += Mv::to(b_y + rows_used, b_x + 1) + Theme::c("main_fg") + Fx::b + "GPU " + gpu_meter(safeVal(gpu.gpu_percent, "gpu-totals"s).back()) + Theme::g("cpu").at(clamp(safeVal(gpu.gpu_percent, "gpu-totals"s).back(), 0ll, 100ll)) + rjust(to_string(safeVal(gpu.gpu_percent, "gpu-totals"s).back()), 5) + Theme::c("main_fg") + '%'; @@ -2209,7 +2209,7 @@ namespace Draw { else height = Cpu::height; else if (not (Mem::shown or Net::shown or Proc::shown)) - height = Term::height/Gpu::shown + (i == 0)*(Term::height%Gpu::shown); + height = (Term::height - total_height) / (Gpu::shown - i) + (i == 0) * ((Term::height - total_height) % (Gpu::shown - i)); else height = max(min_height, (int)ceil((double)Term::height * height_p/Gpu::shown / 100)); @@ -2223,7 +2223,7 @@ namespace Draw { //? Main statistics box 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; + b_y_vec[i] = y_vec[i] + ceil((double)(height - 2 - b_height_vec[i]) / 2) + 1; string name = Config::getS(std::string("custom_gpu_name") + (char)(shown_panels[i]+'0')); if (name.empty()) name = gpu_names[shown_panels[i]];