Merge branch 'master' into cmake_refactor

This commit is contained in:
Matthew Letter 2017-11-28 13:36:02 -07:00
commit fac43bd812
103 changed files with 2609 additions and 2282 deletions

@ -1 +1 @@
1.0.0
1.1.0

@ -35,6 +35,7 @@ set(headers
CellShape.h
CellTraits.h
Hash.h
ImplicitFunction.h
ListTag.h
Math.h
Matrix.h
@ -55,6 +56,7 @@ set(headers
VectorAnalysis.h
VecTraits.h
VecVariable.h
VirtualObjectBase.h
UnaryPredicates.h
)

643
vtkm/ImplicitFunction.h Normal file

@ -0,0 +1,643 @@
//============================================================================
// 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.
//
// Copyright 2017 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2017 UT-Battelle, LLC.
// Copyright 2017 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#ifndef vtk_m_ImplicitFunction_h
#define vtk_m_ImplicitFunction_h
#include <vtkm/Math.h>
#include <vtkm/VectorAnalysis.h>
#include <vtkm/VirtualObjectBase.h>
namespace vtkm
{
//============================================================================
class VTKM_ALWAYS_EXPORT ImplicitFunction : public vtkm::VirtualObjectBase
{
public:
using Scalar = vtkm::FloatDefault;
using Vector = vtkm::Vec<Scalar, 3>;
VTKM_EXEC_CONT virtual Scalar Value(const Vector& point) const = 0;
VTKM_EXEC_CONT virtual Vector Gradient(const Vector& point) const = 0;
VTKM_EXEC_CONT Scalar Value(Scalar x, Scalar y, Scalar z) const
{
return this->Value(Vector(x, y, z));
}
VTKM_EXEC_CONT Vector Gradient(Scalar x, Scalar y, Scalar z) const
{
return this->Gradient(Vector(x, y, z));
}
};
//============================================================================
/// 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
{
public:
using Scalar = vtkm::ImplicitFunction::Scalar;
using Vector = vtkm::ImplicitFunction::Vector;
VTKM_EXEC_CONT ImplicitFunctionValue()
: Function(nullptr)
{
}
VTKM_EXEC_CONT ImplicitFunctionValue(const ImplicitFunction* function)
: Function(function)
{
}
VTKM_EXEC_CONT Scalar operator()(const Vector& point) const
{
return this->Function->Value(point);
}
private:
const vtkm::ImplicitFunction* Function;
};
/// A helpful functor that calls the (virtual) gradient 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 ImplicitFunctionGradient
{
public:
using Scalar = vtkm::ImplicitFunction::Scalar;
using Vector = vtkm::ImplicitFunction::Vector;
VTKM_EXEC_CONT ImplicitFunctionGradient()
: Function(nullptr)
{
}
VTKM_EXEC_CONT ImplicitFunctionGradient(const ImplicitFunction* function)
: Function(function)
{
}
VTKM_EXEC_CONT Vector operator()(const Vector& point) const
{
return this->Function->Gradient(point);
}
private:
const vtkm::ImplicitFunction* Function;
};
//============================================================================
/// \brief Implicit function for a box
class VTKM_ALWAYS_EXPORT Box : public ImplicitFunction
{
public:
VTKM_EXEC_CONT Box()
: MinPoint(Vector(Scalar(0)))
, MaxPoint(Vector(Scalar(0)))
{
}
VTKM_EXEC_CONT Box(const Vector& minPoint, const Vector& maxPoint)
: MinPoint(minPoint)
, MaxPoint(maxPoint)
{
}
VTKM_EXEC_CONT Box(Scalar xmin, Scalar xmax, Scalar ymin, Scalar ymax, Scalar zmin, Scalar zmax)
: MinPoint(xmin, ymin, zmin)
, MaxPoint(xmax, ymax, zmax)
{
}
VTKM_CONT void SetMinPoint(const Vector& point)
{
this->MinPoint = point;
this->Modified();
}
VTKM_CONT void SetMaxPoint(const Vector& point)
{
this->MaxPoint = point;
this->Modified();
}
VTKM_EXEC_CONT const Vector& GetMinPoint() const { return this->MinPoint; }
VTKM_EXEC_CONT const Vector& GetMaxPoint() const { return this->MaxPoint; }
VTKM_EXEC_CONT Scalar Value(const Vector& point) const override
{
Scalar minDistance = vtkm::NegativeInfinity32();
Scalar diff, t, dist;
Scalar distance = Scalar(0.0);
vtkm::IdComponent inside = 1;
for (vtkm::IdComponent d = 0; d < 3; d++)
{
diff = this->MaxPoint[d] - this->MinPoint[d];
if (diff != Scalar(0.0))
{
t = (point[d] - this->MinPoint[d]) / diff;
// Outside before the box
if (t < Scalar(0.0))
{
inside = 0;
dist = this->MinPoint[d] - point[d];
}
// Outside after the box
else if (t > Scalar(1.0))
{
inside = 0;
dist = point[d] - this->MaxPoint[d];
}
else
{
// Inside the box in lower half
if (t <= Scalar(0.5))
{
dist = MinPoint[d] - point[d];
}
// Inside the box in upper half
else
{
dist = point[d] - MaxPoint[d];
}
if (dist > minDistance)
{
minDistance = dist;
}
}
}
else
{
dist = vtkm::Abs(point[d] - MinPoint[d]);
if (dist > Scalar(0.0))
{
inside = 0;
}
}
if (dist > Scalar(0.0))
{
distance += dist * dist;
}
}
distance = vtkm::Sqrt(distance);
if (inside)
{
return minDistance;
}
else
{
return distance;
}
}
VTKM_EXEC_CONT Vector Gradient(const Vector& point) const override
{
vtkm::IdComponent minAxis = 0;
Scalar dist = 0.0;
Scalar minDist = vtkm::Infinity32();
vtkm::Vec<vtkm::IdComponent, 3> location;
Vector normal(Scalar(0));
Vector inside(Scalar(0));
Vector outside(Scalar(0));
Vector center((this->MaxPoint + this->MinPoint) * Scalar(0.5));
// Compute the location of the point with respect to the box
// Point will lie in one of 27 separate regions around or within the box
// Gradient vector is computed differently in each of the regions.
for (vtkm::IdComponent d = 0; d < 3; d++)
{
if (point[d] < this->MinPoint[d])
{
// Outside the box low end
location[d] = 0;
outside[d] = -1.0;
}
else if (point[d] > this->MaxPoint[d])
{
// Outside the box high end
location[d] = 2;
outside[d] = 1.0;
}
else
{
location[d] = 1;
if (point[d] <= center[d])
{
// Inside the box low end
dist = point[d] - this->MinPoint[d];
inside[d] = -1.0;
}
else
{
// Inside the box high end
dist = this->MaxPoint[d] - point[d];
inside[d] = 1.0;
}
if (dist < minDist) // dist is negative
{
minDist = dist;
minAxis = d;
}
}
}
vtkm::Id indx = location[0] + 3 * location[1] + 9 * location[2];
switch (indx)
{
// verts - gradient points away from center point
case 0:
case 2:
case 6:
case 8:
case 18:
case 20:
case 24:
case 26:
for (vtkm::IdComponent d = 0; d < 3; d++)
{
normal[d] = point[d] - center[d];
}
vtkm::Normalize(normal);
break;
// edges - gradient points out from axis of cube
case 1:
case 3:
case 5:
case 7:
case 9:
case 11:
case 15:
case 17:
case 19:
case 21:
case 23:
case 25:
for (vtkm::IdComponent d = 0; d < 3; d++)
{
if (outside[d] != 0.0)
{
normal[d] = point[d] - center[d];
}
else
{
normal[d] = 0.0;
}
}
vtkm::Normalize(normal);
break;
// faces - gradient points perpendicular to face
case 4:
case 10:
case 12:
case 14:
case 16:
case 22:
for (vtkm::IdComponent d = 0; d < 3; d++)
{
normal[d] = outside[d];
}
break;
// interior - gradient is perpendicular to closest face
case 13:
normal[0] = normal[1] = normal[2] = 0.0;
normal[minAxis] = inside[minAxis];
break;
default:
VTKM_ASSERT(false);
break;
}
return normal;
}
private:
Vector MinPoint;
Vector MaxPoint;
};
//============================================================================
/// \brief Implicit function for a cylinder
class VTKM_ALWAYS_EXPORT Cylinder : public vtkm::ImplicitFunction
{
public:
VTKM_EXEC_CONT Cylinder()
: Center(Scalar(0))
, Axis(Scalar(1), Scalar(0), Scalar(0))
, Radius(Scalar(0.2))
{
}
VTKM_EXEC_CONT Cylinder(const Vector& axis, Scalar radius)
: Center(Scalar(0))
, Axis(axis)
, Radius(radius)
{
}
VTKM_EXEC_CONT Cylinder(const Vector& center, const Vector& axis, Scalar radius)
: Center(center)
, Axis(axis)
, Radius(radius)
{
}
VTKM_CONT void SetCenter(const Vector& center)
{
this->Center = center;
this->Modified();
}
VTKM_CONT void SetAxis(const Vector& axis)
{
this->Axis = axis;
this->Modified();
}
VTKM_CONT void SetRadius(Scalar radius)
{
this->Radius = radius;
this->Modified();
}
VTKM_EXEC_CONT Scalar Value(const Vector& point) const override
{
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 override
{
Vector x2c = point - this->Center;
FloatDefault t = this->Axis[0] * x2c[0] + this->Axis[1] * x2c[1] + this->Axis[2] * x2c[2];
vtkm::Vec<FloatDefault, 3> closestPoint = this->Center + (this->Axis * t);
return (point - closestPoint) * FloatDefault(2);
}
private:
Vector Center;
Vector Axis;
Scalar Radius;
};
//============================================================================
/// \brief Implicit function for a frustum
class VTKM_ALWAYS_EXPORT Frustum : public vtkm::ImplicitFunction
{
public:
VTKM_EXEC_CONT Frustum() = default;
VTKM_EXEC_CONT Frustum(const Vector points[6], const Vector normals[6])
{
this->SetPlanes(points, normals);
}
VTKM_EXEC_CONT explicit Frustum(const Vector points[8]) { this->CreateFromPoints(points); }
VTKM_EXEC void SetPlanes(const Vector points[6], const Vector normals[6])
{
for (vtkm::Id index : { 0, 1, 2, 3, 4, 5 })
{
this->Points[index] = points[index];
}
for (vtkm::Id index : { 0, 1, 2, 3, 4, 5 })
{
this->Normals[index] = normals[index];
}
this->Modified();
}
VTKM_EXEC void SetPlane(int idx, const Vector& point, const Vector& normal)
{
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
{
for (vtkm::Id index : { 0, 1, 2, 3, 4, 5 })
{
points[index] = this->Points[index];
}
for (vtkm::Id index : { 0, 1, 2, 3, 4, 5 })
{
normals[index] = this->Normals[index];
}
}
VTKM_EXEC_CONT const Vector* GetPoints() const { return this->Points; }
VTKM_EXEC_CONT const Vector* GetNormals() const { return this->Normals; }
// The points should be specified in the order of hex-cell vertices
VTKM_EXEC_CONT void CreateFromPoints(const Vector points[8])
{
// XXX(clang-format-3.9): 3.8 is silly. 3.9 makes it look like this.
// clang-format off
int planes[6][3] = {
{ 3, 2, 0 }, { 4, 5, 7 }, { 0, 1, 4 }, { 1, 2, 5 }, { 2, 3, 6 }, { 3, 0, 7 }
};
// clang-format on
for (int i = 0; i < 6; ++i)
{
const Vector& v0 = points[planes[i][0]];
const Vector& v1 = points[planes[i][1]];
const Vector& v2 = points[planes[i][2]];
this->Points[i] = v0;
this->Normals[i] = vtkm::Normal(vtkm::Cross(v2 - v0, v1 - v0));
}
this->Modified();
}
VTKM_EXEC_CONT Scalar Value(const Vector& point) const override
{
Scalar maxVal = vtkm::NegativeInfinity<Scalar>();
for (vtkm::Id index : { 0, 1, 2, 3, 4, 5 })
{
const Vector& p = this->Points[index];
const Vector& n = this->Normals[index];
const Scalar val = vtkm::dot(point - p, n);
maxVal = vtkm::Max(maxVal, val);
}
return maxVal;
}
VTKM_EXEC_CONT Vector Gradient(const Vector& point) const override
{
Scalar maxVal = vtkm::NegativeInfinity<Scalar>();
vtkm::Id maxValIdx = 0;
for (vtkm::Id index : { 0, 1, 2, 3, 4, 5 })
{
const Vector& p = this->Points[index];
const Vector& n = this->Normals[index];
Scalar val = vtkm::dot(point - p, n);
if (val > maxVal)
{
maxVal = val;
maxValIdx = index;
}
}
return this->Normals[maxValIdx];
}
private:
Vector Points[6];
Vector Normals[6];
};
//============================================================================
/// \brief Implicit function for a plane
class VTKM_ALWAYS_EXPORT Plane : public vtkm::ImplicitFunction
{
public:
VTKM_EXEC_CONT Plane()
: Origin(Scalar(0))
, Normal(Scalar(0), Scalar(0), Scalar(1))
{
}
VTKM_EXEC_CONT explicit Plane(const Vector& normal)
: Origin(Scalar(0))
, Normal(normal)
{
}
VTKM_EXEC_CONT Plane(const Vector& origin, const Vector& normal)
: Origin(origin)
, Normal(normal)
{
}
VTKM_CONT void SetOrigin(const Vector& origin)
{
this->Origin = origin;
this->Modified();
}
VTKM_CONT void SetNormal(const Vector& normal)
{
this->Normal = normal;
this->Modified();
}
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 override
{
return vtkm::dot(point - this->Origin, this->Normal);
}
VTKM_EXEC_CONT Vector Gradient(const Vector&) const override { return this->Normal; }
private:
Vector Origin;
Vector Normal;
};
//============================================================================
/// \brief Implicit function for a sphere
class VTKM_ALWAYS_EXPORT Sphere : public vtkm::ImplicitFunction
{
public:
VTKM_EXEC_CONT Sphere()
: Radius(Scalar(0.2))
, Center(Scalar(0))
{
}
VTKM_EXEC_CONT explicit Sphere(Scalar radius)
: Radius(radius)
, Center(Scalar(0))
{
}
VTKM_EXEC_CONT Sphere(Vector center, Scalar radius)
: Radius(radius)
, Center(center)
{
}
VTKM_CONT void SetRadius(Scalar radius)
{
this->Radius = radius;
this->Modified();
}
VTKM_CONT void SetCenter(const Vector& center)
{
this->Center = center;
this->Modified();
}
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 override
{
return vtkm::MagnitudeSquared(point - this->Center) - (this->Radius * this->Radius);
}
VTKM_EXEC_CONT Vector Gradient(const Vector& point) const override
{
return Scalar(2) * (point - this->Center);
}
private:
Scalar Radius;
Vector Center;
};
} // namespace vtkm
#ifdef VTKM_CUDA
// Cuda seems to have a bug where it expects the template class VirtualObjectTransfer
// to be instantiated in a consitent 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.
#include <vtkm/cont/cuda/internal/VirtualObjectTransferCuda.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

@ -73,7 +73,7 @@ struct ListTagJoin : detail::ListRoot
using list = typename detail::ListJoin<typename ListTag1::list, typename ListTag2::list>::type;
};
/// A tag that consits of elements that are found in both tags. This struct
/// A tag that consists of elements that are found in both tags. This struct
/// can be subclassed and still behave like a list tag.
template <typename ListTag1, typename ListTag2>
struct ListTagIntersect : detail::ListRoot
@ -85,13 +85,24 @@ struct ListTagIntersect : detail::ListRoot
/// For each typename represented by the list tag, call the functor with a
/// default instance of that type.
///
template <typename Functor, typename ListTag>
VTKM_CONT void ListForEach(Functor&& f, ListTag)
template <typename Functor, typename ListTag, typename... Args>
VTKM_CONT void ListForEach(Functor&& f, ListTag, Args&&... args)
{
VTKM_IS_LIST_TAG(ListTag);
detail::ListForEachImpl(f, typename ListTag::list());
detail::ListForEachImpl(
std::forward<Functor>(f), typename ListTag::list{}, std::forward<Args>(args)...);
}
/// Generate a tag that is the cross product of two other tags. The resulting
// a tag has the form of Tag< std::pair<A1,B1>, std::pair<A1,B2> .... >
///
template <typename ListTag1, typename ListTag2>
struct ListCrossProduct : detail::ListRoot
{
using list =
typename detail::ListCrossProductImpl<typename ListTag1::list, typename ListTag2::list>::type;
};
/// Checks to see if the given \c Type is in the list pointed to by \c ListTag.
/// There is a static boolean named \c value that is set to true if the type is
/// contained in the list and false otherwise.

82
vtkm/VirtualObjectBase.h Normal file

@ -0,0 +1,82 @@
//============================================================================
// 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.
//
// Copyright 2017 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2017 UT-Battelle, LLC.
// Copyright 2017 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#ifndef vtk_m_VirtualObjectBase_h
#define vtk_m_VirtualObjectBase_h
#include <vtkm/Types.h>
namespace vtkm
{
/// \brief Base class for virtual objects that work in the execution environment
///
/// Any class built in VTK-m that has virtual methods and is intended to work in both the control
/// and execution environment should inherit from \c VirtualObjectBase. Hierarchies under \c
/// VirtualObjectBase can be used in conjunction with \c VirtualObjectHandle to transfer from the
/// control environment (where they are set up) to the execution environment (where they are used).
///
/// In addition to inheriting from \c VirtualObjectBase, virtual objects have to satisfy 2 other
/// conditions to work correctly. First, they have to be a plain old data type that can be copied
/// with \c memcpy (with the exception of the virtual table, which \c VirtualObjectHandle will take
/// care of). Second, if the object changes its state in the control environment, it should call
/// \c Modified on itself so the \c VirtualObjectHandle will know it update the object in the
/// execution environment.
///
class VTKM_ALWAYS_EXPORT VirtualObjectBase
{
public:
VTKM_EXEC_CONT virtual ~VirtualObjectBase() = default;
VTKM_EXEC_CONT void Modified() { this->ModifiedCount++; }
VTKM_EXEC_CONT vtkm::Id GetModifiedCount() const { return this->ModifiedCount; }
protected:
VTKM_EXEC_CONT VirtualObjectBase()
: ModifiedCount(0)
{
}
VTKM_EXEC_CONT VirtualObjectBase(const VirtualObjectBase&) = default;
VTKM_EXEC_CONT VirtualObjectBase(VirtualObjectBase&& other)
: ModifiedCount(other.ModifiedCount)
{
}
VTKM_EXEC_CONT VirtualObjectBase& operator=(const VirtualObjectBase&)
{
this->Modified();
return *this;
}
VTKM_EXEC_CONT VirtualObjectBase& operator=(VirtualObjectBase&&)
{
this->Modified();
return *this;
}
private:
vtkm::Id ModifiedCount;
};
} // namespace vtkm
#endif //vtk_m_VirtualObjectBase_h

@ -24,7 +24,7 @@
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/CellSetStructured.h>
#include <vtkm/cont/DynamicArrayHandle.h>
#include <vtkm/cont/ImplicitFunction.h>
#include <vtkm/cont/ImplicitFunctionHandle.h>
#include <vtkm/cont/Timer.h>
#include <vtkm/worklet/DispatcherMapField.h>
@ -264,7 +264,7 @@ public:
typedef void ControlSignature(FieldIn<Vec3>, FieldOut<Scalar>);
typedef void ExecutionSignature(_1, _2);
EvaluateImplicitFunction(const ImplicitFunction& function)
EvaluateImplicitFunction(const ImplicitFunction* function)
: Function(function)
{
}
@ -272,11 +272,11 @@ public:
template <typename VecType, typename ScalarType>
VTKM_EXEC void operator()(const VecType& point, ScalarType& val) const
{
val = this->Function.Value(point);
val = this->Function->Value(point);
}
private:
ImplicitFunction Function;
const ImplicitFunction* Function;
};
template <typename T1, typename T2>
@ -286,7 +286,7 @@ public:
typedef void ControlSignature(FieldIn<Vec3>, FieldOut<Scalar>);
typedef void ExecutionSignature(_1, _2);
Evaluate2ImplicitFunctions(const T1& f1, const T2& f2)
Evaluate2ImplicitFunctions(const T1* f1, const T2* f2)
: Function1(f1)
, Function2(f2)
{
@ -295,12 +295,12 @@ public:
template <typename VecType, typename ScalarType>
VTKM_EXEC void operator()(const VecType& point, ScalarType& val) const
{
val = this->Function1.Value(point) + this->Function2.Value(point);
val = this->Function1->Value(point) + this->Function2->Value(point);
}
private:
T1 Function1;
T2 Function2;
const T1* Function1;
const T2* Function2;
};
struct ValueTypes : vtkm::ListTagBase<vtkm::Float32, vtkm::Float64>
@ -680,7 +680,7 @@ private:
{
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::FloatDefault, 3>> Points;
vtkm::cont::ArrayHandle<vtkm::FloatDefault> Result;
vtkm::cont::Sphere Sphere1, Sphere2;
vtkm::Sphere Sphere1, Sphere2;
};
static ImplicitFunctionBenchData MakeImplicitFunctionBenchData()
@ -703,8 +703,8 @@ private:
portal.Set(i, vtkm::make_Vec(distx(rangen), disty(rangen), distz(rangen)));
}
data.Sphere1 = vtkm::cont::Sphere({ 0.22f, 0.33f, 0.44f }, 0.55f);
data.Sphere2 = vtkm::cont::Sphere({ 0.22f, 0.33f, 0.11f }, 0.77f);
data.Sphere1 = vtkm::Sphere({ 0.22f, 0.33f, 0.44f }, 0.55f);
data.Sphere2 = vtkm::Sphere({ 0.22f, 0.33f, 0.11f }, 0.77f);
return data;
}
@ -720,10 +720,13 @@ private:
VTKM_CONT
vtkm::Float64 operator()()
{
using EvalWorklet = EvaluateImplicitFunction<vtkm::cont::Sphere>;
using EvalWorklet = EvaluateImplicitFunction<vtkm::Sphere>;
using EvalDispatcher = vtkm::worklet::DispatcherMapField<EvalWorklet, DeviceAdapterTag>;
EvalWorklet eval(Internal.Sphere1);
auto handle = vtkm::cont::make_ImplicitFunctionHandle(Internal.Sphere1);
auto function =
static_cast<const vtkm::Sphere*>(handle.PrepareForExecution(DeviceAdapterTag()));
EvalWorklet eval(function);
vtkm::cont::Timer<DeviceAdapterTag> timer;
EvalDispatcher(eval).Invoke(this->Internal.Points, this->Internal.Result);
@ -734,8 +737,8 @@ private:
std::string Description() const
{
std::stringstream description;
description << "Implicit Function (vtkm::cont::Sphere) on "
<< Internal.Points.GetNumberOfValues() << " points";
description << "Implicit Function (vtkm::Sphere) on " << Internal.Points.GetNumberOfValues()
<< " points";
return description.str();
}
@ -743,9 +746,9 @@ private:
};
template <typename Value>
struct BenchDynamicImplicitFunction
struct BenchVirtualImplicitFunction
{
BenchDynamicImplicitFunction()
BenchVirtualImplicitFunction()
: Internal(MakeImplicitFunctionBenchData())
{
}
@ -753,10 +756,11 @@ private:
VTKM_CONT
vtkm::Float64 operator()()
{
using EvalWorklet = EvaluateImplicitFunction<vtkm::exec::ImplicitFunction>;
using EvalWorklet = EvaluateImplicitFunction<vtkm::ImplicitFunction>;
using EvalDispatcher = vtkm::worklet::DispatcherMapField<EvalWorklet, DeviceAdapterTag>;
EvalWorklet eval(Internal.Sphere1.PrepareForExecution(DeviceAdapterTag()));
auto sphere = vtkm::cont::make_ImplicitFunctionHandle(Internal.Sphere1);
EvalWorklet eval(sphere.PrepareForExecution(DeviceAdapterTag()));
vtkm::cont::Timer<DeviceAdapterTag> timer;
EvalDispatcher(eval).Invoke(this->Internal.Points, this->Internal.Result);
@ -767,7 +771,7 @@ private:
std::string Description() const
{
std::stringstream description;
description << "Implicit Function (DynamicImplicitFunction) on "
description << "Implicit Function (VirtualImplicitFunction) on "
<< Internal.Points.GetNumberOfValues() << " points";
return description.str();
}
@ -786,10 +790,14 @@ private:
VTKM_CONT
vtkm::Float64 operator()()
{
using EvalWorklet = Evaluate2ImplicitFunctions<vtkm::cont::Sphere, vtkm::cont::Sphere>;
using EvalWorklet = Evaluate2ImplicitFunctions<vtkm::Sphere, vtkm::Sphere>;
using EvalDispatcher = vtkm::worklet::DispatcherMapField<EvalWorklet, DeviceAdapterTag>;
EvalWorklet eval(Internal.Sphere1, Internal.Sphere2);
auto h1 = vtkm::cont::make_ImplicitFunctionHandle(Internal.Sphere1);
auto h2 = vtkm::cont::make_ImplicitFunctionHandle(Internal.Sphere2);
auto f1 = static_cast<const vtkm::Sphere*>(h1.PrepareForExecution(DeviceAdapterTag()));
auto f2 = static_cast<const vtkm::Sphere*>(h2.PrepareForExecution(DeviceAdapterTag()));
EvalWorklet eval(f1, f2);
vtkm::cont::Timer<DeviceAdapterTag> timer;
EvalDispatcher(eval).Invoke(this->Internal.Points, this->Internal.Result);
@ -800,8 +808,8 @@ private:
std::string Description() const
{
std::stringstream description;
description << "Implicit Function 2x(vtkm::cont::Sphere) on "
<< Internal.Points.GetNumberOfValues() << " points";
description << "Implicit Function 2x(vtkm::Sphere) on " << Internal.Points.GetNumberOfValues()
<< " points";
return description.str();
}
@ -809,9 +817,9 @@ private:
};
template <typename Value>
struct Bench2DynamicImplicitFunctions
struct Bench2VirtualImplicitFunctions
{
Bench2DynamicImplicitFunctions()
Bench2VirtualImplicitFunctions()
: Internal(MakeImplicitFunctionBenchData())
{
}
@ -820,11 +828,13 @@ private:
vtkm::Float64 operator()()
{
using EvalWorklet =
Evaluate2ImplicitFunctions<vtkm::exec::ImplicitFunction, vtkm::exec::ImplicitFunction>;
Evaluate2ImplicitFunctions<vtkm::ImplicitFunction, vtkm::ImplicitFunction>;
using EvalDispatcher = vtkm::worklet::DispatcherMapField<EvalWorklet, DeviceAdapterTag>;
EvalWorklet eval(Internal.Sphere1.PrepareForExecution(DeviceAdapterTag()),
Internal.Sphere2.PrepareForExecution(DeviceAdapterTag()));
auto s1 = vtkm::cont::make_ImplicitFunctionHandle(Internal.Sphere1);
auto s2 = vtkm::cont::make_ImplicitFunctionHandle(Internal.Sphere2);
EvalWorklet eval(s1.PrepareForExecution(DeviceAdapterTag()),
s2.PrepareForExecution(DeviceAdapterTag()));
vtkm::cont::Timer<DeviceAdapterTag> timer;
EvalDispatcher(eval).Invoke(this->Internal.Points, this->Internal.Result);
@ -835,7 +845,7 @@ private:
std::string Description() const
{
std::stringstream description;
description << "Implicit Function 2x(DynamicImplicitFunction) on "
description << "Implicit Function 2x(VirtualImplicitFunction) on "
<< Internal.Points.GetNumberOfValues() << " points";
return description.str();
}
@ -844,9 +854,9 @@ private:
};
VTKM_MAKE_BENCHMARK(ImplicitFunction, BenchImplicitFunction);
VTKM_MAKE_BENCHMARK(ImplicitFunctionDynamic, BenchDynamicImplicitFunction);
VTKM_MAKE_BENCHMARK(ImplicitFunctionVirtual, BenchVirtualImplicitFunction);
VTKM_MAKE_BENCHMARK(ImplicitFunction2, Bench2ImplicitFunctions);
VTKM_MAKE_BENCHMARK(ImplicitFunctionDynamic2, Bench2DynamicImplicitFunctions);
VTKM_MAKE_BENCHMARK(ImplicitFunctionVirtual2, Bench2VirtualImplicitFunctions);
public:
static VTKM_CONT int Run(int benchmarks)
@ -887,9 +897,9 @@ public:
std::cout << "\nBenchmarking Implicit Function\n";
VTKM_RUN_BENCHMARK(ImplicitFunction, FloatDefaultType());
VTKM_RUN_BENCHMARK(ImplicitFunctionDynamic, FloatDefaultType());
VTKM_RUN_BENCHMARK(ImplicitFunctionVirtual, FloatDefaultType());
VTKM_RUN_BENCHMARK(ImplicitFunction2, FloatDefaultType());
VTKM_RUN_BENCHMARK(ImplicitFunctionDynamic2, FloatDefaultType());
VTKM_RUN_BENCHMARK(ImplicitFunctionVirtual2, FloatDefaultType());
}
return 0;

@ -69,7 +69,7 @@ set(headers
ErrorExecution.h
ErrorInternal.h
Field.h
ImplicitFunction.h
ImplicitFunctionHandle.h
MultiBlock.h
PointLocatorUniformGrid.h
RuntimeDeviceInformation.h
@ -80,14 +80,13 @@ set(headers
StorageListTag.h
Timer.h
TryExecute.h
VirtualObjectCache.h
VirtualObjectHandle.h
)
set(template_sources
ArrayHandle.hxx
CellSetExplicit.hxx
CellSetStructured.hxx
ImplicitFunction.hxx
StorageBasic.hxx
)
@ -99,7 +98,6 @@ set(sources
CoordinateSystem.cxx
DynamicArrayHandle.cxx
Field.cxx
ImplicitFunction.cxx
internal/SimplePolymorphicContainer.cxx
MultiBlock.cxx
internal/ArrayManagerExecutionShareWithControl.cxx
@ -112,6 +110,7 @@ set(device_sources
ArrayRangeCompute.cxx
CellSetExplicit.cxx
RuntimeDeviceTracker.cxx
TryExecute.cxx
)
#-----------------------------------------------------------------------------

@ -106,11 +106,11 @@ public:
virtual ~CellSetExplicit();
vtkm::Id GetNumberOfCells() const VTKM_OVERRIDE;
vtkm::Id GetNumberOfPoints() const VTKM_OVERRIDE;
vtkm::Id GetNumberOfFaces() const VTKM_OVERRIDE;
vtkm::Id GetNumberOfEdges() const VTKM_OVERRIDE;
void PrintSummary(std::ostream& out) const VTKM_OVERRIDE;
vtkm::Id GetNumberOfCells() const override;
vtkm::Id GetNumberOfPoints() const override;
vtkm::Id GetNumberOfFaces() const override;
vtkm::Id GetNumberOfEdges() const override;
void PrintSummary(std::ostream& out) const override;
VTKM_CONT vtkm::Id GetSchedulingRange(vtkm::TopologyElementTagCell) const;
VTKM_CONT vtkm::Id GetSchedulingRange(vtkm::TopologyElementTagPoint) const;

@ -72,7 +72,17 @@ struct StorageListTagCoordinateSystemDefault
vtkm::cont::ArrayHandle<vtkm::FloatDefault>>::StorageTag>
{
};
}
}
namespace vtkm
{
template struct ListCrossProduct<::vtkm::TypeListTagFieldVec3,
::vtkm::cont::StorageListTagCoordinateSystemDefault>;
namespace cont
{
using DynamicArrayHandleCoordinateSystem =
vtkm::cont::DynamicArrayHandleBase<VTKM_DEFAULT_COORDINATE_SYSTEM_TYPE_LIST_TAG,
VTKM_DEFAULT_COORDINATE_SYSTEM_STORAGE_LIST_TAG>;
@ -214,10 +224,10 @@ public:
virtual void PrintSummary(std::ostream& out) const;
};
template <typename Functor>
void CastAndCall(const vtkm::cont::CoordinateSystem& coords, const Functor& f)
template <typename Functor, typename... Args>
void CastAndCall(const vtkm::cont::CoordinateSystem& coords, const Functor& f, Args&&... args)
{
coords.GetData().CastAndCall(f);
coords.GetData().CastAndCall(f, std::forward<Args>(args)...);
}
namespace internal

@ -40,6 +40,47 @@ struct DeviceAdapterListTagCommon : vtkm::ListTagBase<vtkm::cont::DeviceAdapterT
vtkm::cont::DeviceAdapterTagSerial>
{
};
namespace detail
{
template <typename FunctorType>
class ExecuteIfValidDeviceTag
{
private:
template <typename DeviceAdapter>
using EnableIfValid = std::enable_if<vtkm::cont::DeviceAdapterTraits<DeviceAdapter>::Valid>;
template <typename DeviceAdapter>
using EnableIfInvalid = std::enable_if<!vtkm::cont::DeviceAdapterTraits<DeviceAdapter>::Valid>;
public:
explicit ExecuteIfValidDeviceTag(const FunctorType& functor)
: Functor(functor)
{
}
template <typename DeviceAdapter>
typename EnableIfValid<DeviceAdapter>::type operator()(DeviceAdapter) const
{
this->Functor(DeviceAdapter());
}
template <typename DeviceAdapter>
typename EnableIfInvalid<DeviceAdapter>::type operator()(DeviceAdapter) const
{
}
private:
FunctorType Functor;
};
} // detail
template <typename DeviceList, typename Functor>
VTKM_CONT void ForEachValidDevice(DeviceList devices, const Functor& functor)
{
vtkm::ListForEach(detail::ExecuteIfValidDeviceTag<Functor>(functor), devices);
}
}
} // namespace vtkm::cont

@ -18,6 +18,8 @@
// this software.
//============================================================================
#include <sstream>
#include <typeindex>
#include <vtkm/cont/DynamicArrayHandle.h>
namespace vtkm
@ -34,6 +36,18 @@ PolymorphicArrayHandleContainerBase::PolymorphicArrayHandleContainerBase()
PolymorphicArrayHandleContainerBase::~PolymorphicArrayHandleContainerBase()
{
}
void ThrowCastAndCallException(PolymorphicArrayHandleContainerBase* ptr,
const std::type_info* type,
const std::type_info* storage)
{
std::ostringstream out;
out << "Could not find appropriate cast for array in CastAndCall1.\n"
"Array: ";
ptr->PrintSummary(out);
out << "TypeList: " << type->name() << "\nStorageList: " << storage->name() << "\n";
throw vtkm::cont::ErrorBadValue(out.str());
}
}
}
} // namespace vtkm::cont::detail

