D3D11CreateDeviceAndSwapChain does not swap to full screen on 2nd monitor
Asked Answered
A

0

8

The original problem that I ran into, was that I wasn't able to get my game to run in full screen on my 2nd monitor. Going to display settings and swapping main display from 2nd to 1st, lets my game run in full screen without any problems. The resolution on both of my monitors is identical so the problem has to be somewhere else. displays

The code that is responsible for the full screen swap looks like this:

// create device and front/back buffers
if( FAILED( hr = D3D11CreateDeviceAndSwapChain( 
    nullptr,
    D3D_DRIVER_TYPE_HARDWARE,
    nullptr,
    createFlags,
    nullptr,
    0,
    D3D11_SDK_VERSION,
    &sd,
    &pSwapChain,
    &pDevice,
    nullptr,
    &pImmediateContext ) ) )
{
    throw CHILI_GFX_EXCEPTION( hr,L"Creating device and swap chain" );
}

while the swap chain description sd was previously created like this:

// create device and swap chain/get render target view
DXGI_SWAP_CHAIN_DESC sd = {};
sd.BufferCount = 1;
sd.BufferDesc.Width = Graphics::ScreenWidth;
sd.BufferDesc.Height = Graphics::ScreenHeight;
sd.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
sd.BufferDesc.RefreshRate.Numerator = 1;
sd.BufferDesc.RefreshRate.Denominator = 60;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.OutputWindow = key.hWnd;
sd.SampleDesc.Count = 1;
sd.SampleDesc.Quality = 0;
sd.Windowed = !f;
sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;

f is set to true and the code does exactly what I want it to do on monitor 1, however the window remains windowed on monitor 2. hr is also S_OK suggesting that everything went fine.

DXGI Reference says that:

We recommend that you create a windowed swap chain and allow the end user to change the swap chain to full screen through IDXGISwapChain::SetFullscreenState;

Quick modification to the code to set the full screen state with the swap chain method results in:

hr = pSwapChain->SetFullscreenState(TRUE, vOutput[0]);

The HRESULT hr says that the method failed with E_FAIL.

As an extra test, changing vOutput[0] to vOutput[1] makes my game work in full screen on another monitor without any problems.

Trying to find information about this led me to multiple steam forum posts where different users were experiencing same type of error when trying to go full screen in games like Devil May Cry 4, Company of Heroes 2 or Resident Evil 5. A thing that all of these posts had in common was that the game didn't run in full screen on 2nd monitor. From the information in these posts I also discovered that full screen will work if the screen resolution is set at 1680x1050 or lower.

This leads me to believe that the actual bug might be somewhere inside direct3D files, but where?

Why is SetFullscreenState returning E_FAIL and D3D11CreateDeviceAndSwapChain does nothing and how can I make it work?

If it's not possible, what's a good replacement for the SetFullscreenState that achieves the same goal?

Adelladella answered 19/5, 2018 at 22:37 Comment(8)
Could it be that you create window with default placement at primary display, then create swap chain and then try to move window on secondary display? The recommended way to create a swap chain is to create swap chain in windowed mode and then make it full screen on particular output by calling IDXGISwapChain::SetFullscreenState supplying pointer to desired DXGI Output.Bonin
I'm not sure how to identify which monitor is being used for the initial window creation, but the initial window spawns on monitor 2 even before swap chain. As for pSwapChain->SetFullscreenState - it always returns E_FAIL so I might need some help on setting that one up too.Hoebart
Well, in order to create swap chain that can be switched between windowed / fullscreen mode you will need to specify DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH flag. Also notice that RefreshRate that you are currently passing when creating swap chain (60 Hz) does not match actual display refresh rate (59 Hz) of the second display.Bonin
I have tried different refresh rates on both monitors with no success. As for swap chain flags - I'm using the framework code I'm not very familiar with how the DXGI interfaces work and msdn lacks examples so I'd appreciate an example from you.Hoebart
I have now successfully managed to test SetFullscreenSate with both IDXGIOutput (one for montor 1 and one for monitor 2) and while the method returns S_OK for monitor 1, it fails with E_FAIL on monitor 2.Hoebart
You might have an easier time figuring out what is going on by avoiding the legacy combo device and swapchain creation function and doing the individual steps. See Anatomy of Direct3D 11 Create Device. There are some known issues trying to do FSE (fullscreen exclusive) with multiple devices at the same time if they are using different drivers.Gardia
I'll randomly guess that these monitors are operating at different DPI settings. A feature available since Win8.1. https://mcmap.net/q/595615/-how-can-i-set-the-dpiaware-property-in-a-windows-application-manifest-to-quot-per-monitor-quot-in-visual-studio/17034Gape
Just FYI, DXGI_MODE_DESC::RefreshRate measures hertz, so I'm going to guess that your numerator and denominator are backwards there.Indefatigable

© 2022 - 2024 — McMap. All rights reserved.