DirectX11 With Windows SDK完整目錄html
歡迎加入QQ羣: 727623616 能夠一塊兒探討DX11,以及有什麼問題也能夠在這裏彙報。git
參考文章:https://blogs.msdn.microsoft.com/chuckw/2012/04/24/wheres-dxerr-lib/github
在龍書11中所使用的HR
宏和dxerr
庫是一個比較實用的錯誤緣由追蹤工具。D3D中的某些函數擁有返回值HRESULT
,經過dxerr
庫,能夠將錯誤碼轉換成錯誤詳細信息的字符串。windows
在DirectX SDK中,包含了頭文件dxerr.h
和庫文件dxerr.lib
,在以往的作法包含了DX SDK後,就能夠直接使用dxerr
了。但若是是要編寫基於Windows SDK的Direct3D程序,在Windows SDK 8.0以上已經沒有了dxerr
庫。函數
此時此刻,你仍然有兩種選擇來脫離對DirectX SDK的依賴:工具
dxerr.h
和dxerr.cpp
源碼來編譯出dxerr.lib
,或者直接加入你的項目當中;dxerr
庫微軟已經將dxerr
庫開源了,下面的連接能夠下載,若是不放心的話,你也能夠到上面的參考文章去下載。測試
在我以往的DirectX11項目中,則是從DXUT中拉過來的dxerr
:調試
DXUT Github/Corecode
但要注意的是,因爲新的dxerr.h
僅提供了DXTrace
的Unicode字符集版本,須要將原來的__FILE__
替換爲__FILEW__
,並在項目屬性頁中將字符集設置爲Unicode。
自Windows SDK 8.0起,HRESULT
值關於DirectX圖形API的錯誤消息字符串映射已經加入到FormatMessage
函數中。咱們能夠直接脫離對dxerr
的依賴,並使用該函數來直接獲取錯誤消息字符串。所以,dxerr
庫也就沒有必要在Windows SDK 8.0以上版本保留了。
鑑於咱們只是要獲取錯誤碼對應的字符串信息,這裏就簡單說起一下該函數的部分用法:
DWORD FormatMessageW( DWORD dwFlags, // [In]FORMAT_MESSAGE系列宏 LPCVOID lpSource, // [In]直接填NULL DWORD dwMessageId, // [In]傳入函數異常時返回的HRESULT DWORD dwLanguageId, // [In]語言ID LPTSTR lpBuffer, // [In]用於輸出消息字符串的緩衝區 DWORD nSize, // [In]WCHAR緩衝區可容納元素個數 va_list *Arguments // [In]直接填NULL );
這裏我將dxerr
中DXTraceW
函數的實現進行了修改,因爲如今錯誤碼信息爲中文,爲此也順便把錯誤窗口和輸出也漢化了。只須要包含Windows.h
和sal.h
就可使用。
函數原型:
// ------------------------------ // DXTraceW函數 // ------------------------------ // 在調試輸出窗口中輸出格式化錯誤信息,可選的錯誤窗口彈出(已漢化) // [In]strFile 當前文件名,一般傳遞宏__FILEW__ // [In]hlslFileName 當前行號,一般傳遞宏__LINE__ // [In]hr 函數執行出現問題時返回的HRESULT值 // [In]strMsg 用於幫助調試定位的字符串,一般傳遞L#x(可能爲NULL) // [In]bPopMsgBox 若是爲TRUE,則彈出一個消息彈窗告知錯誤信息 // 返回值: 形參hr HRESULT WINAPI DXTraceW(_In_z_ const WCHAR* strFile, _In_ DWORD dwLine, _In_ HRESULT hr, _In_opt_ const WCHAR* strMsg, _In_ bool bPopMsgBox);
函數實現:
HRESULT WINAPI DXTraceW(_In_z_ const WCHAR* strFile, _In_ DWORD dwLine, _In_ HRESULT hr, _In_opt_ const WCHAR* strMsg, _In_ bool bPopMsgBox) { WCHAR strBufferFile[MAX_PATH]; WCHAR strBufferLine[128]; WCHAR strBufferError[300]; WCHAR strBufferMsg[1024]; WCHAR strBufferHR[40]; WCHAR strBuffer[3000]; swprintf_s(strBufferLine, 128, L"%lu", dwLine); if (strFile) { swprintf_s(strBuffer, 3000, L"%ls(%ls): ", strFile, strBufferLine); OutputDebugStringW(strBuffer); } size_t nMsgLen = (strMsg) ? wcsnlen_s(strMsg, 1024) : 0; if (nMsgLen > 0) { OutputDebugStringW(strMsg); OutputDebugStringW(L" "); } // Windows SDK 8.0起DirectX的錯誤信息已經集成進錯誤碼中,能夠經過FormatMessageW獲取錯誤信息字符串 // 不須要分配字符串內存 FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), strBufferError, 256, nullptr); WCHAR* errorStr = wcsrchr(strBufferError, L'\r'); if (errorStr) { errorStr[0] = L'\0'; // 擦除FormatMessageW帶來的換行符(把\r\n的\r置換爲\0便可) } swprintf_s(strBufferHR, 40, L" (0x%0.8x)", hr); wcscat_s(strBufferError, strBufferHR); swprintf_s(strBuffer, 3000, L"錯誤碼含義:%ls", strBufferError); OutputDebugStringW(strBuffer); OutputDebugStringW(L"\n"); if (bPopMsgBox) { wcscpy_s(strBufferFile, MAX_PATH, L""); if (strFile) wcscpy_s(strBufferFile, MAX_PATH, strFile); wcscpy_s(strBufferMsg, 1024, L""); if (nMsgLen > 0) swprintf_s(strBufferMsg, 1024, L"當前調用:%ls\n", strMsg); swprintf_s(strBuffer, 3000, L"文件名:%ls\n行號:%ls\n錯誤碼含義:%ls\n%ls您須要調試當前應用程序嗎?", strBufferFile, strBufferLine, strBufferError, strBufferMsg); int nResult = MessageBoxW(GetForegroundWindow(), strBuffer, L"錯誤", MB_YESNO | MB_ICONERROR); if (nResult == IDYES) DebugBreak(); } return hr; }
如今的HR宏變成了這樣:
// ------------------------------ // HR宏 // ------------------------------ // Debug模式下的錯誤提醒與追蹤 #if defined(DEBUG) | defined(_DEBUG) #ifndef HR #define HR(x) \ { \ HRESULT hr = (x); \ if(FAILED(hr)) \ { \ DXTraceW(__FILEW__, (DWORD)__LINE__, hr, L#x, true);\ } \ } #endif #else #ifndef HR #define HR(x) (x) #endif #endif
測試效果以下:
在調試輸出窗口也能夠看到:
DirectX11 With Windows SDK完整目錄
歡迎加入QQ羣: 727623616 能夠一塊兒探討DX11,以及有什麼問題也能夠在這裏彙報。