@ -31,10 +31,11 @@
#include <vtkm/cont/internal/DynamicTransform.h>
#include <sstream>
namespace vtkm
{
template struct ListCrossProduct<VTKM_DEFAULT_TYPE_LIST_TAG, VTKM_DEFAULT_STORAGE_LIST_TAG>;
namespace cont
{
@ -131,9 +132,8 @@ template <typename Type, typename Storage>
VTKM_CONT vtkm::cont::ArrayHandle<Type, Storage>* DynamicArrayHandleTryCast(
vtkm::cont::detail::PolymorphicArrayHandleContainerBase* arrayContainer)
{
vtkm::cont::detail::PolymorphicArrayHandleContainer<Type, Storage>* downcastContainer =
dynamic_cast<vtkm::cont::detail::PolymorphicArrayHandleContainer<Type, Storage>*>(
arrayContainer);
vtkm::cont::detail::PolymorphicArrayHandleContainer<Type, Storage>* downcastContainer = nullptr;
downcastContainer = dynamic_cast<decltype(downcastContainer)>(arrayContainer);
if (downcastContainer != nullptr)
{
return &downcastContainer->Array;
@ -357,8 +357,8 @@ public:
/// two lists to VTKM_DEFAULT_TYPE_LIST_TAG and VTK_DEFAULT_STORAGE_LIST_TAG,
/// respectively.
///
template <typename Functor>
VTKM_CONT void CastAndCall(const Functor& f) const;
template <typename Functor, typename... Args>
VTKM_CONT void CastAndCall(const Functor& f, Args&&...) const;
/// \brief Create a new array of the same type as this array.
///
@ -406,135 +406,66 @@ using DynamicArrayHandle =
namespace detail
{
template <typename Functor, typename Type>
struct DynamicArrayHandleTryStorage
struct DynamicArrayHandleTry
{
const DynamicArrayHandle* const Array;
const Functor& Function;
bool FoundCast;
VTKM_CONT
DynamicArrayHandleTryStorage(const DynamicArrayHandle& array, const Functor& f)
: Array(&array)
, Function(f)
, FoundCast(false)
DynamicArrayHandleTry(const PolymorphicArrayHandleContainerBase* const c)
: Container(c)
{
}
template <typename Storage>
VTKM_CONT void operator()(Storage)
template <typename T, typename U, typename... Args>
void operator()(std::pair<T, U>&& p, Args&&... args) const
{
this->DoCast(Storage(),
typename vtkm::cont::internal::IsValidArrayHandle<Type, Storage>::type());
using storage = vtkm::cont::internal::Storage<T, U>;
using invalid = typename std::is_base_of<vtkm::cont::internal::UndefinedStorage, storage>::type;
this->run(std::forward<decltype(p)>(p), invalid{}, args...);
}
private:
template <typename Storage>
void DoCast(Storage, std::true_type)
template <typename T, typename U, typename Functor, typename... Args>
void run(std::pair<T, U>&&, std::false_type, Functor&& f, bool& called, Args&&... args) const
{
if (!this->FoundCast && this->Array->template IsTypeAndStorage<Type, Storage>())
if (!called)
{
this->Function(this->Array->template CastToTypeStorage<Type, Storage>());
this->FoundCast = true;
using downcastType = const vtkm::cont::detail::PolymorphicArrayHandleContainer<T, U>* const;
downcastType downcastContainer = dynamic_cast<downcastType>(this->Container);
if (downcastContainer)
{
f(downcastContainer->Array, std::forward<Args>(args)...);
called = true;
}
}
}
template <typename Storage>
void DoCast(Storage, std::false_type)
template <typename T, typename U, typename... Args>
void run(std::pair<T, U>&&, std::true_type, Args&&...) const
{
// This type of array handle cannot exist, so do nothing.
}
void operator=(const DynamicArrayHandleTryStorage<Functor, Type>&) = delete;
};
template <typename Functor, typename StorageList>
struct DynamicArrayHandleTryType
{
const DynamicArrayHandle* const Array;
const Functor& Function;
bool FoundCast;
VTKM_CONT
DynamicArrayHandleTryType(const DynamicArrayHandle& array, const Functor& f)
: Array(&array)
, Function(f)
, FoundCast(false)
{
}
template <typename Type>
VTKM_CONT void operator()(Type)
{
if (this->FoundCast)
{
return;
}
using TryStorageType = DynamicArrayHandleTryStorage<Functor, Type>;
TryStorageType tryStorage = TryStorageType(*this->Array, this->Function);
vtkm::ListForEach(tryStorage, StorageList());
if (tryStorage.FoundCast)
{
this->FoundCast = true;
}
}
private:
void operator=(const DynamicArrayHandleTryType<Functor, StorageList>&) = delete;
const PolymorphicArrayHandleContainerBase* const Container;
};
VTKM_CONT_EXPORT void ThrowCastAndCallException(PolymorphicArrayHandleContainerBase*,
const std::type_info*,
const std::type_info*);
} // namespace detail
template <typename TypeList, typename StorageList>
template <typename Functor>
VTKM_CONT void DynamicArrayHandleBase<TypeList, StorageList>::CastAndCall(const Functor& f) const
template <typename Functor, typename... Args>
VTKM_CONT void DynamicArrayHandleBase<TypeList, StorageList>::CastAndCall(const Functor& f,
Args&&... args) const
{
VTKM_IS_LIST_TAG(TypeList);
VTKM_IS_LIST_TAG(StorageList);
using TryTypeType = detail::DynamicArrayHandleTryType<Functor, StorageList>;
//For optimizations we should compile once the cross product for the default types
//and make it extern
using crossProduct = typename vtkm::ListCrossProduct<TypeList, StorageList>;
// We cast this to a DynamicArrayHandle because at this point we are ignoring
// the type/storage lists in it. There is no sense in adding more unnecessary
// template cases.
// The downside to this approach is that a copy is created, causing an
// atomic increment, which affects both performance and library size.
// For these reasons we have a specialization of this method to remove
// the copy when the type/storage lists are the default
DynamicArrayHandle t(*this);
TryTypeType tryType = TryTypeType(t, f);
vtkm::ListForEach(tryType, TypeList());
if (!tryType.FoundCast)
bool called = false;
auto* ptr = this->ArrayContainer.get();
vtkm::ListForEach(
detail::DynamicArrayHandleTry(ptr), crossProduct{}, f, called, std::forward<Args>(args)...);
if (!called)
{
std::ostringstream out;
out << "Could not find appropriate cast for array in CastAndCall1.\n"
"Array: ";
this->PrintSummary(out);
out << "TypeList: " << typeid(TypeList).name()
<< "\nStorageList: " << typeid(StorageList).name() << "\n";
throw vtkm::cont::ErrorBadValue(out.str());
}
}
template <>
template <typename Functor>
VTKM_CONT void
DynamicArrayHandleBase<VTKM_DEFAULT_TYPE_LIST_TAG, VTKM_DEFAULT_STORAGE_LIST_TAG>::CastAndCall(
const Functor& f) const
{
using TryTypeType = detail::DynamicArrayHandleTryType<Functor, VTKM_DEFAULT_STORAGE_LIST_TAG>;
// We can remove the copy, as the current DynamicArrayHandle is already
// the default one, and no reason to do an atomic increment and increase
// library size, and reduce performance
TryTypeType tryType = TryTypeType(*this, f);
vtkm::ListForEach(tryType, VTKM_DEFAULT_TYPE_LIST_TAG());
if (!tryType.FoundCast)
{
throw vtkm::cont::ErrorBadValue("Could not find appropriate cast for array in CastAndCall2.");
// throw an exception
detail::ThrowCastAndCallException(ptr, &typeid(TypeList), &typeid(StorageList));
}
}
@ -549,6 +480,7 @@ struct DynamicTransformTraits<vtkm::cont::DynamicArrayHandleBase<TypeList, Stora
} // namespace internal
}
} // namespace vtkm::cont
#endif //vtk_m_cont_DynamicArrayHandle_h

@ -227,8 +227,8 @@ public:
/// DynamicCellSet). You can use \c ResetCellSetList to get different
/// behavior from \c CastAndCall.
///
template <typename Functor>
VTKM_CONT void CastAndCall(const Functor& f) const;
template <typename Functor, typename... Args>
VTKM_CONT void CastAndCall(const Functor& f, Args&&...) const;
/// \brief Create a new cell set of the same type as this cell set.
///
@ -272,51 +272,42 @@ private:
namespace detail
{
template <typename Functor>
struct DynamicCellSetTryCellSet
struct DynamicCellSetTry
{
vtkm::cont::internal::SimplePolymorphicContainerBase* CellSetContainer;
const Functor& Function;
bool FoundCast;
VTKM_CONT
DynamicCellSetTryCellSet(vtkm::cont::internal::SimplePolymorphicContainerBase* cellSetContainer,
const Functor& f)
: CellSetContainer(cellSetContainer)
, Function(f)
, FoundCast(false)
DynamicCellSetTry(
const vtkm::cont::internal::SimplePolymorphicContainerBase* const cellSetContainer)
: Container(cellSetContainer)
{
}
template <typename CellSetType>
VTKM_CONT void operator()(CellSetType)
template <typename CellSetType, typename Functor, typename... Args>
void operator()(CellSetType, Functor&& f, bool& called, Args&&... args) const
{
if (!this->FoundCast)
using downcastType = const vtkm::cont::internal::SimplePolymorphicContainer<CellSetType>* const;
if (!called)
{
CellSetType* cellSet = detail::DynamicCellSetTryCast<CellSetType>(this->CellSetContainer);
if (cellSet != nullptr)
downcastType downcastContainer = dynamic_cast<downcastType>(this->Container);
if (downcastContainer)
{
this->Function(*cellSet);
this->FoundCast = true;
f(downcastContainer->Item, std::forward<Args>(args)...);
called = true;
}
}
}
private:
void operator=(const DynamicCellSetTryCellSet<Functor>&) = delete;
const vtkm::cont::internal::SimplePolymorphicContainerBase* const Container;
};
} // namespace detail
template <typename CellSetList>
template <typename Functor>
VTKM_CONT void DynamicCellSetBase<CellSetList>::CastAndCall(const Functor& f) const
template <typename Functor, typename... Args>
VTKM_CONT void DynamicCellSetBase<CellSetList>::CastAndCall(const Functor& f, Args&&... args) const
{
using TryCellSetType = detail::DynamicCellSetTryCellSet<Functor>;
TryCellSetType tryCellSet = TryCellSetType(this->CellSetContainer.get(), f);
vtkm::ListForEach(tryCellSet, CellSetList());
if (!tryCellSet.FoundCast)
bool called = false;
detail::DynamicCellSetTry tryCellSet(this->CellSetContainer.get());
vtkm::ListForEach(tryCellSet, CellSetList{}, f, called, std::forward<Args>(args)...);
if (!called)
{
throw vtkm::cont::ErrorBadValue("Could not find appropriate cast for cell set.");
}

@ -27,7 +27,7 @@
#include <exception>
#include <string>
#include <vtkm/internal/ExportMacros.h> // For VTKM_OVERRIDE
#include <vtkm/internal/ExportMacros.h> // For VTKM_NOEXCEPT
namespace vtkm
{
@ -55,7 +55,7 @@ public:
#endif
// For std::exception compatibility:
const char* what() const VTKM_NOEXCEPT VTKM_OVERRIDE { return this->Message.c_str(); }
const char* what() const VTKM_NOEXCEPT override { return this->Message.c_str(); }
protected:
Error() {}

@ -401,10 +401,10 @@ private:
}
};
template <typename Functor>
void CastAndCall(const vtkm::cont::Field& field, const Functor& f)
template <typename Functor, typename... Args>
void CastAndCall(const vtkm::cont::Field& field, const Functor& f, Args&&... args)
{
field.GetData().CastAndCall(f);
field.GetData().CastAndCall(f, std::forward<Args>(args)...);
}
namespace internal

@ -1,29 +0,0 @@
//============================================================================
// 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.
//
// Copyright 2017 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2017 UT-Battelle, LLC.
// Copyright 2017 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#include <vtkm/cont/ImplicitFunction.h>
namespace vtkm
{
namespace cont
{
ImplicitFunction::~ImplicitFunction() = default;
}
} // vtkm::cont

@ -1,286 +0,0 @@
//============================================================================
// 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.
//
// Copyright 2017 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2017 UT-Battelle, LLC.
// Copyright 2017 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#ifndef vtk_m_cont_ImplicitFunction_h
#define vtk_m_cont_ImplicitFunction_h
#include <vtkm/internal/Configure.h>
#include <vtkm/cont/VirtualObjectCache.h>
#include <vtkm/exec/ImplicitFunction.h>
#include <memory>
namespace vtkm
{
namespace cont
{
class VTKM_CONT_EXPORT ImplicitFunction
{
public:
virtual ~ImplicitFunction();
template <typename DeviceAdapter>
vtkm::exec::ImplicitFunction PrepareForExecution(DeviceAdapter device) const
{
if (!this->Cache->GetValid())
{
this->SetDefaultDevices();
}
return this->Cache->GetVirtualObject(device);
}
void Modified() { this->Cache->SetRefreshFlag(true); }
protected:
using CacheType = vtkm::cont::VirtualObjectCache<vtkm::exec::ImplicitFunction>;
ImplicitFunction()
: Cache(new CacheType)
{
}
ImplicitFunction(ImplicitFunction&& other)
: Cache(std::move(other.Cache))
{
}
ImplicitFunction& operator=(ImplicitFunction&& other)
{
if (this != &other)
{
this->Cache = std::move(other.Cache);
}
return *this;
}
virtual void SetDefaultDevices() const = 0;
std::unique_ptr<CacheType> Cache;
};
template <typename Derived>
class VTKM_ALWAYS_EXPORT ImplicitFunctionImpl : public ImplicitFunction
{
public:
template <typename DeviceAdapterList>
void ResetDevices(DeviceAdapterList devices)
{
this->Cache->Bind(static_cast<const Derived*>(this), devices);
}
protected:
ImplicitFunctionImpl() = default;
ImplicitFunctionImpl(const ImplicitFunctionImpl&)
: ImplicitFunction()
{
}
// Cannot default due to a bug in VS2013
ImplicitFunctionImpl(ImplicitFunctionImpl&& other)
: ImplicitFunction(std::move(other))
{
}
ImplicitFunctionImpl& operator=(const ImplicitFunctionImpl&) { return *this; }
// Cannot default due to a bug in VS2013
ImplicitFunctionImpl& operator=(ImplicitFunctionImpl&& other)
{
ImplicitFunction::operator=(std::move(other));
return *this;
}
void SetDefaultDevices() const override { this->Cache->Bind(static_cast<const Derived*>(this)); }
};
//============================================================================
// ImplicitFunctions:
//============================================================================
/// \brief Implicit function for a box
class VTKM_ALWAYS_EXPORT Box : public ImplicitFunctionImpl<Box>
{
public:
Box();
Box(vtkm::Vec<FloatDefault, 3> minPoint, vtkm::Vec<FloatDefault, 3> maxPoint);
Box(FloatDefault xmin,
FloatDefault xmax,
FloatDefault ymin,
FloatDefault ymax,
FloatDefault zmin,
FloatDefault zmax);
void SetMinPoint(const vtkm::Vec<FloatDefault, 3>& point);
void SetMaxPoint(const vtkm::Vec<FloatDefault, 3>& point);
const vtkm::Vec<FloatDefault, 3>& GetMinPoint() const;
const vtkm::Vec<FloatDefault, 3>& GetMaxPoint() const;
VTKM_EXEC_CONT
FloatDefault Value(const vtkm::Vec<FloatDefault, 3>& x) const;
VTKM_EXEC_CONT
FloatDefault Value(FloatDefault x, FloatDefault y, FloatDefault z) const;
VTKM_EXEC_CONT
vtkm::Vec<FloatDefault, 3> Gradient(const vtkm::Vec<FloatDefault, 3>& x) const;
VTKM_EXEC_CONT
vtkm::Vec<FloatDefault, 3> Gradient(FloatDefault x, FloatDefault y, FloatDefault z) const;
private:
vtkm::Vec<FloatDefault, 3> MinPoint;
vtkm::Vec<FloatDefault, 3> MaxPoint;
};
//============================================================================
/// \brief Implicit function for a cylinder
class VTKM_ALWAYS_EXPORT Cylinder : public ImplicitFunctionImpl<Cylinder>
{
public:
Cylinder();
Cylinder(const vtkm::Vec<FloatDefault, 3>& axis, FloatDefault radius);
Cylinder(const vtkm::Vec<FloatDefault, 3>& center,
const vtkm::Vec<FloatDefault, 3>& axis,
FloatDefault radius);
void SetCenter(const vtkm::Vec<FloatDefault, 3>& center);
void SetAxis(const vtkm::Vec<FloatDefault, 3>& axis);
void SetRadius(FloatDefault radius);
const vtkm::Vec<FloatDefault, 3>& GetCenter() const;
const vtkm::Vec<FloatDefault, 3>& GetAxis() const;
FloatDefault GetRadius() const;
VTKM_EXEC_CONT
FloatDefault Value(const vtkm::Vec<FloatDefault, 3>& x) const;
VTKM_EXEC_CONT
FloatDefault Value(FloatDefault x, FloatDefault y, FloatDefault z) const;
VTKM_EXEC_CONT
vtkm::Vec<FloatDefault, 3> Gradient(const vtkm::Vec<FloatDefault, 3>& x) const;
VTKM_EXEC_CONT
vtkm::Vec<FloatDefault, 3> Gradient(FloatDefault x, FloatDefault y, FloatDefault z) const;
private:
vtkm::Vec<FloatDefault, 3> Center;
vtkm::Vec<FloatDefault, 3> Axis;
FloatDefault Radius;
};
//============================================================================
/// \brief Implicit function for a frustum
class VTKM_ALWAYS_EXPORT Frustum : public ImplicitFunctionImpl<Frustum>
{
public:
Frustum();
Frustum(const vtkm::Vec<FloatDefault, 3> points[6], const vtkm::Vec<FloatDefault, 3> normals[6]);
explicit Frustum(const vtkm::Vec<FloatDefault, 3> points[8]);
void SetPlanes(const vtkm::Vec<FloatDefault, 3> points[6],
const vtkm::Vec<FloatDefault, 3> normals[6]);
void SetPlane(int idx, vtkm::Vec<FloatDefault, 3>& point, vtkm::Vec<FloatDefault, 3>& normal);
void GetPlanes(vtkm::Vec<FloatDefault, 3> points[6], vtkm::Vec<FloatDefault, 3> normals[6]) const;
const vtkm::Vec<FloatDefault, 3>* GetPoints() const;
const vtkm::Vec<FloatDefault, 3>* GetNormals() const;
// The points should be specified in the order of hex-cell vertices
void CreateFromPoints(const vtkm::Vec<FloatDefault, 3> points[8]);
VTKM_EXEC_CONT
FloatDefault Value(FloatDefault x, FloatDefault y, FloatDefault z) const;
VTKM_EXEC_CONT
FloatDefault Value(const vtkm::Vec<FloatDefault, 3>& x) const;
VTKM_EXEC_CONT
vtkm::Vec<FloatDefault, 3> Gradient(FloatDefault, FloatDefault, FloatDefault) const;
VTKM_EXEC_CONT
vtkm::Vec<FloatDefault, 3> Gradient(const vtkm::Vec<FloatDefault, 3>&) const;
private:
vtkm::Vec<FloatDefault, 3> Points[6];
vtkm::Vec<FloatDefault, 3> Normals[6];
};
//============================================================================
/// \brief Implicit function for a plane
class VTKM_ALWAYS_EXPORT Plane : public ImplicitFunctionImpl<Plane>
{
public:
Plane();
explicit Plane(const vtkm::Vec<FloatDefault, 3>& normal);
Plane(const vtkm::Vec<FloatDefault, 3>& origin, const vtkm::Vec<FloatDefault, 3>& normal);
void SetOrigin(const vtkm::Vec<FloatDefault, 3>& origin);
void SetNormal(const vtkm::Vec<FloatDefault, 3>& normal);
const vtkm::Vec<FloatDefault, 3>& GetOrigin() const;
const vtkm::Vec<FloatDefault, 3>& GetNormal() const;
VTKM_EXEC_CONT
FloatDefault Value(FloatDefault x, FloatDefault y, FloatDefault z) const;
VTKM_EXEC_CONT
FloatDefault Value(const vtkm::Vec<FloatDefault, 3>& x) const;
VTKM_EXEC_CONT
vtkm::Vec<FloatDefault, 3> Gradient(FloatDefault, FloatDefault, FloatDefault) const;
VTKM_EXEC_CONT
vtkm::Vec<FloatDefault, 3> Gradient(const vtkm::Vec<FloatDefault, 3>&) const;
private:
vtkm::Vec<FloatDefault, 3> Origin;
vtkm::Vec<FloatDefault, 3> Normal;
};
//============================================================================
/// \brief Implicit function for a sphere
class VTKM_ALWAYS_EXPORT Sphere : public ImplicitFunctionImpl<Sphere>
{
public:
Sphere();
explicit Sphere(FloatDefault radius);
Sphere(vtkm::Vec<FloatDefault, 3> center, FloatDefault radius);
void SetRadius(FloatDefault radius);
void SetCenter(const vtkm::Vec<FloatDefault, 3>& center);
FloatDefault GetRadius() const;
const vtkm::Vec<FloatDefault, 3>& GetCenter() const;
VTKM_EXEC_CONT
FloatDefault Value(FloatDefault x, FloatDefault y, FloatDefault z) const;
VTKM_EXEC_CONT
FloatDefault Value(const vtkm::Vec<FloatDefault, 3>& x) const;
VTKM_EXEC_CONT
vtkm::Vec<FloatDefault, 3> Gradient(FloatDefault x, FloatDefault y, FloatDefault z) const;
VTKM_EXEC_CONT
vtkm::Vec<FloatDefault, 3> Gradient(const vtkm::Vec<FloatDefault, 3>& x) const;
private:
FloatDefault Radius;
vtkm::Vec<FloatDefault, 3> Center;
};
}
} // vtkm::cont
#include <vtkm/cont/ImplicitFunction.hxx>
#endif // vtk_m_cont_ImplicitFunction_h

@ -1,640 +0,0 @@
//============================================================================
// 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.
//
// Copyright 2017 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2017 UT-Battelle, LLC.
// Copyright 2017 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#include <vtkm/VectorAnalysis.h>
#include <vtkm/cont/ErrorBadValue.h>
#include <algorithm>
#include <limits>
namespace vtkm
{
namespace cont
{
//============================================================================
inline Box::Box()
: MinPoint(vtkm::Vec<FloatDefault, 3>(FloatDefault(0)))
, MaxPoint(vtkm::Vec<FloatDefault, 3>(FloatDefault(1)))
{
}
inline Box::Box(vtkm::Vec<FloatDefault, 3> minPoint, vtkm::Vec<FloatDefault, 3> maxPoint)
: MinPoint(minPoint)
, MaxPoint(maxPoint)
{
}
inline Box::Box(FloatDefault xmin,
FloatDefault xmax,
FloatDefault ymin,
FloatDefault ymax,
FloatDefault zmin,
FloatDefault zmax)
{
MinPoint[0] = xmin;
MaxPoint[0] = xmax;
MinPoint[1] = ymin;
MaxPoint[1] = ymax;
MinPoint[2] = zmin;
MaxPoint[2] = zmax;
}
inline void Box::SetMinPoint(const vtkm::Vec<FloatDefault, 3>& point)
{
this->MinPoint = point;
this->Modified();
}
inline void Box::SetMaxPoint(const vtkm::Vec<FloatDefault, 3>& point)
{
this->MaxPoint = point;
this->Modified();
}
inline const vtkm::Vec<FloatDefault, 3>& Box::GetMinPoint() const
{
return this->MinPoint;
}
inline const vtkm::Vec<FloatDefault, 3>& Box::GetMaxPoint() const
{
return this->MaxPoint;
}
VTKM_EXEC_CONT
inline FloatDefault Box::Value(FloatDefault x, FloatDefault y, FloatDefault z) const
{
return this->Value(vtkm::Vec<vtkm::FloatDefault, 3>(x, y, z));
}
VTKM_EXEC_CONT
inline vtkm::Vec<FloatDefault, 3> Box::Gradient(FloatDefault x,
FloatDefault y,
FloatDefault z) const
{
return this->Gradient(vtkm::Vec<FloatDefault, 3>(x, y, z));
}
VTKM_EXEC_CONT
inline FloatDefault Box::Value(const vtkm::Vec<FloatDefault, 3>& x) const
{
FloatDefault minDistance = vtkm::NegativeInfinity32();
FloatDefault diff, t, dist;
FloatDefault distance = FloatDefault(0.0);
vtkm::IdComponent inside = 1;
for (vtkm::IdComponent d = 0; d < 3; d++)
{
diff = this->MaxPoint[d] - this->MinPoint[d];
if (diff != FloatDefault(0.0))
{
t = (x[d] - this->MinPoint[d]) / diff;
// Outside before the box
if (t < FloatDefault(0.0))
{
inside = 0;
dist = this->MinPoint[d] - x[d];
}
// Outside after the box
else if (t > FloatDefault(1.0))
{
inside = 0;
dist = x[d] - this->MaxPoint[d];
}
else
{
// Inside the box in lower half
if (t <= FloatDefault(0.5))
{
dist = MinPoint[d] - x[d];
}
// Inside the box in upper half
else
{
dist = x[d] - MaxPoint[d];
}
if (dist > minDistance)
{
minDistance = dist;
}
}
}
else
{
dist = vtkm::Abs(x[d] - MinPoint[d]);
if (dist > FloatDefault(0.0))
{
inside = 0;
}
}
if (dist > FloatDefault(0.0))
{
distance += dist * dist;
}
}
distance = vtkm::Sqrt(distance);
if (inside)
{
return minDistance;
}
else
{
return distance;
}
}
VTKM_EXEC_CONT
inline vtkm::Vec<FloatDefault, 3> Box::Gradient(const vtkm::Vec<FloatDefault, 3>& x) const
{
vtkm::IdComponent minAxis = 0;
FloatDefault dist = 0.0;
FloatDefault minDist = vtkm::Infinity32();
vtkm::Vec<vtkm::IdComponent, 3> location;
vtkm::Vec<FloatDefault, 3> normal(FloatDefault(0));
vtkm::Vec<FloatDefault, 3> inside(FloatDefault(0));
vtkm::Vec<FloatDefault, 3> outside(FloatDefault(0));
vtkm::Vec<FloatDefault, 3> center((this->MaxPoint + this->MinPoint) * FloatDefault(0.5));
// Compute the location of the point with respect to the box
// Point will lie in one of 27 separate regions around or within the box
// Gradient vector is computed differently in each of the regions.
for (vtkm::IdComponent d = 0; d < 3; d++)
{
if (x[d] < this->MinPoint[d])
{
// Outside the box low end
location[d] = 0;
outside[d] = -1.0;
}
else if (x[d] > this->MaxPoint[d])
{
// Outside the box high end
location[d] = 2;
outside[d] = 1.0;
}
else
{
location[d] = 1;
if (x[d] <= center[d])
{
// Inside the box low end
dist = x[d] - this->MinPoint[d];
inside[d] = -1.0;
}
else
{
// Inside the box high end
dist = this->MaxPoint[d] - x[d];
inside[d] = 1.0;
}
if (dist < minDist) // dist is negative
{
minDist = dist;
minAxis = d;
}
}
}
vtkm::Id indx = location[0] + 3 * location[1] + 9 * location[2];
switch (indx)
{
// verts - gradient points away from center point
case 0:
case 2:
case 6:
case 8:
case 18:
case 20:
case 24:
case 26:
for (vtkm::IdComponent d = 0; d < 3; d++)
{
normal[d] = x[d] - center[d];
}
vtkm::Normalize(normal);
break;
// edges - gradient points out from axis of cube
case 1:
case 3:
case 5:
case 7:
case 9:
case 11:
case 15:
case 17:
case 19:
case 21:
case 23:
case 25:
for (vtkm::IdComponent d = 0; d < 3; d++)
{
if (outside[d] != 0.0)
{
normal[d] = x[d] - center[d];
}
else
{
normal[d] = 0.0;
}
}
vtkm::Normalize(normal);
break;
// faces - gradient points perpendicular to face
case 4:
case 10:
case 12:
case 14:
case 16:
case 22:
for (vtkm::IdComponent d = 0; d < 3; d++)
{
normal[d] = outside[d];
}
break;
// interior - gradient is perpendicular to closest face
case 13:
normal[0] = normal[1] = normal[2] = 0.0;
normal[minAxis] = inside[minAxis];
break;
default:
VTKM_ASSERT(false);
break;
}
return normal;
}
//============================================================================
inline Cylinder::Cylinder()
: Center(FloatDefault(0))
, Axis(vtkm::make_Vec(FloatDefault(1), FloatDefault(0), FloatDefault(0)))
, Radius(FloatDefault(0.2))
{
}
inline Cylinder::Cylinder(const vtkm::Vec<FloatDefault, 3>& axis, FloatDefault radius)
: Center(FloatDefault(0))
, Axis(vtkm::Normal(axis))
, Radius(radius)
{
}
inline Cylinder::Cylinder(const vtkm::Vec<FloatDefault, 3>& center,
const vtkm::Vec<FloatDefault, 3>& axis,
FloatDefault radius)
: Center(center)
, Axis(vtkm::Normal(axis))
, Radius(radius)
{
}
inline void Cylinder::SetCenter(const vtkm::Vec<FloatDefault, 3>& center)
{
this->Center = center;
this->Modified();
}
inline void Cylinder::SetAxis(const vtkm::Vec<FloatDefault, 3>& axis)
{
this->Axis = vtkm::Normal(axis);
this->Modified();
}
inline void Cylinder::SetRadius(FloatDefault radius)
{
this->Radius = radius;
this->Modified();
}
inline const vtkm::Vec<FloatDefault, 3>& Cylinder::GetCenter() const
{
return this->Center;
}
inline const vtkm::Vec<FloatDefault, 3>& Cylinder::GetAxis() const
{
return this->Axis;
}
inline FloatDefault Cylinder::GetRadius() const
{
return this->Radius;
}
VTKM_EXEC_CONT
inline FloatDefault Cylinder::Value(const vtkm::Vec<FloatDefault, 3>& x) const
{
vtkm::Vec<FloatDefault, 3> x2c = x - this->Center;
FloatDefault proj = vtkm::dot(this->Axis, x2c);
return vtkm::dot(x2c, x2c) - (proj * proj) - (this->Radius * this->Radius);
}
VTKM_EXEC_CONT
inline FloatDefault Cylinder::Value(FloatDefault x, FloatDefault y, FloatDefault z) const
{
return this->Value(vtkm::Vec<vtkm::FloatDefault, 3>(x, y, z));
}
VTKM_EXEC_CONT
inline vtkm::Vec<FloatDefault, 3> Cylinder::Gradient(const vtkm::Vec<FloatDefault, 3>& x) const
{
vtkm::Vec<FloatDefault, 3> x2c = x - this->Center;
FloatDefault t = this->Axis[0] * x2c[0] + this->Axis[1] * x2c[1] + this->Axis[2] * x2c[2];
vtkm::Vec<FloatDefault, 3> closestPoint = this->Center + (this->Axis * t);
return (x - closestPoint) * FloatDefault(2);
}
VTKM_EXEC_CONT
inline vtkm::Vec<FloatDefault, 3> Cylinder::Gradient(FloatDefault x,
FloatDefault y,
FloatDefault z) const
{
return this->Gradient(vtkm::Vec<FloatDefault, 3>(x, y, z));
}
//============================================================================
inline Frustum::Frustum()
{
std::fill(this->Points, this->Points + 6, vtkm::Vec<FloatDefault, 3>{});
std::fill(this->Normals, this->Normals + 6, vtkm::Vec<FloatDefault, 3>{});
}
inline Frustum::Frustum(const vtkm::Vec<FloatDefault, 3> points[6],
const vtkm::Vec<FloatDefault, 3> normals[6])
{
std::copy(points, points + 6, this->Points);
std::copy(normals, normals + 6, this->Normals);
}
inline Frustum::Frustum(const vtkm::Vec<FloatDefault, 3> points[8])
{
this->CreateFromPoints(points);
}
inline void Frustum::SetPlanes(const vtkm::Vec<FloatDefault, 3> points[6],
const vtkm::Vec<FloatDefault, 3> normals[6])
{
std::copy(points, points + 6, this->Points);
std::copy(normals, normals + 6, this->Normals);
this->Modified();
}
inline void Frustum::GetPlanes(vtkm::Vec<FloatDefault, 3> points[6],
vtkm::Vec<FloatDefault, 3> normals[6]) const
{
std::copy(this->Points, this->Points + 6, points);
std::copy(this->Normals, this->Normals + 6, normals);
}
inline const vtkm::Vec<FloatDefault, 3>* Frustum::GetPoints() const
{
return this->Points;
}
inline const vtkm::Vec<FloatDefault, 3>* Frustum::GetNormals() const
{
return this->Normals;
}
inline void Frustum::SetPlane(int idx,
vtkm::Vec<FloatDefault, 3>& point,
vtkm::Vec<FloatDefault, 3>& normal)
{
if (idx < 0 || idx >= 6)
{
std::string msg = "Plane idx ";
msg += std::to_string(idx) + " is out of range [0, 5]";
throw vtkm::cont::ErrorBadValue(msg);
}
this->Points[idx] = point;
this->Normals[idx] = normal;
this->Modified();
}
inline void Frustum::CreateFromPoints(const vtkm::Vec<FloatDefault, 3> points[8])
{
// XXX(clang-format-3.9): 3.8 is silly. 3.9 makes it look like this.
// clang-format off
int planes[6][3] = {
{ 3, 2, 0 }, { 4, 5, 7 }, { 0, 1, 4 }, { 1, 2, 5 }, { 2, 3, 6 }, { 3, 0, 7 }
};
// clang-format on
for (int i = 0; i < 6; ++i)
{
auto& v0 = points[planes[i][0]];
auto& v1 = points[planes[i][1]];
auto& v2 = points[planes[i][2]];
this->Points[i] = v0;
this->Normals[i] = vtkm::Normal(vtkm::Cross(v2 - v0, v1 - v0));
this->Modified();
}
}
VTKM_EXEC_CONT
inline FloatDefault Frustum::Value(FloatDefault x, FloatDefault y, FloatDefault z) const
{
FloatDefault maxVal = -std::numeric_limits<FloatDefault>::max();
for (int i = 0; i < 6; ++i)
{
auto& p = this->Points[i];
auto& n = this->Normals[i];
FloatDefault val = ((x - p[0]) * n[0]) + ((y - p[1]) * n[1]) + ((z - p[2]) * n[2]);
maxVal = vtkm::Max(maxVal, val);
}
return maxVal;
}
VTKM_EXEC_CONT
inline FloatDefault Frustum::Value(const vtkm::Vec<FloatDefault, 3>& x) const
{
return this->Value(x[0], x[1], x[2]);
}
VTKM_EXEC_CONT
inline vtkm::Vec<FloatDefault, 3> Frustum::Gradient(FloatDefault x,
FloatDefault y,
FloatDefault z) const
{
FloatDefault maxVal = -std::numeric_limits<FloatDefault>::max();
int maxValIdx = 0;
for (int i = 0; i < 6; ++i)
{
auto& p = this->Points[i];
auto& n = this->Normals[i];
FloatDefault val = ((x - p[0]) * n[0]) + ((y - p[1]) * n[1]) + ((z - p[2]) * n[2]);
if (val > maxVal)
{
maxVal = val;
maxValIdx = i;
}
}
return this->Normals[maxValIdx];
}
VTKM_EXEC_CONT
inline vtkm::Vec<FloatDefault, 3> Frustum::Gradient(const vtkm::Vec<FloatDefault, 3>& x) const
{
return this->Gradient(x[0], x[1], x[2]);
}
//============================================================================
inline Plane::Plane()
: Origin(FloatDefault(0))
, Normal(FloatDefault(0), FloatDefault(0), FloatDefault(1))
{
}
inline Plane::Plane(const vtkm::Vec<FloatDefault, 3>& normal)
: Origin(FloatDefault(0))
, Normal(normal)
{
}
inline Plane::Plane(const vtkm::Vec<FloatDefault, 3>& origin,
const vtkm::Vec<FloatDefault, 3>& normal)
: Origin(origin)
, Normal(normal)
{
}
inline void Plane::SetOrigin(const vtkm::Vec<FloatDefault, 3>& origin)
{
this->Origin = origin;
this->Modified();
}
inline void Plane::SetNormal(const vtkm::Vec<FloatDefault, 3>& normal)
{
this->Normal = normal;
this->Modified();
}
inline const vtkm::Vec<FloatDefault, 3>& Plane::GetOrigin() const
{
return this->Origin;
}
inline const vtkm::Vec<FloatDefault, 3>& Plane::GetNormal() const
{
return this->Normal;
}
VTKM_EXEC_CONT
inline FloatDefault Plane::Value(FloatDefault x, FloatDefault y, FloatDefault z) const
{
return ((x - this->Origin[0]) * this->Normal[0]) + ((y - this->Origin[1]) * this->Normal[1]) +
((z - this->Origin[2]) * this->Normal[2]);
}
VTKM_EXEC_CONT
inline FloatDefault Plane::Value(const vtkm::Vec<FloatDefault, 3>& x) const
{
return this->Value(x[0], x[1], x[2]);
}
VTKM_EXEC_CONT
inline vtkm::Vec<FloatDefault, 3> Plane::Gradient(FloatDefault, FloatDefault, FloatDefault) const
{
return this->Normal;
}
VTKM_EXEC_CONT
inline vtkm::Vec<FloatDefault, 3> Plane::Gradient(const vtkm::Vec<FloatDefault, 3>&) const
{
return this->Normal;
}
//============================================================================
inline Sphere::Sphere()
: Radius(FloatDefault(0.2))
, Center(FloatDefault(0))
{
}
inline Sphere::Sphere(FloatDefault radius)
: Radius(radius)
, Center(FloatDefault(0))
{
}
inline Sphere::Sphere(vtkm::Vec<FloatDefault, 3> center, FloatDefault radius)
: Radius(radius)
, Center(center)
{
}
inline void Sphere::SetRadius(FloatDefault radius)
{
this->Radius = radius;
this->Modified();
}
inline void Sphere::SetCenter(const vtkm::Vec<FloatDefault, 3>& center)
{
this->Center = center;
this->Modified();
}
inline FloatDefault Sphere::GetRadius() const
{
return this->Radius;
}
inline const vtkm::Vec<FloatDefault, 3>& Sphere::GetCenter() const
{
return this->Center;
}
VTKM_EXEC_CONT
inline FloatDefault Sphere::Value(FloatDefault x, FloatDefault y, FloatDefault z) const
{
return ((x - this->Center[0]) * (x - this->Center[0]) +
(y - this->Center[1]) * (y - this->Center[1]) +
(z - this->Center[2]) * (z - this->Center[2])) -
(this->Radius * this->Radius);
}
VTKM_EXEC_CONT
inline FloatDefault Sphere::Value(const vtkm::Vec<FloatDefault, 3>& x) const
{
return this->Value(x[0], x[1], x[2]);
}
VTKM_EXEC_CONT
inline vtkm::Vec<FloatDefault, 3> Sphere::Gradient(FloatDefault x,
FloatDefault y,
FloatDefault z) const
{
return this->Gradient(vtkm::Vec<FloatDefault, 3>(x, y, z));
}
VTKM_EXEC_CONT
inline vtkm::Vec<FloatDefault, 3> Sphere::Gradient(const vtkm::Vec<FloatDefault, 3>& x) const
{
return FloatDefault(2) * (x - this->Center);
}
}
} // vtkm::cont

@ -0,0 +1,78 @@
//============================================================================
// 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.
//
// Copyright 2017 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2017 UT-Battelle, LLC.
// Copyright 2017 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#ifndef vtk_m_cont_ImplicitFunctionHandle_h
#define vtk_m_cont_ImplicitFunctionHandle_h
#include <vtkm/ImplicitFunction.h>
#include <vtkm/cont/VirtualObjectHandle.h>
namespace vtkm
{
namespace cont
{
class VTKM_ALWAYS_EXPORT ImplicitFunctionHandle
: public vtkm::cont::VirtualObjectHandle<vtkm::ImplicitFunction>
{
private:
using Superclass = vtkm::cont::VirtualObjectHandle<vtkm::ImplicitFunction>;
public:
ImplicitFunctionHandle() = default;
template <typename ImplicitFunctionType,
typename DeviceAdapterList = VTKM_DEFAULT_DEVICE_ADAPTER_LIST_TAG>
explicit ImplicitFunctionHandle(ImplicitFunctionType* function,
bool acquireOwnership = true,
DeviceAdapterList devices = DeviceAdapterList())
: Superclass(function, acquireOwnership, devices)
{
}
};
template <typename ImplicitFunctionType,
typename DeviceAdapterList = VTKM_DEFAULT_DEVICE_ADAPTER_LIST_TAG>
VTKM_CONT ImplicitFunctionHandle
make_ImplicitFunctionHandle(ImplicitFunctionType&& func,
DeviceAdapterList devices = DeviceAdapterList())
{
using IFType = typename std::remove_reference<ImplicitFunctionType>::type;
return ImplicitFunctionHandle(
new IFType(std::forward<ImplicitFunctionType>(func)), true, devices);
}
template <typename ImplicitFunctionType, typename... Args>
VTKM_CONT ImplicitFunctionHandle make_ImplicitFunctionHandle(Args&&... args)
{
return ImplicitFunctionHandle(new ImplicitFunctionType(std::forward<Args>(args)...),
true,
VTKM_DEFAULT_DEVICE_ADAPTER_LIST_TAG());
}
template <typename ImplicitFunctionType, typename DeviceAdapterList, typename... Args>
VTKM_CONT ImplicitFunctionHandle make_ImplicitFunctionHandle(Args&&... args)
{
return ImplicitFunctionHandle(
new ImplicitFunctionType(std::forward<Args>(args)...), true, DeviceAdapterList());
}
}
} // vtkm::cont
#endif // vtk_m_cont_ImplicitFunctionHandle_h

@ -29,7 +29,10 @@
#include <vtkm/cont/tbb/DeviceAdapterTBB.h>
#include <algorithm>
#include <map>
#include <mutex>
#include <sstream>
#include <thread>
#define VTKM_MAX_DEVICE_ADAPTER_ID 8
@ -155,8 +158,22 @@ void RuntimeDeviceTracker::ForceDeviceImpl(vtkm::cont::DeviceAdapterId deviceId,
VTKM_CONT
vtkm::cont::RuntimeDeviceTracker GetGlobalRuntimeDeviceTracker()
{
static vtkm::cont::RuntimeDeviceTracker globalTracker;
return globalTracker;
static std::mutex mtx;
static std::map<std::thread::id, vtkm::cont::RuntimeDeviceTracker> globalTrackers;
std::thread::id this_id = std::this_thread::get_id();
std::unique_lock<std::mutex> lock(mtx);
auto iter = globalTrackers.find(this_id);
if (iter != globalTrackers.end())
{
return iter->second;
}
else
{
vtkm::cont::RuntimeDeviceTracker tracker;
globalTrackers[this_id] = tracker;
return tracker;
}
}
}
} // namespace vtkm::cont

