Оконный рендеринг с другим адаптером

У меня есть ноутбук с двумя адаптерами - Intel и NVIDIA. Я использую Windows 10, и в биосе нет возможности отключить встроенный адаптер Intel. Я могу указать использовать адаптер NVIDIA для определенных приложений или по умолчанию для всех устройств Direct3D. Когда я использую адаптер Intel (который является фиксированным адаптером для рабочего стола Windows), мое 3D-приложение в оконном режиме работает нормально.

Если я изменю глобальную настройку NVIDIA, чтобы принудительно использовать адаптер NVIDIA для всех устройств Direct3D, или изменю свой код, чтобы выбрать адаптер NVIDIA, код выполняется без ошибок (у меня подключено устройство отладки DirectX), но в моем окне ничего не отображается.

Я считаю, что невозможно подключить вывод цепочки обмена Windowed к адаптеру, который не является адаптером, используемым рабочим столом Windows, но я никогда не видел, чтобы это было явно выражено.

Это означает, что на ноутбуке, использующем встроенный аппаратный адаптер для рабочего стола Windows, я не могу использовать более мощный адаптер NVIDIA в Windows, и мне придется использовать полноэкранный режим.

Может ли кто-нибудь подтвердить это или предложить метод создания устройства, который позволяет мне успешно обращаться ко второму адаптеру в окне?

Для ясности мой код создания устройства:

   private static void initializeDirect3DGraphicsDevice(System.Windows.Forms.Control winFormsControl, out Device device, out SharpDX.DXGI.SwapChain sc)
    {
        SharpDX.DXGI.SwapChainDescription destination = new SharpDX.DXGI.SwapChainDescription()
        {
            BufferCount = 1,
            ModeDescription = new SharpDX.DXGI.ModeDescription(
                winFormsControl.ClientSize.Width,
                winFormsControl.ClientSize.Height,
                new SharpDX.DXGI.Rational(60, 1),
                SharpDX.DXGI.Format.R8G8B8A8_UNorm),
            IsWindowed = true,
            OutputHandle = winFormsControl.Handle,
            SampleDescription = new SharpDX.DXGI.SampleDescription(1, 0),
            SwapEffect = SharpDX.DXGI.SwapEffect.Discard,
            Usage = SharpDX.DXGI.Usage.RenderTargetOutput
        };

        using (SharpDX.DXGI.Factory1 factory = new SharpDX.DXGI.Factory1())
        {
            // Pick the adapter with teh best video memory allocation - this is the NVIDIA adapter
            List<SharpDX.DXGI.Adapter> adapters = factory.Adapters.OrderBy(item => (long)item.Description.DedicatedVideoMemory).Reverse().ToList();
            SharpDX.DXGI.Adapter bestAdapter = adapters.First();

            foreach(SharpDX.DXGI.Output output in bestAdapter.Outputs)
            {
                System.Diagnostics.Debug.WriteLine("Adapter " + bestAdapter.Description.Description.Substring(0,20) + " output " + output.Description.DeviceName);
            }

            device = new Device(bestAdapter, DeviceCreationFlags.Debug);
            // Uncomment the below to allow the NVIDIA control panel to select the adapter for me.
            //device = new Device(SharpDX.Direct3D.DriverType.Hardware, DeviceCreationFlags.Debug);
            sc = new SharpDX.DXGI.SwapChain(factory, device, destination);
            factory.MakeWindowAssociation(winFormsControl.Handle, SharpDX.DXGI.WindowAssociationFlags.IgnoreAll);

            System.Diagnostics.Debug.WriteLine("Device created with feature level " + device.FeatureLevel + " on adapter " + bestAdapter.Description.Description.Substring(0, 20));
            System.Diagnostics.Debug.WriteLine("");
        }




    }

person PhillipH    schedule 01.03.2017    source источник


Ответы (1)


Запатентованная технология NVIDIA, используемая для управления интегрированным устройством Intel и дискретной частью NVIDIA, известна как Optimus< /а>. У AMD есть похожая технология, которую они называют PowerXpress. Они оба играют трюки с устройством Direct3D по умолчанию в драйвере, чтобы управлять этим поведением, что может быть немного странно для разработчика.

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

Пользователь всегда может заставить приложение использовать то или иное через панель управления, что является лучшим пользовательским интерфейсом. Проблема в том, что значение по умолчанию часто не подходит для игр. Решение для классических настольных приложений Win32 заключается в том, чтобы поместить «магический экспорт» в ваш EXE-файл, который программное обеспечение NVIDIA/AMD будет использовать для выбора значения по умолчанию для приложения, которого нет в базе данных:

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

Другой вариант — не использовать адаптер по умолчанию при создании устройства и явно перечислять их. Это должно работать, но означает, что у пользователя больше нет возможности легко изменить используемое устройство. Пример кода перечисления см. в DeviceResources и метод GetHardwareAdapter в частности. Как я заметил выше, драйверы возятся с перечислением, поэтому «магический экспорт», вероятно, является лучшим общим решением.

person Chuck Walbourn    schedule 01.03.2017
comment
Спасибо за подробное объяснение. К сожалению, я уже использовал перечисление адаптеров и явно выбрал адаптер NVIDIA, а также попытался использовать панель управления NVIDIA, чтобы по умолчанию использовать их адаптер для всех новых созданий устройств Direct3D. Я подозреваю, что из-за того, что я нацелен на оконную цепочку обмена (не на полный экран) и что Windows уже использует адаптер Intel (вы не можете это изменить), единственная допустимая конфигурация — использовать адаптер Intel. Я думаю, мне нужно изменить свой код, чтобы сделать его полноэкранным, чтобы использовать предложенный вами метод. Я обновил код создания своего устройства для ясности. - person PhillipH; 02.03.2017