1

所以我正在学习 DirectX 11,我正在制作东西,我遇到了一个调试错误(试图从交换链访问 0x00000000),我认为 CreateDeviceAndSwapChain 应该解决这个问题,但它没有。这是我的代码:

 #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();
}

(顺便说一句,数据类型 uint 被定义为 unsigned int。)

请帮忙!

4

1 回答 1

1

如果仍然适用,我注意到它close()被放置在while(主)循环开始之前。它在之后被放置。这是您的代码部分:

// 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;
}

您需要close()在循环关闭后发生。请注意,将某些内容“放在循环内”意味着将某些内容从字面上放置在 while 循环内。在这里,你想要它TranslateMessage(&msg);,那么DispatchMessage(&msg);while(GetMessage(&msg, NULL, 0, 0)是真的。此外,您希望在此循环中运行您自己的函数。

随着循环一次又一次地发生,您希望每次都绘制框架。为此,您可以添加else, 并在其中运行函数。

IE:

// 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;
}

您可能会遇到违规,因为 COM 对象在循环开始之前已被释放。

于 2014-01-28T15:20:25.223 回答