diff --git a/source/blender/compositor/realtime_compositor/intern/shader_operation.cc b/source/blender/compositor/realtime_compositor/intern/shader_operation.cc index 76fc4afbd68..46da9a259af 100644 --- a/source/blender/compositor/realtime_compositor/intern/shader_operation.cc +++ b/source/blender/compositor/realtime_compositor/intern/shader_operation.cc @@ -73,7 +73,7 @@ void ShaderOperation::execute() GPU_texture_unbind_all(); GPU_texture_image_unbind_all(); - GPU_uniformbuf_unbind_all(); + GPU_uniformbuf_debug_unbind_all(); GPU_shader_unbind(); } diff --git a/source/blender/draw/intern/draw_command.hh b/source/blender/draw/intern/draw_command.hh index abfa16da7be..6b1c622f63a 100644 --- a/source/blender/draw/intern/draw_command.hh +++ b/source/blender/draw/intern/draw_command.hh @@ -67,10 +67,10 @@ struct RecordingState { } if (G.debug & G_DEBUG_GPU) { - GPU_storagebuf_unbind_all(); + GPU_storagebuf_debug_unbind_all(); GPU_texture_image_unbind_all(); GPU_texture_unbind_all(); - GPU_uniformbuf_unbind_all(); + GPU_uniformbuf_debug_unbind_all(); } } }; diff --git a/source/blender/draw/intern/draw_manager_exec.cc b/source/blender/draw/intern/draw_manager_exec.cc index 007446bc11c..9915c2be35f 100644 --- a/source/blender/draw/intern/draw_manager_exec.cc +++ b/source/blender/draw/intern/draw_manager_exec.cc @@ -320,8 +320,8 @@ void DRW_state_reset() GPU_texture_unbind_all(); GPU_texture_image_unbind_all(); - GPU_uniformbuf_unbind_all(); - GPU_storagebuf_unbind_all(); + GPU_uniformbuf_debug_unbind_all(); + GPU_storagebuf_debug_unbind_all(); /* Should stay constant during the whole rendering. */ GPU_point_size(5); @@ -1011,8 +1011,8 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state) if (G.debug & G_DEBUG_GPU) { GPU_texture_unbind_all(); GPU_texture_image_unbind_all(); - GPU_uniformbuf_unbind_all(); - GPU_storagebuf_unbind_all(); + GPU_uniformbuf_debug_unbind_all(); + GPU_storagebuf_debug_unbind_all(); } } GPU_shader_bind(shgroup->shader); diff --git a/source/blender/gpu/GPU_storage_buffer.hh b/source/blender/gpu/GPU_storage_buffer.hh index d0aac3e3b96..f96286a3835 100644 --- a/source/blender/gpu/GPU_storage_buffer.hh +++ b/source/blender/gpu/GPU_storage_buffer.hh @@ -34,7 +34,11 @@ void GPU_storagebuf_update(GPUStorageBuf *ssbo, const void *data); void GPU_storagebuf_bind(GPUStorageBuf *ssbo, int slot); void GPU_storagebuf_unbind(GPUStorageBuf *ssbo); -void GPU_storagebuf_unbind_all(); +/** + * Resets the internal slot usage tracking. But there is no guarantee that + * this actually undo the bindings for the next draw call. Only has effect when G_DEBUG_GPU is set. + */ +void GPU_storagebuf_debug_unbind_all(); void GPU_storagebuf_clear_to_zero(GPUStorageBuf *ssbo); diff --git a/source/blender/gpu/GPU_uniform_buffer.hh b/source/blender/gpu/GPU_uniform_buffer.hh index 836f611fd73..e2a773fbf0a 100644 --- a/source/blender/gpu/GPU_uniform_buffer.hh +++ b/source/blender/gpu/GPU_uniform_buffer.hh @@ -38,7 +38,11 @@ void GPU_uniformbuf_update(GPUUniformBuf *ubo, const void *data); void GPU_uniformbuf_bind(GPUUniformBuf *ubo, int slot); void GPU_uniformbuf_bind_as_ssbo(GPUUniformBuf *ubo, int slot); void GPU_uniformbuf_unbind(GPUUniformBuf *ubo); -void GPU_uniformbuf_unbind_all(); +/** + * Resets the internal slot usage tracking. But there is no guarantee that + * this actually undo the bindings for the next draw call. Only has effect when G_DEBUG_GPU is set. + */ +void GPU_uniformbuf_debug_unbind_all(); void GPU_uniformbuf_clear_to_zero(GPUUniformBuf *ubo); diff --git a/source/blender/gpu/dummy/dummy_context.hh b/source/blender/gpu/dummy/dummy_context.hh index f9e2cc0a3bf..35774c31196 100644 --- a/source/blender/gpu/dummy/dummy_context.hh +++ b/source/blender/gpu/dummy/dummy_context.hh @@ -46,6 +46,9 @@ class DummyContext : public Context { return false; } void debug_capture_scope_end(void * /*scope*/) override {} + + void debug_unbind_all_ubo() override {} + void debug_unbind_all_ssbo() override {} }; } // namespace blender::gpu diff --git a/source/blender/gpu/intern/gpu_context_private.hh b/source/blender/gpu/intern/gpu_context_private.hh index 728d29824b7..1ba2e47b295 100644 --- a/source/blender/gpu/intern/gpu_context_private.hh +++ b/source/blender/gpu/intern/gpu_context_private.hh @@ -93,6 +93,11 @@ class Context { virtual bool debug_capture_scope_begin(void *scope) = 0; virtual void debug_capture_scope_end(void *scope) = 0; + /* Consider all buffers slot empty after these call for error checking. + * But doesn't really free them. */ + virtual void debug_unbind_all_ubo() = 0; + virtual void debug_unbind_all_ssbo() = 0; + bool is_active_on_thread(); }; diff --git a/source/blender/gpu/intern/gpu_storage_buffer.cc b/source/blender/gpu/intern/gpu_storage_buffer.cc index 8db29992bc6..de345fe5470 100644 --- a/source/blender/gpu/intern/gpu_storage_buffer.cc +++ b/source/blender/gpu/intern/gpu_storage_buffer.cc @@ -19,6 +19,7 @@ #include "GPU_storage_buffer.hh" #include "GPU_vertex_buffer.hh" +#include "gpu_context_private.hh" #include "gpu_storage_buffer_private.hh" /* -------------------------------------------------------------------- */ @@ -85,9 +86,9 @@ void GPU_storagebuf_unbind(GPUStorageBuf *ssbo) unwrap(ssbo)->unbind(); } -void GPU_storagebuf_unbind_all() +void GPU_storagebuf_debug_unbind_all() { - /* FIXME */ + Context::get()->debug_unbind_all_ssbo(); } void GPU_storagebuf_clear_to_zero(GPUStorageBuf *ssbo) diff --git a/source/blender/gpu/intern/gpu_uniform_buffer.cc b/source/blender/gpu/intern/gpu_uniform_buffer.cc index eca4740c11e..e15894a5fd7 100644 --- a/source/blender/gpu/intern/gpu_uniform_buffer.cc +++ b/source/blender/gpu/intern/gpu_uniform_buffer.cc @@ -19,6 +19,7 @@ #include "GPU_material.hh" #include "GPU_uniform_buffer.hh" +#include "gpu_context_private.hh" #include "gpu_uniform_buffer_private.hh" /* -------------------------------------------------------------------- */ @@ -240,9 +241,9 @@ void GPU_uniformbuf_unbind(GPUUniformBuf *ubo) unwrap(ubo)->unbind(); } -void GPU_uniformbuf_unbind_all() +void GPU_uniformbuf_debug_unbind_all() { - /* FIXME */ + Context::get()->debug_unbind_all_ubo(); } void GPU_uniformbuf_clear_to_zero(GPUUniformBuf *ubo) diff --git a/source/blender/gpu/metal/mtl_context.hh b/source/blender/gpu/metal/mtl_context.hh index 0e7e615358a..bc6ab625fe4 100644 --- a/source/blender/gpu/metal/mtl_context.hh +++ b/source/blender/gpu/metal/mtl_context.hh @@ -786,6 +786,9 @@ class MTLContext : public Context { bool debug_capture_scope_begin(void *scope) override; void debug_capture_scope_end(void *scope) override; + void debug_unbind_all_ubo() override{}; + void debug_unbind_all_ssbo() override{}; + /*** MTLContext Utility functions. */ /* * All below functions modify the global state for the context, controlling the flow of diff --git a/source/blender/gpu/opengl/gl_context.cc b/source/blender/gpu/opengl/gl_context.cc index cc58d7084d4..de95e643e80 100644 --- a/source/blender/gpu/opengl/gl_context.cc +++ b/source/blender/gpu/opengl/gl_context.cc @@ -140,6 +140,7 @@ void GLContext::activate() /* Not really following the state but we should consider * no ubo bound when activating a context. */ bound_ubo_slots = 0; + bound_ssbo_slots = 0; immActivate(); } diff --git a/source/blender/gpu/opengl/gl_context.hh b/source/blender/gpu/opengl/gl_context.hh index 5061de0ac59..d59ebab9903 100644 --- a/source/blender/gpu/opengl/gl_context.hh +++ b/source/blender/gpu/opengl/gl_context.hh @@ -74,6 +74,7 @@ class GLContext : public Context { /** Used for debugging purpose. Bitflags of all bound slots. */ uint16_t bound_ubo_slots; + uint16_t bound_ssbo_slots; private: /** @@ -135,6 +136,9 @@ class GLContext : public Context { bool debug_capture_scope_begin(void *scope) override; void debug_capture_scope_end(void *scope) override; + void debug_unbind_all_ubo() override; + void debug_unbind_all_ssbo() override; + private: static void orphans_add(Vector &orphan_list, std::mutex &list_mutex, GLuint id); void orphans_clear(); diff --git a/source/blender/gpu/opengl/gl_debug.cc b/source/blender/gpu/opengl/gl_debug.cc index 71c09e7e356..37637c989ce 100644 --- a/source/blender/gpu/opengl/gl_debug.cc +++ b/source/blender/gpu/opengl/gl_debug.cc @@ -224,6 +224,10 @@ 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 ssbo needs to + * be big enough to feed the data range the shader awaits. */ + uint16_t ssbo_needed = interface->enabled_ssbo_mask_; + ssbo_needed &= ~ctx->bound_ssbo_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_; @@ -233,7 +237,7 @@ void check_gl_resources(const char *info) 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 && ima_needed == 0) { + if (ubo_needed == 0 && tex_needed == 0 && ima_needed == 0 && ssbo_needed == 0) { return; } @@ -248,6 +252,17 @@ void check_gl_resources(const char *info) } } + for (int i = 0; ssbo_needed != 0; i++, ssbo_needed >>= 1) { + if ((ssbo_needed & 1) != 0) { + const ShaderInput *ssbo_input = interface->ssbo_get(i); + const char *ssbo_name = interface->input_name_get(ssbo_input); + const char *sh_name = ctx->shader->name_get(); + char msg[256]; + SNPRINTF(msg, "Missing SSBO bind at slot %d : %s > %s : %s", i, sh_name, ssbo_name, info); + 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. */ @@ -432,6 +447,16 @@ bool GLContext::debug_capture_scope_begin(void * /*scope*/) void GLContext::debug_capture_scope_end(void * /*scope*/) {} +void GLContext::debug_unbind_all_ubo() +{ + this->bound_ubo_slots = 0u; +} + +void GLContext::debug_unbind_all_ssbo() +{ + this->bound_ssbo_slots = 0u; +} + /** \} */ } // namespace blender::gpu diff --git a/source/blender/gpu/opengl/gl_storage_buffer.cc b/source/blender/gpu/opengl/gl_storage_buffer.cc index 76a76492ce9..3a4189282b5 100644 --- a/source/blender/gpu/opengl/gl_storage_buffer.cc +++ b/source/blender/gpu/opengl/gl_storage_buffer.cc @@ -115,8 +115,7 @@ void GLStorageBuf::bind(int slot) #ifndef NDEBUG BLI_assert(slot < 16); - /* TODO */ - // GLContext::get()->bound_ssbo_slots |= 1 << slot; + GLContext::get()->bound_ssbo_slots |= 1 << slot; #endif } @@ -133,8 +132,7 @@ void GLStorageBuf::unbind() /* NOTE: This only unbinds the last bound slot. */ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, slot_, 0); /* Hope that the context did not change. */ - /* TODO */ - // GLContext::get()->bound_ssbo_slots &= ~(1 << slot_); + GLContext::get()->bound_ssbo_slots &= ~(1 << slot_); #endif slot_ = 0; } diff --git a/source/blender/gpu/vulkan/vk_context.hh b/source/blender/gpu/vulkan/vk_context.hh index fe7884b180e..37417252c4a 100644 --- a/source/blender/gpu/vulkan/vk_context.hh +++ b/source/blender/gpu/vulkan/vk_context.hh @@ -56,6 +56,9 @@ class VKContext : public Context, NonCopyable { bool debug_capture_scope_begin(void *scope) override; void debug_capture_scope_end(void *scope) override; + void debug_unbind_all_ubo() override{}; + void debug_unbind_all_ssbo() override{}; + bool has_active_framebuffer() const; void activate_framebuffer(VKFrameBuffer &framebuffer); void deactivate_framebuffer();