Как обеспечить, чтобы приложение DirectX 11 использовало дискретный графический процессор на ноутбуке с двумя графическими процессорами на C ++? - PullRequest
0 голосов
/ 30 марта 2019

В настоящее время я работаю над проектом игрового движка с DirectX 11, который будет скомпилирован в динамически связанную библиотеку и будет вызываться из exe-файла. Мой двигатель работает отлично. Однако я заметил странную проблему.

У меня есть три игровых проекта, которые используют этот движок. Они создаются и устанавливаются одинаково, параметры компоновщика / компилятора полностью совпадают, и они связаны с одинаковыми библиотеками. Но когда я открываю исполняемые файлы, только один из них будет использовать dGPU на моем ноутбуке, в то время как два других используют графический процессор Intel.

Я использую Visual Studio 2017 и Windows 10 SDK 17763. Я не обхожу все графические устройства в своем коде, а использую видеоадаптер по умолчанию. И поскольку они используют один и тот же код, я предполагаю, что поведение должно быть одинаковым.

Вот как я создаю 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 Screenshot of the app that is using NVIDIA GPU

Снимок экрана приложения, которое не использует графический процессор NVIDIA Screenshot of the app that is not using NVIDIA GPU

Вы можете видеть на скриншотах, что в верхнем левом углу первого скриншота есть счетчик FPS, сгенерированный NVIDIA GeForce Experience, а справа есть уведомление о том, что GeForce Overlay включен, что означает что приложение использует графический процессор NVIDIA. Однако ни один из этих двух не показан на втором рисунке, что означает, что приложение использует графический процессор Intel.

1 Ответ

1 голос
/ 02 апреля 2019

Для этих «гибридных» систем драйвер поставщика в основном «выбирает правильный графический процессор», а пользователь управляет им через собственный интерфейс настроек.

До 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++)
{
…
}
...