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')
-rw-r--r--source/blender/gpu/CMakeLists.txt1
-rw-r--r--source/blender/gpu/opengl/gl_backend.cc18
-rw-r--r--source/blender/gpu/opengl/gl_batch.cc3
-rw-r--r--source/blender/gpu/opengl/gl_context.cc6
-rw-r--r--source/blender/gpu/opengl/gl_context.hh1
-rw-r--r--source/blender/gpu/opengl/gl_debug.cc75
-rw-r--r--source/blender/gpu/opengl/gl_debug.hh103
-rw-r--r--source/blender/gpu/opengl/gl_debug_layer.cc165
-rw-r--r--source/blender/gpu/opengl/gl_framebuffer.cc21
-rw-r--r--source/blender/gpu/opengl/gl_immediate.cc14
-rw-r--r--source/blender/gpu/opengl/gl_shader.cc23
-rw-r--r--source/blender/gpu/opengl/gl_state.cc1
-rw-r--r--source/blender/gpu/opengl/gl_state.hh4
-rw-r--r--source/blender/gpu/opengl/gl_texture.cc56
-rw-r--r--source/blender/gpu/opengl/gl_uniform_buffer.cc7
15 files changed, 384 insertions, 114 deletions
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index bb50cd3744f..72dc610f3c8 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -93,6 +93,7 @@ set(SRC
opengl/gl_context.cc
opengl/gl_drawlist.cc
opengl/gl_debug.cc
+ opengl/gl_debug_layer.cc
opengl/gl_framebuffer.cc
opengl/gl_immediate.cc
opengl/gl_index_buffer.cc
diff --git a/source/blender/gpu/opengl/gl_backend.cc b/source/blender/gpu/opengl/gl_backend.cc
index c8d57a20a38..7285b9ad35c 100644
--- a/source/blender/gpu/opengl/gl_backend.cc
+++ b/source/blender/gpu/opengl/gl_backend.cc
@@ -178,7 +178,7 @@ static bool detect_mip_render_workaround(void)
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glClear(GL_COLOR_BUFFER_BIT);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
- glDrawBuffer(GL_BACK);
+
/* Read mip 1. If color is not the same as the clear_color, the rendering failed. */
glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 1, GL_RGBA, GL_FLOAT, source_pix);
bool enable_workaround = !equals_v4v4(clear_color, source_pix);
@@ -207,10 +207,12 @@ static void detect_workarounds(void)
printf(" version: %s\n\n", version);
GCaps.depth_blitting_workaround = true;
GCaps.mip_render_workaround = true;
+ GLContext::debug_layer_workaround = true;
GLContext::unused_fb_slot_workaround = true;
GLContext::texture_copy_workaround = true;
/* Turn off extensions. */
GLContext::base_instance_support = false;
+ GLContext::debug_layer_support = false;
GLContext::texture_cube_map_array_support = false;
return;
}
@@ -321,6 +323,10 @@ static void detect_workarounds(void)
GLContext::derivative_signs[1] = 1.0;
}
}
+ /* Enable our own incomplete debug layer if no other is available. */
+ if (GLContext::debug_layer_support == false) {
+ GLContext::debug_layer_workaround = true;
+ }
}
/** Internal capabilities. */
@@ -333,6 +339,7 @@ bool GLContext::base_instance_support = false;
bool GLContext::debug_layer_support = false;
bool GLContext::texture_cube_map_array_support = false;
/** Workarounds. */
+bool GLContext::debug_layer_workaround = false;
bool GLContext::texture_copy_workaround = false;
bool GLContext::unused_fb_slot_workaround = false;
float GLContext::derivative_signs[2] = {1.0f, 1.0f};
@@ -355,14 +362,15 @@ void GLBackend::capabilities_init(void)
glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &GLContext::max_ubo_size);
GLContext::base_instance_support = GLEW_ARB_base_instance;
GLContext::texture_cube_map_array_support = GLEW_ARB_texture_cube_map_array;
- GLContext::debug_layer_support = (GLEW_VERSION_4_3 || GLEW_KHR_debug);
+ GLContext::debug_layer_support = GLEW_VERSION_4_3 || GLEW_KHR_debug || GLEW_ARB_debug_output;
+ detect_workarounds();
+
+ /* Disable this feature entirely when not debugging. */
if ((G.debug & G_DEBUG_GPU) == 0) {
- /* Disable this feature entierly when not debugging. */
GLContext::debug_layer_support = false;
+ GLContext::debug_layer_workaround = false;
}
-
- detect_workarounds();
}
/** \} */
diff --git a/source/blender/gpu/opengl/gl_batch.cc b/source/blender/gpu/opengl/gl_batch.cc
index b25bafad6a3..17bc1013a78 100644
--- a/source/blender/gpu/opengl/gl_batch.cc
+++ b/source/blender/gpu/opengl/gl_batch.cc
@@ -324,7 +324,6 @@ void GLBatch::bind(int i_first)
void GLBatch::draw(int v_first, int v_count, int i_first, int i_count)
{
GL_CHECK_RESOURCES("Batch");
- GL_CHECK_ERROR("Batch Pre drawing");
this->bind(i_first);
@@ -346,7 +345,6 @@ void GLBatch::draw(int v_first, int v_count, int i_first, int i_count)
glDrawElementsInstancedBaseVertex(
gl_type, v_count, index_type, v_first_ofs, i_count, base_index);
}
- GL_CHECK_ERROR("Batch Post-drawing Indexed");
}
else {
#ifdef __APPLE__
@@ -361,7 +359,6 @@ void GLBatch::draw(int v_first, int v_count, int i_first, int i_count)
#ifdef __APPLE__
glEnable(GL_PRIMITIVE_RESTART);
#endif
- GL_CHECK_ERROR("Batch Post-drawing Non-indexed");
}
}
diff --git a/source/blender/gpu/opengl/gl_context.cc b/source/blender/gpu/opengl/gl_context.cc
index 6b3b06ef12b..9c98953f469 100644
--- a/source/blender/gpu/opengl/gl_context.cc
+++ b/source/blender/gpu/opengl/gl_context.cc
@@ -74,6 +74,9 @@ GLContext::GLContext(void *ghost_window, GLSharedOrphanLists &shared_orphan_list
GHOST_DisposeRectangle(bounds);
if (default_fbo != 0) {
+ /* Bind default framebuffer, otherwise state might be undefined because of
+ * detect_mip_render_workaround(). */
+ glBindFramebuffer(GL_FRAMEBUFFER, default_fbo);
front_left = new GLFrameBuffer("front_left", this, GL_COLOR_ATTACHMENT0, default_fbo, w, h);
back_left = new GLFrameBuffer("back_left", this, GL_COLOR_ATTACHMENT0, default_fbo, w, h);
}
@@ -81,6 +84,7 @@ GLContext::GLContext(void *ghost_window, GLSharedOrphanLists &shared_orphan_list
front_left = new GLFrameBuffer("front_left", this, GL_FRONT_LEFT, 0, w, h);
back_left = new GLFrameBuffer("back_left", this, GL_BACK_LEFT, 0, w, h);
}
+
GLboolean supports_stereo_quad_buffer = GL_FALSE;
glGetBooleanv(GL_STEREO, &supports_stereo_quad_buffer);
if (supports_stereo_quad_buffer) {
@@ -95,7 +99,7 @@ GLContext::GLContext(void *ghost_window, GLSharedOrphanLists &shared_orphan_list
active_fb = back_left;
static_cast<GLStateManager *>(state_manager)->active_fb = static_cast<GLFrameBuffer *>(
- back_left);
+ active_fb);
}
GLContext::~GLContext()
diff --git a/source/blender/gpu/opengl/gl_context.hh b/source/blender/gpu/opengl/gl_context.hh
index 10ae396d138..1cef6e61425 100644
--- a/source/blender/gpu/opengl/gl_context.hh
+++ b/source/blender/gpu/opengl/gl_context.hh
@@ -65,6 +65,7 @@ class GLContext : public Context {
static bool debug_layer_support;
static bool texture_cube_map_array_support;
/** Workarounds. */
+ static bool debug_layer_workaround;
static bool texture_copy_workaround;
static bool unused_fb_slot_workaround;
static float derivative_signs[2];
diff --git a/source/blender/gpu/opengl/gl_debug.cc b/source/blender/gpu/opengl/gl_debug.cc
index 468d1514d60..de88fdc154c 100644
--- a/source/blender/gpu/opengl/gl_debug.cc
+++ b/source/blender/gpu/opengl/gl_debug.cc
@@ -112,17 +112,13 @@ static void APIENTRY debug_callback(GLenum UNUSED(source),
#undef APIENTRY
+/* This function needs to be called once per context. */
void init_gl_callbacks(void)
{
-#ifdef __APPLE__
- fprintf(stderr, "GPUDebug: OpenGL debug callback is not available on Apple\n");
- return;
-#endif /* not Apple */
-
char msg[256] = "";
const char format[] = "Successfully hooked OpenGL debug callback using %s";
- if (GLContext::debug_layer_support) {
+ if (GLEW_VERSION_4_3 || GLEW_KHR_debug) {
SNPRINTF(msg, format, GLEW_VERSION_4_3 ? "OpenGL 4.3" : "KHR_debug extension");
glEnable(GL_DEBUG_OUTPUT);
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
@@ -148,7 +144,8 @@ void init_gl_callbacks(void)
msg);
}
else {
- fprintf(stderr, "GPUDebug: Failed to hook OpenGL debug callback\n");
+ fprintf(stderr, "GPUDebug: Failed to hook OpenGL debug callback. Use fallback debug layer.\n");
+ init_debug_layer();
}
}
@@ -243,4 +240,68 @@ void raise_gl_error(const char *info)
/** \} */
+/* -------------------------------------------------------------------- */
+/** \name Object Label
+ *
+ * Useful for debugging through renderdoc. Only defined if using --debug-gpu.
+ * Make sure to bind the object first so that it gets defined by the GL implementation.
+ * \{ */
+
+static const char *to_str_prefix(GLenum type)
+{
+ switch (type) {
+ case GL_FRAGMENT_SHADER:
+ case GL_GEOMETRY_SHADER:
+ case GL_VERTEX_SHADER:
+ case GL_SHADER:
+ case GL_PROGRAM:
+ return "SHD-";
+ case GL_SAMPLER:
+ return "SAM-";
+ case GL_TEXTURE:
+ return "TEX-";
+ case GL_FRAMEBUFFER:
+ return "FBO-";
+ case GL_VERTEX_ARRAY:
+ return "VAO-";
+ case GL_UNIFORM_BUFFER:
+ return "UBO-";
+ case GL_BUFFER:
+ return "BUF-";
+ default:
+ return "";
+ }
+}
+static const char *to_str_suffix(GLenum type)
+{
+ switch (type) {
+ case GL_FRAGMENT_SHADER:
+ return "-Frag";
+ case GL_GEOMETRY_SHADER:
+ return "-Geom";
+ case GL_VERTEX_SHADER:
+ return "-Vert";
+ default:
+ return "";
+ }
+}
+
+void object_label(GLenum type, GLuint object, const char *name)
+{
+ if ((G.debug & G_DEBUG_GPU) && (GLEW_VERSION_4_3 || GLEW_KHR_debug)) {
+ char label[64];
+ SNPRINTF(label, "%s%s%s", to_str_prefix(type), name, to_str_suffix(type));
+ /* Small convenience for caller. */
+ if (ELEM(type, GL_FRAGMENT_SHADER, GL_GEOMETRY_SHADER, GL_VERTEX_SHADER)) {
+ type = GL_SHADER;
+ }
+ if (ELEM(type, GL_UNIFORM_BUFFER)) {
+ type = GL_BUFFER;
+ }
+ glObjectLabel(type, object, -1, label);
+ }
+}
+
+/** \} */
+
} // namespace blender::gpu::debug
diff --git a/source/blender/gpu/opengl/gl_debug.hh b/source/blender/gpu/opengl/gl_debug.hh
index 5537147d0fe..892fb1d2ddb 100644
--- a/source/blender/gpu/opengl/gl_debug.hh
+++ b/source/blender/gpu/opengl/gl_debug.hh
@@ -20,16 +20,60 @@
#pragma once
-namespace blender {
-namespace gpu {
-namespace debug {
+#include "gl_context.hh"
-/* Enabled on MacOS by default since there is no support for debug callbacks. */
-#if defined(DEBUG) && defined(__APPLE__)
-# define GL_CHECK_ERROR(info) debug::check_gl_error(info)
-#else
-# define GL_CHECK_ERROR(info)
-#endif
+#include "glew-mx.h"
+
+/* Manual line breaks for readability. */
+/* clang-format off */
+#define _VA_ARG_LIST1(t) t
+#define _VA_ARG_LIST2(t, a) t a
+#define _VA_ARG_LIST4(t, a, b, c) \
+ _VA_ARG_LIST2(t, a), _VA_ARG_LIST2(b, c)
+#define _VA_ARG_LIST6(t, a, b, c, d, e) \
+ _VA_ARG_LIST2(t, a), _VA_ARG_LIST4(b, c, d, e)
+#define _VA_ARG_LIST8(t, a, b, c, d, e, f, g) \
+ _VA_ARG_LIST2(t, a), _VA_ARG_LIST6(b, c, d, e, f, g)
+#define _VA_ARG_LIST10(t, a, b, c, d, e, f, g, h, i) \
+ _VA_ARG_LIST2(t, a), _VA_ARG_LIST8(b, c, d, e, f, g, h, i)
+#define _VA_ARG_LIST12(t, a, b, c, d, e, f, g, h, i, j, k) \
+ _VA_ARG_LIST2(t, a), _VA_ARG_LIST10(b, c, d, e, f, g, h, i, j, k)
+#define _VA_ARG_LIST14(t, a, b, c, d, e, f, g, h, i, j, k, l, m) \
+ _VA_ARG_LIST2(t, a), _VA_ARG_LIST12(b, c, d, e, f, g, h, i, j, k, l, m)
+#define _VA_ARG_LIST16(t, a, b, c, d, e, f, g, h, i, j, k, l, m, o, p) \
+ _VA_ARG_LIST2(t, a), _VA_ARG_LIST14(b, c, d, e, f, g, h, i, j, k, l, m, o, p)
+#define _VA_ARG_LIST18(t, a, b, c, d, e, f, g, h, i, j, k, l, m, o, p, q, r) \
+ _VA_ARG_LIST2(t, a), _VA_ARG_LIST16(b, c, d, e, f, g, h, i, j, k, l, m, o, p, q, r)
+#define _VA_ARG_LIST20(t, a, b, c, d, e, f, g, h, i, j, k, l, m, o, p, q, r, s, u) \
+ _VA_ARG_LIST2(t, a), _VA_ARG_LIST18(b, c, d, e, f, g, h, i, j, k, l, m, o, p, q, r, s, u)
+#define _VA_ARG_LIST22(t, a, b, c, d, e, f, g, h, i, j, k, l, m, o, p, q, r, s, u, v, w) \
+ _VA_ARG_LIST2(t, a), _VA_ARG_LIST20(b, c, d, e, f, g, h, i, j, k, l, m, o, p, q, r, s, u, v, w)
+#define ARG_LIST(...) VA_NARGS_CALL_OVERLOAD(_VA_ARG_LIST, __VA_ARGS__)
+
+#define _VA_ARG_LIST_CALL1(t)
+#define _VA_ARG_LIST_CALL2(t, a) a
+#define _VA_ARG_LIST_CALL4(t, a, b, c) \
+ _VA_ARG_LIST_CALL2(t, a), _VA_ARG_LIST_CALL2(b, c)
+#define _VA_ARG_LIST_CALL6(t, a, b, c, d, e) \
+ _VA_ARG_LIST_CALL2(t, a), _VA_ARG_LIST_CALL4(b, c, d, e)
+#define _VA_ARG_LIST_CALL8(t, a, b, c, d, e, f, g) \
+ _VA_ARG_LIST_CALL2(t, a), _VA_ARG_LIST_CALL6(b, c, d, e, f, g)
+#define _VA_ARG_LIST_CALL10(t, a, b, c, d, e, f, g, h, i) \
+ _VA_ARG_LIST_CALL2(t, a), _VA_ARG_LIST_CALL8(b, c, d, e, f, g, h, i)
+#define _VA_ARG_LIST_CALL12(t, a, b, c, d, e, f, g, h, i, j, k) \
+ _VA_ARG_LIST_CALL2(t, a), _VA_ARG_LIST_CALL10(b, c, d, e, f, g, h, i, j, k)
+#define _VA_ARG_LIST_CALL14(t, a, b, c, d, e, f, g, h, i, j, k, l, m) \
+ _VA_ARG_LIST_CALL2(t, a), _VA_ARG_LIST_CALL12(b, c, d, e, f, g, h, i, j, k, l, m)
+#define _VA_ARG_LIST_CALL16(t, a, b, c, d, e, f, g, h, i, j, k, l, m, o, p) \
+ _VA_ARG_LIST_CALL2(t, a), _VA_ARG_LIST_CALL14(b, c, d, e, f, g, h, i, j, k, l, m, o, p)
+#define _VA_ARG_LIST_CALL18(t, a, b, c, d, e, f, g, h, i, j, k, l, m, o, p, q, r) \
+ _VA_ARG_LIST_CALL2(t, a), _VA_ARG_LIST_CALL16(b, c, d, e, f, g, h, i, j, k, l, m, o, p, q, r)
+#define _VA_ARG_LIST_CALL20(t, a, b, c, d, e, f, g, h, i, j, k, l, m, o, p, q, r, s, u) \
+ _VA_ARG_LIST_CALL2(t, a), _VA_ARG_LIST_CALL18(b, c, d, e, f, g, h, i, j, k, l, m, o, p, q, r, s, u)
+#define _VA_ARG_LIST_CALL22(t, a, b, c, d, e, f, g, h, i, j, k, l, m, o, p, q, r, s, u, v, w) \
+ _VA_ARG_LIST_CALL2(t, a), _VA_ARG_LIST_CALL20(b, c, d, e, f, g, h, i, j, k, l, m, o, p, q, r, s, u, v, w)
+#define ARG_LIST_CALL(...) VA_NARGS_CALL_OVERLOAD(_VA_ARG_LIST_CALL, __VA_ARGS__)
+/* clang-format on */
#ifdef DEBUG
# define GL_CHECK_RESOURCES(info) debug::check_gl_resources(info)
@@ -37,11 +81,52 @@ namespace debug {
# define GL_CHECK_RESOURCES(info)
#endif
+namespace blender {
+namespace gpu {
+namespace debug {
+
void raise_gl_error(const char *info);
void check_gl_error(const char *info);
void check_gl_resources(const char *info);
void init_gl_callbacks(void);
+void init_debug_layer(void);
+
+void object_label(GLenum type, GLuint object, const char *name);
+
} // namespace debug
+
+#define DEBUG_FUNC_OVERRIDE(func, ...) \
+ inline void func(ARG_LIST(__VA_ARGS__)) \
+ { \
+ if (GLContext::debug_layer_workaround) { \
+ debug::check_gl_error("generated before " #func); \
+ ::func(ARG_LIST_CALL(__VA_ARGS__)); \
+ debug::check_gl_error("" #func); \
+ } \
+ else { \
+ ::func(ARG_LIST_CALL(__VA_ARGS__)); \
+ } \
+ }
+
+/* Avoid very long declarations. */
+/* clang-format off */
+DEBUG_FUNC_OVERRIDE(glClear, GLbitfield, mask);
+DEBUG_FUNC_OVERRIDE(glDeleteTextures, GLsizei, n, const GLuint *, textures);
+DEBUG_FUNC_OVERRIDE(glDrawArrays, GLenum, mode, GLint, first, GLsizei, count);
+DEBUG_FUNC_OVERRIDE(glFinish, void);
+DEBUG_FUNC_OVERRIDE(glFlush, void);
+DEBUG_FUNC_OVERRIDE(glGenTextures, GLsizei, n, GLuint *, textures);
+DEBUG_FUNC_OVERRIDE(glGetTexImage, GLenum, target, GLint, level, GLenum, format, GLenum, type, void *, pixels);
+DEBUG_FUNC_OVERRIDE(glReadBuffer, GLenum, mode);
+DEBUG_FUNC_OVERRIDE(glReadPixels, GLint, x, GLint, y, GLsizei, width, GLsizei, height, GLenum, format, GLenum, type, void *, pixels);
+DEBUG_FUNC_OVERRIDE(glTexImage1D, GLenum, target, GLint, level, GLint, internalformat, GLsizei, width, GLint, border, GLenum, format, GLenum, type, const void *, pixels);
+DEBUG_FUNC_OVERRIDE(glTexImage2D, GLenum, target, GLint, level, GLint, internalformat, GLsizei, width, GLsizei, height, GLint, border, GLenum, format, GLenum, type, const void *, pixels);
+DEBUG_FUNC_OVERRIDE(glTexParameteri, GLenum, target, GLenum, pname, GLint, param);
+DEBUG_FUNC_OVERRIDE(glTexParameteriv, GLenum, target, GLenum, pname, const GLint *, params);
+DEBUG_FUNC_OVERRIDE(glTexSubImage1D, GLenum, target, GLint, level, GLint, xoffset, GLsizei, width, GLenum, format, GLenum, type, const void *, pixels);
+DEBUG_FUNC_OVERRIDE(glTexSubImage2D, GLenum, target, GLint, level, GLint, xoffset, GLint, yoffset, GLsizei, width, GLsizei, height, GLenum, format, GLenum, type, const void *, pixels);
+/* clang-format on */
+
} // namespace gpu
} // namespace blender
diff --git a/source/blender/gpu/opengl/gl_debug_layer.cc b/source/blender/gpu/opengl/gl_debug_layer.cc
new file mode 100644
index 00000000000..801cb9dbfbd
--- /dev/null
+++ b/source/blender/gpu/opengl/gl_debug_layer.cc
@@ -0,0 +1,165 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup gpu
+ *
+ * Implement our own subset of KHR_debug extension.
+ * We override the functions pointers by our own implementation that just checks glGetError.
+ */
+
+#include "BLI_utildefines.h"
+
+#include "glew-mx.h"
+
+#include "gl_debug.hh"
+
+typedef void *GPUvoidptr;
+
+#define GPUvoidptr_set void *ret =
+#define GPUvoidptr_ret return ret
+
+#define GLboolean_set GLboolean ret =
+#define GLboolean_ret return ret
+
+#define void_set
+#define void_ret
+
+#define DEBUG_FUNC_DECLARE(pfn, rtn_type, fn, ...) \
+ pfn real_##fn; \
+ static rtn_type GLAPIENTRY debug_##fn(ARG_LIST(__VA_ARGS__)) \
+ { \
+ debug::check_gl_error("generated before " #fn); \
+ rtn_type##_set real_##fn(ARG_LIST_CALL(__VA_ARGS__)); \
+ debug::check_gl_error("" #fn); \
+ rtn_type##_ret; \
+ }
+
+namespace blender::gpu::debug {
+
+/* List of wrapped functions. We dont have to support all of them.
+ * Some functions might be declared as extern in GLEW. We cannot override them in this case.
+ * Keep the list in alphabetical order. */
+
+/* Avoid very long declarations. */
+/* clang-format off */
+DEBUG_FUNC_DECLARE(PFNGLBEGINQUERYPROC, void, glBeginQuery, GLenum, target, GLuint, id);
+DEBUG_FUNC_DECLARE(PFNGLBEGINTRANSFORMFEEDBACKPROC, void, glBeginTransformFeedback, GLenum, primitiveMode);
+DEBUG_FUNC_DECLARE(PFNGLBINDBUFFERBASEPROC, void, glBindBufferBase, GLenum, target, GLuint, index, GLuint, buffer);
+DEBUG_FUNC_DECLARE(PFNGLBINDBUFFERPROC, void, glBindBuffer, GLenum, target, GLuint, buffer);
+DEBUG_FUNC_DECLARE(PFNGLBINDFRAMEBUFFERPROC, void, glBindFramebuffer, GLenum, target, GLuint, framebuffer);
+DEBUG_FUNC_DECLARE(PFNGLBINDSAMPLERPROC, void, glBindSampler, GLuint, unit, GLuint, sampler);
+DEBUG_FUNC_DECLARE(PFNGLBINDVERTEXARRAYPROC, void, glBindVertexArray, GLuint, array);
+DEBUG_FUNC_DECLARE(PFNGLBLITFRAMEBUFFERPROC, void, glBlitFramebuffer, GLint, srcX0, GLint, srcY0, GLint, srcX1, GLint, srcY1, GLint, dstX0, GLint, dstY0, GLint, dstX1, GLint, dstY1, GLbitfield, mask, GLenum, filter);
+DEBUG_FUNC_DECLARE(PFNGLBUFFERDATAPROC, void, glBufferData, GLenum, target, GLsizeiptr, size, const void *, data, GLenum, usage);
+DEBUG_FUNC_DECLARE(PFNGLBUFFERSUBDATAPROC, void, glBufferSubData, GLenum, target, GLintptr, offset, GLsizeiptr, size, const void *, data);
+DEBUG_FUNC_DECLARE(PFNGLDELETEBUFFERSPROC, void, glDeleteBuffers, GLsizei, n, const GLuint *, buffers);
+DEBUG_FUNC_DECLARE(PFNGLDELETEFRAMEBUFFERSPROC, void, glDeleteFramebuffers, GLsizei, n, const GLuint*, framebuffers);
+DEBUG_FUNC_DECLARE(PFNGLDELETEPROGRAMPROC, void, glDeleteProgram, GLuint, program);
+DEBUG_FUNC_DECLARE(PFNGLDELETEQUERIESPROC, void, glDeleteQueries, GLsizei, n, const GLuint *, ids);
+DEBUG_FUNC_DECLARE(PFNGLDELETESAMPLERSPROC, void, glDeleteSamplers, GLsizei, count, const GLuint *, samplers);
+DEBUG_FUNC_DECLARE(PFNGLDELETESHADERPROC, void, glDeleteShader, GLuint, shader);
+DEBUG_FUNC_DECLARE(PFNGLDELETEVERTEXARRAYSPROC, void, glDeleteVertexArrays, GLsizei, n, const GLuint *, arrays);
+DEBUG_FUNC_DECLARE(PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC, void, glDrawArraysInstancedBaseInstance, GLenum, mode, GLint, first, GLsizei, count, GLsizei, primcount, GLuint, baseinstance);
+DEBUG_FUNC_DECLARE(PFNGLDRAWARRAYSINSTANCEDPROC, void, glDrawArraysInstanced, GLenum, mode, GLint, first, GLsizei, count, GLsizei, primcount);
+DEBUG_FUNC_DECLARE(PFNGLDRAWBUFFERSPROC, void, glDrawBuffers, GLsizei, n, const GLenum*, bufs);
+DEBUG_FUNC_DECLARE(PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC, void, glDrawElementsInstancedBaseVertexBaseInstance, GLenum, mode, GLsizei, count, GLenum, type, const void *, indices, GLsizei, primcount, GLint, basevertex, GLuint, baseinstance);
+DEBUG_FUNC_DECLARE(PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC, void, glDrawElementsInstancedBaseVertex, GLenum, mode, GLsizei, count, GLenum, type, const void *, indices, GLsizei, instancecount, GLint, basevertex);
+DEBUG_FUNC_DECLARE(PFNGLENDQUERYPROC, void, glEndQuery, GLenum, target);
+DEBUG_FUNC_DECLARE(PFNGLENDTRANSFORMFEEDBACKPROC, void, glEndTransformFeedback, void);
+DEBUG_FUNC_DECLARE(PFNGLFRAMEBUFFERTEXTURE2DPROC, void, glFramebufferTexture2D, GLenum, target, GLenum, attachment, GLenum, textarget, GLuint, texture, GLint, level);
+DEBUG_FUNC_DECLARE(PFNGLFRAMEBUFFERTEXTURELAYERPROC, void, glFramebufferTextureLayer, GLenum, target, GLenum, attachment, GLuint, texture, GLint, level, GLint, layer);
+DEBUG_FUNC_DECLARE(PFNGLFRAMEBUFFERTEXTUREPROC, void, glFramebufferTexture, GLenum, target, GLenum, attachment, GLuint, texture, GLint, level);
+DEBUG_FUNC_DECLARE(PFNGLGENBUFFERSPROC, void, glGenBuffers, GLsizei, n, GLuint *, buffers);
+DEBUG_FUNC_DECLARE(PFNGLGENERATEMIPMAPPROC, void, glGenerateMipmap, GLenum, target);
+DEBUG_FUNC_DECLARE(PFNGLGENERATETEXTUREMIPMAPPROC, void, glGenerateTextureMipmap, GLuint, texture);
+DEBUG_FUNC_DECLARE(PFNGLGENFRAMEBUFFERSPROC, void, glGenFramebuffers, GLsizei, n, GLuint *, framebuffers);
+DEBUG_FUNC_DECLARE(PFNGLGENQUERIESPROC, void, glGenQueries, GLsizei, n, GLuint *, ids);
+DEBUG_FUNC_DECLARE(PFNGLGENSAMPLERSPROC, void, glGenSamplers, GLsizei, n, GLuint *, samplers);
+DEBUG_FUNC_DECLARE(PFNGLGENVERTEXARRAYSPROC, void, glGenVertexArrays, GLsizei, n, GLuint *, arrays);
+DEBUG_FUNC_DECLARE(PFNGLLINKPROGRAMPROC, void, glLinkProgram, GLuint, program);
+DEBUG_FUNC_DECLARE(PFNGLMAPBUFFERRANGEPROC, GPUvoidptr, glMapBufferRange, GLenum, target, GLintptr, offset, GLsizeiptr, length, GLbitfield, access);
+DEBUG_FUNC_DECLARE(PFNGLTEXBUFFERPROC, void, glTexBuffer, GLenum, target, GLenum, internalFormat, GLuint, buffer);
+DEBUG_FUNC_DECLARE(PFNGLTEXIMAGE3DPROC, void, glTexImage3D, GLenum, target, GLint, level, GLint, internalFormat, GLsizei, width, GLsizei, height, GLsizei, depth, GLint, border, GLenum, format, GLenum, type, const GLvoid *,pixels);
+DEBUG_FUNC_DECLARE(PFNGLTEXSUBIMAGE3DPROC, void, glTexSubImage3D, GLenum, target, GLint, level, GLint, xoffset, GLint, yoffset, GLint, zoffset, GLsizei, width, GLsizei, height, GLsizei, depth, GLenum, format, GLenum, type, const GLvoid *, pixels);
+DEBUG_FUNC_DECLARE(PFNGLTEXTUREBUFFERPROC, void, glTextureBuffer, GLuint, texture, GLenum, internalformat, GLuint, buffer);
+DEBUG_FUNC_DECLARE(PFNGLUNMAPBUFFERPROC, GLboolean, glUnmapBuffer, GLenum, target);
+DEBUG_FUNC_DECLARE(PFNGLUSEPROGRAMPROC, void, glUseProgram, GLuint, program);
+/* clang-format on */
+
+#undef DEBUG_FUNC_DECLARE
+
+/* Init a fallback layer (to KHR_debug) that covers only some functions.
+ * We override the functions pointers by our own implementation that just checks glGetError.
+ * Some additional functions (not overridable) are covered inside the header using wrappers. */
+void init_debug_layer(void)
+{
+#define DEBUG_WRAP(function) \
+ do { \
+ real_##function = ::function; \
+ ::function = &debug_##function; \
+ } while (0)
+
+ DEBUG_WRAP(glBeginQuery);
+ DEBUG_WRAP(glBeginTransformFeedback);
+ DEBUG_WRAP(glBindBuffer);
+ DEBUG_WRAP(glBindBufferBase);
+ DEBUG_WRAP(glBindFramebuffer);
+ DEBUG_WRAP(glBindSampler);
+ DEBUG_WRAP(glBindVertexArray);
+ DEBUG_WRAP(glBlitFramebuffer);
+ DEBUG_WRAP(glBufferData);
+ DEBUG_WRAP(glBufferSubData);
+ DEBUG_WRAP(glDeleteBuffers);
+ DEBUG_WRAP(glDeleteFramebuffers);
+ DEBUG_WRAP(glDeleteProgram);
+ DEBUG_WRAP(glDeleteQueries);
+ DEBUG_WRAP(glDeleteSamplers);
+ DEBUG_WRAP(glDeleteShader);
+ DEBUG_WRAP(glDeleteVertexArrays);
+ DEBUG_WRAP(glDrawArraysInstanced);
+ DEBUG_WRAP(glDrawArraysInstancedBaseInstance);
+ DEBUG_WRAP(glDrawBuffers);
+ DEBUG_WRAP(glDrawElementsInstancedBaseVertex);
+ DEBUG_WRAP(glDrawElementsInstancedBaseVertexBaseInstance);
+ DEBUG_WRAP(glEndQuery);
+ DEBUG_WRAP(glEndTransformFeedback);
+ DEBUG_WRAP(glFramebufferTexture);
+ DEBUG_WRAP(glFramebufferTexture2D);
+ DEBUG_WRAP(glFramebufferTextureLayer);
+ DEBUG_WRAP(glGenBuffers);
+ DEBUG_WRAP(glGenerateMipmap);
+ DEBUG_WRAP(glGenerateTextureMipmap);
+ DEBUG_WRAP(glGenFramebuffers);
+ DEBUG_WRAP(glGenQueries);
+ DEBUG_WRAP(glGenSamplers);
+ DEBUG_WRAP(glGenVertexArrays);
+ DEBUG_WRAP(glLinkProgram);
+ DEBUG_WRAP(glMapBufferRange);
+ DEBUG_WRAP(glTexBuffer);
+ DEBUG_WRAP(glTexImage3D);
+ DEBUG_WRAP(glTexSubImage3D);
+ DEBUG_WRAP(glTextureBuffer);
+ DEBUG_WRAP(glUnmapBuffer);
+ DEBUG_WRAP(glUseProgram);
+
+#undef DEBUG_WRAP
+}
+
+} // namespace blender::gpu::debug \ No newline at end of file
diff --git a/source/blender/gpu/opengl/gl_framebuffer.cc b/source/blender/gpu/opengl/gl_framebuffer.cc
index bfc8a2f74eb..1578c5fa619 100644
--- a/source/blender/gpu/opengl/gl_framebuffer.cc
+++ b/source/blender/gpu/opengl/gl_framebuffer.cc
@@ -26,10 +26,12 @@
#include "GPU_capabilities.h"
#include "gl_backend.hh"
-#include "gl_framebuffer.hh"
+#include "gl_debug.hh"
#include "gl_state.hh"
#include "gl_texture.hh"
+#include "gl_framebuffer.hh"
+
namespace blender::gpu {
/* -------------------------------------------------------------------- */
@@ -63,10 +65,8 @@ GLFrameBuffer::GLFrameBuffer(
viewport_[2] = scissor_[2] = w;
viewport_[3] = scissor_[3] = h;
- if (fbo_id_ && GLContext::debug_layer_support) {
- char sh_name[32];
- SNPRINTF(sh_name, "FrameBuffer-%s", name);
- glObjectLabel(GL_FRAMEBUFFER, fbo_id_, -1, sh_name);
+ if (fbo_id_) {
+ debug::object_label(GL_FRAMEBUFFER, fbo_id_, name_);
}
}
@@ -97,14 +97,11 @@ void GLFrameBuffer::init(void)
context_ = GLContext::get();
state_manager_ = static_cast<GLStateManager *>(context_->state_manager);
glGenFramebuffers(1, &fbo_id_);
+ /* Binding before setting the label is needed on some drivers.
+ * This is not an issue since we call this function only before binding. */
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo_id_);
- if (GLContext::debug_layer_support) {
- char sh_name[64];
- SNPRINTF(sh_name, "FrameBuffer-%s", name_);
- /* Binding before setting the label is needed on some drivers. */
- glBindFramebuffer(GL_FRAMEBUFFER, fbo_id_);
- glObjectLabel(GL_FRAMEBUFFER, fbo_id_, -1, sh_name);
- }
+ debug::object_label(GL_FRAMEBUFFER, fbo_id_, name_);
}
/** \} */
diff --git a/source/blender/gpu/opengl/gl_immediate.cc b/source/blender/gpu/opengl/gl_immediate.cc
index 7afbbf9965c..fd31d77cc80 100644
--- a/source/blender/gpu/opengl/gl_immediate.cc
+++ b/source/blender/gpu/opengl/gl_immediate.cc
@@ -60,11 +60,9 @@ GLImmediate::GLImmediate()
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
- if (GLContext::debug_layer_support) {
- glObjectLabel(GL_VERTEX_ARRAY, vao_id_, -1, "VAO-Immediate");
- glObjectLabel(GL_BUFFER, buffer.vbo_id, -1, "VBO-ImmediateBuffer");
- glObjectLabel(GL_BUFFER, buffer_strict.vbo_id, -1, "VBO-ImmediateBufferStrict");
- }
+ debug::object_label(GL_VERTEX_ARRAY, vao_id_, "Immediate");
+ debug::object_label(GL_BUFFER, buffer.vbo_id, "ImmediateVbo");
+ debug::object_label(GL_BUFFER, buffer_strict.vbo_id, "ImmediateVboStrict");
}
GLImmediate::~GLImmediate()
@@ -89,7 +87,6 @@ uchar *GLImmediate::begin()
const size_t available_bytes = buffer_size() - buffer_offset();
GL_CHECK_RESOURCES("Immediate");
- GL_CHECK_ERROR("Immediate Pre-Begin");
glBindBuffer(GL_ARRAY_BUFFER, vbo_id());
@@ -133,7 +130,6 @@ uchar *GLImmediate::begin()
}
void *data = glMapBufferRange(GL_ARRAY_BUFFER, buffer_offset(), bytes_needed, access);
BLI_assert(data != NULL);
- GL_CHECK_ERROR("Immediate Post-Begin");
bytes_mapped_ = bytes_needed;
return (uchar *)data;
@@ -155,8 +151,6 @@ void GLImmediate::end(void)
}
glUnmapBuffer(GL_ARRAY_BUFFER);
- GL_CHECK_ERROR("Immediate Post-Unmap");
-
if (vertex_len > 0) {
GLContext::get()->state_manager->apply_state();
@@ -180,8 +174,6 @@ void GLImmediate::end(void)
* They are not required so just comment them. (T55722) */
// glBindBuffer(GL_ARRAY_BUFFER, 0);
// glBindVertexArray(0);
-
- GL_CHECK_ERROR("Immediate Post-drawing");
}
buffer_offset() += buffer_bytes_used;
diff --git a/source/blender/gpu/opengl/gl_shader.cc b/source/blender/gpu/opengl/gl_shader.cc
index 4314ecfa6be..7b3a071bf63 100644
--- a/source/blender/gpu/opengl/gl_shader.cc
+++ b/source/blender/gpu/opengl/gl_shader.cc
@@ -28,6 +28,7 @@
#include "GPU_platform.h"
#include "gl_backend.hh"
+#include "gl_debug.hh"
#include "gl_vertex_buffer.hh"
#include "gl_shader.hh"
@@ -48,11 +49,7 @@ GLShader::GLShader(const char *name) : Shader(name)
#endif
shader_program_ = glCreateProgram();
- if (GLContext::debug_layer_support) {
- char sh_name[64];
- SNPRINTF(sh_name, "ShaderProgram-%s", name);
- glObjectLabel(GL_PROGRAM, shader_program_, -1, sh_name);
- }
+ debug::object_label(GL_PROGRAM, shader_program_, name);
}
GLShader::~GLShader(void)
@@ -163,21 +160,7 @@ GLuint GLShader::create_shader_stage(GLenum gl_stage, MutableSpan<const char *>
return 0;
}
- if (GLContext::debug_layer_support) {
- char sh_name[64];
- switch (gl_stage) {
- case GL_VERTEX_SHADER:
- BLI_snprintf(sh_name, sizeof(sh_name), "VertShader-%s", name);
- break;
- case GL_GEOMETRY_SHADER:
- BLI_snprintf(sh_name, sizeof(sh_name), "GeomShader-%s", name);
- break;
- case GL_FRAGMENT_SHADER:
- BLI_snprintf(sh_name, sizeof(sh_name), "FragShader-%s", name);
- break;
- }
- glObjectLabel(GL_SHADER, shader, -1, sh_name);
- }
+ debug::object_label(gl_stage, shader, name);
glAttachShader(shader_program_, shader);
return shader;
diff --git a/source/blender/gpu/opengl/gl_state.cc b/source/blender/gpu/opengl/gl_state.cc
index 6dcb56288e8..970a4d45a88 100644
--- a/source/blender/gpu/opengl/gl_state.cc
+++ b/source/blender/gpu/opengl/gl_state.cc
@@ -30,6 +30,7 @@
#include "glew-mx.h"
#include "gl_context.hh"
+#include "gl_debug.hh"
#include "gl_framebuffer.hh"
#include "gl_texture.hh"
diff --git a/source/blender/gpu/opengl/gl_state.hh b/source/blender/gpu/opengl/gl_state.hh
index db9b9721ad5..fb2ed3403f7 100644
--- a/source/blender/gpu/opengl/gl_state.hh
+++ b/source/blender/gpu/opengl/gl_state.hh
@@ -42,8 +42,8 @@ class GLTexture;
**/
class GLStateManager : public GPUStateManager {
public:
- /** Anothter reference to tje active framebuffer. */
- GLFrameBuffer *active_fb;
+ /** Anothter reference to the active framebuffer. */
+ GLFrameBuffer *active_fb = nullptr;
private:
/** Current state of the GL implementation. Avoids resetting the whole state for every change. */
diff --git a/source/blender/gpu/opengl/gl_texture.cc b/source/blender/gpu/opengl/gl_texture.cc
index ec08b736af2..4e279fc47c1 100644
--- a/source/blender/gpu/opengl/gl_texture.cc
+++ b/source/blender/gpu/opengl/gl_texture.cc
@@ -96,14 +96,7 @@ bool GLTexture::init_internal(void)
glTexParameteri(target_, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}
- if (GLContext::debug_layer_support) {
- char sh_name[64];
- SNPRINTF(sh_name, "Texture-%s", name_);
- /* Binding before setting the label is needed on some drivers. */
- glObjectLabel(GL_TEXTURE, tex_id_, -1, sh_name);
- }
-
- GL_CHECK_ERROR("Post-texture creation");
+ debug::object_label(GL_TEXTURE, tex_id_, name_);
return true;
}
@@ -125,14 +118,8 @@ bool GLTexture::init_internal(GPUVertBuf *vbo)
glTexBuffer(target_, internal_format, gl_vbo->vbo_id_);
}
- if (GLContext::debug_layer_support) {
- char sh_name[64];
- SNPRINTF(sh_name, "Texture-%s", name_);
- /* Binding before setting the label is needed on some drivers. */
- glObjectLabel(GL_TEXTURE, tex_id_, -1, sh_name);
- }
+ debug::object_label(GL_TEXTURE, tex_id_, name_);
- GL_CHECK_ERROR("Post-texture buffer creation");
return true;
}
@@ -193,8 +180,6 @@ void GLTexture::ensure_mipmaps(int miplvl)
break;
}
}
-
- GL_CHECK_ERROR("Post-mipmap creation");
}
this->mip_range_set(0, mipmaps_);
@@ -240,7 +225,6 @@ void GLTexture::update_sub_direct_state_access(
break;
}
}
- GL_CHECK_ERROR("Post-update_sub_direct_state_access");
}
void GLTexture::update_sub(
@@ -304,8 +288,6 @@ void GLTexture::update_sub(
break;
}
}
-
- GL_CHECK_ERROR("Post-update_sub");
}
/** This will create the mipmap images and populate them with filtered data from base level.
@@ -510,22 +492,20 @@ void GLTexture::samplers_init(void)
* - GL_TEXTURE_LOD_BIAS is 0.0f.
**/
- if (GLContext::debug_layer_support) {
- char sampler_name[128];
- SNPRINTF(sampler_name,
- "Sampler%s%s%s%s%s%s%s%s%s%s",
- (state == GPU_SAMPLER_DEFAULT) ? "_default" : "",
- (state & GPU_SAMPLER_FILTER) ? "_filter" : "",
- (state & GPU_SAMPLER_MIPMAP) ? "_mipmap" : "",
- (state & GPU_SAMPLER_REPEAT) ? "_repeat-" : "",
- (state & GPU_SAMPLER_REPEAT_S) ? "S" : "",
- (state & GPU_SAMPLER_REPEAT_T) ? "T" : "",
- (state & GPU_SAMPLER_REPEAT_R) ? "R" : "",
- (state & GPU_SAMPLER_CLAMP_BORDER) ? "_clamp_border" : "",
- (state & GPU_SAMPLER_COMPARE) ? "_compare" : "",
- (state & GPU_SAMPLER_ANISO) ? "_aniso" : "");
- glObjectLabel(GL_SAMPLER, samplers_[i], -1, sampler_name);
- }
+ char sampler_name[128] = "\0\0";
+ SNPRINTF(sampler_name,
+ "%s%s%s%s%s%s%s%s%s%s",
+ (state == GPU_SAMPLER_DEFAULT) ? "_default" : "",
+ (state & GPU_SAMPLER_FILTER) ? "_filter" : "",
+ (state & GPU_SAMPLER_MIPMAP) ? "_mipmap" : "",
+ (state & GPU_SAMPLER_REPEAT) ? "_repeat-" : "",
+ (state & GPU_SAMPLER_REPEAT_S) ? "S" : "",
+ (state & GPU_SAMPLER_REPEAT_T) ? "T" : "",
+ (state & GPU_SAMPLER_REPEAT_R) ? "R" : "",
+ (state & GPU_SAMPLER_CLAMP_BORDER) ? "_clamp_border" : "",
+ (state & GPU_SAMPLER_COMPARE) ? "_compare" : "",
+ (state & GPU_SAMPLER_ANISO) ? "_aniso" : "");
+ debug::object_label(GL_SAMPLER, samplers_[i], &sampler_name[1]);
}
samplers_update();
@@ -535,9 +515,7 @@ void GLTexture::samplers_init(void)
glSamplerParameteri(icon_sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glSamplerParameterf(icon_sampler, GL_TEXTURE_LOD_BIAS, -0.5f);
- if (GLContext::debug_layer_support) {
- glObjectLabel(GL_SAMPLER, icon_sampler, -1, "Sampler-icons");
- }
+ debug::object_label(GL_SAMPLER, icon_sampler, "icons");
}
void GLTexture::samplers_update(void)
diff --git a/source/blender/gpu/opengl/gl_uniform_buffer.cc b/source/blender/gpu/opengl/gl_uniform_buffer.cc
index 74453a08bfe..dd305fca555 100644
--- a/source/blender/gpu/opengl/gl_uniform_buffer.cc
+++ b/source/blender/gpu/opengl/gl_uniform_buffer.cc
@@ -29,6 +29,7 @@
#include "gpu_context_private.hh"
#include "gl_backend.hh"
+#include "gl_debug.hh"
#include "gl_uniform_buffer.hh"
namespace blender::gpu {
@@ -62,11 +63,7 @@ void GLUniformBuf::init(void)
glBindBuffer(GL_UNIFORM_BUFFER, ubo_id_);
glBufferData(GL_UNIFORM_BUFFER, size_in_bytes_, NULL, GL_DYNAMIC_DRAW);
- if (GLContext::debug_layer_support) {
- char sh_name[64];
- SNPRINTF(sh_name, "UBO-%s", name_);
- glObjectLabel(GL_BUFFER, ubo_id_, -1, sh_name);
- }
+ debug::object_label(GL_UNIFORM_BUFFER, ubo_id_, name_);
}
void GLUniformBuf::update(const void *data)