diff options
-rw-r--r-- | source/blender/gpu/CMakeLists.txt | 1 | ||||
-rw-r--r-- | source/blender/gpu/opengl/gl_backend.cc | 18 | ||||
-rw-r--r-- | source/blender/gpu/opengl/gl_batch.cc | 3 | ||||
-rw-r--r-- | source/blender/gpu/opengl/gl_context.cc | 6 | ||||
-rw-r--r-- | source/blender/gpu/opengl/gl_context.hh | 1 | ||||
-rw-r--r-- | source/blender/gpu/opengl/gl_debug.cc | 75 | ||||
-rw-r--r-- | source/blender/gpu/opengl/gl_debug.hh | 103 | ||||
-rw-r--r-- | source/blender/gpu/opengl/gl_debug_layer.cc | 165 | ||||
-rw-r--r-- | source/blender/gpu/opengl/gl_framebuffer.cc | 21 | ||||
-rw-r--r-- | source/blender/gpu/opengl/gl_immediate.cc | 14 | ||||
-rw-r--r-- | source/blender/gpu/opengl/gl_shader.cc | 23 | ||||
-rw-r--r-- | source/blender/gpu/opengl/gl_state.cc | 1 | ||||
-rw-r--r-- | source/blender/gpu/opengl/gl_state.hh | 4 | ||||
-rw-r--r-- | source/blender/gpu/opengl/gl_texture.cc | 56 | ||||
-rw-r--r-- | source/blender/gpu/opengl/gl_uniform_buffer.cc | 7 |
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) |