[Bf-blender-cvs] [4b40e9dbf93] temp-viewport-compositor-compiler: Viewport Compositor: Complete texture pool class

Omar Emara noreply at git.blender.org
Mon Feb 14 11:22:44 CET 2022


Commit: 4b40e9dbf931b71551344ab9e7f0a17361c60253
Author: Omar Emara
Date:   Mon Feb 14 12:18:49 2022 +0200
Branches: temp-viewport-compositor-compiler
https://developer.blender.org/rB4b40e9dbf931b71551344ab9e7f0a17361c60253

Viewport Compositor: Complete texture pool class

This patch adds reference counting support to the texture pool,
separates the allocation implementation to a pure virtual method, and
implements a concrete class for the compositor engine based on the DRW
texture pool.

===================================================================

M	source/blender/draw/engines/compositor/compositor_engine.cc
M	source/blender/gpu/GPU_texture.h
M	source/blender/gpu/intern/gpu_texture.cc
M	source/blender/nodes/NOD_compositor_execute.hh
M	source/blender/nodes/intern/node_compositor_execute.cc

===================================================================

diff --git a/source/blender/draw/engines/compositor/compositor_engine.cc b/source/blender/draw/engines/compositor/compositor_engine.cc
index 4d25f72b1d6..74086dc6eb8 100644
--- a/source/blender/draw/engines/compositor/compositor_engine.cc
+++ b/source/blender/draw/engines/compositor/compositor_engine.cc
@@ -36,6 +36,14 @@
 
 namespace blender::compositor {
 
+class DRWTexturePool : public TexturePool {
+  GPUTexture *allocate_texture(int width, int height, eGPUTextureFormat format) override
+  {
+    DrawEngineType *owner = (DrawEngineType *)this;
+    return DRW_texture_pool_query_2d(width, height, format, owner);
+  }
+};
+
 class DRWCompositorContext : public CompositorContext {
   GPUTexture *get_viewport_texture() override
   {
diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h
index 6fae4a13918..fd58071c6e5 100644
--- a/source/blender/gpu/GPU_texture.h
+++ b/source/blender/gpu/GPU_texture.h
@@ -280,6 +280,9 @@ void GPU_texture_clear(GPUTexture *tex, eGPUDataFormat data_format, const void *
 void GPU_texture_free(GPUTexture *tex);
 
 void GPU_texture_ref(GPUTexture *tex);
+void GPU_texture_set_reference_count(GPUTexture *texture, int count);
+int GPU_texture_get_reference_count(GPUTexture *texture);
+
 void GPU_texture_bind(GPUTexture *tex, int unit);
 void GPU_texture_bind_ex(GPUTexture *tex, eGPUSamplerState state, int unit, bool set_number);
 void GPU_texture_unbind(GPUTexture *tex);
diff --git a/source/blender/gpu/intern/gpu_texture.cc b/source/blender/gpu/intern/gpu_texture.cc
index 1b8b28bf04c..a20aa5bf6bb 100644
--- a/source/blender/gpu/intern/gpu_texture.cc
+++ b/source/blender/gpu/intern/gpu_texture.cc
@@ -523,6 +523,16 @@ void GPU_texture_ref(GPUTexture *tex)
   reinterpret_cast<Texture *>(tex)->refcount++;
 }
 
+void GPU_texture_set_reference_count(GPUTexture *texture, int count)
+{
+  reinterpret_cast<Texture *>(texture)->refcount = count;
+}
+
+int GPU_texture_get_reference_count(GPUTexture *texture)
+{
+  return reinterpret_cast<Texture *>(texture)->refcount;
+}
+
 int GPU_texture_width(const GPUTexture *tex)
 {
   return reinterpret_cast<const Texture *>(tex)->width_get();
diff --git a/source/blender/nodes/NOD_compositor_execute.hh b/source/blender/nodes/NOD_compositor_execute.hh
index 95c95d020c3..ff93b5954f4 100644
--- a/source/blender/nodes/NOD_compositor_execute.hh
+++ b/source/blender/nodes/NOD_compositor_execute.hh
@@ -16,12 +16,88 @@
 
 #pragma once
 
+#include "BLI_hash.hh"
+#include "BLI_map.hh"
+#include "BLI_vector.hh"
+
 #include "DNA_scene_types.h"
 
 #include "GPU_texture.h"
 
 namespace blender::compositor {
 
+/* --------------------------------------------------------------------
+ * Texture Pool.
+ */
+
+/* A key structure used to identify a texture specification in a texture pool. Defines a hash and
+ * an equality operator for use in a hash map. */
+class TexturePoolKey {
+ public:
+  int width;
+  int height;
+  eGPUTextureFormat format;
+
+  TexturePoolKey(int width, int height, eGPUTextureFormat format);
+  TexturePoolKey(const GPUTexture *texture);
+
+  uint64_t hash() const;
+};
+
+inline TexturePoolKey::TexturePoolKey(int width, int height, eGPUTextureFormat format)
+    : width(width), height(height), format(format)
+{
+}
+
+inline TexturePoolKey::TexturePoolKey(const GPUTexture *texture)
+{
+  width = GPU_texture_width(texture);
+  height = GPU_texture_height(texture);
+  format = GPU_texture_format(texture);
+}
+
+inline uint64_t TexturePoolKey::hash() const
+{
+  return get_default_hash_3(width, height, format);
+}
+
+inline bool operator==(const TexturePoolKey &a, const TexturePoolKey &b)
+{
+  return a.width == b.width && a.height == b.height && a.format == b.format;
+}
+
+/* A pool of textures that can be allocated and reused transparently throughout the evaluation of
+ * the node tree. The textures can be reference counted and will only be effectively released back
+ * into the pool when their reference count reaches one. Concrete derived classes are expected to
+ * free the textures once the pool is no longer in use. */
+class TexturePool {
+ private:
+  /* The set of textures in the pool that are available to acquire for each distinct texture
+   * specification. */
+  Map<TexturePoolKey, Vector<GPUTexture *>> textures_;
+
+ public:
+  /* Check if there is an available texture with the given specification in the pool, if such
+   * texture exists, return it, otherwise, return a newly allocated texture. The texture can be
+   * reference counted by providing the number of users that will be using this texture. The
+   * reference count will then be users_count + 1, because the texture pool is itself considered a
+   * user. Expect the texture to be uncleared and contains garbage data. */
+  GPUTexture *acquire(int width, int height, eGPUTextureFormat format, int users_count = 1);
+
+  /* Put the texture back into the pool, potentially to be acquired later by another user. The
+   * texture is only effectively release when its reference count reaches one. Notice that the
+   * texture is release when the texture reference count reaches one not zero, because the texture
+   * pool is itself considered a user of the texture. Expects the texture to be one that was
+   * acquired using the same texture pool. */
+  void release(GPUTexture *texture);
+
+ private:
+  /* Returns a newly allocated texture with the given specification. This method should be
+   * implemented by the compositor engine and should ideally use the DRW texture pool for
+   * allocation. */
+  virtual GPUTexture *allocate_texture(int width, int height, eGPUTextureFormat format) = 0;
+};
+
 /* This abstract class is used by node operations to access data intrinsic to the compositor
  * engine. The compositor engine should implement the class to provide the necessary
  * functionalities for node operations. */
diff --git a/source/blender/nodes/intern/node_compositor_execute.cc b/source/blender/nodes/intern/node_compositor_execute.cc
index e2a528423fa..854bdfc180e 100644
--- a/source/blender/nodes/intern/node_compositor_execute.cc
+++ b/source/blender/nodes/intern/node_compositor_execute.cc
@@ -14,7 +14,6 @@
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
 
-#include "BLI_hash.hh"
 #include "BLI_map.hh"
 #include "BLI_set.hh"
 #include "BLI_string_ref.hh"
@@ -36,73 +35,34 @@ namespace blender::compositor {
 
 using namespace nodes::derived_node_tree_types;
 
-/* A key structure used to identify a texture in a texture pool. Defines a hash and an equality
- * operator for use in a hash map. */
-class TexturePoolKey {
- public:
-  int width;
-  int height;
-  eGPUTextureFormat format;
-
-  TexturePoolKey(int width, int height, eGPUTextureFormat format)
-      : width(width), height(height), format(format)
-  {
-  }
-
-  TexturePoolKey(const GPUTexture *texture)
-  {
-    width = GPU_texture_width(texture);
-    height = GPU_texture_height(texture);
-    format = GPU_texture_format(texture);
-  }
-
-  uint64_t hash() const
-  {
-    return get_default_hash_3(width, height, format);
-  }
-};
+/* --------------------------------------------------------------------
+ * Texture Pool.
+ */
 
-inline bool operator==(const TexturePoolKey &a, const TexturePoolKey &b)
+GPUTexture *TexturePool::acquire(int width, int height, eGPUTextureFormat format, int users_count)
 {
-  return a.width == b.width && a.height == b.height && a.format == b.format;
+  const TexturePoolKey key = TexturePoolKey(width, height, format);
+  Vector<GPUTexture *> &available_textures = textures_.lookup_or_add_default(key);
+  GPUTexture *texture = available_textures.is_empty() ? allocate_texture(width, height, format) :
+                                                        available_textures.pop_last();
+  /* Add 1 to the users count because the texture pool itself is considered a user. */
+  GPU_texture_set_reference_count(texture, users_count + 1);
+  return texture;
 }
 
-/* A pool of textures that can be allocated and reused transparently throughout the evaluation of
- * the node tree. The compositor engine should implement the allocate_texture method, which would
- * ideally use a global DRW texture pool for allocations. The acquired textures are uncleared and
- * are expected to contain garbage data. */
-class TexturePool {
- private:
-  /* The set of textures in the pool that are currently in use. */
-  Set<GPUTexture *> in_use_textures_;
-  /* The set of textures in the pool that are available to acquire. */
-  Map<TexturePoolKey, GPUTexture *> available_textures_;
-
- public:
-  /* Check if there is an available texture with the given specification in the pool, if such
-   * texture exists, return it, otherwise, get a new texture from the DRW texture pool. */
-  GPUTexture *acquire(int width, int height, eGPUTextureFormat format)
-  {
-    const TexturePoolKey key = TexturePoolKey(width, height, format);
-    std::optional<GPUTexture *> available_texture = available_textures_.pop_try(key);
-    if (available_texture) {
-      return *available_texture;
-    }
-    GPUTexture *new_texture = allocate_texture(width, height, format);
-    in_use_textures_.add_new(new_texture);
-    return new_texture;
-  }
-
-  /* Move the texture from the in-use textures set to the available textures set, potentially to be
-   * acquired later by another user. */
-  void release(GPUTexture *texture)
-  {
-    in_use_textures_.remove_contained(texture);
-    available_textures_.add_new(TexturePoolKey(texture), texture);
+void TexturePool::release(GPUTexture *texture)
+{
+  /* Don't release if the texture still has more than 1 user. We check if the reference count is
+   * more than 1, not zero, because the texture pool itself is considered a user of the texture. */
+  if (GPU_texture_get_reference_count(texture) > 1) {
+    return;
   }
+  textures_.lookup(TexturePoolKey(texture)).append(texture);
+}
 
-  virtual GPUTexture *allocate_texture(int with, int height, eGPUTextureFormat format) = 0;
-};
+/* --------------------------------------------------------------------
+ * Compiler.
+ */
 
 class Compiler {
  public:



More information about the Bf-blender-cvs mailing list