GLSL debugPrintfEXT Numeric Format Specifiers

The debugPrintfEXT intrinsic, provided by the GL_EXT_debug_printf extension in GLSL and Vulkan, allows developers to output debugging messages directly from running shaders to the host console or validation layer output. For numeric data, it adopts a standard subset of the C99 printf specification, supporting various specifiers for signed integers, unsigned integers, and floating-point values along with standard length and precision modifiers.

Signed Integer Specifiers

To output signed integer data (int or scalar signed values), debugPrintfEXT supports standard base-10 conversion characters:

  • %d: Formats the value as a signed decimal integer.
  • %i: Identical to %d, formats the value as a signed decimal integer.

Unsigned Integer Specifiers

For unsigned values (uint), debugPrintfEXT supports formatting across decimal, hexadecimal, and octal representations:

  • %u: Formats the value as an unsigned decimal integer.
  • %x: Formats the value as an unsigned hexadecimal integer using lowercase letters (a–f).
  • %X: Formats the value as an unsigned hexadecimal integer using uppercase letters (A–F).
  • %o: Formats the value as an unsigned octal integer.

Floating-Point Specifiers

For single-precision (float) and double-precision (double) types, debugPrintfEXT provides standard decimal and scientific output options:

  • %f: Formats a floating-point number in standard decimal notation (e.g., 12.345678).
  • %F: Identical to %f, but outputs uppercase representations for special values like INF or NAN.
  • %e: Formats a floating-point number in exponential (scientific) notation using a lowercase e (e.g., 1.234568e+01).
  • %E: Formats a floating-point number in exponential notation using an uppercase E (e.g., 1.234568E+01).
  • %g: Converts the value using either %f or %e depending on the magnitude and precision, omitting trailing zeros.
  • %G: Equivalent to %g, but uses uppercase E when exponential notation is selected.
  • %a: Formats a floating-point number as hexadecimal floating-point using lowercase letters and a lowercase p for the exponent.
  • %A: Formats a floating-point number as hexadecimal floating-point using uppercase letters and an uppercase P for the exponent.

64-Bit Integer Modifiers

When working with 64-bit integers (int64_t or uint64_t), standard length modifiers must be prefixed to integer specifiers to prevent undefined output behavior:

  • %ld or %lld: Formats a 64-bit signed integer.
  • %lu or %llu: Formats a 64-bit unsigned integer.
  • %lx or %llx: Formats a 64-bit unsigned integer in hexadecimal.

Flags, Width, and Precision

The numeric specifiers in debugPrintfEXT fully support standard C99 sub-specifiers:

  • Width: Specifies a minimum number of characters to output (e.g., %5d).
  • Precision: Specifies the exact number of fractional digits for floats (e.g., %.2f) or the minimum number of digits for integers (e.g., %.4u).
  • Flags: Supports 0 for zero-padding (e.g., %08x), - for left-alignment, + to always show signs for signed values, and # for alternate forms (such as prefixing 0x with %#x).

Scalar Requirement

debugPrintfEXT does not support vector formats natively. When printing GLSL vector types (like vec3 or uvec4), each vector component must be passed as an individual scalar argument paired with its own numeric format specifier (e.g., debugPrintfEXT("Position: (%f, %f, %f)\n", pos.x, pos.y, pos.z)).