From 136bdb561b4ce05788e7b654c7e734cc35664b91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Sat, 12 Sep 2020 06:10:11 +0200 Subject: GPU: Add Image Load Store extension support This wraps the functionality used to speedup EEVEE volumetrics. This touches the rendering code of EEVEE as it should fix a mis-usage of the GL barrier. The barrier changed type and location, removing an unused barrier. --- source/blender/gpu/opengl/gl_state.cc | 95 +++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) (limited to 'source/blender/gpu/opengl/gl_state.cc') diff --git a/source/blender/gpu/opengl/gl_state.cc b/source/blender/gpu/opengl/gl_state.cc index 1678760e9cd..93753768928 100644 --- a/source/blender/gpu/opengl/gl_state.cc +++ b/source/blender/gpu/opengl/gl_state.cc @@ -76,6 +76,7 @@ void GLStateManager::apply_state(void) this->set_state(this->state); this->set_mutable_state(this->mutable_state); this->texture_bind_apply(); + this->image_bind_apply(); active_fb->apply_state(); }; @@ -538,4 +539,98 @@ uint64_t GLStateManager::bound_texture_slots(void) /** \} */ +/* -------------------------------------------------------------------- */ +/** \name Image Binding (from image load store) + * \{ */ + +void GLStateManager::image_bind(Texture *tex_, int unit) +{ + /* Minimum support is 8 image in the fragment shader. No image for other stages. */ + BLI_assert(GPU_shader_image_load_store_support() && unit < 8); + GLTexture *tex = static_cast(tex_); + if (G.debug & G_DEBUG_GPU) { + tex->check_feedback_loop(); + } + images_[unit] = tex->tex_id_; + formats_[unit] = to_gl_internal_format(tex->format_); + tex->is_bound_ = true; + dirty_image_binds_ |= 1ULL << unit; +} + +void GLStateManager::image_unbind(Texture *tex_) +{ + GLTexture *tex = static_cast(tex_); + if (!tex->is_bound_) { + return; + } + + GLuint tex_id = tex->tex_id_; + for (int i = 0; i < ARRAY_SIZE(images_); i++) { + if (images_[i] == tex_id) { + images_[i] = 0; + dirty_image_binds_ |= 1ULL << i; + } + } + tex->is_bound_ = false; +} + +void GLStateManager::image_unbind_all(void) +{ + for (int i = 0; i < ARRAY_SIZE(images_); i++) { + if (images_[i] != 0) { + images_[i] = 0; + dirty_image_binds_ |= 1ULL << i; + } + } + this->image_bind_apply(); +} + +void GLStateManager::image_bind_apply(void) +{ + if (dirty_image_binds_ == 0) { + return; + } + uint32_t dirty_bind = dirty_image_binds_; + dirty_image_binds_ = 0; + + int first = bitscan_forward_uint(dirty_bind); + int last = 32 - bitscan_reverse_uint(dirty_bind); + int count = last - first; + + if (GLContext::multi_bind_support) { + glBindImageTextures(first, count, images_ + first); + } + else { + for (int unit = first; unit < last; unit++) { + if ((dirty_bind >> unit) & 1UL) { + glBindImageTexture(unit, images_[unit], 0, GL_TRUE, 0, GL_READ_WRITE, formats_[unit]); + } + } + } +} + +uint8_t GLStateManager::bound_image_slots(void) +{ + uint8_t bound_slots = 0; + for (int i = 0; i < ARRAY_SIZE(images_); i++) { + if (images_[i] != 0) { + bound_slots |= 1ULL << i; + } + } + return bound_slots; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Memory barrier + * \{ */ + +void GLStateManager::issue_barrier(eGPUBarrier barrier_bits) +{ + glMemoryBarrier(to_gl(barrier_bits)); +} + +/** \} */ + } // namespace blender::gpu -- cgit v1.2.3