@ -74,6 +74,17 @@ public:
this->SetDeviceState(Traits::GetId(), Traits::GetName(), false);
}
/// Report a failure to allocate memory on a device, this will flag the
/// device as being unusable for all future invocations of the instance of
/// the filter.
///
VTKM_CONT void ReportAllocationFailure(vtkm::Int8 deviceId,
const std::string& name,
const vtkm::cont::ErrorBadAllocation&)
{
this->SetDeviceState(deviceId, name, false);
}
/// Reset the tracker for the given device. This will discard any updates
/// caused by reported failures
///
@ -196,13 +207,13 @@ private:
bool runtimeExists);
};
/// \brief Get the global \c RuntimeDeviceTracker.
/// \brief Get the \c RuntimeDeviceTracker for the current thread.
///
/// Many features in VTK-m will attempt to run algorithms on the "best
/// available device." This often is determined at runtime as failures in
/// one device are recorded and that device is disabled. To prevent having
/// to check over and over again, VTK-m features generally use the global
/// device adapter so that these choices are marked and shared.
/// to check over and over again, VTK-m uses per thread runtime device tracker
/// so that these choices are marked and shared.
///
VTKM_CONT_EXPORT
VTKM_CONT

77
vtkm/cont/TryExecute.cxx Normal file

@ -0,0 +1,77 @@
//============================================================================
// 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.
//
// Copyright 2016 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2016 UT-Battelle, LLC.
// Copyright 2016 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#include <vtkm/cont/ErrorBadAllocation.h>
#include <vtkm/cont/ErrorBadType.h>
#include <vtkm/cont/ErrorBadValue.h>
#include <vtkm/cont/TryExecute.h>
namespace vtkm
{
namespace cont
{
namespace detail
{
void HandleTryExecuteException(vtkm::Int8 deviceId,
const std::string& name,
vtkm::cont::RuntimeDeviceTracker& tracker)
{
try
{
//re-throw the last exception
throw;
}
catch (vtkm::cont::ErrorBadAllocation& e)
{
std::cerr << "caught ErrorBadAllocation " << e.GetMessage() << std::endl;
//currently we only consider OOM errors worth disabling a device for
//than we fallback to another device
tracker.ReportAllocationFailure(deviceId, name, e);
}
catch (vtkm::cont::ErrorBadType& e)
{
//should bad type errors should stop the execution, instead of
//deferring to another device adapter?
std::cerr << "caught ErrorBadType : " << e.GetMessage() << std::endl;
}
catch (vtkm::cont::ErrorBadValue& e)
{
//should bad value errors should stop the filter, instead of deferring
//to another device adapter?
std::cerr << "caught ErrorBadValue : " << e.GetMessage() << std::endl;
}
catch (vtkm::cont::Error& e)
{
//general errors should be caught and let us try the next device adapter.
std::cerr << "exception is: " << e.GetMessage() << std::endl;
}
catch (std::exception& e)
{
std::cerr << "caught standard exception: " << e.what() << std::endl;
}
catch (...)
{
std::cerr << "unknown exception caught" << std::endl;
}
}
}
}
}

@ -21,10 +21,6 @@
#define vtk_m_cont_TryExecute_h
#include <vtkm/cont/DeviceAdapterListTag.h>
#include <vtkm/cont/ErrorBadAllocation.h>
#include <vtkm/cont/ErrorBadType.h>
#include <vtkm/cont/ErrorBadValue.h>
#include <vtkm/cont/RuntimeDeviceTracker.h>
namespace vtkm
@ -35,123 +31,171 @@ namespace cont
namespace detail
{
template <typename Functor, typename Device, bool DeviceAdapterValid>
struct TryExecuteRunIfValid;
VTKM_CONT_EXPORT void HandleTryExecuteException(vtkm::Int8,
const std::string&,
vtkm::cont::RuntimeDeviceTracker&);
template <typename Functor, typename Device>
struct TryExecuteRunIfValid<Functor, Device, false>
template <typename DeviceTag, typename Functor, typename... Args>
bool TryExecuteIfValid(std::true_type,
DeviceTag tag,
Functor&& f,
vtkm::cont::RuntimeDeviceTracker& tracker,
Args&&... args)
{
VTKM_CONT
static bool Run(Functor&, const vtkm::cont::RuntimeDeviceTracker&) { return false; }
};
template <typename Functor, typename Device>
struct TryExecuteRunIfValid<Functor, Device, true>
{
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
VTKM_CONT
static bool Run(Functor& functor, vtkm::cont::RuntimeDeviceTracker tracker)
if (tracker.CanRunOn(tag))
{
if (tracker.CanRunOn(Device()))
try
{
try
{
return functor(Device());
}
catch (vtkm::cont::ErrorBadAllocation& e)
{
std::cerr << "caught ErrorBadAllocation " << e.GetMessage() << std::endl;
//currently we only consider OOM errors worth disabling a device for
//than we fallback to another device
tracker.ReportAllocationFailure(Device(), e);
}
catch (vtkm::cont::ErrorBadType& e)
{
//should bad type errors should stop the execution, instead of
//deferring to another device adapter?
std::cerr << "caught ErrorBadType : " << e.GetMessage() << std::endl;
}
catch (vtkm::cont::ErrorBadValue& e)
{
//should bad value errors should stop the filter, instead of deferring
//to another device adapter?
std::cerr << "caught ErrorBadValue : " << e.GetMessage() << std::endl;
}
catch (vtkm::cont::Error& e)
{
//general errors should be caught and let us try the next device adapter.
std::cerr << "exception is: " << e.GetMessage() << std::endl;
}
catch (std::exception& e)
{
std::cerr << "caught standard exception: " << e.what() << std::endl;
}
catch (...)
{
std::cerr << "unknown exception caught" << std::endl;
}
return f(tag, std::forward<Args>(args)...);
}
// If we are here, then the functor was either never run or failed.
return false;
}
};
template <typename FunctorType>
struct TryExecuteImpl
{
// Warning, these are a references. Make sure referenced objects do not go
// out of scope.
FunctorType& Functor;
vtkm::cont::RuntimeDeviceTracker Tracker;
bool Success;
VTKM_CONT
TryExecuteImpl(
FunctorType& functor,
vtkm::cont::RuntimeDeviceTracker tracker = vtkm::cont::GetGlobalRuntimeDeviceTracker())
: Functor(functor)
, Tracker(tracker)
, Success(false)
{
}
template <typename Device>
VTKM_CONT bool operator()(Device)
{
if (!this->Success)
catch (...)
{
using DeviceTraits = vtkm::cont::DeviceAdapterTraits<Device>;
this->Success = detail::TryExecuteRunIfValid<FunctorType, Device, DeviceTraits::Valid>::Run(
this->Functor, this->Tracker);
using Traits = vtkm::cont::DeviceAdapterTraits<DeviceTag>;
HandleTryExecuteException(Traits::GetId(), Traits::GetName(), tracker);
}
return this->Success;
}
private:
void operator=(const TryExecuteImpl<FunctorType>&) = delete;
// If we are here, then the functor was either never run or failed.
return false;
}
template <typename DeviceTag, typename Functor, typename... Args>
bool TryExecuteIfValid(std::false_type,
DeviceTag,
Functor&&,
vtkm::cont::RuntimeDeviceTracker&,
Args&&...)
{
return false;
}
struct TryExecuteWrapper
{
template <typename DeviceTag, typename Functor, typename... Args>
void operator()(DeviceTag tag,
Functor&& f,
vtkm::cont::RuntimeDeviceTracker& tracker,
bool& ran,
Args&&... args) const
{
if (!ran)
{
using DeviceTraits = vtkm::cont::DeviceAdapterTraits<DeviceTag>;
ran = TryExecuteIfValid(std::integral_constant<bool, DeviceTraits::Valid>(),
tag,
std::forward<Functor>(f),
std::forward<decltype(tracker)>(tracker),
std::forward<Args>(args)...);
}
}
};
template <typename Functor, typename DeviceList, typename... Args>
VTKM_CONT bool TryExecuteImpl(Functor&& functor,
std::true_type,
std::true_type,
vtkm::cont::RuntimeDeviceTracker& tracker,
DeviceList list,
Args&&... args)
{
bool success = false;
detail::TryExecuteWrapper task;
vtkm::ListForEach(
task, list, std::forward<Functor>(functor), tracker, success, std::forward<Args>(args)...);
return success;
}
template <typename Functor, typename... Args>
VTKM_CONT bool TryExecuteImpl(Functor&& functor, std::false_type, std::false_type, Args&&... args)
{
bool success = false;
auto tracker = vtkm::cont::GetGlobalRuntimeDeviceTracker();
detail::TryExecuteWrapper task;
vtkm::ListForEach(task,
VTKM_DEFAULT_DEVICE_ADAPTER_LIST_TAG(),
std::forward<Functor>(functor),
tracker,
success,
std::forward<Args>(args)...);
return success;
}
template <typename Functor, typename Arg1, typename... Args>
VTKM_CONT bool TryExecuteImpl(Functor&& functor,
std::true_type t,
std::false_type,
Arg1&& arg1,
Args&&... args)
{
return TryExecuteImpl(std::forward<Functor>(functor),
t,
t,
std::forward<Arg1>(arg1),
VTKM_DEFAULT_DEVICE_ADAPTER_LIST_TAG(),
std::forward<Args>(args)...);
}
template <typename Functor, typename Arg1, typename... Args>
VTKM_CONT bool TryExecuteImpl(Functor&& functor,
std::false_type,
std::true_type t,
Arg1&& arg1,
Args&&... args)
{
auto tracker = vtkm::cont::GetGlobalRuntimeDeviceTracker();
return TryExecuteImpl(std::forward<Functor>(functor),
t,
t,
tracker,
std::forward<Arg1>(arg1),
std::forward<Args>(args)...);
}
} // namespace detail
///@{
/// \brief Try to execute a functor on a list of devices until one succeeds.
///
/// This function takes a functor and a list of devices. It then tries to run
/// the functor for each device (in the order given in the list) until the
/// execution succeeds.
/// This function takes a functor and optionally a list of devices and \c RuntimeDeviceTracker.
/// It then tries to run the functor for each device (in the order given in the list) until the
/// execution succeeds. The optional \c RuntimeDeviceTracker allows for monitoring for certain
/// failures across calls to TryExecute and skip trying devices with a history of failure.
///
/// The functor parentheses operator should take exactly one argument, which is
/// the \c DeviceAdapterTag to use. The functor should return a \c bool that is
/// \c true if the execution succeeds, \c false if it fails. If an exception is
/// thrown from the functor, then the execution is assumed to have failed.
/// The TryExecute is also able to perfectly forward arbitrary arguments onto the functor.
/// These arguments must be placed after the optional \c RuntimeDeviceTracker, and device adapter
/// list and will passed to the functor in the same order as listed.
///
/// This function also optionally takes a \c RuntimeDeviceTracker, which will
/// monitor for certain failures across calls to TryExecute and skip trying
/// devices with a history of failure.
/// The functor must implement the function call operator ( \c operator() ) with a return type of
/// \c bool and that is \c true if the execution succeeds, \c false if it fails. If an exception
/// is thrown from the functor, then the execution is assumed to have failed. The functor call
/// operator must also take at least one argument being the required \c DeviceAdapterTag to use.
///
/// \code{.cpp}
/// struct TryCallExample
/// {
/// template<typename DeviceList>
/// bool operator()(DeviceList tags, int) const
/// {
/// return true;
/// }
/// };
///
///
/// // Executing without a runtime tracker or device list
/// vtkm::cont::TryExecute(TryCallExample(), int{42});
///
/// // Executing with a runtime tracker
/// auto tracker = vtkm::cont::GetGlobalRuntimeDeviceTracker();
/// vtkm::cont::TryExecute(TryCallExample(), tracker, int{42});
///
/// // Executing with a device list
/// using DeviceList = vtkm::ListTagBase<vtkm::cont::DeviceAdapterTagSerial>;
/// vtkm::cont::TryExecute(TryCallExample(), DeviceList(), int{42});
///
/// // Executing with a runtime tracker and device list
/// vtkm::cont::TryExecute(EdgeCaseFunctor(), tracker, DeviceList(), int{42});
///
/// \endcode
///
/// This function returns \c true if the functor succeeded on a device,
/// \c false otherwise.
@ -159,46 +203,57 @@ private:
/// If no device list is specified, then \c VTKM_DEFAULT_DEVICE_ADAPTER_LIST_TAG
/// is used.
///
template <typename Functor, typename DeviceList>
VTKM_CONT bool TryExecute(const Functor& functor,
vtkm::cont::RuntimeDeviceTracker tracker,
DeviceList)
{
detail::TryExecuteImpl<const Functor> internals(functor, tracker);
vtkm::ListForEach(internals, DeviceList());
return internals.Success;
}
template <typename Functor, typename DeviceList>
VTKM_CONT bool TryExecute(Functor& functor, vtkm::cont::RuntimeDeviceTracker tracker, DeviceList)
{
detail::TryExecuteImpl<Functor> internals(functor, tracker);
vtkm::ListForEach(internals, DeviceList());
return internals.Success;
}
template <typename Functor, typename DeviceList>
VTKM_CONT bool TryExecute(const Functor& functor, DeviceList)
{
return vtkm::cont::TryExecute(functor, vtkm::cont::GetGlobalRuntimeDeviceTracker(), DeviceList());
}
template <typename Functor, typename DeviceList>
VTKM_CONT bool TryExecute(Functor& functor, DeviceList)
{
return vtkm::cont::TryExecute(functor, vtkm::cont::GetGlobalRuntimeDeviceTracker(), DeviceList());
}
/// If no \c RuntimeDeviceTracker specified, then \c GetGlobalRuntimeDeviceTracker()
/// is used.
template <typename Functor>
VTKM_CONT bool TryExecute(
const Functor& functor,
vtkm::cont::RuntimeDeviceTracker tracker = vtkm::cont::GetGlobalRuntimeDeviceTracker())
VTKM_CONT bool TryExecute(Functor&& functor)
{
return vtkm::cont::TryExecute(functor, tracker, VTKM_DEFAULT_DEVICE_ADAPTER_LIST_TAG());
//we haven't been passed either a runtime tracker or a device list
return detail::TryExecuteImpl(functor, std::false_type{}, std::false_type{});
}
template <typename Functor>
VTKM_CONT bool TryExecute(
Functor& functor,
vtkm::cont::RuntimeDeviceTracker tracker = vtkm::cont::GetGlobalRuntimeDeviceTracker())
template <typename Functor, typename Arg1>
VTKM_CONT bool TryExecute(Functor&& functor, Arg1&& arg1)
{
return vtkm::cont::TryExecute(functor, tracker, VTKM_DEFAULT_DEVICE_ADAPTER_LIST_TAG());
//determine if we are being passed a device adapter or runtime tracker as our argument
using is_deviceAdapter = typename std::is_base_of<vtkm::detail::ListRoot, Arg1>::type;
using is_tracker = typename std::is_base_of<vtkm::cont::RuntimeDeviceTracker,
typename std::remove_reference<Arg1>::type>::type;
return detail::TryExecuteImpl(
functor, is_tracker{}, is_deviceAdapter{}, std::forward<Arg1>(arg1));
}
template <typename Functor, typename Arg1, typename Arg2, typename... Args>
VTKM_CONT bool TryExecute(Functor&& functor, Arg1&& arg1, Arg2&& arg2, Args&&... args)
{
//So arg1 can be runtime or device adapter
//if arg1 is runtime, we need to see if arg2 is device adapter
using is_arg1_tracker =
typename std::is_base_of<vtkm::cont::RuntimeDeviceTracker,
typename std::remove_reference<Arg1>::type>::type;
using is_arg2_devicelist = typename std::is_base_of<vtkm::detail::ListRoot, Arg2>::type;
//We now know what of three states we are currently at
using has_runtime_and_deviceAdapter =
brigand::bool_<is_arg1_tracker::value && is_arg2_devicelist::value>;
using has_just_runtime = brigand::bool_<is_arg1_tracker::value && !is_arg2_devicelist::value>;
using has_just_devicelist = typename std::is_base_of<vtkm::detail::ListRoot, Arg1>::type;
//With this information we can now compute if we have a runtime tracker and/or
//the device adapter and enable the correct flags
using first_true =
brigand::bool_<has_runtime_and_deviceAdapter::value || has_just_runtime::value>;
using second_true =
brigand::bool_<has_runtime_and_deviceAdapter::value || has_just_devicelist::value>;
return detail::TryExecuteImpl(functor,
first_true{},
second_true{},
std::forward<Arg1>(arg1),
std::forward<Arg2>(arg2),
std::forward<Args>(args)...);
}
//@} //block doxygen all TryExecute functions
}
} // namespace vtkm::cont

