@@ -65,6 +65,100 @@ vector<GPUInfo> getAvailableGPUs() {
6565 return gpus;
6666}
6767
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+
68162// Resolve an adapter LUID from a PCI bus number by enumerating display devices (SetupAPI).
69163// Returns nullopt if no match is found or if the system doesn't expose the LUID property.
70164inline std::optional<LUID> ResolveAdapterLuidFromPciBus (uint32_t targetBusIndex) {
@@ -132,6 +226,12 @@ class AdapterOption {
132226 bool hasTargetAdapter{}; // Indicates if a target adapter is selected
133227 LUID adapterLuid{}; // Adapter's unique identifier (LUID)
134228 wstring target_name{}; // Target adapter name
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 ---
135235
136236 // Select the best GPU based on dedicated video memory
137237 wstring selectBestGPU () {
@@ -187,6 +287,40 @@ class AdapterOption {
187287 }
188288 }
189289
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+
190324private:
191325 // Find and set the adapter by name, optionally using "name,bus" where bus is the PCI bus number.
192326 bool findAndSetAdapter (const wstring& adapterSpec) {
0 commit comments