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 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.