From e3f8768d8a60b750d98bf976b6c1489d606b7891 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Fri, 17 Jul 2020 14:23:57 +0200 Subject: Refactor: move ParticleFunction to separate file --- source/blender/simulation/CMakeLists.txt | 2 + source/blender/simulation/SIM_particle_function.hh | 89 ++++++++++ .../blender/simulation/intern/particle_function.cc | 160 ++++++++++++++++++ .../blender/simulation/intern/simulation_update.cc | 184 +-------------------- 4 files changed, 252 insertions(+), 183 deletions(-) create mode 100644 source/blender/simulation/SIM_particle_function.hh create mode 100644 source/blender/simulation/intern/particle_function.cc diff --git a/source/blender/simulation/CMakeLists.txt b/source/blender/simulation/CMakeLists.txt index f9fc0b5c798..fa4838b0875 100644 --- a/source/blender/simulation/CMakeLists.txt +++ b/source/blender/simulation/CMakeLists.txt @@ -44,9 +44,11 @@ set(SRC intern/implicit.h intern/implicit_blender.c intern/implicit_eigen.cpp + intern/particle_function.cc intern/simulation_update.cc SIM_mass_spring.h + SIM_particle_function.hh SIM_simulation_update.hh ) diff --git a/source/blender/simulation/SIM_particle_function.hh b/source/blender/simulation/SIM_particle_function.hh new file mode 100644 index 00000000000..eae61b1ae11 --- /dev/null +++ b/source/blender/simulation/SIM_particle_function.hh @@ -0,0 +1,89 @@ +/* + * 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. + */ + +#ifndef __SIM_PARTICLE_FUNCTION_HH__ +#define __SIM_PARTICLE_FUNCTION_HH__ + +#include "FN_attributes_ref.hh" +#include "FN_multi_function.hh" + +#include "BLI_resource_collector.hh" + +namespace blender::sim { + +class ParticleFunctionInput { + public: + virtual ~ParticleFunctionInput() = default; + virtual void add_input(fn::AttributesRef attributes, + fn::MFParamsBuilder ¶ms, + ResourceCollector &resources) const = 0; +}; + +class ParticleFunction { + private: + const fn::MultiFunction *global_fn_; + const fn::MultiFunction *per_particle_fn_; + Array global_inputs_; + Array per_particle_inputs_; + Array output_is_global_; + Vector global_output_indices_; + Vector per_particle_output_indices_; + Vector output_types_; + Vector output_names_; + + friend class ParticleFunctionEvaluator; + + public: + ParticleFunction(const fn::MultiFunction *global_fn, + const fn::MultiFunction *per_particle_fn, + Span global_inputs, + Span per_particle_inputs, + Span output_is_global); +}; + +class ParticleFunctionEvaluator { + private: + ResourceCollector resources_; + const ParticleFunction &particle_fn_; + IndexMask mask_; + fn::MFContextBuilder global_context_; + fn::MFContextBuilder per_particle_context_; + fn::AttributesRef particle_attributes_; + Vector outputs_; + bool is_computed_ = false; + + public: + ParticleFunctionEvaluator(const ParticleFunction &particle_fn, + IndexMask mask, + fn::AttributesRef particle_attributes); + ~ParticleFunctionEvaluator(); + + void compute(); + fn::GVSpan get(uint output_index, StringRef expected_name) const; + + template fn::VSpan get(uint output_index, StringRef expected_name) const + { + return this->get(output_index, expected_name).typed(); + } + + private: + void compute_globals(); + void compute_per_particle(); +}; + +} // namespace blender::sim + +#endif /* __SIM_PARTICLE_FUNCTION_HH__ */ diff --git a/source/blender/simulation/intern/particle_function.cc b/source/blender/simulation/intern/particle_function.cc new file mode 100644 index 00000000000..7a0c9ccdb13 --- /dev/null +++ b/source/blender/simulation/intern/particle_function.cc @@ -0,0 +1,160 @@ +/* + * 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. + */ + +#include "SIM_particle_function.hh" + +namespace blender::sim { + +ParticleFunction::ParticleFunction(const fn::MultiFunction *global_fn, + const fn::MultiFunction *per_particle_fn, + Span global_inputs, + Span per_particle_inputs, + Span output_is_global) + : global_fn_(global_fn), + per_particle_fn_(per_particle_fn), + global_inputs_(global_inputs), + per_particle_inputs_(per_particle_inputs), + output_is_global_(output_is_global) +{ + for (uint i : output_is_global_.index_range()) { + if (output_is_global_[i]) { + uint param_index = global_inputs_.size() + global_output_indices_.size(); + fn::MFParamType param_type = global_fn_->param_type(param_index); + BLI_assert(param_type.is_output()); + output_types_.append(param_type.data_type()); + output_names_.append(global_fn_->param_name(param_index)); + global_output_indices_.append(i); + } + else { + uint param_index = per_particle_inputs_.size() + per_particle_output_indices_.size(); + fn::MFParamType param_type = per_particle_fn_->param_type(param_index); + BLI_assert(param_type.is_output()); + output_types_.append(param_type.data_type()); + output_names_.append(per_particle_fn_->param_name(param_index)); + per_particle_output_indices_.append(i); + } + } +} + +ParticleFunctionEvaluator::ParticleFunctionEvaluator(const ParticleFunction &particle_fn, + IndexMask mask, + fn::AttributesRef particle_attributes) + : particle_fn_(particle_fn), + mask_(mask), + particle_attributes_(particle_attributes), + outputs_(particle_fn_.output_types_.size(), nullptr) +{ +} + +ParticleFunctionEvaluator::~ParticleFunctionEvaluator() +{ + for (uint output_index : outputs_.index_range()) { + void *buffer = outputs_[output_index]; + fn::MFDataType data_type = particle_fn_.output_types_[output_index]; + BLI_assert(data_type.is_single()); /* For now. */ + const fn::CPPType &type = data_type.single_type(); + + if (particle_fn_.output_is_global_[output_index]) { + type.destruct(buffer); + } + else { + type.destruct_indices(outputs_[0], mask_); + } + } +} + +void ParticleFunctionEvaluator::compute() +{ + BLI_assert(!is_computed_); + this->compute_globals(); + this->compute_per_particle(); + is_computed_ = true; +} + +fn::GVSpan ParticleFunctionEvaluator::get(uint output_index, StringRef expected_name) const +{ +#ifdef DEBUG + StringRef real_name = particle_fn_.output_names_[output_index]; + BLI_assert(expected_name == real_name); + BLI_assert(is_computed_); +#endif + UNUSED_VARS_NDEBUG(expected_name); + const void *buffer = outputs_[output_index]; + const fn::CPPType &type = particle_fn_.output_types_[output_index].single_type(); + if (particle_fn_.output_is_global_[output_index]) { + return fn::GVSpan::FromSingleWithMaxSize(type, buffer); + } + else { + return fn::GVSpan(fn::GSpan(type, buffer, mask_.min_array_size())); + } +} + +void ParticleFunctionEvaluator::compute_globals() +{ + if (particle_fn_.global_fn_ == nullptr) { + return; + } + + fn::MFParamsBuilder params(*particle_fn_.global_fn_, mask_.min_array_size()); + + /* Add input parameters. */ + for (const ParticleFunctionInput *input : particle_fn_.global_inputs_) { + input->add_input(particle_attributes_, params, resources_); + } + + /* Add output parameters. */ + for (uint output_index : particle_fn_.global_output_indices_) { + fn::MFDataType data_type = particle_fn_.output_types_[output_index]; + BLI_assert(data_type.is_single()); /* For now. */ + + const fn::CPPType &type = data_type.single_type(); + void *buffer = resources_.linear_allocator().allocate(type.size(), type.alignment()); + params.add_uninitialized_single_output(fn::GMutableSpan(type, buffer, 1)); + outputs_[output_index] = buffer; + } + + particle_fn_.global_fn_->call({0}, params, global_context_); +} + +void ParticleFunctionEvaluator::compute_per_particle() +{ + if (particle_fn_.per_particle_fn_ == nullptr) { + return; + } + + fn::MFParamsBuilder params(*particle_fn_.per_particle_fn_, mask_.min_array_size()); + + /* Add input parameters. */ + for (const ParticleFunctionInput *input : particle_fn_.per_particle_inputs_) { + input->add_input(particle_attributes_, params, resources_); + } + + /* Add output parameters. */ + for (uint output_index : particle_fn_.per_particle_output_indices_) { + fn::MFDataType data_type = particle_fn_.output_types_[output_index]; + BLI_assert(data_type.is_single()); /* For now. */ + + const fn::CPPType &type = data_type.single_type(); + void *buffer = resources_.linear_allocator().allocate(type.size() * mask_.min_array_size(), + type.alignment()); + params.add_uninitialized_single_output(fn::GMutableSpan(type, buffer, mask_.min_array_size())); + outputs_[output_index] = buffer; + } + + particle_fn_.per_particle_fn_->call(mask_, params, global_context_); +} + +} // namespace blender::sim diff --git a/source/blender/simulation/intern/simulation_update.cc b/source/blender/simulation/intern/simulation_update.cc index 95c7b122e7c..d682b018b11 100644 --- a/source/blender/simulation/intern/simulation_update.cc +++ b/source/blender/simulation/intern/simulation_update.cc @@ -14,6 +14,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include "SIM_particle_function.hh" #include "SIM_simulation_update.hh" #include "BKE_customdata.h" @@ -260,189 +261,6 @@ static void update_simulation_state_list(Simulation *simulation, add_missing_particle_states(simulation, state_names); } -class ParticleFunctionInput { - public: - virtual ~ParticleFunctionInput() = default; - virtual void add_input(fn::AttributesRef attributes, - fn::MFParamsBuilder ¶ms, - ResourceCollector &resources) const = 0; -}; - -class ParticleFunction { - private: - const fn::MultiFunction *global_fn_; - const fn::MultiFunction *per_particle_fn_; - Array global_inputs_; - Array per_particle_inputs_; - Array output_is_global_; - Vector global_output_indices_; - Vector per_particle_output_indices_; - Vector output_types_; - Vector output_names_; - - friend class ParticleFunctionEvaluator; - - public: - ParticleFunction(const fn::MultiFunction *global_fn, - const fn::MultiFunction *per_particle_fn, - Span global_inputs, - Span per_particle_inputs, - Span output_is_global) - : global_fn_(global_fn), - per_particle_fn_(per_particle_fn), - global_inputs_(global_inputs), - per_particle_inputs_(per_particle_inputs), - output_is_global_(output_is_global) - { - for (uint i : output_is_global_.index_range()) { - if (output_is_global_[i]) { - uint param_index = global_inputs_.size() + global_output_indices_.size(); - fn::MFParamType param_type = global_fn_->param_type(param_index); - BLI_assert(param_type.is_output()); - output_types_.append(param_type.data_type()); - output_names_.append(global_fn_->param_name(param_index)); - global_output_indices_.append(i); - } - else { - uint param_index = per_particle_inputs_.size() + per_particle_output_indices_.size(); - fn::MFParamType param_type = per_particle_fn_->param_type(param_index); - BLI_assert(param_type.is_output()); - output_types_.append(param_type.data_type()); - output_names_.append(per_particle_fn_->param_name(param_index)); - per_particle_output_indices_.append(i); - } - } - } -}; - -class ParticleFunctionEvaluator { - private: - ResourceCollector resources_; - const ParticleFunction &particle_fn_; - IndexMask mask_; - fn::MFContextBuilder global_context_; - fn::MFContextBuilder per_particle_context_; - fn::AttributesRef particle_attributes_; - Vector outputs_; - bool is_computed_ = false; - - public: - ParticleFunctionEvaluator(const ParticleFunction &particle_fn, - IndexMask mask, - fn::AttributesRef particle_attributes) - : particle_fn_(particle_fn), - mask_(mask), - particle_attributes_(particle_attributes), - outputs_(particle_fn_.output_types_.size(), nullptr) - { - } - - ~ParticleFunctionEvaluator() - { - for (uint output_index : outputs_.index_range()) { - void *buffer = outputs_[output_index]; - fn::MFDataType data_type = particle_fn_.output_types_[output_index]; - BLI_assert(data_type.is_single()); /* For now. */ - const fn::CPPType &type = data_type.single_type(); - - if (particle_fn_.output_is_global_[output_index]) { - type.destruct(buffer); - } - else { - type.destruct_indices(outputs_[0], mask_); - } - } - } - - void compute() - { - BLI_assert(!is_computed_); - this->compute_globals(); - this->compute_per_particle(); - is_computed_ = true; - } - - template fn::VSpan get(uint output_index, StringRef expected_name) const - { - return this->get(output_index, expected_name).typed(); - } - - fn::GVSpan get(uint output_index, StringRef expected_name) const - { -#ifdef DEBUG - StringRef real_name = particle_fn_.output_names_[output_index]; - BLI_assert(expected_name == real_name); - BLI_assert(is_computed_); -#endif - UNUSED_VARS_NDEBUG(expected_name); - const void *buffer = outputs_[output_index]; - const fn::CPPType &type = particle_fn_.output_types_[output_index].single_type(); - if (particle_fn_.output_is_global_[output_index]) { - return fn::GVSpan::FromSingleWithMaxSize(type, buffer); - } - else { - return fn::GVSpan(fn::GSpan(type, buffer, mask_.min_array_size())); - } - } - - private: - void compute_globals() - { - if (particle_fn_.global_fn_ == nullptr) { - return; - } - - fn::MFParamsBuilder params(*particle_fn_.global_fn_, mask_.min_array_size()); - - /* Add input parameters. */ - for (const ParticleFunctionInput *input : particle_fn_.global_inputs_) { - input->add_input(particle_attributes_, params, resources_); - } - - /* Add output parameters. */ - for (uint output_index : particle_fn_.global_output_indices_) { - fn::MFDataType data_type = particle_fn_.output_types_[output_index]; - BLI_assert(data_type.is_single()); /* For now. */ - - const fn::CPPType &type = data_type.single_type(); - void *buffer = resources_.linear_allocator().allocate(type.size(), type.alignment()); - params.add_uninitialized_single_output(fn::GMutableSpan(type, buffer, 1)); - outputs_[output_index] = buffer; - } - - particle_fn_.global_fn_->call({0}, params, global_context_); - } - - void compute_per_particle() - { - if (particle_fn_.per_particle_fn_ == nullptr) { - return; - } - - fn::MFParamsBuilder params(*particle_fn_.per_particle_fn_, mask_.min_array_size()); - - /* Add input parameters. */ - for (const ParticleFunctionInput *input : particle_fn_.per_particle_inputs_) { - input->add_input(particle_attributes_, params, resources_); - } - - /* Add output parameters. */ - for (uint output_index : particle_fn_.per_particle_output_indices_) { - fn::MFDataType data_type = particle_fn_.output_types_[output_index]; - BLI_assert(data_type.is_single()); /* For now. */ - - const fn::CPPType &type = data_type.single_type(); - void *buffer = resources_.linear_allocator().allocate(type.size() * mask_.min_array_size(), - type.alignment()); - params.add_uninitialized_single_output( - fn::GMutableSpan(type, buffer, mask_.min_array_size())); - outputs_[output_index] = buffer; - } - - particle_fn_.per_particle_fn_->call(mask_, params, global_context_); - } -}; - class ParticleAttributeInput : public ParticleFunctionInput { private: std::string attribute_name_; -- cgit v1.2.3