|
1 | 1 | #pragma once |
2 | 2 |
|
3 | | -#include <wrl/client.h> // For ComPtr |
4 | | -#include <dxgi.h> // For IDXGIAdapter, IDXGIFactory1 |
5 | | -#include <algorithm> // For sort |
| 3 | +#include <wrl/client.h> // For ComPtr |
| 4 | +#include <dxgi.h> // For IDXGIAdapter, IDXGIFactory1 |
| 5 | +#include <algorithm> // For sort |
6 | 6 | #include <setupapi.h> |
7 | 7 | #include <devguid.h> |
8 | 8 | #include <devpropdef.h> |
@@ -65,6 +65,100 @@ vector<GPUInfo> getAvailableGPUs() { |
65 | 65 | return gpus; |
66 | 66 | } |
67 | 67 |
|
| 68 | +// #--- // Find the integrated GPU (iGPU) from available adapters |
| 69 | +// #--- // Returns optional LUID if iGPU is found, nullopt otherwise |
| 70 | +// #--- inline std::optional<LUID> findiGPU() { |
| 71 | +// #--- auto gpus = getAvailableGPUs(); |
| 72 | +// #--- if (gpus.empty()) { |
| 73 | +// #--- return std::nullopt; |
| 74 | +// #--- } |
| 75 | +// #--- |
| 76 | +// #--- // iGPU detection criteria: |
| 77 | +// #--- // 1. Not a software adapter (has dedicated video memory > 0) |
| 78 | +// #--- // 2. Low dedicated video memory (typically < 512MB for integrated) |
| 79 | +// #--- // 3. Usually Intel HD/UHD graphics (Vendor ID 0x8086) or AMD APU (Vendor ID 0x1002) |
| 80 | +// #--- // 4. Often the GPU with least dedicated memory (excluding software adapters) |
| 81 | +// #--- |
| 82 | +// #--- const UINT64 iGPUMemoryThreshold = 512ULL * 1024ULL * 1024ULL; // 512MB threshold |
| 83 | +// #--- const UINT intelVendorId = 0x8086; // Intel |
| 84 | +// #--- const UINT amdVendorId = 0x1002; // AMD (for APUs) |
| 85 | +// #--- |
| 86 | +// #--- std::optional<LUID> iGPULuid = std::nullopt; |
| 87 | +// #--- UINT64 minDedicatedMemory = UINT64_MAX; |
| 88 | +// #--- const GPUInfo* candidateGPU = nullptr; |
| 89 | +// #--- |
| 90 | +// #--- // First pass: Look for Intel or AMD integrated graphics with low memory |
| 91 | +// #--- for (const auto& gpu : gpus) { |
| 92 | +// #--- const auto& desc = gpu.desc; |
| 93 | +// #--- |
| 94 | +// #--- // Skip software adapters (zero dedicated memory) |
| 95 | +// #--- if (desc.DedicatedVideoMemory == 0) { |
| 96 | +// #--- continue; |
| 97 | +// #--- } |
| 98 | +// #--- |
| 99 | +// #--- // Check for integrated GPU characteristics |
| 100 | +// #--- bool isLikelyiGPU = false; |
| 101 | +// #--- |
| 102 | +// #--- // Check by vendor ID (Intel or AMD APU) |
| 103 | +// #--- if (desc.VendorId == intelVendorId || desc.VendorId == amdVendorId) { |
| 104 | +// #--- // Intel HD/UHD graphics typically have specific naming patterns |
| 105 | +// #--- wstring name = desc.Description; |
| 106 | +// #--- if (name.find(L"Intel") != wstring::npos && |
| 107 | +// #--- (name.find(L"HD") != wstring::npos || name.find(L"UHD") != wstring::npos)) { |
| 108 | +// #--- isLikelyiGPU = true; |
| 109 | +// #--- } |
| 110 | +// #--- // Check if it has low dedicated memory (typical for iGPU) |
| 111 | +// #--- if (desc.DedicatedVideoMemory < iGPUMemoryThreshold) { |
| 112 | +// #--- isLikelyiGPU = true; |
| 113 | +// #--- } |
| 114 | +// #--- } |
| 115 | +// #--- |
| 116 | +// #--- // Track the GPU with least dedicated memory (usually iGPU) |
| 117 | +// #--- if (desc.DedicatedVideoMemory < minDedicatedMemory) { |
| 118 | +// #--- minDedicatedMemory = desc.DedicatedVideoMemory; |
| 119 | +// #--- // Prioritize Intel/AMD candidates, but also consider low memory GPUs |
| 120 | +// #--- if (isLikelyiGPU || desc.DedicatedVideoMemory < iGPUMemoryThreshold) { |
| 121 | +// #--- candidateGPU = &gpu; |
| 122 | +// #--- } |
| 123 | +// #--- } |
| 124 | +// #--- } |
| 125 | +// #--- |
| 126 | +// #--- // If we found a candidate with Intel/AMD or low memory, return it |
| 127 | +// #--- if (candidateGPU != nullptr) { |
| 128 | +// #--- return candidateGPU->desc.AdapterLuid; |
| 129 | +// #--- } |
| 130 | +// #--- |
| 131 | +// #--- // Fallback: If no clear iGPU found by vendor, return the GPU with least memory |
| 132 | +// #--- // (assuming discrete GPUs typically have more memory) |
| 133 | +// #--- if (minDedicatedMemory != UINT64_MAX && minDedicatedMemory < iGPUMemoryThreshold) { |
| 134 | +// #--- for (const auto& gpu : gpus) { |
| 135 | +// #--- if (gpu.desc.DedicatedVideoMemory == minDedicatedMemory) { |
| 136 | +// #--- return gpu.desc.AdapterLuid; |
| 137 | +// #--- } |
| 138 | +// #--- } |
| 139 | +// #--- } |
| 140 | +// #--- |
| 141 | +// #--- return std::nullopt; |
| 142 | +// #--- } |
| 143 | + |
| 144 | +// #--- // Get iGPU name if available |
| 145 | +// #--- inline wstring getiGPUName() { |
| 146 | +// #--- auto luidOpt = findiGPU(); |
| 147 | +// #--- if (!luidOpt.has_value()) { |
| 148 | +// #--- return L""; |
| 149 | +// #--- } |
| 150 | +// #--- |
| 151 | +// #--- auto gpus = getAvailableGPUs(); |
| 152 | +// #--- for (const auto& gpu : gpus) { |
| 153 | +// #--- if (gpu.desc.AdapterLuid.LowPart == luidOpt.value().LowPart && |
| 154 | +// #--- gpu.desc.AdapterLuid.HighPart == luidOpt.value().HighPart) { |
| 155 | +// #--- return gpu.name; |
| 156 | +// #--- } |
| 157 | +// #--- } |
| 158 | +// #--- |
| 159 | +// #--- return L""; |
| 160 | +// #--- } |
| 161 | + |
68 | 162 | // Resolve an adapter LUID from a PCI bus number by enumerating display devices (SetupAPI). |
69 | 163 | // Returns nullopt if no match is found or if the system doesn't expose the LUID property. |
70 | 164 | inline std::optional<LUID> ResolveAdapterLuidFromPciBus(uint32_t targetBusIndex) { |
@@ -133,6 +227,12 @@ class AdapterOption { |
133 | 227 | LUID adapterLuid{}; // Adapter's unique identifier (LUID) |
134 | 228 | wstring target_name{}; // Target adapter name |
135 | 229 |
|
| 230 | +// #--- // --- iGPU SUPPORT --- |
| 231 | +// #--- bool hasiGPU{}; // Indicates if an iGPU was detected |
| 232 | +// #--- LUID iGPULuid{}; // Integrated GPU's unique identifier (LUID) |
| 233 | +// #--- wstring iGPU_name{}; // Integrated GPU name |
| 234 | +// #--- // --- END iGPU SUPPORT --- |
| 235 | + |
136 | 236 | // Select the best GPU based on dedicated video memory |
137 | 237 | wstring selectBestGPU() { |
138 | 238 | auto gpus = getAvailableGPUs(); |
@@ -187,6 +287,40 @@ class AdapterOption { |
187 | 287 | } |
188 | 288 | } |
189 | 289 |
|
| 290 | +// #--- // --- iGPU DETECTION METHODS --- |
| 291 | +// #--- // Detect and select the integrated GPU (iGPU) |
| 292 | +// #--- // Returns true if iGPU is found and set, false otherwise |
| 293 | +// #--- bool selectiGPU() { |
| 294 | +// #--- auto luidOpt = findiGPU(); |
| 295 | +// #--- if (luidOpt.has_value()) { |
| 296 | +// #--- iGPULuid = luidOpt.value(); |
| 297 | +// #--- iGPU_name = getiGPUName(); |
| 298 | +// #--- hasiGPU = true; |
| 299 | +// #--- return true; |
| 300 | +// #--- } |
| 301 | +// #--- hasiGPU = false; |
| 302 | +// #--- return false; |
| 303 | +// #--- } |
| 304 | +// #--- |
| 305 | +// #--- // Get the iGPU LUID if available |
| 306 | +// #--- std::optional<LUID> getiGPULuid() const { |
| 307 | +// #--- if (hasiGPU) { |
| 308 | +// #--- return iGPULuid; |
| 309 | +// #--- } |
| 310 | +// #--- return std::nullopt; |
| 311 | +// #--- } |
| 312 | +// #--- |
| 313 | +// #--- // Check if iGPU is available |
| 314 | +// #--- bool hasIntegratedGPU() const { |
| 315 | +// #--- return hasiGPU; |
| 316 | +// #--- } |
| 317 | +// #--- |
| 318 | +// #--- // Get iGPU name |
| 319 | +// #--- wstring getiGPUName() const { |
| 320 | +// #--- return iGPU_name; |
| 321 | +// #--- } |
| 322 | +// #--- // --- END iGPU DETECTION METHODS --- |
| 323 | + |
190 | 324 | private: |
191 | 325 | // Find and set the adapter by name, optionally using "name,bus" where bus is the PCI bus number. |
192 | 326 | bool findAndSetAdapter(const wstring& adapterSpec) { |
|
0 commit comments