2
\$\begingroup\$

I followed this tutorial and things were looking good. However, when switching to Fullscreen from 800x600 using alt-enter, I noticed an error in debug output:

DXGI WARNING: IDXGISwapChain::Present: Fullscreen presentation inefficiencies incurred due to application not using IDXGISwapChain::ResizeBuffers appropriately, specifying a DXGI_MODE_DESC not available in IDXGIOutput::GetDisplayModeList, or not using DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH

So I followed MSDN's article about DXGI and fullscreen. I noticed a few things:

  1. Implementing the MSDN article's code as is did not remove the error. WM_SIZE was being called in the function ran through with no errors thrown.

  2. Reading more, I added a section at the end (after viewport) to include swapChain->ResizeTarget. This didn't help.

  3. Normally, my swapChainDesc.flags is set to 0. I tried setting it to DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH as the error suggests, but then WM_SIZE is never sent to my application (with alt-enter), so the function to resizebuffers is never called.

  4. Implementing the MSDN code also caused switching to fullscreen to throw off my depth buffer(...I think). What happens is all models are drawn regardless of whether or not they are behind another model. Upon switching back to windowed mode via alt-enter, this behavior remains.

I've spent around 20 hours over the course of the week trying to figure out this fullscreen transition to no avail. I realize I could just run the Initialize() function for the D3D class of Rastertek's and toggle the fullscreen value, but that seems inefficient.

My code (I tried condensing it by removing error handling):

