• Advertisement
Sign in to follow this  

D3D11 Fullscreen Not Sticking

This topic is 1118 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I am trying to add fullscreen to a D3D11 program I have (not just a borderless window). It seems to attempt to go fullscreen with the monitor going black for a moment but fail and revert to a window. I can't see what would cause this, and it happens if I use DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH and attempt to go fullscreen with Alt+Enter as well. VS debug output shows no complaining from the device.

 

The window is created with "WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU", and I have validated that the backbuffer and depth buffer get my native monitor resolution of 1920x1080. The device is created with "D3D11_CREATE_DEVICE_SINGLETHREADED | D3D11_CREATE_DEVICE_DEBUG"

 

Given that I do not expierence this with any games or other software on my system, I am fairly sure its my code doing something wrong here.

 

Complete working code is below, should compile directly with MSVC (tested on 2013). I striped just the window and D3D creation out (including error handling and cleanup), although its still fairly long.

 
#include <Windows.h>
#include <dxgi.h>
#include <d3d11.h>
#include <stdexcept>
#include <string>

#pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "DXGI.lib")

HWND hwnd = NULL;
bool run = true;
ID3D11Device *d3d11Device;
ID3D11DeviceContext *d3d11Context;
IDXGISwapChain *d3dSwapChain;
ID3D11Texture2D *d3d11BackBuffer;
ID3D11RenderTargetView *d3d11BackBufferTarget;
ID3D11DepthStencilView *d3d11DepthStencilView;

enum WindowMode
{
    WINDOW_WINDOWED,
    WINDOW_BORDERLESS,
    WINDOW_FULLSCREEN
};


void createWindow(unsigned width, unsigned height, WindowMode mode);
void createD3d11(unsigned width, unsigned height, WindowMode mode);
LRESULT __stdcall wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
    
    WindowMode mode = WINDOW_FULLSCREEN;

    createWindow(1920, 1080, mode);

    RECT rect;
    if (mode == WINDOW_WINDOWED)
        GetClientRect(hwnd, &rect);
    else GetWindowRect(hwnd, &rect);
    createD3d11(rect.right - rect.left, rect.bottom - rect.top, mode);

    //loop
    while (run)
    {
        MSG msg;
        while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        d3d11Context->ClearDepthStencilView(d3d11DepthStencilView, D3D11_CLEAR_DEPTH, 1, 0);
        float col[4] = { 0, 0, 1, 1 };
        d3d11Context->ClearRenderTargetView(d3d11BackBufferTarget, col);
        d3dSwapChain->Present(1, 0);
        Sleep(1000 / 30);
    }
    //exit
    return 0;
}


void createWindow(unsigned width, unsigned height, WindowMode mode)
{
    int style;
    if (mode == WINDOW_BORDERLESS)
        style = WS_POPUP;
    else style = WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU;

    //Need a window class
    WNDCLASSEX cls = { 0 };
    cls.cbSize = sizeof(cls);
    cls.style = /*CS_DBLCLKS |*/ CS_OWNDC;
    cls.lpfnWndProc = &wndProc;
    cls.cbClsExtra = 0;
    cls.cbWndExtra = 0;
    cls.hInstance = NULL;
    cls.hIcon = NULL;
    cls.hCursor = LoadCursor(NULL, IDC_ARROW);
    cls.hbrBackground = 0; //(HBRUSH)(COLOR_WINDOW+1);
    cls.lpszMenuName = NULL;
    cls.lpszClassName = L"window";
    cls.hIconSm = NULL;

    RegisterClassEx(&cls);
    //Create the window
    DWORD styleEx = 0;
    hwnd = CreateWindowEx(styleEx, L"window", L"Test Window",
        style,
        CW_USEDEFAULT, CW_USEDEFAULT,
        width, height,
        NULL, NULL, NULL, NULL);
    ShowWindow(hwnd, SW_SHOW);
}

LRESULT __stdcall wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
    case WM_CLOSE:
        run = false;
        return 0;
    default:
        return DefWindowProc(hwnd, msg, wParam, lParam);
    }
}


