forked from flightlessmango/MangoHud
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgpu.cpp
More file actions
205 lines (165 loc) · 6.74 KB
/
Copy pathgpu.cpp
File metadata and controls
205 lines (165 loc) · 6.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
#include <set>
#include "gpu.h"
#include "file_utils.h"
#include "hud_elements.h"
namespace fs = ghc::filesystem;
GPUS::GPUS(const overlay_params* early_params) {
std::set<std::string> gpu_entries;
auto params = early_params ? early_params : get_params().get();
for (const auto& entry : fs::directory_iterator("/sys/class/drm")) {
if (!entry.is_directory())
continue;
std::string node_name = entry.path().filename().string();
// Check if the directory is a render node (e.g., renderD128, renderD129, etc.)
if (node_name.find("renderD") == 0 && node_name.length() > 7) {
// Ensure the rest of the string after "renderD" is numeric
std::string render_number = node_name.substr(7);
if (std::all_of(render_number.begin(), render_number.end(), ::isdigit)) {
gpu_entries.insert(node_name); // Store the render entry
}
}
}
// Now process the sorted GPU entries
uint8_t idx = 0, total_active = 0;
for (const auto& node_name : gpu_entries) {
const std::string driver = get_driver(node_name);
if (driver.empty()) {
SPDLOG_DEBUG("Failed to query driver name of node \"{}\"", node_name);
continue;
}
{
const std::string* d =
std::find(std::begin(supported_drivers), std::end(supported_drivers), driver);
if (d == std::end(supported_drivers)) {
SPDLOG_WARN(
"node \"{}\" is using driver \"{}\" which is unsupported by MangoHud. Skipping...",
node_name, driver
);
continue;
}
}
std::string path = "/sys/class/drm/" + node_name;
std::string device_address = get_pci_device_address(path); // Store the result
const char* pci_dev = device_address.c_str();
uint32_t vendor_id = 0;
uint32_t device_id = 0;
if (!device_address.empty())
{
try {
vendor_id = std::stoul(read_line("/sys/bus/pci/devices/" + device_address + "/vendor"), nullptr, 16);
} catch(...) {
SPDLOG_ERROR("stoul failed on: {}", "/sys/bus/pci/devices/" + device_address + "/vendor");
}
try {
device_id = std::stoul(read_line("/sys/bus/pci/devices/" + device_address + "/device"), nullptr, 16);
} catch (...) {
SPDLOG_ERROR("stoul failed on: {}", "/sys/bus/pci/devices/" + device_address + "/device");
}
}
std::shared_ptr<GPU> ptr =
std::make_shared<GPU>(node_name, vendor_id, device_id, pci_dev, driver);
if (params->gpu_list.size() == 1 && params->gpu_list[0] == idx++)
ptr->is_active = true;
if (!params->pci_dev.empty() && pci_dev == params->pci_dev)
ptr->is_active = true;
available_gpus.emplace_back(ptr);
SPDLOG_DEBUG(
"GPU Found: node_name: {}, driver: {}, vendor_id: {:x} device_id: {:x} pci_dev: {}",
node_name, driver, vendor_id, device_id, pci_dev
);
if (ptr->is_active) {
SPDLOG_INFO(
"Set {} as active GPU (driver={} id={:x}:{:x} pci_dev={})",
node_name, driver, vendor_id, device_id, pci_dev
);
total_active++;
}
}
if (total_active < 2)
return;
for (auto& gpu : available_gpus) {
if (!gpu->is_active)
continue;
SPDLOG_WARN(
"You have more than 1 active GPU, check if you use both pci_dev "
"and gpu_list. If you use fps logging, MangoHud will log only "
"this GPU: name = {}, driver = {}, vendor = {:x}, pci_dev = {}",
gpu->drm_node, gpu->driver, gpu->vendor_id, gpu->pci_dev
);
break;
}
}
std::string GPUS::get_driver(const std::string& node) {
std::string path = "/sys/class/drm/" + node + "/device/driver";
if (!fs::exists(path)) {
SPDLOG_ERROR("{} doesn't exist", path);
return "";
}
if (!fs::is_symlink(path)) {
SPDLOG_ERROR("{} is not a symlink (it should be)", path);
return "";
}
std::string driver = fs::read_symlink(path).string();
driver = driver.substr(driver.rfind("/") + 1);
return driver;
}
std::string GPUS::get_pci_device_address(const std::string& drm_card_path) {
// /sys/class/drm/renderD128/device/subsystem -> /sys/bus/pci
auto subsystem = fs::canonical(drm_card_path + "/device/subsystem").string();
auto idx = subsystem.rfind("/") + 1; // /sys/bus/pci
// ^
// |- find this guy
if (subsystem.substr(idx) != "pci")
return "";
// /sys/class/drm/renderD128/device -> /sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/0000:02:01.0/0000:03:00.0
auto pci_addr = fs::read_symlink(drm_card_path + "/device").string();
idx = pci_addr.rfind("/") + 1; // /sys/.../0000:03:00.0
// ^
// |- find this guy
return pci_addr.substr(idx); // 0000:03:00.0
}
int GPU::index_in_selected_gpus() {
auto selected_gpus = gpus->selected_gpus();
auto it = std::find_if(selected_gpus.begin(), selected_gpus.end(),
[this](const std::shared_ptr<GPU>& gpu) {
return gpu.get() == this;
});
if (it != selected_gpus.end()) {
return std::distance(selected_gpus.begin(), it);
}
return -1;
}
std::string GPU::gpu_text() {
std::string gpu_text;
size_t index = this->index_in_selected_gpus();
if (gpus->selected_gpus().size() == 1) {
// When there's exactly one selected GPU, return "GPU" without index
gpu_text = "GPU";
if (gpus->params()->gpu_text.size() > 0) {
gpu_text = gpus->params()->gpu_text[0];
}
} else if (gpus->selected_gpus().size() > 1) {
// When there are multiple selected GPUs, use GPU+index or matching gpu_text
gpu_text = "GPU" + std::to_string(index);
if (gpus->params()->gpu_text.size() > index) {
gpu_text = gpus->params()->gpu_text[index];
}
} else {
// Default case for no selected GPUs
gpu_text = "GPU";
}
return gpu_text;
}
std::string GPU::vram_text() {
std::string vram_text;
size_t index = this->index_in_selected_gpus();
if (gpus->selected_gpus().size() > 1)
vram_text = "VRAM" + std::to_string(index);
else
vram_text = "VRAM";
return vram_text;
}
std::shared_ptr<const overlay_params> GPUS::params() {
return get_params();
}
std::unique_ptr<GPUS> gpus = nullptr;