【问题标题】:Windows freezes after trying to render triangle in directx11尝试在 directx11 中渲染三角形后 Windows 冻结
【发布时间】:2016-10-04 10:47:20
【问题描述】:

我是 Directx 编程的新手,所以我开始使用 dx11 在线学习一些教程。 我可以很好地初始化win32窗口和directx11,但是当我尝试绘制三角形窗口时,它会冻结我的电脑,所以我必须重新启动它。我已经寻找解决方案,但没有任何帮助。

这是我的 WinMain 代码:

#include "DXApp.h"
#include<DirectXMath.h>


class App : public DXApp {
public:
App(HINSTANCE hInstance);
~App();

bool Init() override;
void Update(float dt) override;
void Render(float dt) override;

};

int WINAPI WinMain(__in HINSTANCE hInstance, __in_opt HINSTANCE hPrevInstance, __in LPSTR lpCmdLine, __in int nShowCmd) {
App app(hInstance);

if (!app.Init()) return 1;

return app.Run();
}

App::App(HINSTANCE hInstance) : DXApp(hInstance)
{
}

App::~App()
{
}

bool App::Init()
{
return DXApp::Init();
}

void App::Update(float dt)
{
}

    void App::Render(float dt)
{
    immediateContext->ClearRenderTargetView(renderTargetView, DirectX::Colors::CornflowerBlue);
    immediateContext->Draw(3, 0);
    swapChain->Present(0, 0);
}

还有我的应用标头和 cpp:

DXApp.h:

#pragma once
#include<Windows.h>
#include<string>
#include"DXUtil.h"
#include<d3dcompiler.h>
#pragma comment(lib, "d3dcompiler.lib")
#define WIN32_LEAN_AND_MEAN

class DXApp
{
public:
DXApp(HINSTANCE hInstance);
void cleanUp();
virtual ~DXApp(void);

//MAIN APPLICATION LOOP

int Run();

//FRAMEWORK METHODS

virtual bool Init();
virtual void Update(float dt) = 0;
virtual void Render(float dt) = 0;
virtual LRESULT MsgProc(HWND hwnd, unsigned int msg, WPARAM wParam, LPARAM lParam);

protected:

HWND            hAppWnd;
HINSTANCE       hAppInstance;
unsigned int    ClientWidth;
unsigned int    ClientHeight;
std::string     AppTitle;
DWORD           WindStyle;

//DIRECTX ATTRIBUTES

ID3D11Device*               device;
ID3D11DeviceContext*        immediateContext;
IDXGISwapChain*             swapChain;
ID3D11RenderTargetView*     renderTargetView;
D3D_DRIVER_TYPE             driverType;
D3D_FEATURE_LEVEL           featureLevel;
D3D11_VIEWPORT              viewport;

ID3D11Buffer*               triangleVertBuffer;
ID3D11PixelShader*          pixelShader;
ID3D11VertexShader*         vertexShader;
ID3D10Blob*                 VSBuffer;
ID3D10Blob*                 PSBuffer;
ID3D11InputLayout*          vertLayout;

protected:

//INITIALZE WIN32 WINDOW

bool windowInit();

//INITIALIZE DIRECTX

bool direct3dInit();
};

DXApp.cpp:

#include "DXApp.h"

命名空间{

DXApp * g_pApp = nullptr;
}

LRESULT CALLBACK MainWndProc(HWND hwnd, unsigned int msg, WPARAM wParam, LPARAM lParam) {

if (g_pApp) return g_pApp->MsgProc(hwnd, msg, wParam, lParam);
否则返回 DefWindowProc(hwnd, msg, wParam, lParam);
}



//顶点

结构顶点{
顶点()​​{}
顶点(float x,float y,float z):pos(x,y,z){}
DirectX::XMFLOAT3 位置;

};

