Merge topic 'new-instance-variable-components'

4d02add0e Enable new instances of unknown arrays with dynamic sizes

Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !3150
This commit is contained in:
Kenneth Moreland 2023-11-08 16:19:17 +00:00 committed by Kitware Robot
commit e27573cca9
5 changed files with 107 additions and 23 deletions

@ -0,0 +1,16 @@
# Enable new instances of unknown arrays with dynamic sizes
`UnknownArrayHandle` allows you to create a new instance of a compatible
array so that when receiving an array of unknown type, a place to put the
output can be created. However, these methods only worked if the number of
components in each value could be determined statically at compile time.
However, there are some special `ArrayHandle`s that can define the number
of components at runtime. In this case, the `ArrayHandle` would throw an
exception if `NewInstanceBasic` or `NewInstanceFloatBasic` was called.
Although rare, this condition could happen when, for example, an array was
extracted from an `UnknownArrayHandle` with `ExtractArrayFromComponents` or
with `CastAndCallWithExtractedArray` and then the resulting array was
passed to a function with arrays passed with `UnknownArrayHandle` such as
`ArrayCopy`.

@ -219,7 +219,7 @@ VTKM_CONT UnknownArrayHandle UnknownArrayHandle::NewInstanceBasic() const
}
if (this->Container)
{
newArray.Container = this->Container->NewInstanceBasic();
newArray.Container = this->Container->NewInstanceBasic(this->Container->ArrayHandlePointer);
}
return newArray;
}
@ -237,7 +237,8 @@ VTKM_CONT UnknownArrayHandle UnknownArrayHandle::NewInstanceFloatBasic() const
UnknownArrayHandle newArray;
if (this->Container)
{
newArray.Container = this->Container->NewInstanceFloatBasic();
newArray.Container =
this->Container->NewInstanceFloatBasic(this->Container->ArrayHandlePointer);
}
return newArray;
}

