Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOmar Emara <mail@OmarEmara.dev>2022-04-15 14:07:20 +0300
committerOmar Emara <mail@OmarEmara.dev>2022-04-15 14:07:20 +0300
commit5d78f0e12f181a282d20febfaed71453097fd22c (patch)
treee08c4636490303e58a4292dc4d011ad6048d0756
parent74e9cad08276ba01a2360846d7cf26cfa03e7ece (diff)
Viewport Compositor: Complete eager evaluation and draw enginetemp-viewport-compositor-compiler
-rw-r--r--source/blender/draw/engines/compositor/compositor_engine.cc148
-rw-r--r--source/blender/draw/engines/compositor/compositor_engine.h23
-rw-r--r--source/blender/draw/intern/draw_manager.c28
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_composite.cc5
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_split_viewer.cc3
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_viewer.cc5
-rw-r--r--source/blender/viewport_compositor/VPC_context.hh5
-rw-r--r--source/blender/viewport_compositor/VPC_texture_pool.hh26
-rw-r--r--source/blender/viewport_compositor/intern/evaluator.cc7
-rw-r--r--source/blender/viewport_compositor/intern/operation.cc1
-rw-r--r--source/blender/viewport_compositor/intern/texture_pool.cc7
11 files changed, 166 insertions, 92 deletions
diff --git a/source/blender/draw/engines/compositor/compositor_engine.cc b/source/blender/draw/engines/compositor/compositor_engine.cc
index 13fc8dc0f64..c9f2a3dcac1 100644
--- a/source/blender/draw/engines/compositor/compositor_engine.cc
+++ b/source/blender/draw/engines/compositor/compositor_engine.cc
@@ -5,6 +5,7 @@
#include "BLT_translation.h"
+#include "DNA_ID_enums.h"
#include "DNA_scene_types.h"
#include "DEG_depsgraph_query.h"
@@ -30,18 +31,18 @@ class DRWTexturePool : public TexturePool {
}
};
-static const Scene *get_context_scene()
-{
- return DRW_context_state_get()->scene;
-}
-
class DRWContext : public Context {
public:
using Context::Context;
const Scene *get_scene() override
{
- return get_context_scene();
+ return DRW_context_state_get()->scene;
+ }
+
+ int2 get_viewport_size() override
+ {
+ return int2(float2(DRW_viewport_size_get()));
}
GPUTexture *get_viewport_texture() override
@@ -56,59 +57,116 @@ class DRWContext : public Context {
}
};
-/* It is sufficient to check for the scene node tree because the engine will not be enabled when
- * the viewport shading option is disabled. */
-static bool is_compositor_enabled()
-{
- const Scene *scene = get_context_scene();
- if (scene->use_nodes && scene->nodetree) {
- return true;
+class Engine {
+ private:
+ DRWTexturePool texture_pool_;
+ DRWContext context_;
+ Evaluator evaluator_;
+ /* Stores the viewport size at the time the last compositor evaluation happened. See the
+ * update_viewport_size method for more information. */
+ int2 viewport_size_;
+
+ public:
+ Engine() : context_(texture_pool_), evaluator_(context_, node_tree())
+ {
}
- return false;
-}
-static void draw()
-{
- if (!is_compositor_enabled()) {
- return;
+ /* Update the viewport size and evaluate the compositor. */
+ void draw()
+ {
+ update_viewport_size();
+ evaluator_.evaluate();
}
- /* Reset default view. */
- DRW_view_set_active(nullptr);
+ /* If the size of the viewport changed from the last time the compositor was evaluated, update
+ * the viewport size and reset the evaluator. That's because the evaluator compiles the node tree
+ * in a manner that is specifically optimized for the size of the viewport. This should be called
+ * before evaluating the compositor. */
+ void update_viewport_size()
+ {
+ if (viewport_size_ == context_.get_viewport_size()) {
+ return;
+ }
- DRWTexturePool texture_pool;
- DRWContext context(texture_pool);
- const Scene *scene = get_context_scene();
- Evaluator evaluator(context, *scene->nodetree);
- evaluator.evaluate();
-}
+ viewport_size_ = context_.get_viewport_size();
+
+ evaluator_.reset();
+ }
+
+ /* If the compositor node tree changed, reset the evaluator. */
+ void update(const Depsgraph *depsgraph)
+ {
+ if (DEG_id_type_updated(depsgraph, ID_NT)) {
+ evaluator_.reset();
+ }
+ }
+
+ /* Get a reference to the compositor node tree. */
+ static bNodeTree &node_tree()
+ {
+ return *DRW_context_state_get()->scene->nodetree;
+ }
+};
} // namespace blender::viewport_compositor
-static void compositor_draw(void *UNUSED(data))
+using namespace blender::viewport_compositor;
+
+typedef struct CompositorData {
+ DrawEngineType *engine_type;
+ DRWViewportEmptyList *fbl;
+ DRWViewportEmptyList *txl;
+ DRWViewportEmptyList *psl;
+ DRWViewportEmptyList *stl;
+ Engine *instance_data;
+} CompositorData;
+
+static void compositor_engine_init(void *data)
+{
+ CompositorData *compositor_data = static_cast<CompositorData *>(data);
+
+ if (!compositor_data->instance_data) {
+ compositor_data->instance_data = new Engine();
+ }
+}
+
+static void compositor_engine_free(void *instance_data)
+{
+ Engine *engine = static_cast<Engine *>(instance_data);
+ delete engine;
+}
+
+static void compositor_engine_draw(void *data)
+{
+ const CompositorData *compositor_data = static_cast<CompositorData *>(data);
+ compositor_data->instance_data->draw();
+}
+
+static void compositor_engine_update(void *data)
{
- blender::viewport_compositor::draw();
+ const CompositorData *compositor_data = static_cast<CompositorData *>(data);
+ compositor_data->instance_data->update(DRW_context_state_get()->depsgraph);
}
extern "C" {
-static const DrawEngineDataSize compositor_data_size = {};
+static const DrawEngineDataSize compositor_data_size = DRW_VIEWPORT_DATA_SIZE(CompositorData);
DrawEngineType draw_engine_compositor_type = {
- nullptr,
- nullptr,
- N_("Compositor"),
- &compositor_data_size,
- nullptr,
- nullptr,
- nullptr,
- nullptr,
- nullptr,
- nullptr,
- &compositor_draw,
- nullptr,
- nullptr,
- nullptr,
- nullptr,
+ nullptr, /* next */
+ nullptr, /* prev */
+ N_("Compositor"), /* idname */
+ &compositor_data_size, /* vedata_size */
+ &compositor_engine_init, /* engine_init */
+ nullptr, /* engine_free */
+ &compositor_engine_free, /* instance_free */
+ nullptr, /* cache_init */
+ nullptr, /* cache_populate */
+ nullptr, /* cache_finish */
+ &compositor_engine_draw, /* draw_scene */
+ &compositor_engine_update, /* view_update */
+ nullptr, /* id_update */
+ nullptr, /* render_to_image */
+ nullptr, /* store_metadata */
};
}
diff --git a/source/blender/draw/engines/compositor/compositor_engine.h b/source/blender/draw/engines/compositor/compositor_engine.h
index 4c76ad27bab..3d58d78105f 100644
--- a/source/blender/draw/engines/compositor/compositor_engine.h
+++ b/source/blender/draw/engines/compositor/compositor_engine.h
@@ -1,24 +1,5 @@
-/*
- * 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.
- *
- * Copyright 2021, Blender Foundation.
- */
-
-/** \file
- * \ingroup draw_engine
- */
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2022 Blender Foundation. All rights reserved. */
#pragma once
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index 4a372e264d8..6fbbf829b2b 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -1434,6 +1434,27 @@ static void drw_engines_enable_editors(void)
}
}
+static bool is_compositor_enabled()
+{
+ if (!(DST.draw_ctx.v3d->shading.flag & V3D_SHADING_COMPOSITOR)) {
+ return false;
+ }
+
+ if (!(DST.draw_ctx.v3d->shading.type > OB_MATERIAL)) {
+ return false;
+ }
+
+ if (!DST.draw_ctx.scene->use_nodes) {
+ return false;
+ }
+
+ if (!DST.draw_ctx.scene->nodetree) {
+ return false;
+ }
+
+ return true;
+}
+
/* Beware: This can go recursive if not handled properly. */
static void drw_compositor_scenes_render(DRWManager *drw,
Scene *scene_active,
@@ -1456,10 +1477,7 @@ static void drw_compositor_scenes_render(DRWManager *drw,
int view = GPU_viewport_active_view_get(viewport);
int prev_flag2 = v3d->flag2;
- const eDrawType drawtype = drw->draw_ctx.v3d->shading.type;
- const bool use_compositor = ((drw->draw_ctx.v3d->shading.flag & V3D_SHADING_COMPOSITOR) != 0) &&
- (drawtype > OB_MATERIAL) && (scene_active->nodetree != NULL) &&
- (scene_active->use_nodes != false);
+ const bool use_compositor = is_compositor_enabled();
if (!use_compositor) {
/* Still setup the current active view. This way we get correct update without compositor. */
@@ -1581,7 +1599,7 @@ static void drw_engines_enable(ViewLayer *UNUSED(view_layer),
}
if (!DST.options.is_compositor_scene_render) {
- if (((v3d->shading.flag & V3D_SHADING_COMPOSITOR) != 0) && (drawtype > OB_MATERIAL)) {
+ if (is_compositor_enabled()) {
use_drw_engine(&draw_engine_compositor_type);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_composite.cc b/source/blender/nodes/composite/nodes/node_composite_composite.cc
index 74c031d6366..9560c994a6e 100644
--- a/source/blender/nodes/composite/nodes/node_composite_composite.cc
+++ b/source/blender/nodes/composite/nodes/node_composite_composite.cc
@@ -61,7 +61,7 @@ class CompositeOperation : public NodeOperation {
GPUTexture *viewport_texture = context().get_viewport_texture();
/* If the input image is a texture, copy the input texture to the viewport texture. */
- if (get_input("Image").is_texture()) {
+ if (input_image.is_texture()) {
/* Make sure any prior writes to the texture are reflected before copying it. */
GPU_memory_barrier(GPU_BARRIER_TEXTURE_UPDATE);
@@ -77,8 +77,7 @@ class CompositeOperation : public NodeOperation {
/* The operation domain have the same dimensions of the viewport without any transformations. */
Domain compute_domain() override
{
- GPUTexture *viewport_texture = context().get_viewport_texture();
- return Domain(int2(GPU_texture_width(viewport_texture), GPU_texture_height(viewport_texture)));
+ return Domain(context().get_viewport_size());
}
};
diff --git a/source/blender/nodes/composite/nodes/node_composite_split_viewer.cc b/source/blender/nodes/composite/nodes/node_composite_split_viewer.cc
index 2f041a5c70f..055a65888ea 100644
--- a/source/blender/nodes/composite/nodes/node_composite_split_viewer.cc
+++ b/source/blender/nodes/composite/nodes/node_composite_split_viewer.cc
@@ -102,8 +102,7 @@ class ViewerOperation : public NodeOperation {
/* The operation domain have the same dimensions of the viewport without any transformations. */
Domain compute_domain() override
{
- GPUTexture *viewport_texture = context().get_viewport_texture();
- return Domain(int2(GPU_texture_width(viewport_texture), GPU_texture_height(viewport_texture)));
+ return Domain(context().get_viewport_size());
}
GPUShader *get_split_viewer_shader()
diff --git a/source/blender/nodes/composite/nodes/node_composite_viewer.cc b/source/blender/nodes/composite/nodes/node_composite_viewer.cc
index 86adc411689..0a79c9c6c10 100644
--- a/source/blender/nodes/composite/nodes/node_composite_viewer.cc
+++ b/source/blender/nodes/composite/nodes/node_composite_viewer.cc
@@ -88,7 +88,7 @@ class ViewerOperation : public NodeOperation {
GPUTexture *viewport_texture = context().get_viewport_texture();
/* If the input image is a texture, copy the input texture to the viewport texture. */
- if (get_input("Image").is_texture()) {
+ if (input_image.is_texture()) {
/* Make sure any prior writes to the texture are reflected before copying it. */
GPU_memory_barrier(GPU_BARRIER_TEXTURE_UPDATE);
@@ -104,8 +104,7 @@ class ViewerOperation : public NodeOperation {
/* The operation domain have the same dimensions of the viewport without any transformations. */
Domain compute_domain() override
{
- GPUTexture *viewport_texture = context().get_viewport_texture();
- return Domain(int2(GPU_texture_width(viewport_texture), GPU_texture_height(viewport_texture)));
+ return Domain(context().get_viewport_size());
}
};
diff --git a/source/blender/viewport_compositor/VPC_context.hh b/source/blender/viewport_compositor/VPC_context.hh
index 6d80510e48c..a6494936f4f 100644
--- a/source/blender/viewport_compositor/VPC_context.hh
+++ b/source/blender/viewport_compositor/VPC_context.hh
@@ -3,6 +3,8 @@
#pragma once
+#include "BLI_math_vec_types.hh"
+
#include "DNA_scene_types.h"
#include "GPU_texture.h"
@@ -25,6 +27,9 @@ class Context {
/* Get the active compositing scene. */
virtual const Scene *get_scene() = 0;
+ /* Get the dimensions of the viewport. */
+ virtual int2 get_viewport_size() = 0;
+
/* Get the texture representing the viewport where the result of the compositor should be
* written. This should be called by output nodes to get their target texture. */
virtual GPUTexture *get_viewport_texture() = 0;
diff --git a/source/blender/viewport_compositor/VPC_texture_pool.hh b/source/blender/viewport_compositor/VPC_texture_pool.hh
index bd762b3fa9c..cc5419c57aa 100644
--- a/source/blender/viewport_compositor/VPC_texture_pool.hh
+++ b/source/blender/viewport_compositor/VPC_texture_pool.hh
@@ -17,14 +17,17 @@ namespace blender::viewport_compositor {
* Texture Pool Key.
*/
-/* 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. */
+/* A key 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:
int2 size;
eGPUTextureFormat format;
+ /* Construct a key from the given texture size and format. */
TexturePoolKey(int2 size, eGPUTextureFormat format);
+
+ /* Construct a key from the size and format of the given texture. */
TexturePoolKey(const GPUTexture *texture);
uint64_t hash() const;
@@ -34,12 +37,12 @@ class TexturePoolKey {
* Texture Pool.
*/
-/* A pool of textures that can be used to allocate textures and reused transparently throughout the
- * evaluation of the compositor. This texture pool only pools textures throughout a single
- * evaluation of the compositor and will reset after the evaluation without freeing any textures.
- * Cross-evaluation pooling and freeing of unused textures is the responsibility of the back-end
- * texture pool used by the allocate_texture method. In the case of the viewport compositor engine,
- * this would be the global DRWTexturePool of the draw manager. */
+/* A pool of textures that can be used to allocate textures that can be reused transparently
+ * throughout the evaluation of the compositor. This texture pool only pools textures throughout a
+ * single evaluation of the compositor and will reset after the evaluation without freeing any
+ * textures. Cross-evaluation pooling and freeing of unused textures is the responsibility of the
+ * back-end texture pool used by the allocate_texture method. In the case of the viewport
+ * compositor engine, this would be the global DRWTexturePool of the draw manager. */
class TexturePool {
private:
/* The set of textures in the pool that are available to acquire for each distinct texture
@@ -56,7 +59,7 @@ class TexturePool {
GPUTexture *acquire_color(int2 size);
/* Shorthand for acquire with GPU_RGBA16F format. Identical to acquire_color because vector
- * textures are and should internally be stored in RGBA textures. */
+ * are stored in RGBA textures because RGB texture have limited support. */
GPUTexture *acquire_vector(int2 size);
/* Shorthand for acquire with GPU_R16F format. */
@@ -66,6 +69,11 @@ class TexturePool {
* the texture to be one that was acquired using the same texture pool. */
void release(GPUTexture *texture);
+ /* Reset the texture pool by clearing all available textures. The textures are not freed. If they
+ * are not needed, they should be freed by the back-end texture pool used by the allocate_texture
+ * method. This should be called after the compositor is done evaluating. */
+ void reset();
+
private:
/* Returns a newly allocated texture with the given specification. This method should be
* implemented by the compositor engine and should use a global texture pool that is persistent
diff --git a/source/blender/viewport_compositor/intern/evaluator.cc b/source/blender/viewport_compositor/intern/evaluator.cc
index 14d3edc3b18..bc60a660f04 100644
--- a/source/blender/viewport_compositor/intern/evaluator.cc
+++ b/source/blender/viewport_compositor/intern/evaluator.cc
@@ -27,9 +27,13 @@ Evaluator::Evaluator(Context &context, bNodeTree &node_tree)
void Evaluator::evaluate()
{
+ /* Reset the texture pool that was potentially populated from a previous evaluation. */
+ context_.texture_pool().reset();
+
/* The node tree is not compiled yet, so compile and evaluate the node tree. */
if (!is_compiled_) {
compile_and_evaluate();
+ is_compiled_ = true;
return;
}
@@ -80,9 +84,6 @@ void Evaluator::compile_and_evaluate()
compile_and_evaluate_node(node, compile_state);
}
}
-
- /* Mark the node tree as compiled. */
- is_compiled_ = true;
}
void Evaluator::compile_and_evaluate_node(DNode node, CompileState &compile_state)
diff --git a/source/blender/viewport_compositor/intern/operation.cc b/source/blender/viewport_compositor/intern/operation.cc
index bd757af781b..7558fc9c51f 100644
--- a/source/blender/viewport_compositor/intern/operation.cc
+++ b/source/blender/viewport_compositor/intern/operation.cc
@@ -169,6 +169,7 @@ void Operation::evaluate_input_processors()
/* The input processors are not added yet, so add and evaluate the input processors. */
if (!input_processors_added_) {
add_and_evaluate_input_processors();
+ input_processors_added_ = true;
return;
}
diff --git a/source/blender/viewport_compositor/intern/texture_pool.cc b/source/blender/viewport_compositor/intern/texture_pool.cc
index 2c08bf90335..7fcc5a4d010 100644
--- a/source/blender/viewport_compositor/intern/texture_pool.cc
+++ b/source/blender/viewport_compositor/intern/texture_pool.cc
@@ -61,9 +61,9 @@ GPUTexture *TexturePool::acquire_color(int2 size)
return acquire(size, GPU_RGBA16F);
}
-/* Vectors are and should be stored in RGBA textures. */
GPUTexture *TexturePool::acquire_vector(int2 size)
{
+ /* Vectors are stored in RGBA textures because RGB textures have limited support. */
return acquire(size, GPU_RGBA16F);
}
@@ -77,4 +77,9 @@ void TexturePool::release(GPUTexture *texture)
textures_.lookup(TexturePoolKey(texture)).append(texture);
}
+void TexturePool::reset()
+{
+ textures_.clear();
+}
+
} // namespace blender::viewport_compositor