DirectX 11调试层捕获错误字符串

4

我已经使得DirectX调试层正常工作,并且它可以将错误和警告输出到Visual Studio的输出窗口。例如:

D3D11 WARNING: ID3D11DeviceContext::OMSetRenderTargets: Resource being set to OM RenderTarget slot 0 is still bound on input! [ STATE_SETTING WARNING #9: DEVICE_OMSETRENDERTARGETS_HAZARD]

我有一个自定义的日志系统,可以保存到文件并在其他窗口中打印。我想捕获调试信息字符串,并以自己的方式显示它们。是否支持此功能?如果是,我该如何做?

2个回答

9

由于我自己也遇到了这个问题,并发现之前的答案有点不够详细,所以我想给出一个更详细的解决方案,现在我已经让它正常工作了:

可以通过从内部消息队列中读取消息来获得DirectX11的所有API调用,在此我将引用 这里 中提供的API调用。

通过调用ID3D11InfoQueue::GetMessage访问内部消息队列,该方法需要传入消息索引并使用 D3D11_MESSAGE 结构体填充提供的缓冲区,该结构体包含所需信息(严重级别、类别、ID和文本)。

然而,当我尝试迭代这个缓冲区时,我发现该缓冲区为空(通过调用ID3D11InfoQueue::GetNumStoredMessages)这似乎是由于某些过滤器而发生的。为了使运行时实际上填充此缓冲区,我首先需要调用ID3D11InfoQueue::PushEmptyStorageFilter,它推送一个不过滤任何消息的过滤器:

//HANDLE_HRESULT is just a macro of mine to check for S_OK return value
HANDLE_HRESULT(debug_info_queue->PushEmptyStorageFilter());

这个过滤器是与Chuck Walbourn's答案中提到的博客文章讨论的部分(虽然该链接只将我重定向至主页面,实际的博客文章在这里)。但它不包含有关如何重定向消息的任何信息。

一旦生成了消息,您可以像这样迭代它们:

UINT64 message_count = debug_info_queue->GetNumStoredMessages();

for(UINT64 i = 0; i < message_count; i++){
    SIZE_T message_size = 0;
    debug_info_queue->GetMessage(i, nullptr, &message_size); //get the size of the message

    D3D11_MESSAGE* message = (D3D11_MESSAGE*) malloc(message_size); //allocate enough space
    HANDLE_HRESULT(debug_info_queue->GetMessage(i, message, &message_size)); //get the actual message

    //do whatever you want to do with it
    printf("Directx11: %.*s", message->DescriptionByteLength, message->pDescription);

    free(message);
}

debug_info_queue->ClearStoredMessages();

debug_info_queue是ID3D11InfoQueue接口,可以通过以下方式获取:

ID3D11InfoQueue* debug_info_queue;
device->QueryInterface(__uuidof(ID3D11InfoQueue), (void **)&debug_info_queue);

5

您可以使用ID3D11InfoQueue接口来实现自己的调试消息输出。

using Microsoft::WRL::ComPtr;

ComPtr<ID3D11Debug> d3dDebug;
if (SUCCEEDED(device.As(&d3dDebug)))
{
    ComPtr<ID3D11InfoQueue> d3dInfoQueue;
    if (SUCCEEDED(d3dDebug.As(&d3dInfoQueue)))
    {

请参见此博客文章:this blog post

调试层的默认行为是:每当有信息时,它将立即被打印出来。ID3D12InfoQueue提供了一种捕获消息并在我们的日志系统中显示的方法。然而,如果发生崩溃并且不再继续,我们将失去最后一次捕获后的所有消息。这里是否有任何消息回调,或者我应该捕获异常并刷新所有消息? - stanleyerror

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接