简单的 DirectX 11 程序运行时错误

Posted

技术标签:

【中文标题】简单的 DirectX 11 程序运行时错误【英文标题】:Simple DirectX 11 program runtime error 【发布时间】:2011-08-15 17:59:30 【问题描述】:

我是 DirectX 11 的新手,我已经设法在我的书中获得了绘图三角形章节。 我已经编写了这段代码,但出现运行时错误: “DirectX 11.exe 中 0x00cd14e6 处未处理的异常:0xc0000005:访问冲突读取位置 0x00000000。”

我的编译器显示错误出在 InitPipeline 函数处,但我在此处找不到错误。 我做错了什么?

代码:

    #include <windows.h>
#include <windowsx.h>

#include <d3d11.h>
#include <D3DX11.h>
#include <D3DX10.h>

#pragma comment(lib,"d3d11.lib")
#pragma comment(lib,"d3dx11.lib")
#pragma comment(lib,"d3dx10.lib")

#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 600

IDXGISwapChain                  *swapchain;
ID3D11Device                    *dev;
ID3D11DeviceContext             *devcon;

ID3D11InputLayout               *pInputLayout;
ID3D11Buffer                    *pVBuffer;
ID3D11RenderTargetView          *backbuffer;
ID3D11VertexShader              *pVS;
ID3D11PixelShader               *pPS;

// Type
struct VERTEX

    FLOAT X,Y,Z;
    D3DXCOLOR Color;
;
//DirectX
void InitPipeline()

    // load and compile the two shaders
     ID3D10Blob *VS, *PS;
     D3DX11CompileFromFile("shaders.hlsl", 0, 0, "VShader", "vs_5_0", 0, 0, 0, &VS, 0, 0);
     D3DX11CompileFromFile("shaders.hlsl", 0, 0, "PShader", "ps_5_0", 0, 0, 0, &PS, 0, 0);

     //debug
     if(!dev)
     
         MessageBox(NULL, "DEV = NULL", "ERROR", NULL);
     
     if(!devcon)
     
         MessageBox(NULL, "DEVCON = NULL", "ERROR", NULL);
     

     if(!VS)
     
         MessageBox(NULL, "VS = NULL", "ERROR", NULL);
     
     if(!PS)
     
         MessageBox(NULL, "PS = NULL", "ERROR", NULL);
     
     // encapsulate both shaders into shader objects
     dev->CreateVertexShader(VS->GetBufferPointer(), VS->GetBufferSize(), NULL, &pVS);
     dev->CreatePixelShader(PS->GetBufferPointer(), PS->GetBufferSize(), NULL, &pPS);

     // set the shader objects
     devcon->VSSetShader(pVS, 0, 0);
     devcon->PSSetShader(pPS, 0, 0);

    D3D11_INPUT_ELEMENT_DESC ied[] =
    
        "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0,0,D3D11_INPUT_PER_VERTEX_DATA,0,
        "COLOR",0,DXGI_FORMAT_R32G32B32A32_FLOAT,0,D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0,
    ;

    dev->CreateInputLayout(ied, 2, VS->GetBufferPointer(), VS->GetBufferSize(), &pInputLayout);
    devcon->IASetInputLayout(pInputLayout);



void InitGraphics()

    VERTEX OurVertices[] =
    
        1,0,0,D3DXCOLOR(1,0,0,1),
        0,-1,0,D3DXCOLOR(1,0,0,1),
        0,0,1,D3DXCOLOR(1,0,0,1),
    ;

    D3D11_BUFFER_DESC bd;
    ZeroMemory(&bd, sizeof(D3D11_BUFFER_DESC));
    bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
    bd.ByteWidth = sizeof(VERTEX)*3;
    bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
    bd.Usage = D3D11_USAGE_DYNAMIC;

    dev->CreateBuffer(&bd, NULL, &pVBuffer);

    D3D11_MAPPED_SUBRESOURCE ms;
    devcon->Map(pVBuffer, NULL, D3D11_MAP_WRITE_DISCARD, NULL, &ms);
    memcpy(ms.pData, OurVertices, sizeof(OurVertices));
    devcon->Unmap(pVBuffer, NULL);

void RenderFrame()

    devcon->ClearRenderTargetView(backbuffer, D3DXCOLOR(0,0,1,1));

    UINT stride = sizeof(VERTEX);
    UINT offset = 0;
    devcon->IASetVertexBuffers(0, 1, &pVBuffer, &stride, &offset);
    devcon->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
    devcon->Draw(3,0);

    swapchain->Present(0,0);

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.BufferDesc.Width = SCREEN_WIDTH;                   // set the back buffer width
     scd.BufferDesc.Height = SCREEN_HEIGHT;                 // set the back buffer height
     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 = 4;                              // how many multisamples
     scd.Windowed = TRUE;                                   // windowed/full-screen mode
     scd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;    // allow full-screen switching

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




     // 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 = SCREEN_WIDTH;
     viewport.Height = SCREEN_HEIGHT;

     devcon->RSSetViewports(1, &viewport);

    InitPipeline();
     InitGraphics();
 
