Shader printf¶
This debugging feature is built-in blender shader system. It allows the usage of printf directly inside shader code.
For example:
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 formatting options are limited to %s, %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(occurrence: * Extract the format string and store it inside a dictionary. * Replaceprintfbyprint_headerandprint_valuecalls. * Addgpu_printresource info to shaders that containsprintfcalls. - On each redraw:
* If a
printfis detected in the shader codebase: * Create theprintf_bufat context binding. * Bind theprintf_bufat every call toGPU_shader_bind. * Readback, print and delete theprintf_bufat context unbind.