Skip to content

Commit 6b57a3c

Browse files
authored
originals
for the agent t make sure all alterations is commented out, in the new code.
1 parent c279ea9 commit 6b57a3c

3 files changed

Lines changed: 5383 additions & 0 deletions

File tree

orgfolder/AdapterOption.h

Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
#pragma once
2+
3+
#include <wrl/client.h> // For ComPtr
4+
#include <dxgi.h> // For IDXGIAdapter, IDXGIFactory1
5+
#include <algorithm> // For sort
6+
#include <setupapi.h>
7+
#include <devguid.h>
8+
#include <devpropdef.h>
9+
#include <devpkey.h>
10+
#include <cstdint>
11+
#include <optional>
12+
#include <string>
13+
#include <vector>
14+
#include <fstream>
15+
16+
using namespace std;
17+
using namespace Microsoft::WRL;
18+
19+
// DEVPKEY_Device_Luid: {60b193cb-5276-4d0f-96fc-f173ab17af69}, 2
20+
// Define it ourselves to avoid SDK/WDK header differences where DEVPKEY_Device_Luid may not be declared.
21+
static const DEVPROPKEY DEVPKEY_Device_Luid_Custom = {
22+
{ 0x60b193cb, 0x5276, 0x4d0f, { 0x96, 0xfc, 0xf1, 0x73, 0xab, 0xad, 0x3e, 0xc6 } },
23+
2
24+
};
25+
26+
// Structure to vector gpus
27+
struct GPUInfo {
28+
wstring name; // GPU name
29+
ComPtr<IDXGIAdapter> adapter;// COM pointer to the adapter
30+
DXGI_ADAPTER_DESC desc; // Adapter description
31+
};
32+
33+
// Sort function for GPUs by dedicated video memory
34+
bool CompareGPUs(const GPUInfo& a, const GPUInfo& b) {
35+
return a.desc.DedicatedVideoMemory > b.desc.DedicatedVideoMemory;
36+
}
37+
38+
// Get a enumerate list of available GPUs
39+
vector<GPUInfo> getAvailableGPUs() {
40+
vector<GPUInfo> gpus; // Vector to hold all GPU's information
41+
42+
ComPtr<IDXGIFactory1> factory;
43+
if (!SUCCEEDED(CreateDXGIFactory1(IID_PPV_ARGS(&factory)))) {
44+
return gpus;
45+
}
46+
47+
// Enumerate all adapters (GPUs)
48+
for (UINT i = 0;; i++) {
49+
ComPtr<IDXGIAdapter> adapter;
50+
if (!SUCCEEDED(factory->EnumAdapters(i, &adapter))) {
51+
break;
52+
}
53+
54+
DXGI_ADAPTER_DESC desc;
55+
56+
if (!SUCCEEDED(adapter->GetDesc(&desc))) {
57+
continue;
58+
}
59+
60+
// Add the adapter information to the list
61+
GPUInfo info{ desc.Description, adapter, desc };
62+
gpus.push_back(info);
63+
}
64+
65+
return gpus;
66+
}
67+
68+
// Resolve an adapter LUID from a PCI bus number by enumerating display devices (SetupAPI).
69+
// Returns nullopt if no match is found or if the system doesn't expose the LUID property.
70+
inline std::optional<LUID> ResolveAdapterLuidFromPciBus(uint32_t targetBusIndex) {
71+
HDEVINFO devInfo = SetupDiGetClassDevsW(&GUID_DEVCLASS_DISPLAY, nullptr, nullptr, DIGCF_PRESENT);
72+
if (devInfo == INVALID_HANDLE_VALUE) {
73+
return std::nullopt;
74+
}
75+
76+
SP_DEVINFO_DATA devData = {};
77+
devData.cbSize = sizeof(devData);
78+
79+
std::optional<LUID> result = std::nullopt;
80+
81+
for (DWORD i = 0; SetupDiEnumDeviceInfo(devInfo, i, &devData); ++i) {
82+
DWORD currentBus = 0;
83+
if (!SetupDiGetDeviceRegistryPropertyW(
84+
devInfo,
85+
&devData,
86+
SPDRP_BUSNUMBER,
87+
nullptr,
88+
reinterpret_cast<PBYTE>(&currentBus),
89+
sizeof(currentBus),
90+
nullptr)) {
91+
continue;
92+
}
93+
94+
if (static_cast<uint32_t>(currentBus) != targetBusIndex) {
95+
continue;
96+
}
97+
98+
// DEVPKEY_Device_Luid is exposed as a UINT64 on Windows; convert into LUID.
99+
DEVPROPTYPE propType = 0;
100+
ULONG propSize = 0;
101+
ULONGLONG luid64 = 0;
102+
103+
if (!SetupDiGetDevicePropertyW(
104+
devInfo,
105+
&devData,
106+
&DEVPKEY_Device_Luid_Custom,
107+
&propType,
108+
reinterpret_cast<PBYTE>(&luid64),
109+
sizeof(luid64),
110+
&propSize,
111+
0)) {
112+
continue;
113+
}
114+
115+
if (propType != DEVPROP_TYPE_UINT64 || propSize != sizeof(luid64)) {
116+
continue;
117+
}
118+
119+
LUID luid{};
120+
luid.LowPart = static_cast<DWORD>(luid64 & 0xFFFFFFFFull);
121+
luid.HighPart = static_cast<LONG>((luid64 >> 32) & 0xFFFFFFFFull);
122+
result = luid;
123+
break;
124+
}
125+
126+
SetupDiDestroyDeviceInfoList(devInfo);
127+
return result;
128+
}
129+
130+
class AdapterOption {
131+
public:
132+
bool hasTargetAdapter{}; // Indicates if a target adapter is selected
133+
LUID adapterLuid{}; // Adapter's unique identifier (LUID)
134+
wstring target_name{}; // Target adapter name
135+
136+
// Select the best GPU based on dedicated video memory
137+
wstring selectBestGPU() {
138+
auto gpus = getAvailableGPUs();
139+
if (gpus.empty()) {
140+
return L""; // Error check for headless / vm
141+
}
142+
143+
// Sort GPUs by dedicated video memory in descending order
144+
sort(gpus.begin(), gpus.end(), CompareGPUs);
145+
auto bestGPU = gpus.front(); // Get the GPU with the most memory
146+
147+
return bestGPU.name;
148+
}
149+
150+
// Load friendlyname from a file OR select the best GPU
151+
void load(const wchar_t* path) {
152+
ifstream ifs{ path };
153+
154+
if (!ifs.is_open()) {
155+
target_name = selectBestGPU();
156+
}
157+
else {
158+
string line;
159+
getline(ifs, line);
160+
target_name.assign(line.begin(), line.end());
161+
}
162+
163+
// Find and set the adapter based on the target name
164+
if (!findAndSetAdapter(target_name)) {
165+
// If the adapter is not found, select the best GPU and retry
166+
target_name = selectBestGPU();
167+
findAndSetAdapter(target_name);
168+
}
169+
}
170+
171+
// Set the target adapter from a given name and validate it
172+
void xmlprovide(const wstring& xtarg) {
173+
target_name = xtarg;
174+
if (!findAndSetAdapter(target_name)) {
175+
// If the adapter is not found, select the best GPU and retry
176+
target_name = selectBestGPU();
177+
findAndSetAdapter(target_name);
178+
}
179+
}
180+
181+
// Apply the adapter settings to the specified adapter
182+
void apply(const IDDCX_ADAPTER& adapter) {
183+
if (hasTargetAdapter && IDD_IS_FUNCTION_AVAILABLE(IddCxAdapterSetRenderAdapter)) {
184+
IDARG_IN_ADAPTERSETRENDERADAPTER arg{};
185+
arg.PreferredRenderAdapter = adapterLuid;
186+
IddCxAdapterSetRenderAdapter(adapter, &arg);
187+
}
188+
}
189+
190+
private:
191+
// Find and set the adapter by name, optionally using "name,bus" where bus is the PCI bus number.
192+
bool findAndSetAdapter(const wstring& adapterSpec) {
193+
// If user provides "name,bus", use bus to resolve LUID (more deterministic on multi-GPU setups).
194+
const size_t comma = adapterSpec.find(L',');
195+
if (comma != wstring::npos) {
196+
const wstring namePart = adapterSpec.substr(0, comma);
197+
wstring busPart = adapterSpec.substr(comma + 1);
198+
// Trim whitespace in bus part
199+
busPart.erase(remove_if(busPart.begin(), busPart.end(), iswspace), busPart.end());
200+
201+
wchar_t* end = nullptr;
202+
const unsigned long busUl = wcstoul(busPart.c_str(), &end, 10);
203+
const bool parsedOk = (end != nullptr) && (*end == L'\0') && (end != busPart.c_str());
204+
if (parsedOk && busUl <= 0xFFFFFFFFul) {
205+
if (auto luidOpt = ResolveAdapterLuidFromPciBus(static_cast<uint32_t>(busUl)); luidOpt.has_value()) {
206+
adapterLuid = luidOpt.value();
207+
hasTargetAdapter = true;
208+
return true;
209+
}
210+
}
211+
212+
// Fall through to name matching using the name portion.
213+
return findAndSetAdapter(namePart);
214+
}
215+
216+
const wstring& adapterName = adapterSpec;
217+
auto gpus = getAvailableGPUs();
218+
219+
// Iterate through all available GPUs
220+
for (const auto& gpu : gpus) {
221+
if (_wcsicmp(gpu.name.c_str(), adapterName.c_str()) == 0) {
222+
adapterLuid = gpu.desc.AdapterLuid; // Set the adapter LUID
223+
hasTargetAdapter = true; // Indicate that a target adapter is selected
224+
return true;
225+
}
226+
}
227+
228+
hasTargetAdapter = false; // Indicate that no target adapter is selected
229+
return false;
230+
}
231+
};

0 commit comments

Comments
 (0)