@ -1,310 +0,0 @@
//============================================================================
// 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.
//
// Copyright 2017 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2017 UT-Battelle, LLC.
// Copyright 2017 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#ifndef vtk_m_cont_VirtualObjectCache_h
#define vtk_m_cont_VirtualObjectCache_h
#include <vtkm/cont/DeviceAdapterListTag.h>
#include <vtkm/cont/ErrorBadType.h>
#include <vtkm/cont/ErrorBadValue.h>
#include <vtkm/cont/internal/DeviceAdapterTag.h>
#include <vtkm/cont/internal/VirtualObjectTransfer.h>
#include <array>
#include <type_traits>
#define VTKM_MAX_DEVICE_ADAPTER_ID 8
namespace vtkm
{
namespace cont
{
/// \brief Implements VTK-m's execution side <em> Virtual Methods </em>
/// functionality.
///
/// The template parameter \c VirtualObject is the class that acts as the
/// interface. Following is a method for implementing such classes:
/// 1. Create a <tt>const void*</tt> member variable that will hold a
/// reference to the target class.
/// 2. For each virtual-like method:
/// a. Create a typedef for a function with the same signature,
/// except for an extra <tt>const void*</tt> argument.
/// b. Create a function pointer member variable with the type of the
/// associated typedef from 2a.
/// c. Create an implementation of the method, that calls the associated
/// function pointer with the void pointer to the target class as one of
/// the arguments.
/// 3. Create the following template function:
/// \code{.cpp}
/// template<typename TargetClass>
/// VTKM_EXEC void Bind(const TargetClass *deviceTarget);
/// \endcode
/// This function should set the void pointer from 1 to \c deviceTarget,
/// and assign the function pointers from 2b to functions that cast their
/// first argument to <tt>const TargetClass*</tt> and call the corresponding
/// member function on it.
///
/// Both \c VirtualObject and target class objects should be bitwise copyable.
///
/// \sa vtkm::exec::ImplicitFunction, vtkm::cont::ImplicitFunction
///
template <typename VirtualObject>
class VirtualObjectCache
{
public:
VirtualObjectCache()
: Target(nullptr)
, CurrentDevice(VTKM_DEVICE_ADAPTER_UNDEFINED)
, DeviceState(nullptr)
, RefreshFlag(false)
{
}
~VirtualObjectCache() { this->Reset(); }
VirtualObjectCache(const VirtualObjectCache& other)
: Target(other.Target)
, Transfers(other.Transfers)
, CurrentDevice(VTKM_DEVICE_ADAPTER_UNDEFINED)
, DeviceState(nullptr)
, RefreshFlag(false)
{
}
VirtualObjectCache& operator=(const VirtualObjectCache& other)
{
if (this != &other)
{
this->Target = other.Target;
this->Transfers = other.Transfers;
this->CurrentDevice = VTKM_DEVICE_ADAPTER_UNDEFINED;
this->DeviceState = nullptr;
this->RefreshFlag = false;
this->Object = VirtualObject();
}
return *this;
}
VirtualObjectCache(VirtualObjectCache&& other)
: Target(other.Target)
, Transfers(other.Transfers)
, CurrentDevice(other.CurrentDevice)
, DeviceState(other.DeviceState)
, RefreshFlag(other.RefreshFlag)
, Object(other.Object)
{
other.CurrentDevice = VTKM_DEVICE_ADAPTER_UNDEFINED;
other.DeviceState = nullptr;
}
VirtualObjectCache& operator=(VirtualObjectCache&& other)
{
if (this != &other)
{
this->Target = other.Target;
this->Transfers = std::move(other.Transfers);
this->CurrentDevice = other.CurrentDevice;
this->DeviceState = other.DeviceState;
this->RefreshFlag = other.RefreshFlag;
this->Object = std::move(other.Object);
other.CurrentDevice = VTKM_DEVICE_ADAPTER_UNDEFINED;
other.DeviceState = nullptr;
}
return *this;
}
/// Reset to the default constructed state
void Reset()
{
this->ReleaseResources();
this->Target = nullptr;
this->Transfers.fill(TransferInterface());
}
void ReleaseResources()
{
if (this->CurrentDevice > 0)
{
this->GetCurrentTransfer().Cleanup(this->DeviceState);
this->CurrentDevice = VTKM_DEVICE_ADAPTER_UNDEFINED;
this->DeviceState = nullptr;
this->RefreshFlag = false;
this->Object = VirtualObject();
}
}
/// Get if in a valid state (a target is bound)
bool GetValid() const { return this->Target != nullptr; }
// Set/Get if the cached virtual object should be refreshed to the current
// state of the target
void SetRefreshFlag(bool value) { this->RefreshFlag = value; }
bool GetRefreshFlag() const { return this->RefreshFlag; }
/// Bind to \c target. The lifetime of target is expected to be managed
/// externally, and should be valid for as long as it is bound.
/// Also accepts a list-tag of device adapters where the virtual
/// object may be used (default = \c VTKM_DEFAULT_DEVICE_ADAPTER_LIST_TAG).
///
template <typename TargetClass, typename DeviceAdapterList = VTKM_DEFAULT_DEVICE_ADAPTER_LIST_TAG>
void Bind(const TargetClass* target, DeviceAdapterList devices = DeviceAdapterList())
{
this->Reset();
this->Target = target;
vtkm::ListForEach(CreateTransferInterface<TargetClass>(this->Transfers.data()), devices);
}
/// Get a \c VirtualObject for \c DeviceAdapter.
/// VirtualObjectCache and VirtualObject are analogous to ArrayHandle and Portal
/// The returned VirtualObject will be invalidated if:
/// 1. A new VirtualObject is requested for a different DeviceAdapter
/// 2. VirtualObjectCache is destroyed
/// 3. Reset or ReleaseResources is called
///
template <typename DeviceAdapter>
VirtualObject GetVirtualObject(DeviceAdapter)
{
using DeviceInfo = vtkm::cont::DeviceAdapterTraits<DeviceAdapter>;
if (!this->GetValid())
{
throw vtkm::cont::ErrorBadValue("No target object bound");
}
vtkm::cont::DeviceAdapterId deviceId = DeviceInfo::GetId();
if (deviceId < 0 || deviceId >= VTKM_MAX_DEVICE_ADAPTER_ID)
{
std::string msg = "Device '" + DeviceInfo::GetName() + "' has invalid ID of " +
std::to_string(deviceId) + "(VTKM_MAX_DEVICE_ADAPTER_ID = " +
std::to_string(VTKM_MAX_DEVICE_ADAPTER_ID) + ")";
throw vtkm::cont::ErrorBadType(msg);
}
if (this->CurrentDevice != deviceId)
{
this->ReleaseResources();
std::size_t idx = static_cast<std::size_t>(deviceId);
TransferInterface& transfer = this->Transfers[idx];
if (!TransferInterfaceValid(transfer))
{
std::string msg = DeviceInfo::GetName() + " was not in the list specified in Bind";
throw vtkm::cont::ErrorBadType(msg);
}
this->CurrentDevice = deviceId;
this->DeviceState = transfer.Create(this->Object, this->Target);
}
else if (this->RefreshFlag)
{
this->GetCurrentTransfer().Update(this->DeviceState, this->Target);
}
this->RefreshFlag = false;
return this->Object;
}
private:
struct TransferInterface
{
using CreateSig = void*(VirtualObject&, const void*);
using UpdateSig = void(void*, const void*);
using CleanupSig = void(void*);
CreateSig* Create = nullptr;
UpdateSig* Update = nullptr;
CleanupSig* Cleanup = nullptr;
};
static bool TransferInterfaceValid(const TransferInterface& t) { return t.Create != nullptr; }
TransferInterface& GetCurrentTransfer()
{
return this->Transfers[static_cast<std::size_t>(this->CurrentDevice)];
}
template <typename TargetClass>
class CreateTransferInterface
{
private:
template <typename DeviceAdapter>
using EnableIfValid = std::enable_if<vtkm::cont::DeviceAdapterTraits<DeviceAdapter>::Valid>;
template <typename DeviceAdapter>
using EnableIfInvalid = std::enable_if<!vtkm::cont::DeviceAdapterTraits<DeviceAdapter>::Valid>;
public:
CreateTransferInterface(TransferInterface* transfers)
: Transfers(transfers)
{
}
// Use SFINAE to create entries for valid device adapters only
template <typename DeviceAdapter>
typename EnableIfValid<DeviceAdapter>::type operator()(DeviceAdapter) const
{
using DeviceInfo = vtkm::cont::DeviceAdapterTraits<DeviceAdapter>;
if (DeviceInfo::GetId() >= 0 && DeviceInfo::GetId() < VTKM_MAX_DEVICE_ADAPTER_ID)
{
using TransferImpl =
internal::VirtualObjectTransfer<VirtualObject, TargetClass, DeviceAdapter>;
std::size_t id = static_cast<std::size_t>(DeviceInfo::GetId());
TransferInterface& transfer = this->Transfers[id];
transfer.Create = &TransferImpl::Create;
transfer.Update = &TransferImpl::Update;
transfer.Cleanup = &TransferImpl::Cleanup;
}
else
{
std::string msg = "Device '" + DeviceInfo::GetName() + "' has invalid ID of " +
std::to_string(DeviceInfo::GetId()) + "(VTKM_MAX_DEVICE_ADAPTER_ID = " +
std::to_string(VTKM_MAX_DEVICE_ADAPTER_ID) + ")";
throw vtkm::cont::ErrorBadType(msg);
}
}
template <typename DeviceAdapter>
typename EnableIfInvalid<DeviceAdapter>::type operator()(DeviceAdapter) const
{
}
private:
TransferInterface* Transfers;
};
const void* Target;
std::array<TransferInterface, VTKM_MAX_DEVICE_ADAPTER_ID> Transfers;
vtkm::cont::DeviceAdapterId CurrentDevice;
void* DeviceState;
bool RefreshFlag;
VirtualObject Object;
};
}
} // vtkm::cont
#undef VTKM_MAX_DEVICE_ADAPTER_ID
#endif // vtk_m_cont_VirtualObjectCache_h

@ -0,0 +1,277 @@
//============================================================================
// 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.
//
// Copyright 2017 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2017 UT-Battelle, LLC.
// Copyright 2017 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#ifndef vtk_m_cont_VirtualObjectHandle_h
#define vtk_m_cont_VirtualObjectHandle_h
#include <vtkm/cont/DeviceAdapterListTag.h>
#include <vtkm/cont/ErrorBadType.h>
#include <vtkm/cont/ErrorBadValue.h>
#include <vtkm/cont/internal/DeviceAdapterTag.h>
#include <vtkm/cont/internal/VirtualObjectTransfer.h>
#include <array>
#include <type_traits>
#define VTKM_MAX_DEVICE_ADAPTER_ID 8
namespace vtkm
{
namespace cont
{
/// \brief Implements VTK-m's execution side <em> Virtual Methods </em> functionality.
///
/// The template parameter \c VirtualBaseType is the base class that acts as the
/// interface. This base clase must inherit from \c vtkm::VirtualObjectBase. See the
/// documentation of that class to see the other requirements.
///
/// A derived object can be bound to the handle either during construction or using the \c Reset
/// function on previously constructed handles. These function accept a control side pointer to
/// the derived class object, a boolean flag stating if the handle should acquire ownership of
/// the object (i.e. manage the lifetime), and a type-list of device adapter tags where the object
/// is expected to be used.
///
/// To get an execution side pointer call the \c PrepareForExecution function. The device adapter
/// passed to this function should be one of the device in the list passed during the set up of
/// the handle.
///
///
/// \sa vtkm::VirtualObjectBase
///
template <typename VirtualBaseType>
class VTKM_ALWAYS_EXPORT VirtualObjectHandle
{
VTKM_STATIC_ASSERT_MSG((std::is_base_of<vtkm::VirtualObjectBase, VirtualBaseType>::value),
"All virtual objects must be subclass of vtkm::VirtualObjectBase.");
public:
VTKM_CONT VirtualObjectHandle()
: Internals(new InternalStruct)
{
}
template <typename VirtualDerivedType,
typename DeviceAdapterList = VTKM_DEFAULT_DEVICE_ADAPTER_LIST_TAG>
VTKM_CONT explicit VirtualObjectHandle(VirtualDerivedType* derived,
bool acquireOwnership = true,
DeviceAdapterList devices = DeviceAdapterList())
: Internals(new InternalStruct)
{
this->Reset(derived, acquireOwnership, devices);
}
/// Get if in a valid state (a target is bound)
VTKM_CONT bool GetValid() const { return this->Internals->VirtualObject != nullptr; }
/// Get if this handle owns the control side target object
VTKM_CONT bool OwnsObject() const { return this->Internals->Owner; }
/// Get the control side pointer to the virtual object
VTKM_CONT VirtualBaseType* Get() const { return this->Internals->VirtualObject; }
/// Reset the underlying derived type object
template <typename VirtualDerivedType,
typename DeviceAdapterList = VTKM_DEFAULT_DEVICE_ADAPTER_LIST_TAG>
VTKM_CONT void Reset(VirtualDerivedType* derived,
bool acquireOwnership = true,
DeviceAdapterList devices = DeviceAdapterList())
{
this->Reset();
if (derived)
{
VTKM_STATIC_ASSERT_MSG((std::is_base_of<VirtualBaseType, VirtualDerivedType>::value),
"Tried to bind a type that is not a subclass of the base class.");
this->Internals->VirtualObject = derived;
this->Internals->Owner = acquireOwnership;
vtkm::cont::ForEachValidDevice(
devices,
CreateTransferInterface<VirtualDerivedType>(this->Internals->Transfers.data(), derived));
}
}
void Reset() { this->Internals->Reset(); }
/// Release all the execution side resources
VTKM_CONT void ReleaseExecutionResources() { this->Internals->ReleaseExecutionResources(); }
/// Get a valid \c VirtualBaseType* with the current control side state for \c DeviceAdapter.
/// VirtualObjectHandle and the returned pointer are analogous to ArrayHandle and Portal
/// The returned pointer will be invalidated if:
/// 1. A new pointer is requested for a different DeviceAdapter
/// 2. VirtualObjectHandle is destroyed
/// 3. Reset or ReleaseResources is called
///
template <typename DeviceAdapter>
VTKM_CONT const VirtualBaseType* PrepareForExecution(DeviceAdapter) const
{
using DeviceInfo = vtkm::cont::DeviceAdapterTraits<DeviceAdapter>;
if (!this->GetValid())
{
throw vtkm::cont::ErrorBadValue("No target object bound");
}
vtkm::cont::DeviceAdapterId deviceId = DeviceInfo::GetId();
if (deviceId < 0 || deviceId >= VTKM_MAX_DEVICE_ADAPTER_ID)
{
std::string msg = "Device '" + DeviceInfo::GetName() + "' has invalid ID of " +
std::to_string(deviceId) + "(VTKM_MAX_DEVICE_ADAPTER_ID = " +
std::to_string(VTKM_MAX_DEVICE_ADAPTER_ID) + ")";
throw vtkm::cont::ErrorBadType(msg);
}
if (!this->Internals->Current || this->Internals->Current->GetDeviceId() != deviceId)
{
if (!this->Internals->Transfers[static_cast<std::size_t>(deviceId)])
{
std::string msg = DeviceInfo::GetName() + " was not in the list specified in Bind";
throw vtkm::cont::ErrorBadType(msg);
}
if (this->Internals->Current)
{
this->Internals->Current->ReleaseResources();
}
this->Internals->Current =
this->Internals->Transfers[static_cast<std::size_t>(deviceId)].get();
}
return this->Internals->Current->PrepareForExecution();
}
private:
class TransferInterface
{
public:
VTKM_CONT virtual ~TransferInterface() = default;
VTKM_CONT virtual vtkm::cont::DeviceAdapterId GetDeviceId() const = 0;
VTKM_CONT virtual const VirtualBaseType* PrepareForExecution() = 0;
VTKM_CONT virtual void ReleaseResources() = 0;
};
template <typename VirtualDerivedType, typename DeviceAdapter>
class TransferInterfaceImpl : public TransferInterface
{
public:
VTKM_CONT TransferInterfaceImpl(const VirtualDerivedType* virtualObject)
: LastModifiedCount(-1)
, VirtualObject(virtualObject)
, Transfer(virtualObject)
{
}
VTKM_CONT vtkm::cont::DeviceAdapterId GetDeviceId() const override
{
return vtkm::cont::DeviceAdapterTraits<DeviceAdapter>::GetId();
}
VTKM_CONT const VirtualBaseType* PrepareForExecution() override
{
vtkm::Id modifiedCount = this->VirtualObject->GetModifiedCount();
bool updateData = (this->LastModifiedCount != modifiedCount);
const VirtualBaseType* executionObject = this->Transfer.PrepareForExecution(updateData);
this->LastModifiedCount = modifiedCount;
return executionObject;
}
VTKM_CONT void ReleaseResources() override { this->Transfer.ReleaseResources(); }
private:
vtkm::Id LastModifiedCount;
const VirtualDerivedType* VirtualObject;
vtkm::cont::internal::VirtualObjectTransfer<VirtualDerivedType, DeviceAdapter> Transfer;
};
template <typename VirtualDerivedType>
class CreateTransferInterface
{
public:
CreateTransferInterface(std::unique_ptr<TransferInterface>* transfers,
const VirtualDerivedType* virtualObject)
: Transfers(transfers)
, VirtualObject(virtualObject)
{
}
template <typename DeviceAdapter>
void operator()(DeviceAdapter) const
{
using DeviceInfo = vtkm::cont::DeviceAdapterTraits<DeviceAdapter>;
if (DeviceInfo::GetId() < 0 || DeviceInfo::GetId() >= VTKM_MAX_DEVICE_ADAPTER_ID)
{
std::string msg = "Device '" + DeviceInfo::GetName() + "' has invalid ID of " +
std::to_string(DeviceInfo::GetId()) + "(VTKM_MAX_DEVICE_ADAPTER_ID = " +
std::to_string(VTKM_MAX_DEVICE_ADAPTER_ID) + ")";
throw vtkm::cont::ErrorBadType(msg);
}
using TransferImpl = TransferInterfaceImpl<VirtualDerivedType, DeviceAdapter>;
this->Transfers[DeviceInfo::GetId()].reset(new TransferImpl(this->VirtualObject));
}
private:
std::unique_ptr<TransferInterface>* Transfers;
const VirtualDerivedType* VirtualObject;
};
struct InternalStruct
{
VirtualBaseType* VirtualObject = nullptr;
bool Owner = false;
std::array<std::unique_ptr<TransferInterface>, VTKM_MAX_DEVICE_ADAPTER_ID> Transfers;
TransferInterface* Current = nullptr;
VTKM_CONT void ReleaseExecutionResources()
{
if (this->Current)
{
this->Current->ReleaseResources();
this->Current = nullptr;
}
}
VTKM_CONT void Reset()
{
this->ReleaseExecutionResources();
for (auto& transfer : this->Transfers)
{
transfer.reset(nullptr);
}
if (this->Owner)
{
delete this->VirtualObject;
}
this->VirtualObject = nullptr;
this->Owner = false;
}
VTKM_CONT ~InternalStruct() { this->Reset(); }
};
std::shared_ptr<InternalStruct> Internals;
};
}
} // vtkm::cont
#undef VTKM_MAX_DEVICE_ADAPTER_ID
#endif // vtk_m_cont_VirtualObjectHandle_h

@ -133,6 +133,7 @@ void ExecutionArrayInterfaceBasic<DeviceAdapterTagCuda>::CopyFromControl(
// execution:
if (controlPtr == executionPtr && CudaAllocator::IsDevicePointer(controlPtr))
{
CudaAllocator::PrepareForInput(executionPtr, numBytes);
return;
}
@ -160,6 +161,7 @@ void ExecutionArrayInterfaceBasic<DeviceAdapterTagCuda>::CopyToControl(const voi
}
// If it is managed, just return and let CUDA handle the migration for us.
CudaAllocator::PrepareForControl(controlPtr, numBytes);
return;
}
@ -170,6 +172,29 @@ void ExecutionArrayInterfaceBasic<DeviceAdapterTagCuda>::CopyToControl(const voi
cudaStreamPerThread));
}
void ExecutionArrayInterfaceBasic<DeviceAdapterTagCuda>::UsingForRead(const void* controlPtr,
const void* executionPtr,
vtkm::UInt64 numBytes) const
{
CudaAllocator::PrepareForInput(executionPtr, static_cast<size_t>(numBytes));
}
void ExecutionArrayInterfaceBasic<DeviceAdapterTagCuda>::UsingForWrite(const void* controlPtr,
const void* executionPtr,
vtkm::UInt64 numBytes) const
{
CudaAllocator::PrepareForOutput(executionPtr, static_cast<size_t>(numBytes));
}
void ExecutionArrayInterfaceBasic<DeviceAdapterTagCuda>::UsingForReadWrite(
const void* controlPtr,
const void* executionPtr,
vtkm::UInt64 numBytes) const
{
CudaAllocator::PrepareForInPlace(executionPtr, static_cast<size_t>(numBytes));
}
} // end namespace internal
VTKM_INSTANTIATE_ARRAYHANDLES_FOR_DEVICE_ADAPTER(DeviceAdapterTagCuda)

@ -159,6 +159,16 @@ struct VTKM_CONT_EXPORT ExecutionArrayInterfaceBasic<DeviceAdapterTagCuda>
VTKM_CONT void CopyToControl(const void* executionPtr,
void* controlPtr,
vtkm::UInt64 numBytes) const final;
VTKM_CONT void UsingForRead(const void* controlPtr,
const void* executionPtr,
vtkm::UInt64 numBytes) const final;
VTKM_CONT void UsingForWrite(const void* controlPtr,
const void* executionPtr,
vtkm::UInt64 numBytes) const final;
VTKM_CONT void UsingForReadWrite(const void* controlPtr,
const void* executionPtr,
vtkm::UInt64 numBytes) const final;
};
} // namespace internal