bool D3D::Initialize(int screenWidth, int screenHeight, bool vsync, HWND hWnd, bool fullscreen, float screenDepth, float screenNear)
{
    HRESULT result;
    IDXGIFactory* factory;
    IDXGIAdapter* adapter;
    IDXGIOutput* adapterOutput;
    unsigned int numerator, denominator;
    int error;
    DXGI_SWAP_CHAIN_DESC swapChainDesc;
    D3D_FEATURE_LEVEL featureLevel;
    ID3D11Texture2D* backBufferPtr;
    D3D11_TEXTURE2D_DESC depthBufferDesc;
    D3D11_DEPTH_STENCIL_DESC depthStencilDesc;
    D3D11_DEPTH_STENCIL_DESC depthDisabledStencilDesc;
    D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc;
    D3D11_RASTERIZER_DESC rasterDesc;
    D3D11_VIEWPORT viewport;
    float fieldOfView, screenAspect;
    D3D11_BLEND_DESC blendStateDesc;

    // Enumerate Display Modes and choose appropriate Refresh Rate
    CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&factory);
    factory->EnumAdapters(0, &adapter);
    adapter->EnumOutputs(0, &adapterOutput);
    adapterOutput->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, &numModes, NULL);
    displayModeList = new DXGI_MODE_DESC[numModes];
    adapterOutput->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, &numModes, displayModeList);

    // Iterate through Display Modes. displayModeList is a member variable for later use.
    GetRefreshRate(screenWidth, screenHeight, numerator, denominator);

    adapterOutput->Release();
    adapterOutput = 0;

    adapter->Release();
    adapter = 0;

    factory->Release();
    factory = 0;

    // Swap Chain Description
    ZeroMemory(&swapChainDesc, sizeof(swapChainDesc));
    swapChainDesc.BufferCount = 1;
    swapChainDesc.BufferDesc.Width = screenWidth;
    swapChainDesc.BufferDesc.Height = screenHeight;
    swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;

    // I'm going to assume VSYNC is enable for now
    swapChainDesc.BufferDesc.RefreshRate.Numerator = numerator;
    swapChainDesc.BufferDesc.RefreshRate.Denominator = denominator;

    swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    swapChainDesc.OutputWindow = hWnd;
    swapChainDesc.SampleDesc.Count = 1;
    swapChainDesc.SampleDesc.Quality = 0;
    swapChainDesc.Windowed = true;
    swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
    swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;

    // Regarding Flags, I've mentioned above that when not set to 0, WM_SIZE is not called when ALT-ENTER is pressed.
    //swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
    swapChainDesc.Flags = 0;

    featureLevel = D3D_FEATURE_LEVEL_11_0;

    // Create Swap Chain, D3D Device and Device Context
    D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, &featureLevel, 1, D3D11_SDK_VERSION, &swapChainDesc, &swapChain, &device, NULL, &deviceContext);
    swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&backBufferPtr);
    device->CreateRenderTargetView(backBufferPtr, NULL, &renderTargetView);
    backBufferPtr->Release();
    backBufferPtr = 0;

    // Set up Depth and Stencil Buffers
    ZeroMemory(&depthBufferDesc, sizeof(depthBufferDesc));
    depthBufferDesc.Width = screenWidth;
    depthBufferDesc.Height = screenHeight;
    depthBufferDesc.MipLevels = 1;
    depthBufferDesc.ArraySize = 1;
    depthBufferDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
    depthBufferDesc.SampleDesc.Count = 1;
    depthBufferDesc.SampleDesc.Quality = 0;
    depthBufferDesc.Usage = D3D11_USAGE_DEFAULT;
    depthBufferDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
    depthBufferDesc.CPUAccessFlags = 0;
    depthBufferDesc.MiscFlags = 0;

    // Create Depth/Stencil Buffer using description
    device->CreateTexture2D(&depthBufferDesc, NULL, &depthStencilBuffer);

    // Create Stencil State
    ZeroMemory(&depthStencilDesc, sizeof(depthStencilDesc));
    depthStencilDesc.DepthEnable = true;
    depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
    depthStencilDesc.DepthFunc = D3D11_COMPARISON_LESS;
    depthStencilDesc.StencilEnable = true;
    depthStencilDesc.StencilReadMask = 0xFF;
    depthStencilDesc.StencilWriteMask = 0xFF;

    // Stencil operation if Pixel is Front-Facing
    depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
    depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
    depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
    depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;

    // Stencil operation if Pixel is Back-Facing
    depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
    depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR;
    depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
    depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;

    // Create the Depth Stencil State
    device->CreateDepthStencilState(&depthStencilDesc, &depthStencilState);
    deviceContext->OMSetDepthStencilState(depthStencilState, 1);

    // Similar steps for Disabled Depth Stencil State - Omitted

    // Create Blend State - Omitted

    // Depth Stencil View Description and Creation - Omitted
    // Bind Depth Stencil and Render Target View to the Output Render Pipeline
    deviceContext->OMSetRenderTargets(1, &renderTargetView, depthStencilView);

    // Configure Rasterizer
    rasterDesc.AntialiasedLineEnable = false;
    rasterDesc.CullMode = D3D11_CULL_BACK;
    rasterDesc.DepthBias = 0;
    rasterDesc.DepthBiasClamp = 0.0f;
    rasterDesc.DepthClipEnable = true;
    rasterDesc.FillMode = D3D11_FILL_SOLID;
    rasterDesc.FrontCounterClockwise = false;
    rasterDesc.MultisampleEnable = false;
    rasterDesc.ScissorEnable = false;
    rasterDesc.SlopeScaledDepthBias = 0.0f;

    device->CreateRasterizerState(&rasterDesc, &rasterState);
    deviceContext->RSSetState(rasterState);

    // Setup and Create Viewport
    viewport.Width = (float)screenWidth;
    viewport.Height = (float)screenHeight;
    viewport.MinDepth = 0.0f;
    viewport.MaxDepth = 1.0f;
    viewport.TopLeftX = 0.0f;
    viewport.TopLeftY = 0.0f;

    deviceContext->RSSetViewports(1, &viewport);

    // Create various Matrices
}

And the ToggleFullscreen function (WM_SIZE calls this, sending LPARAM):

