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:
Diffstat (limited to 'source/blender/gpu/opengl/gl_debug.cc')
-rw-r--r--source/blender/gpu/opengl/gl_debug.cc130
1 files changed, 102 insertions, 28 deletions
diff --git a/source/blender/gpu/opengl/gl_debug.cc b/source/blender/gpu/opengl/gl_debug.cc
index db99e90d0ec..4e45ff11fc7 100644
--- a/source/blender/gpu/opengl/gl_debug.cc
+++ b/source/blender/gpu/opengl/gl_debug.cc
@@ -30,8 +30,11 @@
#include "BKE_global.h"
+#include "GPU_debug.h"
#include "GPU_platform.h"
+#include "CLG_log.h"
+
#include "glew-mx.h"
#include "gl_context.hh"
@@ -41,8 +44,12 @@
#include <stdio.h>
+static CLG_LogRef LOG = {"gpu.debug"};
+
/* Avoid too much NVidia buffer info in the output log. */
#define TRIM_NVIDIA_BUFFER_INFO 1
+/* Avoid unneeded shader statistics. */
+#define TRIM_SHADER_STATS_INFO 1
namespace blender::gpu::debug {
@@ -60,8 +67,6 @@ namespace blender::gpu::debug {
# define APIENTRY
#endif
-#define VERBOSE 1
-
static void APIENTRY debug_callback(GLenum UNUSED(source),
GLenum type,
GLuint UNUSED(id),
@@ -70,42 +75,65 @@ static void APIENTRY debug_callback(GLenum UNUSED(source),
const GLchar *message,
const GLvoid *UNUSED(userParm))
{
- const char format[] = "GPUDebug: %s%s\033[0m\n";
+ if (ELEM(type, GL_DEBUG_TYPE_PUSH_GROUP, GL_DEBUG_TYPE_POP_GROUP)) {
+ /* The debug layer will emit a message each time a debug group is pushed or popped.
+ * We use that for easy command grouping inside frame analyzer tools. */
+ return;
+ }
if (TRIM_NVIDIA_BUFFER_INFO &&
GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_ANY, GPU_DRIVER_OFFICIAL) &&
- STREQLEN("Buffer detailed info", message, 20)) {
- /** Supress buffer infos flooding the output. */
+ STRPREFIX(message, "Buffer detailed info")) {
+ /** Suppress buffer infos flooding the output. */
return;
}
+ if (TRIM_SHADER_STATS_INFO && STRPREFIX(message, "Shader Stats")) {
+ /** Suppress buffer infos flooding the output. */
+ return;
+ }
+
+ const bool use_color = CLG_color_support_get(&LOG);
+
if (ELEM(severity, GL_DEBUG_SEVERITY_LOW, GL_DEBUG_SEVERITY_NOTIFICATION)) {
- if (VERBOSE) {
- fprintf(stderr, format, "\033[2m", message);
+ if (((LOG.type->flag & CLG_FLAG_USE) && (LOG.type->level >= CLG_SEVERITY_INFO))) {
+ const char *format = use_color ? "\033[2m%s\033[0m" : "%s";
+ CLG_logf(LOG.type, CLG_SEVERITY_INFO, "Notification", "", format, message);
}
}
else {
+ char debug_groups[512] = "";
+ GPU_debug_get_groups_names(sizeof(debug_groups), debug_groups);
+ CLG_Severity clog_severity;
+
switch (type) {
case GL_DEBUG_TYPE_ERROR:
case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
- fprintf(stderr, format, "\033[31;1mError\033[39m: ", message);
+ clog_severity = CLG_SEVERITY_ERROR;
break;
case GL_DEBUG_TYPE_PORTABILITY:
case GL_DEBUG_TYPE_PERFORMANCE:
case GL_DEBUG_TYPE_OTHER:
case GL_DEBUG_TYPE_MARKER: /* KHR has this, ARB does not */
default:
- fprintf(stderr, format, "\033[33;1mWarning\033[39m: ", message);
+ clog_severity = CLG_SEVERITY_WARN;
break;
}
- if (VERBOSE && severity == GL_DEBUG_SEVERITY_HIGH) {
- /* Focus on error message. */
- fprintf(stderr, "\033[2m");
- BLI_system_backtrace(stderr);
- fprintf(stderr, "\033[0m\n");
- fflush(stderr);
+ if (((LOG.type->flag & CLG_FLAG_USE) && (LOG.type->level >= clog_severity))) {
+ CLG_logf(LOG.type, clog_severity, debug_groups, "", "%s", message);
+ if (severity == GL_DEBUG_SEVERITY_HIGH) {
+ /* Focus on error message. */
+ if (use_color) {
+ fprintf(stderr, "\033[2m");
+ }
+ BLI_system_backtrace(stderr);
+ if (use_color) {
+ fprintf(stderr, "\033[0m\n");
+ }
+ fflush(stderr);
+ }
}
}
}
@@ -113,8 +141,10 @@ static void APIENTRY debug_callback(GLenum UNUSED(source),
#undef APIENTRY
/* This function needs to be called once per context. */
-void init_gl_callbacks(void)
+void init_gl_callbacks()
{
+ CLOG_ENSURE(&LOG);
+
char msg[256] = "";
const char format[] = "Successfully hooked OpenGL debug callback using %s";
@@ -122,8 +152,8 @@ void init_gl_callbacks(void)
SNPRINTF(msg, format, GLEW_VERSION_4_3 ? "OpenGL 4.3" : "KHR_debug extension");
glEnable(GL_DEBUG_OUTPUT);
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
- glDebugMessageCallback((GLDEBUGPROC)debug_callback, NULL);
- glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE);
+ glDebugMessageCallback((GLDEBUGPROC)debug_callback, nullptr);
+ glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_TRUE);
glDebugMessageInsert(GL_DEBUG_SOURCE_APPLICATION,
GL_DEBUG_TYPE_MARKER,
0,
@@ -134,8 +164,8 @@ void init_gl_callbacks(void)
else if (GLEW_ARB_debug_output) {
SNPRINTF(msg, format, "ARB_debug_output");
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
- glDebugMessageCallbackARB((GLDEBUGPROCARB)debug_callback, NULL);
- glDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE);
+ glDebugMessageCallbackARB((GLDEBUGPROCARB)debug_callback, nullptr);
+ glDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_TRUE);
glDebugMessageInsertARB(GL_DEBUG_SOURCE_APPLICATION_ARB,
GL_DEBUG_TYPE_OTHER_ARB,
0,
@@ -144,7 +174,7 @@ void init_gl_callbacks(void)
msg);
}
else {
- fprintf(stderr, "GPUDebug: Failed to hook OpenGL debug callback. Use fallback debug layer.\n");
+ CLOG_STR_WARN(&LOG, "Failed to hook OpenGL debug callback. Use fallback debug layer.");
init_debug_layer();
}
}
@@ -183,14 +213,14 @@ void check_gl_error(const char *info)
default:
char msg[256];
SNPRINTF(msg, "Unknown GL error: %x : %s", error, info);
- debug_callback(0, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, 0, msg, NULL);
+ debug_callback(0, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, 0, msg, nullptr);
break;
}
}
void check_gl_resources(const char *info)
{
- if (!(G.debug & G_DEBUG_GPU)) {
+ if (!(G.debug & G_DEBUG_GPU) || GPU_bgl_get()) {
return;
}
@@ -200,13 +230,16 @@ void check_gl_resources(const char *info)
* be big enough to feed the data range the shader awaits. */
uint16_t ubo_needed = interface->enabled_ubo_mask_;
ubo_needed &= ~ctx->bound_ubo_slots;
-
/* NOTE: This only check binding. To be valid, the bound texture needs to
* be the same format/target the shader expects. */
uint64_t tex_needed = interface->enabled_tex_mask_;
tex_needed &= ~GLContext::state_manager_active_get()->bound_texture_slots();
+ /* NOTE: This only check binding. To be valid, the bound image needs to
+ * be the same format/target the shader expects. */
+ uint8_t ima_needed = interface->enabled_ima_mask_;
+ ima_needed &= ~GLContext::state_manager_active_get()->bound_image_slots();
- if (ubo_needed == 0 && tex_needed == 0) {
+ if (ubo_needed == 0 && tex_needed == 0 && ima_needed == 0) {
return;
}
@@ -217,25 +250,38 @@ void check_gl_resources(const char *info)
const char *sh_name = ctx->shader->name_get();
char msg[256];
SNPRINTF(msg, "Missing UBO bind at slot %d : %s > %s : %s", i, sh_name, ubo_name, info);
- debug_callback(0, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, 0, msg, NULL);
+ debug_callback(0, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, 0, msg, nullptr);
}
}
for (int i = 0; tex_needed != 0; i++, tex_needed >>= 1) {
if ((tex_needed & 1) != 0) {
+ /* FIXME: texture_get might return an image input instead. */
const ShaderInput *tex_input = interface->texture_get(i);
const char *tex_name = interface->input_name_get(tex_input);
const char *sh_name = ctx->shader->name_get();
char msg[256];
SNPRINTF(msg, "Missing Texture bind at slot %d : %s > %s : %s", i, sh_name, tex_name, info);
- debug_callback(0, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, 0, msg, NULL);
+ debug_callback(0, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, 0, msg, nullptr);
+ }
+ }
+
+ for (int i = 0; ima_needed != 0; i++, ima_needed >>= 1) {
+ if ((ima_needed & 1) != 0) {
+ /* FIXME: texture_get might return a texture input instead. */
+ const ShaderInput *tex_input = interface->texture_get(i);
+ const char *tex_name = interface->input_name_get(tex_input);
+ const char *sh_name = ctx->shader->name_get();
+ char msg[256];
+ SNPRINTF(msg, "Missing Image bind at slot %d : %s > %s : %s", i, sh_name, tex_name, info);
+ debug_callback(0, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, 0, msg, nullptr);
}
}
}
void raise_gl_error(const char *info)
{
- debug_callback(0, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, 0, info, NULL);
+ debug_callback(0, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, 0, info, nullptr);
}
/** \} */
@@ -305,3 +351,31 @@ void object_label(GLenum type, GLuint object, const char *name)
/** \} */
} // namespace blender::gpu::debug
+
+namespace blender::gpu {
+
+/* -------------------------------------------------------------------- */
+/** \name Debug Groups
+ *
+ * Useful for debugging through render-doc. This makes all the API calls grouped into "passes".
+ * \{ */
+
+void GLContext::debug_group_begin(const char *name, int index)
+{
+ if ((G.debug & G_DEBUG_GPU) && (GLEW_VERSION_4_3 || GLEW_KHR_debug)) {
+ /* Add 10 to avoid conlision with other indices from other possible callback layers. */
+ index += 10;
+ glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, index, -1, name);
+ }
+}
+
+void GLContext::debug_group_end()
+{
+ if ((G.debug & G_DEBUG_GPU) && (GLEW_VERSION_4_3 || GLEW_KHR_debug)) {
+ glPopDebugGroup();
+ }
+}
+
+/** \} */
+
+} // namespace blender::gpu