@ -52,6 +52,7 @@ bool CudaAllocator::UsingManagedMemory()
bool CudaAllocator::IsDevicePointer(const void* ptr)
{
CudaAllocator::Initialize();
if (!ptr)
{
return false;
@ -72,7 +73,7 @@ bool CudaAllocator::IsDevicePointer(const void* ptr)
bool CudaAllocator::IsManagedPointer(const void* ptr)
{
if (!ptr)
if (!ptr || !ManagedMemorySupported)
{
return false;
}
@ -109,23 +110,17 @@ void* CudaAllocator::Allocate(std::size_t numBytes)
void CudaAllocator::Free(void* ptr)
{
CudaAllocator::Initialize();
VTKM_CUDA_CALL(cudaFree(ptr));
}
void CudaAllocator::PrepareForControl(const void* ptr, std::size_t numBytes)
{
CudaAllocator::Initialize();
if (ManagedMemorySupported)
if (IsManagedPointer(ptr))
{
#if CUDART_VERSION >= 8000
// TODO these hints need to be benchmarked and adjusted once we start
// sharing the pointers between cont/exec
VTKM_CUDA_CALL(
cudaMemAdvise(ptr, numBytes, cudaMemAdviseSetPreferredLocation, cudaCpuDeviceId));
VTKM_CUDA_CALL(cudaMemAdvise(ptr, numBytes, cudaMemAdviseUnsetReadMostly, cudaCpuDeviceId));
VTKM_CUDA_CALL(cudaMemAdvise(ptr, numBytes, cudaMemAdviseSetAccessedBy, cudaCpuDeviceId));
VTKM_CUDA_CALL(cudaMemPrefetchAsync(ptr, numBytes, cudaCpuDeviceId, cudaStreamPerThread));
#endif // CUDA >= 8.0
}
@ -133,15 +128,14 @@ void CudaAllocator::PrepareForControl(const void* ptr, std::size_t numBytes)
void CudaAllocator::PrepareForInput(const void* ptr, std::size_t numBytes)
{
CudaAllocator::Initialize();
if (ManagedMemorySupported)
if (IsManagedPointer(ptr))
{
#if CUDART_VERSION >= 8000
int dev;
VTKM_CUDA_CALL(cudaGetDevice(&dev));
VTKM_CUDA_CALL(cudaMemAdvise(ptr, numBytes, cudaMemAdviseSetPreferredLocation, dev));
VTKM_CUDA_CALL(cudaMemAdvise(ptr, numBytes, cudaMemAdviseSetReadMostly, dev));
// VTKM_CUDA_CALL(cudaMemAdvise(ptr, numBytes, cudaMemAdviseSetPreferredLocation, dev));
// VTKM_CUDA_CALL(cudaMemAdvise(ptr, numBytes, cudaMemAdviseSetReadMostly, dev));
VTKM_CUDA_CALL(cudaMemAdvise(ptr, numBytes, cudaMemAdviseSetAccessedBy, dev));
VTKM_CUDA_CALL(cudaMemPrefetchAsync(ptr, numBytes, dev, cudaStreamPerThread));
#endif // CUDA >= 8.0
}
@ -149,15 +143,14 @@ void CudaAllocator::PrepareForInput(const void* ptr, std::size_t numBytes)
void CudaAllocator::PrepareForOutput(const void* ptr, std::size_t numBytes)
{
CudaAllocator::Initialize();
if (ManagedMemorySupported)
if (IsManagedPointer(ptr))
{
#if CUDART_VERSION >= 8000
int dev;
VTKM_CUDA_CALL(cudaGetDevice(&dev));
VTKM_CUDA_CALL(cudaMemAdvise(ptr, numBytes, cudaMemAdviseSetPreferredLocation, dev));
VTKM_CUDA_CALL(cudaMemAdvise(ptr, numBytes, cudaMemAdviseUnsetReadMostly, dev));
// VTKM_CUDA_CALL(cudaMemAdvise(ptr, numBytes, cudaMemAdviseSetPreferredLocation, dev));
// VTKM_CUDA_CALL(cudaMemAdvise(ptr, numBytes, cudaMemAdviseUnsetReadMostly, dev));
VTKM_CUDA_CALL(cudaMemAdvise(ptr, numBytes, cudaMemAdviseSetAccessedBy, dev));
VTKM_CUDA_CALL(cudaMemPrefetchAsync(ptr, numBytes, dev, cudaStreamPerThread));
#endif // CUDA >= 8.0
}
@ -165,15 +158,14 @@ void CudaAllocator::PrepareForOutput(const void* ptr, std::size_t numBytes)
void CudaAllocator::PrepareForInPlace(const void* ptr, std::size_t numBytes)
{
CudaAllocator::Initialize();
if (ManagedMemorySupported)
if (IsManagedPointer(ptr))
{
#if CUDART_VERSION >= 8000
int dev;
VTKM_CUDA_CALL(cudaGetDevice(&dev));
VTKM_CUDA_CALL(cudaMemAdvise(ptr, numBytes, cudaMemAdviseSetPreferredLocation, dev));
VTKM_CUDA_CALL(cudaMemAdvise(ptr, numBytes, cudaMemAdviseUnsetReadMostly, dev));
// VTKM_CUDA_CALL(cudaMemAdvise(ptr, numBytes, cudaMemAdviseSetPreferredLocation, dev));
// VTKM_CUDA_CALL(cudaMemAdvise(ptr, numBytes, cudaMemAdviseUnsetReadMostly, dev));
VTKM_CUDA_CALL(cudaMemAdvise(ptr, numBytes, cudaMemAdviseSetAccessedBy, dev));
VTKM_CUDA_CALL(cudaMemPrefetchAsync(ptr, numBytes, dev, cudaStreamPerThread));
#endif // CUDA >= 8.0
}

@ -20,6 +20,7 @@
#ifndef vtk_m_cont_cuda_internal_VirtualObjectTransferCuda_h
#define vtk_m_cont_cuda_internal_VirtualObjectTransferCuda_h
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/cuda/ErrorCuda.h>
#include <vtkm/cont/cuda/internal/DeviceAdapterTagCuda.h>
#include <vtkm/cont/internal/VirtualObjectTransfer.h>
@ -34,45 +35,108 @@ namespace internal
namespace detail
{
template <typename VirtualObject, typename TargetClass>
__global__ void CreateKernel(VirtualObject* object, const TargetClass* target)
template <typename VirtualDerivedType>
__global__ void ConstructVirtualObjectKernel(VirtualDerivedType* deviceObject,
const VirtualDerivedType* targetObject)
{
object->Bind(target);
// Use the "placement new" syntax to construct an object in pre-allocated memory
new (deviceObject) VirtualDerivedType(*targetObject);
}
template <typename VirtualDerivedType>
__global__ void UpdateVirtualObjectKernel(VirtualDerivedType* deviceObject,
const VirtualDerivedType* targetObject)
{
*deviceObject = *targetObject;
}
template <typename VirtualDerivedType>
__global__ void DeleteVirtualObjectKernel(VirtualDerivedType* deviceObject)
{
deviceObject->~VirtualDerivedType();
}
} // detail
template <typename VirtualObject, typename TargetClass>
struct VirtualObjectTransfer<VirtualObject, TargetClass, vtkm::cont::DeviceAdapterTagCuda>
template <typename VirtualDerivedType>
struct VirtualObjectTransfer<VirtualDerivedType, vtkm::cont::DeviceAdapterTagCuda>
{
static void* Create(VirtualObject& object, const void* target)
VTKM_CONT VirtualObjectTransfer(const VirtualDerivedType* virtualObject)
: ControlObject(virtualObject)
, ExecutionObject(nullptr)
{
TargetClass* cutarget;
VTKM_CUDA_CALL(cudaMalloc(&cutarget, sizeof(TargetClass)));
VTKM_CUDA_CALL(cudaMemcpyAsync(
cutarget, target, sizeof(TargetClass), cudaMemcpyHostToDevice, cudaStreamPerThread));
VirtualObject* cuobject;
VTKM_CUDA_CALL(cudaMalloc(&cuobject, sizeof(VirtualObject)));
detail::CreateKernel<<<1, 1, 0, cudaStreamPerThread>>>(cuobject, cutarget);
VTKM_CUDA_CHECK_ASYNCHRONOUS_ERROR();
VTKM_CUDA_CALL(cudaMemcpyAsync(
&object, cuobject, sizeof(VirtualObject), cudaMemcpyDeviceToHost, cudaStreamPerThread));
VTKM_CUDA_CALL(cudaFree(cuobject));
return cutarget;
}
static void Update(void* deviceState, const void* target)
VTKM_CONT ~VirtualObjectTransfer() { this->ReleaseResources(); }
VirtualObjectTransfer(const VirtualObjectTransfer&) = delete;
void operator=(const VirtualObjectTransfer&) = delete;
VTKM_CONT const VirtualDerivedType* PrepareForExecution(bool updateData)
{
VTKM_CUDA_CALL(cudaMemcpyAsync(
deviceState, target, sizeof(TargetClass), cudaMemcpyHostToDevice, cudaStreamPerThread));
if (this->ExecutionObject == nullptr)
{
// deviceTarget will hold a byte copy of the host object on the device. The virtual table
// will be wrong.
VirtualDerivedType* deviceTarget;
VTKM_CUDA_CALL(cudaMalloc(&deviceTarget, sizeof(VirtualDerivedType)));
VTKM_CUDA_CALL(cudaMemcpy(
deviceTarget, this->ControlObject, sizeof(VirtualDerivedType), cudaMemcpyHostToDevice));
// Allocate memory for the object that will eventually be a correct copy on the device.
VTKM_CUDA_CALL(cudaMalloc(&this->ExecutionObject, sizeof(VirtualDerivedType)));
// Initialize the device object
detail::ConstructVirtualObjectKernel<<<1, 1>>>(this->ExecutionObject, deviceTarget);
VTKM_CUDA_CHECK_ASYNCHRONOUS_ERROR();
// Clean up intermediate copy
VTKM_CUDA_CALL(cudaFree(deviceTarget));
}
else if (updateData)
{
// deviceTarget will hold a byte copy of the host object on the device. The virtual table
// will be wrong.
VirtualDerivedType* deviceTarget;
VTKM_CUDA_CALL(cudaMalloc(&deviceTarget, sizeof(VirtualDerivedType)));
VTKM_CUDA_CALL(cudaMemcpy(
deviceTarget, this->ControlObject, sizeof(VirtualDerivedType), cudaMemcpyHostToDevice));
// Initialize the device object
detail::UpdateVirtualObjectKernel<<<1, 1>>>(this->ExecutionObject, deviceTarget);
VTKM_CUDA_CHECK_ASYNCHRONOUS_ERROR();
// Clean up intermediate copy
VTKM_CUDA_CALL(cudaFree(deviceTarget));
}
else
{
// Nothing to do. The device object is already up to date.
}
return this->ExecutionObject;
}
static void Cleanup(void* deviceState) { VTKM_CUDA_CALL(cudaFree(deviceState)); }
VTKM_CONT void ReleaseResources()
{
if (this->ExecutionObject != nullptr)
{
detail::DeleteVirtualObjectKernel<<<1, 1>>>(this->ExecutionObject);
VTKM_CUDA_CALL(cudaFree(this->ExecutionObject));
this->ExecutionObject = nullptr;
}
}
private:
const VirtualDerivedType* ControlObject;
VirtualDerivedType* ExecutionObject;
};
}
}
} // vtkm::cont::internal
#define VTKM_EXPLICITLY_INSTANTIATE_TRANSFER(DerivedType) \
template class vtkm::cont::internal::VirtualObjectTransfer<DerivedType, \
vtkm::cont::DeviceAdapterTagCuda>
#endif // vtk_m_cont_cuda_internal_VirtualObjectTransferCuda_h

@ -29,6 +29,6 @@ set(unit_tests
UnitTestCudaMath.cu
UnitTestCudaShareUserProvidedManagedMemory.cu
UnitTestCudaPointLocatorUniformGrid.cxx
UnitTestCudaVirtualObjectCache.cu
UnitTestCudaVirtualObjectHandle.cu
)
vtkm_unit_tests(SOURCES ${unit_tests})

@ -17,22 +17,22 @@
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#include <vtkm/cont/testing/TestingVirtualObjectCache.h>
#include <vtkm/cont/testing/TestingVirtualObjectHandle.h>
namespace
{
void TestVirtualObjectCache()
void TestVirtualObjectHandle()
{
using DeviceAdapterList =
vtkm::ListTagBase<vtkm::cont::DeviceAdapterTagSerial, vtkm::cont::DeviceAdapterTagCuda>;
vtkm::cont::testing::TestingVirtualObjectCache<DeviceAdapterList>::Run();
vtkm::cont::testing::TestingVirtualObjectHandle<DeviceAdapterList>::Run();
}
} // anonymous namespace
int UnitTestCudaVirtualObjectCache(int, char* [])
int UnitTestCudaVirtualObjectHandle(int, char* [])
{
return vtkm::cont::testing::Testing::Run(TestVirtualObjectCache);
return vtkm::cont::testing::Testing::Run(TestVirtualObjectHandle);
}

@ -112,6 +112,17 @@ struct VTKM_CONT_EXPORT ExecutionArrayInterfaceBasicBase
void* controlPtr,
vtkm::UInt64 numBytes) const = 0;
VTKM_CONT virtual void UsingForRead(const void* controlPtr,
const void* executionPtr,
vtkm::UInt64 numBytes) const = 0;
VTKM_CONT virtual void UsingForWrite(const void* controlPtr,
const void* executionPtr,
vtkm::UInt64 numBytes) const = 0;
VTKM_CONT virtual void UsingForReadWrite(const void* controlPtr,
const void* executionPtr,
vtkm::UInt64 numBytes) const = 0;
protected:
StorageBasicBase& ControlStorage;
};

@ -267,6 +267,9 @@ ArrayHandle<T, StorageTagBasic>::PrepareForInput(DeviceAdapterTag device) const
InternalStruct* priv = const_cast<InternalStruct*>(this->Internals.get());
this->PrepareForDevice(device);
const vtkm::UInt64 numBytes = static_cast<vtkm::UInt64>(sizeof(ValueType)) *
static_cast<vtkm::UInt64>(this->GetStorage().GetNumberOfValues());
if (!this->Internals->ExecutionArrayValid)
{
@ -284,9 +287,6 @@ ArrayHandle<T, StorageTagBasic>::PrepareForInput(DeviceAdapterTag device) const
this->Internals->ControlArray.GetBasePointer(),
this->Internals->ControlArray.GetCapacityPointer());
const vtkm::UInt64 numBytes = static_cast<vtkm::UInt64>(sizeof(ValueType)) *
static_cast<vtkm::UInt64>(this->GetStorage().GetNumberOfValues());
priv->ExecutionInterface->Allocate(execArray, numBytes);
priv->ExecutionInterface->CopyFromControl(
@ -294,6 +294,8 @@ ArrayHandle<T, StorageTagBasic>::PrepareForInput(DeviceAdapterTag device) const
this->Internals->ExecutionArrayValid = true;
}
this->Internals->ExecutionInterface->UsingForRead(
priv->ControlArray.GetArray(), priv->ExecutionArray, numBytes);
return PortalFactory<DeviceAdapterTag>::CreatePortalConst(this->Internals->ExecutionArray,
this->Internals->ExecutionArrayEnd);
@ -320,11 +322,17 @@ ArrayHandle<T, StorageTagBasic>::PrepareForOutput(vtkm::Id numVals, DeviceAdapte
this->Internals->ControlArray.GetBasePointer(),
this->Internals->ControlArray.GetCapacityPointer());
this->Internals->ExecutionInterface->Allocate(
execArray, static_cast<vtkm::UInt64>(sizeof(ValueType)) * static_cast<vtkm::UInt64>(numVals));
const vtkm::UInt64 numBytes =
static_cast<vtkm::UInt64>(sizeof(ValueType)) * static_cast<vtkm::UInt64>(numVals);
this->Internals->ExecutionInterface->Allocate(execArray, numBytes);
this->Internals->ExecutionInterface->UsingForWrite(
priv->ControlArray.GetArray(), priv->ExecutionArray, numBytes);
this->Internals->ExecutionArrayValid = true;
return PortalFactory<DeviceAdapterTag>::CreatePortal(this->Internals->ExecutionArray,
this->Internals->ExecutionArrayEnd);
}
@ -339,6 +347,9 @@ ArrayHandle<T, StorageTagBasic>::PrepareForInPlace(DeviceAdapterTag device)
this->PrepareForDevice(device);
const vtkm::UInt64 numBytes = static_cast<vtkm::UInt64>(sizeof(ValueType)) *
static_cast<vtkm::UInt64>(this->GetStorage().GetNumberOfValues());
if (!this->Internals->ExecutionArrayValid)
{
// Initialize an empty array if needed:
@ -355,9 +366,6 @@ ArrayHandle<T, StorageTagBasic>::PrepareForInPlace(DeviceAdapterTag device)
this->Internals->ControlArray.GetBasePointer(),
this->Internals->ControlArray.GetCapacityPointer());
vtkm::UInt64 numBytes = static_cast<vtkm::UInt64>(sizeof(ValueType)) *
static_cast<vtkm::UInt64>(this->GetStorage().GetNumberOfValues());
priv->ExecutionInterface->Allocate(execArray, numBytes);
priv->ExecutionInterface->CopyFromControl(
@ -366,6 +374,9 @@ ArrayHandle<T, StorageTagBasic>::PrepareForInPlace(DeviceAdapterTag device)
this->Internals->ExecutionArrayValid = true;
}
priv->ExecutionInterface->UsingForReadWrite(
priv->ControlArray.GetArray(), priv->ExecutionArray, numBytes);
// Invalidate the control array, since we expect the values to be modified:
this->Internals->ControlArrayValid = false;

@ -77,6 +77,22 @@ void ExecutionArrayInterfaceBasicShareWithControl::CopyToControl(const void* src
std::copy(srcBegin, srcEnd, dstBegin);
}
}
void ExecutionArrayInterfaceBasicShareWithControl::UsingForRead(const void*,
const void*,
vtkm::UInt64) const
{
}
void ExecutionArrayInterfaceBasicShareWithControl::UsingForWrite(const void*,
const void*,
vtkm::UInt64) const
{
}
void ExecutionArrayInterfaceBasicShareWithControl::UsingForReadWrite(const void*,
const void*,
vtkm::UInt64) const
{
}
}
}
} // end namespace vtkm::cont::internal

@ -141,8 +141,19 @@ struct VTKM_CONT_EXPORT ExecutionArrayInterfaceBasicShareWithControl
VTKM_CONT void Allocate(TypelessExecutionArray& execArray, vtkm::UInt64 numBytes) const final;
VTKM_CONT void Free(TypelessExecutionArray& execArray) const final;
VTKM_CONT void CopyFromControl(const void* src, void* dst, vtkm::UInt64 bytes) const final;
VTKM_CONT void CopyToControl(const void* src, void* dst, vtkm::UInt64 bytes) const final;
VTKM_CONT void UsingForRead(const void* controlPtr,
const void* executionPtr,
vtkm::UInt64 numBytes) const final;
VTKM_CONT void UsingForWrite(const void* controlPtr,
const void* executionPtr,
vtkm::UInt64 numBytes) const final;
VTKM_CONT void UsingForReadWrite(const void* controlPtr,
const void* executionPtr,
vtkm::UInt64 numBytes) const final;
};
}
}

@ -22,6 +22,8 @@
#include "vtkm/internal/IndexTag.h"
#include <utility>
namespace vtkm
{
namespace cont
@ -29,6 +31,10 @@ namespace cont
template <typename T, typename S>
class ArrayHandle;
class CoordinateSystem;
class Field;
template <vtkm::IdComponent>
class CellSetStructured;
template <typename T>
@ -41,57 +47,75 @@ class CellSetPermutation;
/// A Generic interface to CastAndCall. The default implementation simply calls
/// DynamicObject's CastAndCall, but specializations of this function exist for
/// other classes (e.g. Field, CoordinateSystem, ArrayHandle).
template <typename DynamicObject, typename Functor>
void CastAndCall(const DynamicObject& dynamicObject, const Functor& f)
template <typename DynamicObject, typename Functor, typename... Args>
void CastAndCall(const DynamicObject& dynamicObject, const Functor& f, Args&&... args)
{
dynamicObject.CastAndCall(f);
dynamicObject.CastAndCall(f, std::forward<Args>(args)...);
}
/// A specialization of CastAndCall for basic CoordinateSystem to make
/// it be treated just like any other dynamic object
// actually implemented in vtkm/cont/CoordinateSystem
template <typename Functor, typename... Args>
void CastAndCall(const CoordinateSystem& coords, const Functor& f, Args&&... args);
/// A specialization of CastAndCall for basic Field to make
/// it be treated just like any other dynamic object
// actually implemented in vtkm/cont/Field
template <typename Functor, typename... Args>
void CastAndCall(const vtkm::cont::Field& field, const Functor& f, Args&&... args);
/// A specialization of CastAndCall for basic ArrayHandle types,
/// Since the type is already known no deduction is needed.
/// This specialization is used to simplify numerous worklet algorithms
template <typename T, typename U, typename Functor>
void CastAndCall(const vtkm::cont::ArrayHandle<T, U>& handle, const Functor& f)
template <typename T, typename U, typename Functor, typename... Args>
void CastAndCall(const vtkm::cont::ArrayHandle<T, U>& handle, const Functor& f, Args&&... args)
{
f(handle);
f(handle, std::forward<Args>(args)...);
}
/// A specialization of CastAndCall for basic CellSetStructured types,
/// Since the type is already known no deduction is needed.
/// This specialization is used to simplify numerous worklet algorithms
template <vtkm::IdComponent Dim, typename Functor>
void CastAndCall(const vtkm::cont::CellSetStructured<Dim>& cellset, const Functor& f)
template <vtkm::IdComponent Dim, typename Functor, typename... Args>
void CastAndCall(const vtkm::cont::CellSetStructured<Dim>& cellset,
const Functor& f,
Args&&... args)
{
f(cellset);
f(cellset, std::forward<Args>(args)...);
}
/// A specialization of CastAndCall for basic CellSetSingleType types,
/// Since the type is already known no deduction is needed.
/// This specialization is used to simplify numerous worklet algorithms
template <typename ConnectivityStorageTag, typename Functor>
template <typename ConnectivityStorageTag, typename Functor, typename... Args>
void CastAndCall(const vtkm::cont::CellSetSingleType<ConnectivityStorageTag>& cellset,
const Functor& f)
const Functor& f,
Args&&... args)
{
f(cellset);
f(cellset, std::forward<Args>(args)...);
}
/// A specialization of CastAndCall for basic CellSetExplicit types,
/// Since the type is already known no deduction is needed.
/// This specialization is used to simplify numerous worklet algorithms
template <typename T, typename S, typename U, typename V, typename Functor>
void CastAndCall(const vtkm::cont::CellSetExplicit<T, S, U, V>& cellset, const Functor& f)
template <typename T, typename S, typename U, typename V, typename Functor, typename... Args>
void CastAndCall(const vtkm::cont::CellSetExplicit<T, S, U, V>& cellset,
const Functor& f,
Args&&... args)
{
f(cellset);
f(cellset, std::forward<Args>(args)...);
}
/// A specialization of CastAndCall for basic CellSetPermutation types,
/// Since the type is already known no deduction is needed.
/// This specialization is used to simplify numerous worklet algorithms
template <typename PermutationType, typename CellSetType, typename Functor>
template <typename PermutationType, typename CellSetType, typename Functor, typename... Args>
void CastAndCall(const vtkm::cont::CellSetPermutation<PermutationType, CellSetType>& cellset,
const Functor& f)
const Functor& f,
Args&&... args)
{
f(cellset);
f(cellset, std::forward<Args>(args)...);
}
namespace internal

@ -20,6 +20,8 @@
#ifndef vtk_m_cont_internal_VirtualObjectTransfer_h
#define vtk_m_cont_internal_VirtualObjectTransfer_h
#include <vtkm/VirtualObjectBase.h>
namespace vtkm
{
namespace cont
@ -27,23 +29,31 @@ namespace cont
namespace internal
{
template <typename VirtualObject, typename TargetClass, typename DeviceAdapter>
template <typename VirtualDerivedType, typename DeviceAdapter>
struct VirtualObjectTransfer
#ifdef VTKM_DOXYGEN_ONLY
{
/// Takes a void* to host copy of the target object, transfers it to the
/// device, binds it to the VirtualObject, and returns a void* to an internal
/// state structure.
/// A VirtualObjectTransfer is constructed with a pointer to the derived type that (eventually)
/// gets transferred to the execution environment of the given DeviceAdapter.
///
static void* Create(VirtualObject& object, const void* hostTarget);
VTKM_CONT VirtualObjectTransfer(const VirtualDerivedType* virtualObject);
/// Performs cleanup of the device state used to track the VirtualObject on
/// the device.
/// \brief Transfers the virtual object to the execution environment.
///
static void Cleanup(void* deviceState);
/// This method transfers the virtual object to the execution environment and returns a pointer
/// to the object that can be used in the execution environment (but not necessarily the control
/// environment). If the \c updateData flag is true, then the data is always copied to the
/// execution environment (such as if the data were updated since the last call to \c
/// PrepareForExecution). If the \c updateData flag is false and the object was already
/// transferred previously, the previously created object is returned.
///
VTKM_CONT const VirtualDerivedType* PrepareForExecution(bool updateData);
/// Update the device state with the state of target
static void Update(void* deviceState, const void* target);
/// \brief Frees up any resources in the execution environment.
///
/// Any previously returned virtual object from \c PrepareForExecution becomes invalid.
///
VTKM_CONT void ReleaseResources();
}
#endif
;

@ -20,6 +20,11 @@
#ifndef vtk_m_cont_internal_VirtualObjectTransferShareWithControl_h
#define vtk_m_cont_internal_VirtualObjectTransferShareWithControl_h
#include <vtkm/StaticAssert.h>
#include <vtkm/VirtualObjectBase.h>
#include <typeinfo>
namespace vtkm
{
namespace cont
@ -27,19 +32,23 @@ namespace cont
namespace internal
{
template <typename VirtualObject, typename TargetClass>
template <typename VirtualDerivedType>
struct VirtualObjectTransferShareWithControl
{
static void* Create(VirtualObject& object, const void* target)
VTKM_CONT VirtualObjectTransferShareWithControl(const VirtualDerivedType* virtualObject)
: VirtualObject(virtualObject)
{
static int dummyState = 0;
object.Bind(static_cast<const TargetClass*>(target));
return &dummyState;
}
static void Update(void*, const void*) {}
VTKM_CONT const VirtualDerivedType* PrepareForExecution(bool vtkmNotUsed(updateData))
{
return this->VirtualObject;
}
static void Cleanup(void*) {}
VTKM_CONT void ReleaseResources() {}
private:
const VirtualDerivedType* VirtualObject;
};
}
}

@ -83,6 +83,11 @@ public:
auto inputPortal = input.PrepareForInput(DeviceAdapterTagSerial());
auto outputPortal = output.PrepareForOutput(inSize, DeviceAdapterTagSerial());
if (inSize <= 0)
{
return;
}
using InputType = decltype(inputPortal.Get(0));
using OutputType = decltype(outputPortal.Get(0));

@ -31,10 +31,14 @@ namespace cont
namespace internal
{
template <typename VirtualObject, typename TargetClass>
struct VirtualObjectTransfer<VirtualObject, TargetClass, vtkm::cont::DeviceAdapterTagSerial>
: public VirtualObjectTransferShareWithControl<VirtualObject, TargetClass>
template <typename VirtualDerivedType>
struct VirtualObjectTransfer<VirtualDerivedType, vtkm::cont::DeviceAdapterTagSerial>
: VirtualObjectTransferShareWithControl<VirtualDerivedType>
{
VTKM_CONT VirtualObjectTransfer(const VirtualDerivedType* virtualObject)
: VirtualObjectTransferShareWithControl<VirtualDerivedType>(virtualObject)
{
}
};
}
}

@ -28,6 +28,6 @@ set(unit_tests
UnitTestSerialDeviceAdapter.cxx
UnitTestSerialImplicitFunction.cxx
UnitTestSerialPointLocatorUniformGrid.cxx
UnitTestSerialVirtualObjectCache.cxx
UnitTestSerialVirtualObjectHandle.cxx
)
vtkm_unit_tests(TBB SOURCES ${unit_tests})

@ -17,21 +17,21 @@
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#include <vtkm/cont/testing/TestingVirtualObjectCache.h>
#include <vtkm/cont/testing/TestingVirtualObjectHandle.h>
namespace
{
void TestVirtualObjectCache()
void TestVirtualObjectHandle()
{
using DeviceAdapterList = vtkm::ListTagBase<vtkm::cont::DeviceAdapterTagSerial>;
vtkm::cont::testing::TestingVirtualObjectCache<DeviceAdapterList>::Run();
vtkm::cont::testing::TestingVirtualObjectHandle<DeviceAdapterList>::Run();
}
} // anonymous namespace
int UnitTestSerialVirtualObjectCache(int, char* [])
int UnitTestSerialVirtualObjectHandle(int, char* [])
{
return vtkm::cont::testing::Testing::Run(TestVirtualObjectCache);
return vtkm::cont::testing::Testing::Run(TestVirtualObjectHandle);
}

@ -31,10 +31,14 @@ namespace cont
namespace internal
{
template <typename VirtualObject, typename TargetClass>
struct VirtualObjectTransfer<VirtualObject, TargetClass, vtkm::cont::DeviceAdapterTagTBB>
: public VirtualObjectTransferShareWithControl<VirtualObject, TargetClass>
template <typename VirtualDerivedType>
struct VirtualObjectTransfer<VirtualDerivedType, vtkm::cont::DeviceAdapterTagTBB>
: VirtualObjectTransferShareWithControl<VirtualDerivedType>
{
VTKM_CONT VirtualObjectTransfer(const VirtualDerivedType* virtualObject)
: VirtualObjectTransferShareWithControl<VirtualDerivedType>(virtualObject)
{
}
};
}
}

@ -28,6 +28,6 @@ set(unit_tests
UnitTestTBBDeviceAdapter.cxx
UnitTestTBBImplicitFunction.cxx
UnitTestTBBPointLocatorUniformGrid.cxx
UnitTestTBBVirtualObjectCache.cxx
UnitTestTBBVirtualObjectHandle.cxx
)
vtkm_unit_tests(TBB SOURCES ${unit_tests})

@ -17,22 +17,22 @@
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#include <vtkm/cont/testing/TestingVirtualObjectCache.h>
#include <vtkm/cont/testing/TestingVirtualObjectHandle.h>
namespace
{
void TestVirtualObjectCache()
void TestVirtualObjectHandle()
{
using DeviceAdapterList =
vtkm::ListTagBase<vtkm::cont::DeviceAdapterTagSerial, vtkm::cont::DeviceAdapterTagTBB>;
vtkm::cont::testing::TestingVirtualObjectCache<DeviceAdapterList>::Run();
vtkm::cont::testing::TestingVirtualObjectHandle<DeviceAdapterList>::Run();
}
} // anonymous namespace
int UnitTestTBBVirtualObjectCache(int, char* [])
int UnitTestTBBVirtualObjectHandle(int, char* [])
{
return vtkm::cont::testing::Testing::Run(TestVirtualObjectCache);
return vtkm::cont::testing::Testing::Run(TestVirtualObjectHandle);
}

@ -31,7 +31,7 @@ set(headers
TestingFancyArrayHandles.h
TestingImplicitFunction.h
TestingPointLocatorUniformGrid.h
TestingVirtualObjectCache.h
TestingVirtualObjectHandle.h
)
vtkm_declare_headers(${headers})

@ -316,44 +316,31 @@ public:
class VirtualObjectTransferKernel
{
public:
struct Interface
struct Interface : public vtkm::VirtualObjectBase
{
using FooSig = vtkm::Id(const void*);
template <typename T>
VTKM_EXEC void Bind(const T* target)
{
this->Target = target;
this->FooPtr = [](const void* t) { return static_cast<const T*>(t)->Foo(); };
}
VTKM_EXEC
vtkm::Id Foo() const { return this->FooPtr(this->Target); }
const void* Target;
FooSig* FooPtr;
VTKM_EXEC virtual vtkm::Id Foo() const = 0;
};
struct Concrete
struct Concrete : public Interface
{
vtkm::Id Foo() const { return this->Value; }
VTKM_EXEC vtkm::Id Foo() const override { return this->Value; }
vtkm::Id Value = 0;
};
VirtualObjectTransferKernel(const Interface& vo, IdArrayHandle& result)
VirtualObjectTransferKernel(const Interface* vo, IdArrayHandle& result)
: Virtual(vo)
, Result(result.PrepareForInPlace(DeviceAdapterTag()))
{
}
VTKM_EXEC
void operator()(vtkm::Id) const { this->Result.Set(0, this->Virtual.Foo()); }
void operator()(vtkm::Id) const { this->Result.Set(0, this->Virtual->Foo()); }
VTKM_CONT void SetErrorMessageBuffer(const vtkm::exec::internal::ErrorMessageBuffer&) {}
private:
Interface Virtual;
const Interface* Virtual;
IdPortalType Result;
};
@ -512,10 +499,9 @@ private:
VTKM_CONT
static void TestVirtualObjectTransfer()
{
using VirtualObject = typename VirtualObjectTransferKernel::Interface;
using BaseType = typename VirtualObjectTransferKernel::Interface;
using TargetType = typename VirtualObjectTransferKernel::Concrete;
using Transfer =
vtkm::cont::internal::VirtualObjectTransfer<VirtualObject, TargetType, DeviceAdapterTag>;
using Transfer = vtkm::cont::internal::VirtualObjectTransfer<TargetType, DeviceAdapterTag>;
IdArrayHandle result;
result.Allocate(1);
@ -524,21 +510,21 @@ private:
TargetType target;
target.Value = 5;
VirtualObject vo;
void* state = Transfer::Create(vo, &target);
Transfer transfer(&target);
const BaseType* base = transfer.PrepareForExecution(false);
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing VirtualObjectTransfer" << std::endl;
Algorithm::Schedule(VirtualObjectTransferKernel(vo, result), 1);
Algorithm::Schedule(VirtualObjectTransferKernel(base, result), 1);
VTKM_TEST_ASSERT(result.GetPortalConstControl().Get(0) == 5, "Did not get expected result");
target.Value = 10;
Transfer::Update(state, &target);
Algorithm::Schedule(VirtualObjectTransferKernel(vo, result), 1);
base = transfer.PrepareForExecution(true);
Algorithm::Schedule(VirtualObjectTransferKernel(base, result), 1);
VTKM_TEST_ASSERT(result.GetPortalConstControl().Get(0) == 10, "Did not get expected result");
Transfer::Cleanup(state);
transfer.ReleaseResources();
}
static VTKM_CONT void TestAlgorithmSchedule()
@ -1839,6 +1825,15 @@ private:
}
};
template <typename T, typename U>
struct TestCopy<vtkm::Pair<T, U>>
{
static vtkm::Pair<T, U> get(vtkm::Id i)
{
return vtkm::make_Pair(TestCopy<T>::get(i), TestCopy<U>::get(i));
}
};
template <typename T>
static VTKM_CONT void TestCopyArrays()
{
@ -1862,9 +1857,10 @@ private:
VTKM_TEST_ASSERT(temp.GetNumberOfValues() == COPY_ARRAY_SIZE, "Copy Needs to Resize Array");
typename std::vector<T>::const_iterator c = testData.begin();
const auto& portal = temp.GetPortalConstControl();
for (vtkm::Id i = 0; i < COPY_ARRAY_SIZE; i += 50, c += 50)
{
T value = temp.GetPortalConstControl().Get(i);
T value = portal.Get(i);
VTKM_TEST_ASSERT(value == *c, "Got bad value (Copy)");
}
}
@ -2015,19 +2011,15 @@ private:
{
std::cout << "-------------------------------------------------" << std::endl;
std::cout << "Testing Copy to same array type" << std::endl;
TestCopyArrays<vtkm::Vec<vtkm::Float32, 4>>();
TestCopyArrays<vtkm::Vec<vtkm::Float64, 4>>();
TestCopyArrays<vtkm::Vec<vtkm::Float32, 3>>();
TestCopyArrays<vtkm::Vec<vtkm::UInt8, 4>>();
//
TestCopyArrays<vtkm::Vec<vtkm::UInt8, 2>>();
TestCopyArrays<vtkm::Vec<vtkm::UInt16, 2>>();
TestCopyArrays<vtkm::Vec<vtkm::UInt32, 2>>();
TestCopyArrays<vtkm::Vec<vtkm::UInt64, 2>>();
TestCopyArrays<vtkm::Pair<vtkm::Id, vtkm::Float32>>();
TestCopyArrays<vtkm::Pair<vtkm::Id, vtkm::Vec<vtkm::Float32, 3>>>();
//
TestCopyArrays<vtkm::Float32>();
TestCopyArrays<vtkm::Float64>();
//
TestCopyArrays<vtkm::Int8>();
TestCopyArrays<vtkm::Int16>();
TestCopyArrays<vtkm::Int32>();
TestCopyArrays<vtkm::Int64>();
//
@ -2035,8 +2027,6 @@ private:
TestCopyArrays<vtkm::UInt16>();
TestCopyArrays<vtkm::UInt32>();
TestCopyArrays<vtkm::UInt64>();
//
TestCopyArrays<vtkm::Id>();
}
static VTKM_CONT void TestCopyArraysInDiffTypes()