bool D3D::ToggleFullscreen(LPARAM lParam)
{
    if (swapChain)
    {
        unsigned int numerator, denominator;

        OutputDebugString(TEXT("Resizing\n"));

        deviceContext->OMSetRenderTargets(0, 0, 0);
        renderTargetView->Release();

        swapChain->ResizeBuffers(0, 0, 0, DXGI_FORMAT_UNKNOWN, 0);

        ID3D11Texture2D* backBufferPtr;

        swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&backBufferPtr);

        device->CreateRenderTargetView(backBufferPtr, NULL, &renderTargetView);

        backBufferPtr->Release();
        backBufferPtr = 0;

        // MSDN list a 0 for depthStencilview, so I figured it would make sense to call this the same way that I originally initialize.
        // With a 0, models are drawn when switched to Fullscreen, but the depth buffer seems foobarred. With depthStencilView (member pointer, not freed until Shutdown()), NOTHING displays
        // in Fullscreen, but when ALT-Enter to return to windowed, things are displaying properly.
        deviceContext->OMSetRenderTargets(1, &renderTargetView, depthStencilView);

        D3D11_VIEWPORT vp;
        vp.Width = LOWORD(lParam);
        vp.Height = HIWORD(lParam);
        vp.MinDepth = 0.0f;
        vp.MaxDepth = 1.0f;
        vp.TopLeftX = 0;
        vp.TopLeftY = 0;

        deviceContext->RSSetViewports(1, &vp);

        // This whole last section was added because I thought perhaps the correct Refresh Rates were not apparent the SwapChain, as the program is initialized in Windowed mode
        // numerator/denominator are passed By Ref
        GetRefreshRate(LOWORD(lParam), HIWORD(lParam), numerator, denominator);

        DXGI_SWAP_CHAIN_DESC dscd;
        DXGI_MODE_DESC dmd;

        swapChain->GetDesc(&dscd);
        dmd = dscd.BufferDesc;

        dmd.RefreshRate.Numerator = numerator;
        dmd.RefreshRate.Denominator = denominator;

        swapChain->ResizeTarget(&dmd);
    }

    return true;
}
\$\endgroup\$
  • \$\begingroup\$ Please add your code \$\endgroup\$ – Tordin Dec 19 '13 at 9:23
  • \$\begingroup\$ Also, I googled this for hours. I've read numerous times that this is an error with Win7 64-bit (my OS). I also get this from the DX SDK examples. Must Win7 users blit in Fullscreen? Or is this a debug output error? \$\endgroup\$ – Lokked Dec 20 '13 at 7:02
  • 1
    \$\begingroup\$ It might just be a warning then that might have been depricated. If it works, it works. For me everything looks okay. but i have never gotten that error. It might be GPU drivers aswell causing some havok. \$\endgroup\$ – Tordin Dec 20 '13 at 8:36
  • \$\begingroup\$ Alright, is ther a way I can tell if Present1 is doing a blit instead of a flip, as the error suggests? And do I need to recreate my depthStencilView after resizing the buffers? Could this be why all my models are being drawn regardless of being occluded? \$\endgroup\$ – Lokked Dec 20 '13 at 8:54
3
\$\begingroup\$

The problem with the models overlapping after ToggleFullscreen() is that the Depth Stencil View also needs to be recreated when the back buffer is resized. I made these modifications to ToggleFullscreen():

...
D3D11_TEXTURE2D_DESC depthBufferDesc;
D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc;

depthStencilView->Release();
depthStencilBuffer->Release();

ZeroMemory(&depthBufferDesc, sizeof(depthBufferDesc));
depthBufferDesc.Width = LOWORD(lParam);
depthBufferDesc.Height = HIWORD(lParam);
depthBufferDesc.MipLevels = 1;
depthBufferDesc.ArraySize = 1;
depthBufferDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
depthBufferDesc.SampleDesc.Count = 1;
depthBufferDesc.SampleDesc.Quality = 0;
depthBufferDesc.Usage = D3D11_USAGE_DEFAULT;
depthBufferDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
depthBufferDesc.CPUAccessFlags = 0;
depthBufferDesc.MiscFlags = 0;

// Create Depth/Stencil Buffer using description
device->CreateTexture2D(&depthBufferDesc, NULL, &depthStencilBuffer);

ZeroMemory(&depthStencilViewDesc, sizeof(depthStencilViewDesc));
depthStencilViewDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
depthStencilViewDesc.Texture2D.MipSlice = 0;

device->CreateDepthStencilView(depthStencilBuffer, &depthStencilViewDesc, &depthStencilView);

deviceContext->OMSetRenderTargets(1, &renderTargetView, depthStencilView);

// Set up Viewport as above

I still get the DXGI Error above, but as Tordin mentioned, it may just be a non-issue error, as I filled the window with models until my Frame Rate lowered to something acceptable, then switched to FullScreen and didn't notice any difference.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.