@ -231,7 +231,7 @@ struct VTKM_CONT_EXPORT UnknownAHContainer
using NewInstanceType = void*();
NewInstanceType* NewInstance;
using NewInstanceBasicType = std::shared_ptr<UnknownAHContainer>();
using NewInstanceBasicType = std::shared_ptr<UnknownAHContainer>(void*);
NewInstanceBasicType* NewInstanceBasic;
NewInstanceBasicType* NewInstanceFloatBasic;
@ -307,39 +307,56 @@ private:
explicit UnknownAHContainer(const vtkm::cont::ArrayHandle<T, S>& array);
};
template <typename T>
std::shared_ptr<UnknownAHContainer> UnknownAHNewInstanceBasic(vtkm::VecTraitsTagSizeStatic)
template <typename T, typename S>
std::shared_ptr<UnknownAHContainer> UnknownAHNewInstanceBasic(void*, vtkm::VecTraitsTagSizeStatic)
{
return UnknownAHContainer::Make(vtkm::cont::ArrayHandleBasic<T>{});
}
template <typename T>
std::shared_ptr<UnknownAHContainer> UnknownAHNewInstanceBasic(vtkm::VecTraitsTagSizeVariable)
template <typename T, typename S>
std::shared_ptr<UnknownAHContainer> UnknownAHNewInstanceBasic(void* mem,
vtkm::VecTraitsTagSizeVariable)
{
throw vtkm::cont::ErrorBadType("Cannot create a basic array container from with ValueType of " +
vtkm::cont::TypeToString<T>());
vtkm::IdComponent numComponents = UnknownAHNumberOfComponentsFlat<T, S>(mem);
if (numComponents < 1)
{
// Array can have an inconsistent number of components. Cannot be represented by basic array.
throw vtkm::cont::ErrorBadType("Cannot create a basic array from array with ValueType of " +
vtkm::cont::TypeToString<T>());
}
using ComponentType = typename vtkm::VecTraits<T>::BaseComponentType;
return UnknownAHContainer::Make(vtkm::cont::ArrayHandleRuntimeVec<ComponentType>(numComponents));
}
template <typename T>
std::shared_ptr<UnknownAHContainer> UnknownAHNewInstanceBasic()
template <typename T, typename S>
std::shared_ptr<UnknownAHContainer> UnknownAHNewInstanceBasic(void* mem)
{
return UnknownAHNewInstanceBasic<T>(typename vtkm::VecTraits<T>::IsSizeStatic{});
return UnknownAHNewInstanceBasic<T, S>(mem, typename vtkm::VecTraits<T>::IsSizeStatic{});
}
template <typename T>
std::shared_ptr<UnknownAHContainer> UnknownAHNewInstanceFloatBasic(vtkm::VecTraitsTagSizeStatic)
template <typename T, typename S>
std::shared_ptr<UnknownAHContainer> UnknownAHNewInstanceFloatBasic(void*,
vtkm::VecTraitsTagSizeStatic)
{
using FloatT = typename vtkm::VecTraits<T>::template ReplaceBaseComponentType<vtkm::FloatDefault>;
return UnknownAHContainer::Make(vtkm::cont::ArrayHandleBasic<FloatT>{});
}
template <typename T>
std::shared_ptr<UnknownAHContainer> UnknownAHNewInstanceFloatBasic(vtkm::VecTraitsTagSizeVariable)
template <typename T, typename S>
std::shared_ptr<UnknownAHContainer> UnknownAHNewInstanceFloatBasic(void* mem,
vtkm::VecTraitsTagSizeVariable)
{
throw vtkm::cont::ErrorBadType("Cannot create a basic array container from with ValueType of " +
vtkm::cont::TypeToString<T>());
vtkm::IdComponent numComponents = UnknownAHNumberOfComponentsFlat<T, S>(mem);
if (numComponents < 1)
{
// Array can have an inconsistent number of components. Cannot be represented by basic array.
throw vtkm::cont::ErrorBadType("Cannot create a basic array from array with ValueType of " +
vtkm::cont::TypeToString<T>());
}
return UnknownAHContainer::Make(
vtkm::cont::ArrayHandleRuntimeVec<vtkm::FloatDefault>(numComponents));
}
template <typename T>
std::shared_ptr<UnknownAHContainer> UnknownAHNewInstanceFloatBasic()
template <typename T, typename S>
std::shared_ptr<UnknownAHContainer> UnknownAHNewInstanceFloatBasic(void* mem)
{
return UnknownAHNewInstanceFloatBasic<T>(typename vtkm::VecTraits<T>::IsSizeStatic{});
return UnknownAHNewInstanceFloatBasic<T, S>(mem, typename vtkm::VecTraits<T>::IsSizeStatic{});
}
template <typename T, typename S>
@ -352,8 +369,8 @@ inline UnknownAHContainer::UnknownAHContainer(const vtkm::cont::ArrayHandle<T, S
, DeleteFunction(detail::UnknownAHDelete<T, S>)
, Buffers(detail::UnknownAHBuffers<T, S>)
, NewInstance(detail::UnknownAHNewInstance<T, S>)
, NewInstanceBasic(detail::UnknownAHNewInstanceBasic<T>)
, NewInstanceFloatBasic(detail::UnknownAHNewInstanceFloatBasic<T>)
, NewInstanceBasic(detail::UnknownAHNewInstanceBasic<T, S>)
, NewInstanceFloatBasic(detail::UnknownAHNewInstanceFloatBasic<T, S>)
, NumberOfValues(detail::UnknownAHNumberOfValues<T, S>)
, NumberOfComponents(detail::UnknownAHNumberOfComponents<T, S>)
, NumberOfComponentsFlat(detail::UnknownAHNumberOfComponentsFlat<T, S>)

@ -254,6 +254,44 @@ void TryCopy()
ARRAY_SIZE));
}
{
std::cout << "runtime vec size -> runtime vec size (different type)" << std::endl;
using ComponentType = typename VTraits::BaseComponentType;
using SourceType = typename VTraits::template ReplaceComponentType<vtkm::UInt8>;
vtkm::cont::ArrayHandle<SourceType> staticVecArray = MakeInputArray<SourceType>();
vtkm::cont::ArrayHandleRuntimeVec<vtkm::UInt8> input =
vtkm::cont::make_ArrayHandleRuntimeVec(staticVecArray);
vtkm::cont::ArrayHandleRuntimeVec<ComponentType> output(input.GetNumberOfComponents());
vtkm::cont::ArrayCopy(input, output);
// Convert the arrays back to static vec sizes for comparison, because TestValues
// uses a device array copy that may not work on runtime vec sizes.
TestValues(staticVecArray,
output.template AsArrayHandleBasic<vtkm::cont::ArrayHandle<ValueType>>());
}
{
std::cout << "basic -> recombined vec" << std::endl;
using ComponentType = typename VTraits::BaseComponentType;
vtkm::cont::ArrayHandle<ValueType> input = MakeInputArray<ValueType>();
vtkm::cont::ArrayHandle<ValueType> output;
auto recombinedVec =
vtkm::cont::UnknownArrayHandle{ output }.ExtractArrayFromComponents<ComponentType>();
vtkm::cont::ArrayCopy(input, recombinedVec);
TestValues(input, output);
}
{
std::cout << "basic -> recombined vec (different type)" << std::endl;
using SourceType = typename VTraits::template ReplaceComponentType<vtkm::Id>;
using ComponentType = typename VTraits::BaseComponentType;
vtkm::cont::ArrayHandle<SourceType> input = MakeInputArray<SourceType>();
vtkm::cont::ArrayHandle<ValueType> output;
auto recombinedVec =
vtkm::cont::UnknownArrayHandle{ output }.ExtractArrayFromComponents<ComponentType>();
vtkm::cont::ArrayCopy(input, recombinedVec);
TestValues(input, output);
}
// Test the copy methods in UnknownArrayHandle. Although this would be appropriate in
// UnitTestUnknownArrayHandle, it is easier to test copies here.
{

@ -479,6 +479,18 @@ struct CheckExtractedArray
auto extractedData = extractedPortal.Get(valueIndex);
VTKM_TEST_ASSERT(test_equal(originalData, extractedData));
}
// Make sure an extracted array stuffed back into an UnknownArrayHandle works.
// This can happen when working with an extracted array that is passed to functions
// that are implemented with UnknownArrayHandle.
vtkm::cont::UnknownArrayHandle unknownArray{ extractedArray };
using ComponentType =
typename vtkm::VecTraits<typename ExtractedArray::ValueType>::BaseComponentType;
vtkm::cont::UnknownArrayHandle newBasic = unknownArray.NewInstanceBasic();
newBasic.AsArrayHandle<vtkm::cont::ArrayHandleRuntimeVec<ComponentType>>();
vtkm::cont::UnknownArrayHandle newFloat = unknownArray.NewInstanceFloatBasic();
newFloat.AsArrayHandle<vtkm::cont::ArrayHandleRuntimeVec<vtkm::FloatDefault>>();
}
};