@ -22,7 +22,7 @@
#include <vtkm/cont/CoordinateSystem.h>
#include <vtkm/cont/DeviceAdapterListTag.h>
#include <vtkm/cont/ImplicitFunction.h>
#include <vtkm/cont/ImplicitFunctionHandle.h>
#include <vtkm/cont/internal/DeviceAdapterTag.h>
#include <vtkm/cont/testing/MakeTestDataSet.h>
#include <vtkm/cont/testing/Testing.h>
@ -50,7 +50,7 @@ public:
typedef void ControlSignature(FieldIn<Vec3>, FieldOut<Scalar>);
typedef void ExecutionSignature(_1, _2);
EvaluateImplicitFunction(const vtkm::exec::ImplicitFunction& function)
EvaluateImplicitFunction(const vtkm::ImplicitFunction* function)
: Function(function)
{
}
@ -58,16 +58,16 @@ public:
template <typename VecType, typename ScalarType>
VTKM_EXEC void operator()(const VecType& point, ScalarType& val) const
{
val = this->Function.Value(point);
val = this->Function->Value(point);
}
private:
vtkm::exec::ImplicitFunction Function;
const vtkm::ImplicitFunction* Function;
};
template <typename DeviceAdapter>
void EvaluateOnCoordinates(vtkm::cont::CoordinateSystem points,
const vtkm::cont::ImplicitFunction& function,
const vtkm::cont::ImplicitFunctionHandle& function,
vtkm::cont::ArrayHandle<vtkm::FloatDefault>& values,
DeviceAdapter device)
{
@ -141,13 +141,16 @@ private:
template <typename DeviceAdapter>
void TestBox(DeviceAdapter device)
{
std::cout << "Testing vtkm::cont::Box on "
std::cout << "Testing vtkm::Box on "
<< vtkm::cont::DeviceAdapterTraits<DeviceAdapter>::GetName() << "\n";
vtkm::cont::Box box({ 0.0f, -0.5f, -0.5f }, { 1.5f, 1.5f, 0.5f });
vtkm::cont::ArrayHandle<vtkm::FloatDefault> values;
implicit_function_detail::EvaluateOnCoordinates(
this->Input.GetCoordinateSystem(0), box, values, device);
this->Input.GetCoordinateSystem(0),
vtkm::cont::make_ImplicitFunctionHandle(
vtkm::Box({ 0.0f, -0.5f, -0.5f }, { 1.5f, 1.5f, 0.5f })),
values,
device);
std::array<vtkm::FloatDefault, 8> expected = {
{ 0.0f, -0.5f, 0.5f, 0.5f, 0.0f, -0.5f, 0.5f, 0.5f }
@ -159,17 +162,20 @@ private:
template <typename DeviceAdapter>
void TestCylinder(DeviceAdapter device)
{
std::cout << "Testing vtkm::cont::Cylinder on "
std::cout << "Testing vtkm::Cylinder on "
<< vtkm::cont::DeviceAdapterTraits<DeviceAdapter>::GetName() << "\n";
vtkm::cont::Cylinder cylinder;
vtkm::Cylinder cylinder;
cylinder.SetCenter({ 0.0f, 0.0f, 1.0f });
cylinder.SetAxis({ 0.0f, 1.0f, 0.0f });
cylinder.SetRadius(1.0f);
vtkm::cont::ArrayHandle<vtkm::FloatDefault> values;
implicit_function_detail::EvaluateOnCoordinates(
this->Input.GetCoordinateSystem(0), cylinder, values, device);
this->Input.GetCoordinateSystem(0),
vtkm::cont::ImplicitFunctionHandle(&cylinder, false),
values,
device);
std::array<vtkm::FloatDefault, 8> expected = {
{ 0.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, -1.0f }
@ -181,7 +187,7 @@ private:
template <typename DeviceAdapter>
void TestFrustum(DeviceAdapter device)
{
std::cout << "Testing vtkm::cont::Frustum on "
std::cout << "Testing vtkm::Frustum on "
<< vtkm::cont::DeviceAdapterTraits<DeviceAdapter>::GetName() << "\n";
vtkm::Vec<vtkm::FloatDefault, 3> points[8] = {
@ -194,12 +200,15 @@ private:
{ 1.5f, 1.5f, 1.5f }, // 6
{ 0.5f, 1.5f, 1.5f } // 7
};
vtkm::cont::Frustum frustum;
vtkm::Frustum frustum;
frustum.CreateFromPoints(points);
vtkm::cont::ArrayHandle<vtkm::FloatDefault> values;
implicit_function_detail::EvaluateOnCoordinates(
this->Input.GetCoordinateSystem(0), frustum, values, device);
this->Input.GetCoordinateSystem(0),
vtkm::cont::make_ImplicitFunctionHandle(frustum),
values,
device);
std::array<vtkm::FloatDefault, 8> expected = {
{ 0.0f, 0.0f, 0.0f, 0.0f, 0.316228f, 0.316228f, -0.316228f, 0.316228f }
@ -211,23 +220,25 @@ private:
template <typename DeviceAdapter>
void TestPlane(DeviceAdapter device)
{
std::cout << "Testing vtkm::cont::Plane on "
std::cout << "Testing vtkm::Plane on "
<< vtkm::cont::DeviceAdapterTraits<DeviceAdapter>::GetName() << "\n";
vtkm::cont::Plane plane({ 0.5f, 0.5f, 0.5f }, { 1.0f, 0.0f, 1.0f });
vtkm::cont::ArrayHandle<vtkm::FloatDefault> values;
auto planeHandle = vtkm::cont::make_ImplicitFunctionHandle<vtkm::Plane>(
vtkm::make_Vec(0.5f, 0.5f, 0.5f), vtkm::make_Vec(1.0f, 0.0f, 1.0f));
auto plane = static_cast<vtkm::Plane*>(planeHandle.Get());
vtkm::cont::ArrayHandle<vtkm::FloatDefault> values;
implicit_function_detail::EvaluateOnCoordinates(
this->Input.GetCoordinateSystem(0), plane, values, device);
this->Input.GetCoordinateSystem(0), planeHandle, values, device);
std::array<vtkm::FloatDefault, 8> expected1 = {
{ -1.0f, 0.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f }
};
VTKM_TEST_ASSERT(implicit_function_detail::TestArrayEqual(values, expected1),
"Result does not match expected values");
plane.SetNormal({ -1.0f, 0.0f, -1.0f });
plane->SetNormal({ -1.0f, 0.0f, -1.0f });
implicit_function_detail::EvaluateOnCoordinates(
this->Input.GetCoordinateSystem(0), plane, values, device);
this->Input.GetCoordinateSystem(0), planeHandle, values, device);
std::array<vtkm::FloatDefault, 8> expected2 = {
{ 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, -1.0f, 0.0f }
};
@ -238,13 +249,15 @@ private:
template <typename DeviceAdapter>
void TestSphere(DeviceAdapter device)
{
std::cout << "Testing vtkm::cont::Sphere on "
std::cout << "Testing vtkm::Sphere on "
<< vtkm::cont::DeviceAdapterTraits<DeviceAdapter>::GetName() << "\n";
vtkm::cont::Sphere sphere({ 0.0f, 0.0f, 0.0f }, 1.0f);
vtkm::cont::ArrayHandle<vtkm::FloatDefault> values;
implicit_function_detail::EvaluateOnCoordinates(
this->Input.GetCoordinateSystem(0), sphere, values, device);
this->Input.GetCoordinateSystem(0),
vtkm::cont::make_ImplicitFunctionHandle<vtkm::Sphere>(vtkm::make_Vec(0.0f, 0.0f, 0.0f), 1.0f),
values,
device);
std::array<vtkm::FloatDefault, 8> expected = {
{ -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 2.0f, 1.0f }

@ -17,14 +17,14 @@
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#ifndef vtk_m_cont_testing_TestingVirtualObjectCache_h
#define vtk_m_cont_testing_TestingVirtualObjectCache_h
#ifndef vtk_m_cont_testing_TestingVirtualObjectHandle_h
#define vtk_m_cont_testing_TestingVirtualObjectHandle_h
#include <vtkm/Types.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ArrayHandleTransform.h>
#include <vtkm/cont/DeviceAdapterAlgorithm.h>
#include <vtkm/cont/VirtualObjectCache.h>
#include <vtkm/cont/VirtualObjectHandle.h>
#include <vtkm/cont/testing/Testing.h>
#define ARRAY_LEN 8
@ -39,62 +39,76 @@ namespace testing
namespace virtual_object_detail
{
class Transformer
class Transformer : public vtkm::VirtualObjectBase
{
public:
template <typename T>
VTKM_EXEC void Bind(const T* target)
VTKM_EXEC
virtual vtkm::FloatDefault Eval(vtkm::FloatDefault val) const = 0;
};
class Square : public Transformer
{
public:
VTKM_EXEC
vtkm::FloatDefault Eval(vtkm::FloatDefault val) const override { return val * val; }
};
class Multiply : public Transformer
{
public:
VTKM_CONT
void SetMultiplicand(vtkm::FloatDefault val)
{
this->Concrete = target;
this->Caller = [](const void* concrete, vtkm::FloatDefault val) {
return static_cast<const T*>(concrete)->operator()(val);
};
this->Multiplicand = val;
this->Modified();
}
VTKM_CONT
vtkm::FloatDefault GetMultiplicand() const { return this->Multiplicand; }
VTKM_EXEC
vtkm::FloatDefault operator()(vtkm::FloatDefault val) const
vtkm::FloatDefault Eval(vtkm::FloatDefault val) const override
{
return this->Caller(this->Concrete, val);
return val * this->Multiplicand;
}
private:
using Signature = vtkm::FloatDefault(const void*, vtkm::FloatDefault);
const void* Concrete;
Signature* Caller;
vtkm::FloatDefault Multiplicand = 0.0f;
};
struct Square
class TransformerFunctor
{
VTKM_EXEC
vtkm::FloatDefault operator()(vtkm::FloatDefault val) const { return val * val; }
};
public:
TransformerFunctor() = default;
explicit TransformerFunctor(const Transformer* impl)
: Impl(impl)
{
}
struct Multiply
{
VTKM_EXEC
vtkm::FloatDefault operator()(vtkm::FloatDefault val) const { return val * this->Multiplicand; }
vtkm::FloatDefault operator()(vtkm::FloatDefault val) const { return this->Impl->Eval(val); }
vtkm::FloatDefault Multiplicand;
private:
const Transformer* Impl;
};
} // virtual_object_detail
template <typename DeviceAdapterList>
class TestingVirtualObjectCache
class TestingVirtualObjectHandle
{
private:
using FloatArrayHandle = vtkm::cont::ArrayHandle<vtkm::FloatDefault>;
using ArrayTransform =
vtkm::cont::ArrayHandleTransform<FloatArrayHandle, virtual_object_detail::Transformer>;
using TransformerCache = vtkm::cont::VirtualObjectCache<virtual_object_detail::Transformer>;
vtkm::cont::ArrayHandleTransform<FloatArrayHandle, virtual_object_detail::TransformerFunctor>;
using TransformerHandle = vtkm::cont::VirtualObjectHandle<virtual_object_detail::Transformer>;
class TestStage1
{
public:
TestStage1(const FloatArrayHandle& input, TransformerCache& manager)
TestStage1(const FloatArrayHandle& input, TransformerHandle& handle)
: Input(&input)
, Manager(&manager)
, Handle(&handle)
{
}
@ -107,7 +121,9 @@ private:
for (int n = 0; n < 2; ++n)
{
ArrayTransform transformed(*this->Input, this->Manager->GetVirtualObject(device));
virtual_object_detail::TransformerFunctor tfnctr(this->Handle->PrepareForExecution(device));
ArrayTransform transformed(*this->Input, tfnctr);
FloatArrayHandle output;
Algorithm::Copy(transformed, output);
auto portal = output.GetPortalConstControl();
@ -120,14 +136,14 @@ private:
if (n == 0)
{
std::cout << "\tReleaseResources and test again..." << std::endl;
this->Manager->ReleaseResources();
this->Handle->ReleaseExecutionResources();
}
}
}
private:
const FloatArrayHandle* Input;
TransformerCache* Manager;
TransformerHandle* Handle;
};
class TestStage2
@ -135,10 +151,10 @@ private:
public:
TestStage2(const FloatArrayHandle& input,
virtual_object_detail::Multiply& mul,
TransformerCache& manager)
TransformerHandle& handle)
: Input(&input)
, Mul(&mul)
, Manager(&manager)
, Handle(&handle)
{
}
@ -149,17 +165,18 @@ private:
std::cout << "\tDeviceAdapter: " << vtkm::cont::DeviceAdapterTraits<DeviceAdapter>::GetName()
<< std::endl;
this->Mul->Multiplicand = 2;
this->Manager->SetRefreshFlag(true);
this->Mul->SetMultiplicand(2);
for (int n = 0; n < 2; ++n)
{
ArrayTransform transformed(*this->Input, this->Manager->GetVirtualObject(device));
virtual_object_detail::TransformerFunctor tfnctr(this->Handle->PrepareForExecution(device));
ArrayTransform transformed(*this->Input, tfnctr);
FloatArrayHandle output;
Algorithm::Copy(transformed, output);
auto portal = output.GetPortalConstControl();
for (vtkm::Id i = 0; i < ARRAY_LEN; ++i)
{
VTKM_TEST_ASSERT(portal.Get(i) == FloatDefault(i) * this->Mul->Multiplicand,
VTKM_TEST_ASSERT(portal.Get(i) == FloatDefault(i) * this->Mul->GetMultiplicand(),
"\tIncorrect result");
}
std::cout << "\tSuccess." << std::endl;
@ -167,8 +184,7 @@ private:
if (n == 0)
{
std::cout << "\tUpdate and test again..." << std::endl;
this->Mul->Multiplicand = 3;
this->Manager->SetRefreshFlag(true);
this->Mul->SetMultiplicand(3);
}
}
}
@ -176,7 +192,7 @@ private:
private:
const FloatArrayHandle* Input;
virtual_object_detail::Multiply* Mul;
TransformerCache* Manager;
TransformerHandle* Handle;
};
public:
@ -190,20 +206,20 @@ public:
portal.Set(i, vtkm::FloatDefault(i));
}
TransformerCache manager;
TransformerHandle handle;
std::cout << "Testing with concrete type 1 (Square)..." << std::endl;
virtual_object_detail::Square sqr;
manager.Bind(&sqr, DeviceAdapterList());
vtkm::ListForEach(TestStage1(input, manager), DeviceAdapterList());
handle.Reset(&sqr, false, DeviceAdapterList());
vtkm::ListForEach(TestStage1(input, handle), DeviceAdapterList());
std::cout << "Reset..." << std::endl;
manager.Reset();
handle.Reset();
std::cout << "Testing with concrete type 2 (Multiply)..." << std::endl;
virtual_object_detail::Multiply mul;
manager.Bind(&mul, DeviceAdapterList());
vtkm::ListForEach(TestStage2(input, mul, manager), DeviceAdapterList());
handle.Reset(&mul, false, DeviceAdapterList());
vtkm::ListForEach(TestStage2(input, mul, handle), DeviceAdapterList());
}
};
}

@ -90,12 +90,14 @@ public:
}
};
template <typename VirtualObject, typename TargetClass>
struct VirtualObjectTransfer<VirtualObject,
TargetClass,
vtkm::cont::DeviceAdapterTagTestAlgorithmGeneral>
: public VirtualObjectTransferShareWithControl<VirtualObject, TargetClass>
template <typename TargetClass>
struct VirtualObjectTransfer<TargetClass, vtkm::cont::DeviceAdapterTagTestAlgorithmGeneral>
: public VirtualObjectTransferShareWithControl<TargetClass>
{
VirtualObjectTransfer(const TargetClass* target)
: VirtualObjectTransferShareWithControl<TargetClass>(target)
{
}
};
template <typename T>

@ -106,14 +106,12 @@ struct TestValueFunctor
T operator()(vtkm::Id index) const { return TestValue(index, T()); }
};
bool CheckCalled;
struct CheckFunctor
{
template <typename T, typename Storage>
void operator()(vtkm::cont::ArrayHandle<T, Storage> array) const
void operator()(vtkm::cont::ArrayHandle<T, Storage> array, bool& called) const
{
CheckCalled = true;
called = true;
std::cout << " Checking for type: " << typeid(T).name() << std::endl;
VTKM_TEST_ASSERT(array.GetNumberOfValues() == ARRAY_SIZE, "Unexpected array size.");
@ -138,10 +136,11 @@ void CheckDynamicArray(vtkm::cont::DynamicArrayHandle array, vtkm::IdComponent n
{
BasicDynamicArrayChecks(array, numComponents);
array.CastAndCall(CheckFunctor());
bool called = false;
array.CastAndCall(CheckFunctor(), called);
VTKM_TEST_ASSERT(
CheckCalled, "The functor was never called (and apparently a bad value exception not thrown).");
called, "The functor was never called (and apparently a bad value exception not thrown).");
}
template <typename TypeList, typename StorageList>
@ -150,10 +149,11 @@ void CheckDynamicArray(vtkm::cont::DynamicArrayHandleBase<TypeList, StorageList>
{
BasicDynamicArrayChecks(array, numComponents);
CastAndCall(array, CheckFunctor());
bool called = false;
CastAndCall(array, CheckFunctor(), called);
VTKM_TEST_ASSERT(
CheckCalled, "The functor was never called (and apparently a bad value exception not thrown).");
called, "The functor was never called (and apparently a bad value exception not thrown).");
}
template <typename T>
@ -223,8 +223,6 @@ void TryNewInstance(T, DynamicArrayType originalArray)
template <typename T>
void TryDefaultType(T)
{
CheckCalled = false;
vtkm::cont::DynamicArrayHandle array = CreateDynamicArray(T());
CheckDynamicArray(array, vtkm::VecTraits<T>::NUM_COMPONENTS);
@ -237,8 +235,6 @@ struct TryBasicVTKmType
template <typename T>
void operator()(T) const
{
CheckCalled = false;
vtkm::cont::DynamicArrayHandle array = CreateDynamicArray(T());
CheckDynamicArray(array.ResetTypeList(vtkm::TypeListTagAll()),
@ -263,10 +259,7 @@ void TryUnusualType()
std::cout << " Caught exception for unrecognized type." << std::endl;
}
CheckCalled = false;
CheckDynamicArray(array.ResetTypeList(TypeListTagString()), 1);
VTKM_TEST_ASSERT(
CheckCalled, "The functor was never called (and apparently a bad value exception not thrown).");
std::cout << " Found type when type list was reset." << std::endl;
}
@ -284,7 +277,6 @@ void TryUnusualStorage()
std::cout << " Caught exception for unrecognized storage." << std::endl;
}
CheckCalled = false;
CheckDynamicArray(array.ResetStorageList(StorageListTagUnusual()), 1);
std::cout << " Found instance when storage list was reset." << std::endl;
}
@ -334,17 +326,14 @@ void TryUnusualTypeAndStorage()
VTKM_TEST_FAIL("ResetTypeAndStorageLists should have handled the custom type/storage.");
}
CheckCalled = false;
CheckDynamicArray(
array.ResetTypeList(TypeListTagString()).ResetStorageList(StorageListTagUnusual()), 1);
std::cout << " Found instance when type and storage lists were reset." << std::endl;
CheckCalled = false;
CheckDynamicArray(
array.ResetStorageList(StorageListTagUnusual()).ResetTypeList(TypeListTagString()), 1);
std::cout << " Found instance when storage and type lists were reset." << std::endl;
CheckCalled = false;
CheckDynamicArray(array.ResetTypeAndStorageLists(TypeListTagString(), StorageListTagUnusual()),
1);
std::cout << " Found instance when storage and type lists were reset." << std::endl;

@ -34,17 +34,16 @@ struct NonDefaultCellSetList
{
};
bool CheckCalled;
template <typename ExpectedCellType>
struct CheckFunctor
{
void operator()(const ExpectedCellType&) const { CheckCalled = true; }
void operator()(const ExpectedCellType&, bool& called) const { called = true; }
template <typename UnexpectedType>
void operator()(const UnexpectedType&) const
void operator()(const UnexpectedType&, bool& called) const
{
VTKM_TEST_FAIL("CastAndCall functor called with wrong type.");
called = false;
}
};
@ -60,17 +59,17 @@ void CheckDynamicCellSet(const CellSetType& cellSet,
dynamicCellSet.template Cast<CellSetType>();
CheckCalled = false;
dynamicCellSet.CastAndCall(CheckFunctor<CellSetType>());
bool called = false;
dynamicCellSet.CastAndCall(CheckFunctor<CellSetType>(), called);
VTKM_TEST_ASSERT(
CheckCalled, "The functor was never called (and apparently a bad value exception not thrown).");
called, "The functor was never called (and apparently a bad value exception not thrown).");
CheckCalled = false;
CastAndCall(dynamicCellSet, CheckFunctor<CellSetType>());
called = false;
CastAndCall(dynamicCellSet, CheckFunctor<CellSetType>(), called);
VTKM_TEST_ASSERT(
CheckCalled, "The functor was never called (and apparently a bad value exception not thrown).");
called, "The functor was never called (and apparently a bad value exception not thrown).");
}
template <typename CellSetType, typename CellSetList>

@ -21,6 +21,7 @@
#define VTKM_DEVICE_ADAPTER VTKM_DEVICE_ADAPTER_ERROR
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/RuntimeDeviceTracker.h>
#include <vtkm/cont/TryExecute.h>
#include <vtkm/cont/serial/DeviceAdapterSerial.h>
@ -36,30 +37,27 @@ static const vtkm::Id ARRAY_SIZE = 10;
struct TryExecuteTestFunctor
{
vtkm::IdComponent NumCalls;
vtkm::cont::ArrayHandle<vtkm::FloatDefault> InArray;
vtkm::cont::ArrayHandle<vtkm::FloatDefault> OutArray;
VTKM_CONT
TryExecuteTestFunctor(vtkm::cont::ArrayHandle<vtkm::FloatDefault> inArray,
vtkm::cont::ArrayHandle<vtkm::FloatDefault> outArray)
TryExecuteTestFunctor()
: NumCalls(0)
, InArray(inArray)
, OutArray(outArray)
{
}
template <typename Device>
VTKM_CONT bool operator()(Device)
VTKM_CONT bool operator()(Device,
const vtkm::cont::ArrayHandle<vtkm::FloatDefault>& in,
vtkm::cont::ArrayHandle<vtkm::FloatDefault>& out)
{
using Algorithm = vtkm::cont::DeviceAdapterAlgorithm<Device>;
Algorithm::Copy(this->InArray, this->OutArray);
Algorithm::Copy(in, out);
this->NumCalls++;
return true;
}
};
template <typename DeviceList>
void TryExecuteWithList(DeviceList, bool expectSuccess)
void TryExecuteWithDevice(DeviceList, bool expectSuccess)
{
vtkm::cont::ArrayHandle<vtkm::FloatDefault> inArray;
vtkm::cont::ArrayHandle<vtkm::FloatDefault> outArray;
@ -67,9 +65,9 @@ void TryExecuteWithList(DeviceList, bool expectSuccess)
inArray.Allocate(ARRAY_SIZE);
SetPortal(inArray.GetPortalControl());
TryExecuteTestFunctor functor(inArray, outArray);
TryExecuteTestFunctor functor;
bool result = vtkm::cont::TryExecute(functor, DeviceList());
bool result = vtkm::cont::TryExecute(functor, DeviceList(), inArray, outArray);
if (expectSuccess)
{
@ -81,6 +79,96 @@ void TryExecuteWithList(DeviceList, bool expectSuccess)
{
VTKM_TEST_ASSERT(!result, "Call returned true when expected failure.");
}
//verify the ability to pass rvalue functors
vtkm::cont::ArrayHandle<vtkm::FloatDefault> outArray2;
result = vtkm::cont::TryExecute(TryExecuteTestFunctor(), DeviceList(), inArray, outArray2);
if (expectSuccess)
{
VTKM_TEST_ASSERT(result, "Call returned failure when expected success.");
CheckPortal(outArray2.GetPortalConstControl());
}
else
{
VTKM_TEST_ASSERT(!result, "Call returned true when expected failure.");
}
}
template <typename DeviceList>
void TryExecuteAllExplicit(DeviceList, bool expectSuccess)
{
vtkm::cont::RuntimeDeviceTracker tracker;
vtkm::cont::ArrayHandle<vtkm::FloatDefault> inArray;
vtkm::cont::ArrayHandle<vtkm::FloatDefault> outArray;
inArray.Allocate(ARRAY_SIZE);
SetPortal(inArray.GetPortalControl());
bool result =
vtkm::cont::TryExecute(TryExecuteTestFunctor(), tracker, DeviceList(), inArray, outArray);
if (expectSuccess)
{
VTKM_TEST_ASSERT(result, "Call returned failure when expected success.");
CheckPortal(outArray.GetPortalConstControl());
}
else
{
VTKM_TEST_ASSERT(!result, "Call returned true when expected failure.");
}
}
struct EdgeCaseFunctor
{
template <typename DeviceList>
bool operator()(DeviceList, int, float, bool) const
{
return true;
}
template <typename DeviceList>
bool operator()(DeviceList) const
{
return true;
}
};
void TryExecuteAllEdgeCases()
{
using ValidDevice = vtkm::cont::DeviceAdapterTagSerial;
using SingleValidList = vtkm::ListTagBase<ValidDevice>;
auto tracker = vtkm::cont::GetGlobalRuntimeDeviceTracker();
std::cout << "TryExecute no Runtime, no Device, no parameters." << std::endl;
vtkm::cont::TryExecute(EdgeCaseFunctor());
std::cout << "TryExecute no Runtime, no Device, with parameters." << std::endl;
vtkm::cont::TryExecute(EdgeCaseFunctor(), int{ 42 }, float{ 3.14f }, bool{ true });
std::cout << "TryExecute with Runtime, no Device, no parameters." << std::endl;
vtkm::cont::TryExecute(EdgeCaseFunctor(), tracker);
std::cout << "TryExecute with Runtime, no Device, with parameters." << std::endl;
vtkm::cont::TryExecute(EdgeCaseFunctor(), tracker, int{ 42 }, float{ 3.14f }, bool{ true });
std::cout << "TryExecute no Runtime, with Device, no parameters." << std::endl;
vtkm::cont::TryExecute(EdgeCaseFunctor(), SingleValidList());
std::cout << "TryExecute no Runtime, with Device, with parameters." << std::endl;
vtkm::cont::TryExecute(
EdgeCaseFunctor(), SingleValidList(), int{ 42 }, float{ 3.14f }, bool{ true });
std::cout << "TryExecute with Runtime, with Device, no parameters." << std::endl;
vtkm::cont::TryExecute(EdgeCaseFunctor(), tracker, SingleValidList());
std::cout << "TryExecute with Runtime, with Device, with parameters." << std::endl;
vtkm::cont::TryExecute(
EdgeCaseFunctor(), tracker, SingleValidList(), int{ 42 }, float{ 3.14f }, bool{ true });
}
template <typename DeviceList>
void TryExecuteTests(DeviceList list, bool expectSuccess)
{
TryExecuteAllExplicit(list, expectSuccess);
TryExecuteWithDevice(list, expectSuccess);
}
static void Run()
@ -88,21 +176,24 @@ static void Run()
using ValidDevice = vtkm::cont::DeviceAdapterTagSerial;
using InvalidDevice = vtkm::cont::DeviceAdapterTagError;
TryExecuteAllEdgeCases();
std::cout << "Try a list with a single entry." << std::endl;
using SingleValidList = vtkm::ListTagBase<ValidDevice>;
TryExecuteWithList(SingleValidList(), true);
TryExecuteTests(SingleValidList(), true);
std::cout << "Try a list with two valid devices." << std::endl;
using DoubleValidList = vtkm::ListTagBase<ValidDevice, ValidDevice>;
TryExecuteWithList(DoubleValidList(), true);
TryExecuteTests(DoubleValidList(), true);
std::cout << "Try a list with only invalid device." << std::endl;
using SingleInvalidList = vtkm::ListTagBase<InvalidDevice>;
TryExecuteWithList(SingleInvalidList(), false);
TryExecuteTests(SingleInvalidList(), false);
std::cout << "Try a list with an invalid and valid device." << std::endl;
using InvalidAndValidList = vtkm::ListTagBase<InvalidDevice, ValidDevice>;
TryExecuteWithList(InvalidAndValidList(), true);
TryExecuteTests(InvalidAndValidList(), true);
}
} // anonymous namespace

@ -21,12 +21,10 @@
#ifndef vtk_m_filter_ClipWithImplicitFunction_h
#define vtk_m_filter_ClipWithImplicitFunction_h
#include <vtkm/cont/ImplicitFunction.h>
#include <vtkm/cont/ImplicitFunctionHandle.h>
#include <vtkm/filter/FilterDataSet.h>
#include <vtkm/worklet/Clip.h>
#include <memory>
namespace vtkm
{
namespace filter
@ -34,26 +32,18 @@ namespace filter
/// \brief Clip a dataset using an implicit function
///
/// Clip a dataset using a given implicit function value, such as vtkm::cont::Sphere
/// or vtkm::cont::Frustum.
/// Clip a dataset using a given implicit function value, such as vtkm::Sphere
/// or vtkm::Frustum.
/// The resulting geometry will not be water tight.
class ClipWithImplicitFunction : public vtkm::filter::FilterDataSet<ClipWithImplicitFunction>
{
public:
template <typename ImplicitFunctionType, typename DerivedPolicy>
void SetImplicitFunction(const std::shared_ptr<ImplicitFunctionType>& func,
const vtkm::filter::PolicyBase<DerivedPolicy>& policy);
template <typename ImplicitFunctionType>
void SetImplicitFunction(const std::shared_ptr<ImplicitFunctionType>& func)
void SetImplicitFunction(const vtkm::cont::ImplicitFunctionHandle& func)
{
this->Function = func;
}
std::shared_ptr<vtkm::cont::ImplicitFunction> GetImplicitFunction() const
{
return this->Function;
}
const vtkm::cont::ImplicitFunctionHandle& GetImplicitFunction() const { return this->Function; }
template <typename DerivedPolicy, typename DeviceAdapter>
vtkm::filter::Result DoExecute(const vtkm::cont::DataSet& input,
@ -70,7 +60,7 @@ public:
const DeviceAdapter& tag);
private:
std::shared_ptr<vtkm::cont::ImplicitFunction> Function;
vtkm::cont::ImplicitFunctionHandle Function;
vtkm::worklet::Clip Worklet;
};
}

@ -53,16 +53,6 @@ struct PointMapHelper
} // end namespace clipwithimplicitfunction
//-----------------------------------------------------------------------------
template <typename ImplicitFunctionType, typename DerivedPolicy>
inline void ClipWithImplicitFunction::SetImplicitFunction(
const std::shared_ptr<ImplicitFunctionType>& func,
const vtkm::filter::PolicyBase<DerivedPolicy>&)
{
func->ResetDevices(DerivedPolicy::DeviceAdapterList);
this->Function = func;
}
//-----------------------------------------------------------------------------
template <typename DerivedPolicy, typename DeviceAdapter>
inline vtkm::filter::Result ClipWithImplicitFunction::DoExecute(
@ -79,7 +69,7 @@ inline vtkm::filter::Result ClipWithImplicitFunction::DoExecute(
input.GetCoordinateSystem(this->GetActiveCoordinateSystemIndex());
vtkm::cont::CellSetExplicit<> outputCellSet = this->Worklet.Run(
vtkm::filter::ApplyPolicy(cells, policy), *this->Function, inputCoords, device);
vtkm::filter::ApplyPolicy(cells, policy), this->Function, inputCoords, device);
// compute output coordinates
vtkm::cont::DynamicArrayHandle outputCoordsArray;

@ -21,7 +21,7 @@
#ifndef vtk_m_filter_ExtractGeometry_h
#define vtk_m_filter_ExtractGeometry_h
#include <vtkm/cont/ImplicitFunction.h>
#include <vtkm/cont/ImplicitFunctionHandle.h>
#include <vtkm/filter/FilterDataSet.h>
#include <vtkm/worklet/ExtractGeometry.h>
@ -52,20 +52,12 @@ public:
ExtractGeometry();
// Set the volume of interest to extract
template <typename ImplicitFunctionType, typename DerivedPolicy>
void SetImplicitFunction(const std::shared_ptr<ImplicitFunctionType>& func,
const vtkm::filter::PolicyBase<DerivedPolicy>& policy);
template <typename ImplicitFunctionType>
void SetImplicitFunction(const std::shared_ptr<ImplicitFunctionType>& func)
void SetImplicitFunction(const vtkm::cont::ImplicitFunctionHandle& func)
{
this->Function = func;
}
std::shared_ptr<vtkm::cont::ImplicitFunction> GetImplicitFunction() const
{
return this->Function;
}
const vtkm::cont::ImplicitFunctionHandle& GetImplicitFunction() const { return this->Function; }
VTKM_CONT
bool GetExtractInside() { return this->ExtractInside; }
@ -111,7 +103,7 @@ private:
bool ExtractInside;
bool ExtractBoundaryCells;
bool ExtractOnlyBoundaryCells;
std::shared_ptr<vtkm::cont::ImplicitFunction> Function;
vtkm::cont::ImplicitFunctionHandle Function;
vtkm::worklet::ExtractGeometry Worklet;
};

