当前位置: 首页 > news >正文

DirectX11--HR宏关于dxerr库的替代方案

DirectX11 With Windows SDK完整目录

欢迎加入QQ群: 727623616 可以一起探讨DX11,以及有什么问题也可以在这里汇报。

综述

参考文章:https://blogs.msdn.microsoft.com/chuckw/2012/04/24/wheres-dxerr-lib/

在龙书11中所使用的HR宏和dxerr库是一个比较实用的错误原因追踪工具。D3D中的某些函数拥有返回值HRESULT,通过dxerr库,可以将错误码转换成错误详细信息的字符串。

在DirectX SDK中,包含了头文件dxerr.h和库文件dxerr.lib,在以往的做法包含了DX SDK后,就可以直接使用dxerr了。但如果是要编写基于Windows SDK的Direct3D程序,在Windows SDK 8.0以上已经没有了dxerr库。

此时此刻,你仍然有两种选择来脱离对DirectX SDK的依赖:

  1. 寻找较新的dxerr.hdxerr.cpp源码来编译出dxerr.lib,或者直接加入你的项目当中;
  2. 直接抛弃dxerr

新的dxerr源码

微软已经将dxerr库开源了,下面的链接可以下载,如果不放心的话,你也可以到上面的参考文章去下载。

dxerr_nov2015.zip下载地址

在我以往的DirectX11项目中,则是从DXUT中拉过来的dxerr

DXUT Github/Core

但要注意的是,由于新的dxerr.h仅提供了DXTrace的Unicode字符集版本,需要将原来的__FILE__替换为__FILEW__,并在项目属性页中将字符集设置为Unicode

1172605-20181222222206381-1198412375.png

抛弃dxerr库

自Windows SDK 8.0起,HRESULT值关于DirectX图形API的错误消息字符串映射已经加入到FormatMessage函数中。我们可以直接脱离对dxerr的依赖,并使用该函数来直接获取错误消息字符串。因此,dxerr库也就没有必要在Windows SDK 8.0以上版本保留了。

FormatMessageW函数--获取格式化消息字符串

鉴于我们只是要获取错误码对应的字符串信息,这里就简单提及一下该函数的部分用法:

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
);

DXTraceW函数

这里我将dxerrDXTraceW函数的实现进行了修改,由于现在错误码信息为中文,为此也顺便把错误窗口和输出也汉化了。只需要包含Windows.hsal.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宏变成了这样:

// ------------------------------
// 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

测试效果如下:
1172605-20181224193702338-831563243.png

在调试输出窗口也可以看到:
1172605-20181224194246433-956466849.png

DirectX11 With Windows SDK完整目录

欢迎加入QQ群: 727623616 可以一起探讨DX11,以及有什么问题也可以在这里汇报。

转载于:https://www.cnblogs.com/X-Jun/p/10170535.html

相关文章:

  • Oracle 存储过程
  • WPF 判断调用方法堆栈
  • (转)scrum常见工具列表
  • GCC编译器对常量的一个处理
  • 串口调试程序v1.0
  • 周赛6(28)
  • 软件架构师成长之路
  • Django之一个基于多表的图书管理系统
  • 大学排名爬取 + 绘制树状图 + 绘制圆饼图
  • 一封支付宝老员工的离职信
  • spark的广播变量
  • regsvr32.exe使用详解
  • openwrt下定义软件包的依赖关系类型
  • 找不到IIS Out-Of-Process Pooled Applications
  • 注册表:DWORD
  • 【编码】-360实习笔试编程题(二)-2016.03.29
  • 230. Kth Smallest Element in a BST
  • Android路由框架AnnoRouter:使用Java接口来定义路由跳转
  • Bootstrap JS插件Alert源码分析
  • css的样式优先级
  • Iterator 和 for...of 循环
  • javascript面向对象之创建对象
  • jquery cookie
  • js写一个简单的选项卡
  • Laravel5.4 Queues队列学习
  • MQ框架的比较
  • socket.io+express实现聊天室的思考(三)
  • Spring Cloud Feign的两种使用姿势
  • 前端面试之闭包
  • 如何将自己的网站分享到QQ空间,微信,微博等等
  • 无服务器化是企业 IT 架构的未来吗?
  • 详解NodeJs流之一
  • 通过调用文摘列表API获取文摘
  • ​LeetCode解法汇总2670. 找出不同元素数目差数组
  • !!java web学习笔记(一到五)
  • #pragma multi_compile #pragma shader_feature
  • #中的引用型是什么意识_Java中四种引用有什么区别以及应用场景
  • $refs 、$nextTic、动态组件、name的使用
  • (1) caustics\
  • (1)(1.19) TeraRanger One/EVO测距仪
  • (delphi11最新学习资料) Object Pascal 学习笔记---第5章第5节(delphi中的指针)
  • (pytorch进阶之路)扩散概率模型
  • (二) Windows 下 Sublime Text 3 安装离线插件 Anaconda
  • (二)PySpark3:SparkSQL编程
  • (附源码)springboot 智能停车场系统 毕业设计065415
  • (含笔试题)深度解析数据在内存中的存储
  • (数位dp) 算法竞赛入门到进阶 书本题集
  • (转)Linq学习笔记
  • .apk文件,IIS不支持下载解决
  • .NET 2.0中新增的一些TryGet,TryParse等方法
  • .NET Core/Framework 创建委托以大幅度提高反射调用的性能
  • .NET 动态调用WebService + WSE + UsernameToken
  • .NET面试题解析(11)-SQL语言基础及数据库基本原理
  • /proc/interrupts 和 /proc/stat 查看中断的情况
  • /tmp目录下出现system-private文件夹解决方法