diff options
Diffstat (limited to 'source/blender/compositor/realtime_compositor')
21 files changed, 258 insertions, 181 deletions
diff --git a/source/blender/compositor/realtime_compositor/CMakeLists.txt b/source/blender/compositor/realtime_compositor/CMakeLists.txt index 9fe156c3ef2..1f1333332f5 100644 --- a/source/blender/compositor/realtime_compositor/CMakeLists.txt +++ b/source/blender/compositor/realtime_compositor/CMakeLists.txt @@ -2,13 +2,13 @@ set(INC . + ../../blenkernel + ../../blenlib ../../gpu - ../../nodes ../../imbuf - ../../blenlib ../../makesdna ../../makesrna - ../../blenkernel + ../../nodes ../../gpu/intern ../../../../intern/guardedalloc ) diff --git a/source/blender/compositor/realtime_compositor/COM_compile_state.hh b/source/blender/compositor/realtime_compositor/COM_compile_state.hh index ed6ad414e3b..924919bbef6 100644 --- a/source/blender/compositor/realtime_compositor/COM_compile_state.hh +++ b/source/blender/compositor/realtime_compositor/COM_compile_state.hh @@ -143,7 +143,7 @@ class CompileState { * the give node. */ void add_node_to_shader_compile_unit(DNode node); - /* Get a reference to the shader compile unit. */ + /* Get a reference to the shader compile unit. */ ShaderCompileUnit &get_shader_compile_unit(); /* Clear the compile unit. This should be called once the compile unit is compiled to ready it to diff --git a/source/blender/compositor/realtime_compositor/COM_conversion_operation.hh b/source/blender/compositor/realtime_compositor/COM_conversion_operation.hh index 15e1d0722ea..310333aea5a 100644 --- a/source/blender/compositor/realtime_compositor/COM_conversion_operation.hh +++ b/source/blender/compositor/realtime_compositor/COM_conversion_operation.hh @@ -11,11 +11,13 @@ namespace blender::realtime_compositor { -/* ------------------------------------------------------------------------------------------------- - * Conversion Operation +/* -------------------------------------------------------------------- */ +/** \name Conversion Operation * * A simple operation that converts a result from a certain type to another. See the derived - * classes for more details. */ + * classes for more details. + * \{ */ + class ConversionOperation : public SimpleOperation { public: using SimpleOperation::SimpleOperation; @@ -37,13 +39,18 @@ class ConversionOperation : public SimpleOperation { /* Get the shader the will be used for conversion. */ virtual GPUShader *get_conversion_shader() const = 0; -}; -/* ------------------------------------------------------------------------------------------------- - * Convert Float To Vector Operation + /** \} */ + +}; // namespace blender::realtime_compositorclassConversionOperation:publicSimpleOperation + +/* -------------------------------------------------------------------- */ +/** \name Convert Float to Vector Operation * * Takes a float result and outputs a vector result. All three components of the output are filled - * with the input float. */ + * with the input float. + * \{ */ + class ConvertFloatToVectorOperation : public ConversionOperation { public: ConvertFloatToVectorOperation(Context &context); @@ -53,11 +60,15 @@ class ConvertFloatToVectorOperation : public ConversionOperation { GPUShader *get_conversion_shader() const override; }; -/* ------------------------------------------------------------------------------------------------- - * Convert Float To Color Operation +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Convert Float to Color Operation * * Takes a float result and outputs a color result. All three color channels of the output are - * filled with the input float and the alpha channel is set to 1. */ + * filled with the input float and the alpha channel is set to 1. + * \{ */ + class ConvertFloatToColorOperation : public ConversionOperation { public: ConvertFloatToColorOperation(Context &context); @@ -67,11 +78,15 @@ class ConvertFloatToColorOperation : public ConversionOperation { GPUShader *get_conversion_shader() const override; }; -/* ------------------------------------------------------------------------------------------------- - * Convert Color To Float Operation +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Convert Color to Float Operation * * Takes a color result and outputs a float result. The output is the average of the three color - * channels, the alpha channel is ignored. */ + * channels, the alpha channel is ignored. + * \{ */ + class ConvertColorToFloatOperation : public ConversionOperation { public: ConvertColorToFloatOperation(Context &context); @@ -81,11 +96,15 @@ class ConvertColorToFloatOperation : public ConversionOperation { GPUShader *get_conversion_shader() const override; }; -/* ------------------------------------------------------------------------------------------------- - * Convert Color To Vector Operation +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Convert Color to Vector Operation * * Takes a color result and outputs a vector result. The output is a copy of the three color - * channels to the three vector components. */ + * channels to the three vector components. + * \{ */ + class ConvertColorToVectorOperation : public ConversionOperation { public: ConvertColorToVectorOperation(Context &context); @@ -95,11 +114,18 @@ class ConvertColorToVectorOperation : public ConversionOperation { GPUShader *get_conversion_shader() const override; }; -/* ------------------------------------------------------------------------------------------------- - * Convert Vector To Float Operation +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Convert Vector to Float Operation * * Takes a vector result and outputs a float result. The output is the average of the three - * components. */ + * components. + * \{ */ + +/* + * + * */ class ConvertVectorToFloatOperation : public ConversionOperation { public: ConvertVectorToFloatOperation(Context &context); @@ -109,11 +135,15 @@ class ConvertVectorToFloatOperation : public ConversionOperation { GPUShader *get_conversion_shader() const override; }; -/* ------------------------------------------------------------------------------------------------- - * Convert Vector To Color Operation +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Convert Vector to Color Operation * * Takes a vector result and outputs a color result. The output is a copy of the three vector - * components to the three color channels with the alpha channel set to 1. */ + * components to the three color channels with the alpha channel set to 1. + * \{ */ + class ConvertVectorToColorOperation : public ConversionOperation { public: ConvertVectorToColorOperation(Context &context); @@ -123,4 +153,6 @@ class ConvertVectorToColorOperation : public ConversionOperation { GPUShader *get_conversion_shader() const override; }; +/** \} */ + } // namespace blender::realtime_compositor diff --git a/source/blender/compositor/realtime_compositor/COM_domain.hh b/source/blender/compositor/realtime_compositor/COM_domain.hh index a4f9eb68db4..54d712f7578 100644 --- a/source/blender/compositor/realtime_compositor/COM_domain.hh +++ b/source/blender/compositor/realtime_compositor/COM_domain.hh @@ -149,7 +149,7 @@ class Domain { /* Transform the domain by the given transformation. This effectively pre-multiply the given * transformation by the current transformation of the domain. */ - void transform(const float3x3 &transformation); + void transform(const float3x3 &input_transformation); /* Returns a domain of size 1x1 and an identity transformation. */ static Domain identity(); diff --git a/source/blender/compositor/realtime_compositor/COM_evaluator.hh b/source/blender/compositor/realtime_compositor/COM_evaluator.hh index fd6feb0948b..258a2a038c4 100644 --- a/source/blender/compositor/realtime_compositor/COM_evaluator.hh +++ b/source/blender/compositor/realtime_compositor/COM_evaluator.hh @@ -104,9 +104,6 @@ class Evaluator { Context &context_; /* A reference to the compositor node tree. */ bNodeTree &node_tree_; - /* The derived and reference node trees representing the compositor node tree. Those are - * initialized when the node tree is compiled and freed when the evaluator resets. */ - NodeTreeRefMap node_tree_reference_map_; std::unique_ptr<DerivedNodeTree> derived_node_tree_; /* The compiled operations stream. This contains ordered pointers to the operations that were * compiled. This is initialized when the node tree is compiled and freed when the evaluator diff --git a/source/blender/compositor/realtime_compositor/COM_shader_node.hh b/source/blender/compositor/realtime_compositor/COM_shader_node.hh index 453226ec452..50337935d03 100644 --- a/source/blender/compositor/realtime_compositor/COM_shader_node.hh +++ b/source/blender/compositor/realtime_compositor/COM_shader_node.hh @@ -73,7 +73,7 @@ class ShaderNode { const DNode &node() const; /* Returns a reference to the node this operations represents. */ - bNode &bnode() const; + const bNode &bnode() const; private: /* Populate the inputs of the node. The input link is set to nullptr and is expected to be diff --git a/source/blender/compositor/realtime_compositor/COM_shader_operation.hh b/source/blender/compositor/realtime_compositor/COM_shader_operation.hh index a33dcbf25be..d03e52ac8f2 100644 --- a/source/blender/compositor/realtime_compositor/COM_shader_operation.hh +++ b/source/blender/compositor/realtime_compositor/COM_shader_operation.hh @@ -224,7 +224,7 @@ class ShaderOperation : public Operation { * * This method first generates the necessary code to load the inputs and store the outputs. Then, * it creates a compute shader from the generated sources. Finally, it adds the necessary GPU - * resources to the shader. */ + * resources to the shader. */ static void generate_code(void *thunk, GPUMaterial *material, GPUCodegenOutput *code_generator); /* Add an image in the shader for each of the declared outputs. Additionally, emit code to define diff --git a/source/blender/compositor/realtime_compositor/COM_simple_operation.hh b/source/blender/compositor/realtime_compositor/COM_simple_operation.hh index 1655e52ac9a..0061986ce42 100644 --- a/source/blender/compositor/realtime_compositor/COM_simple_operation.hh +++ b/source/blender/compositor/realtime_compositor/COM_simple_operation.hh @@ -15,7 +15,7 @@ namespace blender::realtime_compositor { * A simple operation is an operation that takes exactly one input and computes exactly one output. * Moreover, the output is guaranteed to only have a single user, that is, its reference count will * be one. Such operations can be attached to the inputs of operations to pre-process the inputs to - * prepare them before the operation is executed.*/ + * prepare them before the operation is executed. */ class SimpleOperation : public Operation { private: /* The identifier of the output. This is constant for all operations. */ diff --git a/source/blender/compositor/realtime_compositor/COM_utilities.hh b/source/blender/compositor/realtime_compositor/COM_utilities.hh index 4bd61aab5cb..efd1bc2b6b0 100644 --- a/source/blender/compositor/realtime_compositor/COM_utilities.hh +++ b/source/blender/compositor/realtime_compositor/COM_utilities.hh @@ -16,44 +16,54 @@ namespace blender::realtime_compositor { using namespace nodes::derived_node_tree_types; -/* Get the origin socket of the given node input. If the input is not linked, the socket itself is +/** + * Get the origin socket of the given node input. If the input is not linked, the socket itself is * returned. If the input is linked, the socket that is linked to it is returned, which could * either be an input or an output. An input socket is returned when the given input is connected - * to an unlinked input of a group input node. */ + * to an unlinked input of a group input node. + */ DSocket get_input_origin_socket(DInputSocket input); -/* Get the output socket linked to the given node input. If the input is not linked to an output, a - * null output is returned. */ +/** + * Get the output socket linked to the given node input. If the input is not linked to an output, + * a null output is returned. + */ DOutputSocket get_output_linked_to_input(DInputSocket input); -/* Get the result type that corresponds to the type of the given socket. */ -ResultType get_node_socket_result_type(const SocketRef *socket); +/** Get the result type that corresponds to the type of the given socket. */ +ResultType get_node_socket_result_type(const bNodeSocket *socket); -/* Returns true if any of the nodes linked to the given output satisfies the given condition, and - * false otherwise. */ +/** + * Returns true if any of the nodes linked to the given output satisfies the given condition, + * and false otherwise. + */ bool is_output_linked_to_node_conditioned(DOutputSocket output, FunctionRef<bool(DNode)> condition); -/* Returns the number of inputs linked to the given output that satisfy the given condition. */ +/** Returns the number of inputs linked to the given output that satisfy the given condition. */ int number_of_inputs_linked_to_output_conditioned(DOutputSocket output, FunctionRef<bool(DInputSocket)> condition); -/* A node is a shader node if it defines a method to get a shader node operation. */ +/** A node is a shader node if it defines a method to get a shader node operation. */ bool is_shader_node(DNode node); -/* Returns true if the given node is supported, that is, have an implementation. Returns false - * otherwise. */ +/** + * Returns true if the given node is supported, that is, have an implementation. + * Returns false otherwise. + */ bool is_node_supported(DNode node); -/* Get the input descriptor of the given input socket. */ -InputDescriptor input_descriptor_from_input_socket(const InputSocketRef *socket); +/** Get the input descriptor of the given input socket. */ +InputDescriptor input_descriptor_from_input_socket(const bNodeSocket *socket); -/* Dispatch the given compute shader in a 2D compute space such that the number of threads in both +/** + * Dispatch the given compute shader in a 2D compute space such that the number of threads in both * dimensions is as small as possible but at least covers the entirety of threads_range assuming * the shader has a local group size given by local_size. That means that the number of threads * might be a bit larger than threads_range, so shaders has to put that into consideration. A * default local size of 16x16 is assumed, which is the optimal local size for many image - * processing shaders. */ + * processing shaders. + */ void compute_dispatch_threads_at_least(GPUShader *shader, int2 threads_range, int2 local_size = int2(16)); diff --git a/source/blender/compositor/realtime_compositor/intern/compile_state.cc b/source/blender/compositor/realtime_compositor/intern/compile_state.cc index 5b485224111..5fa2fc9d544 100644 --- a/source/blender/compositor/realtime_compositor/intern/compile_state.cc +++ b/source/blender/compositor/realtime_compositor/intern/compile_state.cc @@ -46,7 +46,7 @@ Result &CompileState::get_result_from_output_socket(DOutputSocket output) * reference to the result from that operation using the output identifier. */ if (node_operations_.contains(output.node())) { NodeOperation *operation = node_operations_.lookup(output.node()); - return operation->get_result(output->identifier()); + return operation->get_result(output->identifier); } /* Otherwise, the output belongs to a node that was compiled into a shader operation, so @@ -113,17 +113,17 @@ Domain CompileState::compute_shader_node_domain(DNode node) /* Go over the inputs and find the domain of the non single value input with the highest domain * priority. */ - for (const InputSocketRef *input_ref : node->inputs()) { - const DInputSocket input{node.context(), input_ref}; + for (const bNodeSocket *input : node->input_sockets()) { + const DInputSocket dinput{node.context(), input}; /* Get the output linked to the input. If it is null, that means the input is unlinked, so skip * it. */ - const DOutputSocket output = get_output_linked_to_input(input); + const DOutputSocket output = get_output_linked_to_input(dinput); if (!output) { continue; } - const InputDescriptor input_descriptor = input_descriptor_from_input_socket(input_ref); + const InputDescriptor input_descriptor = input_descriptor_from_input_socket(input); /* If the output belongs to a node that is part of the shader compile unit, then the domain of * the input is the domain of the compile unit itself. */ @@ -149,6 +149,11 @@ Domain CompileState::compute_shader_node_domain(DNode node) continue; } + /* An input that skips realization can't be a domain input. */ + if (input_descriptor.skip_realization) { + continue; + } + /* Notice that the lower the domain priority value is, the higher the priority is, hence the * less than comparison. */ if (input_descriptor.domain_priority < current_domain_priority) { diff --git a/source/blender/compositor/realtime_compositor/intern/conversion_operation.cc b/source/blender/compositor/realtime_compositor/intern/conversion_operation.cc index d6bf74ffbee..3743b9bba87 100644 --- a/source/blender/compositor/realtime_compositor/intern/conversion_operation.cc +++ b/source/blender/compositor/realtime_compositor/intern/conversion_operation.cc @@ -12,9 +12,9 @@ namespace blender::realtime_compositor { -/* ------------------------------------------------------------------------------------------------- - * Conversion Operation. - */ +/* -------------------------------------------------------------------- */ +/** \name Conversion Operation + * \{ */ void ConversionOperation::execute() { @@ -79,9 +79,11 @@ SimpleOperation *ConversionOperation::construct_if_needed(Context &context, return nullptr; } -/* ------------------------------------------------------------------------------------------------- - * Convert Float To Vector Operation. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Convert Float to Vector Operation + * \{ */ ConvertFloatToVectorOperation::ConvertFloatToVectorOperation(Context &context) : ConversionOperation(context) @@ -102,9 +104,11 @@ GPUShader *ConvertFloatToVectorOperation::get_conversion_shader() const return shader_manager().get("compositor_convert_float_to_vector"); } -/* ------------------------------------------------------------------------------------------------- - * Convert Float To Color Operation. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Convert Float to Color Operation + * \{ */ ConvertFloatToColorOperation::ConvertFloatToColorOperation(Context &context) : ConversionOperation(context) @@ -127,9 +131,11 @@ GPUShader *ConvertFloatToColorOperation::get_conversion_shader() const return shader_manager().get("compositor_convert_float_to_color"); } -/* ------------------------------------------------------------------------------------------------- - * Convert Color To Float Operation. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Convert Color to Float Operation + * \{ */ ConvertColorToFloatOperation::ConvertColorToFloatOperation(Context &context) : ConversionOperation(context) @@ -151,9 +157,11 @@ GPUShader *ConvertColorToFloatOperation::get_conversion_shader() const return shader_manager().get("compositor_convert_color_to_float"); } -/* ------------------------------------------------------------------------------------------------- - * Convert Color To Vector Operation. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Convert Color to Vector Operation + * \{ */ ConvertColorToVectorOperation::ConvertColorToVectorOperation(Context &context) : ConversionOperation(context) @@ -175,9 +183,11 @@ GPUShader *ConvertColorToVectorOperation::get_conversion_shader() const return shader_manager().get("compositor_convert_color_to_vector"); } -/* ------------------------------------------------------------------------------------------------- - * Convert Vector To Float Operation. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Convert Vector to Float Operation + * \{ */ ConvertVectorToFloatOperation::ConvertVectorToFloatOperation(Context &context) : ConversionOperation(context) @@ -199,9 +209,11 @@ GPUShader *ConvertVectorToFloatOperation::get_conversion_shader() const return shader_manager().get("compositor_convert_vector_to_float"); } -/* ------------------------------------------------------------------------------------------------- - * Convert Vector To Color Operation. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Convert Vector to Color Operation + * \{ */ ConvertVectorToColorOperation::ConvertVectorToColorOperation(Context &context) : ConversionOperation(context) @@ -222,4 +234,6 @@ GPUShader *ConvertVectorToColorOperation::get_conversion_shader() const return shader_manager().get("compositor_convert_vector_to_color"); } +/** \} */ + } // namespace blender::realtime_compositor diff --git a/source/blender/compositor/realtime_compositor/intern/evaluator.cc b/source/blender/compositor/realtime_compositor/intern/evaluator.cc index d358389f2e9..48457bec199 100644 --- a/source/blender/compositor/realtime_compositor/intern/evaluator.cc +++ b/source/blender/compositor/realtime_compositor/intern/evaluator.cc @@ -45,7 +45,6 @@ void Evaluator::reset() { operations_stream_.clear(); derived_node_tree_.reset(); - node_tree_reference_map_.clear(); is_compiled_ = false; } @@ -67,7 +66,7 @@ bool Evaluator::validate_node_tree() void Evaluator::compile_and_evaluate() { - derived_node_tree_ = std::make_unique<DerivedNodeTree>(node_tree_, node_tree_reference_map_); + derived_node_tree_ = std::make_unique<DerivedNodeTree>(node_tree_); if (!validate_node_tree()) { return; @@ -93,7 +92,7 @@ void Evaluator::compile_and_evaluate() void Evaluator::compile_and_evaluate_node(DNode node, CompileState &compile_state) { - NodeOperation *operation = node->typeinfo()->get_compositor_operation(context_, node); + NodeOperation *operation = node->typeinfo->get_compositor_operation(context_, node); compile_state.map_node_to_node_operation(node, operation); @@ -113,16 +112,16 @@ void Evaluator::map_node_operation_inputs_to_their_results(DNode node, NodeOperation *operation, CompileState &compile_state) { - for (const InputSocketRef *input_ref : node->inputs()) { - const DInputSocket input{node.context(), input_ref}; + for (const bNodeSocket *input : node->input_sockets()) { + const DInputSocket dinput{node.context(), input}; - DSocket origin = get_input_origin_socket(input); + DSocket dorigin = get_input_origin_socket(dinput); /* The origin socket is an output, which means the input is linked. So map the input to the * result we get from the output. */ - if (origin->is_output()) { - Result &result = compile_state.get_result_from_output_socket(DOutputSocket(origin)); - operation->map_input_to_result(input->identifier(), &result); + if (dorigin->is_output()) { + Result &result = compile_state.get_result_from_output_socket(DOutputSocket(dorigin)); + operation->map_input_to_result(input->identifier, &result); continue; } @@ -130,8 +129,8 @@ void Evaluator::map_node_operation_inputs_to_their_results(DNode node, * origin is the input socket itself or the input is connected to an unlinked input of a group * input node and the origin is the input of the group input node. So map the input to the * result of a newly created Input Single Value Operation. */ - auto *input_operation = new InputSingleValueOperation(context_, DInputSocket(origin)); - operation->map_input_to_result(input->identifier(), &input_operation->get_result()); + auto *input_operation = new InputSingleValueOperation(context_, DInputSocket(dorigin)); + operation->map_input_to_result(input->identifier, &input_operation->get_result()); operations_stream_.append(std::unique_ptr<InputSingleValueOperation>(input_operation)); diff --git a/source/blender/compositor/realtime_compositor/intern/input_single_value_operation.cc b/source/blender/compositor/realtime_compositor/intern/input_single_value_operation.cc index 0bdd40e3636..b3cc86b5f79 100644 --- a/source/blender/compositor/realtime_compositor/intern/input_single_value_operation.cc +++ b/source/blender/compositor/realtime_compositor/intern/input_single_value_operation.cc @@ -14,7 +14,7 @@ const StringRef InputSingleValueOperation::output_identifier_ = StringRef("Outpu InputSingleValueOperation::InputSingleValueOperation(Context &context, DInputSocket input_socket) : Operation(context), input_socket_(input_socket) { - const ResultType result_type = get_node_socket_result_type(input_socket_.socket_ref()); + const ResultType result_type = get_node_socket_result_type(input_socket_.bsocket()); Result result = Result(result_type, texture_pool()); /* The result of an input single value operation is guaranteed to have a single user. */ @@ -29,17 +29,19 @@ void InputSingleValueOperation::execute() Result &result = get_result(); result.allocate_single_value(); + const bNodeSocket *bsocket = input_socket_.bsocket(); + /* Set the value of the result to the default value of the input socket. */ switch (result.type()) { case ResultType::Float: - result.set_float_value(input_socket_->default_value<bNodeSocketValueFloat>()->value); + result.set_float_value(bsocket->default_value_typed<bNodeSocketValueFloat>()->value); break; case ResultType::Vector: result.set_vector_value( - float3(input_socket_->default_value<bNodeSocketValueVector>()->value)); + float3(bsocket->default_value_typed<bNodeSocketValueVector>()->value)); break; case ResultType::Color: - result.set_color_value(float4(input_socket_->default_value<bNodeSocketValueRGBA>()->value)); + result.set_color_value(float4(bsocket->default_value_typed<bNodeSocketValueRGBA>()->value)); break; } } diff --git a/source/blender/compositor/realtime_compositor/intern/node_operation.cc b/source/blender/compositor/realtime_compositor/intern/node_operation.cc index f02d0906447..1c20c967ddb 100644 --- a/source/blender/compositor/realtime_compositor/intern/node_operation.cc +++ b/source/blender/compositor/realtime_compositor/intern/node_operation.cc @@ -25,27 +25,27 @@ using namespace nodes::derived_node_tree_types; NodeOperation::NodeOperation(Context &context, DNode node) : Operation(context), node_(node) { - for (const OutputSocketRef *output : node->outputs()) { + for (const bNodeSocket *output : node->output_sockets()) { const ResultType result_type = get_node_socket_result_type(output); const Result result = Result(result_type, texture_pool()); - populate_result(output->identifier(), result); + populate_result(output->identifier, result); } - for (const InputSocketRef *input : node->inputs()) { + for (const bNodeSocket *input : node->input_sockets()) { const InputDescriptor input_descriptor = input_descriptor_from_input_socket(input); - declare_input_descriptor(input->identifier(), input_descriptor); + declare_input_descriptor(input->identifier, input_descriptor); } } void NodeOperation::compute_results_reference_counts(const Schedule &schedule) { - for (const OutputSocketRef *output_ref : node()->outputs()) { - const DOutputSocket output{node().context(), output_ref}; + for (const bNodeSocket *output : this->node()->output_sockets()) { + const DOutputSocket doutput{node().context(), output}; const int reference_count = number_of_inputs_linked_to_output_conditioned( - output, [&](DInputSocket input) { return schedule.contains(input.node()); }); + doutput, [&](DInputSocket input) { return schedule.contains(input.node()); }); - get_result(output->identifier()).set_initial_reference_count(reference_count); + get_result(doutput->identifier).set_initial_reference_count(reference_count); } } @@ -56,7 +56,7 @@ const DNode &NodeOperation::node() const const bNode &NodeOperation::bnode() const { - return *node_->bnode(); + return *node_; } bool NodeOperation::should_compute_output(StringRef identifier) diff --git a/source/blender/compositor/realtime_compositor/intern/operation.cc b/source/blender/compositor/realtime_compositor/intern/operation.cc index 42dd5aeebe8..832196cc5ef 100644 --- a/source/blender/compositor/realtime_compositor/intern/operation.cc +++ b/source/blender/compositor/realtime_compositor/intern/operation.cc @@ -66,6 +66,11 @@ Domain Operation::compute_domain() continue; } + /* An input that skips realization can't be a domain input. */ + if (descriptor.skip_realization) { + continue; + } + /* Notice that the lower the domain priority value is, the higher the priority is, hence the * less than comparison. */ if (descriptor.domain_priority < current_domain_priority) { @@ -83,7 +88,7 @@ void Operation::add_and_evaluate_input_processors() * because the construction of the input processors may depend on the result of previous input * processors for all inputs. For instance, the realize on domain input processor considers the * value of all inputs, so previous input processors for all inputs needs to be added and - * evaluated first. */ + * evaluated first. */ for (const StringRef &identifier : results_mapped_to_inputs_.keys()) { SimpleOperation *single_value = ReduceToSingleValueOperation::construct_if_needed( diff --git a/source/blender/compositor/realtime_compositor/intern/realize_on_domain_operation.cc b/source/blender/compositor/realtime_compositor/intern/realize_on_domain_operation.cc index 47993060a74..817293c0fa6 100644 --- a/source/blender/compositor/realtime_compositor/intern/realize_on_domain_operation.cc +++ b/source/blender/compositor/realtime_compositor/intern/realize_on_domain_operation.cc @@ -41,7 +41,7 @@ void RealizeOnDomainOperation::execute() const float3x3 local_transformation = input.domain().transformation * domain_.transformation.inverted(); - /* Set the origin of the transformation to be the center of the domain. */ + /* Set the origin of the transformation to be the center of the domain. */ const float3x3 transformation = float3x3::from_origin_transformation( local_transformation, float2(domain_.size) / 2.0f); diff --git a/source/blender/compositor/realtime_compositor/intern/scheduler.cc b/source/blender/compositor/realtime_compositor/intern/scheduler.cc index ce8b9330541..ac5cc55a73f 100644 --- a/source/blender/compositor/realtime_compositor/intern/scheduler.cc +++ b/source/blender/compositor/realtime_compositor/intern/scheduler.cc @@ -8,6 +8,8 @@ #include "NOD_derived_node_tree.hh" +#include "BKE_node_runtime.hh" + #include "COM_scheduler.hh" #include "COM_utilities.hh" @@ -21,22 +23,22 @@ using namespace nodes::derived_node_tree_types; * node will be returned. */ static DNode compute_output_node(DerivedNodeTree &tree) { - const NodeTreeRef &root_tree = tree.root_context().tree(); + const bNodeTree &root_tree = tree.root_context().btree(); - for (const NodeRef *node : root_tree.nodes_by_type("CompositorNodeComposite")) { - if (node->bnode()->flag & NODE_DO_OUTPUT) { + for (const bNode *node : root_tree.nodes_by_type("CompositorNodeComposite")) { + if (node->flag & NODE_DO_OUTPUT) { return DNode(&tree.root_context(), node); } } - for (const NodeRef *node : root_tree.nodes_by_type("CompositorNodeViewer")) { - if (node->bnode()->flag & NODE_DO_OUTPUT) { + for (const bNode *node : root_tree.nodes_by_type("CompositorNodeViewer")) { + if (node->flag & NODE_DO_OUTPUT) { return DNode(&tree.root_context(), node); } } - for (const NodeRef *node : root_tree.nodes_by_type("CompositorNodeSplitViewer")) { - if (node->bnode()->flag & NODE_DO_OUTPUT) { + for (const bNode *node : root_tree.nodes_by_type("CompositorNodeSplitViewer")) { + if (node->flag & NODE_DO_OUTPUT) { return DNode(&tree.root_context(), node); } } @@ -120,25 +122,25 @@ static NeededBuffers compute_number_of_needed_buffers(DNode output_node) /* Go over the node dependencies connected to the inputs of the node and push them to the node * stack if they were not computed already. */ Set<DNode> pushed_nodes; - for (const InputSocketRef *input_ref : node->inputs()) { - const DInputSocket input{node.context(), input_ref}; + for (const bNodeSocket *input : node->input_sockets()) { + const DInputSocket dinput{node.context(), input}; /* Get the output linked to the input. If it is null, that means the input is unlinked and * has no dependency node. */ - const DOutputSocket output = get_output_linked_to_input(input); - if (!output) { + const DOutputSocket doutput = get_output_linked_to_input(dinput); + if (!doutput) { continue; } /* The node dependency was already computed or pushed before, so skip it. */ - if (needed_buffers.contains(output.node()) || pushed_nodes.contains(output.node())) { + if (needed_buffers.contains(doutput.node()) || pushed_nodes.contains(doutput.node())) { continue; } /* The output node needs to be computed, push the node dependency to the node stack and * indicate that it was pushed. */ - node_stack.push(output.node()); - pushed_nodes.add_new(output.node()); + node_stack.push(doutput.node()); + pushed_nodes.add_new(doutput.node()); } /* If any of the node dependencies were pushed, that means that not all of them were computed @@ -154,26 +156,26 @@ static NeededBuffers compute_number_of_needed_buffers(DNode output_node) * buffers needed to compute the most demanding of the node dependencies. */ int number_of_input_buffers = 0; int buffers_needed_by_dependencies = 0; - for (const InputSocketRef *input_ref : node->inputs()) { - const DInputSocket input{node.context(), input_ref}; + for (const bNodeSocket *input : node->input_sockets()) { + const DInputSocket dinput{node.context(), input}; /* Get the output linked to the input. If it is null, that means the input is unlinked. * Unlinked inputs do not take a buffer, so skip those inputs. */ - const DOutputSocket output = get_output_linked_to_input(input); - if (!output) { + const DOutputSocket doutput = get_output_linked_to_input(dinput); + if (!doutput) { continue; } /* Since this input is linked, if the link is not between two shader nodes, it means that the * node takes a buffer through this input and so we increment the number of input buffers. */ - if (!is_shader_node(node) || !is_shader_node(output.node())) { + if (!is_shader_node(node) || !is_shader_node(doutput.node())) { number_of_input_buffers++; } /* If the number of buffers needed by the node dependency is more than the total number of * buffers needed by the dependencies, then update the latter to be the former. This is * computing the "d" in the aforementioned equation "max(n + m, d)". */ - const int buffers_needed_by_dependency = needed_buffers.lookup(output.node()); + const int buffers_needed_by_dependency = needed_buffers.lookup(doutput.node()); if (buffers_needed_by_dependency > buffers_needed_by_dependencies) { buffers_needed_by_dependencies = buffers_needed_by_dependency; } @@ -181,17 +183,18 @@ static NeededBuffers compute_number_of_needed_buffers(DNode output_node) /* Compute the number of buffers that will be computed/output by this node. */ int number_of_output_buffers = 0; - for (const OutputSocketRef *output_ref : node->outputs()) { - const DOutputSocket output{node.context(), output_ref}; + for (const bNodeSocket *output : node->output_sockets()) { + const DOutputSocket doutput{node.context(), output}; /* The output is not linked, it outputs no buffer. */ - if (output->logically_linked_sockets().is_empty()) { + if (!output->is_logically_linked()) { continue; } /* If any of the links is not between two shader nodes, it means that the node outputs * a buffer through this output and so we increment the number of output buffers. */ - if (!is_output_linked_to_node_conditioned(output, is_shader_node) || !is_shader_node(node)) { + if (!is_output_linked_to_node_conditioned(doutput, is_shader_node) || + !is_shader_node(node)) { number_of_output_buffers++; } } @@ -255,24 +258,24 @@ Schedule compute_schedule(DerivedNodeTree &tree) * want the node with the highest number of needed buffers to be schedule first, but since * those are pushed to the traversal stack, we need to push them in reverse order. */ Vector<DNode> sorted_dependency_nodes; - for (const InputSocketRef *input_ref : node->inputs()) { - const DInputSocket input{node.context(), input_ref}; + for (const bNodeSocket *input : node->input_sockets()) { + const DInputSocket dinput{node.context(), input}; /* Get the output linked to the input. If it is null, that means the input is unlinked and * has no dependency node, so skip it. */ - const DOutputSocket output = get_output_linked_to_input(input); - if (!output) { + const DOutputSocket doutput = get_output_linked_to_input(dinput); + if (!doutput) { continue; } /* The dependency node was added before, so skip it. The number of dependency nodes is very * small, typically less than 3, so a linear search is okay. */ - if (sorted_dependency_nodes.contains(output.node())) { + if (sorted_dependency_nodes.contains(doutput.node())) { continue; } /* The dependency node was already schedule, so skip it. */ - if (schedule.contains(output.node())) { + if (schedule.contains(doutput.node())) { continue; } @@ -280,7 +283,7 @@ Schedule compute_schedule(DerivedNodeTree &tree) * typically less than 3, so insertion sort is okay. */ int insertion_position = 0; for (int i = 0; i < sorted_dependency_nodes.size(); i++) { - if (needed_buffers.lookup(output.node()) > + if (needed_buffers.lookup(doutput.node()) > needed_buffers.lookup(sorted_dependency_nodes[i])) { insertion_position++; } @@ -288,7 +291,7 @@ Schedule compute_schedule(DerivedNodeTree &tree) break; } } - sorted_dependency_nodes.insert(insertion_position, output.node()); + sorted_dependency_nodes.insert(insertion_position, doutput.node()); } /* Push the sorted dependency nodes to the node stack in order. */ diff --git a/source/blender/compositor/realtime_compositor/intern/shader_node.cc b/source/blender/compositor/realtime_compositor/intern/shader_node.cc index f23485cee96..96dd50790c3 100644 --- a/source/blender/compositor/realtime_compositor/intern/shader_node.cc +++ b/source/blender/compositor/realtime_compositor/intern/shader_node.cc @@ -57,9 +57,9 @@ const DNode &ShaderNode::node() const return node_; } -bNode &ShaderNode::bnode() const +const bNode &ShaderNode::bnode() const { - return *node_->bnode(); + return *node_; } static eGPUType gpu_type_from_socket_type(eNodeSocketDatatype type) @@ -77,17 +77,17 @@ static eGPUType gpu_type_from_socket_type(eNodeSocketDatatype type) } } -static void gpu_stack_vector_from_socket(float *vector, const SocketRef *socket) +static void gpu_stack_vector_from_socket(float *vector, const bNodeSocket *socket) { - switch (socket->bsocket()->type) { + switch (socket->type) { case SOCK_FLOAT: - vector[0] = socket->default_value<bNodeSocketValueFloat>()->value; + vector[0] = socket->default_value_typed<bNodeSocketValueFloat>()->value; return; case SOCK_VECTOR: - copy_v3_v3(vector, socket->default_value<bNodeSocketValueVector>()->value); + copy_v3_v3(vector, socket->default_value_typed<bNodeSocketValueVector>()->value); return; case SOCK_RGBA: - copy_v4_v4(vector, socket->default_value<bNodeSocketValueRGBA>()->value); + copy_v4_v4(vector, socket->default_value_typed<bNodeSocketValueRGBA>()->value); return; default: BLI_assert_unreachable(); @@ -101,8 +101,8 @@ static void populate_gpu_node_stack(DSocket socket, GPUNodeStack &stack) /* This will be initialized later by the GPU material compiler or the compile method. */ stack.link = nullptr; - stack.sockettype = socket->bsocket()->type; - stack.type = gpu_type_from_socket_type((eNodeSocketDatatype)socket->bsocket()->type); + stack.sockettype = socket->type; + stack.type = gpu_type_from_socket_type((eNodeSocketDatatype)socket->type); if (socket->is_input()) { const DInputSocket input(socket); @@ -117,10 +117,10 @@ static void populate_gpu_node_stack(DSocket socket, GPUNodeStack &stack) * unlinked input or an unlinked input of a group input node that the socket is linked to, * otherwise, get the value from the socket itself. */ if (origin->is_input()) { - gpu_stack_vector_from_socket(stack.vec, origin.socket_ref()); + gpu_stack_vector_from_socket(stack.vec, origin.bsocket()); } else { - gpu_stack_vector_from_socket(stack.vec, socket.socket_ref()); + gpu_stack_vector_from_socket(stack.vec, socket.bsocket()); } } else { @@ -132,10 +132,11 @@ void ShaderNode::populate_inputs() { /* Reserve a stack for each input in addition to an extra stack at the end to mark the end of the * array, as this is what the GPU module functions expect. */ - inputs_.resize(node_->inputs().size() + 1); + const int num_input_sockets = node_->input_sockets().size(); + inputs_.resize(num_input_sockets + 1); inputs_.last().end = true; - for (int i = 0; i < node_->inputs().size(); i++) { + for (int i = 0; i < num_input_sockets; i++) { populate_gpu_node_stack(node_.input(i), inputs_[i]); } } @@ -144,10 +145,11 @@ void ShaderNode::populate_outputs() { /* Reserve a stack for each output in addition to an extra stack at the end to mark the end of * the array, as this is what the GPU module functions expect. */ - outputs_.resize(node_->outputs().size() + 1); + const int num_output_sockets = node_->output_sockets().size(); + outputs_.resize(num_output_sockets + 1); outputs_.last().end = true; - for (int i = 0; i < node_->outputs().size(); i++) { + for (int i = 0; i < num_output_sockets; i++) { populate_gpu_node_stack(node_.output(i), outputs_[i]); } } diff --git a/source/blender/compositor/realtime_compositor/intern/shader_operation.cc b/source/blender/compositor/realtime_compositor/intern/shader_operation.cc index a097c81a4c5..8e52baf63ec 100644 --- a/source/blender/compositor/realtime_compositor/intern/shader_operation.cc +++ b/source/blender/compositor/realtime_compositor/intern/shader_operation.cc @@ -128,7 +128,7 @@ void ShaderOperation::construct_material(void *thunk, GPUMaterial *material) { ShaderOperation *operation = static_cast<ShaderOperation *>(thunk); for (DNode node : operation->compile_unit_) { - ShaderNode *shader_node = node->typeinfo()->get_compositor_shader_node(node); + ShaderNode *shader_node = node->typeinfo->get_compositor_shader_node(node); operation->shader_nodes_.add_new(node, std::unique_ptr<ShaderNode>(shader_node)); operation->link_node_inputs(node, material); @@ -141,27 +141,27 @@ void ShaderOperation::construct_material(void *thunk, GPUMaterial *material) void ShaderOperation::link_node_inputs(DNode node, GPUMaterial *material) { - for (const InputSocketRef *input_ref : node->inputs()) { - const DInputSocket input{node.context(), input_ref}; + for (const bNodeSocket *input : node->input_sockets()) { + const DInputSocket dinput{node.context(), input}; /* Get the output linked to the input. If it is null, that means the input is unlinked. * Unlinked inputs are linked by the node compile method, so skip this here. */ - const DOutputSocket output = get_output_linked_to_input(input); - if (!output) { + const DOutputSocket doutput = get_output_linked_to_input(dinput); + if (!doutput) { continue; } /* If the origin node is part of the shader operation, then the link is internal to the GPU * material graph and is linked appropriately. */ - if (compile_unit_.contains(output.node())) { - link_node_input_internal(input, output); + if (compile_unit_.contains(doutput.node())) { + link_node_input_internal(dinput, doutput); continue; } /* Otherwise, the origin node is not part of the shader operation, then the link is external to * the GPU material graph and an input to the shader operation must be declared and linked to * the node input. */ - link_node_input_external(input, output, material); + link_node_input_external(dinput, doutput, material); } } @@ -169,10 +169,10 @@ void ShaderOperation::link_node_input_internal(DInputSocket input_socket, DOutputSocket output_socket) { ShaderNode &output_node = *shader_nodes_.lookup(output_socket.node()); - GPUNodeStack &output_stack = output_node.get_output(output_socket->identifier()); + GPUNodeStack &output_stack = output_node.get_output(output_socket->identifier); ShaderNode &input_node = *shader_nodes_.lookup(input_socket.node()); - GPUNodeStack &input_stack = input_node.get_input(input_socket->identifier()); + GPUNodeStack &input_stack = input_node.get_input(input_socket->identifier); input_stack.link = output_stack.link; } @@ -183,7 +183,7 @@ void ShaderOperation::link_node_input_external(DInputSocket input_socket, { ShaderNode &node = *shader_nodes_.lookup(input_socket.node()); - GPUNodeStack &stack = node.get_input(input_socket->identifier()); + GPUNodeStack &stack = node.get_input(input_socket->identifier); /* An input was already declared for that same output socket, so no need to declare it again. */ if (!output_to_material_attribute_map_.contains(output_socket)) { @@ -219,8 +219,8 @@ void ShaderOperation::declare_operation_input(DInputSocket input_socket, /* Declare the input descriptor for this input and prefer to declare its type to be the same as * the type of the output socket because doing type conversion in the shader is much cheaper. */ - InputDescriptor input_descriptor = input_descriptor_from_input_socket(input_socket.socket_ref()); - input_descriptor.type = get_node_socket_result_type(output_socket.socket_ref()); + InputDescriptor input_descriptor = input_descriptor_from_input_socket(input_socket.bsocket()); + input_descriptor.type = get_node_socket_result_type(output_socket.bsocket()); declare_input_descriptor(input_identifier, input_descriptor); /* Add a new GPU attribute representing an input to the GPU material. Instead of using the @@ -242,16 +242,16 @@ void ShaderOperation::declare_operation_input(DInputSocket input_socket, void ShaderOperation::populate_results_for_node(DNode node, GPUMaterial *material) { - for (const OutputSocketRef *output_ref : node->outputs()) { - const DOutputSocket output{node.context(), output_ref}; + for (const bNodeSocket *output : node->output_sockets()) { + const DOutputSocket doutput{node.context(), output}; /* If any of the nodes linked to the output are not part of the shader operation, then an * output result needs to be populated for it. */ const bool need_to_populate_result = is_output_linked_to_node_conditioned( - output, [&](DNode node) { return !compile_unit_.contains(node); }); + doutput, [&](DNode node) { return !compile_unit_.contains(node); }); if (need_to_populate_result) { - populate_operation_result(output, material); + populate_operation_result(doutput, material); } } } @@ -276,7 +276,7 @@ void ShaderOperation::populate_operation_result(DOutputSocket output_socket, GPU const unsigned int output_id = output_sockets_to_output_identifiers_map_.size(); std::string output_identifier = "output" + std::to_string(output_id); - const ResultType result_type = get_node_socket_result_type(output_socket.socket_ref()); + const ResultType result_type = get_node_socket_result_type(output_socket.bsocket()); const Result result = Result(result_type, texture_pool()); populate_result(output_identifier, result); @@ -284,7 +284,7 @@ void ShaderOperation::populate_operation_result(DOutputSocket output_socket, GPU output_sockets_to_output_identifiers_map_.add_new(output_socket, output_identifier); ShaderNode &node = *shader_nodes_.lookup(output_socket.node()); - GPUNodeLink *output_link = node.get_output(output_socket->identifier()).link; + GPUNodeLink *output_link = node.get_output(output_socket->identifier).link; /* Link the output node stack to an output storer storing in the appropriate result. The result * is identified by its index in the operation and the index is encoded as a float to be passed @@ -481,6 +481,10 @@ void ShaderOperation::generate_code_for_inputs(GPUMaterial *material, /* The attributes of the GPU material represents the inputs of the operation. */ ListBase attributes = GPU_material_attributes(material); + if (BLI_listbase_is_empty(&attributes)) { + return; + } + /* Add a texture sampler for each of the inputs with the same name as the attribute. */ LISTBASE_FOREACH (GPUMaterialAttribute *, attribute, &attributes) { shader_create_info.sampler(0, ImageType::FLOAT_2D, attribute->name, Frequency::BATCH); diff --git a/source/blender/compositor/realtime_compositor/intern/texture_pool.cc b/source/blender/compositor/realtime_compositor/intern/texture_pool.cc index 1568970a030..6bf2041e6ba 100644 --- a/source/blender/compositor/realtime_compositor/intern/texture_pool.cc +++ b/source/blender/compositor/realtime_compositor/intern/texture_pool.cc @@ -13,9 +13,9 @@ namespace blender::realtime_compositor { -/* -------------------------------------------------------------------- - * Texture Pool Key. - */ +/* -------------------------------------------------------------------- */ +/** \name Texture Pool Key + * \{ */ TexturePoolKey::TexturePoolKey(int2 size, eGPUTextureFormat format) : size(size), format(format) { @@ -37,9 +37,11 @@ bool operator==(const TexturePoolKey &a, const TexturePoolKey &b) return a.size == b.size && a.format == b.format; } -/* -------------------------------------------------------------------- - * Texture Pool. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Texture Pool + * \{ */ GPUTexture *TexturePool::acquire(int2 size, eGPUTextureFormat format) { @@ -81,4 +83,6 @@ void TexturePool::reset() textures_.clear(); } +/** \} */ + } // namespace blender::realtime_compositor diff --git a/source/blender/compositor/realtime_compositor/intern/utilities.cc b/source/blender/compositor/realtime_compositor/intern/utilities.cc index 169ba70e9eb..1a5823b8441 100644 --- a/source/blender/compositor/realtime_compositor/intern/utilities.cc +++ b/source/blender/compositor/realtime_compositor/intern/utilities.cc @@ -26,7 +26,7 @@ using TargetSocketPathInfo = DOutputSocket::TargetSocketPathInfo; DSocket get_input_origin_socket(DInputSocket input) { /* The input is unlinked. Return the socket itself. */ - if (input->logically_linked_sockets().is_empty()) { + if (!input->is_logically_linked()) { return input; } @@ -52,9 +52,9 @@ DOutputSocket get_output_linked_to_input(DInputSocket input) return DOutputSocket(origin); } -ResultType get_node_socket_result_type(const SocketRef *socket) +ResultType get_node_socket_result_type(const bNodeSocket *socket) { - switch (socket->bsocket()->type) { + switch (socket->type) { case SOCK_FLOAT: return ResultType::Float; case SOCK_VECTOR: @@ -95,21 +95,20 @@ int number_of_inputs_linked_to_output_conditioned(DOutputSocket output, bool is_shader_node(DNode node) { - return node->typeinfo()->get_compositor_shader_node; + return node->typeinfo->get_compositor_shader_node; } bool is_node_supported(DNode node) { - return node->typeinfo()->get_compositor_operation || - node->typeinfo()->get_compositor_shader_node; + return node->typeinfo->get_compositor_operation || node->typeinfo->get_compositor_shader_node; } -InputDescriptor input_descriptor_from_input_socket(const InputSocketRef *socket) +InputDescriptor input_descriptor_from_input_socket(const bNodeSocket *socket) { using namespace nodes; InputDescriptor input_descriptor; input_descriptor.type = get_node_socket_result_type(socket); - const NodeDeclaration *node_declaration = socket->node().declaration(); + const NodeDeclaration *node_declaration = socket->owner_node().declaration(); /* Not every node have a declaration, in which case, we assume the default values for the rest of * the properties. */ if (!node_declaration) { @@ -117,6 +116,7 @@ InputDescriptor input_descriptor_from_input_socket(const InputSocketRef *socket) } const SocketDeclarationPtr &socket_declaration = node_declaration->inputs()[socket->index()]; input_descriptor.domain_priority = socket_declaration->compositor_domain_priority(); + input_descriptor.skip_realization = socket_declaration->compositor_skip_realization(); input_descriptor.expects_single_value = socket_declaration->compositor_expects_single_value(); return input_descriptor; } |