D3D11_INPUT_ELEMENT_DESC 布局[] = {
{ "位置", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
无符号整数 numLayoutElements = ARRAYSIZE(布局);



DXApp::DXApp(HINSTANCE hInstance)
{
hAppInstance = hInstance;
hAppWnd = NULL;
客户端宽度 = 1280;
客户端高度 = 720;
AppTitle = "DirectX11 引擎";
WindStyle = WS_OVERLAPPEDWINDOW;
g_pApp = 这个;

//直接发送

设备 = nullptr;
交换链 = nullptr;
立即上下文 = nullptr;
渲染目标视图 = nullptr;

顶点着色器 = nullptr;
像素着色器 = nullptr;
triangleVertBuffer = nullptr;
VSBuffer = nullptr;
PSBuffer = nullptr;
vertLayout = nullptr;
}

无效 DXApp::cleanUp()
{
if (immediateContext) immediateContext->ClearState();
内存::SafeRelease(renderTargetView);
内存::SafeRelease(immediateContext);
内存::SafeRelease(swapChain);
内存::SafeRelease(设备);

内存::SafeRelease(vertLayout);
内存::SafeRelease(PSBuffer);
内存::SafeRelease(VSBuffer);
内存::SafeRelease(triangleVertBuffer);
内存::SafeRelease(pixelShader);
内存::SafeRelease(vertexShader);
}


DXApp::~DXApp()
{
//直接清除
if (immediateContext) immediateContext->ClearState();
内存::SafeRelease(renderTargetView);
内存::SafeRelease(immediateContext);
内存::SafeRelease(swapChain);
内存::SafeRelease(设备);

内存::SafeRelease(vertLayout);
内存::SafeRelease(PSBuffer);
内存::SafeRelease(VSBuffer);
内存::SafeRelease(triangleVertBuffer);
内存::SafeRelease(pixelShader);
内存::SafeRelease(vertexShader);
}


int DXApp::Run() {

味精味精 = { 0 };
而(WM_QUIT!= msg.message){
    if (PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE)) {
        TranslateMessage(&msg);
        调度消息(&msg);
    }
    别的 {
        更新(0.0f);

        渲染(0.0f);
    }
}
return static_cast(msg.wParam);
}

布尔 DXApp::Init()
{
如果(!windowInit()){
    返回假;
}

如果(!direct3dInit()){
    返回假;
}

返回真;
}

布尔 DXApp::windowInit()
{
WNDCLASSEX wcex;
ZeroMemory(&wcex, sizeof(WNDCLASSEX));

wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.hInstance = hAppInstance;
wcex.lpfnWndProc = MainWndProc;
wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = "DXAPPWNDCLASS";
wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

if (!RegisterClassEx(&wcex)) {
    OutputDebugString("\n创建窗口类失败!!\n");
    返回假;
}

RECT r = { 0, 0, ClientWidth, ClientHeight };
AdjustWindowRect(&r, WindStyle, false);

无符号整数宽度 = r.right - r.left;
无符号整数高度 = r.bottom - r.top;

无符号整数 x = GetSystemMetrics(SM_CXSCREEN) / 2 - 宽度 / 2;
无符号整数 y = GetSystemMetrics(SM_CYSCREEN) / 2 - 高度 / 2;

hAppWnd = CreateWindow("DXAPPWNDCLASS", AppTitle.c_str(), WindStyle, x, y, 宽度, 高度, NULL, NULL, hAppInstance, NULL);
如果(!hAppWnd){
    OutputDebugString("\n创建窗口失败!!\n");
    返回假;
}

ShowWindow(hAppWnd, SW_SHOW);
返回真;
}

//直接初始化

布尔 DXApp::direct3dInit()
{
无符号 int createDeviceFlags = 0;

#ifdef 调试
createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif // 调试

D3D_DRIVER_TYPE driverTypes[] = {

    D3D_DRIVER_TYPE_HARDWARE,
    D3D_DRIVER_TYPE_WARP,
    D3D_DRIVER_TYPE_REFERENCE
};

无符号整数 numDriverTypes = ARRAYSIZE(driverTypes);

D3D_FEATURE_LEVEL featureLevels[] = {

    D3D_FEATURE_LEVEL_11_0,
    D3D_FEATURE_LEVEL_10_1,
    D3D_FEATURE_LEVEL_10_0,
    D3D_FEATURE_LEVEL_9_3
};

无符号整数 numFeatureLevels = ARRAYSIZE(featureLevels);

DXGI_SWAP_CHAIN_DESC swapDesc;
ZeroMemory(&swapDesc, sizeof(DXGI_SWAP_CHAIN_DESC));

swapDesc.BufferCount = 1;
swapDesc.BufferDesc.Width = ClientWidth;
swapDesc.BufferDesc.Height = ClientHeight;
swapDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swapDesc.BufferDesc.RefreshRate.Numerator = 60;
swapDesc.BufferDesc.RefreshRate.Denominator = 1;
swapDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapDesc.OutputWindow = hAppWnd;
swapDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
swapDesc.Windowed = true;
swapDesc.SampleDesc.Count = 1;
swapDesc.SampleDesc.Quality = 0;
swapDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;

HRESULT 结果;
for (int i = 0; i GetBuffer(NULL, __uuidof(ID3D11Texture2D), reinterpret_cast(&backBufferTex));
设备->CreateRenderTargetView(backBufferTex, nullptr, &renderTargetView);

//绑定渲染目标视图
immediateContext->OMSetRenderTargets(1, &renderTargetView, nullptr);

//从文件编译着色器
结果 = D3DCompileFromFile(L"VertexShader.hlsl", 0, 0, "vertexShader", "vs_4_0", 0, 0, &VSBuffer, &VSBuffer);
结果 = D3DCompileFromFile(L"PixelShader.hlsl", 0, 0, "pixelShader", "ps_4_0", 0, 0, &PSBuffer, &PSBuffer);

//创建着色器对象
结果 = 设备->CreateVertexShader(VSBuffer->GetBufferPointer(), VSBuffer->GetBufferSize(), 0, &vertexShader);
结果 = 设备->CreatePixelShader(PSBuffer->GetBufferPointer(), PSBuffer->GetBufferSize(), 0, &pixelShader);

//设置着色器
immediateContext->VSSetShader(vertexShader, 0, 0);
immediateContext->PSSetShader(pixelShader, 0, 0);

//创建顶点缓冲区
顶点 v[] = {
    顶点(0.0f,0.5f,0.5f),
    顶点(0.5f,-0.5f,0.5f),
    顶点(-0.5f,0.5f,0.5f),
};

D3D11_BUFFER_DESC vertexBufferDesc;
ZeroMemory(&vertexBufferDesc, sizeof(D3D11_BUFFER_DESC));

vertexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
vertexBufferDesc.ByteWidth = sizeof(Vertex) * 3;
vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vertexBufferDesc.CPUAccessFlags = 0;
vertexBufferDesc.MiscFlags = 0;

D3D11_SUBRESOURCE_DATA 顶点缓冲区数据;
ZeroMemory(&vertexBufferData, sizeof(vertexBufferData));
vertexBufferData.pSysMem = v;

结果 = 设备->CreateBuffer(&vertexBufferDesc, &vertexBufferData, &triangleVertBuffer);

//设置顶点缓冲区
unsigned int stride = sizeof(Vertex);
无符号整数偏移 = 0;
immediateContext->IAGetVertexBuffers(0, 1, &triangleVertBuffer, &stride, &offset);

//创建输入布局
设备->CreateInputLayout(layout, numLayoutElements, VSBuffer->GetBufferPointer(), VSBuffer->GetBufferSize(), &vertLayout);

//设置输入布局
immediateContext->IASetInputLayout(vertLayout);

//设置原始拓扑
immediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

//视口创建
ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT));

viewport.Width = static_cast(ClientWidth);
viewport.Height = static_cast(ClientHeight);
视口.TopLeftX = 0;
视口.TopLeftY = 0;
视口.MinDepth = 0.0f;
视口.MaxDepth = 1.0f;

//设置视口
immediateContext->RSSetViewports(1, &viewport);


返回真;

}