void CleanD3D()

    swapchain->SetFullscreenState(FALSE, NULL);
    dev->Release();
    devcon->Release();
    swapchain->Release();
    pInputLayout->Release();
    pVBuffer->Release();
    backbuffer->Release();
    pVS->Release();
    pPS->Release();


// Window
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

    switch(message)
    
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    

INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, INT nCmdShow)

    HWND hWnd;

    WNDCLASSEX wc;
    ZeroMemory(&wc, sizeof(WNDCLASSEX));
    wc.cbSize = sizeof(WNDCLASSEX);
    //wc.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hIcon = (HICON)LoadIcon(NULL, IDI_APPLICATION);
    wc.hInstance = hInstance;
    wc.lpfnWndProc = WndProc;
    wc.lpszClassName = "DirectXWindow";
    wc.style = CS_HREDRAW | CS_VREDRAW;

    RegisterClassEx(&wc);

    hWnd = CreateWindowEx(NULL,
        "DirectXWindow",
        "DirectX 11 (June 2010",
        WS_OVERLAPPEDWINDOW,
        0,0,
        SCREEN_WIDTH, SCREEN_HEIGHT,
        NULL,
        NULL,
        hInstance,
        NULL);

    ShowWindow(hWnd, nCmdShow);

    InitD3D(hWnd);
    UpdateWindow(hWnd);

    MSG msg = 0;

    while(msg.message != WM_QUIT)
    
        if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        
            TranslateMessage(&msg);
            DispatchMessage(&msg);

        
        else
        
            RenderFrame();
        
    
    CleanD3D();

    return msg.wParam;

【问题讨论】:

在它崩溃之前放置一个断点,然后在调试器中单步执行代码。在每一行之前,查看下一行中使用的每个指针,看看它们中是否有任何一个是 0x00000000 【参考方案1】:

该错误基本上意味着您在某处使用了空指针。检查你所有的指针。我的猜测是某处的某些函数无法设置您的指针(或者您的参数顺序错误)。

【讨论】:

嗨!在我的书中,没有写任何关于分配和初始化的内容。即使在 DirectX 教程网页上,他们也不会初始化它们 link @Janman:我相信D3D11CreateDeviceAndSwapChain 应该初始化它们。正如我所说,检查你的指针。只有这样你才能找到答案。 我检查了我的“D3D11CreateDeviceAndSwapChain”,没有任何问题(我什至将网页中的“InitD3D()”函数复制粘贴到我的代码中)。仍然没有运气。我发现很难找到错误。 @Janman:检查指针。在InitPipeline() 中,类似if (!dev) std::cout &lt;&lt; "dev is null!\n"; 之类的代码用于其他指针。一旦你弄清楚哪个是空的,然后调查原因。调试没有什么魔力。 @Janman:shaders.hlsl 在正确的目录中吗?我猜这就是问题所在。对D3DX11CompileFromFile 进行失败检查,您应该会发现问题。【参考方案2】:

您正在使用NULL 指针。您定义了 8 个全局 D3D 接口指针,并且在 InitPipeline 中使用了 devdevcon,它们需要先分配和初始化,然后才能调用它们的任何方法。

【讨论】:

嗨!在我的书中,没有写任何关于分配和初始化的内容。即使在 DirectX 教程网页上,他们也不会初始化它们 link 创建函数返回一个HRESULT,您应该在使用设备之前检查它以确保它成功。我看不到您在代码 sn-p 中的哪个位置调用了任何 ID3D 创建函数:msdn.microsoft.com/en-us/library/ff476153(v=VS.85).aspx 已经添加了一个 if(FAILED()),我告诉我 DeviceAndSwapChain 它成功了。 (更新了问题中的代码)。 嗯,这是一个很好的猜测。我可以做更多的猜测,但调试起来会容易得多。断点、断言、日志或消息框。挑选你的毒药,找出哪个指针为空,何时变为空。【参考方案3】:

尝试设置 scd.SampleDesc.Count = 1

这个值告诉 Direct3D 应该在抗锯齿中投入多少细节,数字越大越好。 Direct3D 11 显卡在此保证最多支持 4 个,但最小值为 1 个。 也许您的显卡不支持 Direct3D 11?

【讨论】:

以上是关于简单的 DirectX 11 程序运行时错误的主要内容,如果未能解决你的问题,请参考以下文章

DirectX 11:运行简单的 DirectX 应用程序时运行时崩溃

Windows 8.1 上的 DirectX 11 缺少 SDK 组件

DirectX - 按 ctrl + alt + del 时出错

“无法初始化 Direct3d”

DirectX OMSetRenderTargets 中的访问冲突

DirectX11 执行警告 #355