[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