//消息

LRESULT DXApp::MsgProc(HWND hwnd, unsigned int msg, WPARAM wParam, LPARAM lParam)
{
开关(味精){
案例 WM_DESTROY:
    PostQuitMessage(0);
    返回0;
默认:
    返回 DefWindowProc(hwnd, msg, wParam, lParam);

}
}

感谢您的帮助。

【问题讨论】:

  • 您的示例很长,缩小问题范围通常有助于找到问题。你可以在stackoverflow.com/help/mcve中学习如何给出好的例子
  • 我只知道 opengl,但是快速浏览一下着色器可能值得仔细研究一下。相当于着色器的段错误有时会引起很多麻烦,包括冻结您的操作系统。例如,您对VSSetShader 的调用似乎没有正确的参数,为什么它们都是0?再次,我不知道 DX 的语义,但我认为其中一个应该是 1?我在看here,我可能会误解,但我相信 0 会被视为 NULL 并且不会使用着色器?
  • @sjm324 谢谢,但是 VSSetShader 没问题,我没有使用任何接口,所以两者都应该是 0。0 被视为 NULL,但正如我所说,在这种情况下没关系。

标签: c++ visual-studio directx directx-11


【解决方案1】:

调试 Direct3D 程序的第一步是:

(1) 确保您正确检查了所有 HRESULT 值。 您的代码中有许多地方未能检查结果。如果 Direct3D 函数返回 void,则可以忽略错误检查。否则你需要使用SUCCEEDEDFAILED,或者使用ThrowIfFailed之类的东西。这本质上是因为在失败之后继续进行操作会使得调试问题的真正原因变得非常困难。

(2) 启用 Direct3D 调试设备并查找输出。您的调试版本中似乎有此功能。您在调试窗口中看到任何输出吗?

让程序“挂起”您的系统是非常罕见的,但如果您的驱动程序错误或硬件有故障,则可能会发生这种情况。但是,如果没有更多详细信息,则很难诊断,因为您的程序一开始就有错误。

【讨论】:

  • 感谢您提供有关检查 HRESULT 的建议。问题在于使用IAGetVertexBuffers 而不是IASetVertexBuffers。操作系统停止崩溃,但我仍然遇到着色器问题:“找不到入口点”
  • 接受答案并开始一个新问题,其中包括 HLSL 源代码和您对编译器的调用。
猜你喜欢
  • 1970-01-01
  • 2022-01-08
  • 2021-04-08
  • 1970-01-01
  • 1970-01-01
  • 2015-10-09
  • 2013-04-05
  • 2020-04-05
相关资源
最近更新 更多