简体   繁体   中英

C++ Directx Error: Access Violation, swapchain was nullptr

I'm trying to learn 3D Drawing with DirectX and i got this Code in a Tutorial, but every time i try and compile it, my compiler gives out a "Access Violation swapchain was nullptr" Error.

Thanks in advance

   // include the basic windows header files and the Direct3D header files
    #include <windows.h>
    #include <windowsx.h>
    #include <d3d11.h>
    #include <d3dx11.h>
    #include <d3dx10.h>

    // include the Direct3D Library file
    #pragma comment (lib, "d3d11.lib")
    #pragma comment (lib, "d3dx11.lib")
    #pragma comment (lib, "d3dx10.lib")

    // global declarations
    IDXGISwapChain *swapchain;             // the pointer to the swap chain interface
    ID3D11Device *dev;                     // the pointer to our Direct3D device interface
    ID3D11DeviceContext *devcon;           // the pointer to our Direct3D device context
    ID3D11RenderTargetView *backbuffer;    // the pointer to our back buffer

    // function prototypes
    void InitD3D(HWND hWnd);    // sets up and initializes Direct3D
    void RenderFrame(void);     // renders a single frame
    void CleanD3D(void);        // closes Direct3D and releases memory

    // the WindowProc function prototype
    LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);


    // the entry point for any Windows program
    int WINAPI WinMain(HINSTANCE hInstance,
                       HINSTANCE hPrevInstance,
                       LPSTR lpCmdLine,
                       int nCmdShow)
    {
        HWND hWnd;
        WNDCLASSEX wc;

        ZeroMemory(&wc, sizeof(WNDCLASSEX));

        wc.cbSize = sizeof(WNDCLASSEX);
        wc.style = CS_HREDRAW | CS_VREDRAW;
        wc.lpfnWndProc = WindowProc;
        wc.hInstance = hInstance;
        wc.hCursor = LoadCursor(NULL, IDC_ARROW);
        wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
        wc.lpszClassName = L"WindowClass";

        RegisterClassEx(&wc);

        RECT wr = {0, 0, 800, 600};
        AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);

        hWnd = CreateWindowEx(NULL,
                              L"WindowClass",
                              L"Our First Direct3D Program",
                              WS_OVERLAPPEDWINDOW,
                              300,
                              300,
                              wr.right - wr.left,
                              wr.bottom - wr.top,
                              NULL,
                              NULL,
                              hInstance,
                              NULL);

        ShowWindow(hWnd, nCmdShow);

        // set up and initialize Direct3D
        InitD3D(hWnd);

        // enter the main loop:

        MSG msg;

        while(TRUE)
        {
            if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);

                if(msg.message == WM_QUIT)
                    break;
            }

            RenderFrame();
        }

        // clean up DirectX and COM
        CleanD3D();

        return msg.wParam;
    }


    // this is the main message handler for the program
    LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        switch(message)
        {
            case WM_DESTROY:
                {
                    PostQuitMessage(0);
                    return 0;
                } break;
        }

        return DefWindowProc (hWnd, message, wParam, lParam);
    }


    // this function initializes and prepares Direct3D for use
    void InitD3D(HWND hWnd)
    {
        // create a struct to hold information about the swap chain
        DXGI_SWAP_CHAIN_DESC scd;

        // clear out the struct for use
        ZeroMemory(&scd, sizeof(DXGI_SWAP_CHAIN_DESC));

        // fill the swap chain description struct
        scd.BufferCount = 1;                                    // one back buffer
        scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;     // use 32-bit color
        scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;      // how swap chain is to be used
        scd.OutputWindow = hWnd;                                // the window to be used
        scd.SampleDesc.Count = 1;                               // how many multisamples
        scd.SampleDesc.Quality = 0;                             // multisample quality level
        scd.Windowed = TRUE;                                    // windowed/full-screen mode

        // create a device, device context and swap chain using the information in the scd struct
        D3D11CreateDeviceAndSwapChain(NULL,
                                      D3D_DRIVER_TYPE_HARDWARE,
                                      NULL,
                                      NULL,
                                      NULL,
                                      NULL,
                                      D3D11_SDK_VERSION,
                                      &scd,
                                      &swapchain,
                                      &dev,
                                      NULL,
                                      &devcon);


        // get the address of the back buffer
        ID3D11Texture2D *pBackBuffer;
        swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);

        // use the back buffer address to create the render target
        dev->CreateRenderTargetView(pBackBuffer, NULL, &backbuffer);
        pBackBuffer->Release();

        // set the render target as the back buffer
        devcon->OMSetRenderTargets(1, &backbuffer, NULL);


        // Set the viewport
        D3D11_VIEWPORT viewport;
        ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT));

        viewport.TopLeftX = 0;
        viewport.TopLeftY = 0;
        viewport.Width = 800;
        viewport.Height = 600;

        devcon->RSSetViewports(1, &viewport);
    }


    // this is the function used to render a single frame
    void RenderFrame(void)
    {
        // clear the back buffer to a deep blue
        devcon->ClearRenderTargetView(backbuffer, D3DXCOLOR(0.0f, 0.2f, 0.4f, 1.0f));

        // do 3D rendering on the back buffer here

        // switch the back buffer and the front buffer
        swapchain->Present(0, 0);
    }


// this is the function that cleans up Direct3D and COM
void CleanD3D(void)
{
    // close and release all existing COM objects
    swapchain->Release();
    backbuffer->Release();
    dev->Release();
    devcon->Release();
}

When programming COM APis like Direct3D, it's critical that you check the return value of all functions that return an HRESULT . If it's safe to ignore the return value, then it will return void .

This means using the SUCCEEDED or FAILED macros on every HRESULT. You should avoid doing == S_OK or != S_OK as there are success results other than S_OK . With modern C++, an even better option is to use ThrowIfFailed for 'fatal fast fail' scenarios where your program cannot recover from a failure.

Your code is also failing to check for a failure in the call to RegisterClassEx or CreateWindowEx which could result in the hWnd being null before you really get started.

You should also consider using nullptr instead of NULL . You are passing NULL in places that actually take a UINT which only compiles since you are using the old-school preprocessor define for 0.

Once you are checking the return values, the next step is to enable the debug device. See Anatomy of Direct3D 11 Create Device and Direct3D SDK Debug Layer Tricks . The debug layer will provide additional information in the debug output window when returning common failures like E_INVALIDARG .

Note that BufferCount needs to be at least 2. Anything below 1 is treated as 2 anyhow.

Since you are new to Direct3D 11 programming, I recommend you take a look at the DirectX Tool Kit tutorials .

You should also initialize all variables.

IDXGISwapChain *swapchain = nullptr;
ID3D11Device *dev = nullptr;
ID3D11DeviceContext *devcon = nullptr;
ID3D11RenderTargetView *backbuffer = nullptr;

You should really avoid using 'raw' pointers for COM objects. A better choice is to use a COM smart-pointer like ComPtr .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM