The `VecTraits` class allows templated functions, methods, and classes to
treat type arguments uniformly as `Vec` types or to otherwise differentiate
between scalar and vector types. This only works for types that `VecTraits`
is defined for.
The `VecTraits` templated class now has a default implementation that will
be used for any type that does not have a `VecTraits` specialization. This
removes many surprise compiler errors when using a template that, unknown
to you, has `VecTraits` in its implementation.
One potential issue is that if `VecTraits` gets defined for a new type, the
behavior of `VecTraits` could change for that type in backward-incompatible
ways. If `VecTraits` is used in a purely generic way, this should not be an
issue. However, if assumptions were made about the components and length,
this could cause problems.
Fixes#589
There are some common uses of `ArrayCopy` that don't use basic arrays.
Rather than move away from `ArrayCopy` for these use cases, compile a
special fast path for these cases.
This required some restructuring of the code to get the template
resolution to work correctly.
Rather than require `ArrayCopy` to create special versions of copy for
all arrays, use a precompiled versions. This should speed up compiles,
reduce the amount of code being generated, and require the device
compiler on fewer source files.
There are some cases where you still need to copy arrays that are not
well supported by the precompiled versions in `ArrayCopy`. (It will
always work, but the fallback is very slow.) In this case, you will want
to switch over to `ArrayCopyDevice`, which has the old behavior.
Added the following form of `ArrayCopy`:
```cpp
VTKM_CONT_EXPORT void ArrayCopy(
const vtkm::cont::UnknownArrayHandle& source,
const vtkm::cont::UnknownArrayHandle& destination);
```
Note that the destination array is a constant reference. This is
actually OK because you can change the contents of an
`UnknownArrayHandle` (as long as you don't change the array being
referenced). The main motivation for this change is to allow you to call
this form of `ArrayCopy` while passing in a `ArrayHandle` as the second
argument. C++ will automatically make the conversion, but the function
has to accept a const reference for it to be passed correctly.
Note that there is still a form of `ArrayCopy` that accepts a non-const
reference to the destination array. The two arrays behave the same
except for one difference. For the non-const version, if the
`UnknownArrayHandle` does not already point to an array (i.e. is not
valid), a new array will be created and placed in the destination
object. However, because this cannot be done for a const reference, an
exception is thrown instead.
This method is a remenant of when `ArrayHandle` could only store data on
one device at a time. It is now capable of storing data on any number of
devices (as well as the host), so asking for "the" device no longer
makes sense. Thus, this method is deprecated in favor of
`ArrayHandle::IsOnDevice`.
This deprecation leads to fixing some older functionality that still
assumed data could only be on one device at a time.
Fixes#592.
Often times you have an array of an unknown type (likely from a data set),
and you need it to be of a particular type (or can make a reasonable but
uncertain assumption about it being a particular type). You really just
want a shallow copy (a reference in a concrete `ArrayHandle`) if that is
possible.
`ArrayCopyShallowIfPossible` pulls an array of a specific type from an
`UnknownArrayHandle`. If the type is compatible, it will perform a shallow
copy. If it is not possible, a deep copy is performed to get it to the
correct type.
Fixes#572.
Add an overload of `ArrayCopy` that takes `UnknownArrayHandle`s and
copies them for (almost) any `ArrayHandle` type.
The code uses `CastAndCallWithExtractedArray` to reduce the total number
of copy conditions to about 100, which are all precompiled into the
library. On a debug build on my mac, this creates a .o file of 21MB.
That's not great, but not terrible. Hopefully, this can be used to
consolidate copy implementations elsewhere.
The circular dependency came from UnknownArrayHandle.h needing
VTKmDefaultTypes.h, which needed all the cell set types. Some of those
cell sets used ArrayCopy in templated functions. Changed those functions
to directly deep copy the ArrayHandle.
The `VariantArrayHandle` will soon be deprecated for its replacement of
`UnknownArrayHandle`. Thus, `Field` and related classes should start
using the new `UnknownArrayHandle`.
What was previously declared as `ArrayHandleNewStyle` is now just the
implementation of `ArrayHandle`. The old implementation of `ArrayHandle`
has been moved to `ArrayHandleDeprecated`, and `ArrayHandle`s still
using this implementation must declare `VTKM_ARRAY_HANDLE_DEPRECATED` to
use it.
The new method `ArrayHandle::DeepCopy` had the pattern such that the
data in the `this` array was pushed to the provided destination array.
However, this is the opposite pattern used in the equivalent method in
VTK, which takes the data from the provided array and copies it to
`this` array.
So, swap the pattern to match that of VTK. Also, make the method name
more descriptive by renaming it to `DeepCopyFrom`. Hopefully, users will
read that to mean given the `ArrayHandle`, you copy data from the other
provided `ArrayHandle`.
A recent modification to `ArrayCopy` created a fast path for when
copying arrays of the same type. This fast path just deep copies the
buffers. The issue was that the buffer copy was creating new buffers
instead of updating the existing buffers. The passed in `ArrayHandle`
would get updated to the new buffers, but any other `ArrayHandle`s
sharing those buffers would still have the old versions. That would lead
to unexpected errors in code like this.
```cpp
vtkm::cont::ArrayHandle<T> outArray1;
vtkm::cont::ArrayHandle<T> outArray2 = outArray1;
vtkm::cont::ArrayCopy(inArray, outArray2);
```
If `inArray` was a different type than `outArray2`, then the data for
both `outArray1` and `outArray2` would be updated (which is the expected
behavior for something considered a "pointer"). However, if `inArray`
was the same type as `outArray2`, then the fast path would change
`outArray2` but leave `outArray1` the same.
This behavior has been corrected so that, in this case, the data of
`outArray1` always follows that of `outArray2`.
C++ was not resolving the overloads of `ArrayCopyImpl` as expected,
which was causing `ArrayCopy` to sometimes use a less efficient method
for copying.
Also fix an issue with `Buffer::DeepCopy` that caused a deadlock when
copying a buffer that was not actually allocated anywhere (as well as
failing to copy the metadata, which was probably the whole point).
`ArrayHandle::DeepCopy` creates a new `ArrayHandle` of the same type and
deep copies the data into it.
This functionality is similar to `ArrayCopy`. However, it can be used
without having to compile for the device on which the copy happens.
Now that the data in an `ArrayHandle` is stored in `Buffer` objects, we
now have a more efficient way of doing deep copies of memory. Rather
than call `Algorithm::Copy`, which iterates over the array and copies
each item, `ArrayCopy` now uses the `Buffer` interface to do direct
device-to-device (or host-to-host) mem copies. This should be more
efficent and take less time to compile.
Note that this direct `Buffer` copy only works if the two `ArrayHandle`s
are of the same type. If they are different, `ArrayCopy` still has to
fall back to using `Algorithm::Copy`.
Also note that not all `ArrayHandle`s are using the new `ArrayHandle`
interface (and therefore not using `Buffer` objects). Thus, a fallback
is still available for old `ArrayHandle` types.
`CoordinateSystem` differed from `Field` in that its `GetData`
method returned an `ArrayHandleVirtualCoordinates` instead of
a `VariantArrayHandle`. This is probably confusing since
`CoordianteSystem` inherits `Field` and has a pretty dramatic
difference in this behavior.
In preparation to deprecate `ArrayHandleVirtualCoordinates`, this
changes `CoordiantSystem` to be much more like `Field`. (In the
future, we may change the `CoordinateSystem` to point to a `Field`
rather than be a special `Field`.)
A method named `GetDataAsMultiplexer` has been added to
`CoordinateSystem`. This method allows you to get data from
`CoordinateSystem` as a single array type without worrying
about creating functors to handle different types and without
needing virtual methods.
This is still more convenient than declaring DeviceAdapterAlgorithm just
to copy two arrays. Now the function works whether or not you know what
the device should be.
This is a convenience method to do a deep copy of an array. This comes
up a lot, but can be a pain if you don't have a specific device adapter
on which to do the copy.