@ -34,7 +34,7 @@ struct CallWorker
vtkm::cont::DynamicCellSet& Output;
vtkm::worklet::ExtractGeometry& Worklet;
const vtkm::cont::CoordinateSystem& Coords;
const vtkm::cont::ImplicitFunction& Function;
const vtkm::cont::ImplicitFunctionHandle& Function;
bool ExtractInside;
bool ExtractBoundaryCells;
bool ExtractOnlyBoundaryCells;
@ -42,7 +42,7 @@ struct CallWorker
CallWorker(vtkm::cont::DynamicCellSet& output,
vtkm::worklet::ExtractGeometry& worklet,
const vtkm::cont::CoordinateSystem& coords,
const vtkm::cont::ImplicitFunction& function,
const vtkm::cont::ImplicitFunctionHandle& function,
bool extractInside,
bool extractBoundaryCells,
bool extractOnlyBoundaryCells)
@ -76,15 +76,6 @@ namespace vtkm
namespace filter
{
//-----------------------------------------------------------------------------
template <typename ImplicitFunctionType, typename DerivedPolicy>
inline void ExtractGeometry::SetImplicitFunction(const std::shared_ptr<ImplicitFunctionType>& func,
const vtkm::filter::PolicyBase<DerivedPolicy>&)
{
func->ResetDevices(DerivedPolicy::DeviceAdapterList);
this->Function = func;
}
//-----------------------------------------------------------------------------
inline VTKM_CONT ExtractGeometry::ExtractGeometry()
: vtkm::filter::FilterDataSet<ExtractGeometry>()
@ -110,7 +101,7 @@ inline VTKM_CONT vtkm::filter::Result ExtractGeometry::DoExecute(
CallWorker<DeviceAdapter> worker(outCells,
this->Worklet,
coords,
*this->Function,
this->Function,
this->ExtractInside,
this->ExtractBoundaryCells,
this->ExtractOnlyBoundaryCells);

@ -21,7 +21,7 @@
#ifndef vtk_m_filter_ExtractPoints_h
#define vtk_m_filter_ExtractPoints_h
#include <vtkm/cont/ImplicitFunction.h>
#include <vtkm/cont/ImplicitFunctionHandle.h>
#include <vtkm/filter/CleanGrid.h>
#include <vtkm/filter/FilterDataSet.h>
#include <vtkm/worklet/ExtractPoints.h>
@ -53,21 +53,12 @@ public:
void SetCompactPoints(bool value) { this->CompactPoints = value; }
/// Set the volume of interest to extract
template <typename ImplicitFunctionType, typename DerivedPolicy>
void SetImplicitFunction(const std::shared_ptr<ImplicitFunctionType>& func,
const vtkm::filter::PolicyBase<DerivedPolicy>& policy);
/// Set the volume of interest to extract
template <typename ImplicitFunctionType>
void SetImplicitFunction(const std::shared_ptr<ImplicitFunctionType>& func)
void SetImplicitFunction(const vtkm::cont::ImplicitFunctionHandle& func)
{
this->Function = func;
}
std::shared_ptr<vtkm::cont::ImplicitFunction> GetImplicitFunction() const
{
return this->Function;
}
const vtkm::cont::ImplicitFunctionHandle& GetImplicitFunction() const { return this->Function; }
VTKM_CONT
bool GetExtractInside() { return this->ExtractInside; }
@ -93,7 +84,7 @@ public:
private:
bool ExtractInside;
std::shared_ptr<vtkm::cont::ImplicitFunction> Function;
vtkm::cont::ImplicitFunctionHandle Function;
bool CompactPoints;
vtkm::filter::CleanGrid Compactor;

@ -44,15 +44,6 @@ namespace vtkm
namespace filter
{
//-----------------------------------------------------------------------------
template <typename ImplicitFunctionType, typename DerivedPolicy>
inline void ExtractPoints::SetImplicitFunction(const std::shared_ptr<ImplicitFunctionType>& func,
const vtkm::filter::PolicyBase<DerivedPolicy>&)
{
func->ResetDevices(DerivedPolicy::DeviceAdapterList);
this->Function = func;
}
//-----------------------------------------------------------------------------
inline VTKM_CONT ExtractPoints::ExtractPoints()
: vtkm::filter::FilterDataSet<ExtractPoints>()
@ -79,7 +70,7 @@ inline vtkm::filter::Result ExtractPoints::DoExecute(
outCellSet = worklet.Run(vtkm::filter::ApplyPolicy(cells, policy),
vtkm::filter::ApplyPolicy(coords, policy),
*this->Function,
this->Function,
this->ExtractInside,
device);

@ -139,11 +139,11 @@ inline VTKM_CONT bool FilterDataSet<Derived>::MapFieldOntoOutput(
{
vtkm::filter::FieldMetadata metaData(field);
typedef internal::ResolveFieldTypeAndMap<Derived, DerivedPolicy> FunctorType;
FunctorType functor(
static_cast<Derived*>(this), result, metaData, policy, this->Tracker, valid);
FunctorType functor(static_cast<Derived*>(this), result, metaData, policy, valid);
typedef vtkm::filter::FilterTraits<Derived> Traits;
vtkm::cont::CastAndCall(vtkm::filter::ApplyPolicy(field, policy, Traits()), functor);
vtkm::cont::CastAndCall(
vtkm::filter::ApplyPolicy(field, policy, Traits()), functor, this->Tracker);
}
//the bool valid will be modified by the map algorithm to hold if the

@ -162,10 +162,11 @@ inline VTKM_CONT Result FilterDataSetWithField<Derived>::PrepareForExecution(
Result result;
typedef internal::ResolveFieldTypeAndExecute<Derived, DerivedPolicy, Result> FunctorType;
FunctorType functor(static_cast<Derived*>(this), input, metaData, policy, this->Tracker, result);
FunctorType functor(static_cast<Derived*>(this), input, metaData, policy, result);
typedef vtkm::filter::FilterTraits<Derived> Traits;
vtkm::cont::CastAndCall(vtkm::filter::ApplyPolicy(field, policy, Traits()), functor);
vtkm::cont::CastAndCall(
vtkm::filter::ApplyPolicy(field, policy, Traits()), functor, this->Tracker);
return result;
}
@ -184,10 +185,11 @@ inline VTKM_CONT Result FilterDataSetWithField<Derived>::PrepareForExecution(
//determine the field type first
Result result;
typedef internal::ResolveFieldTypeAndExecute<Derived, DerivedPolicy, Result> FunctorType;
FunctorType functor(static_cast<Derived*>(this), input, metaData, policy, this->Tracker, result);
FunctorType functor(static_cast<Derived*>(this), input, metaData, policy, result);
typedef vtkm::filter::FilterTraits<Derived> Traits;
vtkm::cont::CastAndCall(vtkm::filter::ApplyPolicy(field, policy, Traits()), functor);
vtkm::cont::CastAndCall(
vtkm::filter::ApplyPolicy(field, policy, Traits()), functor, this->Tracker);
return result;
}
@ -214,10 +216,9 @@ inline VTKM_CONT bool FilterDataSetWithField<Derived>::MapFieldOntoOutput(
{
vtkm::filter::FieldMetadata metaData(field);
typedef internal::ResolveFieldTypeAndMap<Derived, DerivedPolicy> FunctorType;
FunctorType functor(
static_cast<Derived*>(this), result, metaData, policy, this->Tracker, valid);
FunctorType functor(static_cast<Derived*>(this), result, metaData, policy, valid);
vtkm::cont::CastAndCall(vtkm::filter::ApplyPolicy(field, policy), functor);
vtkm::cont::CastAndCall(vtkm::filter::ApplyPolicy(field, policy), functor, this->Tracker);
}
//the bool valid will be modified by the map algorithm to hold if the

@ -159,10 +159,11 @@ FilterField<Derived>::PrepareForExecution(const vtkm::cont::DataSet& input,
Result result;
typedef internal::ResolveFieldTypeAndExecute<Derived, DerivedPolicy, Result> FunctorType;
FunctorType functor(static_cast<Derived*>(this), input, metaData, policy, this->Tracker, result);
FunctorType functor(static_cast<Derived*>(this), input, metaData, policy, result);
typedef vtkm::filter::FilterTraits<Derived> Traits;
vtkm::cont::CastAndCall(vtkm::filter::ApplyPolicy(field, policy, Traits()), functor);
vtkm::cont::CastAndCall(
vtkm::filter::ApplyPolicy(field, policy, Traits()), functor, this->Tracker);
return result;
}
@ -181,10 +182,11 @@ FilterField<Derived>::PrepareForExecution(const vtkm::cont::DataSet& input,
Result result;
typedef internal::ResolveFieldTypeAndExecute<Derived, DerivedPolicy, Result> FunctorType;
FunctorType functor(static_cast<Derived*>(this), input, metaData, policy, this->Tracker, result);
FunctorType functor(static_cast<Derived*>(this), input, metaData, policy, result);
typedef vtkm::filter::FilterTraits<Derived> Traits;
vtkm::cont::CastAndCall(vtkm::filter::ApplyPolicy(field, policy, Traits()), functor);
vtkm::cont::CastAndCall(
vtkm::filter::ApplyPolicy(field, policy, Traits()), functor, this->Tracker);
return result;
}
}

@ -35,6 +35,18 @@ namespace filter
namespace internal
{
struct ResolveFieldTypeAndExecuteForDevice
{
template <typename DeviceAdapterTag, typename InstanceType, typename FieldType>
bool operator()(DeviceAdapterTag tag, InstanceType&& instance, FieldType&& field) const
{
instance.Result = instance.DerivedClass->DoExecute(
instance.InputData, field, instance.Metadata, instance.Policy, tag);
return instance.Result.IsValid();
}
};
template <typename Derived, typename DerivedPolicy, typename ResultType>
struct ResolveFieldTypeAndExecute
{
@ -44,56 +56,28 @@ struct ResolveFieldTypeAndExecute
const vtkm::cont::DataSet& InputData;
const vtkm::filter::FieldMetadata& Metadata;
const vtkm::filter::PolicyBase<DerivedPolicy>& Policy;
vtkm::cont::RuntimeDeviceTracker Tracker;
ResultType& Result;
ResolveFieldTypeAndExecute(Derived* derivedClass,
const vtkm::cont::DataSet& inputData,
const vtkm::filter::FieldMetadata& fieldMeta,
const vtkm::filter::PolicyBase<DerivedPolicy>& policy,
const vtkm::cont::RuntimeDeviceTracker& tracker,
ResultType& result)
: DerivedClass(derivedClass)
, InputData(inputData)
, Metadata(fieldMeta)
, Policy(policy)
, Tracker(tracker)
, Result(result)
{
}
private:
template <typename T, typename StorageTag>
struct ResolveFieldTypeAndExecuteForDevice
void operator()(const vtkm::cont::ArrayHandle<T, StorageTag>& field,
vtkm::cont::RuntimeDeviceTracker& tracker) const
{
typedef vtkm::cont::ArrayHandle<T, StorageTag> FieldArrayHandle;
ResolveFieldTypeAndExecuteForDevice(const Self& instance, const FieldArrayHandle& field)
: Instance(instance)
, Field(field)
{
}
const Self& Instance;
const vtkm::cont::ArrayHandle<T, StorageTag>& Field;
template <typename DeviceAdapterTag>
bool operator()(DeviceAdapterTag tag) const
{
this->Instance.Result = this->Instance.DerivedClass->DoExecute(
this->Instance.InputData, this->Field, this->Instance.Metadata, this->Instance.Policy, tag);
return this->Instance.Result.IsValid();
}
private:
void operator=(const ResolveFieldTypeAndExecuteForDevice<T, StorageTag>&) = delete;
};
public:
template <typename T, typename StorageTag>
void operator()(const vtkm::cont::ArrayHandle<T, StorageTag>& field) const
{
ResolveFieldTypeAndExecuteForDevice<T, StorageTag> doResolve(*this, field);
vtkm::cont::TryExecute(doResolve, this->Tracker, typename DerivedPolicy::DeviceAdapterList());
ResolveFieldTypeAndExecuteForDevice doResolve;
vtkm::cont::TryExecute(
doResolve, tracker, typename DerivedPolicy::DeviceAdapterList(), *this, field);
}
private:

@ -43,6 +43,15 @@ namespace filter
{
namespace internal
{
struct ResolveFieldTypeAndMapForDevice
{
template <typename DeviceAdapterTag, typename InstanceType, typename FieldType>
bool operator()(DeviceAdapterTag tag, InstanceType&& instance, FieldType&& field) const
{
return instance.DerivedClass->DoMapField(
instance.InputResult, field, instance.Metadata, instance.Policy, tag);
}
};
template <typename Derived, typename DerivedPolicy>
struct ResolveFieldTypeAndMap
@ -53,63 +62,28 @@ struct ResolveFieldTypeAndMap
vtkm::filter::Result& InputResult;
const vtkm::filter::FieldMetadata& Metadata;
const vtkm::filter::PolicyBase<DerivedPolicy>& Policy;
vtkm::cont::RuntimeDeviceTracker Tracker;
bool& RanProperly;
ResolveFieldTypeAndMap(Derived* derivedClass,
vtkm::filter::Result& inResult,
const vtkm::filter::FieldMetadata& fieldMeta,
const vtkm::filter::PolicyBase<DerivedPolicy>& policy,
const vtkm::cont::RuntimeDeviceTracker& tracker,
bool& ran)
: DerivedClass(derivedClass)
, InputResult(inResult)
, Metadata(fieldMeta)
, Policy(policy)
, Tracker(tracker)
, RanProperly(ran)
{
}
private:
template <typename T, typename StorageTag>
struct ResolveFieldTypeAndMapForDevice
void operator()(const vtkm::cont::ArrayHandle<T, StorageTag>& field,
vtkm::cont::RuntimeDeviceTracker& tracker) const
{
typedef vtkm::cont::ArrayHandle<T, StorageTag> FieldArrayHandle;
ResolveFieldTypeAndMapForDevice(const Self& instance, const FieldArrayHandle& field)
: Instance(instance)
, Field(field)
, Valid(false)
{
}
const Self& Instance;
const vtkm::cont::ArrayHandle<T, StorageTag>& Field;
mutable bool Valid;
template <typename DeviceAdapterTag>
bool operator()(DeviceAdapterTag tag) const
{
this->Valid = this->Instance.DerivedClass->DoMapField(this->Instance.InputResult,
this->Field,
this->Instance.Metadata,
this->Instance.Policy,
tag);
return this->Valid;
}
private:
void operator=(const ResolveFieldTypeAndMapForDevice<T, StorageTag>&) = delete;
};
public:
template <typename T, typename StorageTag>
void operator()(const vtkm::cont::ArrayHandle<T, StorageTag>& field) const
{
ResolveFieldTypeAndMapForDevice<T, StorageTag> doResolve(*this, field);
vtkm::cont::TryExecute(doResolve, this->Tracker, typename DerivedPolicy::DeviceAdapterList());
this->RanProperly = doResolve.Valid;
ResolveFieldTypeAndMapForDevice doResolve;
this->RanProperly = vtkm::cont::TryExecute(
doResolve, tracker, typename DerivedPolicy::DeviceAdapterList(), *this, field);
}
private:

@ -60,11 +60,10 @@ void TestClipStructured()
vtkm::Vec<vtkm::FloatDefault, 3> center(1, 1, 0);
vtkm::FloatDefault radius(0.5);
auto sphere = std::make_shared<vtkm::cont::Sphere>(center, radius);
vtkm::filter::Result result;
vtkm::filter::ClipWithImplicitFunction clip;
clip.SetImplicitFunction(sphere);
clip.SetImplicitFunction(vtkm::cont::make_ImplicitFunctionHandle(vtkm::Sphere(center, radius)));
result = clip.Execute(ds);
clip.MapFieldOntoOutput(result, ds.GetField("scalars"));

@ -40,7 +40,7 @@ public:
// Implicit function
vtkm::Vec<vtkm::FloatDefault, 3> minPoint(1.f, 1.f, 1.f);
vtkm::Vec<vtkm::FloatDefault, 3> maxPoint(3.f, 3.f, 3.f);
auto box = std::make_shared<vtkm::cont::Box>(minPoint, maxPoint);
auto box = vtkm::cont::make_ImplicitFunctionHandle<vtkm::Box>(minPoint, maxPoint);
// Setup and run filter to extract by volume of interest
vtkm::filter::ExtractGeometry extractGeometry;
@ -76,7 +76,7 @@ public:
// Implicit function
vtkm::Vec<vtkm::FloatDefault, 3> minPoint(1.f, 1.f, 1.f);
vtkm::Vec<vtkm::FloatDefault, 3> maxPoint(3.f, 3.f, 3.f);
auto box = std::make_shared<vtkm::cont::Box>(minPoint, maxPoint);
auto box = vtkm::cont::make_ImplicitFunctionHandle<vtkm::Box>(minPoint, maxPoint);
// Setup and run filter to extract by volume of interest
vtkm::filter::ExtractGeometry extractGeometry;
@ -112,7 +112,7 @@ public:
// Implicit function
vtkm::Vec<vtkm::FloatDefault, 3> minPoint(0.5f, 0.5f, 0.5f);
vtkm::Vec<vtkm::FloatDefault, 3> maxPoint(3.5f, 3.5f, 3.5f);
auto box = std::make_shared<vtkm::cont::Box>(minPoint, maxPoint);
auto box = vtkm::cont::make_ImplicitFunctionHandle<vtkm::Box>(minPoint, maxPoint);
// Setup and run filter to extract by volume of interest
vtkm::filter::ExtractGeometry extractGeometry;
@ -147,7 +147,7 @@ public:
// Implicit function
vtkm::Vec<vtkm::FloatDefault, 3> minPoint(0.5f, 0.5f, 0.5f);
vtkm::Vec<vtkm::FloatDefault, 3> maxPoint(3.5f, 3.5f, 3.5f);
auto box = std::make_shared<vtkm::cont::Box>(minPoint, maxPoint);
auto box = vtkm::cont::make_ImplicitFunctionHandle<vtkm::Box>(minPoint, maxPoint);
// Setup and run filter to extract by volume of interest
vtkm::filter::ExtractGeometry extractGeometry;

@ -40,7 +40,7 @@ public:
// Implicit function
vtkm::Vec<vtkm::FloatDefault, 3> minPoint(1.f, 1.f, 1.f);
vtkm::Vec<vtkm::FloatDefault, 3> maxPoint(3.f, 3.f, 3.f);
auto box = std::make_shared<vtkm::cont::Box>(minPoint, maxPoint);
auto box = vtkm::cont::make_ImplicitFunctionHandle<vtkm::Box>(minPoint, maxPoint);
// Setup and run filter to extract by volume of interest
vtkm::filter::ExtractPoints extractPoints;
@ -82,7 +82,7 @@ public:
// Implicit function
vtkm::Vec<vtkm::FloatDefault, 3> minPoint(1.f, 1.f, 1.f);
vtkm::Vec<vtkm::FloatDefault, 3> maxPoint(3.f, 3.f, 3.f);
auto box = std::make_shared<vtkm::cont::Box>(minPoint, maxPoint);
auto box = vtkm::cont::make_ImplicitFunctionHandle<vtkm::Box>(minPoint, maxPoint);
// Setup and run filter to extract by volume of interest
vtkm::filter::ExtractPoints extractPoints;
@ -125,7 +125,7 @@ public:
// Implicit function
vtkm::Vec<vtkm::FloatDefault, 3> center(2.f, 2.f, 2.f);
vtkm::FloatDefault radius(1.8f);
auto sphere = std::make_shared<vtkm::cont::Sphere>(center, radius);
auto sphere = vtkm::cont::make_ImplicitFunctionHandle<vtkm::Sphere>(center, radius);
// Setup and run filter to extract by volume of interest
vtkm::filter::ExtractPoints extractPoints;
@ -154,7 +154,7 @@ public:
// Implicit function
vtkm::Vec<vtkm::FloatDefault, 3> minPoint(0.f, 0.f, 0.f);
vtkm::Vec<vtkm::FloatDefault, 3> maxPoint(1.f, 1.f, 1.f);
auto box = std::make_shared<vtkm::cont::Box>(minPoint, maxPoint);
auto box = vtkm::cont::make_ImplicitFunctionHandle<vtkm::Box>(minPoint, maxPoint);
// Setup and run filter to extract by volume of interest
vtkm::filter::ExtractPoints extractPoints;
@ -183,7 +183,7 @@ public:
// Implicit function
vtkm::Vec<vtkm::FloatDefault, 3> minPoint(0.f, 0.f, 0.f);
vtkm::Vec<vtkm::FloatDefault, 3> maxPoint(1.f, 1.f, 1.f);
auto box = std::make_shared<vtkm::cont::Box>(minPoint, maxPoint);
auto box = vtkm::cont::make_ImplicitFunctionHandle<vtkm::Box>(minPoint, maxPoint);
// Setup and run filter to extract by volume of interest
vtkm::filter::ExtractPoints extractPoints;

@ -89,8 +89,6 @@
#define VTKM_NOEXCEPT noexcept
#endif
#define VTKM_OVERRIDE override
// Clang will warn about weak vtables (-Wweak-vtables) on exception classes,
// but there's no good way to eliminate them in this case because MSVC (See
// http://stackoverflow.com/questions/24511376). These macros will silence the

@ -165,30 +165,30 @@ struct ListIntersect<SameListTag, SameListTag>
using type = SameListTag;
};
template <typename Functor>
VTKM_CONT void ListForEachImpl(Functor&&, brigand::empty_sequence)
template <typename Functor, typename... Args>
VTKM_CONT void ListForEachImpl(Functor&&, brigand::list<>, Args&&...)
{
}
template <typename Functor, typename T1>
VTKM_CONT void ListForEachImpl(Functor&& f, brigand::list<T1>)
template <typename Functor, typename T1, typename... Args>
VTKM_CONT void ListForEachImpl(Functor&& f, brigand::list<T1>, Args&&... args)
{
f(T1{});
f(T1{}, std::forward<Args>(args)...);
}
template <typename Functor, typename T1, typename T2>
VTKM_CONT void ListForEachImpl(Functor&& f, brigand::list<T1, T2>)
template <typename Functor, typename T1, typename T2, typename... Args>
VTKM_CONT void ListForEachImpl(Functor&& f, brigand::list<T1, T2>, Args&&... args)
{
f(T1{});
f(T2{});
f(T1{}, std::forward<Args>(args)...);
f(T2{}, std::forward<Args>(args)...);
}
template <typename Functor, typename T1, typename T2, typename T3>
VTKM_CONT void ListForEachImpl(Functor&& f, brigand::list<T1, T2, T3>)
template <typename Functor, typename T1, typename T2, typename T3, typename... Args>
VTKM_CONT void ListForEachImpl(Functor&& f, brigand::list<T1, T2, T3>, Args&&... args)
{
f(T1{});
f(T2{});
f(T3{});
f(T1{}, std::forward<Args>(args)...);
f(T2{}, std::forward<Args>(args)...);
f(T3{}, std::forward<Args>(args)...);
}
template <typename Functor,
@ -196,16 +196,49 @@ template <typename Functor,
typename T2,
typename T3,
typename T4,
typename... ArgTypes>
VTKM_CONT void ListForEachImpl(Functor&& f, brigand::list<T1, T2, T3, T4, ArgTypes...>)
typename... ArgTypes,
typename... Args>
VTKM_CONT void ListForEachImpl(Functor&& f,
brigand::list<T1, T2, T3, T4, ArgTypes...>&&,
Args&&... args)
{
f(T1{});
f(T2{});
f(T3{});
f(T4{});
ListForEachImpl(f, brigand::list<ArgTypes...>());
f(T1{}, std::forward<Args>(args)...);
f(T2{}, std::forward<Args>(args)...);
f(T3{}, std::forward<Args>(args)...);
f(T4{}, std::forward<Args>(args)...);
ListForEachImpl(
std::forward<Functor>(f), brigand::list<ArgTypes...>{}, std::forward<Args>(args)...);
}
template <typename T, typename U, typename R>
struct ListCrossProductAppend
{
using type = brigand::push_back<T, std::pair<U, R>>;
};
template <typename T, typename U, typename R2>
struct ListCrossProductImplUnrollR2
{
using P =
brigand::fold<R2,
brigand::list<>,
ListCrossProductAppend<brigand::_state, brigand::_element, brigand::pin<U>>>;
using type = brigand::append<T, P>;
};
template <typename R1, typename R2>
struct ListCrossProductImpl
{
using type = brigand::fold<
R2,
brigand::list<>,
ListCrossProductImplUnrollR2<brigand::_state, brigand::_element, brigand::pin<R1>>>;
};
} // namespace detail
//-----------------------------------------------------------------------------

@ -127,7 +127,7 @@ public:
void Render(const vtkm::rendering::Camera& camera,
const vtkm::rendering::WorldAnnotator& worldAnnotator,
vtkm::rendering::Canvas& canvas) VTKM_OVERRIDE;
vtkm::rendering::Canvas& canvas) override;
};
}
} //namespace vtkm::rendering

@ -177,13 +177,13 @@ void AxisAnnotation3D::Render(const Camera& camera,
switch (this->Axis)
{
case 0:
tickSize[1] = this->TickMajorSize;
tickSize[1] = this->TickMinorSize;
break;
case 1:
tickSize[0] = this->TickMajorSize;
tickSize[0] = this->TickMinorSize;
break;
case 2:
tickSize[0] = this->TickMajorSize;
tickSize[0] = this->TickMinorSize;
break;
}
}
@ -192,13 +192,13 @@ void AxisAnnotation3D::Render(const Camera& camera,
switch (this->Axis)
{
case 0:
tickSize[2] = this->TickMajorSize;
tickSize[2] = this->TickMinorSize;
break;
case 1:
tickSize[2] = this->TickMajorSize;
tickSize[2] = this->TickMinorSize;
break;
case 2:
tickSize[1] = this->TickMajorSize;
tickSize[1] = this->TickMinorSize;
break;
}
}

@ -123,7 +123,7 @@ public:
virtual void Render(const vtkm::rendering::Camera& camera,
const vtkm::rendering::WorldAnnotator& worldAnnotator,
vtkm::rendering::Canvas& canvas) VTKM_OVERRIDE;
vtkm::rendering::Canvas& canvas) override;
};
}
} //namespace vtkm::rendering

@ -44,11 +44,11 @@ public:
~CanvasEGL();
virtual void Initialize() VTKM_OVERRIDE;
virtual void Initialize() override;
virtual void Activate() VTKM_OVERRIDE;
virtual void Activate() override;
vtkm::rendering::Canvas* NewCopy() const VTKM_OVERRIDE;
vtkm::rendering::Canvas* NewCopy() const override;
private:
std::shared_ptr<detail::CanvasEGLInternals> Internals;

@ -38,43 +38,43 @@ public:
~CanvasGL();
void Initialize() VTKM_OVERRIDE;
void Initialize() override;
void Activate() VTKM_OVERRIDE;
void Activate() override;
void Clear() VTKM_OVERRIDE;
void Clear() override;
void Finish() VTKM_OVERRIDE;
void Finish() override;
vtkm::rendering::Canvas* NewCopy() const VTKM_OVERRIDE;
vtkm::rendering::Canvas* NewCopy() const override;
void SetViewToWorldSpace(const vtkm::rendering::Camera& camera, bool clip) VTKM_OVERRIDE;
void SetViewToWorldSpace(const vtkm::rendering::Camera& camera, bool clip) override;
void SetViewToScreenSpace(const vtkm::rendering::Camera& camera, bool clip) VTKM_OVERRIDE;
void SetViewToScreenSpace(const vtkm::rendering::Camera& camera, bool clip) override;
void SetViewportClipping(const vtkm::rendering::Camera& camera, bool clip) VTKM_OVERRIDE;
void SetViewportClipping(const vtkm::rendering::Camera& camera, bool clip) override;
void RefreshColorBuffer() const VTKM_OVERRIDE;
void RefreshColorBuffer() const override;
virtual void RefreshDepthBuffer() const VTKM_OVERRIDE;
virtual void RefreshDepthBuffer() const override;
vtkm::rendering::WorldAnnotator* CreateWorldAnnotator() const VTKM_OVERRIDE;
vtkm::rendering::WorldAnnotator* CreateWorldAnnotator() const override;
protected:
void AddLine(const vtkm::Vec<vtkm::Float64, 2>& point0,
const vtkm::Vec<vtkm::Float64, 2>& point1,
vtkm::Float32 linewidth,
const vtkm::rendering::Color& color) const VTKM_OVERRIDE;
const vtkm::rendering::Color& color) const override;
void AddColorBar(const vtkm::Bounds& bounds,
const vtkm::rendering::ColorTable& colorTable,
bool horizontal) const VTKM_OVERRIDE;
bool horizontal) const override;
void AddColorSwatch(const vtkm::Vec<vtkm::Float64, 2>& point0,
const vtkm::Vec<vtkm::Float64, 2>& point1,
const vtkm::Vec<vtkm::Float64, 2>& point2,
const vtkm::Vec<vtkm::Float64, 2>& point3,
const vtkm::rendering::Color& color) const VTKM_OVERRIDE;
const vtkm::rendering::Color& color) const override;
void AddText(const vtkm::Vec<vtkm::Float32, 2>& position,
vtkm::Float32 scale,
@ -82,7 +82,7 @@ protected:
vtkm::Float32 windowAspect,
const vtkm::Vec<vtkm::Float32, 2>& anchor,
const vtkm::rendering::Color& color,
const std::string& text) const VTKM_OVERRIDE;
const std::string& text) const override;
private:
vtkm::rendering::BitmapFont Font;

@ -45,15 +45,15 @@ public:
~CanvasOSMesa();
virtual void Initialize() VTKM_OVERRIDE;
virtual void Initialize() override;
virtual void RefreshColorBuffer() const VTKM_OVERRIDE;
virtual void RefreshColorBuffer() const override;
virtual void Activate() VTKM_OVERRIDE;
virtual void Activate() override;
virtual void Finish() VTKM_OVERRIDE;
virtual void Finish() override;
vtkm::rendering::Canvas* NewCopy() const VTKM_OVERRIDE;
vtkm::rendering::Canvas* NewCopy() const override;
private:
std::shared_ptr<detail::CanvasOSMesaInternals> Internals;

@ -37,7 +37,7 @@ public:
~CanvasRayTracer();
vtkm::rendering::Canvas* NewCopy() const VTKM_OVERRIDE;
vtkm::rendering::Canvas* NewCopy() const override;
void WriteToCanvas(const vtkm::rendering::raytracing::Ray<vtkm::Float32>& rays,
const vtkm::cont::ArrayHandle<vtkm::Float32>& colors,

@ -37,20 +37,20 @@ public:
~MapperConnectivity();
void SetSampleDistance(const vtkm::Float32&);
void SetCanvas(vtkm::rendering::Canvas* canvas) VTKM_OVERRIDE;
virtual vtkm::rendering::Canvas* GetCanvas() const VTKM_OVERRIDE;
void SetCanvas(vtkm::rendering::Canvas* canvas) override;
virtual vtkm::rendering::Canvas* GetCanvas() const override;
virtual void RenderCells(const vtkm::cont::DynamicCellSet& cellset,
const vtkm::cont::CoordinateSystem& coords,
const vtkm::cont::Field& scalarField,
const vtkm::rendering::ColorTable&, //colorTable
const vtkm::rendering::Camera& camera,
const vtkm::Range& scalarRange) VTKM_OVERRIDE;
const vtkm::Range& scalarRange) override;
virtual void StartScene() VTKM_OVERRIDE;
virtual void EndScene() VTKM_OVERRIDE;
virtual void StartScene() override;
virtual void EndScene() override;
vtkm::rendering::Mapper* NewCopy() const VTKM_OVERRIDE;
vtkm::rendering::Mapper* NewCopy() const override;
void CreateDefaultView();
protected:

