master ohmu/fastfetch-openbsd / src / detection / gpu / gpu_windows.cpp
ohmu  ·  2026-10-15
 1extern "C" {
 2#include "gpu.h"
 3#include "common/library.h"
 4#include "common/debug.h"
 5}
 6
 7#if __has_include(<directx/dxcore.h>) && __has_include(<dxguids/dxguids.h>)
 8
 9    #include <directx/dxcore.h>
10    #include <dxguids/dxguids.h>
11    #include "common/windows/util.hpp"
12
13static IDXCoreAdapterFactory* loadDxCoreFactory() {
14    static bool initialized = false;
15    static IDXCoreAdapterFactory* factory = nullptr;
16    if (initialized) {
17        return factory; // Already loaded
18    }
19
20    initialized = true;
21    FF_LIBRARY_LOAD(dxcore, nullptr, "dxcore" FF_LIBRARY_EXTENSION, 1)
22
23    // DXCoreCreateAdapterFactory is a reloaded function, so we can't use FF_LIBRARY_LOAD_SYMBOL_MESSAGE here
24    typedef HRESULT (*DXCoreCreateAdapterFactory_t)(REFIID riid, void** ppvFactory);
25
26    #ifndef FF_DISABLE_DLOPEN
27    auto ffDXCoreCreateAdapterFactory = (DXCoreCreateAdapterFactory_t) dlsym(dxcore, "DXCoreCreateAdapterFactory");
28    if (ffDXCoreCreateAdapterFactory == nullptr) {
29        return nullptr;
30    }
31    #else
32    auto ffDXCoreCreateAdapterFactory = (DXCoreCreateAdapterFactory_t) DXCoreCreateAdapterFactory;
33    #endif
34
35    HRESULT hr = ffDXCoreCreateAdapterFactory(IID_PPV_ARGS(&factory));
36    if (FAILED(hr)) {
37        FF_DEBUG("DXCoreCreateAdapterFactory failed with HRESULT: 0x%08lX (%s)", hr, ffDebugHResult(hr));
38        return nullptr;
39    }
40
41    dxcore = nullptr; // Don't unload
42    return factory;
43}
44
45extern "C" const char* ffGPUDetectTypeWithDXCore(LUID adapterLuid, FFGPUResult* gpu) {
46    auto* factory = loadDxCoreFactory();
47    if (!factory) {
48        return "Failed to load DXCore library or create adapter factory";
49    }
50
51    IDXCoreAdapter* adapter = nullptr;
52    HRESULT hr = factory->GetAdapterByLuid(adapterLuid, IID_PPV_ARGS(&adapter));
53    if (FAILED(hr)) {
54        FF_DEBUG("GetAdapterByLuid failed with HRESULT: 0x%08lX (%s)", hr, ffDebugHResult(hr));
55        return "Failed to get adapter by LUID";
56    }
57
58    on_scope_exit releaseAdapter{ [adapter] { adapter->Release(); } };
59
60    bool isIntegrated = false;
61    hr = adapter->GetProperty(DXCoreAdapterProperty::IsIntegrated, sizeof(isIntegrated), &isIntegrated);
62    if (FAILED(hr)) {
63        FF_DEBUG("GetProperty(IsIntegrated) failed with HRESULT: 0x%08lX (%s)", hr, ffDebugHResult(hr));
64        return "Failed to get adapter properties";
65    }
66
67    gpu->type = isIntegrated ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
68    FF_DEBUG("GPU type determined using DXCore: %s", isIntegrated ? "Integrated" : "Discrete");
69
70    return nullptr;
71}
72
73#else
74
75    #warning "DXCore headers not available, GPU type detection may be less accurate"
76
77extern "C" const char* ffGPUDetectTypeWithDXCore(LUID adapterLuid, FFGPUResult* gpu) {
78    FF_UNUSED(adapterLuid, gpu);
79    FF_DEBUG("DXCore not available, skipping GPU type detection with DXCore");
80    return "DXCore not available";
81}
82
83#endif