DirectX11 With Windows SDK完整目录html
欢迎加入QQ群: 727623616 能够一块儿探讨DX11,以及有什么问题也能够在这里汇报。框架
DirectX11的API是由一系列的COM组件来管理的,这些前缀带I的接口类最终都继承自IUnknown
接口类。IUnknown
的三个方法以下:函数
方法 | 描述 |
---|---|
IUnknown::AddRef | 内部引用计数加1。在每次复制了一个这样的指针后,应当调用该方法以保证计数准确性 |
IUnknown::QueryInterface | 查询该实例是否实现了另外一个接口,若是存在则返回该接口的指针,而且对该接口的引用计数加1 |
IUnknown::Release | 内部引用数减1。只有当内部引用数到达0时才会真正释放 |
在实际的使用状况来看,一般咱们几乎不会使用第一个方法。而用的最多的就是第三个方法了,每次用完该实例后,咱们必需要使用相似下面的宏来释放:3d
#define ReleaseCOM(x) { if(x){ x->Release(); x = nullptr; } }
并且若是出现了忘记释放某个接口指针的状况话,内存泄漏的提醒就有可可以你去调试一成天了。指针
为了解决上述问题,从繁杂的人工释放中解脱,在本教程中大量使用了ComPtr
智能指针。并且在龙书12的教程源码中也用到了该智能指针。该智能指针能够帮助咱们来管理这些COM组件实现的接口实例,而无需过多担忧内存的泄漏。该智能指针的大小和通常的指针大小是一致的,没有额外的内存空间占用。因此本教程能够不须要用到接口类ID3D11Debug
来协助检查内存泄漏。调试
使用该智能指针须要包含头文件wrl/client.h
,而且智能指针类模板ComPtr
位于名称空间Microsoft::WRL
内。code
首先有五个比较经常使用的方法须要了解一下:htm
方法 | 描述 |
---|---|
ComPtr
|
该方法返回T*,而且不会触发引用计数加1,经常使用在COM组件接口的函数输入 |
ComPtr
|
该方法返回T** ,经常使用在COM组件接口的函数输出 |
ComPtr
|
该方法对里面的实例调用Release方法,并将指针置为nullptr |
ComPtr
|
该方法至关于先调用Reset 方法,再调用GetAddressOf 方法获取T** ,经常使用在COM组件接口的函数输出,适用于实例可能会被反复构造的状况下 |
ComPtr
|
一个模板函数,能够替代IUnknown::QueryInterface 的调用,须要传递一个ComPtr实例的地址 |
而后是一些运算符重载的方法:blog
运算符 | 描述 |
---|---|
& | 至关于调用了ComPtr<T>::ReleaseAndGetAddressOf 方法,不推荐使用 |
-> | 和裸指针的行为一致 |
= | 不要将裸指针指向的实例赋给它,若传递的是ComPtr
|
==和!= | 能够和nullptr ,或者另外一个ComPtr
|
注意:大体在比
10.0.16299.0
更早的Windows SDK版本中,ComPtr
使用了一个RemoveIUnknownBase
类模板将IUnknown
的三个接口都设为了private
,以防止用户直接操做这些方法,这也就使得ComPtr
没法直接使用COM组件的QueryInterface
方法。所以,使用ComPtr<T>::As
是一种合适的选择。继承
我的建议,在使用该智能指针后就应该要避免使用IUnknown
提供的三个接口方法来进行操做。
虽然替换成ComPtr
后代码量变长了,可是带来的收益确定比你本身花费大量时间在检查释放内存上强的多。
下面的D3DApp
将全部COM组件指针都换成了ComPtr
:
class D3DApp { public: D3DApp(HINSTANCE hInstance); // 在构造函数的初始化列表应当设置好初始参数 virtual ~D3DApp(); HINSTANCE AppInst()const; // 获取应用实例的句柄 HWND MainWnd()const; // 获取主窗口句柄 float AspectRatio()const; // 获取屏幕宽高比 int Run(); // 运行程序,进行游戏主循环 // 框架方法。客户派生类须要重载这些方法以实现特定的应用需求 virtual bool Init(); // 该父类方法须要初始化窗口和Direct3D部分 virtual void OnResize(); // 该父类方法须要在窗口大小变更的时候调用 virtual void UpdateScene(float dt) = 0; // 子类须要实现该方法,完成每一帧的更新 virtual void DrawScene() = 0; // 子类须要实现该方法,完成每一帧的绘制 virtual LRESULT MsgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); // 窗口的消息回调函数 protected: bool InitMainWindow(); // 窗口初始化 bool InitDirect3D(); // Direct3D初始化 void CalculateFrameStats(); // 计算每秒帧数并在窗口显示 protected: HINSTANCE m_hAppInst; // 应用实例句柄 HWND m_hMainWnd; // 主窗口句柄 bool m_AppPaused; // 应用是否暂停 bool m_Minimized; // 应用是否最小化 bool m_Maximized; // 应用是否最大化 bool m_Resizing; // 窗口大小是否变化 bool m_Enable4xMsaa; // 是否开启4倍多重采样 UINT m_4xMsaaQuality; // MSAA支持的质量等级 GameTimer m_Timer; // 计时器 // 使用模板别名(C++11)简化类型名 template <class T> using ComPtr = Microsoft::WRL::ComPtr<T>; // Direct3D 11 ComPtr<ID3D11Device> m_pd3dDevice; // D3D11设备 ComPtr<ID3D11DeviceContext> m_pd3dImmediateContext; // D3D11设备上下文 ComPtr<IDXGISwapChain> m_pSwapChain; // D3D11交换链 // Direct3D 11.1 ComPtr<ID3D11Device1> m_pd3dDevice1; // D3D11.1设备 ComPtr<ID3D11DeviceContext1> m_pd3dImmediateContext1; // D3D11.1设备上下文 ComPtr<IDXGISwapChain1> m_pSwapChain1; // D3D11.1交换链 // 经常使用资源 ComPtr<ID3D11Texture2D> m_pDepthStencilBuffer; // 深度模板缓冲区 ComPtr<ID3D11RenderTargetView> m_pRenderTargetView; // 渲染目标视图 ComPtr<ID3D11DepthStencilView> m_pDepthStencilView; // 深度模板视图 D3D11_VIEWPORT m_ScreenViewport; // 视口 // 派生类应该在构造函数设置好这些自定义的初始参数 std::wstring m_MainWndCaption; // 主窗口标题 int m_ClientWidth; // 视口宽度 int m_ClientHeight; // 视口高度 };
DirectX11 With Windows SDK完整目录
欢迎加入QQ群: 727623616 能够一块儿探讨DX11,以及有什么问题也能够在这里汇报。