void DeviceResources::CreateWindowSizeDependentResources()

in src/GraphControl/DirectX/DeviceResources.cpp [233:447]


    void DeviceResources::CreateWindowSizeDependentResources()
    {
        // Clear the previous window size specific context.
        static constexpr std::array<ID3D11RenderTargetView*, 1> nullViews = { nullptr };
        m_d3dContext->OMSetRenderTargets(static_cast<UINT>(nullViews.size()), &nullViews[0], nullptr);
        m_d3dRenderTargetView = nullptr;
        m_d2dContext->SetTarget(nullptr);
        m_d2dTargetBitmap = nullptr;
        m_d3dDepthStencilView = nullptr;
        m_d3dContext->Flush1(D3D11_CONTEXT_TYPE_ALL, nullptr);

        UpdateRenderTargetSize();

        m_d3dRenderTargetSize.Width = m_outputSize.Width;
        m_d3dRenderTargetSize.Height = m_outputSize.Height;

        if (m_swapChain != nullptr)
        {
            // If the swap chain already exists, resize it.
            HRESULT hr = m_swapChain->ResizeBuffers(
                2, // Double-buffered swap chain.
                lround(m_d3dRenderTargetSize.Width),
                lround(m_d3dRenderTargetSize.Height),
                DXGI_FORMAT_B8G8R8A8_UNORM,
                0);

            if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)
            {
                // If the device was removed for any reason, a new device and swap chain will need to be created.
                HandleDeviceLost();

                // Everything is set up now. Do not continue execution of this method. HandleDeviceLost will reenter this method
                // and correctly set up the new device.
                return;
            }
            else
            {
                DX::ThrowIfFailed(hr);
            }
        }
        else
        {
            // Otherwise, create a new one using the same adapter as the existing Direct3D device.
            DXGI_SCALING scaling = DisplayMetrics::SupportHighResolutions ? DXGI_SCALING_NONE : DXGI_SCALING_STRETCH;
            DXGI_SWAP_CHAIN_DESC1 swapChainDesc = { 0 };

            swapChainDesc.Width = lround(m_d3dRenderTargetSize.Width);        // Match the size of the window.
            swapChainDesc.Height = lround(m_d3dRenderTargetSize.Height);
            swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;                // This is the most common swap chain format.
            swapChainDesc.Stereo = false;
            swapChainDesc.SampleDesc.Count = 1;                                // Don't use multi-sampling.
            swapChainDesc.SampleDesc.Quality = 0;
            swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
            swapChainDesc.BufferCount = 2;                                    // Use double-buffering to minimize latency.
            swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;    // All Windows Store apps must use _FLIP_ SwapEffects.
            swapChainDesc.Flags = 0;
            swapChainDesc.Scaling = scaling;
            swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE;

            // This sequence obtains the DXGI factory that was used to create the Direct3D device above.
            ComPtr<IDXGIDevice3> dxgiDevice;
            DX::ThrowIfFailed(
                m_d3dDevice.As(&dxgiDevice)
            );

            ComPtr<IDXGIAdapter> dxgiAdapter;
            DX::ThrowIfFailed(
                dxgiDevice->GetAdapter(&dxgiAdapter)
            );

            ComPtr<IDXGIFactory4> dxgiFactory;
            DX::ThrowIfFailed(
                dxgiAdapter->GetParent(IID_PPV_ARGS(&dxgiFactory))
            );

            // When using XAML interop, the swap chain must be created for composition.
            ComPtr<IDXGISwapChain1> swapChain;
            DX::ThrowIfFailed(
                dxgiFactory->CreateSwapChainForComposition(
                    m_d3dDevice.Get(),
                    &swapChainDesc,
                    nullptr,
                    &swapChain
                )
            );

            DX::ThrowIfFailed(
                swapChain.As(&m_swapChain)
            );

            // Associate swap chain with SwapChainPanel
            // UI changes will need to be dispatched back to the UI thread
            m_swapChainPanel->Dispatcher->RunAsync(CoreDispatcherPriority::High, ref new DispatchedHandler([=]()
            {
                // Get backing native interface for SwapChainPanel
                ComPtr<ISwapChainPanelNative> panelNative;
                DX::ThrowIfFailed(
                    reinterpret_cast<IUnknown*>(m_swapChainPanel)->QueryInterface(IID_PPV_ARGS(&panelNative))
                );

                DX::ThrowIfFailed(
                    panelNative->SetSwapChain(m_swapChain.Get())
                );
            }, CallbackContext::Any));

            // Ensure that DXGI does not queue more than one frame at a time. This both reduces latency and
            // ensures that the application will only render after each VSync, minimizing power consumption.
            DX::ThrowIfFailed(
                dxgiDevice->SetMaximumFrameLatency(1)
            );
        }

        // Set the proper orientation for the swap chain, and generate 2D and
        // 3D matrix transformations for rendering to the rotated swap chain.
        // Note the rotation angle for the 2D and 3D transforms are different.
        // This is due to the difference in coordinate spaces.  Additionally,
        // the 3D matrix is specified explicitly to avoid rounding errors.

        m_orientationTransform2D = Matrix3x2F::Identity();
        m_orientationTransform3D = ScreenRotation::Rotation0;

        // Setup inverse scale on the swap chain
        DXGI_MATRIX_3X2_F inverseScale = { 0 };
        inverseScale._11 = 1.0f / m_effectiveCompositionScaleX;
        inverseScale._22 = 1.0f / m_effectiveCompositionScaleY;
        ComPtr<IDXGISwapChain2> spSwapChain2;
        DX::ThrowIfFailed(
            m_swapChain.As<IDXGISwapChain2>(&spSwapChain2)
        );

        DX::ThrowIfFailed(
            spSwapChain2->SetMatrixTransform(&inverseScale)
        );

        // Create a render target view of the swap chain back buffer.
        ComPtr<ID3D11Texture2D1> backBuffer;
        DX::ThrowIfFailed(
            m_swapChain->GetBuffer(0, IID_PPV_ARGS(&backBuffer))
        );

        DX::ThrowIfFailed(
            m_d3dDevice->CreateRenderTargetView1(
                backBuffer.Get(),
                nullptr,
                &m_d3dRenderTargetView
            )
        );

        // Create a depth stencil view for use with 3D rendering if needed.
        CD3D11_TEXTURE2D_DESC1 depthStencilDesc(
            DXGI_FORMAT_D24_UNORM_S8_UINT,
            lround(m_d3dRenderTargetSize.Width),
            lround(m_d3dRenderTargetSize.Height),
            1, // This depth stencil view has only one texture.
            1, // Use a single mipmap level.
            D3D11_BIND_DEPTH_STENCIL
        );

        ComPtr<ID3D11Texture2D1> depthStencil;
        DX::ThrowIfFailed(
            m_d3dDevice->CreateTexture2D1(
                &depthStencilDesc,
                nullptr,
                &depthStencil
            )
        );

        CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D);
        DX::ThrowIfFailed(
            m_d3dDevice->CreateDepthStencilView(
                depthStencil.Get(),
                &depthStencilViewDesc,
                &m_d3dDepthStencilView
            )
        );

        // Set the 3D rendering viewport to target the entire window.
        m_screenViewport = CD3D11_VIEWPORT(
            0.0f,
            0.0f,
            m_d3dRenderTargetSize.Width,
            m_d3dRenderTargetSize.Height
        );

        m_d3dContext->RSSetViewports(1, &m_screenViewport);

        // Create a Direct2D target bitmap associated with the
        // swap chain back buffer and set it as the current target.
        D2D1_BITMAP_PROPERTIES1 bitmapProperties =
            D2D1::BitmapProperties1(
                D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW,
                D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED),
                m_dpi,
                m_dpi
            );

        ComPtr<IDXGISurface2> dxgiBackBuffer;
        DX::ThrowIfFailed(
            m_swapChain->GetBuffer(0, IID_PPV_ARGS(&dxgiBackBuffer))
        );

        DX::ThrowIfFailed(
            m_d2dContext->CreateBitmapFromDxgiSurface(
                dxgiBackBuffer.Get(),
                &bitmapProperties,
                &m_d2dTargetBitmap
            )
        );

        m_d2dContext->SetTarget(m_d2dTargetBitmap.Get());
        m_d2dContext->SetDpi(m_effectiveDpi, m_effectiveDpi);

        // Grayscale text anti-aliasing is recommended for all Windows Store apps.
        m_d2dContext->SetTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE);
    }