使用调试层调试应用

建议使用 调试层 来调试应用,以确保它们没有错误和警告。 调试层可帮助你编写 Direct3D 代码。 此外,使用调试层时可以提高工作效率,因为可以立即查看混淆呈现错误甚至在其源出现黑屏的原因。 调试层提供多个问题的警告。 例如,调试层针对以下问题提供警告:

  • 忘记设置纹理,但在像素着色器中读取纹理
  • 输出深度,但没有深度模具状态绑定
  • 纹理创建失败,出现 INVALIDARG

下面我们将讨论如何启用 调试层 ,以及一些可以使用调试层来防止的问题。

启用调试层

若要启用调试层,请在调用 D3D11CreateDevice 函数以创建呈现设备时,在 Flags 参数中指定D3D11_CREATE_DEVICE_DEBUG标志。 以下示例代码演示如何在 Microsoft Visual Studio 项目处于调试版本中时启用调试层:

        UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
#if defined(_DEBUG)
        // If the project is in a debug build, enable the debug layer.
        creationFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
        // Define the ordering of feature levels that Direct3D attempts to create.
        D3D_FEATURE_LEVEL featureLevels[] =
        {
            D3D_FEATURE_LEVEL_11_1,
            D3D_FEATURE_LEVEL_11_0,
            D3D_FEATURE_LEVEL_10_1,
            D3D_FEATURE_LEVEL_10_0,
            D3D_FEATURE_LEVEL_9_3,
            D3D_FEATURE_LEVEL_9_1
        };

        ComPtr<ID3D11Device> d3dDevice;
        ComPtr<ID3D11DeviceContext> d3dDeviceContext;
        DX::ThrowIfFailed(
            D3D11CreateDevice(
                nullptr,                    // specify nullptr to use the default adapter
                D3D_DRIVER_TYPE_HARDWARE,
                nullptr,                    // specify nullptr because D3D_DRIVER_TYPE_HARDWARE 
                                            // indicates that this function uses hardware
                creationFlags,              // optionally set debug and Direct2D compatibility flags
                featureLevels,
                ARRAYSIZE(featureLevels),
                D3D11_SDK_VERSION,          // always set this to D3D11_SDK_VERSION
                &d3dDevice,
                nullptr,
                &d3dDeviceContext
                )
            );

使用调试层防止应用中的错误

如果滥用 Direct3D 11 API 或传递错误参数, 调试层 的调试输出将报告错误或警告。 然后,你可以更正错误。 接下来,我们将介绍一些可能导致未定义行为甚至操作系统崩溃的编码问题。 可以使用调试层来捕获和防止这些问题。

不要将 NULL 指针传递给 Map

如果将 NULL 传递给 ID3D11DeviceContext::Map 方法的 pResourcepMappedResource 参数,则 Map 的行为未定义。 如果创建了仅支持 核心层的设备, 则映射 参数无效可能会使操作系统崩溃。 如果创建了支持 调试层的设备,则调试输出将在此无效 的映射 调用上报告错误。

在源和目标资源中限制源框

在调用 ID3D11DeviceContext::CopySubresourceRegion 方法时,源框必须位于源资源内。 目标偏移量、 (x、y 和 z) 允许源框在写入目标资源时偏移,但源框的尺寸和偏移量必须在资源的大小范围内。 如果尝试在目标资源外部复制或指定大于源资源的源框, 则 CopySubresourceRegion 的行为未定义。 如果创建了支持 调试层的设备,则调试输出将在此无效 的 CopySubresourceRegion 调用上报告错误。 CopySubresourceRegion 的参数无效会导致未定义的行为,并可能导致不正确的呈现、剪辑、无副本甚至删除呈现设备。

请勿删除 DiscardResource 或 DiscardView

除非正确创建资源,否则运行时会删除对 ID3D11DeviceContext1::D iscardResourceID3D11DeviceContext1::D iscardView 的调用。

传递给 ID3D11DeviceContext1::D iscardResource 的资源必须是使用 D3D11_USAGE_DEFAULTD3D11_USAGE_DYNAMIC 创建的,否则运行时会删除对 DiscardResource 的调用。

传递给 ID3D11DeviceContext1::D iscardView 的视图的资源必须已使用 D3D11_USAGE_DEFAULTD3D11_USAGE_DYNAMIC 创建,否则运行时会删除对 DiscardView 的调用。

如果创建了支持 调试层的设备,则调试输出将报告有关丢弃的调用的错误。

软件层