c++ - 如何确保 DirectX 11 应用程序在带有 C++ 的双 GPU 笔记本电脑上使用独立 GPU?

标签 c++ visual-studio-2017 directx-11

我目前正在使用 DirectX 11 开发一个游戏引擎项目,该项目将被编译为一个动态链接库,并由一个 exe 文件调用。我的引擎工作得很好。但是,我注意到一个奇怪的问题。

我有三个使用此引擎的游戏项目。它们以相同的方式创建和设置,链接器/编译器选项完全相同,并且它们与相同的库链接。但是,当我打开可执行文件时,只有其中一个会使用笔记本电脑上的 dGPU,而另外两个使用 Intel GPU。

我使用的是 Visual Studio 2017 和 Windows 10 SDK 17763。我没有在我的代码中遍历所有 GPU 设备,而是使用默认的视频适配器。由于他们使用相同的代码,我认为行为应该是相同的。

下面是我如何创建我的 ID3D11Device

    DXGI_SWAP_CHAIN_DESC swapDesc = {};
    swapDesc.BufferCount = 2;
    swapDesc.BufferDesc.Width = width;
    swapDesc.BufferDesc.Height = height;
    swapDesc.BufferDesc.RefreshRate.Numerator = 0;
    swapDesc.BufferDesc.RefreshRate.Denominator = 1;
    swapDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    swapDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
    swapDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
    swapDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    swapDesc.Flags = 0;
    swapDesc.OutputWindow = hWnd;
    swapDesc.SampleDesc.Count = 1;
    swapDesc.SampleDesc.Quality = 0;
    swapDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
    swapDesc.Windowed = true;

    // Attempt to initialize DirectX
    return D3D11CreateDeviceAndSwapChain(
        nullptr,                // Video adapter (physical GPU) to use, or null for default
        D3D_DRIVER_TYPE_HARDWARE,   // We want to use the hardware (GPU)
        nullptr,                // Used when doing software rendering
        deviceFlags,                // Any special options
        nullptr,        // Optional array of possible versions we want as fallback
        0,              // The number of fallback in the above param
        D3D11_SDK_VERSION,          // Current version of the SDK
        &swapDesc,                  // Address of swap chain options
        &swapChain,                 // Pointer to our Swap Chain pointer
        &device,                    // Pointer to our Device pointer
        &dxFeatureLevel,            // This will hold the actual feature level the app will use
        &context);                  // Pointer to our Device Context pointer

这是两个 EXE 的结果。

使用 NVIDIA GPU 的应用程序屏幕截图 Screenshot of the app that is using NVIDIA GPU

未使用 NVIDIA GPU 的应用程序屏幕截图 Screenshot of the app that is not using NVIDIA GPU

从截图中可以看到,在第一个截图的左上角有一个NVIDIA GeForce Experience生成的FPS计数器,右边有一个提示GeForce Overlay开启的通知,这意味着该应用程序正在使用 NVIDIA GPU。然而,这两个都没有显示在第二张图片上,这意味着该应用程序正在使用英特尔 GPU。

最佳答案

对于这些“混合”系统,“选择合适的 GPU”主要取决于供应商的驱动程序,而用户则通过其专有设置 UI 对其进行管理。

在 Windows 10 (17134) 之前,您可以通过在源代码中使用这些“已知”导出来为 Win32 桌面应用程序提供的唯一编程提示:

// Indicates to hybrid graphics systems to prefer the discrete part by default
extern "C" 
{
    __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
    __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
}

如果 DXGI 1.6 在 Windows 10 (17134) 或更高版本上运行,您可以使用 IDXGIFactory6 通过 EnumAdapterByGpuPreference 进行适配器枚举。

ComPtr<IDXGIFactory6> factory6;
HRESULT hr = m_dxgiFactory.As(&factory6);
if (SUCCEEDED(hr))
{
    for (UINT adapterIndex = 0;
        DXGI_ERROR_NOT_FOUND != factory6->EnumAdapterByGpuPreference(
            adapterIndex,
            DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE,
            IID_PPV_ARGS(adapter.ReleaseAndGetAddressOf()));
        adapterIndex++)
    {
…
    }
}
else for (UINT adapterIndex = 0;
    DXGI_ERROR_NOT_FOUND != m_dxgiFactory->EnumAdapters1(
        adapterIndex,
        adapter.ReleaseAndGetAddressOf());
    adapterIndex++)
{
…
}

关于c++ - 如何确保 DirectX 11 应用程序在带有 C++ 的双 GPU 笔记本电脑上使用独立 GPU?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55435230/

相关文章:

C++ 将 uint8_t 转换为 unsigned long

.net - 在 Visual Studio 2017 中临时禁用依赖项验证

c# - EntityFrameworkCore.Tools 的 NuGet 包更新错误

c++ - Qt 5 QPrinterInfo::availablePrinters() 没有动态列出打印机

c++ - C++ 的检测(诊断)库

c++ - DirectX 渲染和 OMP

c++ - ID3D11DeviceContext::DrawIndexed 方法是否等待顶点和像素着色器操作完成?

c++ - DXGI_FORMAT_YUY2 纹理在 Windows 8.1 和 Windows 10 下返回不同的 RowPitch

c# - 从 C++ win32 程序连接到命名管道时遇到问题

c++ - 为什么 Cmake 不能使用 include_directories 找到库?