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,以及有什麼問題也能夠在這裏彙報。