Skip to content

Shader printf

This debugging feature is built-in blender shader system. It allows the usage of printf directly inside shader code.

For example:

printf("gl_FragCoord %f %f\n", gl_FragCoord.x, gl_FragCoord.y);

Note

This feature is only available in debug mode by default. This is to prevent shipping with printf inside shaders since their presence triggers some expensive synchronization.

You can force enable it in release mode by setting GPU_FORCE_ENABLE_SHADER_PRINTF to 1.

The size of the output buffer can be adjusted by changing GPU_SHADER_PRINTF_MAX_CAPACITY.

It is important to limit the amount of threads that call the printf, otherwise the buffer limit might be easily exceeded. This can be done using this snippet (to be adapted for each the shader type):

#ifdef GPU_FRAGMENT_SHADER
  if (all(equal(ivec2(gl_FragCoord.xy), ivec2(100)))) {
    printf("Here\n");
  }
#endif

Some limitations: - The formating options are limited to %u, %x, %d and %f. - The output is async and will only happen when either the gpu::Context is unbinded or when GPU_render_step is called. - If buffer overflows, only an error message is printed.

Note

These limitations should ultimately be fixed or offer a way to workaround them.

Implementation details

The format strings are stored into dictionary on CPU and indexed by their hash. Only the hash of the format and the data is written by the shader inside the printf_buf. The CPU does the data formatting.

The printf support is implemented by doing these steps: - On startup: - For each printf( occurences: - Extract the format string and store it inside a dictionary. - Replace printf by print_header and print_value calls. - Add gpu_print resource info to shaders that contains printf calls. - On each redraw: - If a printf is detected in the shader codebase: - Create the printf_buf at context binding. - Bind the printf_buf at every call to GPU_shader_bind. - Readback, print and delete the printf_buf at context unbind.