//============================================================================ // Copyright (c) Kitware, Inc. // All rights reserved. // See LICENSE.txt for details. // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notice for more information. //============================================================================ #include #include #include #include #include #include #include namespace vtkm { namespace filter { namespace internal { template struct SupportsPreExecute { template ().PreExecute( std::declval(), std::declval>()))> static std::true_type has(int); template static std::false_type has(...); using type = decltype(has(0)); }; template struct SupportsPostExecute { template ().PostExecute( std::declval(), std::declval(), std::declval>()))> static std::true_type has(int); template static std::false_type has(...); using type = decltype(has(0)); }; template struct SupportsPrepareForExecution { template ().PrepareForExecution( std::declval(), std::declval>()))> static std::true_type has(int); template static std::false_type has(...); using type = decltype(has(0)); }; template struct SupportsMapFieldOntoOutput { template ().MapFieldOntoOutput( std::declval(), std::declval(), std::declval>()))> static std::true_type has(int); template static std::false_type has(...); using type = decltype(has(0)); }; //-------------------------------------------------------------------------------- template void CallPreExecuteInternal(std::true_type, Derived* self, Args&&... args) { return self->PreExecute(std::forward(args)...); } //-------------------------------------------------------------------------------- template void CallPreExecuteInternal(std::false_type, Derived*, Args&&...) { } //-------------------------------------------------------------------------------- template void CallPreExecute(Derived* self, const InputType& input, const vtkm::filter::PolicyBase& policy) { using call_supported_t = typename SupportsPreExecute::type; CallPreExecuteInternal(call_supported_t(), self, input, policy); } //-------------------------------------------------------------------------------- template void CallMapFieldOntoOutputInternal(std::true_type, Derived* self, const vtkm::cont::DataSet& input, vtkm::cont::DataSet& output, const vtkm::filter::PolicyBase& policy) { for (vtkm::IdComponent cc = 0; cc < input.GetNumberOfFields(); ++cc) { auto field = input.GetField(cc); if (self->GetFieldsToPass().IsFieldSelected(field)) { self->MapFieldOntoOutput(output, field, policy); } } } //-------------------------------------------------------------------------------- template void CallMapFieldOntoOutputInternal(std::false_type, Derived* self, const vtkm::cont::DataSet& input, vtkm::cont::DataSet& output, const vtkm::filter::PolicyBase&) { // no MapFieldOntoOutput method is present. In that case, we simply copy the // requested input fields to the output. for (vtkm::IdComponent cc = 0; cc < input.GetNumberOfFields(); ++cc) { auto field = input.GetField(cc); if (self->GetFieldsToPass().IsFieldSelected(field)) { output.AddField(field); } } } //-------------------------------------------------------------------------------- template void CallMapFieldOntoOutput(Derived* self, const vtkm::cont::DataSet& input, vtkm::cont::DataSet& output, vtkm::filter::PolicyBase policy) { using call_supported_t = typename SupportsMapFieldOntoOutput::type; CallMapFieldOntoOutputInternal(call_supported_t(), self, input, output, policy); } //-------------------------------------------------------------------------------- // forward declare. template InputType CallPrepareForExecution(Derived* self, const InputType& input, const vtkm::filter::PolicyBase& policy); //-------------------------------------------------------------------------------- template InputType CallPrepareForExecutionInternal(std::true_type, Derived* self, const InputType& input, const vtkm::filter::PolicyBase& policy) { return self->PrepareForExecution(input, policy); } //-------------------------------------------------------------------------------- // specialization for PartitionedDataSet input when `PrepareForExecution` is not provided // by the subclass. we iterate over blocks and execute for each block // individually. template vtkm::cont::PartitionedDataSet CallPrepareForExecutionInternal( std::false_type, Derived* self, const vtkm::cont::PartitionedDataSet& input, const vtkm::filter::PolicyBase& policy) { vtkm::cont::PartitionedDataSet output; for (const auto& inBlock : input) { vtkm::cont::DataSet outBlock = CallPrepareForExecution(self, inBlock, policy); CallMapFieldOntoOutput(self, inBlock, outBlock, policy); output.AppendPartition(outBlock); } return output; } //-------------------------------------------------------------------------------- template InputType CallPrepareForExecution(Derived* self, const InputType& input, const vtkm::filter::PolicyBase& policy) { using call_supported_t = typename SupportsPrepareForExecution::type; return CallPrepareForExecutionInternal(call_supported_t(), self, input, policy); } //-------------------------------------------------------------------------------- template void CallPostExecuteInternal(std::true_type, Derived* self, const InputType& input, InputType& output, const vtkm::filter::PolicyBase& policy) { self->PostExecute(input, output, policy); } //-------------------------------------------------------------------------------- template void CallPostExecuteInternal(std::false_type, Derived*, Args&&...) { } //-------------------------------------------------------------------------------- template void CallPostExecute(Derived* self, const InputType& input, InputType& output, const vtkm::filter::PolicyBase& policy) { using call_supported_t = typename SupportsPostExecute::type; CallPostExecuteInternal(call_supported_t(), self, input, output, policy); } } //---------------------------------------------------------------------------- template inline VTKM_CONT Filter::Filter() : Invoke() , FieldsToPass(vtkm::filter::FieldSelection::MODE_ALL) { } //---------------------------------------------------------------------------- template inline VTKM_CONT Filter::~Filter() { } //---------------------------------------------------------------------------- template inline VTKM_CONT vtkm::cont::DataSet Filter::Execute(const vtkm::cont::DataSet& input) { Derived* self = static_cast(this); vtkm::cont::PartitionedDataSet output = self->Execute(vtkm::cont::PartitionedDataSet(input)); if (output.GetNumberOfPartitions() > 1) { throw vtkm::cont::ErrorFilterExecution("Expecting at most 1 block."); } return output.GetNumberOfPartitions() == 1 ? output.GetPartition(0) : vtkm::cont::DataSet(); } //---------------------------------------------------------------------------- template inline VTKM_CONT vtkm::cont::PartitionedDataSet Filter::Execute( const vtkm::cont::PartitionedDataSet& input) { VTKM_LOG_SCOPE(vtkm::cont::LogLevel::Perf, "Filter (%d partitions): '%s'", (int)input.GetNumberOfPartitions(), vtkm::cont::TypeToString().c_str()); Derived* self = static_cast(this); vtkm::filter::PolicyDefault policy; // Call `void Derived::PreExecute(input, policy)`, if defined. internal::CallPreExecute(self, input, policy); // Call `PrepareForExecution` (which should probably be renamed at some point) vtkm::cont::PartitionedDataSet output = internal::CallPrepareForExecution(self, input, policy); // Call `Derived::PostExecute(input, output, policy)` if defined. internal::CallPostExecute(self, input, output, policy); return output; } //---------------------------------------------------------------------------- template template VTKM_CONT vtkm::cont::DataSet Filter::Execute( const vtkm::cont::DataSet& input, vtkm::filter::PolicyBase policy) { Derived* self = static_cast(this); VTKM_DEPRECATED_SUPPRESS_BEGIN vtkm::cont::PartitionedDataSet output = self->Execute(vtkm::cont::PartitionedDataSet(input), policy); VTKM_DEPRECATED_SUPPRESS_END if (output.GetNumberOfPartitions() > 1) { throw vtkm::cont::ErrorFilterExecution("Expecting at most 1 block."); } return output.GetNumberOfPartitions() == 1 ? output.GetPartition(0) : vtkm::cont::DataSet(); } //---------------------------------------------------------------------------- template template VTKM_CONT vtkm::cont::PartitionedDataSet Filter::Execute( const vtkm::cont::PartitionedDataSet& input, vtkm::filter::PolicyBase policy) { VTKM_LOG_SCOPE(vtkm::cont::LogLevel::Perf, "Filter (%d partitions): '%s'", (int)input.GetNumberOfPartitions(), vtkm::cont::TypeToString().c_str()); Derived* self = static_cast(this); // Call `void Derived::PreExecute(input, policy)`, if defined. internal::CallPreExecute(self, input, policy); // Call `PrepareForExecution` (which should probably be renamed at some point) vtkm::cont::PartitionedDataSet output = internal::CallPrepareForExecution(self, input, policy); // Call `Derived::PostExecute(input, output, policy)` if defined. internal::CallPostExecute(self, input, output, policy); return output; } //---------------------------------------------------------------------------- template template inline VTKM_CONT void Filter::MapFieldsToPass( const vtkm::cont::DataSet& input, vtkm::cont::DataSet& output, vtkm::filter::PolicyBase policy) { Derived* self = static_cast(this); for (vtkm::IdComponent cc = 0; cc < input.GetNumberOfFields(); ++cc) { auto field = input.GetField(cc); if (this->GetFieldsToPass().IsFieldSelected(field)) { internal::CallMapFieldOntoOutput(self, output, field, policy); } } } } }