mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-09-16 17:22:55 +00:00
eda6dc39f2
When you use an `ArrayHandle` as an output array in a worklet (for example, as a `FieldOut`), the fetch operation does not read values from the array during the `Load`. Instead, it just constructs a new object. This makes sense as an output array is expected to have garbage in it anyway. This is a problem for some special arrays that contain `Vec`-like objects that are sized dynamically. For example, if you use an `ArrayHandleGroupVecVariable`, each entry is a dynamically sized `Vec`. The array is referenced by creating a special version of `Vec` that holds a reference to the array portal and an index. Components are retrieved and set by accessing the memory in the array portal. This allows us to have a dynamically sized `Vec` in the execution environment without having to allocate within the worklet. The problem comes when we want to use one of these arrays with `Vec`-like objects for an output. The typical fetch fails because you cannot construct one of these `Vec`-like objects without an array portal to bind it to. In these cases, we need the fetch to create the `Vec`-like object by reading it from the array. Even though the data will be garbage, you get the necessary buffer into the array (and nothing more). Previously, the problem was fixed by creating partial specializations of the `Fetch` for these `ArrayHandle`s. This worked OK as long as you were using the array directly. However, the approach failed if the `ArrayHandle` was wrapped in another `ArrayHandle` (for example, if an `ArrayHandleView` was applied to an `ArrayHandleGroupVecVariable`). To get around this problem and simplify things, the basic `Fetch` for direct output arrays is changed to handle all cases where the values in the `ArrayHandle` cannot be directly constructed. A compile-time check of the array's value type is checked with `std::is_default_constructible`. If it can be constructed, then the array is not accessed. If it cannot be constructed, then it grabs a value out of the array.
89 lines
3.0 KiB
C++
89 lines
3.0 KiB
C++
//============================================================================
|
|
// 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.
|
|
//============================================================================
|
|
#ifndef vtk_m_exec_arg_FetchTagArrayDirectOut_h
|
|
#define vtk_m_exec_arg_FetchTagArrayDirectOut_h
|
|
|
|
#include <vtkm/exec/arg/AspectTagDefault.h>
|
|
#include <vtkm/exec/arg/Fetch.h>
|
|
|
|
#include <type_traits>
|
|
|
|
namespace vtkm
|
|
{
|
|
namespace exec
|
|
{
|
|
namespace arg
|
|
{
|
|
|
|
/// \brief \c Fetch tag for setting array values with direct indexing.
|
|
///
|
|
/// \c FetchTagArrayDirectOut is a tag used with the \c Fetch class to store
|
|
/// values in an array portal. The fetch uses direct indexing, so the thread
|
|
/// index given to \c Store is used as the index into the array.
|
|
///
|
|
struct FetchTagArrayDirectOut
|
|
{
|
|
};
|
|
|
|
template <typename ExecObjectType>
|
|
struct Fetch<vtkm::exec::arg::FetchTagArrayDirectOut,
|
|
vtkm::exec::arg::AspectTagDefault,
|
|
ExecObjectType>
|
|
{
|
|
using ValueType = typename ExecObjectType::ValueType;
|
|
|
|
VTKM_SUPPRESS_EXEC_WARNINGS
|
|
template <typename ThreadIndicesType>
|
|
VTKM_EXEC ValueType Load(const ThreadIndicesType& indices,
|
|
const ExecObjectType& arrayPortal) const
|
|
{
|
|
return this->DoLoad(
|
|
indices, arrayPortal, typename std::is_default_constructible<ValueType>::type{});
|
|
}
|
|
|
|
VTKM_SUPPRESS_EXEC_WARNINGS
|
|
template <typename ThreadIndicesType, typename T>
|
|
VTKM_EXEC void Store(const ThreadIndicesType& indices,
|
|
const ExecObjectType& arrayPortal,
|
|
const T& value) const
|
|
{
|
|
arrayPortal.Set(indices.GetOutputIndex(), static_cast<ValueType>(value));
|
|
}
|
|
|
|
private:
|
|
VTKM_SUPPRESS_EXEC_WARNINGS
|
|
template <typename ThreadIndicesType>
|
|
VTKM_EXEC ValueType DoLoad(const ThreadIndicesType&, const ExecObjectType&, std::true_type) const
|
|
{
|
|
// Load is a no-op for this fetch.
|
|
return ValueType();
|
|
}
|
|
|
|
VTKM_SUPPRESS_EXEC_WARNINGS
|
|
template <typename ThreadIndicesType>
|
|
VTKM_EXEC ValueType DoLoad(const ThreadIndicesType& indices,
|
|
const ExecObjectType& arrayPortal,
|
|
std::false_type) const
|
|
{
|
|
// Cannot create a ValueType object, so pull one out of the array portal. This may seem
|
|
// weird because an output array often has garbage in it. However, this case can happen
|
|
// with special arrays with Vec-like values that reference back to the array memory.
|
|
// For example, with ArrayHandleRecombineVec, the values are actual objects that point
|
|
// back to the array for on demand reading and writing. You need the buffer established
|
|
// by the array even if there is garbage in that array.
|
|
return arrayPortal.Get(indices.GetOutputIndex());
|
|
}
|
|
};
|
|
}
|
|
}
|
|
} // namespace vtkm::exec::arg
|
|
|
|
#endif //vtk_m_exec_arg_FetchTagArrayDirectOut_h
|