Debugging graphics applications is always a tricky affair. The following can help in this regard.

Debugging tools

There are several graphics debugging tools to consider when working with graphics APIs. In most cases, when not obtaining the expected result, attaching a frame debugger is recommended. A list of compatible frame debuggers follows:

  • Direct3D 11: Visual Studio Graphics Analyzer & Renderdoc
  • Direct3D 12: Visual Studio Graphics Analyzer
  • Vulkan: Renderdoc

It is advisable to get these tools up and running for the target APIs as soon as possible, in order to make sure frame debugging is an option when results turn out not as expected. These tools can show all commands submitted to the API, all data in buffers and textures and in some cases the in and output of various shader stages. Familiarizing yourself with these tools can save a lot of time otherwise spent on debugging.

Increasing debuggability

Several actions can be taken in order to make debugging in frame debuggers a little bit easier. All of the above graphics APIs support giving any API objects names. This means that rather than showing a Depth Stencil View as “Depth stencil view 1", the depth stencil view can instead be called “Shadow map (spotlight 1)". This can allow for resources to be more easily distinguishable at face value.

The API for renaming objects is as follows:

  • Direct3D 11: SetPrivateData with WKPDID_D3DDebugObjectName as GUID, the string length as DataSize, and the string as pData
  • Direct3D 12: SetName on any object the name can be set on
  • Vulkan: vkDebugMarkerSetObjectNameEXT on the object. (Requires VK_EXT_debug_marker to be enabled)

In addition to naming objects, you can also add events. This allows a list like this:

- DrawIndexed ( ... )
- DrawIndexed ( ... )
- DrawIndexed ( ... )
- DrawIndexed ( ... )
- DrawIndexed ( ... )

To be turned into a list like this:

- Shadow rendering
    - Spotlight 1
        - DrawIndexed ( ... )
        - DrawIndexed ( ... )
    - Spotlight 2
        - DrawIndexed ( ... )
- Main render
    - DrawIndexed ( ... )
    - DrawIndexed ( ... )

This will allow for jumping to the draw call you are interested in as soon as possible, aiding in the debugging process.

The API for placing event markers:

  • Direct3D 11: BeginEvent on the ID3D11DeviceContext2. Note that earlier versions of ID3D11DeviceContext do not support debug markers.
  • Direct3D 12: BeginEvent on the graphics command list to start an event, EndEvent to close the event. In BeginEvent, Metadata indicates the type of event. The values we are interested in in this case are 0 and 1. 0 indicates that pData refers to a string of wchar_t characters, whereas 1 indicates the string is of char characters
  • Vulkan: vkCmdDebugMarkerBeginEXT to start a debug marker, vkCmdDebugMarkerEndEXT