Commit: 7e22582377203538d24ff693359aed2f6359bfe4 Author: Omar Emara Date: Mon Feb 14 10:11:12 2022 +0200 Branches: temp-viewport-compositor-compiler https://developer.blender.org/rB7e22582377203538d24ff693359aed2f6359bfe4
Viewport Compositor: Move components to bf_nodes We want to avoid directly linking bf_nodes to bf_draw, so we should start reorganizing implementation files. All components are moved to bf_nodes, this is also where interfaces are defined to be implemented in the compositor engine. =================================================================== M source/blender/draw/engines/compositor/compositor_engine.cc M source/blender/nodes/CMakeLists.txt M source/blender/nodes/NOD_compositor_execute.hh A 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 340f9310f08..4d25f72b1d6 100644 --- a/source/blender/draw/engines/compositor/compositor_engine.cc +++ b/source/blender/draw/engines/compositor/compositor_engine.cc @@ -22,315 +22,30 @@ * Engine processing the render buffer using GLSL to apply the scene compositing node tree. */ -#include "DRW_render.h" - -#include "BLI_hash.hh" -#include "BLI_map.hh" -#include "BLI_set.hh" -#include "BLI_string_ref.hh" -#include "BLI_utildefines.h" -#include "BLI_vector.hh" -#include "BLI_vector_set.hh" - -#include "DNA_node_types.h" #include "DNA_scene_types.h" -#include "GPU_texture.h" +#include "DRW_render.h" #include "IMB_colormanagement.h" #include "NOD_compositor_execute.hh" -#include "NOD_derived_node_tree.hh" + +#include "GPU_texture.h" #include "compositor_shader.hh" namespace blender::compositor { -using nodes::CompositorContext; -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); - } -}; - -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 reused transparently throughout the evaluation of the node tree. - * Uses the DRW texture pool as a base for allocation. 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; - } - DrawEngineType *owner = (DrawEngineType *)this; - GPUTexture *new_texture = DRW_texture_pool_query_2d(width, height, format, owner); - 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); - } -}; - class DRWCompositorContext : public CompositorContext { - private: - /* The node currently being executed. */ - DNode node_; - /* A map associating output sockets with the textures storing their contents. The map only stores - * the textures that were already computed by a dependency node and are still needed by one or - * more dependent nodes, so the node currently executing can get its inputs and outputs from this - * member. See get_input_texture and get_output_texture. */ - const Map<DSocket, GPUTexture *> &allocated_textures_; - - public: - DRWCompositorContext(DNode node, const Map<DSocket, GPUTexture *> &allocated_textures) - : node_(node), allocated_textures_(allocated_textures) - { - } - - const GPUTexture *get_input_texture(StringRef identifier) override - { - /* Find the output socket connected to the input with the given input identifier and return its - * allocated texture. If the input is not linked, return nullptr. */ - GPUTexture *texture = nullptr; - node_.input_by_identifier(identifier).foreach_origin_socket([&](const DSocket origin) { - texture = allocated_textures_.lookup(origin); - }); - return texture; - } - - const GPUTexture *get_output_texture(StringRef identifier) override - { - return allocated_textures_.lookup(node_.output_by_identifier(identifier)); - } - - const GPUTexture *get_viewport_texture() override + GPUTexture *get_viewport_texture() override { return DRW_viewport_texture_list_get()->color; } - const GPUTexture *get_pass_texture(int view_layer, eScenePassType pass_type) override + GPUTexture *get_pass_texture(int view_layer, eScenePassType pass_type) override { return DRW_render_pass_find(DRW_context_state_get()->scene, view_layer, pass_type)->pass_tx; } - - const bNode &node() override - { - return *node_->bnode(); - } -}; - -class Compiler { - public: - private: - /* The derived and reference node trees repressing the compositor setup. */ - NodeTreeRefMap tree_ref_map_; - DerivedNodeTree tree_; - /* The output node whose result should be computed and drawn. */ - DNode output_node_; - /* Stores a heuristic estimation of the number of needed intermediate buffers - * to compute every node and all of its dependencies. */ - Map<DNode, int> needed_buffers_; - /* An ordered set of nodes defining the schedule of node execution. */ - VectorSet<DNode> node_schedule_; - - public: - Compiler(bNodeTree *scene_node_tree) : tree_(*scene_node_tree, tree_ref_map_){}; - - void compile() - { - compute_output_node(); - compute_needed_buffers(output_node_); - compute_schedule(output_node_); - } - - void dump_schedule() - { - for (const DNode &node : node_schedule_) { - std::cout << node->name() << std::endl; - } - } - - private: - /* Computes the output node whose result should be computed and drawn. The output node is the - * node marked as NODE_DO_OUTPUT. If multiple types of output nodes are marked, then the - * preference will be CMP_NODE_COMPOSITE > CMP_NODE_VIEWER > CMP_NODE_SPLITVIEWER. */ - void compute_output_node() - { - const NodeTreeRef &root_tree = tree_.root_context().tree(); - for (const NodeRef *node : root_tree.nodes_by_type("CompositorNodeComposite")) { - if (node->bnode()->flag & NODE_DO_OUTPUT) { - output_node_ = DNode(&tree_.root_context(), node); - return; - } - } - for (const NodeRef *node : root_tree.nodes_by_type("CompositorNodeViewer")) { - if (node->bnode()->flag & NODE_DO_OUTPUT) { - output_node_ = DNode(&tree_.root_context(), node); - return; - } - } - for (const NodeRef *node : root_tree.nodes_by_type("CompositorNodeSplitViewer")) { - if (node->bnode()->flag & NODE_DO_OUTPUT) { - output_node_ = DNode(&tree_.root_context(), node); - return; - } - } - } - - /* Computes a heuristic estimation of the number of needed intermediate buffers to compute this - * node and all of its dependencies. The method recursively computes the needed buffers for all - * node dependencies and stores them in the needed_buffers_ map. So the root/output node can be - * provided to compute the needed buffers for all nodes. - * - * Consider a node that takes n number of buffers as an input from a number of node dependencies, - * which we shall call the input nodes. The node also computes and outputs m number of buffers. - * In order for the node to compute its output, a number of intermediate buffers will be needed. - * Since the node takes n buffers and outputs m buffers, then the number of buffers directly - * needed by the node is (n + m). But each of the input buffers are computed by a node that, in - * turn, needs a number of buffers to compute its output. So the total number of buffers needed - * to compute the output of the node is max(n + m, d) where d is the number of buffers needed by - * the input node that needs the largest number of buffers. We only consider the input node that - * needs the largest number of buffers, because those buffers can be reused by any input node - * that needs a lesser number of buffers. - * - * If the node tree was, in fact, a tree, then this would be an accurate computation. However, - * the node tree is in fact a graph that allows output sharing, so the computation in this case - * is merely a heuristic estimation that works well in most cases. */ - int compute_needed_buffers(DNode node) - { - /* Compute the number of buffers that the node takes as an input as well as the number of - * buffers needed to compute the most demanding dependency node. */ - int input_buffers = 0; - int buffers_needed_by_dependencies = 0; - for (const InputSocketRef *input_ref : node->inputs()) { - const DInputSocket input{node.context(), input_ref}; - /* Only consider inputs that are linked, that is, those that take a buffer. */ - input.foreach_origin_socket([&](const DSocket origin) { - input_buffers++; - /* The origin node was already computed before, so skip it. */ - if (needed_buffers_.contains(origin.node())) { - return; - } - /* Recursively compute the number of buffers needed to compute this dependency node. */ - const int buffers_needed_by_origin = compute_needed_buffers(origin.node()); - if (buffers_needed_by_origin > buffers_needed_by_dependencies) { - buffers_needed_by_dependencies = buffers_needed_by_origin; - } - }); - } - - /* Compute the number of buffers that will be computed/output by this node. */ - int output_buffers = 0; - for (const OutputSocketRef *output : node->outputs()) { - if (output->logically_linked_sockets().size() != 0) { - output_buffers++; - } - @@ Diff output truncated at 10240 characters. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org List details, subscription details or unsubscribe: https://lists.blender.org/mailman/listinfo/bf-blender-cvs