Commit fdb7abe7 authored by Kenneth Moreland's avatar Kenneth Moreland Committed by Kitware Robot
Browse files

Merge topic 'all-execobj-trivially-copyable'

294a30fd Check that all execution objects are trivially copyable
bd5b84fa Have VTKM_IS_TRIVIAL* macros show types better
3813fb51

 Make ArrayPortalRecombineVec trivially copyable
Acked-by: Kitware Robot's avatarKitware Robot <kwrobot@kitware.com>
Acked-by: Li-Ta Lo's avatarLi-Ta Lo <ollie@lanl.gov>
Merge-request: !2416
parents 33f6f0be 294a30fd
...@@ -294,24 +294,29 @@ namespace internal ...@@ -294,24 +294,29 @@ namespace internal
template <typename SourcePortalType> template <typename SourcePortalType>
class ArrayPortalRecombineVec class ArrayPortalRecombineVec
{ {
vtkm::VecCConst<SourcePortalType> Portals; // Note that this ArrayPortal has a pointer to a C array of other portals. We need to
// make sure that the pointer is valid on the device we are using it on. See the
// CreateReadPortal and CreateWritePortal in the Storage below to see how that is
// managed.
const SourcePortalType* Portals;
vtkm::IdComponent NumberOfComponents;
public: public:
using ValueType = vtkm::internal::RecombineVec<SourcePortalType>; using ValueType = vtkm::internal::RecombineVec<SourcePortalType>;
ArrayPortalRecombineVec() = default; ArrayPortalRecombineVec() = default;
ArrayPortalRecombineVec(const vtkm::VecCConst<SourcePortalType>& portals)
: Portals(portals)
{
}
ArrayPortalRecombineVec(const SourcePortalType* portals, vtkm::IdComponent numComponents) ArrayPortalRecombineVec(const SourcePortalType* portals, vtkm::IdComponent numComponents)
: Portals(portals, numComponents) : Portals(portals)
, NumberOfComponents(numComponents)
{ {
} }
VTKM_EXEC_CONT vtkm::Id GetNumberOfValues() const { return this->Portals[0].GetNumberOfValues(); } VTKM_EXEC_CONT vtkm::Id GetNumberOfValues() const { return this->Portals[0].GetNumberOfValues(); }
VTKM_EXEC_CONT ValueType Get(vtkm::Id index) const { return ValueType(this->Portals, index); } VTKM_EXEC_CONT ValueType Get(vtkm::Id index) const
{
return ValueType({ this->Portals, this->NumberOfComponents }, index);
}
VTKM_EXEC_CONT void Set(vtkm::Id index, const ValueType& value) const VTKM_EXEC_CONT void Set(vtkm::Id index, const ValueType& value) const
{ {
...@@ -324,8 +329,8 @@ public: ...@@ -324,8 +329,8 @@ public:
VTKM_EXEC_CONT void Set(vtkm::Id index, const T& value) const VTKM_EXEC_CONT void Set(vtkm::Id index, const T& value) const
{ {
using Traits = vtkm::VecTraits<T>; using Traits = vtkm::VecTraits<T>;
VTKM_ASSERT(Traits::GetNumberOfComponents(value) == this->Portals.GetNumberOfComponents()); VTKM_ASSERT(Traits::GetNumberOfComponents(value) == this->NumberOfComponents);
for (vtkm::IdComponent cIndex = 0; cIndex < this->Portals.GetNumberOfComponents(); ++cIndex) for (vtkm::IdComponent cIndex = 0; cIndex < this->NumberOfComponents; ++cIndex)
{ {
this->Portals[cIndex].Set(index, Traits::GetComponent(value, cIndex)); this->Portals[cIndex].Set(index, Traits::GetComponent(value, cIndex));
} }
...@@ -441,7 +446,6 @@ public: ...@@ -441,7 +446,6 @@ public:
vtkm::cont::DeviceAdapterId device, vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token) vtkm::cont::Token& token)
{ {
ReadPortalType portal;
vtkm::IdComponent numComponents = NumberOfComponents(buffers); vtkm::IdComponent numComponents = NumberOfComponents(buffers);
// The array portal needs a runtime-allocated array of portals for each component. // The array portal needs a runtime-allocated array of portals for each component.
...@@ -479,7 +483,6 @@ public: ...@@ -479,7 +483,6 @@ public:
vtkm::cont::DeviceAdapterId device, vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token) vtkm::cont::Token& token)
{ {
WritePortalType portal;
vtkm::IdComponent numComponents = NumberOfComponents(buffers); vtkm::IdComponent numComponents = NumberOfComponents(buffers);
// The array portal needs a runtime-allocated array of portals for each component. // The array portal needs a runtime-allocated array of portals for each component.
......
...@@ -32,6 +32,8 @@ ...@@ -32,6 +32,8 @@
#include <vtkm/worklet/internal/WorkletBase.h> #include <vtkm/worklet/internal/WorkletBase.h>
#include <vtkmstd/is_trivial.h>
#include <sstream> #include <sstream>
namespace vtkm namespace vtkm
...@@ -316,6 +318,14 @@ struct DispatcherBaseTransportFunctor ...@@ -316,6 +318,14 @@ struct DispatcherBaseTransportFunctor
using T = vtkm::internal::remove_pointer_and_decay<ControlParameter>; using T = vtkm::internal::remove_pointer_and_decay<ControlParameter>;
using TransportType = typename vtkm::cont::arg::Transport<TransportTag, T, Device>; using TransportType = typename vtkm::cont::arg::Transport<TransportTag, T, Device>;
using type = typename std::decay<typename TransportType::ExecObjectType>::type; using type = typename std::decay<typename TransportType::ExecObjectType>::type;
// If you get a compile error here, it means that an execution object type is not
// trivially copyable. This is strictly disallowed. All execution objects must be
// trivially copyable so that the can be memcpy-ed between host and devices.
// Note that it is still legal for execution objects to have pointers or other
// references to resources on a particular device. It is up to the generating code
// to ensure that all referenced resources are valid on the target device.
VTKM_IS_TRIVIALLY_COPYABLE(type);
}; };
template <typename ControlParameter, vtkm::IdComponent Index> template <typename ControlParameter, vtkm::IdComponent Index>
......
...@@ -55,10 +55,10 @@ struct is_trivial : std::false_type ...@@ -55,10 +55,10 @@ struct is_trivial : std::false_type
// `VTKM_IS_TRIVIALLY_COPYABLE`, which will always pass on compilers that don't // `VTKM_IS_TRIVIALLY_COPYABLE`, which will always pass on compilers that don't
// support is_trivially_copyable, but will do the correct check on compilers that // support is_trivially_copyable, but will do the correct check on compilers that
// do support it. // do support it.
#define VTKM_IS_TRIVIALLY_COPYABLE(type) VTKM_STATIC_ASSERT(true) #define VTKM_IS_TRIVIALLY_COPYABLE(...) VTKM_STATIC_ASSERT(true)
#define VTKM_IS_TRIVIALLY_CONSTRUCTIBLE(...) VTKM_STATIC_ASSERT(true) #define VTKM_IS_TRIVIALLY_CONSTRUCTIBLE(...) VTKM_STATIC_ASSERT(true)
#define VTKM_IS_TRIVIALLY_DESTRUCTIBLE(...) VTKM_STATIC_ASSERT(true) #define VTKM_IS_TRIVIALLY_DESTRUCTIBLE(...) VTKM_STATIC_ASSERT(true)
#define VTKM_IS_TRIVIAL(type) VTKM_STATIC_ASSERT(true) #define VTKM_IS_TRIVIAL(...) VTKM_STATIC_ASSERT(true)
} // namespace vtkmstd } // namespace vtkmstd
...@@ -71,18 +71,54 @@ using std::is_trivially_constructible; ...@@ -71,18 +71,54 @@ using std::is_trivially_constructible;
using std::is_trivially_copyable; using std::is_trivially_copyable;
using std::is_trivially_destructible; using std::is_trivially_destructible;
#define VTKM_IS_TRIVIALLY_COPYABLE(type) \ namespace detail
VTKM_STATIC_ASSERT_MSG(::vtkmstd::is_trivially_copyable<type>::value, \ {
"Type must be trivially copyable to be used here.")
#define VTKM_IS_TRIVIALLY_CONSTRUCTIBLE(...) \ // Note: the reason why we redirect the trivial checks to these classes is so when the checks
VTKM_STATIC_ASSERT_MSG(::vtkmstd::is_trivially_constructible<__VA_ARGS__>::value, \ // fail it is easier to read from the error messages exactly which type was being checked. If
"Type must be trivially constructible to be used here.") // you just do a static assert in a macro, the error message is likely to give you either
#define VTKM_IS_TRIVIALLY_DESTRUCTIBLE(...) \ // macro argument names or unresolved types in the error message, which is unhelpful.
VTKM_STATIC_ASSERT_MSG(::vtkmstd::is_trivially_destructible<__VA_ARGS__>::value, \
"Type must be trivially constructible to be used here.") template <typename T>
#define VTKM_IS_TRIVIAL(type) \ struct CheckTriviallyCopyable
VTKM_STATIC_ASSERT_MSG(::vtkmstd::is_trivial<type>::value, \ {
"Type must be trivial to be used here.") VTKM_STATIC_ASSERT_MSG(vtkmstd::is_trivially_copyable<T>::value,
"Type must be trivially copyable to be used here.");
static constexpr bool value = true;
};
template <typename T>
struct CheckTriviallyConstructible
{
VTKM_STATIC_ASSERT_MSG(::vtkmstd::is_trivially_constructible<T>::value,
"Type must be trivially constructible to be used here.");
static constexpr bool value = true;
};
template <typename T>
struct CheckTriviallyDestructible
{
VTKM_STATIC_ASSERT_MSG(::vtkmstd::is_trivially_destructible<T>::value,
"Type must be trivially destructible to be used here.");
static constexpr bool value = true;
};
template <typename T>
struct CheckTrivial
{
VTKM_STATIC_ASSERT_MSG(::vtkmstd::is_trivial<T>::value, "Type must be trivial to be used here.");
static constexpr bool value = true;
};
} // namespace detail
#define VTKM_IS_TRIVIALLY_COPYABLE(...) \
VTKM_STATIC_ASSERT(::vtkmstd::detail::CheckTriviallyCopyable<__VA_ARGS__>::value)
#define VTKM_IS_TRIVIALLY_CONSTRUCTIBLE(...) \
VTKM_STATIC_ASSERT(::vtkmstd::detail::CheckTriviallyConstructible<__VA_ARGS__>::value)
#define VTKM_IS_TRIVIALLY_DESTRUCTIBLE(...) \
VTKM_STATIC_ASSERT(::vtkmstd::detail::CheckTriviallyDestructible<__VA_ARGS__>::value)
#define VTKM_IS_TRIVIAL(...) VTKM_STATIC_ASSERT(::vtkmstd::detail::CheckTrivial<__VA_ARGS__>::value)
} // namespace vtkmstd } // namespace vtkmstd
#endif #endif
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment