Search code examples
c++visual-studiodirectxdirectx-11

DirectX 11 Debug Layer Capture Error Strings


I have the DirectX Debug Layer working and it outputs errors and warnings to the output window in visual studio. Like this for example (not the actual issue I'm facing):

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

I have a custom logging system that saves to files and prints in other windows. I'd like to capture the debug message strings, and display them in my own way. Is this supported? If so how do I do it?


Solution

  • Since I had this problem myself and found the previous answer a bit lackluster, I want to give a more detailed solution, now that I've got this working:

    All API calls I will reference can be found here

    One can get messages out of DirectX11 by reading them from an internal message queue, that can be accessed by calling ID3D11InfoQueue::GetMessage, which takes the index of the message to get and fills a provided buffer with a D3D11_MESSAGE struct, that contains all the wanted information (Severity, Category, ID and Text).

    However, I discovered that this buffer was empty (by calling ID3D11InfoQueue::GetNumStoredMessages) when I tried to iterate over it. That seemed to be due to some filtering going on. In order for the runtime to actually fill this buffer, I first had to call ID3D11InfoQueue::PushEmptyStorageFilter, which pushes a filter that doesn't filter out any messages:

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

    This filtering is the part that is actually discussed in the blog post that is linked in Chuck Walbourn's answer (allthough the link only directs me to the main page, the actual blog post is here). It doesn't contain any info on how to redirect the messages though.

    Once the messages are generated, you can iterate over them like so:

    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 is the ID3D11InfoQueue interface and can be obtained like so:

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