从 DirectX12 调试层获取有用信息

Getting Useful Information from the DirectX12 Debug Layer

我正在 Visual Studio 社区 2019 中开发我的第一个 DirectX 12 C++ 应用程序,但我无法从 Visual Studio 输出 window 中的调试日志输出中获取有用信息。

我的问题是我正在尝试通过调用 CreateSwapChain 创建交换链,但是对此函数的调用失败并产生以下错误消息的 HRESULT:

应用程序进行了无效调用。调用的参数或某些对象的状态不正确。 启用 D3D 调试层以便通过调试消息查看详细信息。

除此之外,我可以在输出 window 中看到来自 Visual Studio 的标准调试输出。它显示加载了哪些 .dll 文件以及抛出了异常。我不相信这些输出来自 DirectX。

为了启用调试层,我尝试了以下代码,从我的 WinMain 函数的第一行开始:

#if defined(DEBUG) || defined(_DEBUG)
Microsoft::WRL::ComPtr<ID3D12Debug> debugController;
ThrowIfFailed(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController)));
debugController->EnableDebugLayer();
#endif

此外,我 运行 dxcpl.exe 打开 DirectX 控制面板,将我的可执行文件添加到范围列表,然后 select Direct3D/DXGI调试层选项。

我通过 selecting Debug->Start Debugging 再次执行代码,在 Visual Studio Output window 我现在可以看到从“D3D12”报告的 INFO 消息,例如:

