Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2022-08-08 20:01:38 +0300
committerClément Foucault <foucault.clem@gmail.com>2022-08-09 16:45:46 +0300
commitf6639cc4fc1fd9fbbe1454ce216d6d0c8fe1ebdf (patch)
treedc4b1924fc1d4fbd085351cc26dab32c3235b448 /source/blender/draw/intern/shaders
parent2e4727e123c1cc652212875074f19f7b4bf46563 (diff)
DRW: DebugDraw: Port module to C++ and add GPU capabilities
This is a complete rewrite of the draw debug drawing module in C++. It uses `GPUStorageBuf` to store the data to be drawn and use indirect drawing. This makes it easier to do a mirror API for GPU shaders. The C++ API class is exposed through `draw_debug.hh` and should be used when possible in new code. However, the debug drawing will not work for platform not yet supporting `GPUStorageBuf`. Also keep in mind that this module must only be used in debug build for performance and compatibility reasons.
Diffstat (limited to 'source/blender/draw/intern/shaders')
-rw-r--r--source/blender/draw/intern/shaders/common_debug_draw_lib.glsl216
-rw-r--r--source/blender/draw/intern/shaders/common_debug_print_lib.glsl389
-rw-r--r--source/blender/draw/intern/shaders/common_view_lib.glsl3
-rw-r--r--source/blender/draw/intern/shaders/draw_debug_draw_display_frag.glsl9
-rw-r--r--source/blender/draw/intern/shaders/draw_debug_draw_display_vert.glsl15
-rw-r--r--source/blender/draw/intern/shaders/draw_debug_info.hh51
-rw-r--r--source/blender/draw/intern/shaders/draw_debug_print_display_frag.glsl133
-rw-r--r--source/blender/draw/intern/shaders/draw_debug_print_display_vert.glsl29
8 files changed, 845 insertions, 0 deletions
diff --git a/source/blender/draw/intern/shaders/common_debug_draw_lib.glsl b/source/blender/draw/intern/shaders/common_debug_draw_lib.glsl
new file mode 100644
index 00000000000..7a79f957462
--- /dev/null
+++ b/source/blender/draw/intern/shaders/common_debug_draw_lib.glsl
@@ -0,0 +1,216 @@
+
+/**
+ * Debugging drawing library
+ *
+ * Quick way to draw debug geometry. All input should be in world space and
+ * will be rendered in the default view. No additional setup required.
+ **/
+
+/** Global switch option. */
+bool drw_debug_draw_enable = true;
+const vec4 drw_debug_default_color = vec4(1.0, 0.0, 0.0, 1.0);
+
+/* -------------------------------------------------------------------- */
+/** \name Interals
+ * \{ */
+
+uint drw_debug_start_draw(uint v_needed)
+{
+ uint vertid = atomicAdd(drw_debug_draw_v_count, v_needed);
+ /* NOTE: Skip the header manually. */
+ vertid += 1;
+ return vertid;
+}
+
+uint drw_debug_color_pack(vec4 color)
+{
+ color = clamp(color, 0.0, 1.0);
+ uint result = 0;
+ result |= uint(color.x * 255.0) << 0u;
+ result |= uint(color.y * 255.0) << 8u;
+ result |= uint(color.z * 255.0) << 16u;
+ result |= uint(color.w * 255.0) << 24u;
+ return result;
+}
+
+void drw_debug_line(inout uint vertid, vec3 v1, vec3 v2, uint color)
+{
+ drw_debug_verts_buf[vertid++] = DRWDebugVert(
+ floatBitsToUint(v1.x), floatBitsToUint(v1.y), floatBitsToUint(v1.z), color);
+ drw_debug_verts_buf[vertid++] = DRWDebugVert(
+ floatBitsToUint(v2.x), floatBitsToUint(v2.y), floatBitsToUint(v2.z), color);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name API
+ * \{ */
+
+/**
+ * Draw a line.
+ */
+void drw_debug_line(vec3 v1, vec3 v2, vec4 color)
+{
+ if (!drw_debug_draw_enable) {
+ return;
+ }
+ const uint v_needed = 2;
+ uint vertid = drw_debug_start_draw(v_needed);
+ if (vertid + v_needed < DRW_DEBUG_DRAW_VERT_MAX) {
+ drw_debug_line(vertid, v1, v2, drw_debug_color_pack(color));
+ }
+}
+void drw_debug_line(vec3 v1, vec3 v2)
+{
+ drw_debug_line(v1, v2, drw_debug_default_color);
+}
+
+/**
+ * Draw a quad contour.
+ */
+void drw_debug_quad(vec3 v1, vec3 v2, vec3 v3, vec3 v4, vec4 color)
+{
+ if (!drw_debug_draw_enable) {
+ return;
+ }
+ const uint v_needed = 8;
+ uint vertid = drw_debug_start_draw(v_needed);
+ if (vertid + v_needed < DRW_DEBUG_DRAW_VERT_MAX) {
+ uint pcolor = drw_debug_color_pack(color);
+ drw_debug_line(vertid, v1, v2, pcolor);
+ drw_debug_line(vertid, v2, v3, pcolor);
+ drw_debug_line(vertid, v3, v4, pcolor);
+ drw_debug_line(vertid, v4, v1, pcolor);
+ }
+}
+void drw_debug_quad(vec3 v1, vec3 v2, vec3 v3, vec3 v4)
+{
+ drw_debug_quad(v1, v2, v3, v4, drw_debug_default_color);
+}
+
+/**
+ * Draw a point as octahedron wireframe.
+ */
+void drw_debug_point(vec3 p, float radius, vec4 color)
+{
+ if (!drw_debug_draw_enable) {
+ return;
+ }
+ vec3 c = vec3(radius, -radius, 0);
+ vec3 v1 = p + c.xzz;
+ vec3 v2 = p + c.zxz;
+ vec3 v3 = p + c.yzz;
+ vec3 v4 = p + c.zyz;
+ vec3 v5 = p + c.zzx;
+ vec3 v6 = p + c.zzy;
+
+ const uint v_needed = 12 * 2;
+ uint vertid = drw_debug_start_draw(v_needed);
+ if (vertid + v_needed < DRW_DEBUG_DRAW_VERT_MAX) {
+ uint pcolor = drw_debug_color_pack(color);
+ drw_debug_line(vertid, v1, v2, pcolor);
+ drw_debug_line(vertid, v2, v3, pcolor);
+ drw_debug_line(vertid, v3, v4, pcolor);
+ drw_debug_line(vertid, v4, v1, pcolor);
+ drw_debug_line(vertid, v1, v5, pcolor);
+ drw_debug_line(vertid, v2, v5, pcolor);
+ drw_debug_line(vertid, v3, v5, pcolor);
+ drw_debug_line(vertid, v4, v5, pcolor);
+ drw_debug_line(vertid, v1, v6, pcolor);
+ drw_debug_line(vertid, v2, v6, pcolor);
+ drw_debug_line(vertid, v3, v6, pcolor);
+ drw_debug_line(vertid, v4, v6, pcolor);
+ }
+}
+void drw_debug_point(vec3 p, float radius)
+{
+ drw_debug_point(p, radius, drw_debug_default_color);
+}
+void drw_debug_point(vec3 p)
+{
+ drw_debug_point(p, 0.01);
+}
+
+/**
+ * Draw a sphere wireframe as 3 axes circle.
+ */
+void drw_debug_sphere(vec3 p, float radius, vec4 color)
+{
+ if (!drw_debug_draw_enable) {
+ return;
+ }
+ const int circle_resolution = 16;
+ const uint v_needed = circle_resolution * 2 * 3;
+ uint vertid = drw_debug_start_draw(v_needed);
+ if (vertid + v_needed < DRW_DEBUG_DRAW_VERT_MAX) {
+ uint pcolor = drw_debug_color_pack(color);
+ for (int axis = 0; axis < 3; axis++) {
+ for (int edge = 0; edge < circle_resolution; edge++) {
+ float angle1 = (2.0 * 3.141592) * float(edge + 0) / float(circle_resolution);
+ vec3 p1 = vec3(cos(angle1), sin(angle1), 0.0);
+ p1 = vec3(p1[(0 + axis) % 3], p1[(1 + axis) % 3], p1[(2 + axis) % 3]);
+
+ float angle2 = (2.0 * 3.141592) * float(edge + 1) / float(circle_resolution);
+ vec3 p2 = vec3(cos(angle2), sin(angle2), 0.0);
+ p2 = vec3(p2[(0 + axis) % 3], p2[(1 + axis) % 3], p2[(2 + axis) % 3]);
+
+ drw_debug_line(vertid, p1, p2, pcolor);
+ }
+ }
+ }
+}
+void drw_debug_sphere(vec3 p, float radius)
+{
+ drw_debug_sphere(p, radius, drw_debug_default_color);
+}
+
+/**
+ * Draw a matrix transformation as 3 colored axes.
+ */
+void drw_debug_matrix(mat4 mat, vec4 color)
+{
+ vec4 p[4] = vec4[4](vec4(0, 0, 0, 1), vec4(1, 0, 0, 1), vec4(0, 1, 0, 1), vec4(0, 0, 1, 1));
+ for (int i = 0; i < 4; i++) {
+ p[i] = mat * p[i];
+ p[i].xyz /= p[i].w;
+ }
+ drw_debug_line(p[0].xyz, p[0].xyz, vec4(1, 0, 0, 1));
+ drw_debug_line(p[0].xyz, p[1].xyz, vec4(0, 1, 0, 1));
+ drw_debug_line(p[0].xyz, p[2].xyz, vec4(0, 0, 1, 1));
+}
+void drw_debug_matrix(mat4 mat)
+{
+ drw_debug_matrix(mat, drw_debug_default_color);
+}
+
+/**
+ * Draw a matrix as a 2 units length bounding box, centered on origin.
+ */
+void drw_debug_matrix_as_bbox(mat4 mat, vec4 color)
+{
+ vec4 p[8] = vec4[8](vec4(-1, -1, -1, 1),
+ vec4(1, -1, -1, 1),
+ vec4(1, 1, -1, 1),
+ vec4(-1, 1, -1, 1),
+ vec4(-1, -1, 1, 1),
+ vec4(1, -1, 1, 1),
+ vec4(1, 1, 1, 1),
+ vec4(-1, 1, 1, 1));
+ for (int i = 0; i < 8; i++) {
+ p[i] = mat * p[i];
+ p[i].xyz /= p[i].w;
+ }
+ drw_debug_quad(p[0].xyz, p[1].xyz, p[2].xyz, p[3].xyz, color);
+ drw_debug_line(p[0].xyz, p[4].xyz, color);
+ drw_debug_line(p[1].xyz, p[5].xyz, color);
+ drw_debug_line(p[2].xyz, p[6].xyz, color);
+ drw_debug_line(p[3].xyz, p[7].xyz, color);
+ drw_debug_quad(p[4].xyz, p[5].xyz, p[6].xyz, p[7].xyz, color);
+}
+void drw_debug_matrix_as_bbox(mat4 mat)
+{
+ drw_debug_matrix_as_bbox(mat, drw_debug_default_color);
+}
+
+/** \} */
diff --git a/source/blender/draw/intern/shaders/common_debug_print_lib.glsl b/source/blender/draw/intern/shaders/common_debug_print_lib.glsl
new file mode 100644
index 00000000000..0c7f32bd00d
--- /dev/null
+++ b/source/blender/draw/intern/shaders/common_debug_print_lib.glsl
@@ -0,0 +1,389 @@
+
+/**
+ * Debug print implementation for shaders.
+ *
+ * `print()`:
+ * Log variable or strings inside the viewport.
+ * Using a unique non string argument will print the variable name with it.
+ * Concatenate by using multiple arguments. i.e: `print("Looped ", n, "times.")`.
+ * `drw_print_no_endl()`:
+ * Same as `print()` but does not finish the line.
+ * `drw_print_value()`:
+ * Display only the value of a variable. Does not finish the line.
+ * `drw_print_value_hex()`:
+ * Display only the hex representation of a variable. Does not finish the line.
+ * `drw_print_value_binary()`: Display only the binary representation of a
+ * variable. Does not finish the line.
+ *
+ * IMPORTANT: As it is now, it is not yet thread safe. Only print from one thread. You can use the
+ * IS_DEBUG_MOUSE_FRAGMENT macro in fragment shader to filter using mouse position or
+ * IS_FIRST_INVOCATION in compute shaders.
+ *
+ * NOTE: Floating point representation might not be very precise (see drw_print_value(float)).
+ *
+ * IMPORTANT: Multipler drawcalls can write to the buffer in sequence (if they are from different
+ * shgroups). However, we add barriers to support this case and it might change the application
+ * behavior. Uncomment DISABLE_DEBUG_SHADER_drw_print_BARRIER to remove the barriers if that
+ * happens. But then you are limited to a single invocation output.
+ *
+ * IMPORTANT: All of these are copied to the CPU debug libs (draw_debug.cc). They need to be kept
+ * in sync to write the same data.
+ */
+
+/** Global switch option when you want to silence all prints from all shaders at once. */
+bool drw_debug_print_enable = true;
+
+/* Set drw_print_col to max value so we will start by creating a new line and get the correct
+ * threadsafe row. */
+uint drw_print_col = DRW_DEBUG_PRINT_WORD_WRAP_COLUMN;
+uint drw_print_row = 0u;
+
+void drw_print_newline()
+{
+ if (!drw_debug_print_enable) {
+ return;
+ }
+ drw_print_col = 0u;
+ drw_print_row = atomicAdd(drw_debug_print_row_shared, 1u) + 1u;
+}
+
+void drw_print_string_start(uint len)
+{
+ if (!drw_debug_print_enable) {
+ return;
+ }
+ /* Break before word. */
+ if (drw_print_col + len > DRW_DEBUG_PRINT_WORD_WRAP_COLUMN) {
+ drw_print_newline();
+ }
+}
+
+void drw_print_char4(uint data)
+{
+ if (!drw_debug_print_enable) {
+ return;
+ }
+ /* Convert into char stream. */
+ for (; data != 0u; data >>= 8u) {
+ uint char1 = data & 0xFFu;
+ /* Check for null terminator. */
+ if (char1 == 0x00) {
+ break;
+ }
+ uint cursor = atomicAdd(drw_debug_print_cursor, 1u);
+ /* NOTE: Skip the header manually. */
+ cursor += 4;
+ if (cursor < DRW_DEBUG_PRINT_MAX) {
+ /* For future usage. (i.e: Color) */
+ uint flags = 0u;
+ uint col = drw_print_col++;
+ uint drw_print_header = (flags << 24u) | (drw_print_row << 16u) | (col << 8u);
+ drw_debug_print_buf[cursor] = drw_print_header | char1;
+ /* Break word. */
+ if (drw_print_col > DRW_DEBUG_PRINT_WORD_WRAP_COLUMN) {
+ drw_print_newline();
+ }
+ }
+ }
+}
+
+/**
+ * NOTE(fclem): Strange behavior emerge when trying to increment the digit
+ * counter inside the append function. It looks like the compiler does not see
+ * it is referenced as an index for char4 and thus do not capture the right
+ * reference. I do not know if this is undefined behavior. As a matter of
+ * precaution, we implement all the append function separately. This behavior
+ * was observed on both Mesa & amdgpu-pro.
+ */
+/* Using ascii char code. Expect char1 to be less or equal to 0xFF. Appends chars to the right. */
+void drw_print_append_char(uint char1, inout uint char4)
+{
+ char4 = (char4 << 8u) | char1;
+}
+
+void drw_print_append_digit(uint digit, inout uint char4)
+{
+ const uint char_A = 0x41u;
+ const uint char_0 = 0x30u;
+ bool is_hexadecimal = digit > 9u;
+ char4 = (char4 << 8u) | (is_hexadecimal ? (char_A + digit - 10u) : (char_0 + digit));
+}
+
+void drw_print_append_space(inout uint char4)
+{
+ char4 = (char4 << 8u) | 0x20u;
+}
+
+void drw_print_value_binary(uint value)
+{
+ drw_print_no_endl("0b");
+ drw_print_string_start(10u * 4u);
+ uint digits[10] = uint[10](0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u);
+ uint digit = 0u;
+ for (uint i = 0u; i < 32u; i++) {
+ drw_print_append_digit(((value >> i) & 1u), digits[digit / 4u]);
+ digit++;
+ if ((i % 4u) == 3u) {
+ drw_print_append_space(digits[digit / 4u]);
+ digit++;
+ }
+ }
+ /* Numbers are written from right to left. So we need to reverse the order. */
+ for (int j = 9; j >= 0; j--) {
+ drw_print_char4(digits[j]);
+ }
+}
+
+void drw_print_value_binary(int value)
+{
+ drw_print_value_binary(uint(value));
+}
+
+void drw_print_value_binary(float value)
+{
+ drw_print_value_binary(floatBitsToUint(value));
+}
+
+void drw_print_value_uint(uint value, const bool hex, bool is_negative, const bool is_unsigned)
+{
+ drw_print_string_start(3u * 4u);
+ const uint blank_value = hex ? 0x30303030u : 0x20202020u;
+ const uint prefix = hex ? 0x78302020u : 0x20202020u;
+ uint digits[3] = uint[3](blank_value, blank_value, prefix);
+ const uint base = hex ? 16u : 10u;
+ uint digit = 0u;
+ /* Add `u` suffix. */
+ if (is_unsigned) {
+ drw_print_append_char('u', digits[digit / 4u]);
+ digit++;
+ }
+ /* Number's digits. */
+ for (; value != 0u || digit == uint(is_unsigned); value /= base) {
+ drw_print_append_digit(value % base, digits[digit / 4u]);
+ digit++;
+ }
+ /* Add negative sign. */
+ if (is_negative) {
+ drw_print_append_char('-', digits[digit / 4u]);
+ digit++;
+ }
+ /* Need to pad to uint alignment because we are issuing chars in "reverse". */
+ for (uint i = digit % 4u; i < 4u && i > 0u; i++) {
+ drw_print_append_space(digits[digit / 4u]);
+ digit++;
+ }
+ /* Numbers are written from right to left. So we need to reverse the order. */
+ for (int j = 2; j >= 0; j--) {
+ drw_print_char4(digits[j]);
+ }
+}
+
+void drw_print_value_hex(uint value)
+{
+ drw_print_value_uint(value, true, false, false);
+}
+
+void drw_print_value_hex(int value)
+{
+ drw_print_value_uint(uint(value), true, false, false);
+}
+
+void drw_print_value_hex(float value)
+{
+ drw_print_value_uint(floatBitsToUint(value), true, false, false);
+}
+
+void drw_print_value(uint value)
+{
+ drw_print_value_uint(value, false, false, true);
+}
+
+void drw_print_value(int value)
+{
+ drw_print_value_uint(uint(abs(value)), false, (value < 0), false);
+}
+
+void drw_print_value(bool value)
+{
+ if (value) {
+ drw_print_no_endl("true ");
+ }
+ else {
+ drw_print_no_endl("false");
+ }
+}
+
+/* NOTE(@fclem): This is homebrew and might not be 100% accurate (accuracy has
+ * not been tested and might dependent on compiler implementation). If unsure,
+ * use drw_print_value_hex and transcribe the value manually with another tool. */
+void drw_print_value(float val)
+{
+ /* We pad the string to match normal float values length. */
+ if (isnan(val)) {
+ drw_print_no_endl(" NaN");
+ return;
+ }
+ if (isinf(val)) {
+ if (sign(val) < 0.0) {
+ drw_print_no_endl(" -Inf");
+ }
+ else {
+ drw_print_no_endl(" Inf");
+ }
+ return;
+ }
+
+ /* Adjusted for significant digits (6) with sign (1), decimal separator (1)
+ * and exponent (4). */
+ const float significant_digits = 6.0;
+ drw_print_string_start(3u * 4u);
+ uint digits[3] = uint[3](0x20202020u, 0x20202020u, 0x20202020u);
+
+ float exponent = floor(log(abs(val)) / log(10.0));
+ bool display_exponent = exponent >= (significant_digits) ||
+ exponent <= (-significant_digits + 1.0);
+
+ float int_significant_digits = min(exponent + 1.0, significant_digits);
+ float dec_significant_digits = max(0.0, significant_digits - int_significant_digits);
+ /* Power to get to the rounding point. */
+ float rounding_power = dec_significant_digits;
+
+ if (val == 0.0 || isinf(exponent)) {
+ display_exponent = false;
+ int_significant_digits = dec_significant_digits = 1.0;
+ }
+ /* Remap to keep significant numbers count. */
+ if (display_exponent) {
+ int_significant_digits = 1.0;
+ dec_significant_digits = significant_digits - int_significant_digits;
+ rounding_power = -exponent + dec_significant_digits;
+ }
+ /* Round at the last significant digit. */
+ val = round(val * pow(10.0, rounding_power));
+ /* Get back to final exponent. */
+ val *= pow(10.0, -dec_significant_digits);
+
+ float int_part;
+ float dec_part = modf(val, int_part);
+
+ dec_part *= pow(10.0, dec_significant_digits);
+
+ const uint base = 10u;
+ uint digit = 0u;
+ /* Exponent */
+ uint value = uint(abs(exponent));
+ if (display_exponent) {
+ for (int i = 0; value != 0u || i == 0; i++, value /= base) {
+ drw_print_append_digit(value % base, digits[digit / 4u]);
+ digit++;
+ }
+ /* Exponent sign. */
+ uint sign_char = (exponent < 0.0) ? '-' : '+';
+ drw_print_append_char(sign_char, digits[digit / 4u]);
+ digit++;
+ /* Exponent `e` suffix. */
+ drw_print_append_char(0x65u, digits[digit / 4u]);
+ digit++;
+ }
+ /* Decimal part. */
+ value = uint(abs(dec_part));
+#if 0 /* We don't do that because it makes unstable values really hard to \
+ read. */
+ /* Trim trailing zeros. */
+ while ((value % base) == 0u) {
+ value /= base;
+ if (value == 0u) {
+ break;
+ }
+ }
+#endif
+ if (value != 0u) {
+ for (int i = 0; value != 0u || i == 0; i++, value /= base) {
+ drw_print_append_digit(value % base, digits[digit / 4u]);
+ digit++;
+ }
+ /* Point separator. */
+ drw_print_append_char('.', digits[digit / 4u]);
+ digit++;
+ }
+ /* Integer part. */
+ value = uint(abs(int_part));
+ for (int i = 0; value != 0u || i == 0; i++, value /= base) {
+ drw_print_append_digit(value % base, digits[digit / 4u]);
+ digit++;
+ }
+ /* Negative sign. */
+ if (val < 0.0) {
+ drw_print_append_char('-', digits[digit / 4u]);
+ digit++;
+ }
+ /* Need to pad to uint alignment because we are issuing chars in "reverse". */
+ for (uint i = digit % 4u; i < 4u && i > 0u; i++) {
+ drw_print_append_space(digits[digit / 4u]);
+ digit++;
+ }
+ /* Numbers are written from right to left. So we need to reverse the order. */
+ for (int j = 2; j >= 0; j--) {
+ drw_print_char4(digits[j]);
+ }
+}
+
+void drw_print_value(vec2 value)
+{
+ drw_print_no_endl("vec2(", value[0], ", ", value[1], ")");
+}
+
+void drw_print_value(vec3 value)
+{
+ drw_print_no_endl("vec3(", value[0], ", ", value[1], ", ", value[1], ")");
+}
+
+void drw_print_value(vec4 value)
+{
+ drw_print_no_endl("vec4(", value[0], ", ", value[1], ", ", value[2], ", ", value[3], ")");
+}
+
+void drw_print_value(ivec2 value)
+{
+ drw_print_no_endl("ivec2(", value[0], ", ", value[1], ")");
+}
+
+void drw_print_value(ivec3 value)
+{
+ drw_print_no_endl("ivec3(", value[0], ", ", value[1], ", ", value[1], ")");
+}
+
+void drw_print_value(ivec4 value)
+{
+ drw_print_no_endl("ivec4(", value[0], ", ", value[1], ", ", value[2], ", ", value[3], ")");
+}
+
+void drw_print_value(uvec2 value)
+{
+ drw_print_no_endl("uvec2(", value[0], ", ", value[1], ")");
+}
+
+void drw_print_value(uvec3 value)
+{
+ drw_print_no_endl("uvec3(", value[0], ", ", value[1], ", ", value[1], ")");
+}
+
+void drw_print_value(uvec4 value)
+{
+ drw_print_no_endl("uvec4(", value[0], ", ", value[1], ", ", value[2], ", ", value[3], ")");
+}
+
+void drw_print_value(bvec2 value)
+{
+ drw_print_no_endl("bvec2(", value[0], ", ", value[1], ")");
+}
+
+void drw_print_value(bvec3 value)
+{
+ drw_print_no_endl("bvec3(", value[0], ", ", value[1], ", ", value[1], ")");
+}
+
+void drw_print_value(bvec4 value)
+{
+ drw_print_no_endl("bvec4(", value[0], ", ", value[1], ", ", value[2], ", ", value[3], ")");
+}
diff --git a/source/blender/draw/intern/shaders/common_view_lib.glsl b/source/blender/draw/intern/shaders/common_view_lib.glsl
index 8eecaa46b58..8ab2ef10e4c 100644
--- a/source/blender/draw/intern/shaders/common_view_lib.glsl
+++ b/source/blender/draw/intern/shaders/common_view_lib.glsl
@@ -37,6 +37,9 @@ layout(std140) uniform viewBlock
# endif
#endif
+#define IS_DEBUG_MOUSE_FRAGMENT (ivec2(gl_FragCoord) == drw_view.mouse_pixel)
+#define IS_FIRST_INVOCATION (gl_GlobalInvocationID == uvec3(0))
+
#define ViewNear (ViewVecs[0].w)
#define ViewFar (ViewVecs[1].w)
diff --git a/source/blender/draw/intern/shaders/draw_debug_draw_display_frag.glsl b/source/blender/draw/intern/shaders/draw_debug_draw_display_frag.glsl
new file mode 100644
index 00000000000..3fc5294b024
--- /dev/null
+++ b/source/blender/draw/intern/shaders/draw_debug_draw_display_frag.glsl
@@ -0,0 +1,9 @@
+
+/**
+ * Display debug edge list.
+ **/
+
+void main()
+{
+ out_color = interp.color;
+}
diff --git a/source/blender/draw/intern/shaders/draw_debug_draw_display_vert.glsl b/source/blender/draw/intern/shaders/draw_debug_draw_display_vert.glsl
new file mode 100644
index 00000000000..92c546aa203
--- /dev/null
+++ b/source/blender/draw/intern/shaders/draw_debug_draw_display_vert.glsl
@@ -0,0 +1,15 @@
+
+/**
+ * Display debug edge list.
+ **/
+
+void main()
+{
+ /* Skip the first vertex containing header data. */
+ DRWDebugVert vert = drw_debug_verts_buf[gl_VertexID + 1];
+ vec3 pos = uintBitsToFloat(uvec3(vert.pos0, vert.pos1, vert.pos2));
+ vec4 col = vec4((uvec4(vert.color) >> uvec4(0, 8, 16, 24)) & 0xFFu);
+
+ interp.color = col;
+ gl_Position = persmat * vec4(pos, 1.0);
+}
diff --git a/source/blender/draw/intern/shaders/draw_debug_info.hh b/source/blender/draw/intern/shaders/draw_debug_info.hh
new file mode 100644
index 00000000000..7fbbc858d61
--- /dev/null
+++ b/source/blender/draw/intern/shaders/draw_debug_info.hh
@@ -0,0 +1,51 @@
+
+#include "gpu_shader_create_info.hh"
+
+/* -------------------------------------------------------------------- */
+/** \name Debug print
+ *
+ * Allows print() function to have logging support inside shaders.
+ * \{ */
+
+GPU_SHADER_CREATE_INFO(draw_debug_print)
+ .typedef_source("draw_shader_shared.h")
+ .storage_buf(7, Qualifier::READ_WRITE, "uint", "drw_debug_print_buf[]");
+
+GPU_SHADER_INTERFACE_INFO(draw_debug_print_display_iface, "").flat(Type::UINT, "char_index");
+
+GPU_SHADER_CREATE_INFO(draw_debug_print_display)
+ .do_static_compilation(true)
+ .typedef_source("draw_shader_shared.h")
+ .storage_buf(7, Qualifier::READ, "uint", "drw_debug_print_buf[]")
+ .vertex_out(draw_debug_print_display_iface)
+ .fragment_out(0, Type::VEC4, "out_color")
+ .vertex_source("draw_debug_print_display_vert.glsl")
+ .fragment_source("draw_debug_print_display_frag.glsl")
+ .additional_info("draw_view");
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Debug draw shapes
+ *
+ * Allows to draw lines and points just like the DRW_debug module functions.
+ * \{ */
+
+GPU_SHADER_CREATE_INFO(draw_debug_draw)
+ .typedef_source("draw_shader_shared.h")
+ .storage_buf(6, Qualifier::READ_WRITE, "DRWDebugVert", "drw_debug_verts_buf[]");
+
+GPU_SHADER_INTERFACE_INFO(draw_debug_draw_display_iface, "interp").flat(Type::VEC4, "color");
+
+GPU_SHADER_CREATE_INFO(draw_debug_draw_display)
+ .do_static_compilation(true)
+ .typedef_source("draw_shader_shared.h")
+ .storage_buf(6, Qualifier::READ, "DRWDebugVert", "drw_debug_verts_buf[]")
+ .vertex_out(draw_debug_draw_display_iface)
+ .fragment_out(0, Type::VEC4, "out_color")
+ .push_constant(Type::MAT4, "persmat")
+ .vertex_source("draw_debug_draw_display_vert.glsl")
+ .fragment_source("draw_debug_draw_display_frag.glsl")
+ .additional_info("draw_view");
+
+/** \} */
diff --git a/source/blender/draw/intern/shaders/draw_debug_print_display_frag.glsl b/source/blender/draw/intern/shaders/draw_debug_print_display_frag.glsl
new file mode 100644
index 00000000000..fe608816109
--- /dev/null
+++ b/source/blender/draw/intern/shaders/draw_debug_print_display_frag.glsl
@@ -0,0 +1,133 @@
+
+/**
+ * Display characters using an ascii table.
+ **/
+
+#pragma BLENDER_REQUIRE(common_math_lib.glsl)
+
+bool char_intersect(uvec2 bitmap_position)
+{
+ /* Using 8x8 = 64bits = uvec2. */
+ uvec2 ascii_bitmap[96] = uvec2[96](uvec2(0x00000000u, 0x00000000u),
+ uvec2(0x18001800u, 0x183c3c18u),
+ uvec2(0x00000000u, 0x36360000u),
+ uvec2(0x7f363600u, 0x36367f36u),
+ uvec2(0x301f0c00u, 0x0c3e031eu),
+ uvec2(0x0c666300u, 0x00633318u),
+ uvec2(0x3b336e00u, 0x1c361c6eu),
+ uvec2(0x00000000u, 0x06060300u),
+ uvec2(0x060c1800u, 0x180c0606u),
+ uvec2(0x180c0600u, 0x060c1818u),
+ uvec2(0x3c660000u, 0x00663cffu),
+ uvec2(0x0c0c0000u, 0x000c0c3fu),
+ uvec2(0x000c0c06u, 0x00000000u),
+ uvec2(0x00000000u, 0x0000003fu),
+ uvec2(0x000c0c00u, 0x00000000u),
+ uvec2(0x06030100u, 0x6030180cu),
+ uvec2(0x6f673e00u, 0x3e63737bu),
+ uvec2(0x0c0c3f00u, 0x0c0e0c0cu),
+ uvec2(0x06333f00u, 0x1e33301cu),
+ uvec2(0x30331e00u, 0x1e33301cu),
+ uvec2(0x7f307800u, 0x383c3633u),
+ uvec2(0x30331e00u, 0x3f031f30u),
+ uvec2(0x33331e00u, 0x1c06031fu),
+ uvec2(0x0c0c0c00u, 0x3f333018u),
+ uvec2(0x33331e00u, 0x1e33331eu),
+ uvec2(0x30180e00u, 0x1e33333eu),
+ uvec2(0x000c0c00u, 0x000c0c00u),
+ uvec2(0x000c0c06u, 0x000c0c00u),
+ uvec2(0x060c1800u, 0x180c0603u),
+ uvec2(0x003f0000u, 0x00003f00u),
+ uvec2(0x180c0600u, 0x060c1830u),
+ uvec2(0x0c000c00u, 0x1e333018u),
+ uvec2(0x7b031e00u, 0x3e637b7bu),
+ uvec2(0x3f333300u, 0x0c1e3333u),
+ uvec2(0x66663f00u, 0x3f66663eu),
+ uvec2(0x03663c00u, 0x3c660303u),
+ uvec2(0x66361f00u, 0x1f366666u),
+ uvec2(0x16467f00u, 0x7f46161eu),
+ uvec2(0x16060f00u, 0x7f46161eu),
+ uvec2(0x73667c00u, 0x3c660303u),
+ uvec2(0x33333300u, 0x3333333fu),
+ uvec2(0x0c0c1e00u, 0x1e0c0c0cu),
+ uvec2(0x33331e00u, 0x78303030u),
+ uvec2(0x36666700u, 0x6766361eu),
+ uvec2(0x46667f00u, 0x0f060606u),
+ uvec2(0x6b636300u, 0x63777f7fu),
+ uvec2(0x73636300u, 0x63676f7bu),
+ uvec2(0x63361c00u, 0x1c366363u),
+ uvec2(0x06060f00u, 0x3f66663eu),
+ uvec2(0x3b1e3800u, 0x1e333333u),
+ uvec2(0x36666700u, 0x3f66663eu),
+ uvec2(0x38331e00u, 0x1e33070eu),
+ uvec2(0x0c0c1e00u, 0x3f2d0c0cu),
+ uvec2(0x33333f00u, 0x33333333u),
+ uvec2(0x331e0c00u, 0x33333333u),
+ uvec2(0x7f776300u, 0x6363636bu),
+ uvec2(0x1c366300u, 0x6363361cu),
+ uvec2(0x0c0c1e00u, 0x3333331eu),
+ uvec2(0x4c667f00u, 0x7f633118u),
+ uvec2(0x06061e00u, 0x1e060606u),
+ uvec2(0x30604000u, 0x03060c18u),
+ uvec2(0x18181e00u, 0x1e181818u),
+ uvec2(0x00000000u, 0x081c3663u),
+ uvec2(0x000000ffu, 0x00000000u),
+ uvec2(0x00000000u, 0x0c0c1800u),
+ uvec2(0x3e336e00u, 0x00001e30u),
+ uvec2(0x66663b00u, 0x0706063eu),
+ uvec2(0x03331e00u, 0x00001e33u),
+ uvec2(0x33336e00u, 0x3830303eu),
+ uvec2(0x3f031e00u, 0x00001e33u),
+ uvec2(0x06060f00u, 0x1c36060fu),
+ uvec2(0x333e301fu, 0x00006e33u),
+ uvec2(0x66666700u, 0x0706366eu),
+ uvec2(0x0c0c1e00u, 0x0c000e0cu),
+ uvec2(0x3033331eu, 0x30003030u),
+ uvec2(0x1e366700u, 0x07066636u),
+ uvec2(0x0c0c1e00u, 0x0e0c0c0cu),
+ uvec2(0x7f6b6300u, 0x0000337fu),
+ uvec2(0x33333300u, 0x00001f33u),
+ uvec2(0x33331e00u, 0x00001e33u),
+ uvec2(0x663e060fu, 0x00003b66u),
+ uvec2(0x333e3078u, 0x00006e33u),
+ uvec2(0x66060f00u, 0x00003b6eu),
+ uvec2(0x1e301f00u, 0x00003e03u),
+ uvec2(0x0c2c1800u, 0x080c3e0cu),
+ uvec2(0x33336e00u, 0x00003333u),
+ uvec2(0x331e0c00u, 0x00003333u),
+ uvec2(0x7f7f3600u, 0x0000636bu),
+ uvec2(0x1c366300u, 0x00006336u),
+ uvec2(0x333e301fu, 0x00003333u),
+ uvec2(0x0c263f00u, 0x00003f19u),
+ uvec2(0x0c0c3800u, 0x380c0c07u),
+ uvec2(0x18181800u, 0x18181800u),
+ uvec2(0x0c0c0700u, 0x070c0c38u),
+ uvec2(0x00000000u, 0x6e3b0000u),
+ uvec2(0x00000000u, 0x00000000u));
+
+ if (!in_range_inclusive(bitmap_position, uvec2(0), uvec2(7))) {
+ return false;
+ }
+ uint char_bits = ascii_bitmap[char_index][bitmap_position.y >> 2u & 1u];
+ char_bits = (char_bits >> ((bitmap_position.y & 3u) * 8u + bitmap_position.x));
+ return (char_bits & 1u) != 0u;
+}
+
+void main()
+{
+ uvec2 bitmap_position = uvec2(gl_PointCoord.xy * 8.0);
+ /* Point coord start from top left corner. But layout is from bottom to top. */
+ bitmap_position.y = 7 - bitmap_position.y;
+
+ if (char_intersect(bitmap_position)) {
+ out_color = vec4(1);
+ }
+ else if (char_intersect(bitmap_position + uvec2(0, 1))) {
+ /* Shadow */
+ out_color = vec4(0, 0, 0, 1);
+ }
+ else {
+ /* Transparent Background for ease of read. */
+ out_color = vec4(0, 0, 0, 0.2);
+ }
+} \ No newline at end of file
diff --git a/source/blender/draw/intern/shaders/draw_debug_print_display_vert.glsl b/source/blender/draw/intern/shaders/draw_debug_print_display_vert.glsl
new file mode 100644
index 00000000000..c8fc3815436
--- /dev/null
+++ b/source/blender/draw/intern/shaders/draw_debug_print_display_vert.glsl
@@ -0,0 +1,29 @@
+
+/**
+ * Display characters using an ascii table. Outputs one point per character.
+ **/
+
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
+
+void main()
+{
+ /* Skip first 4 chars containing header data. */
+ uint char_data = drw_debug_print_buf[gl_VertexID + 4];
+ char_index = (char_data & 0xFFu) - 0x20u;
+
+ /* Discard invalid chars. */
+ if (char_index >= 96u) {
+ gl_Position = vec4(-1);
+ gl_PointSize = 0.0;
+ return;
+ }
+ uint row = (char_data >> 16u) & 0xFFu;
+ uint col = (char_data >> 8u) & 0xFFu;
+
+ float char_size = 16.0;
+ /* Change anchor point to the top left. */
+ vec2 pos_on_screen = char_size * vec2(col, row) + char_size * 4;
+ gl_Position = vec4(
+ pos_on_screen * drw_view.viewport_size_inverse * vec2(2.0, -2.0) - vec2(1.0, -1.0), 0, 1);
+ gl_PointSize = char_size;
+} \ No newline at end of file