如何使用DXGISwapChain BackBuffer渲染ID3D11Texture2D资源

时间:2017-11-23 10:29:56

标签: directx-11 direct3d11 dxgi

使用AcquireNextFrame DirectX11 API捕获Windows屏幕,我对渲染部分有太多困惑。如何使用ID3D11Texture2D backBuffer将DXGI_SWAP_CHAIN_DESC1资源渲染到窗口中。

在代码GetFrame(&Frame, &TimeOut)中,函数将从ID3D11Texture2D获取Frame,因此下一步是渲染部分。使用backBuffer交换链将每个Frame渲染到屏幕上。

我初始化了所有的设备和驱动程序,但不知道我哪里出错了,我为此做了太多的研发,但我仍然没有发现甚至是DirectX概念的新手,所以请有人指导我。

     using namespace DirectX;

    //--------------------------------------------------------------------------------------
    // Global Variables
    //--------------------------------------------------------------------------------------
    HINSTANCE               g_hInst = nullptr;
    HWND                    g_hWnd = nullptr;
    D3D_DRIVER_TYPE         g_driverType = D3D_DRIVER_TYPE_NULL;
    D3D_FEATURE_LEVEL       g_featureLevel = D3D_FEATURE_LEVEL_11_0;
    ID3D11Device*           g_pd3dDevice = nullptr;
    ID3D11Device1*          g_pd3dDevice1 = nullptr;
    ID3D11DeviceContext*    g_pImmediateContext = nullptr;
    ID3D11DeviceContext1*   g_pImmediateContext1 = nullptr;
    IDXGISwapChain*         g_pSwapChain = nullptr;
    IDXGISwapChain1*        g_pSwapChain1 = nullptr;
    ID3D11RenderTargetView* g_pRenderTargetView = nullptr;
    ID3D11Texture2D*        Frame;


    //--------------------------------------------------------------------------------------
    // Forward declarations
    //--------------------------------------------------------------------------------------
    HRESULT InitWindow( HINSTANCE hInstance, int nCmdShow );
    HRESULT InitDevice();
    void CleanupDevice();
    LRESULT CALLBACK    WndProc( HWND, UINT, WPARAM, LPARAM );
    void Render();



    //--------------------------------------------------------------------------------------
    // Entry point to the program. Initializes everything and goes into a message processing 
    // loop. Idle time is used to render the scene.
    //--------------------------------------------------------------------------------------
    int WINAPI wWinMain( _In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow )
    {
        UNREFERENCED_PARAMETER( hPrevInstance );
        UNREFERENCED_PARAMETER( lpCmdLine );

        if( FAILED( InitWindow( hInstance, nCmdShow ) ) )
            return 0;

        if( FAILED( InitDevice() ) )
        {
            CleanupDevice();
            return 0;
        }

        //DUPLICATIONMANAGER class which helps to capture windows screen 
        //For reduce space class code is not mentioned here  
        DUPLICATIONMANAGER DuplMgr;
        HRESULT Ret;
        // Main message loop
        MSG msg = {0};
        while( WM_QUIT != msg.message )
        {
            if( PeekMessage( &msg, nullptr, 0, 0, PM_REMOVE ) )
            {
                TranslateMessage( &msg );
                DispatchMessage( &msg );
            }
            else
            {

//GetFrame method will fetch ID3D11Texture2D resource using AcquireNextFrame API
//Now I have a ID3D11Texture2D Frame here how to render this resource in to backBuffer

                Ret = DuplMgr.GetFrame(&Frame, &TimeOut);

               if (Ret != DUPL_RETURN_SUCCESS)
               {
                   break;
               }
                Render();
            }
        }

        CleanupDevice();

        return ( int )msg.wParam;
    }


    //--------------------------------------------------------------------------------------
    // Register class and create window
    //--------------------------------------------------------------------------------------
    HRESULT InitWindow( HINSTANCE hInstance, int nCmdShow )
    {
        // Register class
        WNDCLASSEX wcex;
        wcex.cbSize = sizeof( WNDCLASSEX );
        wcex.style = CS_HREDRAW | CS_VREDRAW;
        wcex.lpfnWndProc = WndProc;
        wcex.cbClsExtra = 0;
        wcex.cbWndExtra = 0;
        wcex.hInstance = hInstance;
        wcex.hIcon = LoadIcon( hInstance, ( LPCTSTR )IDI_TUTORIAL1 );
        wcex.hCursor = LoadCursor( nullptr, IDC_ARROW );
        wcex.hbrBackground = ( HBRUSH )( COLOR_WINDOW + 1 );
        wcex.lpszMenuName = nullptr;
        wcex.lpszClassName = L"TutorialWindowClass";
        wcex.hIconSm = LoadIcon( wcex.hInstance, ( LPCTSTR )IDI_TUTORIAL1 );
        if( !RegisterClassEx( &wcex ) )
            return E_FAIL;

        // Create window
        g_hInst = hInstance;
        RECT rc = { 0, 0, 800, 600 };
        AdjustWindowRect( &rc, WS_OVERLAPPEDWINDOW, FALSE );
        g_hWnd = CreateWindow( L"TutorialWindowClass", L"Direct3D 11 Tutorial 1: Direct3D 11 Basics",
                               WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
                               CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, nullptr, nullptr, hInstance,
                               nullptr );
        if( !g_hWnd )
            return E_FAIL;

        ShowWindow( g_hWnd, nCmdShow );

        return S_OK;
    }


    //--------------------------------------------------------------------------------------
    // Create Direct3D device and swap chain
    //--------------------------------------------------------------------------------------
    HRESULT InitDevice()
    {
        HRESULT hr = S_OK;

        RECT rc;
        GetClientRect( g_hWnd, &rc );
        UINT width = rc.right - rc.left;
        UINT height = rc.bottom - rc.top;

        UINT createDeviceFlags = 0;
    #ifdef _DEBUG
        createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
    #endif

        D3D_DRIVER_TYPE driverTypes[] =
        {
            D3D_DRIVER_TYPE_HARDWARE,
            D3D_DRIVER_TYPE_WARP,
            D3D_DRIVER_TYPE_REFERENCE,
        };
        UINT numDriverTypes = ARRAYSIZE( driverTypes );

        D3D_FEATURE_LEVEL featureLevels[] =
        {
            D3D_FEATURE_LEVEL_11_1,
            D3D_FEATURE_LEVEL_11_0,
            D3D_FEATURE_LEVEL_10_1,
            D3D_FEATURE_LEVEL_10_0,
        };
        UINT numFeatureLevels = ARRAYSIZE( featureLevels );

        for( UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++ )
        {
            g_driverType = driverTypes[driverTypeIndex];
            hr = D3D11CreateDevice( nullptr, g_driverType, nullptr, createDeviceFlags, featureLevels, numFeatureLevels,
                                    D3D11_SDK_VERSION, &g_pd3dDevice, &g_featureLevel, &g_pImmediateContext );

            if ( hr == E_INVALIDARG )
            {
                // DirectX 11.0 platforms will not recognize D3D_FEATURE_LEVEL_11_1 so we need to retry without it
                hr = D3D11CreateDevice( nullptr, g_driverType, nullptr, createDeviceFlags, &featureLevels[1], numFeatureLevels - 1,
                                        D3D11_SDK_VERSION, &g_pd3dDevice, &g_featureLevel, &g_pImmediateContext );
            }

            if( SUCCEEDED( hr ) )
                break;
        }
        if( FAILED( hr ) )
            return hr;

        // Obtain DXGI factory from device (since we used nullptr for pAdapter above)
        IDXGIFactory1* dxgiFactory = nullptr;
        {
            IDXGIDevice* dxgiDevice = nullptr;
            hr = g_pd3dDevice->QueryInterface( __uuidof(IDXGIDevice), reinterpret_cast<void**>(&dxgiDevice) );
            if (SUCCEEDED(hr))
            {
                IDXGIAdapter* adapter = nullptr;
                hr = dxgiDevice->GetAdapter(&adapter);
                if (SUCCEEDED(hr))
                {
                    hr = adapter->GetParent( __uuidof(IDXGIFactory1), reinterpret_cast<void**>(&dxgiFactory) );
                    adapter->Release();
                }
                dxgiDevice->Release();
            }
        }
        if (FAILED(hr))
            return hr;

        // Create swap chain
        IDXGIFactory2* dxgiFactory2 = nullptr;
        hr = dxgiFactory->QueryInterface( __uuidof(IDXGIFactory2), reinterpret_cast<void**>(&dxgiFactory2) );
        if ( dxgiFactory2 )
        {
            // DirectX 11.1 or later
            hr = g_pd3dDevice->QueryInterface( __uuidof(ID3D11Device1), reinterpret_cast<void**>(&g_pd3dDevice1) );
            if (SUCCEEDED(hr))
            {
                (void) g_pImmediateContext->QueryInterface( __uuidof(ID3D11DeviceContext1), reinterpret_cast<void**>(&g_pImmediateContext1) );
            }

            DXGI_SWAP_CHAIN_DESC1 sd;
            ZeroMemory(&sd, sizeof(sd));
            sd.Width = width;
            sd.Height = height;
            sd.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
            sd.SampleDesc.Count = 1;
            sd.SampleDesc.Quality = 0;
            sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
            sd.BufferCount = 1;

            hr = dxgiFactory2->CreateSwapChainForHwnd( g_pd3dDevice, g_hWnd, &sd, nullptr, nullptr, &g_pSwapChain1 );
            if (SUCCEEDED(hr))
            {
                hr = g_pSwapChain1->QueryInterface( __uuidof(IDXGISwapChain), reinterpret_cast<void**>(&g_pSwapChain) );
            }

            dxgiFactory2->Release();
        }
        else
        {
            // DirectX 11.0 systems
            DXGI_SWAP_CHAIN_DESC sd;
            ZeroMemory(&sd, sizeof(sd));
            sd.BufferCount = 1;
            sd.BufferDesc.Width = width;
            sd.BufferDesc.Height = height;
            sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
            sd.BufferDesc.RefreshRate.Numerator = 60;
            sd.BufferDesc.RefreshRate.Denominator = 1;
            sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
            sd.OutputWindow = g_hWnd;
            sd.SampleDesc.Count = 1;
            sd.SampleDesc.Quality = 0;
            sd.Windowed = TRUE;

            hr = dxgiFactory->CreateSwapChain( g_pd3dDevice, &sd, &g_pSwapChain );
        }

        // Note this tutorial doesn't handle full-screen swapchains so we block the ALT+ENTER shortcut
        dxgiFactory->MakeWindowAssociation( g_hWnd, DXGI_MWA_NO_ALT_ENTER );

        dxgiFactory->Release();

        if (FAILED(hr))
            return hr;

        // Create a render target view
        ID3D11Texture2D* pBackBuffer = nullptr;
        hr = g_pSwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), reinterpret_cast<void**>( &pBackBuffer ) );
        if( FAILED( hr ) )
            return hr;

        hr = g_pd3dDevice->CreateRenderTargetView( pBackBuffer, nullptr, &g_pRenderTargetView );
        pBackBuffer->Release();
        if( FAILED( hr ) )
            return hr;

        g_pImmediateContext->OMSetRenderTargets( 1, &g_pRenderTargetView, nullptr );

        // Setup the viewport
        D3D11_VIEWPORT vp;
        vp.Width = (FLOAT)width;
        vp.Height = (FLOAT)height;
        vp.MinDepth = 0.0f;
        vp.MaxDepth = 1.0f;
        vp.TopLeftX = 0;
        vp.TopLeftY = 0;
        g_pImmediateContext->RSSetViewports( 1, &vp );

        return S_OK;
    }


    //--------------------------------------------------------------------------------------
    // Render the frame
    //--------------------------------------------------------------------------------------
    void Render()
    {           

        g_pSwapChain->Present( 0, 0 );
    }


    //--------------------------------------------------------------------------------------
    // Clean up the objects we've created
    //--------------------------------------------------------------------------------------
    void CleanupDevice()
    {
        if( g_pImmediateContext ) g_pImmediateContext->ClearState();

        if( g_pRenderTargetView ) g_pRenderTargetView->Release();
        if( g_pSwapChain1 ) g_pSwapChain1->Release();
        if( g_pSwapChain ) g_pSwapChain->Release();
        if( g_pImmediateContext1 ) g_pImmediateContext1->Release();
        if( g_pImmediateContext ) g_pImmediateContext->Release();
        if( g_pd3dDevice1 ) g_pd3dDevice1->Release();
        if( g_pd3dDevice ) g_pd3dDevice->Release();
    }

0 个答案:

没有答案