1
\$\begingroup\$

I am currently writing a Directx 11 engine and have problems with the resolution when switching to exclusive fullscreen on my 1440p monitor. If i call SetFullscreenState(TRUE, NULL), the screen changes modes from 2560x1440 to 1920x1440 and my windows gets stretched. The WM_SIZE message also contains the size 1920x1440.

My initialization code (without error checking):

DXGI_SWAP_CHAIN_DESC swap_chain_desc = {0};
swap_chain_desc.BufferDesc.Width = window_data.width;
swap_chain_desc.BufferDesc.Height = window_data.height;
swap_chain_desc.BufferDesc.Format = DXGI_FORMAT.B8G8R8A8_UNORM;
swap_chain_desc.BufferDesc.Scaling = DXGI_MODE_SCALING.STRETCHED;
swap_chain_desc.SampleDesc.Count = 1;
swap_chain_desc.SampleDesc.Quality = 0;
swap_chain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swap_chain_desc.BufferCount = 2;
swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT.FLIP_DISCARD;
swap_chain_desc.OutputWindow = window_data.window_handle;
swap_chain_desc.Windowed = true;

//swap_chain_desc.Flags |= DXGI_SWAP_CHAIN_FLAG.ALLOW_MODE_SWITCH;

D3D_FEATURE_LEVEL feature_level;
UINT flags = D3D11_CREATE_DEVICE_FLAG.DEBUG;
HRESULT hr = D3D11CreateDeviceAndSwapChain(null, D3D_DRIVER_TYPE.HARDWARE, null, flags, null, 0, D3D11_SDK_VERSION, 
                                            &swap_chain_desc, &swap_chain, &device, &feature_level, &device_context);
d3d11_data.current_swap_chain_flags = swap_chain_desc.Flags;

When i get a WM_SIZE message, i resize the swap chain to the size passed as lParam. I also make sure not to change the swap chain flags when resizing:

    UINT width = LOWORD(lParam);
    UINT height = HIWORD(lParam);
    d3d11_data.device_context.OMSetRenderTargets(0, null, null);
    d3d11_data.render_target_view.Release();

    HRESULT hr = d3d11_data.swap_chain.ResizeBuffers(0, width, height, DXGI_FORMAT.UNKNOWN, d3d11_data.current_swap_chain_flags);

    ID3D11Texture2D framebuffer;
    hr = d3d11_data.swap_chain.GetBuffer(0, &IID_ID3D11Texture2D, cast(void**)&framebuffer);

    hr = d3d11_data.device.CreateRenderTargetView(framebuffer, null, &d3d11_data.render_target_view);
    framebuffer.Release();

    d3d11_data.device_context.OMSetRenderTargets(1, &d3d11_data.render_target_view, null);

    D3D11_VIEWPORT viewport = {0};
    viewport.Width = width;
    viewport.Height = height;
    viewport.MinDepth = 0.0f;
    viewport.MaxDepth = 1.0f;
    viewport.TopLeftX = 0;
    viewport.TopLeftY = 0;
    d3d11_data.device_context.RSSetViewports(1, &viewport);

I do not get any debug output nor do any of these functions return an error code. Things i have tried:

  • Messing with the compatibility setting of the application (DPI, "fullscreen optimization").

  • Ignoring the size passed with WM_SIZE and resizing the swap chain to 2560x1440.

  • Passing the DXGI_SWAP_CHAIN_FLAG.ALLOW_MODE_SWITCH flag and setting the render target to 2560x1440 using ResizeTarget and a DXGI_MODE_DESC optained via mode enumaration. This will change the refresh rate to e.g. 60Hz, but the resolution will still be 1920x1440.

  • Using a different windowed resolution before going fullscreen.

  • Enabling DXGI debug output via DXGIGetDebugInterface

None of them had any visible effect on the result. Windowed fullscreen via SetWindowPos works fine at the correct resolution. Any ideas on what might be happening?

\$\endgroup\$
2
  • \$\begingroup\$ Have you tried using D3D11_CREATE_DEVICE_DEBUG to see if any errors are reported? I'd also recommend adding assert(!FAILED(hr)); checks as a bare minimum when calling functions that return an HRESULT. \$\endgroup\$
    – Adam
    Oct 24, 2021 at 19:10
  • \$\begingroup\$ @Adam I already use D3D11_CREATE_DEVICE_DEBUG and as stated in the question, there is no debug output nor does any function return an error in hr. \$\endgroup\$
    – Kyto
    Oct 24, 2021 at 20:48

2 Answers 2

1
\$\begingroup\$

The problem was that i specified the scaling mode to be DXGI_MODE_SCALING_STRECHED, not DXGI_MODE_SCALING_UNSPECIFIED. As per the MSDN doc ( https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/bb173066(v=vs.85) ) this will change the resolution, even if the requested resolution is the entire screen.

\$\endgroup\$
0
\$\begingroup\$

One thing that's worth trying is enumerating the supported modes and picking one of those that matches the resolution you need, instead of creating your own DXGI_MODE_DESC. See https://docs.microsoft.com/en-us/windows/win32/direct3d11/overviews-direct3d-11-devices-get-adapter-info

Another option is to use IDXGIOutput::FindClosestMatchingMode() which will search through the available modes for you.

Also note that DXGI has a different way to enable debug mode than DX11, and that might help you diagnose what's going on as it generates extra debug output.

\$\endgroup\$
1
  • \$\begingroup\$ Hallo @Adam, I tried using a 2560x1440 DXGI_MODE_DESC obtained from mode enumeration but this will only change the refresh rate, the resolution will still be 1920x1440. I also already enabled DXGI debug output. \$\endgroup\$
    – Kyto
    Oct 25, 2021 at 8:07

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .