@@ -4396,6 +4396,87 @@ static LSTATUS get_device_property(struct device *device, const DEVPROPKEY *prop
4396
4396
return ls ;
4397
4397
}
4398
4398
4399
+ /* CW HACK 23560: Diablo IV needs GPU LUIDs to match between setupapi and (D3DMetal's) dxgi */
4400
+ #ifdef __x86_64__
4401
+ #define COBJMACROS
4402
+ #include <dxgi.h>
4403
+
4404
+ static const DEVPROPKEY DEVPROPKEY_GPU_LUID =
4405
+ { { 0x60b193cb , 0x5276 , 0x4d0f , { 0x96 , 0xfc , 0xf1 , 0x73 , 0xab , 0xad , 0x3e , 0xc6 } }, 2 };
4406
+
4407
+ static const GUID my_IDXGIFactory =
4408
+ { 0x7b7166ec , 0x21c7 , 0x44ae , { 0xb2 ,0x1a , 0xc9 ,0xae ,0x32 ,0x1a ,0xe3 ,0x69 } };
4409
+
4410
+ static BOOL CALLBACK check_is_diablo_iv (INIT_ONCE * once , void * param , void * * context )
4411
+ {
4412
+ BOOL * is_d4 = param ;
4413
+ WCHAR name [MAX_PATH ], * module_exe ;
4414
+ if (GetModuleFileNameW (NULL , name , ARRAYSIZE (name )))
4415
+ {
4416
+ module_exe = wcsrchr (name , '\\' );
4417
+ module_exe = module_exe ? module_exe + 1 : name ;
4418
+ * is_d4 = !wcsicmp (module_exe , L"Diablo IV.exe" );
4419
+ }
4420
+
4421
+ return TRUE;
4422
+ }
4423
+
4424
+ static BOOL is_diablo_iv (void )
4425
+ {
4426
+ static BOOL is_d4 = FALSE;
4427
+ static INIT_ONCE once = INIT_ONCE_STATIC_INIT ;
4428
+ InitOnceExecuteOnce (& once , check_is_diablo_iv , & is_d4 , NULL );
4429
+ return is_d4 ;
4430
+ }
4431
+
4432
+ static BOOL using_d3dmetal (void )
4433
+ {
4434
+ /* D3DMetal's dxgi.dll doesn't include a version resource (or any resources) */
4435
+ return (GetFileVersionInfoSizeW (L"dxgi.dll" , NULL ) > 0 ) ? FALSE : TRUE;
4436
+ }
4437
+
4438
+ static void get_luid_from_d3dmetal (LUID * luid )
4439
+ {
4440
+ /* Diablo IV retrieves the GPU LUID through setupapi and expects it to match the LUID reported by
4441
+ * D3DMetal.
4442
+ *
4443
+ * For now, load D3DMetal's dxgi and get its LUID.
4444
+ *
4445
+ * This assumes there's only one GPU (which is currently always true on Apple Silicon Macs).
4446
+ */
4447
+ static HMODULE dxgi ;
4448
+ typeof (CreateDXGIFactory ) * dxgi_CreateDXGIFactory ;
4449
+ IDXGIFactory * factory = NULL ;
4450
+ IDXGIAdapter * adapter = NULL ;
4451
+ DXGI_ADAPTER_DESC desc ;
4452
+
4453
+ if (!dxgi )
4454
+ {
4455
+ dxgi = LoadLibraryW (L"dxgi.dll" );
4456
+ if (!dxgi ) return ;
4457
+ }
4458
+
4459
+ dxgi_CreateDXGIFactory = (void * )GetProcAddress (dxgi , "CreateDXGIFactory" );
4460
+ if (!dxgi_CreateDXGIFactory ) goto done ;
4461
+
4462
+ dxgi_CreateDXGIFactory (& my_IDXGIFactory , (void * * )& factory );
4463
+ if (!factory ) goto done ;
4464
+
4465
+ IDXGIFactory_EnumAdapters (factory , 0 , & adapter );
4466
+ if (!adapter ) goto done ;
4467
+
4468
+ if (IDXGIAdapter_GetDesc (adapter , & desc ) != S_OK )
4469
+ goto done ;
4470
+
4471
+ TRACE ("Using LUID %08lx:%08lx from D3DMetal dxgi\n" , desc .AdapterLuid .HighPart , desc .AdapterLuid .LowPart );
4472
+ memcpy (luid , & desc .AdapterLuid , sizeof (* luid ));
4473
+
4474
+ done :
4475
+ if (adapter ) IDXGIAdapter_Release (adapter );
4476
+ if (factory ) IDXGIFactory_Release (factory );
4477
+ }
4478
+ #endif
4479
+
4399
4480
/***********************************************************************
4400
4481
* SetupDiGetDevicePropertyW (SETUPAPI.@)
4401
4482
*/
@@ -4414,6 +4495,15 @@ BOOL WINAPI SetupDiGetDevicePropertyW(HDEVINFO devinfo, PSP_DEVINFO_DATA device_
4414
4495
4415
4496
ls = get_device_property (device , prop_key , prop_type , prop_buff , prop_buff_size , required_size , flags );
4416
4497
4498
+ #ifdef __x86_64__
4499
+ /* CW HACK 23560 */
4500
+ if (ls == NO_ERROR && prop_buff && prop_buff_size == sizeof (LUID ) &&
4501
+ IsEqualDevPropKey (* prop_key , DEVPROPKEY_GPU_LUID ) && is_diablo_iv () && using_d3dmetal ())
4502
+ {
4503
+ get_luid_from_d3dmetal ((LUID * )prop_buff );
4504
+ }
4505
+ #endif
4506
+
4417
4507
SetLastError (ls );
4418
4508
return !ls ;
4419
4509
}
0 commit comments