SourceLevelDebuggingHLSL.rst 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. ================================
  2. Source Level Debugging with HLSL
  3. ================================
  4. .. contents::
  5. :local:
  6. Introduction
  7. ============
  8. This document describes the specifics of source level debuging with HLSL. The
  9. basic infrastructure is based on :doc:`Source Level Debugging with LLVM
  10. <SourceLevelDebugging>`, so the focus here is on the specifics of DXIL
  11. programs compiled from HLSL.
  12. DXIL Debug Information Format
  13. =============================
  14. The debug information for an HLSL program in DXIL form is stored as an LLVM
  15. module with debug information represented according to the :doc:`Source Level
  16. Debugging with LLVM <SourceLevelDebugging>` document.
  17. The :ref:`dxil_container_format` describes how a single data structure
  18. holds both a DXIL program, debug information, and other optional parts.
  19. There are three parts that are associated with debug information.
  20. * DFCC_DXIL ('DXIL'). A valid DXIL program has no debug information. This is
  21. the program described by debug information.
  22. * DFCC_ShaderDebugInfoDXIL ('ILDB'). This is an LLVM module with debug
  23. information. It's an augmented version of the original DXIL module. For
  24. historical reasons, this is sometimes referred to as 'the PDB of the
  25. program'.
  26. * DFCC_ShaderDebugName ('ILDN'). This is a name for an external entity holding
  27. the debug information.
  28. Using Debug Information
  29. =======================
  30. The debug information can be used directly by looking up the debug information
  31. part and loading into an LLVM module. There is full fidelity with debug
  32. information via this mechanism, although it requires linking in the LLVM
  33. supporting libraries.
  34. For compatibility, the dxcompiler.dll binary also exposes a limited
  35. implementation of the DIA APIs. To do this, a CLSID_DxcDiaDataSource class
  36. should be created via a call to DxcCreateInstance, and a loadDataFromIStream
  37. call with the debug part will initialize it.
  38. The DxcContext::Recompile implementation provides an example of how to
  39. initialize the diagnostic objects from debug information, extract high-level
  40. information and recreate the compilation options and inputs.
  41. Using Debug Names
  42. =================
  43. The only current use case for the debug name is as a relative path to a file
  44. that provides shader debug information. A debugging tool would typically have
  45. a list of paths to act as search roots.
  46. Command-Line Options
  47. ====================
  48. The following command-line options are used with the DirectX Shader Compiler
  49. tools to work with debug information.
  50. * /Zi. Enables debug information during compilation.
  51. * /Zss. Builds debug names that consider source information.
  52. * /Zsb. Builds debug names that consider only the output binary.
  53. * /Fd. Extracts debug information to a different file.
  54. * /Qstrip_debug. Removes debug information from a container.
  55. The most common use cases are as follows.
  56. * Build debug information and leave it in the container. In this case, simply
  57. compiling with /Zi will do the trick.
  58. * Build debug information and extract it to an auto-generated external
  59. file. In this case, /Zi and /Fd should both be used, and the /Fd value
  60. should end in a trailing backslash when using dxc, naming the target
  61. directory in which to place the file. /Zss is the default, but /Zsb can be
  62. used to deduplicate files. When using /Fd with a directory name,
  63. /Qstrip_debug is implied.
  64. A less common use case is to specify an explicit name for the external
  65. file. In this case, the command-line should include /Zi, /Fd with a specific
  66. name, and /Qstrip_debug.
  67. Implementation Notes
  68. ====================
  69. The current implementation provides a few interesting behaviors worth noting.
  70. * The shader debug name is derived from either the DXIL or the ILDB parts by
  71. hashing the byte contents, but it can be replaced programmatically.
  72. * Source content is included in the debug information blob by default. This
  73. helps with scenarios where the code never exists on-disk, but is instead
  74. generated on-the-fly.
  75. * Typically the derivation is done from the ILDB part, which includes
  76. source-specific information, and so two shaders with different sources will
  77. have different debug information. However the option is provided via (-Zsb)
  78. to include debug information that only takes into consideration the DXIL
  79. binary. In this case, two shaders that compile to the same binary will have
  80. the same debug information, which can be used to deduplicate content when
  81. any equivalent source program is acceptable for debugging.
  82. Future Directions
  83. =================
  84. This section is purely speculative, but captures some of the thoughts about
  85. future debugging capabilities.
  86. * If driver-level constructs should be debugged, they need to be mapped to
  87. DXIL first, and from there on to HLSL.
  88. * Including content in debug is convenient, especially when sources are
  89. transient, but they are inefficient (again, especially for a large number of
  90. transient sources). Deduplicating sources would be beneficial.
  91. * Integration with symbol servers and source servers can simplify some of the
  92. developer workflows.