void createD3d11(unsigned width, unsigned height, WindowMode mode)
{
    IDXGIFactory1 *dxgiFactory = NULL;
    UINT flags = D3D11_CREATE_DEVICE_SINGLETHREADED | D3D11_CREATE_DEVICE_DEBUG;

    D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_11_0 };
    unsigned featureLevelsLen = (unsigned)(sizeof(featureLevels) / sizeof(featureLevels[0]));
    D3D_FEATURE_LEVEL featureLevel;

    CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)&dxgiFactory);
    D3D11CreateDevice(
        NULL,
        D3D_DRIVER_TYPE_HARDWARE,
        NULL,
        flags,
        featureLevels,
        featureLevelsLen,
        D3D11_SDK_VERSION,//7
        &d3d11Device,
        &featureLevel,
        &d3d11Context);

    //Swap chain
    DXGI_SAMPLE_DESC renderTargetSampleDesc;
    renderTargetSampleDesc.Count = 4;
    renderTargetSampleDesc.Quality = D3D11_STANDARD_MULTISAMPLE_PATTERN;

    DXGI_SWAP_CHAIN_DESC swapChainDesc = { 0 };
    swapChainDesc.BufferCount = 1;
    swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    //TODO: This needs to be either user defined or taken from the monitor
    swapChainDesc.BufferDesc.RefreshRate.Numerator = 60;
    swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
    swapChainDesc.BufferDesc.Width = width;
    swapChainDesc.BufferDesc.Height = height;
    swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    swapChainDesc.OutputWindow = hwnd;
    swapChainDesc.SampleDesc = renderTargetSampleDesc;
    swapChainDesc.Windowed = mode != WINDOW_FULLSCREEN;
    swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
    swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;

    dxgiFactory->CreateSwapChain(d3d11Device, &swapChainDesc, &d3dSwapChain);
    //Depth stencil
    ID3D11Texture2D *d3d11DepthStencilTexture = NULL;
    D3D11_TEXTURE2D_DESC depthStencilTextureDesc;
    memset(&depthStencilTextureDesc, 0, sizeof(depthStencilTextureDesc));
    depthStencilTextureDesc.Width = width;
    depthStencilTextureDesc.Height = height;
    depthStencilTextureDesc.MipLevels = 1;
    depthStencilTextureDesc.ArraySize = 1;
    depthStencilTextureDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
    depthStencilTextureDesc.SampleDesc = renderTargetSampleDesc;
    depthStencilTextureDesc.Usage = D3D11_USAGE_DEFAULT;
    depthStencilTextureDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
    depthStencilTextureDesc.CPUAccessFlags = 0;
    depthStencilTextureDesc.MiscFlags = 0;
    d3d11Device->CreateTexture2D(&depthStencilTextureDesc, NULL, &d3d11DepthStencilTexture);

    D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc;
    memset(&depthStencilViewDesc, 0, sizeof(depthStencilViewDesc));
    depthStencilViewDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
    depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
    depthStencilViewDesc.Texture2D.MipSlice = 0;
    d3d11Device->CreateDepthStencilView(d3d11DepthStencilTexture, &depthStencilViewDesc, &d3d11DepthStencilView);


    //render target
    d3dSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&d3d11BackBuffer);
    d3d11Device->CreateRenderTargetView(d3d11BackBuffer, NULL, &d3d11BackBufferTarget);

    dxgiFactory->Release();


    d3d11Context->OMSetRenderTargets(1, &d3d11BackBufferTarget, d3d11DepthStencilView);
    //viewport
    D3D11_VIEWPORT viewport;
    viewport.TopLeftX = 0;
    viewport.TopLeftY = 0;
    viewport.Width = (float)width;
    viewport.Height = (float)height;
    viewport.MinDepth = 0;
    viewport.MaxDepth = 1;
    d3d11Context->RSSetViewports(1, &viewport);
}

Edited by SyncViews

Share this post


Link to post
Share on other sites
Advertisement
Sign in to follow this  

  • Advertisement