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

Posted

技术标签:

【中文标题】DirectX 11:运行简单的 DirectX 应用程序时运行时崩溃【英文标题】:DirectX 11: Runtime crash when running simple DirectX application 【发布时间】:2014-08-29 18:40:46 【问题描述】:

我尝试从基类继承一些公共全局变量,并成功启动并运行窗口,并以简单的方式类似地初始化了 Directx - 在它自己的类中,继承全局变量,例如 HWND hWnd

但是,当程序运行时,D3D11CreateDeviceAndSwapChain() 失败。进一步检查,调试器给出:

DXGI ERROR: IDXGIFactory::CreateSwapChain: No target window specified in DXGI_SWAP_CHAIN_DESC, and no window associated with owning factory. [ MISCELLANEOUS ERROR #6: ]

DXGI_SWAP_CHAIN_DESC结构如下:

SwapChainDesc.BufferCount = 1;
SwapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
SwapChainDesc.BufferDesc.Width = 1024;
SwapChainDesc.BufferDesc.Height = 768;
SwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
SwapChainDesc.OutputWindow = hWnd;
SwapChainDesc.BufferDesc.RefreshRate.Numerator = 60;
SwapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
SwapChainDesc.SampleDesc.Count = 4;
SwapChainDesc.Windowed = TRUE;
SwapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;

hWnd 的存储位置:

class Infinity
public:
    Infinity();
    ~Infinity();
    HWND hWnd;
;

这样继承:

class Direct3D : public Infinity
public:
    Direct3D();
    ~Direct3D();
    IDXGISwapChain          *Swapchain; //Display modes.
    ID3D11Device            *Device;
    ID3D11DeviceContext     *DeviceContext;
    ID3D11RenderTargetView  *RenderTargetView;

    void D3D_Start(int width, int height);
    void D3D_Render();
    void D3D_Terminate();
Direct3D;

在运行时检查SwapChainDesc.OutputWindow = hWnd; 的值,它为空。 (0x00000000) 我认为这就是导致Swapchain->GetBuffer 失败的原因,因为D3D11CreateDeviceAndSwapChain 需要一个有效的HWND。如果这是真的,为什么ShowWindow() 成功了?

编辑:我还应该补充一点,ShowWindow()是一个类似的类,继承自class Infinity

class Windows : public Infinity
public:
    Windows();
    ~Windows();
    bool DisplayWindow(int width, int height, HINSTANCE hInstance);
    static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
Windows;

【问题讨论】:

hWnd 在您的代码中不是全局变量,它是一个数据成员。 @NmdMystery hWnd 不应该在这个类结构中充当全局吗?两个类都继承自Infinity 不,因为它是一个实例变量。所有实例变量都是对象的本地变量。如果您实例化一个 Window 类型的对象,然后实例化另一个 Direct3D 类型的对象,它们将各自拥有自己的 hWnd 实例。您可能想要做的是制作 hWnd static,这样就只有一个 hWnd 副本,并且所有继承类都可以访问它(当然,如果您只打算制作一个窗口)。 嗯,我试过了,收到了LNK2001LNK1120 (Error 1 error LNK2001: unresolved external symbol "public: static struct HWND__ * Infinity::hWnd" (?hWnd@Infinity@@2PAUHWND__@@A) c:\Users\...\Win32Project3.obj Win32Project3 )只有1个窗口- 您还必须在您的 cpp 文件中的类之外声明它,如下所示:HWND Infinity::hWnd = NULL;。但请注意,从长远来看,我的建议可能不是您想要的设计。 【参考方案1】:

观察以下代码:

class A 
public:
    int memA;
    static int memB;
;

int A::memB = 0;

class B : public A ;

class C : public A ;

int main() 
    A a;
    B b;
    C c;

    a.memA = 4;
    b.memA = 5;
    c.memA = 6;

    A::memB = 4;
    B::memB = 5;
    C::memB = 6;

    printf("a.memA = %d\n", a.memA);
    printf("b.memA = %d\n", b.memA);
    printf("c.memA = %d\n", c.memA);

    printf("A::memB = %d\n", A::memB);
    printf("B::memB = %d\n", B::memB);
    printf("C::memB = %d\n", C::memB);

    return 0;

这段代码的输出是:

a.memA = 4
b.memA = 5
c.memA = 6
A::memB = 6
B::memB = 6
C::memB = 6

通过将成员设为静态,您可以确保:A) 该成员只有一个实例,并且 B) 所有子类都可以直接访问该成员(假设它不是私有的)。您的 hWnd 不是全局的,因为您的代码是编写的,但是将其设为静态将完成您想要的。

下面的代码就是这样做的:

//header file
class Infinity 
public:
    static HWND hWnd;
;

//cpp file
HWND Infinity::hWnd = NULL;

您的 Direct3D 类将能够访问由您的 Window 类写入的非空 hWnd。如果您打算创建一个窗口,这仅是一种有效的解决方案 - 否则,您将不得不求助于两个类之间更复杂的父子关系(可能不使用继承)。

【讨论】:

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

Directx 11 运行时错误

Directx 11 前缓冲器

Directx11学习笔记 封装一个简单的Dx11DemoBase

吃鸡出现运行引擎dx11 运行引擎需要dx11功能级别10.0怎么解决

显卡上总说的directx 11 和游戏总说支持这个 到底啥意思 啥显卡支持directx呢 请详细讲讲 高分

基于 DirectX11 的 MMDViewer 01-简介