...
D3D12 INFO: Create ID3D12CommandAllocator: Addr=0x0C3CBD78, ExtRef=1, IntRef=0 [ STATE_CREATION          INFO #558: CREATE_COMMANDALLOCATOR]
D3D12 INFO: Create ID3D12GraphicsCommandList: Addr=0x0C42EA78, ExtRef=1, IntRef=0 [ STATE_CREATION INFO #560: CREATE_COMMANDLIST12]
D3D12 INFO: Create ID3D12GraphicsCommandList: Addr=0x0C479C68, ExtRef=1, IntRef=0 [ STATE_CREATION INFO #560: CREATE_COMMANDLIST12]
Exception thrown at 0x7705B5B2 in D3DX12.exe: Microsoft C++ exception: _com_error at memory location 0x003ADDC8.
Exception thrown at 0x7705B5B2 in D3DX12.exe: Microsoft C++ exception: _com_error at memory location 0x003ADDC8.
Exception thrown at 0x7705B5B2 in D3DX12.exe: Microsoft C++ exception: D3DAppException at memory location 0x003AE670.
D3D12 INFO: Destroy ID3D12GraphicsCommandList: Name="unnamed", Addr=0x0C479C68 [ STATE_CREATION INFO #586: DESTROY_COMMANDLIST12]
D3D12 INFO: Destroy ID3D12GraphicsCommandList: Name="unnamed", Addr=0x0C42EA78 [ STATE_CREATION INFO #586: DESTROY_COMMANDLIST12]
D3D12 INFO: Destroy ID3D12CommandAllocator: Name="unnamed", Addr=0x0C3CBD78 [ STATE_CREATION INFO #584: DESTROY_COMMANDALLOCATOR]
...

请注意,在一系列异常消息之前的最后一个 INFO 消息用于创建命令列表。命令列表是我在创建交换链之前立即创建的。我怀疑我传递给交换链的 window 有问题,但我的怀疑并不是真正重要的。我相信 DirectX 12 应该准确地告诉我问题是什么(即“错误:您的 window 句柄因 ”而无效),因为我相信这就是调试层的目的及其原因告诉我启用它。我相信我已经根据上面的代码启用了调试层,但是,与启用它之前相比,我没有收到更多有用的信息。

所以,这里真正的问题是为什么只有 DirectX 12 INFO 日志而没有 ERROR、WARN 或任何其他类型的消息来指示创建交换链的调用失败的原因?

提前感谢您的帮助。

我花了几个小时搜索,但我找到了我没有收到 DirectX 12 应用程序错误日志的原因。

我使用以下方法创建了我的 DXGI 工厂:

ThrowIfFailed(CreateDXGIFactory1(IID_PPV_ARGS(&factory)));

这将为 DXGI 版本 1.1 创建一个 DXGI 工厂。相反,函数 CreateDXGIFactory2 的第一个参数接受调试标志:

ThrowIfFailed(CreateDXGIFactory2(DXGI_CREATE_FACTORY_DEBUG, IID_PPV_ARGS(&factory)));

现在改用它会显示错误日志:

D3D12 INFO: Create ID3D12CommandAllocator: Addr=0x0D6D1D18, ExtRef=1, IntRef=0 [ STATE_CREATION INFO #558: CREATE_COMMANDALLOCATOR]
D3D12 INFO: Create ID3D12GraphicsCommandList: Addr=0x0D7358C8, ExtRef=1, IntRef=0 [ STATE_CREATION INFO #560: CREATE_COMMANDLIST12]
D3D12 INFO: Create ID3D12GraphicsCommandList: Addr=0x0D777D40, ExtRef=1, IntRef=0 [ STATE_CREATION INFO #560: CREATE_COMMANDLIST12]
DXGI ERROR: IDXGIFactory::CreateSwapChain: Flip model swapchains (DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL and DXGI_SWAP_EFFECT_FLIP_DISCARD) do not support multisampling. DXGI_SWAP_CHAIN_DESC{ SwapChainType = ..._HWND, BufferDesc = DXGI_MODE_DESC1{Width = 1920, Height = 1080, RefreshRate = DXGI_RATIONAL{ Numerator = 144, Denominator = 1 }, Format = R8G8B8A8_UNORM, ScanlineOrdering = ..._UNSPECIFIED, Scaling = ..._UNSPECIFIED, Stereo = FALSE }, SampleDesc = DXGI_SAMPLE_DESC{ Count = 4, Quality = 1 }, BufferUsage = 0x20, BufferCount = 2, OutputWindow = 0x001C0808, Scaling = ..._STRETCH, Windowed = TRUE, SwapEffect = ..._FLIP_DISCARD, AlphaMode = ..._IGNORE, Flags = 0x2 } [ MISCELLANEOUS ERROR #102: ]
Exception thrown at 0x7705B5B2 in D3DX12.exe: Microsoft C++ exception: _com_error at memory location 0x012FDD00.
DXGI ERROR: IDXGIFactory::CreateSwapChain: Flip model swapchains (DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL and DXGI_SWAP_EFFECT_FLIP_DISCARD) do not support multisampling. DXGI_SWAP_CHAIN_DESC{ SwapChainType = ..._HWND, BufferDesc = DXGI_MODE_DESC1{Width = 1920, Height = 1080, RefreshRate = DXGI_RATIONAL{ Numerator = 144, Denominator = 1 }, Format = R8G8B8A8_UNORM, ScanlineOrdering = ..._UNSPECIFIED, Scaling = ..._UNSPECIFIED, Stereo = FALSE }, SampleDesc = DXGI_SAMPLE_DESC{ Count = 4, Quality = 1 }, BufferUsage = 0x20, BufferCount = 2, OutputWindow = 0x001C0808, Scaling = ..._STRETCH, Windowed = TRUE, SwapEffect = ..._FLIP_DISCARD, AlphaMode = ..._IGNORE, Flags = 0x2 } [ MISCELLANEOUS ERROR #102: ]
Exception thrown at 0x7705B5B2 in D3DX12.exe: Microsoft C++ exception: _com_error at memory location 0x012FDD00.
Exception thrown at 0x7705B5B2 in D3DX12.exe: Microsoft C++ exception: D3DAppException at memory location 0x012FE5A8.
D3D12 INFO: Destroy ID3D12GraphicsCommandList: Name="unnamed", Addr=0x0D777D40 [ STATE_CREATION INFO #586: DESTROY_COMMANDLIST12]
D3D12 INFO: Destroy ID3D12GraphicsCommandList: Name="unnamed", Addr=0x0D7358C8 [ STATE_CREATION INFO #586: DESTROY_COMMANDLIST12]
D3D12 INFO: Destroy ID3D12CommandAllocator: Name="unnamed", Addr=0x0D6D1D18 [ STATE_CREATION INFO #584: DESTROY_COMMANDALLOCATOR]

我不确定 DXGI 的历史 API,但我希望这能帮助其他人解决这个问题,因为这让我很头疼。我目前正在研究 Frank Luna 的 DirectX 12 3D 游戏编程简介。他让你启用调试层,但我在他的示例中没有看到任何此标志的设置。我克隆了他的sample project目录,试图让他的应用出错,结果发现没有ERROR日志报错。只会出现一个消息对话框,给出与我之前发布的相同的 HRESULT 错误(它还表示应该启用调试层)。

谢谢。