mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-10-05 01:49:02 +00:00
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`.
This commit is contained in:
parent
b7125bd6fc
commit
4d02add0e0
16
docs/changelog/new-instance-variable-components.md
Normal file
16
docs/changelog/new-instance-variable-components.md
Normal file
@ -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>>();
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user