Deprecated virutal methods in ImplicitFunctions

The `ImplicitFunction` classes are now trivial classes that can be
passed among host and devices. Because of this, we now need to know the
type of the `ImplicitFunction` in order to use it.

The old functionality still exists (when virtual methods are still being
compiled), but will give deprecation warnings. It is also not possible
to get a pointer from `ImplicitFunctionHandle` and cast it back to the
original data type (because the type changed). This is a weird testing
feature that makes little sense in practice.

Also unsupported in the deprecated classes is the ability to change
the object and have those changes reflected in the handle. This is
unfortunate, but it would have been difficult to implement this
feature that is going away and only appears to be used in some of
the tests.
This commit is contained in:
Kenneth Moreland 2021-02-18 14:27:00 -07:00
parent 561db99b30
commit 0cddbef0b9
4 changed files with 347 additions and 142 deletions

@ -248,50 +248,35 @@ public:
}
};
template <typename ImplicitFunction>
class EvaluateImplicitFunction : public vtkm::worklet::WorkletMapField
{
public:
using ControlSignature = void(FieldIn, FieldOut);
using ExecutionSignature = void(_1, _2);
using ControlSignature = void(FieldIn, FieldOut, ExecObject);
using ExecutionSignature = void(_1, _2, _3);
EvaluateImplicitFunction(const ImplicitFunction* function)
: Function(function)
template <typename VecType, typename ScalarType, typename FunctionType>
VTKM_EXEC void operator()(const VecType& point,
ScalarType& val,
const FunctionType& function) const
{
val = function->Value(point);
}
template <typename VecType, typename ScalarType>
VTKM_EXEC void operator()(const VecType& point, ScalarType& val) const
{
val = this->Function->Value(point);
}
private:
const ImplicitFunction* Function;
};
template <typename T1, typename T2>
class Evaluate2ImplicitFunctions : public vtkm::worklet::WorkletMapField
{
public:
using ControlSignature = void(FieldIn, FieldOut);
using ExecutionSignature = void(_1, _2);
using ControlSignature = void(FieldIn, FieldOut, ExecObject, ExecObject);
using ExecutionSignature = void(_1, _2, _3, _4);
Evaluate2ImplicitFunctions(const T1* f1, const T2* f2)
: Function1(f1)
, Function2(f2)
template <typename VecType, typename ScalarType, typename FType1, typename FType2>
VTKM_EXEC void operator()(const VecType& point,
ScalarType& val,
const FType1& function1,
const FType2& function2) const
{
val = function1->Value(point) + function2->Value(point);
}
template <typename VecType, typename ScalarType>
VTKM_EXEC void operator()(const VecType& point, ScalarType& val) const
{
val = this->Function1->Value(point) + this->Function2->Value(point);
}
private:
const T1* Function1;
const T2* Function2;
};
struct PassThroughFunctor
@ -821,7 +806,7 @@ static ImplicitFunctionBenchData MakeImplicitFunctionBenchData()
void BenchImplicitFunction(::benchmark::State& state)
{
using EvalWorklet = EvaluateImplicitFunction<vtkm::Sphere>;
using EvalWorklet = EvaluateImplicitFunction;
const vtkm::cont::DeviceAdapterId device = Config.Device;
@ -835,8 +820,7 @@ void BenchImplicitFunction(::benchmark::State& state)
vtkm::cont::Token token;
auto handle = vtkm::cont::make_ImplicitFunctionHandle(data.Sphere1);
auto function = static_cast<const vtkm::Sphere*>(handle.PrepareForExecution(device, token));
EvalWorklet eval(function);
EvalWorklet eval;
vtkm::cont::Timer timer{ device };
vtkm::cont::Invoker invoker{ device };
@ -845,7 +829,7 @@ void BenchImplicitFunction(::benchmark::State& state)
{
(void)_;
timer.Start();
invoker(eval, data.Points, data.Result);
invoker(eval, data.Points, data.Result, handle);
timer.Stop();
state.SetIterationTime(timer.GetElapsedTime());
@ -855,7 +839,7 @@ VTKM_BENCHMARK(BenchImplicitFunction);
void BenchVirtualImplicitFunction(::benchmark::State& state)
{
using EvalWorklet = EvaluateImplicitFunction<vtkm::ImplicitFunction>;
using EvalWorklet = EvaluateImplicitFunction;
const vtkm::cont::DeviceAdapterId device = Config.Device;
@ -869,7 +853,7 @@ void BenchVirtualImplicitFunction(::benchmark::State& state)
vtkm::cont::Token token;
auto sphere = vtkm::cont::make_ImplicitFunctionHandle(data.Sphere1);
EvalWorklet eval(sphere.PrepareForExecution(device, token));
EvalWorklet eval;
vtkm::cont::Timer timer{ device };
vtkm::cont::Invoker invoker{ device };
@ -878,7 +862,7 @@ void BenchVirtualImplicitFunction(::benchmark::State& state)
{
(void)_;
timer.Start();
invoker(eval, data.Points, data.Result);
invoker(eval, data.Points, data.Result, sphere);
timer.Stop();
state.SetIterationTime(timer.GetElapsedTime());
@ -888,7 +872,7 @@ VTKM_BENCHMARK(BenchVirtualImplicitFunction);
void Bench2ImplicitFunctions(::benchmark::State& state)
{
using EvalWorklet = Evaluate2ImplicitFunctions<vtkm::Sphere, vtkm::Sphere>;
using EvalWorklet = Evaluate2ImplicitFunctions;
const vtkm::cont::DeviceAdapterId device = Config.Device;
@ -903,9 +887,7 @@ void Bench2ImplicitFunctions(::benchmark::State& state)
vtkm::cont::Token token;
auto h1 = vtkm::cont::make_ImplicitFunctionHandle(data.Sphere1);
auto h2 = vtkm::cont::make_ImplicitFunctionHandle(data.Sphere2);
auto f1 = static_cast<const vtkm::Sphere*>(h1.PrepareForExecution(device, token));
auto f2 = static_cast<const vtkm::Sphere*>(h2.PrepareForExecution(device, token));
EvalWorklet eval(f1, f2);
EvalWorklet eval;
vtkm::cont::Timer timer{ device };
vtkm::cont::Invoker invoker{ device };
@ -914,7 +896,7 @@ void Bench2ImplicitFunctions(::benchmark::State& state)
{
(void)_;
timer.Start();
invoker(eval, data.Points, data.Result);
invoker(eval, data.Points, data.Result, h1, h2);
timer.Stop();
state.SetIterationTime(timer.GetElapsedTime());
@ -924,7 +906,7 @@ VTKM_BENCHMARK(Bench2ImplicitFunctions);
void Bench2VirtualImplicitFunctions(::benchmark::State& state)
{
using EvalWorklet = Evaluate2ImplicitFunctions<vtkm::ImplicitFunction, vtkm::ImplicitFunction>;
using EvalWorklet = Evaluate2ImplicitFunctions;
const vtkm::cont::DeviceAdapterId device = Config.Device;
@ -939,7 +921,7 @@ void Bench2VirtualImplicitFunctions(::benchmark::State& state)
vtkm::cont::Token token;
auto s1 = vtkm::cont::make_ImplicitFunctionHandle(data.Sphere1);
auto s2 = vtkm::cont::make_ImplicitFunctionHandle(data.Sphere2);
EvalWorklet eval(s1.PrepareForExecution(device, token), s2.PrepareForExecution(device, token));
EvalWorklet eval;
vtkm::cont::Timer timer{ device };
vtkm::cont::Invoker invoker{ device };
@ -948,7 +930,7 @@ void Bench2VirtualImplicitFunctions(::benchmark::State& state)
{
(void)_;
timer.Start();
invoker(eval, data.Points, data.Result);
invoker(eval, data.Points, data.Result, s1, s2);
timer.Stop();
state.SetIterationTime(timer.GetElapsedTime());

@ -11,15 +11,21 @@
#define vtk_m_ImplicitFunction_h
#include <vtkm/Bounds.h>
#include <vtkm/Deprecated.h>
#include <vtkm/Math.h>
#include <vtkm/VectorAnalysis.h>
#include <vtkm/VirtualObjectBase.h>
// For interface class only.
#include <vtkm/cont/ExecutionAndControlObjectBase.h>
namespace vtkm
{
//============================================================================
class VTKM_ALWAYS_EXPORT ImplicitFunction : public vtkm::VirtualObjectBase
#ifndef VTKM_NO_DEPRECATED_VIRTUAL
class VTKM_DEPRECATED(1.6, "ImplicitFunction with virtual methods no longer supported.")
VTKM_ALWAYS_EXPORT ImplicitFunction : public vtkm::VirtualObjectBase
{
public:
using Scalar = vtkm::FloatDefault;
@ -38,13 +44,51 @@ public:
return this->Gradient(Vector(x, y, z));
}
};
#endif // VTKM_NO_DEPRECATED_VIRTUAL
//============================================================================
namespace internal
{
/// \brief Base class for all `ImplicitFunction` classes.
///
/// `ImplicitFunctionBase` uses the curiously recurring template pattern (CRTP). Subclasses
/// must provide their own type for the template parameter. Subclasses must implement
/// `Value` and `Gradient` methods.
///
/// Also, all subclasses must be trivially copiable. This is so they can be copied among
/// host and devices.
///
template <typename Derived>
class ImplicitFunctionBase : public vtkm::cont::ExecutionAndControlObjectBase
{
public:
using Scalar = vtkm::FloatDefault;
using Vector = vtkm::Vec<Scalar, 3>;
VTKM_EXEC_CONT Scalar Value(Scalar x, Scalar y, Scalar z) const
{
return reinterpret_cast<const Derived*>(this)->Value(Vector(x, y, z));
}
VTKM_EXEC_CONT Vector Gradient(Scalar x, Scalar y, Scalar z) const
{
return reinterpret_cast<const Derived*>(this)->Gradient(Vector(x, y, z));
}
};
} // namespace vtkm::internal
//============================================================================
#ifndef VTKM_NO_DEPRECATED_VIRTUAL
VTKM_DEPRECATED_SUPPRESS_BEGIN
/// A helpful functor that calls the (virtual) value method of a given ImplicitFunction. Can be
/// passed to things that expect a functor instead of an ImplictFunction class (like an array
/// transform).
///
class VTKM_ALWAYS_EXPORT ImplicitFunctionValue
class VTKM_DEPRECATED(1.6,
"Use ImplicitFunctionValueFunctor.") VTKM_ALWAYS_EXPORT ImplicitFunctionValue
{
public:
using Scalar = vtkm::ImplicitFunction::Scalar;
@ -73,7 +117,8 @@ private:
/// passed to things that expect a functor instead of an ImplictFunction class (like an array
/// transform).
///
class VTKM_ALWAYS_EXPORT ImplicitFunctionGradient
class VTKM_DEPRECATED(1.6, "Use ImplicitFunctionGradientFunctor.")
VTKM_ALWAYS_EXPORT ImplicitFunctionGradient
{
public:
using Scalar = vtkm::ImplicitFunction::Scalar;
@ -98,6 +143,80 @@ private:
const vtkm::ImplicitFunction* Function;
};
VTKM_DEPRECATED_SUPPRESS_END
#endif // VTKM_NO_DEPRECATED_VIRTUAL
//============================================================================
/// A helpful functor that calls the value method of a given `ImplicitFunction`. Can be
/// passed to things that expect a functor instead of an `ImplictFunction` class (like an array
/// transform).
///
template <typename FunctionType>
class ImplicitFunctionValueFunctor
{
public:
using Scalar = typename FunctionType::Scalar;
using Vector = typename FunctionType::Vector;
VTKM_EXEC_CONT ImplicitFunctionValueFunctor() = default;
VTKM_EXEC_CONT ImplicitFunctionValueFunctor(
const vtkm::internal::ImplicitFunctionBase<FunctionType>& function)
: Function(reinterpret_cast<const FunctionType&>(function))
{
}
VTKM_EXEC_CONT Scalar operator()(const Vector& point) const
{
return this->Function.Value(point);
}
private:
FunctionType Function;
};
template <typename FunctionType>
vtkm::ImplicitFunctionValueFunctor<FunctionType> make_ImplicitFunctionValueFunctor(
const vtkm::internal::ImplicitFunctionBase<FunctionType>& function)
{
return ImplicitFunctionValueFunctor<FunctionType>(function);
}
/// A helpful functor that calls the gradient method of a given `ImplicitFunction`. Can be
/// passed to things that expect a functor instead of an `ImplictFunction` class (like an array
/// transform).
///
template <typename FunctionType>
class ImplicitFunctionGradientFunctor
{
public:
using Scalar = typename FunctionType::Scalar;
using Vector = typename FunctionType::Vector;
VTKM_EXEC_CONT ImplicitFunctionGradientFunctor() = default;
VTKM_EXEC_CONT ImplicitFunctionGradientFunctor(
const vtkm::internal::ImplicitFunctionBase<FunctionType>& function)
: Function(reinterpret_cast<const FunctionType&>(function))
{
}
VTKM_EXEC_CONT Vector operator()(const Vector& point) const
{
return this->Function->Gradient(point);
}
private:
FunctionType Function;
};
template <typename FunctionType>
vtkm::ImplicitFunctionGradientFunctor<FunctionType> make_ImplicitFunctionGradientFunctor(
const vtkm::internal::ImplicitFunctionBase<FunctionType>& function)
{
return ImplicitFunctionGradientFunctor<FunctionType>(function);
}
//============================================================================
/// \brief Implicit function for a box
///
@ -106,7 +225,7 @@ private:
/// meeting along shared edges and all faces are orthogonal to the x-y-z
/// coordinate axes.
class VTKM_ALWAYS_EXPORT Box : public ImplicitFunction
class VTKM_ALWAYS_EXPORT Box : public internal::ImplicitFunctionBase<Box>
{
public:
/// \brief Construct box with center at (0,0,0) and each side of length 1.0.
@ -130,17 +249,9 @@ public:
VTKM_CONT Box(const vtkm::Bounds& bounds) { this->SetBounds(bounds); }
VTKM_CONT void SetMinPoint(const Vector& point)
{
this->MinPoint = point;
this->Modified();
}
VTKM_CONT void SetMinPoint(const Vector& point) { this->MinPoint = point; }
VTKM_CONT void SetMaxPoint(const Vector& point)
{
this->MaxPoint = point;
this->Modified();
}
VTKM_CONT void SetMaxPoint(const Vector& point) { this->MaxPoint = point; }
VTKM_EXEC_CONT const Vector& GetMinPoint() const { return this->MinPoint; }
@ -159,7 +270,7 @@ public:
vtkm::Range(this->MinPoint[2], this->MaxPoint[2]));
}
VTKM_EXEC_CONT Scalar Value(const Vector& point) const final
VTKM_EXEC_CONT Scalar Value(const Vector& point) const
{
Scalar minDistance = vtkm::NegativeInfinity32();
Scalar diff, t, dist;
@ -227,7 +338,7 @@ public:
}
}
VTKM_EXEC_CONT Vector Gradient(const Vector& point) const final
VTKM_EXEC_CONT Vector Gradient(const Vector& point) const
{
vtkm::IdComponent minAxis = 0;
Scalar dist = 0.0;
@ -349,6 +460,11 @@ public:
return normal;
}
VTKM_DEPRECATED(1.6, "ImplicitFunctions are no longer pointers. Use . operator.")
VTKM_EXEC Box* operator->() { return this; }
VTKM_DEPRECATED(1.6, "ImplicitFunctions are no longer pointers. Use . operator.")
VTKM_EXEC const Box* operator->() const { return this; }
private:
Vector MinPoint;
Vector MaxPoint;
@ -365,7 +481,7 @@ private:
///
/// Note that the cylinder is infinite in extent.
///
class VTKM_ALWAYS_EXPORT Cylinder final : public vtkm::ImplicitFunction
class VTKM_ALWAYS_EXPORT Cylinder : public vtkm::internal::ImplicitFunctionBase<Cylinder>
{
public:
/// Construct cylinder radius of 0.5; centered at origin with axis
@ -391,32 +507,20 @@ public:
{
}
VTKM_CONT void SetCenter(const Vector& center)
{
this->Center = center;
this->Modified();
}
VTKM_CONT void SetCenter(const Vector& center) { this->Center = center; }
VTKM_CONT void SetAxis(const Vector& axis)
{
this->Axis = vtkm::Normal(axis);
this->Modified();
}
VTKM_CONT void SetAxis(const Vector& axis) { this->Axis = vtkm::Normal(axis); }
VTKM_CONT void SetRadius(Scalar radius)
{
this->Radius = radius;
this->Modified();
}
VTKM_CONT void SetRadius(Scalar radius) { this->Radius = radius; }
VTKM_EXEC_CONT Scalar Value(const Vector& point) const final
VTKM_EXEC_CONT Scalar Value(const Vector& point) const
{
Vector x2c = point - this->Center;
FloatDefault proj = vtkm::Dot(this->Axis, x2c);
return vtkm::Dot(x2c, x2c) - (proj * proj) - (this->Radius * this->Radius);
}
VTKM_EXEC_CONT Vector Gradient(const Vector& point) const final
VTKM_EXEC_CONT Vector Gradient(const Vector& point) const
{
Vector x2c = point - this->Center;
FloatDefault t = this->Axis[0] * x2c[0] + this->Axis[1] * x2c[1] + this->Axis[2] * x2c[2];
@ -424,6 +528,10 @@ public:
return (point - closestPoint) * FloatDefault(2);
}
VTKM_DEPRECATED(1.6, "ImplicitFunctions are no longer pointers. Use . operator.")
VTKM_EXEC Cylinder* operator->() { return this; }
VTKM_DEPRECATED(1.6, "ImplicitFunctions are no longer pointers. Use . operator.")
VTKM_EXEC const Cylinder* operator->() const { return this; }
private:
Vector Center;
@ -433,7 +541,7 @@ private:
//============================================================================
/// \brief Implicit function for a frustum
class VTKM_ALWAYS_EXPORT Frustum final : public vtkm::ImplicitFunction
class VTKM_ALWAYS_EXPORT Frustum : public vtkm::internal::ImplicitFunctionBase<Frustum>
{
public:
/// \brief Construct axis-aligned frustum with center at (0,0,0) and each side of length 1.0.
@ -456,7 +564,6 @@ public:
{
this->Normals[index] = normals[index];
}
this->Modified();
}
VTKM_EXEC void SetPlane(int idx, const Vector& point, const Vector& normal)
@ -464,7 +571,6 @@ public:
VTKM_ASSERT((idx >= 0) && (idx < 6));
this->Points[idx] = point;
this->Normals[idx] = normal;
this->Modified();
}
VTKM_EXEC_CONT void GetPlanes(Vector points[6], Vector normals[6]) const
@ -502,10 +608,9 @@ public:
this->Points[i] = v0;
this->Normals[i] = vtkm::Normal(vtkm::TriangleNormal(v0, v1, v2));
}
this->Modified();
}
VTKM_EXEC_CONT Scalar Value(const Vector& point) const final
VTKM_EXEC_CONT Scalar Value(const Vector& point) const
{
Scalar maxVal = vtkm::NegativeInfinity<Scalar>();
for (vtkm::Id index : { 0, 1, 2, 3, 4, 5 })
@ -518,7 +623,7 @@ public:
return maxVal;
}
VTKM_EXEC_CONT Vector Gradient(const Vector& point) const final
VTKM_EXEC_CONT Vector Gradient(const Vector& point) const
{
Scalar maxVal = vtkm::NegativeInfinity<Scalar>();
vtkm::Id maxValIdx = 0;
@ -536,6 +641,11 @@ public:
return this->Normals[maxValIdx];
}
VTKM_DEPRECATED(1.6, "ImplicitFunctions are no longer pointers. Use . operator.")
VTKM_EXEC Frustum* operator->() { return this; }
VTKM_DEPRECATED(1.6, "ImplicitFunctions are no longer pointers. Use . operator.")
VTKM_EXEC const Frustum* operator->() const { return this; }
private:
Vector Points[6] = { { -0.5f, 0.0f, 0.0f }, { 0.5f, 0.0f, 0.0f }, { 0.0f, -0.5f, 0.0f },
{ 0.0f, 0.5f, 0.0f }, { 0.0f, 0.0f, -0.5f }, { 0.0f, 0.0f, 0.5f } };
@ -550,7 +660,7 @@ private:
/// The normal does not have to be a unit vector. The implicit function will
/// still evaluate to 0 at the plane, but the values outside the plane
/// (and the gradient) will be scaled by the length of the normal vector.
class VTKM_ALWAYS_EXPORT Plane final : public vtkm::ImplicitFunction
class VTKM_ALWAYS_EXPORT Plane : public vtkm::internal::ImplicitFunctionBase<Plane>
{
public:
/// Construct plane passing through origin and normal to z-axis.
@ -574,27 +684,24 @@ public:
{
}
VTKM_CONT void SetOrigin(const Vector& origin)
{
this->Origin = origin;
this->Modified();
}
VTKM_CONT void SetOrigin(const Vector& origin) { this->Origin = origin; }
VTKM_CONT void SetNormal(const Vector& normal)
{
this->Normal = normal;
this->Modified();
}
VTKM_CONT void SetNormal(const Vector& normal) { this->Normal = normal; }
VTKM_EXEC_CONT const Vector& GetOrigin() const { return this->Origin; }
VTKM_EXEC_CONT const Vector& GetNormal() const { return this->Normal; }
VTKM_EXEC_CONT Scalar Value(const Vector& point) const final
VTKM_EXEC_CONT Scalar Value(const Vector& point) const
{
return vtkm::Dot(point - this->Origin, this->Normal);
}
VTKM_EXEC_CONT Vector Gradient(const Vector&) const final { return this->Normal; }
VTKM_EXEC_CONT Vector Gradient(const Vector&) const { return this->Normal; }
VTKM_DEPRECATED(1.6, "ImplicitFunctions are no longer pointers. Use . operator.")
VTKM_EXEC Plane* operator->() { return this; }
VTKM_DEPRECATED(1.6, "ImplicitFunctions are no longer pointers. Use . operator.")
VTKM_EXEC const Plane* operator->() const { return this; }
private:
Vector Origin;
@ -609,7 +716,7 @@ private:
/// The value of the sphere implicit function is the square of the distance
/// from the center biased by the radius (so the surface of the sphere is
/// at value 0).
class VTKM_ALWAYS_EXPORT Sphere final : public vtkm::ImplicitFunction
class VTKM_ALWAYS_EXPORT Sphere : public vtkm::internal::ImplicitFunctionBase<Sphere>
{
public:
/// Construct sphere with center at (0,0,0) and radius = 0.5.
@ -632,32 +739,29 @@ public:
{
}
VTKM_CONT void SetRadius(Scalar radius)
{
this->Radius = radius;
this->Modified();
}
VTKM_CONT void SetRadius(Scalar radius) { this->Radius = radius; }
VTKM_CONT void SetCenter(const Vector& center)
{
this->Center = center;
this->Modified();
}
VTKM_CONT void SetCenter(const Vector& center) { this->Center = center; }
VTKM_EXEC_CONT Scalar GetRadius() const { return this->Radius; }
VTKM_EXEC_CONT const Vector& GetCenter() const { return this->Center; }
VTKM_EXEC_CONT Scalar Value(const Vector& point) const final
VTKM_EXEC_CONT Scalar Value(const Vector& point) const
{
return vtkm::MagnitudeSquared(point - this->Center) - (this->Radius * this->Radius);
}
VTKM_EXEC_CONT Vector Gradient(const Vector& point) const final
VTKM_EXEC_CONT Vector Gradient(const Vector& point) const
{
return Scalar(2) * (point - this->Center);
}
VTKM_DEPRECATED(1.6, "ImplicitFunctions are no longer pointers. Use . operator.")
VTKM_EXEC Sphere* operator->() { return this; }
VTKM_DEPRECATED(1.6, "ImplicitFunctions are no longer pointers. Use . operator.")
VTKM_EXEC const Sphere* operator->() const { return this; }
private:
Scalar Radius;
Vector Center;
@ -665,18 +769,4 @@ private:
} // namespace vtkm
// Cuda seems to have a bug where it expects the template class VirtualObjectTransfer
// to be instantiated in a consistent order among all the translation units of an
// executable. Failing to do so results in random crashes and incorrect results.
// We workaroud this issue by explicitly instantiating VirtualObjectTransfer for
// all the implicit functions here.
#ifdef VTKM_CUDA
#include <vtkm/cont/internal/VirtualObjectTransferInstantiate.h>
VTKM_EXPLICITLY_INSTANTIATE_TRANSFER(vtkm::Box);
VTKM_EXPLICITLY_INSTANTIATE_TRANSFER(vtkm::Cylinder);
VTKM_EXPLICITLY_INSTANTIATE_TRANSFER(vtkm::Frustum);
VTKM_EXPLICITLY_INSTANTIATE_TRANSFER(vtkm::Plane);
VTKM_EXPLICITLY_INSTANTIATE_TRANSFER(vtkm::Sphere);
#endif
#endif //vtk_m_ImplicitFunction_h

@ -13,13 +13,55 @@
#include <vtkm/ImplicitFunction.h>
#include <vtkm/cont/VirtualObjectHandle.h>
#ifdef VTKM_NO_DEPRECATED_VIRTUAL
#error "ImplicitFunction with virtual methods is removed. Do not include ImplicitFunctionHeader.h"
#endif
VTKM_DEPRECATED_SUPPRESS_BEGIN
namespace vtkm
{
namespace cont
{
class VTKM_ALWAYS_EXPORT ImplicitFunctionHandle
: public vtkm::cont::VirtualObjectHandle<vtkm::ImplicitFunction>
namespace detail
{
// Wrong namespace, but it's only for deprecated code.
template <typename FunctionType>
class VTKM_ALWAYS_EXPORT ImplicitFunctionBaseExecWrapper : public vtkm::ImplicitFunction
{
FunctionType Function;
public:
VTKM_CONT ImplicitFunctionBaseExecWrapper(const FunctionType& function)
: Function(function)
{
}
VTKM_EXEC_CONT virtual ~ImplicitFunctionBaseExecWrapper() noexcept override
{
// This must not be defaulted, since defaulted virtual destructors are
// troublesome with CUDA __host__ __device__ markup.
}
VTKM_EXEC_CONT virtual Scalar Value(const Vector& point) const override
{
return this->Function.Value(point);
}
VTKM_EXEC_CONT virtual Vector Gradient(const Vector& point) const override
{
return this->Function.Gradient(point);
}
};
} // vtkm::cont::detail
class VTKM_DEPRECATED(1.6,
"ImplicitFunctions with virtual methods are no longer supported. "
"Use vtkm::ImplicitFunctionX classes directly.") VTKM_ALWAYS_EXPORT
ImplicitFunctionHandle : public vtkm::cont::VirtualObjectHandle<vtkm::ImplicitFunction>
{
private:
using Superclass = vtkm::cont::VirtualObjectHandle<vtkm::ImplicitFunction>;
@ -27,21 +69,70 @@ private:
public:
ImplicitFunctionHandle() = default;
template <typename ImplicitFunctionType,
typename DeviceAdapterList = VTKM_DEFAULT_DEVICE_ADAPTER_LIST>
explicit ImplicitFunctionHandle(ImplicitFunctionType* function,
template <typename VirtualDerivedType,
typename DeviceAdapterList = VTKM_DEFAULT_DEVICE_ADAPTER_LIST,
typename = typename std::enable_if<
std::is_base_of<vtkm::ImplicitFunction, VirtualDerivedType>::value>::type>
explicit ImplicitFunctionHandle(VirtualDerivedType* function,
bool acquireOwnership = true,
DeviceAdapterList devices = DeviceAdapterList())
: Superclass(function, acquireOwnership, devices)
{
}
template <typename ImplicitFunctionType,
typename DeviceAdapterList = VTKM_DEFAULT_DEVICE_ADAPTER_LIST>
explicit ImplicitFunctionHandle(
vtkm::internal::ImplicitFunctionBase<ImplicitFunctionType>* function,
bool acquireOwnership = true,
DeviceAdapterList devices = DeviceAdapterList())
: Superclass(new detail::ImplicitFunctionBaseExecWrapper<ImplicitFunctionType>(
*reinterpret_cast<ImplicitFunctionType*>(function)),
true,
devices)
{
if (acquireOwnership)
{
delete function;
}
}
template <typename ImplicitFunctionType,
typename DeviceAdapterList = VTKM_DEFAULT_DEVICE_ADAPTER_LIST>
VTKM_CONT void Reset(vtkm::internal::ImplicitFunctionBase<ImplicitFunctionType>* function,
bool acquireOwnership = true,
DeviceAdapterList devices = DeviceAdapterList{})
{
this->Reset(new detail::ImplicitFunctionBaseExecWrapper<ImplicitFunctionType>(
*reinterpret_cast<ImplicitFunctionType*>(function)),
true,
devices);
if (acquireOwnership)
{
delete function;
}
}
template <typename VirtualDerivedType,
typename DeviceAdapterList = VTKM_DEFAULT_DEVICE_ADAPTER_LIST,
typename = typename std::enable_if<
std::is_base_of<vtkm::ImplicitFunction, VirtualDerivedType>::value>::type>
VTKM_CONT void Reset(VirtualDerivedType* derived,
bool acquireOwnership = true,
DeviceAdapterList devices = DeviceAdapterList())
{
this->Superclass::Reset(derived, acquireOwnership, devices);
}
};
template <typename ImplicitFunctionType,
typename DeviceAdapterList = VTKM_DEFAULT_DEVICE_ADAPTER_LIST>
VTKM_DEPRECATED(1.6,
"ImplicitFunctions with virtual methods are no longer supported. "
"Use vtkm::ImplicitFunctionX classes directly.")
VTKM_CONT ImplicitFunctionHandle
make_ImplicitFunctionHandle(ImplicitFunctionType&& func,
DeviceAdapterList devices = DeviceAdapterList())
make_ImplicitFunctionHandle(ImplicitFunctionType&& func,
DeviceAdapterList devices = DeviceAdapterList())
{
using IFType = typename std::remove_reference<ImplicitFunctionType>::type;
return ImplicitFunctionHandle(
@ -49,6 +140,9 @@ make_ImplicitFunctionHandle(ImplicitFunctionType&& func,
}
template <typename ImplicitFunctionType, typename... Args>
VTKM_DEPRECATED(1.6,
"ImplicitFunctions with virtual methods are no longer supported. "
"Use vtkm::ImplicitFunctionX classes directly.")
VTKM_CONT ImplicitFunctionHandle make_ImplicitFunctionHandle(Args&&... args)
{
return ImplicitFunctionHandle(new ImplicitFunctionType(std::forward<Args>(args)...),
@ -68,8 +162,10 @@ VTKM_CONT ImplicitFunctionHandle make_ImplicitFunctionHandle(Args&&... args)
/// ImplicitFunction. Can be passed to things that expect a functor instead of an ImplictFunction
/// class (like an array transform).
///
class VTKM_ALWAYS_EXPORT ImplicitFunctionValueHandle
: public vtkm::cont::ExecutionAndControlObjectBase
class VTKM_DEPRECATED(1.6,
"ImplicitFunctions with virtual methods are no longer supported. "
"Use vtkm::ImplicitFunctionValueFunctor.")
VTKM_ALWAYS_EXPORT ImplicitFunctionValueHandle : public vtkm::cont::ExecutionAndControlObjectBase
{
vtkm::cont::ImplicitFunctionHandle Handle;
@ -107,9 +203,12 @@ public:
template <typename ImplicitFunctionType,
typename DeviceAdapterList = VTKM_DEFAULT_DEVICE_ADAPTER_LIST>
VTKM_DEPRECATED(1.6,
"ImplicitFunctions with virtual methods are no longer supported. "
"Use vtkm::ImplicitFunctionValueFunctor.")
VTKM_CONT ImplicitFunctionValueHandle
make_ImplicitFunctionValueHandle(ImplicitFunctionType&& func,
DeviceAdapterList devices = DeviceAdapterList())
make_ImplicitFunctionValueHandle(ImplicitFunctionType&& func,
DeviceAdapterList devices = DeviceAdapterList())
{
using IFType = typename std::remove_reference<ImplicitFunctionType>::type;
return ImplicitFunctionValueHandle(
@ -117,6 +216,9 @@ make_ImplicitFunctionValueHandle(ImplicitFunctionType&& func,
}
template <typename ImplicitFunctionType, typename... Args>
VTKM_DEPRECATED(1.6,
"ImplicitFunctions with virtual methods are no longer supported. "
"Use vtkm::ImplicitFunctionValueFunctor.")
VTKM_CONT ImplicitFunctionValueHandle make_ImplicitFunctionValueHandle(Args&&... args)
{
return ImplicitFunctionValueHandle(new ImplicitFunctionType(std::forward<Args>(args)...),
@ -125,6 +227,9 @@ VTKM_CONT ImplicitFunctionValueHandle make_ImplicitFunctionValueHandle(Args&&...
}
template <typename ImplicitFunctionType, typename DeviceAdapterList, typename... Args>
VTKM_DEPRECATED(1.6,
"ImplicitFunctions with virtual methods are no longer supported. "
"Use vtkm::ImplicitFunctionValueFunctor.")
VTKM_CONT ImplicitFunctionValueHandle make_ImplicitFunctionValueHandle(Args&&... args)
{
return ImplicitFunctionValueHandle(
@ -133,4 +238,25 @@ VTKM_CONT ImplicitFunctionValueHandle make_ImplicitFunctionValueHandle(Args&&...
}
} // vtkm::cont
// Cuda seems to have a bug where it expects the template class VirtualObjectTransfer
// to be instantiated in a consistent order among all the translation units of an
// executable. Failing to do so results in random crashes and incorrect results.
// We workaroud this issue by explicitly instantiating VirtualObjectTransfer for
// all the implicit functions here.
#ifdef VTKM_CUDA
#include <vtkm/cont/internal/VirtualObjectTransferInstantiate.h>
VTKM_EXPLICITLY_INSTANTIATE_TRANSFER(
vtkm::cont::detail::ImplicitFunctionBaseExecWrapper<vtkm::Box>);
VTKM_EXPLICITLY_INSTANTIATE_TRANSFER(
vtkm::cont::detail::ImplicitFunctionBaseExecWrapper<vtkm::Cylinder>);
VTKM_EXPLICITLY_INSTANTIATE_TRANSFER(
vtkm::cont::detail::ImplicitFunctionBaseExecWrapper<vtkm::Frustum>);
VTKM_EXPLICITLY_INSTANTIATE_TRANSFER(
vtkm::cont::detail::ImplicitFunctionBaseExecWrapper<vtkm::Plane>);
VTKM_EXPLICITLY_INSTANTIATE_TRANSFER(
vtkm::cont::detail::ImplicitFunctionBaseExecWrapper<vtkm::Sphere>);
#endif
VTKM_DEPRECATED_SUPPRESS_END
#endif // vtk_m_cont_ImplicitFunctionHandle_h

@ -180,6 +180,7 @@ private:
std::cout << " Specified min/max box" << std::endl;
box.SetMinPoint({ 0.0f, -0.5f, -0.5f });
box.SetMaxPoint({ 1.5f, 1.5f, 0.5f });
boxHandle.Reset(&box, false);
this->Try(boxHandle,
{ { 0.0f, -0.5f, 0.5f, 0.5f, 0.0f, -0.5f, 0.5f, 0.5f } },
{ { vtkm::Vec3f{ -1.0f, 0.0f, 0.0f },
@ -194,6 +195,7 @@ private:
std::cout << " Specified bounds box" << std::endl;
box.SetBounds({ vtkm::Range(0.0, 1.5), vtkm::Range(-0.5, 1.5), vtkm::Range(-0.5, 0.5) });
boxHandle.Reset(&box, false);
this->Try(boxHandle,
{ { 0.0f, -0.5f, 0.5f, 0.5f, 0.0f, -0.5f, 0.5f, 0.5f } },
{ { vtkm::Vec3f{ -1.0f, 0.0f, 0.0f },
@ -232,6 +234,7 @@ private:
cylinder.SetCenter({ 0.0f, 0.0f, 1.0f });
cylinder.SetAxis({ 0.0f, 1.0f, 0.0f });
cylinder.SetRadius(1.0f);
cylinderHandle.Reset(&cylinder, false);
this->Try(cylinderHandle,
{ { 0.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, -1.0f } },
{ { vtkm::Vec3f{ 0.0f, 0.0f, -2.0f },
@ -248,6 +251,7 @@ private:
cylinder.SetCenter({ 0.0f, 0.0f, 0.0f });
cylinder.SetAxis({ 1.0f, 1.0f, 0.0f });
cylinder.SetRadius(1.0f);
cylinderHandle.Reset(&cylinder, false);
this->Try(cylinderHandle,
{ { -1.0f, -0.5f, 0.5f, 0.0f, -0.5f, -1.0f, 0.0f, 0.5f } },
{ { vtkm::Vec3f{ 0.0f, 0.0f, 0.0f },
@ -278,9 +282,8 @@ private:
{ 1.5f, 1.0f, 0.5f }, // 6
{ 1.5f, 1.0f, -0.5f } // 7
};
vtkm::cont::ImplicitFunctionHandle frustumHandle =
vtkm::cont::make_ImplicitFunctionHandle<vtkm::Frustum>(cornerPoints);
vtkm::Frustum* frustum = static_cast<vtkm::Frustum*>(frustumHandle.Get());
vtkm::Frustum frustum{ cornerPoints };
vtkm::cont::ImplicitFunctionHandle frustumHandle(&frustum, false);
this->Try(frustumHandle,
{ { 0.0f, 0.353553f, 0.5f, 0.5f, 0.0f, 0.0f, 0.5f, 0.5f } },
{ { vtkm::Vec3f{ 0.0f, -1.0f, 0.0f },
@ -301,6 +304,7 @@ private:
{ -1.0f, 0.0f, 0.0f }, { 0.707107f, -0.707107f, 0.0f },
{ 0.0f, 0.0f, -1.0f }, { 0.0f, 0.0f, 1.0f } };
frustum->SetPlanes(planePoints, planeNormals);
frustumHandle.Reset(&frustum, false);
this->Try(frustumHandle,
{ { 0.0f, 0.353553f, 0.5f, 0.5f, -0.5f, 0.0f, 0.5f, 0.5f } },
{ { vtkm::Vec3f{ 0.0f, -1.0f, 0.0f },
@ -321,9 +325,8 @@ private:
<< vtkm::cont::DeviceAdapterTraits<DeviceAdapter>::GetName() << "\n";
std::cout << " Default plane" << std::endl;
vtkm::cont::ImplicitFunctionHandle planeHandle =
vtkm::cont::make_ImplicitFunctionHandle(vtkm::Plane());
vtkm::Plane* plane = static_cast<vtkm::Plane*>(planeHandle.Get());
vtkm::Plane plane;
vtkm::cont::ImplicitFunctionHandle planeHandle = vtkm::cont::make_ImplicitFunctionHandle(plane);
this->Try(planeHandle,
{ { 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f } },
{ { vtkm::Vec3f{ 0.0f, 0.0f, 1.0f },
@ -339,6 +342,7 @@ private:
std::cout << " Normal of length 2" << std::endl;
plane->SetOrigin({ 1.0f, 1.0f, 1.0f });
plane->SetNormal({ 0.0f, 0.0f, 2.0f });
planeHandle.Reset(&plane, false);
this->Try(planeHandle,
{ { -2.0f, -2.0f, 0.0f, 0.0f, -2.0f, -2.0f, 0.0f, 0.0f } },
{ { vtkm::Vec3f{ 0.0f, 0.0f, 2.0f },
@ -354,6 +358,7 @@ private:
std::cout << " Oblique plane" << std::endl;
plane->SetOrigin({ 0.5f, 0.5f, 0.5f });
plane->SetNormal({ 1.0f, 0.0f, 1.0f });
planeHandle.Reset(&plane, false);
this->Try(planeHandle,
{ { -1.0f, 0.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f } },
{ { vtkm::Vec3f{ 1.0f, 0.0f, 1.0f },
@ -368,6 +373,7 @@ private:
std::cout << " Another oblique plane" << std::endl;
plane->SetNormal({ -1.0f, 0.0f, -1.0f });
planeHandle.Reset(&plane, false);
this->Try(planeHandle,
{ { 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, -1.0f, 0.0f } },
{ { vtkm::Vec3f{ -1.0f, 0.0f, -1.0f },
@ -405,6 +411,7 @@ private:
std::cout << " Shifted and scaled sphere" << std::endl;
sphere.SetCenter({ 1.0f, 1.0f, 1.0f });
sphere.SetRadius(1.0f);
sphereHandle.Reset(&sphere, false);
this->Try(sphereHandle,
{ { 2.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, -1.0f, 0.0f } },
{ { vtkm::Vec3f{ -2.0f, -2.0f, -2.0f },