@ -45,14 +45,14 @@ public:
const vtkm::cont::Field& scalarField,
const vtkm::rendering::ColorTable& colorTable,
const vtkm::rendering::Camera&,
const vtkm::Range& scalarRange) VTKM_OVERRIDE;
const vtkm::Range& scalarRange) override;
void StartScene() VTKM_OVERRIDE;
void EndScene() VTKM_OVERRIDE;
void SetCanvas(vtkm::rendering::Canvas* canvas) VTKM_OVERRIDE;
virtual vtkm::rendering::Canvas* GetCanvas() const VTKM_OVERRIDE;
void StartScene() override;
void EndScene() override;
void SetCanvas(vtkm::rendering::Canvas* canvas) override;
virtual vtkm::rendering::Canvas* GetCanvas() const override;
vtkm::rendering::Mapper* NewCopy() const VTKM_OVERRIDE;
vtkm::rendering::Mapper* NewCopy() const override;
vtkm::rendering::CanvasGL* Canvas;
GLuint shader_programme;

@ -38,20 +38,20 @@ public:
~MapperRayTracer();
void SetCanvas(vtkm::rendering::Canvas* canvas) VTKM_OVERRIDE;
virtual vtkm::rendering::Canvas* GetCanvas() const VTKM_OVERRIDE;
void SetCanvas(vtkm::rendering::Canvas* canvas) override;
virtual vtkm::rendering::Canvas* GetCanvas() const override;
void RenderCells(const vtkm::cont::DynamicCellSet& cellset,
const vtkm::cont::CoordinateSystem& coords,
const vtkm::cont::Field& scalarField,
const vtkm::rendering::ColorTable& colorTable,
const vtkm::rendering::Camera& camera,
const vtkm::Range& scalarRange) VTKM_OVERRIDE;
const vtkm::Range& scalarRange) override;
virtual void StartScene() VTKM_OVERRIDE;
virtual void EndScene() VTKM_OVERRIDE;
virtual void StartScene() override;
virtual void EndScene() override;
void SetCompositeBackground(bool on);
vtkm::rendering::Mapper* NewCopy() const VTKM_OVERRIDE;
vtkm::rendering::Mapper* NewCopy() const override;
private:
struct InternalsType;

@ -36,20 +36,20 @@ public:
~MapperVolume();
void SetCanvas(vtkm::rendering::Canvas* canvas) VTKM_OVERRIDE;
virtual vtkm::rendering::Canvas* GetCanvas() const VTKM_OVERRIDE;
void SetCanvas(vtkm::rendering::Canvas* canvas) override;
virtual vtkm::rendering::Canvas* GetCanvas() const override;
virtual void RenderCells(const vtkm::cont::DynamicCellSet& cellset,
const vtkm::cont::CoordinateSystem& coords,
const vtkm::cont::Field& scalarField,
const vtkm::rendering::ColorTable&, //colorTable
const vtkm::rendering::Camera& camera,
const vtkm::Range& scalarRange) VTKM_OVERRIDE;
const vtkm::Range& scalarRange) override;
virtual void StartScene() VTKM_OVERRIDE;
virtual void EndScene() VTKM_OVERRIDE;
virtual void StartScene() override;
virtual void EndScene() override;
vtkm::rendering::Mapper* NewCopy() const VTKM_OVERRIDE;
vtkm::rendering::Mapper* NewCopy() const override;
void SetSampleDistance(const vtkm::Float32 distance);
void SetCompositeBackground(const bool compositeBackground);

@ -42,8 +42,8 @@ public:
MapperWireframer();
virtual ~MapperWireframer();
virtual vtkm::rendering::Canvas* GetCanvas() const VTKM_OVERRIDE;
virtual void SetCanvas(vtkm::rendering::Canvas* canvas) VTKM_OVERRIDE;
virtual vtkm::rendering::Canvas* GetCanvas() const override;
virtual void SetCanvas(vtkm::rendering::Canvas* canvas) override;
bool GetShowInternalZones() const;
void SetShowInternalZones(bool showInternalZones);
@ -51,17 +51,17 @@ public:
bool GetIsOverlay() const;
void SetIsOverlay(bool isOverlay);
virtual void StartScene() VTKM_OVERRIDE;
virtual void EndScene() VTKM_OVERRIDE;
virtual void StartScene() override;
virtual void EndScene() override;
virtual void RenderCells(const vtkm::cont::DynamicCellSet& cellset,
const vtkm::cont::CoordinateSystem& coords,
const vtkm::cont::Field& scalarField,
const vtkm::rendering::ColorTable& colorTable,
const vtkm::rendering::Camera& camera,
const vtkm::Range& scalarRange) VTKM_OVERRIDE;
const vtkm::Range& scalarRange) override;
virtual vtkm::rendering::Mapper* NewCopy() const VTKM_OVERRIDE;
virtual vtkm::rendering::Mapper* NewCopy() const override;
private:
struct InternalsType;

@ -48,7 +48,7 @@ public:
void Render(const vtkm::rendering::Camera& camera,
const vtkm::rendering::WorldAnnotator& worldAnnotator,
vtkm::rendering::Canvas& canvas) const VTKM_OVERRIDE;
vtkm::rendering::Canvas& canvas) const override;
};
}
} // namespace vtkm::rendering

@ -48,7 +48,7 @@ public:
void Render(const vtkm::rendering::Camera& camera,
const vtkm::rendering::WorldAnnotator& annotator,
vtkm::rendering::Canvas& canvas) const VTKM_OVERRIDE;
vtkm::rendering::Canvas& canvas) const override;
};
}
} // namespace vtkm::rendering

@ -45,9 +45,9 @@ public:
~View1D();
void Paint() VTKM_OVERRIDE;
void RenderScreenAnnotations() VTKM_OVERRIDE;
void RenderWorldAnnotations() VTKM_OVERRIDE;
void Paint() override;
void RenderScreenAnnotations() override;
void RenderWorldAnnotations() override;
void RenderColorLegendAnnotations();
void EnableLegend();

@ -46,11 +46,11 @@ public:
~View2D();
void Paint() VTKM_OVERRIDE;
void Paint() override;
void RenderScreenAnnotations() VTKM_OVERRIDE;
void RenderScreenAnnotations() override;
void RenderWorldAnnotations() VTKM_OVERRIDE;
void RenderWorldAnnotations() override;
private:
void UpdateCameraProperties();

@ -47,11 +47,11 @@ public:
~View3D();
void Paint() VTKM_OVERRIDE;
void Paint() override;
void RenderScreenAnnotations() VTKM_OVERRIDE;
void RenderScreenAnnotations() override;
void RenderWorldAnnotations() VTKM_OVERRIDE;
void RenderWorldAnnotations() override;
private:
// 3D-specific annotations

@ -42,7 +42,7 @@ public:
const vtkm::Vec<vtkm::Float64, 3>& point1,
vtkm::Float32 lineWidth,
const vtkm::rendering::Color& color,
bool inFront) const VTKM_OVERRIDE;
bool inFront) const override;
void AddText(const vtkm::Vec<vtkm::Float32, 3>& origin,
const vtkm::Vec<vtkm::Float32, 3>& right,
@ -50,7 +50,7 @@ public:
vtkm::Float32 scale,
const vtkm::Vec<vtkm::Float32, 2>& anchor,
const vtkm::rendering::Color& color,
const std::string& text) const VTKM_OVERRIDE;
const std::string& text) const override;
private:
BitmapFont Font;

@ -59,7 +59,7 @@ struct TriangulatorFunctor
void RunTriangulator(const vtkm::cont::DynamicCellSet& cellSet,
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>>& indices,
vtkm::Id& numberOfTriangles,
const vtkm::cont::RuntimeDeviceTracker& tracker)
vtkm::cont::RuntimeDeviceTracker tracker)
{
// TODO: Should the rendering library support policies or some other way to
// configure with custom devices?

@ -43,7 +43,7 @@ void RunTriangulator(
const vtkm::cont::DynamicCellSet& cellSet,
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>>& indices,
vtkm::Id& numberOfTriangles,
const vtkm::cont::RuntimeDeviceTracker& tracker = vtkm::cont::GetGlobalRuntimeDeviceTracker());
vtkm::cont::RuntimeDeviceTracker tracker = vtkm::cont::GetGlobalRuntimeDeviceTracker());
}
}
} // namespace vtkm::rendering::internal

@ -741,6 +741,9 @@ VTKM_CONT void Camera::CreateRaysOnDevice(Ray<Precision>& rays,
vtkm::worklet::DispatcherMapField<MemSet<Precision>, Device>(MemSet<Precision>(0.f))
.Invoke(rays.MinDistance);
vtkm::worklet::DispatcherMapField<MemSet<Precision>, Device>(MemSet<Precision>(0.f))
.Invoke(rays.Distance);
//Reset the Rays Hit Index to -2
vtkm::worklet::DispatcherMapField<MemSet<vtkm::Id>, Device>(MemSet<vtkm::Id>(-2))
.Invoke(rays.HitIdx);

@ -100,10 +100,10 @@ ChannelBuffer<Precision>::ChannelBuffer()
template <typename Precision>
ChannelBuffer<Precision>::ChannelBuffer(const vtkm::Int32 numChannels, const vtkm::Id size)
{
if (size < 1)
throw vtkm::cont::ErrorBadValue("ChannelBuffer: Size must be greater that 0");
if (numChannels < 1)
throw vtkm::cont::ErrorBadValue("ChannelBuffer: NumChannels must be greater that 0");
if (size < 0)
throw vtkm::cont::ErrorBadValue("ChannelBuffer: Size must be greater that -1");
if (numChannels < 0)
throw vtkm::cont::ErrorBadValue("ChannelBuffer: NumChannels must be greater that -1");
this->NumChannels = numChannels;
this->Size = size;
@ -235,7 +235,10 @@ ChannelBuffer<Precision> ChannelBuffer<Precision>::GetChannel(const vtkm::Int32
throw vtkm::cont::ErrorBadValue("ChannelBuffer: invalid channel to extract");
ChannelBuffer<Precision> output(1, this->Size);
output.SetName(this->Name);
if (this->Size == 0)
{
return output;
}
ExtractChannelFunctor<Precision> functor(this, output.Buffer, channel);
vtkm::cont::TryExecute(functor);
@ -373,7 +376,6 @@ public:
{
InvDeltaScalar = 1.f / (maxScalar - minScalar);
}
//std::cout<<"Min scalar "<<minScalar<<" max "<<maxScalar<<std::endl;
}
typedef void ControlSignature(FieldInOut<>);
typedef void ExecutionSignature(_1);

@ -62,8 +62,6 @@ namespace rendering
{
namespace raytracing
{
//
// Advance Ray
// After a ray leaves the mesh, we need to check to see
@ -458,6 +456,40 @@ public:
} //operator
}; //class RayBumper
template <typename FloatType>
class AddPathLengths : public vtkm::worklet::WorkletMapField
{
public:
VTKM_CONT
AddPathLengths() {}
typedef void ControlSignature(FieldIn<RayStatusType>, // ray status
FieldIn<ScalarRenderingTypes>, // cell enter distance
FieldIn<ScalarRenderingTypes>, // cell exit distance
FieldInOut<ScalarRenderingTypes>); // ray absorption data
typedef void ExecutionSignature(_1, _2, _3, _4);
VTKM_EXEC inline void operator()(const vtkm::UInt8& rayStatus,
const FloatType& enterDistance,
const FloatType& exitDistance,
FloatType& distance) const
{
if (rayStatus != RAY_ACTIVE)
{
return;
}
if (exitDistance <= enterDistance)
{
return;
}
FloatType segmentLength = exitDistance - enterDistance;
distance += segmentLength;
}
};
template <typename FloatType>
class Integrate : public vtkm::worklet::WorkletMapField
{
@ -1138,6 +1170,17 @@ public:
this->IntersectTime += timer.GetElapsedTime();
}
template <typename FloatType, typename Device>
void AccumulatePathLengths(Ray<FloatType>& rays, detail::RayTracking<FloatType>& tracker, Device)
{
vtkm::worklet::DispatcherMapField<AddPathLengths<FloatType>, Device>(
AddPathLengths<FloatType>())
.Invoke(rays.Status,
*(tracker.EnterDist),
*(tracker.ExitDist),
rays.GetBuffer("path_lengths").Buffer);
}
template <typename FloatType, typename Device>
void FindLostRays(Ray<FloatType>& rays, detail::RayTracking<FloatType>& tracker, Device)
{
@ -1210,7 +1253,6 @@ public:
bool divideEmisByAbsorp = false;
vtkm::cont::ArrayHandle<FloatType> absorp = rays.Buffers.at(0).Buffer;
vtkm::cont::ArrayHandle<FloatType> emission = rays.GetBuffer("emission").Buffer;
vtkm::worklet::DispatcherMapField<IntegrateEmission<FloatType>, Device>(
IntegrateEmission<FloatType>(rays.Buffers.at(0).GetNumChannels(), divideEmisByAbsorp))
.Invoke(rays.Status,
@ -1242,13 +1284,27 @@ public:
template <typename FloatType>
void PrintDebugRay(Ray<FloatType>& rays, vtkm::Id rayId)
{
if (rayId < 0 || rayId > rays.Distance.GetPortalControl().GetNumberOfValues())
vtkm::Id index = -1;
for (vtkm::Id i = 0; i < rays.NumRays; ++i)
{
if (rays.PixelIdx.GetPortalControl().Get(i) == rayId)
{
index = i;
break;
}
}
if (index == -1)
{
return;
std::cout << "++++++++DEBUG RAY++++++++\n";
std::cout << "Status: " << (int)rays.Status.GetPortalControl().Get(rayId) << "\n";
std::cout << "HitIndex: " << rays.HitIdx.GetPortalControl().Get(rayId) << "\n";
std::cout << "Dist " << rays.Distance.GetPortalControl().Get(rayId) << "\n";
std::cout << "MinDist " << rays.MinDistance.GetPortalControl().Get(rayId) << "\n";
}
std::cout << "++++++++RAY " << rayId << "++++++++\n";
std::cout << "Status: " << (int)rays.Status.GetPortalControl().Get(index) << "\n";
std::cout << "HitIndex: " << rays.HitIdx.GetPortalControl().Get(index) << "\n";
std::cout << "Dist " << rays.Distance.GetPortalControl().Get(index) << "\n";
std::cout << "MinDist " << rays.MinDistance.GetPortalControl().Get(index) << "\n";
std::cout << "Origin " << rays.Origin.GetPortalConstControl().Get(index) << "\n";
std::cout << "Dir " << rays.Dir.GetPortalConstControl().Get(index) << "\n";
std::cout << "+++++++++++++++++++++++++\n";
}
@ -1256,7 +1312,7 @@ public:
void OffsetMinDistances(Ray<FloatType>& rays, Device)
{
vtkm::worklet::DispatcherMapField<AdvanceRay<FloatType>, Device>(
AdvanceRay<FloatType>(FloatType(0.0000001)))
AdvanceRay<FloatType>(FloatType(0.001)))
.Invoke(rays.Status, rays.MinDistance);
}
@ -1303,6 +1359,7 @@ public:
this->SetBoundingBox(Device());
bool hasPathLengths = rays.HasBuffer("path_lengths");
vtkm::cont::Timer<Device> timer;
this->Init(Device());
@ -1319,9 +1376,8 @@ public:
MeshConn.Construct(Device());
logger->AddLogData("active_pixels", rays.NumRays);
bool cullMissedRays = false;
bool cullMissedRays = true;
bool workRemaining = true;
if (this->CountRayStatus)
{
@ -1377,6 +1433,10 @@ public:
else
this->IntegrateCells(rays, rayTracker, Device());
if (hasPathLengths)
{
this->AccumulatePathLengths(rays, rayTracker, Device());
}
//swap enter and exit distances
rayTracker.Swap();
if (this->CountRayStatus)
@ -1405,6 +1465,7 @@ public:
}
vtkm::Float64 renderTime = renderTimer.GetElapsedTime();
this->LogTimers();
logger->AddLogData("active_pixels", rays.NumRays);
logger->CloseLogEntry(renderTime);
} //Render

@ -237,9 +237,9 @@ public:
count++;
}
//TODO: we could make this a recipical, but this is not a bottleneck.
center[0] = center[0] / vtkm::Float32(count + 1);
center[1] = center[1] / vtkm::Float32(count + 1);
center[2] = center[2] / vtkm::Float32(count + 1);
center[0] = center[0] / vtkm::Float32(count);
center[1] = center[1] / vtkm::Float32(count);
center[2] = center[2] / vtkm::Float32(count);
Normalize(center);
code = Morton3D(center[0], center[1], center[2]);
BOUNDS_CHECK(mortonCodes, offset + i);

@ -181,9 +181,28 @@ public:
VTKM_CONT Ray(const vtkm::Int32 size, Device, bool enableIntersectionData = false)
{
NumRays = size;
IntersectionDataEnabled = enableIntersectionData;
ChannelBuffer<Precision> buffer;
this->Buffers.push_back(buffer);
DebugWidth = -1;
DebugHeight = -1;
this->Resize(size, Device());
}
VTKM_CONT void Resize(const vtkm::Int32 size)
{
this->Resize(size, vtkm::cont::DeviceAdapterTagSerial());
}
template <typename Device>
VTKM_CONT void Resize(const vtkm::Int32 size, Device)
{
NumRays = size;
if (IntersectionDataEnabled)
{
IntersectionX.PrepareForOutput(NumRays, Device());
@ -235,12 +254,11 @@ public:
DirX, inComp[0], DirY, inComp[1], DirZ, inComp[2]);
ChannelBuffer<Precision> buffer;
buffer.Resize(NumRays, Device());
this->Buffers.push_back(buffer);
DebugWidth = -1;
DebugHeight = -1;
const size_t numBuffers = this->Buffers.size();
for (size_t i = 0; i < numBuffers; ++i)
{
this->Buffers[i].Resize(NumRays, Device());
}
}
VTKM_CONT
@ -255,9 +273,9 @@ public:
VTKM_CONT
bool HasBuffer(const std::string name)
{
vtkm::Id numBuffers = static_cast<vtkm::Id>(this->Buffers.size());
size_t numBuffers = this->Buffers.size();
bool found = false;
for (vtkm::Id i = 0; i < numBuffers; ++i)
for (size_t i = 0; i < numBuffers; ++i)
{
if (this->Buffers[i].GetName() == name)
{

@ -33,10 +33,6 @@ namespace
template <int N>
struct TestClass
{
enum
{
NUMBER = N
};
};
struct TestListTag1 : vtkm::ListTagBase<TestClass<11>>
@ -63,36 +59,50 @@ struct TestListTagIntersect : vtkm::ListTagIntersect<TestListTag3, TestListTagJo
{
};
struct TestListTagCrossProduct : vtkm::ListCrossProduct<TestListTag3, TestListTag1>
{
};
struct TestListTagUniversal : vtkm::ListTagUniversal
{
};
template <int N, int M>
std::pair<int, int> test_number(std::pair<TestClass<N>, TestClass<M>>)
{
return std::make_pair(N, M);
}
template <int N>
int test_number(TestClass<N>)
{
return N;
}
template <typename T>
struct MutableFunctor
{
std::vector<int> FoundTypes;
std::vector<T> FoundTypes;
template <typename T>
VTKM_CONT void operator()(T)
template <typename U>
VTKM_CONT void operator()(U u)
{
this->FoundTypes.push_back(T::NUMBER);
this->FoundTypes.push_back(test_number(u));
}
};
std::vector<int> g_FoundType;
template <typename T>
struct ConstantFunctor
{
ConstantFunctor() { g_FoundType.erase(g_FoundType.begin(), g_FoundType.end()); }
template <typename T>
VTKM_CONT void operator()(T) const
template <typename U, typename VectorType>
VTKM_CONT void operator()(U u, VectorType& vector) const
{
g_FoundType.push_back(T::NUMBER);
vector.push_back(test_number(u));
}
};
template <vtkm::IdComponent N>
void CheckSame(const vtkm::Vec<int, N>& expected, const std::vector<int>& found)
template <typename T, vtkm::IdComponent N>
void CheckSame(const vtkm::Vec<T, N>& expected, const std::vector<T>& found)
{
VTKM_TEST_ASSERT(static_cast<int>(found.size()) == N, "Got wrong number of items.");
@ -137,13 +147,15 @@ void TryList(const vtkm::Vec<int, N>& expected, ListTag)
VTKM_IS_LIST_TAG(ListTag);
std::cout << " Try mutable for each" << std::endl;
MutableFunctor functor;
MutableFunctor<int> functor;
vtkm::ListForEach(functor, ListTag());
CheckSame(expected, functor.FoundTypes);
std::cout << " Try constant for each" << std::endl;
vtkm::ListForEach(ConstantFunctor(), ListTag());
CheckSame(expected, g_FoundType);
std::vector<int> foundTypes;
ConstantFunctor<int> cfunc;
vtkm::ListForEach(cfunc, ListTag(), foundTypes);
CheckSame(expected, foundTypes);
std::cout << " Try checking contents" << std::endl;
CheckContains(TestClass<11>(), ListTag(), functor.FoundTypes);
@ -157,6 +169,22 @@ void TryList(const vtkm::Vec<int, N>& expected, ListTag)
CheckContains(TestClass<43>(), ListTag(), functor.FoundTypes);
CheckContains(TestClass<44>(), ListTag(), functor.FoundTypes);
}
template <vtkm::IdComponent N, typename ListTag>
void TryList(const vtkm::Vec<std::pair<int, int>, N>& expected, ListTag)
{
VTKM_IS_LIST_TAG(ListTag);
std::cout << " Try mutable for each" << std::endl;
MutableFunctor<std::pair<int, int>> functor;
vtkm::ListForEach(functor, ListTag());
CheckSame(expected, functor.FoundTypes);
std::cout << " Try constant for each" << std::endl;
std::vector<std::pair<int, int>> foundTypes;
ConstantFunctor<std::pair<int, int>> cfunc;
vtkm::ListForEach(cfunc, ListTag(), foundTypes);
CheckSame(expected, foundTypes);
}
template <vtkm::IdComponent N>
void TryList(const vtkm::Vec<int, N>&, TestListTagUniversal tag)
@ -207,6 +235,12 @@ void TestLists()
std::cout << "ListTagIntersect" << std::endl;
TryList(vtkm::Vec<int, 3>(31, 32, 33), TestListTagIntersect());
std::cout << "ListTagCrossProduct" << std::endl;
TryList(vtkm::Vec<std::pair<int, int>, 3>({ 31, 11 }, { 32, 11 }, { 33, 11 }),
TestListTagCrossProduct());
std::cout << "ListTagUniversal" << std::endl;
TryList(vtkm::Vec<int, 4>(1, 2, 3, 4), TestListTagUniversal());
}

@ -30,7 +30,7 @@
#include <vtkm/cont/DeviceAdapterAlgorithm.h>
#include <vtkm/cont/DynamicArrayHandle.h>
#include <vtkm/cont/DynamicCellSet.h>
#include <vtkm/cont/ImplicitFunction.h>
#include <vtkm/cont/ImplicitFunctionHandle.h>
#include <vtkm/cont/Timer.h>
#include <vtkm/exec/ExecutionWholeArray.h>
@ -522,7 +522,7 @@ public:
VTKM_CONT
ClipWithImplicitFunction(Clip* clipper,
const DynamicCellSet& cellSet,
const vtkm::exec::ImplicitFunction& function,
const vtkm::ImplicitFunction* function,
vtkm::cont::CellSetExplicit<>* result)
: Clipper(clipper)
, CellSet(&cellSet)
@ -536,8 +536,8 @@ public:
{
// Evaluate the implicit function on the input coordinates using
// ArrayHandleTransform
vtkm::cont::ArrayHandleTransform<ArrayHandleType, vtkm::exec::ImplicitFunctionValue>
clipScalars(handle, this->Function);
vtkm::cont::ArrayHandleTransform<ArrayHandleType, vtkm::ImplicitFunctionValue> clipScalars(
handle, this->Function);
// Clip at locations where the implicit function evaluates to 0
*this->Result = this->Clipper->Run(*this->CellSet, clipScalars, 0.0, DeviceAdapter());
@ -546,13 +546,13 @@ public:
private:
Clip* Clipper;
const DynamicCellSet* CellSet;
const vtkm::exec::ImplicitFunctionValue Function;
vtkm::ImplicitFunctionValue Function;
vtkm::cont::CellSetExplicit<>* Result;
};
template <typename CellSetList, typename DeviceAdapter>
vtkm::cont::CellSetExplicit<> Run(const vtkm::cont::DynamicCellSetBase<CellSetList>& cellSet,
const vtkm::cont::ImplicitFunction& clipFunction,
const vtkm::cont::ImplicitFunctionHandle& clipFunction,
const vtkm::cont::CoordinateSystem& coords,
DeviceAdapter device)
{

@ -27,7 +27,7 @@
#include <vtkm/cont/CellSetPermutation.h>
#include <vtkm/cont/CoordinateSystem.h>
#include <vtkm/cont/DataSet.h>
#include <vtkm/cont/ImplicitFunction.h>
#include <vtkm/cont/ImplicitFunctionHandle.h>
namespace vtkm
{
@ -58,7 +58,7 @@ public:
}
VTKM_CONT
ExtractCellsByVOI(const vtkm::exec::ImplicitFunction& function,
ExtractCellsByVOI(const vtkm::ImplicitFunction* function,
bool extractInside,
bool extractBoundaryCells,
bool extractOnlyBoundaryCells)
@ -77,11 +77,12 @@ public:
// Count points inside/outside volume of interest
vtkm::IdComponent inCnt = 0;
vtkm::IdComponent outCnt = 0;
for (vtkm::IdComponent indx = 0; indx < numIndices; indx++)
vtkm::Id indx;
for (indx = 0; indx < numIndices; indx++)
{
vtkm::Id ptId = connectivityIn[indx];
vtkm::Id ptId = connectivityIn[static_cast<vtkm::IdComponent>(indx)];
vtkm::Vec<FloatDefault, 3> coordinate = coordinates.Get(ptId);
vtkm::FloatDefault value = this->Function.Value(coordinate);
vtkm::FloatDefault value = this->Function->Value(coordinate);
if (value <= 0)
inCnt++;
if (value >= 0)
@ -106,7 +107,7 @@ public:
}
private:
vtkm::exec::ImplicitFunction Function;
const vtkm::ImplicitFunction* Function;
bool ExtractInside;
bool ExtractBoundaryCells;
bool ExtractOnlyBoundaryCells;
@ -155,7 +156,7 @@ public:
vtkm::cont::CellSetPermutation<CellSetType> Run(
const CellSetType& cellSet,
const vtkm::cont::CoordinateSystem& coordinates,
const vtkm::cont::ImplicitFunction& implicitFunction,
const vtkm::cont::ImplicitFunctionHandle& implicitFunction,
bool extractInside,
bool extractBoundaryCells,
bool extractOnlyBoundaryCells,

@ -26,7 +26,7 @@
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/CoordinateSystem.h>
#include <vtkm/cont/DataSet.h>
#include <vtkm/cont/ImplicitFunction.h>
#include <vtkm/cont/ImplicitFunctionHandle.h>
namespace vtkm
{
@ -51,7 +51,7 @@ public:
typedef _3 ExecutionSignature(_2);
VTKM_CONT
ExtractPointsByVOI(const vtkm::exec::ImplicitFunction& function, bool extractInside)
ExtractPointsByVOI(const vtkm::ImplicitFunction* function, bool extractInside)
: Function(function)
, passValue(extractInside)
, failValue(!extractInside)
@ -62,14 +62,14 @@ public:
bool operator()(const vtkm::Vec<vtkm::Float64, 3>& coordinate) const
{
bool pass = passValue;
vtkm::Float64 value = this->Function.Value(coordinate);
vtkm::Float64 value = this->Function->Value(coordinate);
if (value > 0)
pass = failValue;
return pass;
}
private:
vtkm::exec::ImplicitFunction Function;
const vtkm::ImplicitFunction* Function;
bool passValue;
bool failValue;
};
@ -97,7 +97,7 @@ public:
template <typename CellSetType, typename CoordinateType, typename DeviceAdapter>
vtkm::cont::CellSetSingleType<> Run(const CellSetType& cellSet,
const CoordinateType& coordinates,
const vtkm::cont::ImplicitFunction& implicitFunction,
const vtkm::cont::ImplicitFunctionHandle& implicitFunction,
bool extractInside,
DeviceAdapter device)
{

@ -686,11 +686,11 @@ struct GenerateNormalsDeduced
//
NormalsWorkletPass1 pass1(*edges);
vtkm::worklet::DispatcherMapTopology<NormalsWorkletPass1>(pass1).Invoke(
*cellset, *cellset, coordinates, *field, *normals);
*cellset, *cellset, coordinates, marchingcubes::make_ScalarField(*field), *normals);
NormalsWorkletPass2 pass2(*edges);
vtkm::worklet::DispatcherMapTopology<NormalsWorkletPass2>(pass2).Invoke(
*cellset, *cellset, coordinates, *field, *weights, *normals);
*cellset, *cellset, coordinates, marchingcubes::make_ScalarField(*field), *weights, *normals);
}
};

@ -78,28 +78,20 @@ struct SelectRepresentativePoint : public vtkm::worklet::WorkletReduceByKey
return pointsIn[pointsIn.GetNumberOfComponents() / 2];
}
template <typename KeyType, typename DeviceAdapterTag>
struct RunTrampoline
{
const vtkm::worklet::Keys<KeyType>& Keys;
vtkm::cont::DynamicArrayHandle& OutputPoints;
VTKM_CONT
RunTrampoline(const vtkm::worklet::Keys<KeyType>& keys, vtkm::cont::DynamicArrayHandle& output)
: Keys(keys)
, OutputPoints(output)
template <typename InputPointsArrayType, typename KeyType, typename DeviceAdapterTag>
VTKM_CONT void operator()(const InputPointsArrayType& points,
const vtkm::worklet::Keys<KeyType>& keys,
vtkm::cont::DynamicArrayHandle& output,
DeviceAdapterTag) const
{
}
template <typename InputPointsArrayType>
VTKM_CONT void operator()(const InputPointsArrayType& points) const
{
vtkm::cont::ArrayHandle<typename InputPointsArrayType::ValueType> out;
vtkm::worklet::DispatcherReduceByKey<SelectRepresentativePoint, DeviceAdapterTag> dispatcher;
dispatcher.Invoke(this->Keys, points, out);
dispatcher.Invoke(keys, points, out);
this->OutputPoints = out;
output = out;
}
};
@ -107,11 +99,11 @@ struct SelectRepresentativePoint : public vtkm::worklet::WorkletReduceByKey
VTKM_CONT static vtkm::cont::DynamicArrayHandle Run(
const vtkm::worklet::Keys<KeyType>& keys,
const InputDynamicPointsArrayType& inputPoints,
DeviceAdapterTag)
DeviceAdapterTag tag)
{
vtkm::cont::DynamicArrayHandle output;
RunTrampoline<KeyType, DeviceAdapterTag> trampoline(keys, output);
vtkm::cont::CastAndCall(inputPoints, trampoline);
RunTrampoline trampoline;
vtkm::cont::CastAndCall(inputPoints, trampoline, keys, output, tag);
return output;
}
};

Some files were not shown because too many files have changed in this diff Show More