alecgirman
alecgirman

Reputation: 23

DirectX 11: Null Swap Chain

so I am learning DirectX 11 and I was making stuff and I came across a debugging error (trying to access 0x00000000 from the swap chain) and I thought the CreateDeviceAndSwapChain was supposed to fix that but it didnt. Here is my code:

 #include <windows.h>
 #include <d3d11.h>
 #include <d3dx11.h>
 #include <dxgi.h>
 #include "types.h"  

 //globals
 RECT dimensions;
 HWND hwnd;

 //width and height of the window
 uint width;
 uint height;

//create the driver types
D3D_DRIVER_TYPE dt[] = {
    D3D_DRIVER_TYPE_HARDWARE, D3D_DRIVER_TYPE_WARP, D3D_DRIVER_TYPE_SOFTWARE
};

//create the feature level
D3D_FEATURE_LEVEL fl[] = {
    D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_0, D3D_FEATURE_LEVEL_10_1  
};

//create the selected drivertype
D3D_DRIVER_TYPE selectedDT;

//create the selected feature level
D3D_FEATURE_LEVEL* selectedFL;

//create driver types and feature level uints
uint totalDTs = ARRAYSIZE(dt);
uint totalFLs = ARRAYSIZE(fl); 

//create the swap chain description
DXGI_SWAP_CHAIN_DESC scd;

//create the swap chain
IDXGISwapChain* swapchain; 

//create the device
ID3D11Device* dev;

//create the context
ID3D11DeviceContext* context;

//create the render target view
ID3D11RenderTargetView *rtv;

//functions
void init();
void initswapchaindesc();
void createDevice();
void close();

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

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    // window handler
    HWND hwnd;
    // this struct holds information for the window class
    WNDCLASSEX wc;

    ZeroMemory(&wc, sizeof(WNDCLASSEX));

    // fill the struct
    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 = "WindowClass1";

    // register the window class
    RegisterClassEx(&wc);

    hwnd = CreateWindowEx(NULL,
                          "WindowClass1",    // name of the window class
                          "Our First Windowed Program",   // title of the window
                          WS_OVERLAPPEDWINDOW,    // window style
                          300,    // x-position of the window
                          300,    // y-position of the window
                          800,    // width of the window
                          600,    // height of the window
                          NULL,    // we have no parent window, NULL
                          NULL,    // we aren't using menus, NULL
                          hInstance,    // application handle
                          NULL);    // used with multiple windows, NULL

    // display the window
    ShowWindow(hwnd, nCmdShow);

    // enter the main loop:
    init();
    close();
    MessageBox(hwnd, "Success!", "A message for you", NULL);

    // this struct holds Windows event messages
    MSG msg;

    // wait for the next message in the queue
    while(GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);

        DispatchMessage(&msg);
    }

    return msg.wParam;
}

LRESULT CALLBACK WindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch(message)
    {
        // the quit message
        case WM_DESTROY:
            {
        //quit
                PostQuitMessage(0);
                return 0;
            } 
        break;
    }

    // def message
    return DefWindowProc (hwnd, message, wParam, lParam);
} 

void init() {
    GetClientRect(hwnd, &dimensions);
    width = dimensions.right - dimensions.left;
    height = dimensions.bottom - dimensions.top;

    //initialize the swap chain description
    ZeroMemory(&scd, sizeof(scd));
    scd.BufferCount = 1;
    scd.BufferDesc.Width = width;
    scd.BufferDesc.Height = height;
    scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    scd.BufferDesc.RefreshRate.Denominator = 60;
    scd.BufferDesc.RefreshRate.Numerator = 1;
    scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    scd.OutputWindow = hwnd;
    scd.Windowed = true;
    scd.SampleDesc.Count = 1;
    scd.SampleDesc.Quality = 0;

    uint creationflags;

#ifdef _DEBUG
    creationflags |= D3D11_CREATE_DEVICE_DEBUG;
#endif

    HRESULT devcreateres;
    uint driver = 0;

    for(driver = 0; driver < totalDTs; ++driver) {
        devcreateres = D3D11CreateDeviceAndSwapChain(0, dt[driver], 0, creationflags, fl, totalFLs, 
            D3D11_SDK_VERSION, &scd, &swapchain, &dev, 
            selectedFL, &context);

        if(SUCCEEDED(devcreateres)) {
            selectedDT = dt[driver];
        }
    }

    //create the back buffer image
    ID3D11Texture2D* backbuffer;

    //error here - line 175
    swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&backbuffer);
    dev->CreateRenderTargetView(backbuffer, NULL, &rtv);
    backbuffer->Release();
    context->OMSetRenderTargets(1, &rtv, NULL);

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

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

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

void close() {
    if(swapchain)
        swapchain->Release();
    if(dev)
        dev->Release();
    if(context)
        context->Release();
    if(rtv)
        rtv->Release();
}

(btw the data type uint is defined as unsigned int.)

Please help!

Upvotes: 1

Views: 1979

Answers (1)

Rashid Ellis
Rashid Ellis

Reputation: 330

If still applicable, I noticed that close() was placed before the start of the while (main) loop. It gets placed afterwards. Here's your section of code:

// enter the main loop:
init();
close();
MessageBox(hwnd, "Success!", "A message for you", NULL);

// this struct holds Windows event messages
MSG msg;

// wait for the next message in the queue
while(GetMessage(&msg, NULL, 0, 0))
{
    TranslateMessage(&msg);

    DispatchMessage(&msg);
}

return msg.wParam;
}

You need close() to happen after the loop is closed. Note that placing something "inside the loop" means placing something literally, inside the while loop. Here, you want it to TranslateMessage(&msg);, then DispatchMessage(&msg); while(GetMessage(&msg, NULL, 0, 0) is true. Additionally you want to run you own functions to happen in this loop.

As the loop happens over and over again, you want to draw your frame each time. To do this you can add else, an run the function inside.

i.e:

// enter the main loop:
init();
MessageBox(hwnd, "Success!", "A message for you", NULL);

// this struct holds Windows event messages
MSG msg;

// wait for the next message in the queue
while(GetMessage(&msg, NULL, 0, 0))
{
    TranslateMessage(&msg);

    DispatchMessage(&msg);
}
else
{
    render(); //Your render function.
}
close(); //If this is run, the while loop has closed. This is a good opportunity 
         //to run close() before the function returns msg.wParam
return msg.wParam;
}

You could be getting the violation because the COM objects were released before the loop was started.

Upvotes: 1

Related Questions