mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-09-16 17:22:55 +00:00
Merge branch 'master' of https://gitlab.kitware.com/vtk/vtk-m into sync_streamlines
This commit is contained in:
commit
a5ad12a4f4
@ -58,7 +58,7 @@
|
||||
- .docker_image
|
||||
|
||||
.ubuntu2004_hip_kokkos: &ubuntu2004_hip_kokkos
|
||||
image: "kitware/vtkm:ci-ubuntu2004_hip_kokkos-20230125"
|
||||
image: "kitware/vtkm:ci-ubuntu2004_hip_kokkos-20230220"
|
||||
extends:
|
||||
- .docker_image
|
||||
|
||||
@ -96,7 +96,7 @@
|
||||
when: on_success
|
||||
- when: never
|
||||
|
||||
.run_spock_ci: &run_spock_ci
|
||||
.run_crusher_ci: &run_crusher_ci
|
||||
rules:
|
||||
- if: '$CI_PROJECT_PATH == "ci/csc331_crusher/dev/vtk-m"'
|
||||
when: on_success
|
||||
@ -214,7 +214,7 @@ stages:
|
||||
|
||||
include:
|
||||
- local: '/.gitlab/ci/ascent.yml'
|
||||
- local: '/.gitlab/ci/spock.yml'
|
||||
- local: '/.gitlab/ci/crusher.yml'
|
||||
- local: '/.gitlab/ci/centos7.yml'
|
||||
- local: '/.gitlab/ci/centos8.yml'
|
||||
- local: '/.gitlab/ci/doxygen.yml'
|
||||
|
@ -2,7 +2,7 @@
|
||||
.ascent_gcc_cuda:
|
||||
variables:
|
||||
CCACHE_BASEDIR: "/gpfs/wolf/"
|
||||
CCACHE_DIR: "/gpfs/wolf/proj-shared/csc331/vtk-m/ci/ccache/"
|
||||
CCACHE_DIR: "/gpfs/wolf/csc331/scratch/vbolea/ci/ccache"
|
||||
# -isystem= is not affected by CCACHE_BASEDIR, thus we must ignore it
|
||||
CCACHE_IGNOREOPTIONS: "-isystem=*"
|
||||
CCACHE_NOHASHDIR: "true"
|
||||
@ -12,7 +12,7 @@
|
||||
CMAKE_BUILD_TYPE: "RelWithDebInfo"
|
||||
CMAKE_GENERATOR: "Ninja"
|
||||
CUDAHOSTCXX: "g++"
|
||||
CUSTOM_CI_BUILDS_DIR: "/gpfs/wolf/proj-shared/csc331/vtk-m/ci/runtime"
|
||||
CUSTOM_CI_BUILDS_DIR: "/gpfs/wolf/csc331/scratch/vbolea/ci/vtk-m"
|
||||
|
||||
VTKM_SETTINGS: cuda+ascent+ccache
|
||||
JOB_MODULES: >-
|
||||
@ -30,14 +30,18 @@
|
||||
module purge
|
||||
module load ${JOB_MODULES}
|
||||
module list
|
||||
export PATH="/gpfs/wolf/proj-shared/csc331/vtk-m/ci/utils:$PATH"
|
||||
export PATH="/gpfs/wolf/csc331/scratch/vbolea/ci/utils:$PATH"
|
||||
|
||||
build:ascent_gcc_cuda:
|
||||
stage: build
|
||||
tags: [olcf, ascent, nobatch]
|
||||
tags: [olcf, ascent, batch]
|
||||
extends:
|
||||
- .ascent_gcc_cuda
|
||||
- .run_ascent_ci
|
||||
- .cmake_build_artifacts
|
||||
variables:
|
||||
SCHEDULER_PARAMETERS: -P CSC331 -W 2:00 -nnodes 1 -alloc_flags smt1
|
||||
timeout: 125 minutes
|
||||
before_script:
|
||||
- *setup_env_ecpci
|
||||
- ccache -z
|
||||
@ -46,14 +50,16 @@ build:ascent_gcc_cuda:
|
||||
- git-lfs install
|
||||
- git-lfs pull lfs
|
||||
script:
|
||||
- CTEST_MAX_PARALLELISM=32 cmake -V -P .gitlab/ci/config/gitlab_ci_setup.cmake
|
||||
# Each Ascent (Summit) node has 172 threads (43 cores). SMT1 is needed to
|
||||
# avoid L1 cache pollution among different processes. Thus, using 40 cores
|
||||
# seems a reasonable choice which leaves a couple of cores for system processes.
|
||||
- CTEST_MAX_PARALLELISM=40 cmake -V -P .gitlab/ci/config/gitlab_ci_setup.cmake
|
||||
- ctest -VV -S .gitlab/ci/ctest_configure.cmake
|
||||
artifacts:
|
||||
expire_in: 24 hours
|
||||
when: always
|
||||
paths:
|
||||
- build/
|
||||
timeout: 10 minutes
|
||||
- GITLAB_CI_EMULATION=1 jsrun -n1 -a1 -g1 -c40 -bpacked:40 ctest -VV -S .gitlab/ci/ctest_build.cmake
|
||||
after_script:
|
||||
- *setup_env_ecpci
|
||||
- ccache -s
|
||||
- ctest -VV -S .gitlab/ci/ctest_submit_build.cmake
|
||||
|
||||
test:ascent_gcc_cuda:
|
||||
stage: test
|
||||
@ -67,17 +73,18 @@ test:ascent_gcc_cuda:
|
||||
dependencies:
|
||||
- build:ascent_gcc_cuda
|
||||
variables:
|
||||
SCHEDULER_PARAMETERS: -P CSC331 -W 2:00 -nnodes 1 -alloc_flags gpudefault
|
||||
# For tests we want to use a small number of proccesses, for some reason
|
||||
# a higher parallelism number tend to results in test malfunctions.
|
||||
CTEST_MAX_PARALLELISM: 4
|
||||
# We need this to skip ctest_submit from being run inside a jsrun job
|
||||
GITLAB_CI_EMULATION: 1
|
||||
SCHEDULER_PARAMETERS: -P CSC331 -W 1:00 -nnodes 1 -alloc_flags gpudefault
|
||||
timeout: 65 minutes
|
||||
before_script:
|
||||
- *setup_env_ecpci
|
||||
script:
|
||||
- jsrun -n1 -a1 -g1 -c42 ctest -VV -S .gitlab/ci/ctest_build.cmake
|
||||
- CTEST_MAX_PARALLELISM=4 jsrun -n1 -a1 -g1 -c8 ctest -VV -S .gitlab/ci/ctest_test.cmake
|
||||
- cmake -V -P .gitlab/ci/config/gitlab_ci_setup.cmake
|
||||
- jsrun -n1 -a1 -g1 -c1 ctest -VV -S .gitlab/ci/ctest_test.cmake
|
||||
after_script:
|
||||
- *setup_env_ecpci
|
||||
- ccache -s
|
||||
- ctest -VV -S .gitlab/ci/ctest_submit_build.cmake
|
||||
- ctest -VV -S .gitlab/ci/ctest_submit_test.cmake
|
||||
timeout: 120 minutes
|
||||
|
@ -45,7 +45,7 @@ build:centos8:
|
||||
- build
|
||||
- vtkm
|
||||
- docker
|
||||
- linux
|
||||
- linux-x86_64
|
||||
extends:
|
||||
- .centos8
|
||||
- .cmake_build_linux
|
||||
|
30
.gitlab/ci/config/kokkos.sh
Executable file
30
.gitlab/ci/config/kokkos.sh
Executable file
@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env bash
|
||||
set -x
|
||||
|
||||
WORKDIR="$1"
|
||||
VERSION="$2"
|
||||
|
||||
shift 2
|
||||
|
||||
if [ ! -d "$WORKDIR" ] || [ -z "$VERSION" ]
|
||||
then
|
||||
echo "[E] missing args: Invoke as .gitlab/ci/config/kokkos.sh <WORKDIR> <VERSION> [extra_args]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Build and install Kokkos
|
||||
curl -L "https://github.com/kokkos/kokkos/archive/refs/tags/$VERSION.tar.gz" \
|
||||
| tar -C "$WORKDIR" -xzf -
|
||||
|
||||
cmake -S "$WORKDIR/kokkos-$VERSION" -B "$WORKDIR/kokkos_build" \
|
||||
"-DCMAKE_BUILD_TYPE:STRING=release" \
|
||||
"-DCMAKE_CXX_COMPILER_LAUNCHER=ccache" \
|
||||
"-DCMAKE_CXX_STANDARD:STRING=14" \
|
||||
"-DCMAKE_POSITION_INDEPENDENT_CODE:BOOL=ON" \
|
||||
"-DKokkos_ENABLE_HIP:BOOL=ON" \
|
||||
"-DKokkos_ENABLE_HIP_RELOCATABLE_DEVICE_CODE:BOOL=OFF" \
|
||||
"-DKokkos_ENABLE_SERIAL:BOOL=ON" \
|
||||
$*
|
||||
|
||||
cmake --build "$WORKDIR/kokkos_build"
|
||||
cmake --install "$WORKDIR/kokkos_build"
|
@ -1,9 +1,9 @@
|
||||
# Ad-hoc build that runs in the ECP Hardware, concretely in OLCF Spock.
|
||||
.spock_gcc_hip:
|
||||
.crusher_gcc_hip:
|
||||
variables:
|
||||
CCACHE_BASEDIR: "/gpfs/alpine/world-shared/csc331/"
|
||||
CCACHE_DIR: "/gpfs/alpine/world-shared/csc331/vtk-m/ci/ccache"
|
||||
CUSTOM_CI_BUILDS_DIR: "/gpfs/alpine/world-shared/csc331/vtk-m/ci/runtime"
|
||||
CCACHE_BASEDIR: "/gpfs/alpine/csc331/scratch/"
|
||||
CCACHE_DIR: "/gpfs/alpine/csc331/scratch/vbolea/ci/vtk-m/ccache"
|
||||
CUSTOM_CI_BUILDS_DIR: "/gpfs/alpine/csc331/scratch/vbolea/ci/vtk-m/runtime"
|
||||
|
||||
# -isystem= is not affected by CCACHE_BASEDIR, thus we must ignore it
|
||||
CCACHE_IGNOREOPTIONS: "-isystem=*"
|
||||
@ -12,35 +12,25 @@
|
||||
|
||||
CMAKE_BUILD_TYPE: "RelWithDebInfo"
|
||||
CMAKE_GENERATOR: "Ninja"
|
||||
CMAKE_PREFIX_PATH: "$CI_BUILDS_DIR/kokkos_install"
|
||||
|
||||
# This is needed for the smoke_test, while we use rocm 5 to build VTK-m the
|
||||
# smoke_test needs 4.5 since Kokkos is built agains rocm 4.5
|
||||
LD_LIBRARY_PATH: "/opt/rocm-4.5.0/lib:${LD_LIBRARY_PATH}"
|
||||
LIBRARY_PATH: "/opt/rocm-4.5.0/lib:${LIBRARY_PATH}"
|
||||
KOKKOS_OPTS: >-
|
||||
-DCMAKE_INSTALL_PREFIX:PATH=$CI_BUILDS_DIR/kokkos_install
|
||||
-DCMAKE_CXX_COMPILER:FILEPATH=/opt/rocm-4.5.0/hip/bin/hipcc
|
||||
-DKokkos_ARCH_VEGA90A:BOOL=ON
|
||||
|
||||
# While Kokkos and VTK-m uses ROCm 4.5.0 runtime/sdk, we need to build
|
||||
# VTK-m with HIPCC from ROCM 5
|
||||
CMAKE_HIP_COMPILER: "/opt/rocm-default/llvm/bin/clang++"
|
||||
Kokkos_CXX_COMPILER: "/opt/rocm-default/llvm/bin/clang++"
|
||||
CMAKE_HIP_ARCHITECTURES: "gfx908"
|
||||
|
||||
CC: gcc
|
||||
CXX: g++
|
||||
# DefApps/default;craype;rocm;gcc should be loaded first
|
||||
JOB_MODULES: >-
|
||||
DefApps/default
|
||||
craype-accel-amd-gfx90a
|
||||
rocm/5
|
||||
rocm/4.5.0
|
||||
gcc/10
|
||||
cmake/3.22
|
||||
git
|
||||
git-lfs
|
||||
kokkos/3.5.00
|
||||
lsf-tools
|
||||
ninja
|
||||
spectrum-mpi
|
||||
zstd
|
||||
VTKM_SETTINGS: kokkos+hip+spock+ccache+no_rendering
|
||||
VTKM_SETTINGS: kokkos+hip+gfx90a+crusher+ccache+no_rendering
|
||||
interruptible: true
|
||||
|
||||
.setup_env_ecpci: &setup_env_ecpci |
|
||||
@ -49,12 +39,12 @@
|
||||
module list
|
||||
export PATH="${CCACHE_INSTALL_DIR}/ccache:$PATH"
|
||||
|
||||
build:spock_gcc_hip:
|
||||
build:crusher_gcc_hip:
|
||||
stage: build
|
||||
tags: [spock, shell]
|
||||
tags: [crusher, shell]
|
||||
extends:
|
||||
- .spock_gcc_hip
|
||||
- .run_spock_ci
|
||||
- .crusher_gcc_hip
|
||||
- .run_crusher_ci
|
||||
before_script:
|
||||
- *setup_env_ecpci
|
||||
- mkdir -p "$CCACHE_INSTALL_DIR"
|
||||
@ -62,6 +52,7 @@ build:spock_gcc_hip:
|
||||
- cmake -VV -P .gitlab/ci/config/ccache.cmake
|
||||
- ccache -z
|
||||
- ccache -s
|
||||
- .gitlab/ci/config/kokkos.sh "$CI_BUILDS_DIR" "3.7.01" $KOKKOS_OPTS
|
||||
|
||||
- git remote add lfs https://gitlab.kitware.com/vtk/vtk-m.git
|
||||
- git fetch lfs
|
||||
@ -77,18 +68,18 @@ build:spock_gcc_hip:
|
||||
- build/
|
||||
- .gitlab/ccache/ccache
|
||||
|
||||
test:spock_gcc_hip:
|
||||
test:crusher_gcc_hip:
|
||||
stage: test
|
||||
tags: [spock, slurm]
|
||||
tags: [crusher, slurm]
|
||||
extends:
|
||||
- .spock_gcc_hip
|
||||
- .run_spock_ci
|
||||
- .crusher_gcc_hip
|
||||
- .run_crusher_ci
|
||||
needs:
|
||||
- build:spock_gcc_hip
|
||||
- build:crusher_gcc_hip
|
||||
dependencies:
|
||||
- build:spock_gcc_hip
|
||||
- build:crusher_gcc_hip
|
||||
variables:
|
||||
SCHEDULER_PARAMETERS: "-ACSC331 -pecp -t120 --nice=0 -c32 --gpus=4 -N 1"
|
||||
SCHEDULER_PARAMETERS: "-ACSC331 -pbatch -t120 --nice=0 -c32 --gpus=4 -N 1"
|
||||
# We need this to skip ctest_submit from being run inside a jsrun job
|
||||
GITLAB_CI_EMULATION: 1
|
||||
# Tests errors to address due to different env in Spock
|
@ -14,6 +14,7 @@ RUN apt update && \
|
||||
ninja-build \
|
||||
rsync \
|
||||
ssh \
|
||||
rocthrust-dev \
|
||||
&& \
|
||||
apt clean
|
||||
|
||||
|
@ -62,7 +62,6 @@ test:ubuntu2004_kokkos:
|
||||
|
||||
build:ubuntu2004_hip_kokkos:
|
||||
tags:
|
||||
- build
|
||||
- vtkm
|
||||
- docker
|
||||
- linux-x86_64
|
||||
@ -93,7 +92,6 @@ build:ubuntu2004_hip_kokkos:
|
||||
|
||||
test:ubuntu2004_hip_kokkos:
|
||||
tags:
|
||||
- build
|
||||
- vtkm
|
||||
- docker
|
||||
- linux-x86_64
|
||||
|
@ -357,6 +357,14 @@ if(VTKm_ENABLE_KOKKOS AND NOT TARGET vtkm_kokkos)
|
||||
add_library(vtkm_kokkos_hip INTERFACE)
|
||||
set_property(TARGET vtkm_kokkos_hip PROPERTY EXPORT_NAME kokkos_hip)
|
||||
install(TARGETS vtkm_kokkos_hip EXPORT ${VTKm_EXPORT_NAME})
|
||||
|
||||
# Make sure rocthrust is available if requested
|
||||
if(VTKm_ENABLE_KOKKOS_THRUST)
|
||||
find_package(rocthrust)
|
||||
if(NOT rocthrust_FOUND)
|
||||
message(FATAL_ERROR "rocthrust not found. Please set VTKm_ENABLE_KOKKOS_THRUST to OFF.")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_library(vtkm_kokkos INTERFACE IMPORTED GLOBAL)
|
||||
|
@ -227,6 +227,11 @@ include(VTKmBuildType)
|
||||
# Include the vtk-m wrappers
|
||||
include(VTKmWrappers)
|
||||
|
||||
# By default: Set VTKm_ENABLE_KOKKOS_THRUST to ON if VTKm_ENABLE_KOKKOS is ON, otherwise
|
||||
# disable it (or if the user explicitly turns this option OFF)
|
||||
cmake_dependent_option(VTKm_ENABLE_KOKKOS_THRUST "Enable Kokkos thrust support (only valid with CUDA and HIP)"
|
||||
ON "VTKm_ENABLE_KOKKOS;Kokkos_ENABLE_CUDA OR Kokkos_ENABLE_HIP" OFF)
|
||||
|
||||
# Create vtkm_compiler_flags library. This is an interface library that
|
||||
# holds all the C++ compiler flags that are needed for consumers and
|
||||
# when building VTK-m.
|
||||
|
@ -1,7 +1,7 @@
|
||||
VTKm License Version 2.0
|
||||
========================================================================
|
||||
|
||||
Copyright (c) 2014-2022
|
||||
Copyright (c) 2014-2023
|
||||
Kitware Inc.,
|
||||
National Technology & Engineering Solutions of Sandia, LLC (NTESS),
|
||||
UT-Battelle, LLC.,
|
||||
|
@ -1,3 +1,6 @@
|
||||
![GitLab tag](https://img.shields.io/gitlab/v/tag/vtk/vtk-m?color=red&gitlab_url=https%3A%2F%2Fgitlab.kitware.com&include_prereleases&sort=semver)
|
||||
![Spack version](https://img.shields.io/spack/v/vtk-m.svg)
|
||||
|
||||
# VTK-m #
|
||||
|
||||
VTK-m is a toolkit of scientific visualization algorithms for emerging
|
||||
@ -64,7 +67,7 @@ effort.
|
||||
|
||||
VTK-m Requires:
|
||||
|
||||
+ C++11 Compiler. VTK-m has been confirmed to work with the following
|
||||
+ C++14 Compiler. VTK-m has been confirmed to work with the following
|
||||
+ GCC 5.4+
|
||||
+ Clang 5.0+
|
||||
+ XCode 5.0+
|
||||
|
@ -708,29 +708,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
// Get the number of components in a UnknownArrayHandle, ArrayHandle, or Field's
|
||||
// ValueType.
|
||||
struct NumberOfComponents
|
||||
{
|
||||
vtkm::IdComponent NumComponents;
|
||||
|
||||
template <typename ArrayHandleT>
|
||||
VTKM_CONT void operator()(const ArrayHandleT&)
|
||||
{
|
||||
using ValueType = typename ArrayHandleT::ValueType;
|
||||
using Traits = vtkm::VecTraits<ValueType>;
|
||||
this->NumComponents = Traits::NUM_COMPONENTS;
|
||||
}
|
||||
|
||||
template <typename DynamicType>
|
||||
VTKM_CONT static vtkm::IdComponent Check(const DynamicType& obj)
|
||||
{
|
||||
NumberOfComponents functor;
|
||||
vtkm::cont::CastAndCall(obj, functor);
|
||||
return functor.NumComponents;
|
||||
}
|
||||
};
|
||||
|
||||
void FindFields()
|
||||
{
|
||||
if (PointScalarsName.empty())
|
||||
@ -739,7 +716,7 @@ void FindFields()
|
||||
{
|
||||
auto field = GetInputDataSet().GetField(i);
|
||||
if (field.GetAssociation() == vtkm::cont::Field::Association::Points &&
|
||||
NumberOfComponents::Check(field) == 1)
|
||||
field.GetData().GetNumberOfComponentsFlat() == 1)
|
||||
{
|
||||
PointScalarsName = field.GetName();
|
||||
std::cerr << "[FindFields] Found PointScalars: " << PointScalarsName << "\n";
|
||||
@ -754,7 +731,7 @@ void FindFields()
|
||||
{
|
||||
auto field = GetInputDataSet().GetField(i);
|
||||
if (field.GetAssociation() == vtkm::cont::Field::Association::Cells &&
|
||||
NumberOfComponents::Check(field) == 1)
|
||||
field.GetData().GetNumberOfComponentsFlat() == 1)
|
||||
{
|
||||
CellScalarsName = field.GetName();
|
||||
std::cerr << "[FindFields] CellScalars: " << CellScalarsName << "\n";
|
||||
@ -769,7 +746,7 @@ void FindFields()
|
||||
{
|
||||
auto field = GetInputDataSet().GetField(i);
|
||||
if (field.GetAssociation() == vtkm::cont::Field::Association::Points &&
|
||||
NumberOfComponents::Check(field) == 3)
|
||||
field.GetData().GetNumberOfComponentsFlat() == 3)
|
||||
{
|
||||
PointVectorsName = field.GetName();
|
||||
std::cerr << "[FindFields] Found PointVectors: " << PointVectorsName << "\n";
|
||||
|
@ -982,6 +982,55 @@ void ParseBenchmarkOptions(int& argc, char** argv)
|
||||
|
||||
std::cerr << "Using data set dimensions = " << DataSetDim << std::endl;
|
||||
std::cerr << "Using image size = " << ImageSize << "x" << ImageSize << std::endl;
|
||||
|
||||
// Now go back through the arg list and remove anything that is not in the list of
|
||||
// unknown options or non-option arguments.
|
||||
int destArg = 1;
|
||||
// This is copy/pasted from vtkm::cont::Initialize(), should probably be abstracted eventually:
|
||||
for (int srcArg = 1; srcArg < argc; ++srcArg)
|
||||
{
|
||||
std::string thisArg{ argv[srcArg] };
|
||||
bool copyArg = false;
|
||||
|
||||
// Special case: "--" gets removed by optionparser but should be passed.
|
||||
if (thisArg == "--")
|
||||
{
|
||||
copyArg = true;
|
||||
}
|
||||
for (const option::Option* opt = options[UNKNOWN]; !copyArg && opt != nullptr;
|
||||
opt = opt->next())
|
||||
{
|
||||
if (thisArg == opt->name)
|
||||
{
|
||||
copyArg = true;
|
||||
}
|
||||
if ((opt->arg != nullptr) && (thisArg == opt->arg))
|
||||
{
|
||||
copyArg = true;
|
||||
}
|
||||
// Special case: optionparser sometimes removes a single "-" from an option
|
||||
if (thisArg.substr(1) == opt->name)
|
||||
{
|
||||
copyArg = true;
|
||||
}
|
||||
}
|
||||
for (int nonOpt = 0; !copyArg && nonOpt < commandLineParse.nonOptionsCount(); ++nonOpt)
|
||||
{
|
||||
if (thisArg == commandLineParse.nonOption(nonOpt))
|
||||
{
|
||||
copyArg = true;
|
||||
}
|
||||
}
|
||||
if (copyArg)
|
||||
{
|
||||
if (destArg != srcArg)
|
||||
{
|
||||
argv[destArg] = argv[srcArg];
|
||||
}
|
||||
++destArg;
|
||||
}
|
||||
}
|
||||
argc = destArg;
|
||||
}
|
||||
|
||||
// Adding a const char* or std::string to a vector of char* is harder than it sounds.
|
||||
|
@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:3a24175a16a60f3e917170907546a52de15e703bd06017fecd9c6238db9d2726
|
||||
size 103177
|
||||
oid sha256:3f9bdb6825e859500308217228970c406b8f75c0ab16d0c2c8d704dfa9ae2e10
|
||||
size 116102
|
||||
|
3
data/data/curvilinear/kitchen.vtk
Normal file
3
data/data/curvilinear/kitchen.vtk
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:29d6de0eb33dfb792405d3903b1ede382cac417c29bb5d7e17e60be384db42cc
|
||||
size 1940269
|
@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:7a569aff0c6872611ef75a4dcb597e1320cb966b80f840a0dbd76a29b2760dbb
|
||||
size 50335052
|
||||
oid sha256:347b03839fde1734ce4bd7bbf660524d039246ca3a7fd54c356a5fd7d1ffccf8
|
||||
size 50335089
|
||||
|
@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:671345bdb045aeadc8e9fa1060de51e53286c74929c6c8c60a529b318f02bbfc
|
||||
size 3795
|
||||
oid sha256:9ab17ce444d6df1ab28f24ea997adaf2a406ca6b5035da6b17867f742380fbf4
|
||||
size 3832
|
||||
|
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:ef3dfd79f0c8d18780d0749014d71c0226134041283d33de0bcd994e343dd421
|
||||
size 2001070
|
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2bb3d36ea5ecef5e7ef1057d0dddebbc590424915083091ead3dac2928000524
|
||||
size 2904465
|
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:bffad7dae3dd6ef018ad7a9e109464ced0f3b9bc15cf1fb5d555f6d0d00b621f
|
||||
size 3001624
|
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2cbdf56fd5445ddc5b6bc05507b8825fb8d74fe1ccce894bde03e5ff2ecf5fb6
|
||||
size 525141
|
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b947d66dbae99a1ebb392b200a9ea0d380cfccb7fcb3a3739615d0dde558d2f1
|
||||
size 238166
|
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:8c23821f7436bce6d71593698e3cb0047752b4dd671513f8c4e961d4489f199f
|
||||
size 12110311
|
3
data/data/third_party/README.md
vendored
Normal file
3
data/data/third_party/README.md
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:362e59e70e65fd365bc64221decdea1096ac9fe4346e23126ec2d35836215832
|
||||
size 456
|
3
data/data/third_party/ecl_cc/README
vendored
3
data/data/third_party/ecl_cc/README
vendored
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:6f5e6e3dc559fefc7990daaec071fcd620f620e5ab8652dddaa6b43ca4ba08e7
|
||||
size 222
|
3
data/data/third_party/ecl_cc/README.md
vendored
Normal file
3
data/data/third_party/ecl_cc/README.md
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:55f8b9b11031d8a200145763989dedb787efee60b24f39e0c20b139899570d96
|
||||
size 2197
|
3
data/data/third_party/visit/README.md
vendored
Normal file
3
data/data/third_party/visit/README.md
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:279231652c3bc23c31a8c7a6bf2e71f56afd11b6e09b5c05dca5dc48380ee0fb
|
||||
size 1934
|
3
data/data/third_party/visit/example.vtk
vendored
Normal file
3
data/data/third_party/visit/example.vtk
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:ce56bb831ac66983f9689c2a73ec0dd7a7a91294f822ad19bf1caa093a8fba25
|
||||
size 11295710
|
3
data/data/third_party/visit/example_temp.bov
vendored
Normal file
3
data/data/third_party/visit/example_temp.bov
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:724a6dce8f6f5d6478891a915c76c57c5881467240bb055c6001725631f7833a
|
||||
size 350
|
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2071da4365341303e401d20dc6e8bb35ebeccc24b801cc81ab87e75e3a4ef654
|
||||
size 339
|
3
data/data/uniform/rotate-vectors.vtk
Normal file
3
data/data/uniform/rotate-vectors.vtk
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:13241631e0d65d17d7bad2be44b52c0352797135fb585647f5c821e439ff9817
|
||||
size 862894
|
3
data/data/uniform/venn250.visit
Normal file
3
data/data/uniform/venn250.visit
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:62accba30cde47cac6980dbec18c6edc08e48f353da8f0817a810e66631cb89e
|
||||
size 38
|
@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d68d7acc1199af1de37ff581c6e39309e99dc0bae977fc9a0abf054d80aeb52a
|
||||
size 2004559
|
||||
oid sha256:553468d1130df26b48823fa5dc0f58196920056106b9bf0d312d651c66e423c5
|
||||
size 2004653
|
||||
|
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:9a178b29073f2aa0d15375b07d0bdd28369422a352b5dcb5155cf67aebe54bbc
|
||||
size 286099
|
@ -181,7 +181,7 @@ for (auto v : vector)
|
||||
avoided in class, method, and function scopes (fully qualified
|
||||
namespace references are preferred).
|
||||
|
||||
+ All code must be valid by the C++11 specifications. It must also
|
||||
+ All code must be valid by the C++14 specifications. It must also
|
||||
compile with Microsoft Visual Studio 2015.
|
||||
|
||||
+ New code must include regression tests that will run on the dashboards.
|
||||
|
@ -40,6 +40,8 @@ $endif\
|
||||
|
||||
## Create update branch
|
||||
|
||||
- [ ] Freeze the release branch (In Gitlab VTK-m page)
|
||||
- Settings/Repository/Protected Branches: Release; "allowed to push:No one"
|
||||
- [ ] Create update branch `git checkout -b update-to-$(VERSION)`
|
||||
$if(PATCH == 0 and RC == "-rc1")\
|
||||
- [ ] Bring as a second parent the history of master (Solve conflicts always
|
||||
@ -104,6 +106,8 @@ $endif\
|
||||
- [ ] `Do: merge`
|
||||
- Push tags
|
||||
- [ ] `git push origin v$(VERSION)$(RC)`
|
||||
- [ ] Unfreeze the release branch (In Gitlab VTK-m page)
|
||||
- Settings/Repository/Protected Branches: Release; "allowed to push: Maintainers"
|
||||
|
||||
## Update Spack
|
||||
- [ ] Update Spack package: https://github.com/spack/spack/blob/develop/var/spack/repos/builtin/packages/vtk-m/package.py
|
||||
|
@ -1,13 +1,13 @@
|
||||
# Minor Release Roadmap
|
||||
# Release Roadmap
|
||||
|
||||
| Version | Date | Delay (days) | Life-cycle (*planned) | End of Support |
|
||||
| --------- | ------------ | ------- | ----------- | ---------------- |
|
||||
| 1.7.0 | 2021-12-01 | +8 | Long Term | 2022-12-01 |
|
||||
| 1.8.0 | 2022-06-01 | +14 | Long Term | 2023-06-01 |
|
||||
| 1.9.0 | 2022-09-01 | +41 | Short Term | next release |
|
||||
| 2.0.0 | 2022-12-01 | | Long Term* | TBD |
|
||||
| 2.1.0 | 2023-03-01 | | Short Term* | TBD |
|
||||
| 2.2.0 | 2023-06-01 | | Long Term* | TBD |
|
||||
| 1.9.0 | 2022-09-01 | +41 | Short Term | 2023-06-01 |
|
||||
| 2.0.0 | 2022-12-01 | +52 | Long Term* | 2023-12-01 |
|
||||
| 2.1.0 | 2023-06-01 | | Short Term* | TBD |
|
||||
| 2.2.0 | 2023-09-01 | | Long Term* | TBD |
|
||||
|
||||
|
||||
## Legend
|
||||
|
@ -21,10 +21,13 @@ VTK-m 2.0 Release Notes
|
||||
- Attach compressed ZFP data as WholeDataSet field
|
||||
4. [Execution Environment](#Execution-Environment)
|
||||
- Removed ExecutionWholeArray class
|
||||
- Add initial support for aborting execution
|
||||
5. [Worklets and Filters](#Worklets-and-Filters)
|
||||
- Correct particle density filter output field
|
||||
- Rename NewFilter base classes to Filter
|
||||
- Fix handling of cell fields in Tube filter
|
||||
- Fix setting fields to pass in Filter when setting mode
|
||||
- Respect Filter::PassCoordinateSystem flag in filters creating coordinate systems.
|
||||
6. [Build](#Build)
|
||||
- More performance test options
|
||||
- Output complete list of libraries for external Makefiles
|
||||
@ -32,6 +35,7 @@ VTK-m 2.0 Release Notes
|
||||
7. [Other](#Other)
|
||||
- Expose the Variant helper class
|
||||
- Fix VTKM_LOG_SCOPE
|
||||
- Clarify field index ordering in Doxygen
|
||||
|
||||
# Core
|
||||
|
||||
@ -240,6 +244,29 @@ that `ExecutionWholeArray` had was that it provided an subscript operator
|
||||
(somewhat incorrectly). Thus, any use of '[..]' to index the array portal
|
||||
have to be changed to use the `Get` method.
|
||||
|
||||
## Add initial support for aborting execution
|
||||
|
||||
VTK-m now has preliminary support for aborting execution. The per-thread instances of
|
||||
`RuntimeDeviceTracker` have a functor called `AbortChecker`. This functor can be set using
|
||||
`RuntimeDeviceTracker::SetAbortChecker()` and cleared by `RuntimeDeviceTracker::ClearAbortChecker()`
|
||||
The abort checker functor should return `true` if an abort is requested for the thread,
|
||||
otherwise, it should return `false`.
|
||||
|
||||
Before launching a new task, `TaskExecute` calls the functor to see if an abort is requested,
|
||||
and If so, throws an exception of type `vtkm::cont::ErrorUserAbort`.
|
||||
|
||||
Any code that wants to use the abort feature, should set an appropriate `AbortChecker`
|
||||
functor for the target thread. Then any piece of code that has parts that can execute on
|
||||
the device should be put under a `try-catch` block. Any clean-up that is required for an
|
||||
aborted execution should be handled in a `catch` block that handles exceptions of type
|
||||
`vtkm::cont::ErrorUserAbort`.
|
||||
|
||||
The limitation of this implementation is that it is control-side only. The check for abort
|
||||
is done before launching a new device task. Once execution has begun on the device, there is
|
||||
currently no way to abort that. Therefore, this feature is only useful for aborting code
|
||||
that is made up of several smaller device task launches (Which is the case for most
|
||||
worklets and filters in VTK-m)
|
||||
|
||||
# Worklets and Filters
|
||||
|
||||
## Correct particle density filter output field
|
||||
@ -282,6 +309,43 @@ would also get around some problems with the implementation that was
|
||||
removed here when mixing polylines with other cell types and degenerate
|
||||
lines.)
|
||||
|
||||
## Fix setting fields to pass in `Filter` when setting mode
|
||||
|
||||
The `Filter` class has several version of the `SetFieldsToPass` method that
|
||||
works in conjunction with the `FieldSelection` object to specify which
|
||||
fields are mapped. For example, the user might have code like this to pass
|
||||
all fields except those named `pointvar` and `cellvar`:
|
||||
|
||||
``` cpp
|
||||
filter.SetFieldsToPass({ "pointvar", "cellvar" },
|
||||
vtkm::filter::FieldSelection::Mode::Exclude);
|
||||
```
|
||||
|
||||
This previously worked by implicitly creating a `FieldSelection` object
|
||||
using the `std::initializer_list` filled with the 2 strings. This would
|
||||
then be passed to the `SetFieldsToPass` method, which would capture the
|
||||
`FieldSelection` object and change the mode.
|
||||
|
||||
This stopped working in a recent change to `FieldSelection` where each
|
||||
entry is given its own mode. With this new class, the `FieldSelection`
|
||||
constructor would capture each field in the default mode (`Select`) and
|
||||
then change the default mode to `Exclude`. However, the already set modes
|
||||
kept their `Select` status, which is not what is intended.
|
||||
|
||||
This behavior is fixed by adding `SetFieldToPass` overloads that capture
|
||||
both the `initializer_list` and the `Mode` and then constructs the
|
||||
`FieldSelection` correctly.
|
||||
|
||||
## Respect `Filter::PassCoordinateSystem` flag in filters creating coordinate systems
|
||||
|
||||
The `Filter` class has a `PassCoordinateSystem` flag that specifies whether
|
||||
coordinate systems should be passed regardless of whether the associated
|
||||
field is passed. However, if a filter created its output with the
|
||||
`CreateResultCoordinateSystem` method this flag was ignored, and the
|
||||
provided coordinate system was always passed. This might not be what the
|
||||
user intended, so this method has been fixed to first check the
|
||||
`PassCoordinateSystem` flag before setting the coordinates on the output.
|
||||
|
||||
# Build
|
||||
|
||||
## More performance test options
|
||||
@ -375,3 +439,14 @@ This was not what was happening. The second log message was being printed
|
||||
immediately after the first. This is because the scope was taken inside of
|
||||
the `LogScope` method. The macro has been rewritten to put the tracking in
|
||||
the right scope.
|
||||
|
||||
## Clarify field index ordering in Doxygen
|
||||
|
||||
The fields in a `DataSet` are indexed from `0` to `GetNumberOfFields() - 1`.
|
||||
It is natural to assume that the fields will be indexed in the order that
|
||||
they are added, but they are not. Rather, the indexing is arbitrary and can
|
||||
change any time a field is added to the dataset.
|
||||
|
||||
To make this more clear, Doxygen documentation is added to the `DataSet`
|
||||
methods to inform users to not make any assumptions about the order of
|
||||
field indexing.
|
||||
|
3
docs/changelog/2.0/shrink-filter
Normal file
3
docs/changelog/2.0/shrink-filter
Normal file
@ -0,0 +1,3 @@
|
||||
# New Shrink filter
|
||||
|
||||
The Shrink filter shrinks the cells of a DataSet towards their centroid, computed as the average position of the cell points. This filter disconnects the cells, duplicating the points connected to multiple cells. The resulting CellSet is always an `ExplicitCellSet`.
|
18
docs/changelog/array-range-fast-paths.md
Normal file
18
docs/changelog/array-range-fast-paths.md
Normal file
@ -0,0 +1,18 @@
|
||||
# Fast paths for `ArrayRangeCompute` fixed
|
||||
|
||||
The precompiled `ArrayRangeCompute` function was not following proper fast
|
||||
paths for special arrays. For example, when computing the range of an
|
||||
`ArrayHandleUniformPointCoordinates`, the ranges should be taken from the
|
||||
origin and spacing of the special array. However, the precompiled version
|
||||
was calling the generic range computation, which was doing an unnecessary
|
||||
reduction over the entire array. These fast paths have been fixed.
|
||||
|
||||
These mistakes in the code were caused by quirks in how templated method
|
||||
overloading works. To prevent this mistake from happening again in the
|
||||
precompiled `ArrayRangeCompute` function and elsewhere, all templated forms
|
||||
of `ArrayRangeCompute` have been deprecated. Most will call
|
||||
`ArrayRangeCompute` with no issues. For those that need the templated
|
||||
version, `ArrayRangeComputeTemplate` replaces the old templated
|
||||
`ArrayRangeCompute`. There is exactly one templated declaration of
|
||||
`ArrayRangeComputeTemplate` that uses a class, `ArrayRangeComputeImpl`,
|
||||
with partial specialization to ensure the correct form is used.
|
44
docs/changelog/data-license.md
Normal file
44
docs/changelog/data-license.md
Normal file
@ -0,0 +1,44 @@
|
||||
# Clarified license of test data
|
||||
|
||||
The VTK-m source comes distributed with several data files used for
|
||||
regression testing. Some of these are generated specifically by VTK-m
|
||||
developers and are released as part of the VTK-m license, but some come
|
||||
from external sources. For those that come from external sources, we have
|
||||
clarified the license and attribution of those files. In particular, the
|
||||
following files originate from external sources.
|
||||
|
||||
* **internet.egr**: Distributed as part of a graph data set paper. The
|
||||
license of this data is compatible with VTK-m's license. The file is
|
||||
placed in the third-party data directory and the information has been
|
||||
updated to clearly document the correct license for this data.
|
||||
* **example.vtk** and **example_temp.bov**: Distributed as part of the
|
||||
VisIt tutorials. This data is provided under the VisIt license (per Eric
|
||||
Brugger), which is compatible with VTK-m's license. The files are moved
|
||||
to the third-party data directory and the license and attribution is
|
||||
clarified. (These files were previously named "noise" but were changed to
|
||||
match the VisIt tutorial files they came from.)
|
||||
* **vanc.vtk** Data derived from a digital elevation map of Vancouver that
|
||||
comes from GTOPO30. This data is in the public domain, so it is valid for
|
||||
us to use, modify, and redistribute the data under our license.
|
||||
|
||||
The fishtank and fusion/magField datasets were removed. These are standard
|
||||
flow testing data sets that are commonly distributed. However, we could not
|
||||
track down the original source and license, so to be cautious these data
|
||||
sets have been removed and replaced with some generated in house.
|
||||
|
||||
For some of the other data sets, we have traced down the original author
|
||||
and verified that they propery contribute the data to VTK-m and agree to
|
||||
allow it to be distributed under VTK-m's license. Not counting the most
|
||||
trivial examples, here are the originators of the non-trivial data
|
||||
examples.
|
||||
|
||||
* **5x6_&_MC*.ctm** and **8x9test_HierarchicalAugmentedTree*.dat**: Hamish
|
||||
Carr
|
||||
* **warpXfields.vtk** and **warpXparticles.vtk**: Axel Huebl
|
||||
* **amr_wind_flowfield.vtk**: James Kress
|
||||
* **DoubleGyre*.vtk**: James Kress
|
||||
* **venn250.vtk**: Abhishek Yenpure
|
||||
* **wedge_cells.vtk**: Chris Laganella
|
||||
* **kitchen.vtk**: Copyright owned by Kitware, Inc. (who shares the
|
||||
copyright of VTK-m)
|
||||
|
@ -1,10 +0,0 @@
|
||||
# Clarify field index ordering in Doxygen
|
||||
|
||||
The fields in a `DataSet` are indexed from `0` to `GetNumberOfFields() - 1`.
|
||||
It is natural to assume that the fields will be indexed in the order that
|
||||
they are added, but they are not. Rather, the indexing is arbitrary and can
|
||||
change any time a field is added to the dataset.
|
||||
|
||||
To make this more clear, Doxygen documentation is added to the `DataSet`
|
||||
methods to inform users to not make any assumptions about the order of
|
||||
field indexing.
|
23
docs/changelog/runtime-vec-array.md
Normal file
23
docs/changelog/runtime-vec-array.md
Normal file
@ -0,0 +1,23 @@
|
||||
# Added `ArrayHandleRuntimeVec` to specify vector sizes at runtime.
|
||||
|
||||
The new `ArrayHandleRuntimeVec` is a fancy `ArrayHandle` allows you to
|
||||
specify a basic array of `Vec`s where the number of components of the `Vec`
|
||||
are not known until runtime. (It can also optionally specify scalars.) The
|
||||
behavior is much like that of `ArrayHandleGroupVecVariable` except that its
|
||||
representation is much more constrained. This constrained representation
|
||||
allows it to be automatically converted to an `ArrayHandleBasic` with the
|
||||
proper `Vec` value type. This allows one part of code (such as a file
|
||||
reader) to create an array with any `Vec` size, and then that array can be
|
||||
fed to an algorithm that expects an `ArrayHandleBasic` of a certain value
|
||||
type.
|
||||
|
||||
The `UnknownArrayHandle` has also been updated to allow
|
||||
`ArrayHandleRuntimeVec` to work interchangeably with basic `ArrayHandle`.
|
||||
If an `ArrayHandleRuntimeVec` is put into an `UnknownArrayHandle`, it can
|
||||
be later retrieved as an `ArrayHandleBasic` as long as the base component
|
||||
type matches and it has the correct amount of components. This means that
|
||||
an array can be created as an `ArrayHandleRuntimeVec` and be used with any
|
||||
filters or most other features designed to operate on basic `ArrayHandle`s.
|
||||
Likewise, an array added as a basic `ArrayHandle` can be retrieved in an
|
||||
`ArrayHandleRuntimeVec`. This makes it easier to pull arrays from VTK-m and
|
||||
place them in external structures (such as `vtkDataArray`).
|
22
docs/changelog/serialize-dataset.md
Normal file
22
docs/changelog/serialize-dataset.md
Normal file
@ -0,0 +1,22 @@
|
||||
# Simplified serialization of DataSet objects
|
||||
|
||||
`vtkm::cont::DataSet` is a dynamic object that can hold cell sets and
|
||||
fields of many different types, none of which are known until runtime. This
|
||||
causes a problem with serialization, which has to know what type to compile
|
||||
the serialization for, particularly when unserializing the type at the
|
||||
receiving end. The original implementation "solved" the problem by creating
|
||||
a secondary wrapper object that was templated on types of field arrays and
|
||||
cell sets that might be serialized. This is not a great solution as it
|
||||
punts the problem to algorithm developers.
|
||||
|
||||
This problem has been completely solved for fields, as it is possible to
|
||||
serialize most types of arrays without knowing their type now. You still
|
||||
need to iterate over every possible `CellSet` type, but there are not that
|
||||
many `CellSet`s that are practically encountered. Thus, there is now a
|
||||
direct implementation of `Serialization` for `DataSet` that covers all the
|
||||
data types you are likely to encounter.
|
||||
|
||||
The old `SerializableDataSet` has been deprecated. In the unlikely event an
|
||||
algorithm needs to transfer a non-standard type of `CellSet` (such as a
|
||||
permuted cell set), it can use the replacement `DataSetWithCellSetTypes`,
|
||||
which just specifies the cell set types.
|
@ -1,3 +1,4 @@
|
||||
# New Statistics filter
|
||||
|
||||
The statistics filter computes the descriptive statistics of the fields specified by users based on `DescriptiveStatistics`. Users can set `RequiredStatsList` to specify which statistics will be stored in the output data set.
|
||||
The statistics filter computes the descriptive statistics of the fields specified by users based on `DescriptiveStatistics`. Users can set `RequiredStatsList` to specify which statistics will be stored in the output data set. The statistics filter supports the distributed memory case based on the vtkmdiy, and the process with rank 0 will return the correct final reduced results.
|
||||
|
||||
|
18
docs/changelog/unknownarray-runtime-components.md
Normal file
18
docs/changelog/unknownarray-runtime-components.md
Normal file
@ -0,0 +1,18 @@
|
||||
# Added support for getting vec sizes of unknown arrays when runtime selected
|
||||
|
||||
The `GetNumberOfComponents` and `GetNumberOfComponentsFlat` methods in
|
||||
`UnknownArrayHandle` have been updated to correctly report the number of
|
||||
components in special `ArrayHandle`s where the `Vec` sizes of the values
|
||||
are not selected until runtime.
|
||||
|
||||
Previously, these methods always reported 0 because the value type could
|
||||
not report the size of the `Vec`. The lookup has been modified to query the
|
||||
`ArrayHandle`'s `Storage` for the number of components where supported.
|
||||
Note that this only works on `Storage` that provides a method to get the
|
||||
runtime `Vec` size. If that is not provided, as will be the case if the
|
||||
number of components can vary from one value to the next, it will still
|
||||
report 0.
|
||||
|
||||
This feature is implemented by looking for a method named
|
||||
`GetNumberOfComponents` is the `Storage` class for the `ArrayHandle`. If
|
||||
this method is found, it is used to query the size at runtime.
|
19
docs/changelog/vectraits-for-all.md
Normal file
19
docs/changelog/vectraits-for-all.md
Normal file
@ -0,0 +1,19 @@
|
||||
# Implemented `VecTraits` class for all types
|
||||
|
||||
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.
|
3
docs/changelog/visit-file-reader.md
Normal file
3
docs/changelog/visit-file-reader.md
Normal file
@ -0,0 +1,3 @@
|
||||
# Added a reader for VisIt files.
|
||||
|
||||
A VisIt file is a text file that contains the path and filename of a number of VTK files. This provides a convenient way to load `vtkm::cont::PartitionedDataSet` data from VTK files. The first line of the file is the keyword `!NBLOCKS <N>` that specifies the number of VTK files to be read.
|
@ -24,9 +24,9 @@ int main(int argc, char* argv[])
|
||||
if ((argc < 4) || (argc > 5))
|
||||
{
|
||||
std::cerr << "Usage: " << argv[0] << " in_data.vtk field_name clip_value [out_data.vtk]\n\n";
|
||||
std::cerr << "For example, you could use the ucd3d.vtk that comes with the VTK-m source:\n\n";
|
||||
std::cerr << "For example, you could use the example.vtk that comes with the VTK-m source:\n\n";
|
||||
std::cerr << " " << argv[0]
|
||||
<< " <path-to-vtkm-source>/data/data/unstructured/ucd3d.vtk v 0.3\n";
|
||||
<< " <path-to-vtkm-source>/data/data/third_party/visit/example.vtk temp 3.5\n";
|
||||
return 1;
|
||||
}
|
||||
std::string infilename = argv[1];
|
||||
|
@ -16,11 +16,11 @@
|
||||
#include <vtkm/io/VTKDataSetWriter.h>
|
||||
|
||||
// Example computing streamlines.
|
||||
// An example vector field is available in the vtk-m data directory: magField.vtk
|
||||
// An example vector field is available in the vtk-m data directory: rotate-vectors.vtk
|
||||
// Example usage:
|
||||
// this will advect 200 particles 50 steps using a step size of 0.01
|
||||
// this will advect 200 particles 50 steps using a step size of 0.05
|
||||
//
|
||||
// Particle_Advection <path-to-data-dir>/magField.vtk vec 200 50 0.01 output.vtk
|
||||
// Particle_Advection <path-to-data-dir>/rotate-vectors.vtk rotate 200 50 0.05 output.vtk
|
||||
//
|
||||
|
||||
int main(int argc, char** argv)
|
||||
@ -28,10 +28,10 @@ int main(int argc, char** argv)
|
||||
auto opts = vtkm::cont::InitializeOptions::DefaultAnyDevice;
|
||||
auto config = vtkm::cont::Initialize(argc, argv, opts);
|
||||
|
||||
if (argc < 8)
|
||||
if (argc < 7)
|
||||
{
|
||||
std::cerr << "Usage: " << argv[0]
|
||||
<< "dataFile varName numSeeds numSteps stepSize outputFile [options]" << std::endl;
|
||||
<< " dataFile varName numSeeds numSteps stepSize outputFile [options]" << std::endl;
|
||||
std::cerr << "where options are: " << std::endl << config.Usage << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
@ -133,8 +133,7 @@ public:
|
||||
this->Decomposer.fill_bounds(bds, target.gid);
|
||||
|
||||
auto extractedDS = this->Extract(*block, bds);
|
||||
// TODO: Need a better way to serialize DataSet. See issue #725.
|
||||
rp.enqueue(target, vtkm::cont::SerializableDataSet<>(extractedDS));
|
||||
rp.enqueue(target, extractedDS);
|
||||
}
|
||||
// clear our dataset.
|
||||
*block = vtkm::cont::DataSet();
|
||||
@ -149,10 +148,9 @@ public:
|
||||
auto target = rp.in_link().target(cc);
|
||||
if (rp.incoming(target.gid).size() > 0)
|
||||
{
|
||||
// TODO: Need a better way to serialize DataSet. See issue #725.
|
||||
vtkm::cont::SerializableDataSet<> sds;
|
||||
rp.dequeue(target.gid, sds);
|
||||
receives.push_back(sds.DataSet);
|
||||
vtkm::cont::DataSet incomingDS;
|
||||
rp.dequeue(target.gid, incomingDS);
|
||||
receives.push_back(incomingDS);
|
||||
numValues += receives.back().GetCoordinateSystem(0).GetNumberOfPoints();
|
||||
}
|
||||
}
|
||||
|
@ -75,11 +75,11 @@ void LoadData(std::string& fname, std::vector<vtkm::cont::DataSet>& dataSets, in
|
||||
}
|
||||
|
||||
// Example computing streamlines.
|
||||
// An example vector field is available in the vtk-m data directory: magField.vtk
|
||||
// An example vector field is available in the vtk-m data directory: rotate-vectors.vtk
|
||||
// Example usage:
|
||||
// this will advect 200 particles 50 steps using a step size of 0.01
|
||||
// this will advect 200 particles 50 steps using a step size of 0.05
|
||||
//
|
||||
// Particle_Advection <path-to-data-dir>/magField.vtk vec 200 50 0.01 output.vtk
|
||||
// Particle_Advection <path-to-data-dir>/rotate-vectors.vtk vec 200 50 0.05 output.vtk
|
||||
//
|
||||
|
||||
int main(int argc, char** argv)
|
||||
|
@ -24,8 +24,9 @@ int main(int argc, char* argv[])
|
||||
if ((argc < 2) || (argc > 3))
|
||||
{
|
||||
std::cerr << "Usage: " << argv[0] << " in_data.vtk [out_data.vtk]\n\n";
|
||||
std::cerr << "For example, you could use the ucd3d.vtk that comes with the VTK-m source:\n\n";
|
||||
std::cerr << " " << argv[0] << " <path-to-vtkm-source>/data/data/unstructured/ucd3d.vtk\n";
|
||||
std::cerr << "For example, you could use the example.vtk that comes with the VTK-m source:\n\n";
|
||||
std::cerr << " " << argv[0]
|
||||
<< " <path-to-vtkm-source>/data/data/third_party/visit/example.vtk\n";
|
||||
return 1;
|
||||
}
|
||||
std::string infilename = argv[1];
|
||||
|
@ -9,11 +9,10 @@
|
||||
##============================================================================
|
||||
|
||||
#add the directory that contains the VTK-m config file to the cmake
|
||||
#path so that our examples can find VTK-m
|
||||
#path so that our tutorial can find VTK-m
|
||||
#Normally when running CMake, you need to set the VTKm_DIR to
|
||||
#find the VTKmConfig.cmake file. Because we already know where this
|
||||
#file is, we can add the location to look to CMAKE_PREFIX_PATH.
|
||||
|
||||
set(CMAKE_PREFIX_PATH ${VTKm_BINARY_DIR}/${VTKm_INSTALL_CONFIG_DIR})
|
||||
|
||||
cmake_minimum_required(VERSION 3.12...3.15 FATAL_ERROR)
|
||||
@ -22,20 +21,41 @@ project(VTKm_tut)
|
||||
#Find the VTK-m package
|
||||
find_package(VTKm REQUIRED QUIET)
|
||||
|
||||
|
||||
if (VTKm_ENABLE_TUTORIALS)
|
||||
# VTK-m tutorial targets expect vtkm libraries to be namespaced with the prefix vtkm::.
|
||||
# However, as the tutorial can also be built as part of the VTK-m code,
|
||||
# those prefix are not added to the targets (This happens during the
|
||||
# installation). To workaround this issue here, we create IMPORTED libs linking
|
||||
# to the vtkm libraries used by the tutorial targets with the expected vtkm:: prefix.
|
||||
vtkm_module_get_list(module_list)
|
||||
foreach(tgt IN LISTS module_list)
|
||||
if(TARGET ${tgt})
|
||||
# The reason of creating this phony IMPORTED libraries instead of making
|
||||
# ALIAS libraries is that ALIAS libraries are GLOBAL whereas IMPORTED are
|
||||
# local at the directory level where they are created. We do not want these
|
||||
# phony targets to be visible outside of the tutorial directory.
|
||||
vtkm_target_mangle(tgt_name_mangled ${tgt})
|
||||
add_library("vtkm::${tgt_name_mangled}" INTERFACE IMPORTED)
|
||||
target_link_libraries("vtkm::${tgt_name_mangled}" INTERFACE ${tgt})
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
add_executable(io io.cxx)
|
||||
target_link_libraries(io vtkm_filter vtkm_io)
|
||||
target_link_libraries(io vtkm::io)
|
||||
|
||||
add_executable(contour contour.cxx)
|
||||
target_link_libraries(contour vtkm_filter vtkm_io)
|
||||
target_link_libraries(contour vtkm::filter_core vtkm::filter_contour vtkm::io)
|
||||
|
||||
add_executable(contour_two_fields contour_two_fields.cxx)
|
||||
target_link_libraries(contour_two_fields vtkm_filter vtkm_io)
|
||||
target_link_libraries(contour_two_fields vtkm::filter_core vtkm::filter_contour vtkm::io)
|
||||
|
||||
add_executable(two_filters two_filters.cxx)
|
||||
target_link_libraries(two_filters vtkm_filter vtkm_io)
|
||||
target_link_libraries(two_filters vtkm::filter_core vtkm::filter_contour vtkm::io)
|
||||
|
||||
add_executable(mag_grad mag_grad.cxx)
|
||||
target_link_libraries(mag_grad vtkm_filter vtkm_io)
|
||||
target_link_libraries(mag_grad vtkm::filter_core vtkm::filter_vector_analysis vtkm::io)
|
||||
# Because mag_grad.cxx creates a worklet with code that
|
||||
# runs on a GPU, it needs additional information.
|
||||
vtkm_add_target_information(mag_grad
|
||||
@ -44,23 +64,23 @@ vtkm_add_target_information(mag_grad
|
||||
|
||||
if (VTKm_ENABLE_RENDERING)
|
||||
add_executable(rendering rendering.cxx)
|
||||
target_link_libraries(rendering vtkm_filter vtkm_io vtkm_rendering)
|
||||
target_link_libraries(rendering vtkm::io vtkm::rendering)
|
||||
endif ()
|
||||
|
||||
add_executable(error_handling error_handling.cxx)
|
||||
target_link_libraries(error_handling vtkm_filter vtkm_io)
|
||||
target_link_libraries(error_handling vtkm::filter_core vtkm::filter_contour vtkm::io)
|
||||
|
||||
add_executable(logging logging.cxx)
|
||||
target_link_libraries(logging vtkm_filter vtkm_io)
|
||||
target_link_libraries(logging vtkm::io)
|
||||
|
||||
add_executable(point_to_cell point_to_cell.cxx)
|
||||
target_link_libraries(point_to_cell vtkm_cont vtkm_filter vtkm_io)
|
||||
target_link_libraries(point_to_cell vtkm::worklet vtkm::filter_core vtkm::io)
|
||||
vtkm_add_target_information(point_to_cell
|
||||
DROP_UNUSED_SYMBOLS MODIFY_CUDA_FLAGS
|
||||
DEVICE_SOURCES point_to_cell.cxx)
|
||||
|
||||
add_executable(extract_edges extract_edges.cxx)
|
||||
target_link_libraries(extract_edges vtkm_cont vtkm_filter vtkm_io)
|
||||
target_link_libraries(extract_edges vtkm::cont vtkm::filter_core vtkm::filter_contour vtkm::worklet vtkm::io)
|
||||
vtkm_add_target_information(extract_edges
|
||||
DROP_UNUSED_SYMBOLS MODIFY_CUDA_FLAGS
|
||||
DEVICE_SOURCES extract_edges.cxx)
|
||||
|
@ -69,7 +69,7 @@ public:
|
||||
/// \brief A tag to determine whether the type has multiple components.
|
||||
///
|
||||
/// This tag is either TypeTraitsScalarTag or TypeTraitsVectorTag. Scalars can
|
||||
/// also be treated as vectors.
|
||||
/// also be treated as vectors with VecTraits.
|
||||
using DimensionalityTag = vtkm::TypeTraitsUnknownTag;
|
||||
|
||||
VTKM_EXEC_CONT static T ZeroInitialization() { return T(); }
|
||||
|
@ -53,6 +53,18 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
template <vtkm::IdComponent N>
|
||||
VTKM_EXEC_CONT operator vtkm::Vec<ComponentType, N>() const
|
||||
{
|
||||
vtkm::Vec<ComponentType, N> result;
|
||||
this->CopyInto(result);
|
||||
for (vtkm::IdComponent index = this->NumComponents; index < N; ++index)
|
||||
{
|
||||
result[index] = vtkm::TypeTraits<ComponentType>::ZeroInitialization();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
VTKM_EXEC_CONT
|
||||
vtkm::internal::ArrayPortalValueReference<PortalType> operator[](vtkm::IdComponent index) const
|
||||
@ -61,6 +73,20 @@ public:
|
||||
index + this->Offset);
|
||||
}
|
||||
|
||||
template <typename T, vtkm::IdComponent N>
|
||||
VTKM_EXEC_CONT VecFromPortal& operator=(const vtkm::Vec<T, N>& src)
|
||||
{
|
||||
vtkm::IdComponent numComponents = vtkm::Min(N, this->NumComponents);
|
||||
for (vtkm::IdComponent index = 0; index < numComponents; ++index)
|
||||
{
|
||||
this->Portal.Set(index + this->Offset, src[index]);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
VTKM_EXEC_CONT const PortalType& GetPortal() const { return this->Portal; }
|
||||
VTKM_EXEC_CONT vtkm::Id GetOffset() const { return this->Offset; }
|
||||
|
||||
private:
|
||||
PortalType Portal;
|
||||
vtkm::IdComponent NumComponents;
|
||||
@ -109,6 +135,15 @@ struct VecTraits<vtkm::VecFromPortal<PortalType>>
|
||||
return vector[componentIndex];
|
||||
}
|
||||
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
VTKM_EXEC_CONT
|
||||
static void SetComponent(const VecType& vector,
|
||||
vtkm::IdComponent componentIndex,
|
||||
const ComponentType& value)
|
||||
{
|
||||
vector[componentIndex] = value;
|
||||
}
|
||||
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
template <vtkm::IdComponent destSize>
|
||||
VTKM_EXEC_CONT static void CopyInto(const VecType& src, vtkm::Vec<ComponentType, destSize>& dest)
|
||||
|
295
vtkm/VecTraits.h
295
vtkm/VecTraits.h
@ -10,6 +10,8 @@
|
||||
#ifndef vtk_m_VecTraits_h
|
||||
#define vtk_m_VecTraits_h
|
||||
|
||||
#include <vtkm/Deprecated.h>
|
||||
#include <vtkm/StaticAssert.h>
|
||||
#include <vtkm/Types.h>
|
||||
|
||||
namespace vtkm
|
||||
@ -42,60 +44,55 @@ struct VecTraitsTagSizeVariable
|
||||
{
|
||||
};
|
||||
|
||||
namespace internal
|
||||
{
|
||||
|
||||
template <vtkm::IdComponent numComponents>
|
||||
struct VecTraitsMultipleComponentChooser
|
||||
{
|
||||
using Type = vtkm::VecTraitsTagMultipleComponents;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct VecTraitsMultipleComponentChooser<1>
|
||||
{
|
||||
using Type = vtkm::VecTraitsTagSingleComponent;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
/// The VecTraits class gives several static members that define how
|
||||
/// to use a given type as a vector.
|
||||
/// \brief Traits that can be queried to treat any type as a `Vec`.
|
||||
///
|
||||
template <class VecType>
|
||||
/// The VecTraits class gives several static members that define how
|
||||
/// to use a given type as a vector. This is useful for templated
|
||||
/// functions and methods that have a parameter that could be either
|
||||
/// a standard scalar type or a `Vec` or some other `Vec`-like
|
||||
/// object. When using this class, scalar objects are treated like
|
||||
/// a `Vec` of size 1.
|
||||
///
|
||||
/// The default implementation of this template treats the type as
|
||||
/// a scalar. Types that actually behave like vectors should
|
||||
/// specialize this template to provide the proper information.
|
||||
///
|
||||
template <class T>
|
||||
struct VTKM_NEVER_EXPORT VecTraits
|
||||
{
|
||||
#ifdef VTKM_DOXYGEN_ONLY
|
||||
// The base VecTraits should not be used with qualifiers.
|
||||
VTKM_STATIC_ASSERT_MSG((std::is_same<std::remove_pointer_t<std::decay_t<T>>, T>::value),
|
||||
"The base VecTraits should not be used with qualifiers.");
|
||||
|
||||
/// \brief Type of the components in the vector.
|
||||
///
|
||||
/// If the type is really a scalar, then the component type is the same as the scalar type.
|
||||
///
|
||||
using ComponentType = typename VecType::ComponentType;
|
||||
using ComponentType = T;
|
||||
|
||||
/// \brief Base component type in the vector.
|
||||
///
|
||||
/// Similar to ComponentType except that for nested vectors (e.g. Vec<Vec<T, M>, N>), it
|
||||
/// returns the base scalar type at the end of the composition (T in this example).
|
||||
///
|
||||
using BaseComponentType = typename vtkm::VecTraits<ComponentType>::BaseComponentType;
|
||||
using BaseComponentType = T;
|
||||
|
||||
/// \brief Number of components in the vector.
|
||||
///
|
||||
/// This is only defined for vectors of a static size.
|
||||
///
|
||||
static constexpr vtkm::IdComponent NUM_COMPONENTS = VecType::NUM_COMPONENTS;
|
||||
static constexpr vtkm::IdComponent NUM_COMPONENTS = 1;
|
||||
|
||||
/// Number of components in the given vector.
|
||||
///
|
||||
static vtkm::IdComponent GetNumberOfComponents(const VecType& vec);
|
||||
static constexpr vtkm::IdComponent GetNumberOfComponents(const T&) { return NUM_COMPONENTS; }
|
||||
|
||||
/// \brief A tag specifying whether this vector has multiple components (i.e. is a "real" vector).
|
||||
///
|
||||
/// This tag can be useful for creating specialized functions when a vector
|
||||
/// is really just a scalar.
|
||||
///
|
||||
using HasMultipleComponents =
|
||||
typename internal::VecTraitsMultipleComponentChooser<NUM_COMPONENTS>::Type;
|
||||
using HasMultipleComponents = vtkm::VecTraitsTagSingleComponent;
|
||||
|
||||
/// \brief A tag specifying whether the size of this vector is known at compile time.
|
||||
///
|
||||
@ -107,81 +104,113 @@ struct VTKM_NEVER_EXPORT VecTraits
|
||||
|
||||
/// Returns the value in a given component of the vector.
|
||||
///
|
||||
VTKM_EXEC_CONT static const ComponentType& GetComponent(
|
||||
const typename std::remove_const<VecType>::type& vector,
|
||||
vtkm::IdComponent component);
|
||||
VTKM_EXEC_CONT static ComponentType& GetComponent(
|
||||
typename std::remove_const<VecType>::type& vector,
|
||||
vtkm::IdComponent component);
|
||||
VTKM_EXEC_CONT static const ComponentType& GetComponent(const T& vector,
|
||||
vtkm::IdComponent vtkmNotUsed(component))
|
||||
{
|
||||
return vector;
|
||||
}
|
||||
VTKM_EXEC_CONT static ComponentType& GetComponent(T& vector,
|
||||
vtkm::IdComponent vtkmNotUsed(component))
|
||||
{
|
||||
return vector;
|
||||
}
|
||||
|
||||
/// Changes the value in a given component of the vector.
|
||||
///
|
||||
VTKM_EXEC_CONT static void SetComponent(VecType& vector,
|
||||
vtkm::IdComponent component,
|
||||
ComponentType value);
|
||||
VTKM_EXEC_CONT static void SetComponent(T& vector,
|
||||
vtkm::IdComponent vtkmNotUsed(component),
|
||||
ComponentType value)
|
||||
{
|
||||
vector = value;
|
||||
}
|
||||
|
||||
/// \brief Get a vector of the same type but with a different component.
|
||||
///
|
||||
/// This type resolves to another vector with a different component type. For example,
|
||||
/// @code vtkm::VecTraits<vtkm::Vec<T, N>>::ReplaceComponentType<T2> @endcode is vtkm::Vec<T2, N>.
|
||||
/// This replacement is not recursive. So @code VecTraits<Vec<Vec<T, M>, N>::ReplaceComponentType<T2> @endcode
|
||||
/// is vtkm::Vec<T2, N>.
|
||||
/// `vtkm::VecTraits<vtkm::Vec<T, N>>::ReplaceComponentType<T2>` is `vtkm::Vec<T2, N>`.
|
||||
/// This replacement is not recursive. So `VecTraits<Vec<Vec<T, M>, N>::ReplaceComponentType<T2>`
|
||||
/// is `vtkm::Vec<T2, N>`.
|
||||
///
|
||||
template <typename NewComponentType>
|
||||
using ReplaceComponentType = VecTemplate<NewComponentType, N>;
|
||||
using ReplaceComponentType = NewComponentType;
|
||||
|
||||
/// \brief Get a vector of the same type but with a different base component.
|
||||
///
|
||||
/// This type resolves to another vector with a different base component type. The replacement
|
||||
/// is recursive for nested types. For example,
|
||||
/// @code VecTraits<Vec<Vec<T, M>, N>::ReplaceBaseComponentType<T2> @endcode is Vec<Vec<T2, M>, N>.
|
||||
/// `VecTraits<Vec<Vec<T, M>, N>::ReplaceBaseComponentType<T2>` is `Vec<Vec<T2, M>, N>`.
|
||||
///
|
||||
template <typename NewComponentType>
|
||||
using ReplaceBaseComponentType = VecTemplate<
|
||||
typename VecTraits<ComponentType>::template ReplaceBaseComponentType<NewComponentType>,
|
||||
N>;
|
||||
using ReplaceBaseComponentType = NewComponentType;
|
||||
|
||||
/// Copies the components in the given vector into a given Vec object.
|
||||
///
|
||||
template <vktm::IdComponent destSize>
|
||||
VTKM_EXEC_CONT static void CopyInto(const VecType& src, vtkm::Vec<ComponentType, destSize>& dest);
|
||||
#endif // VTKM_DOXYGEN_ONLY
|
||||
template <vtkm::IdComponent destSize>
|
||||
VTKM_EXEC_CONT static void CopyInto(const T& src, vtkm::Vec<ComponentType, destSize>& dest)
|
||||
{
|
||||
dest[0] = src;
|
||||
}
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
struct HasVecTraitsImpl
|
||||
{
|
||||
template <typename A, typename S = typename vtkm::VecTraits<A>::ComponentType>
|
||||
static std::true_type Test(A*);
|
||||
using HasVecTraits VTKM_DEPRECATED(2.1, "All types now have VecTraits defined.") = std::true_type;
|
||||
|
||||
static std::false_type Test(...);
|
||||
|
||||
using Type = decltype(Test(std::declval<T*>()));
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// \brief Determines whether the given type has VecTraits defined.
|
||||
///
|
||||
/// If the given type T has a valid VecTraits class, then HasVecTraits<T> will be set to
|
||||
/// std::true_type. Otherwise it will be set to std::false_type. For example,
|
||||
/// HasVecTraits<vtkm::Id> is the same as std::true_type whereas HasVecTraits<void *> is the same
|
||||
/// as std::false_type. This is useful to block the definition of methods using VecTraits when
|
||||
/// VecTraits are not defined.
|
||||
///
|
||||
template <typename T>
|
||||
using HasVecTraits = typename detail::HasVecTraitsImpl<T>::Type;
|
||||
|
||||
// This partial specialization allows you to define a non-const version of
|
||||
// VecTraits and have it still work for const version.
|
||||
//
|
||||
// These partial specializations allow VecTraits to work with const and reference qualifiers.
|
||||
template <typename T>
|
||||
struct VTKM_NEVER_EXPORT VecTraits<const T> : VecTraits<T>
|
||||
{
|
||||
};
|
||||
template <typename T>
|
||||
struct VTKM_NEVER_EXPORT VecTraits<T&> : VecTraits<T>
|
||||
{
|
||||
};
|
||||
template <typename T>
|
||||
struct VTKM_NEVER_EXPORT VecTraits<const T&> : VecTraits<T>
|
||||
{
|
||||
};
|
||||
|
||||
// This partial specialization allows VecTraits to work with pointers.
|
||||
template <typename T>
|
||||
struct VTKM_NEVER_EXPORT VecTraits<T*> : VecTraits<T>
|
||||
{
|
||||
VTKM_EXEC_CONT static vtkm::IdComponent GetNumberOfComponents(const T* vector)
|
||||
{
|
||||
return VecTraits<T>::GetNumberOfComponents(*vector);
|
||||
}
|
||||
VTKM_EXEC_CONT static auto GetComponent(const T* vector, vtkm::IdComponent component)
|
||||
-> decltype(VecTraits<T>::GetComponent(*vector, component))
|
||||
{
|
||||
return VecTraits<T>::GetComponent(*vector, component);
|
||||
}
|
||||
VTKM_EXEC_CONT static auto GetComponent(T* vector, vtkm::IdComponent component)
|
||||
-> decltype(VecTraits<T>::GetComponent(*vector, component))
|
||||
{
|
||||
return VecTraits<T>::GetComponent(*vector, component);
|
||||
}
|
||||
VTKM_EXEC_CONT static void SetComponent(T* vector,
|
||||
vtkm::IdComponent component,
|
||||
typename VecTraits<T>::ComponentType value)
|
||||
{
|
||||
VecTraits<T>::SetComponent(*vector, component, value);
|
||||
}
|
||||
template <typename NewComponentType>
|
||||
using ReplaceComponentType =
|
||||
typename VecTraits<T>::template ReplaceComponentType<NewComponentType>*;
|
||||
template <typename NewComponentType>
|
||||
using ReplaceBaseComponentType =
|
||||
typename VecTraits<T>::template ReplaceBaseComponentType<NewComponentType>*;
|
||||
template <vtkm::IdComponent destSize>
|
||||
VTKM_EXEC_CONT static void CopyInto(
|
||||
const T* src,
|
||||
vtkm::Vec<typename VecTraits<T>::ComponentType, destSize>& dest)
|
||||
{
|
||||
VecTraits<T>::CopyInto(*src, dest);
|
||||
}
|
||||
};
|
||||
template <typename T>
|
||||
struct VTKM_NEVER_EXPORT VecTraits<const T*> : VecTraits<T*>
|
||||
{
|
||||
};
|
||||
|
||||
#if defined(VTKM_GCC) && (__GNUC__ <= 5)
|
||||
namespace detail
|
||||
@ -203,6 +232,23 @@ struct VecReplaceBaseComponentTypeGCC4or5
|
||||
} // namespace detail
|
||||
#endif // GCC Version 4.8
|
||||
|
||||
namespace internal
|
||||
{
|
||||
|
||||
template <vtkm::IdComponent numComponents, typename ComponentType>
|
||||
struct VecTraitsMultipleComponentChooser
|
||||
{
|
||||
using Type = vtkm::VecTraitsTagMultipleComponents;
|
||||
};
|
||||
|
||||
template <typename ComponentType>
|
||||
struct VecTraitsMultipleComponentChooser<1, ComponentType>
|
||||
{
|
||||
using Type = typename vtkm::VecTraits<ComponentType>::HasMultipleComponents;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
template <typename T, vtkm::IdComponent Size>
|
||||
struct VTKM_NEVER_EXPORT VecTraits<vtkm::Vec<T, Size>>
|
||||
{
|
||||
@ -235,7 +281,7 @@ struct VTKM_NEVER_EXPORT VecTraits<vtkm::Vec<T, Size>>
|
||||
/// when a vector is really just a scalar.
|
||||
///
|
||||
using HasMultipleComponents =
|
||||
typename internal::VecTraitsMultipleComponentChooser<NUM_COMPONENTS>::Type;
|
||||
typename internal::VecTraitsMultipleComponentChooser<NUM_COMPONENTS, ComponentType>::Type;
|
||||
|
||||
/// A tag specifying whether the size of this vector is known at compile
|
||||
/// time. If set to \c VecTraitsTagSizeStatic, then \c NUM_COMPONENTS is set.
|
||||
@ -502,7 +548,8 @@ namespace internal
|
||||
/// Used for overriding VecTraits for basic scalar types.
|
||||
///
|
||||
template <typename ScalarType>
|
||||
struct VTKM_NEVER_EXPORT VecTraitsBasic
|
||||
struct VTKM_DEPRECATED(2.1, "VecTraitsBasic is now the default implementation for VecTraits.")
|
||||
VTKM_NEVER_EXPORT VecTraitsBasic
|
||||
{
|
||||
using ComponentType = ScalarType;
|
||||
using BaseComponentType = ScalarType;
|
||||
@ -541,87 +588,41 @@ struct VTKM_NEVER_EXPORT VecTraitsBasic
|
||||
}
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <typename T, typename = vtkm::HasVecTraits<T>>
|
||||
struct VTKM_NEVER_EXPORT SafeVecTraitsImpl;
|
||||
|
||||
template <typename T>
|
||||
struct VTKM_NEVER_EXPORT SafeVecTraitsImpl<T, std::true_type> : vtkm::VecTraits<T>
|
||||
{
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct VTKM_NEVER_EXPORT SafeVecTraitsImpl<T, std::false_type> : vtkm::internal::VecTraitsBasic<T>
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// \brief A version of VecTraits that will be available for any type.
|
||||
///
|
||||
/// The `VecTraits` template is only defined for types that have a specific specialization
|
||||
/// for it. That means if you use `VecTraits` in a template, that template will likely
|
||||
/// fail to build for types that are not defined for `VecTraits`.
|
||||
///
|
||||
/// To use `VecTraits` in a class that should support all types, not just those with
|
||||
/// defined `VecTraits`, you can use this "safe" version. `SafeVecTraits` is the same as
|
||||
/// `VecTraits` if the latter is defined. If the `VecTraits` are not defined, then
|
||||
/// `SafeVecTraits` treats the type as a simple scalar value.
|
||||
///
|
||||
/// This template ensures that it will work reasonably well for all types. But be careful
|
||||
/// as if `VecTraits` is later defined, the template is likely to change.
|
||||
///
|
||||
template <typename T>
|
||||
struct VTKM_NEVER_EXPORT SafeVecTraits : detail::SafeVecTraitsImpl<T>
|
||||
struct VTKM_DEPRECATED(2.1 "VecTraits now safe to use on any type.") VTKM_NEVER_EXPORT SafeVecTraits
|
||||
: vtkm::VecTraits<T>
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
/// \brief VecTraits for Pair types
|
||||
///
|
||||
/// Although a pair would seem better as a size-2 vector, we treat it as a
|
||||
/// scalar. This is because a \c Vec is assumed to have the same type for
|
||||
/// every component, and a pair in general has a different type for each
|
||||
/// component. Thus we treat a pair as a "scalar" unit.
|
||||
///
|
||||
template <typename T, typename U>
|
||||
struct VTKM_NEVER_EXPORT VecTraits<vtkm::Pair<T, U>>
|
||||
: public vtkm::internal::VecTraitsBasic<vtkm::Pair<T, U>>
|
||||
namespace detail
|
||||
{
|
||||
|
||||
struct VTKM_DEPRECATED(2.1,
|
||||
"VTKM_BASIC_TYPE_VECTOR is no longer necessary because VecTraits implements "
|
||||
"basic type by default.") VTKM_BASIC_TYPE_VECTOR_is_deprecated
|
||||
{
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct issue_VTKM_BASIC_TYPE_VECTOR_deprecation_warning;
|
||||
|
||||
}
|
||||
|
||||
} // namespace vtkm
|
||||
|
||||
#define VTKM_BASIC_TYPE_VECTOR(type) \
|
||||
namespace vtkm \
|
||||
{ \
|
||||
template <> \
|
||||
struct VTKM_NEVER_EXPORT VecTraits<type> : public vtkm::internal::VecTraitsBasic<type> \
|
||||
{ \
|
||||
}; \
|
||||
#define VTKM_BASIC_TYPE_VECTOR(type) \
|
||||
namespace vtkm \
|
||||
{ \
|
||||
namespace detail \
|
||||
{ \
|
||||
template <> \
|
||||
struct issue_VTKM_BASIC_TYPE_VECTOR_deprecation_warning<type> \
|
||||
: public vtkm::detail::VTKM_BASIC_TYPE_VECTOR_is_deprecated \
|
||||
{ \
|
||||
}; \
|
||||
} \
|
||||
}
|
||||
|
||||
/// Allows you to treat basic types as if they were vectors.
|
||||
|
||||
VTKM_BASIC_TYPE_VECTOR(float)
|
||||
VTKM_BASIC_TYPE_VECTOR(double)
|
||||
|
||||
VTKM_BASIC_TYPE_VECTOR(bool)
|
||||
VTKM_BASIC_TYPE_VECTOR(char)
|
||||
VTKM_BASIC_TYPE_VECTOR(signed char)
|
||||
VTKM_BASIC_TYPE_VECTOR(unsigned char)
|
||||
VTKM_BASIC_TYPE_VECTOR(short)
|
||||
VTKM_BASIC_TYPE_VECTOR(unsigned short)
|
||||
VTKM_BASIC_TYPE_VECTOR(int)
|
||||
VTKM_BASIC_TYPE_VECTOR(unsigned int)
|
||||
VTKM_BASIC_TYPE_VECTOR(long)
|
||||
VTKM_BASIC_TYPE_VECTOR(unsigned long)
|
||||
VTKM_BASIC_TYPE_VECTOR(long long)
|
||||
VTKM_BASIC_TYPE_VECTOR(unsigned long long)
|
||||
|
||||
//#undef VTKM_BASIC_TYPE_VECTOR
|
||||
|
||||
#endif //vtk_m_VecTraits_h
|
||||
|
@ -33,21 +33,6 @@ namespace cont
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// Compile-time check to make sure that an `ArrayHandle` passed to `ArrayCopy`
|
||||
// can be passed to a `UnknownArrayHandle`. This function does nothing
|
||||
// except provide a compile error that is easier to understand than if you
|
||||
// let it go and error in `UnknownArrayHandle`. (Huh? I'm not using that.)
|
||||
template <typename T>
|
||||
inline void ArrayCopyValueTypeCheck()
|
||||
{
|
||||
VTKM_STATIC_ASSERT_MSG(vtkm::HasVecTraits<T>::value,
|
||||
"An `ArrayHandle` that has a special value type that is not supported "
|
||||
"by the precompiled version of `ArrayCopy` has been used. If this array "
|
||||
"must be deep copied, consider using `ArrayCopyDevice`. Look at the "
|
||||
"compile error for the type assigned to template parameter `T` to "
|
||||
"see the offending type.");
|
||||
}
|
||||
|
||||
template <typename S>
|
||||
struct ArrayCopyConcreteSrc;
|
||||
|
||||
@ -74,8 +59,6 @@ void ArrayCopyImpl(const vtkm::cont::UnknownArrayHandle& source,
|
||||
std::false_type,
|
||||
std::true_type)
|
||||
{
|
||||
detail::ArrayCopyValueTypeCheck<T>();
|
||||
|
||||
using DestType = vtkm::cont::ArrayHandle<T, S>;
|
||||
if (source.CanConvert<DestType>())
|
||||
{
|
||||
@ -96,9 +79,6 @@ void ArrayCopyImpl(const vtkm::cont::ArrayHandle<TS, SS>& source,
|
||||
std::true_type,
|
||||
std::true_type)
|
||||
{
|
||||
ArrayCopyValueTypeCheck<TS>();
|
||||
ArrayCopyValueTypeCheck<TD>();
|
||||
|
||||
detail::ArrayCopyConcreteSrc<SS>{}(source, destination);
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,7 @@ namespace internal
|
||||
// is defined rather than where it is resolved. This causes problems when extracting
|
||||
// components of, say, an ArrayHandleMultiplexer holding an ArrayHandleSOA.
|
||||
template <typename T, typename S>
|
||||
vtkm::cont::ArrayHandleStride<typename vtkm::internal::SafeVecTraits<T>::BaseComponentType>
|
||||
vtkm::cont::ArrayHandleStride<typename vtkm::VecTraits<T>::BaseComponentType>
|
||||
ArrayExtractComponentFallback(const vtkm::cont::ArrayHandle<T, S>& src,
|
||||
vtkm::IdComponent componentIndex,
|
||||
vtkm::CopyFlag allowCopy)
|
||||
@ -53,7 +53,7 @@ ArrayExtractComponentFallback(const vtkm::cont::ArrayHandle<T, S>& src,
|
||||
<< vtkm::cont::TypeToString<vtkm::cont::ArrayHandle<T, S>>()
|
||||
<< " requires an inefficient memory copy.");
|
||||
|
||||
using BaseComponentType = typename vtkm::internal::SafeVecTraits<T>::BaseComponentType;
|
||||
using BaseComponentType = typename vtkm::VecTraits<T>::BaseComponentType;
|
||||
vtkm::Id numValues = src.GetNumberOfValues();
|
||||
vtkm::cont::ArrayHandleBasic<BaseComponentType> dest;
|
||||
dest.Allocate(numValues);
|
||||
@ -78,10 +78,10 @@ template <typename S>
|
||||
struct ArrayExtractComponentImpl : ArrayExtractComponentImplInefficient
|
||||
{
|
||||
template <typename T>
|
||||
vtkm::cont::ArrayHandleStride<typename vtkm::internal::SafeVecTraits<T>::BaseComponentType>
|
||||
operator()(const vtkm::cont::ArrayHandle<T, S>& src,
|
||||
vtkm::IdComponent componentIndex,
|
||||
vtkm::CopyFlag allowCopy) const
|
||||
vtkm::cont::ArrayHandleStride<typename vtkm::VecTraits<T>::BaseComponentType> operator()(
|
||||
const vtkm::cont::ArrayHandle<T, S>& src,
|
||||
vtkm::IdComponent componentIndex,
|
||||
vtkm::CopyFlag allowCopy) const
|
||||
{
|
||||
// This is the slow "default" implementation. ArrayHandle implementations should provide
|
||||
// more efficient overloads where applicable.
|
||||
@ -93,15 +93,13 @@ template <>
|
||||
struct ArrayExtractComponentImpl<vtkm::cont::StorageTagStride>
|
||||
{
|
||||
template <typename T>
|
||||
vtkm::cont::ArrayHandleStride<typename vtkm::internal::SafeVecTraits<T>::BaseComponentType>
|
||||
operator()(const vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagStride>& src,
|
||||
vtkm::IdComponent componentIndex,
|
||||
vtkm::CopyFlag allowCopy) const
|
||||
vtkm::cont::ArrayHandleStride<typename vtkm::VecTraits<T>::BaseComponentType> operator()(
|
||||
const vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagStride>& src,
|
||||
vtkm::IdComponent componentIndex,
|
||||
vtkm::CopyFlag allowCopy) const
|
||||
{
|
||||
return this->DoExtract(src,
|
||||
componentIndex,
|
||||
allowCopy,
|
||||
typename vtkm::internal::SafeVecTraits<T>::HasMultipleComponents{});
|
||||
return this->DoExtract(
|
||||
src, componentIndex, allowCopy, typename vtkm::VecTraits<T>::HasMultipleComponents{});
|
||||
}
|
||||
|
||||
private:
|
||||
@ -112,7 +110,7 @@ private:
|
||||
vtkm::VecTraitsTagSingleComponent) const
|
||||
{
|
||||
VTKM_ASSERT(componentIndex == 0);
|
||||
using VTraits = vtkm::internal::SafeVecTraits<T>;
|
||||
using VTraits = vtkm::VecTraits<T>;
|
||||
using TBase = typename VTraits::BaseComponentType;
|
||||
VTKM_STATIC_ASSERT(VTraits::NUM_COMPONENTS == 1);
|
||||
|
||||
@ -135,7 +133,7 @@ private:
|
||||
vtkm::CopyFlag allowCopy,
|
||||
vtkm::VecTraitsTagMultipleComponents) const
|
||||
{
|
||||
using VTraits = vtkm::internal::SafeVecTraits<VecType>;
|
||||
using VTraits = vtkm::VecTraits<VecType>;
|
||||
using T = typename VTraits::ComponentType;
|
||||
constexpr vtkm::IdComponent N = VTraits::NUM_COMPONENTS;
|
||||
|
||||
@ -254,10 +252,10 @@ using ArrayExtractComponentIsInefficient = typename std::is_base_of<
|
||||
/// `vtkm::cont::internal::ArrayExtractComponentImpl`.
|
||||
///
|
||||
template <typename T, typename S>
|
||||
vtkm::cont::ArrayHandleStride<typename vtkm::internal::SafeVecTraits<T>::BaseComponentType>
|
||||
ArrayExtractComponent(const vtkm::cont::ArrayHandle<T, S>& src,
|
||||
vtkm::IdComponent componentIndex,
|
||||
vtkm::CopyFlag allowCopy = vtkm::CopyFlag::On)
|
||||
vtkm::cont::ArrayHandleStride<typename vtkm::VecTraits<T>::BaseComponentType> ArrayExtractComponent(
|
||||
const vtkm::cont::ArrayHandle<T, S>& src,
|
||||
vtkm::IdComponent componentIndex,
|
||||
vtkm::CopyFlag allowCopy = vtkm::CopyFlag::On)
|
||||
{
|
||||
return internal::ArrayExtractComponentImpl<S>{}(src, componentIndex, allowCopy);
|
||||
}
|
||||
|
@ -120,9 +120,6 @@ VTKM_CONT void ArrayGetValues(const vtkm::cont::ArrayHandle<vtkm::Id, SIds>& ids
|
||||
const vtkm::cont::ArrayHandle<T, SData>& data,
|
||||
vtkm::cont::ArrayHandle<T, SOut>& output)
|
||||
{
|
||||
VTKM_STATIC_ASSERT_MSG(
|
||||
vtkm::HasVecTraits<T>::value,
|
||||
"ArrayGetValues can only be used with arrays containing value types with VecTraits defined.");
|
||||
using DataArrayHandle = vtkm::cont::ArrayHandle<T, SData>;
|
||||
using InefficientExtract =
|
||||
vtkm::cont::internal::ArrayExtractComponentIsInefficient<DataArrayHandle>;
|
||||
|
@ -752,9 +752,9 @@ VTKM_NEVER_EXPORT VTKM_CONT inline void printSummary_ArrayHandle_Value(
|
||||
std::ostream& out,
|
||||
vtkm::VecTraitsTagMultipleComponents)
|
||||
{
|
||||
using Traits = vtkm::internal::SafeVecTraits<T>;
|
||||
using Traits = vtkm::VecTraits<T>;
|
||||
using ComponentType = typename Traits::ComponentType;
|
||||
using IsVecOfVec = typename vtkm::internal::SafeVecTraits<ComponentType>::HasMultipleComponents;
|
||||
using IsVecOfVec = typename vtkm::VecTraits<ComponentType>::HasMultipleComponents;
|
||||
vtkm::IdComponent numComponents = Traits::GetNumberOfComponents(value);
|
||||
out << "(";
|
||||
printSummary_ArrayHandle_Value(Traits::GetComponent(value, 0), out, IsVecOfVec());
|
||||
@ -774,10 +774,10 @@ VTKM_NEVER_EXPORT VTKM_CONT inline void printSummary_ArrayHandle_Value(
|
||||
{
|
||||
out << "{";
|
||||
printSummary_ArrayHandle_Value(
|
||||
value.first, out, typename vtkm::internal::SafeVecTraits<T1>::HasMultipleComponents());
|
||||
value.first, out, typename vtkm::VecTraits<T1>::HasMultipleComponents());
|
||||
out << ",";
|
||||
printSummary_ArrayHandle_Value(
|
||||
value.second, out, typename vtkm::internal::SafeVecTraits<T2>::HasMultipleComponents());
|
||||
value.second, out, typename vtkm::VecTraits<T2>::HasMultipleComponents());
|
||||
out << "}";
|
||||
}
|
||||
|
||||
@ -793,7 +793,7 @@ VTKM_NEVER_EXPORT VTKM_CONT inline void printSummary_ArrayHandle(
|
||||
{
|
||||
using ArrayType = vtkm::cont::ArrayHandle<T, StorageT>;
|
||||
using PortalType = typename ArrayType::ReadPortalType;
|
||||
using IsVec = typename vtkm::internal::SafeVecTraits<T>::HasMultipleComponents;
|
||||
using IsVec = typename vtkm::VecTraits<T>::HasMultipleComponents;
|
||||
|
||||
vtkm::Id sz = array.GetNumberOfValues();
|
||||
|
||||
|
@ -11,6 +11,8 @@
|
||||
#define vtk_m_cont_ArrayHandleCartesianProduct_h
|
||||
|
||||
#include <vtkm/Assert.h>
|
||||
#include <vtkm/Range.h>
|
||||
#include <vtkm/VecTraits.h>
|
||||
|
||||
#include <vtkm/cont/ArrayExtractComponent.h>
|
||||
#include <vtkm/cont/ArrayHandle.h>
|
||||
@ -486,6 +488,77 @@ struct ArrayExtractComponentImpl<vtkm::cont::StorageTagCartesianProduct<STs...>>
|
||||
}
|
||||
};
|
||||
|
||||
template <typename S>
|
||||
struct ArrayRangeComputeImpl;
|
||||
|
||||
template <typename ST1, typename ST2, typename ST3>
|
||||
struct VTKM_CONT_EXPORT ArrayRangeComputeImpl<vtkm::cont::StorageTagCartesianProduct<ST1, ST2, ST3>>
|
||||
{
|
||||
template <typename T>
|
||||
VTKM_CONT vtkm::cont::ArrayHandle<vtkm::Range> operator()(
|
||||
const vtkm::cont::ArrayHandle<vtkm::Vec<T, 3>,
|
||||
vtkm::cont::StorageTagCartesianProduct<ST1, ST2, ST3>>& input_,
|
||||
vtkm::cont::DeviceAdapterId device) const
|
||||
{
|
||||
vtkm::cont::ArrayHandle<vtkm::Range> result;
|
||||
result.Allocate(3);
|
||||
auto resultPortal = result.WritePortal();
|
||||
|
||||
const vtkm::cont::ArrayHandleCartesianProduct<vtkm::cont::ArrayHandle<T, ST1>,
|
||||
vtkm::cont::ArrayHandle<T, ST2>,
|
||||
vtkm::cont::ArrayHandle<T, ST3>>& input = input_;
|
||||
vtkm::cont::ArrayHandle<vtkm::Range> componentRangeArray;
|
||||
|
||||
vtkm::IdComponent index = 0;
|
||||
vtkm::cont::ArrayHandle<T, ST1> firstArray = input.GetFirstArray();
|
||||
componentRangeArray = vtkm::cont::internal::ArrayRangeComputeImpl<ST1>{}(firstArray, device);
|
||||
vtkm::Id numSubComponents = componentRangeArray.GetNumberOfValues();
|
||||
if (numSubComponents > 1)
|
||||
{
|
||||
result.Allocate(result.GetNumberOfValues() + numSubComponents - 1, vtkm::CopyFlag::On);
|
||||
resultPortal = result.WritePortal();
|
||||
}
|
||||
auto componentRangePortal = componentRangeArray.ReadPortal();
|
||||
for (vtkm::IdComponent subComponent = 0; subComponent < numSubComponents; ++subComponent)
|
||||
{
|
||||
resultPortal.Set(index, componentRangePortal.Get(subComponent));
|
||||
++index;
|
||||
}
|
||||
|
||||
vtkm::cont::ArrayHandle<T, ST2> secondArray = input.GetSecondArray();
|
||||
componentRangeArray = vtkm::cont::internal::ArrayRangeComputeImpl<ST2>{}(secondArray, device);
|
||||
numSubComponents = componentRangeArray.GetNumberOfValues();
|
||||
if (numSubComponents > 1)
|
||||
{
|
||||
result.Allocate(result.GetNumberOfValues() + numSubComponents - 1, vtkm::CopyFlag::On);
|
||||
resultPortal = result.WritePortal();
|
||||
}
|
||||
componentRangePortal = componentRangeArray.ReadPortal();
|
||||
for (vtkm::IdComponent subComponent = 0; subComponent < numSubComponents; ++subComponent)
|
||||
{
|
||||
resultPortal.Set(index, componentRangePortal.Get(subComponent));
|
||||
++index;
|
||||
}
|
||||
|
||||
vtkm::cont::ArrayHandle<T, ST3> thirdArray = input.GetThirdArray();
|
||||
componentRangeArray = vtkm::cont::internal::ArrayRangeComputeImpl<ST3>{}(thirdArray, device);
|
||||
numSubComponents = componentRangeArray.GetNumberOfValues();
|
||||
if (numSubComponents > 1)
|
||||
{
|
||||
result.Allocate(result.GetNumberOfValues() + numSubComponents - 1, vtkm::CopyFlag::On);
|
||||
resultPortal = result.WritePortal();
|
||||
}
|
||||
componentRangePortal = componentRangeArray.ReadPortal();
|
||||
for (vtkm::IdComponent subComponent = 0; subComponent < numSubComponents; ++subComponent)
|
||||
{
|
||||
resultPortal.Set(index, componentRangePortal.Get(subComponent));
|
||||
++index;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
}
|
||||
|
@ -12,6 +12,9 @@
|
||||
|
||||
#include <vtkm/cont/ArrayHandleImplicit.h>
|
||||
|
||||
#include <vtkm/Range.h>
|
||||
#include <vtkm/VecFlat.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace cont
|
||||
@ -90,6 +93,36 @@ vtkm::cont::ArrayHandleConstant<T> make_ArrayHandleConstant(T value, vtkm::Id nu
|
||||
{
|
||||
return vtkm::cont::ArrayHandleConstant<T>(value, numberOfValues);
|
||||
}
|
||||
|
||||
namespace internal
|
||||
{
|
||||
|
||||
template <typename S>
|
||||
struct ArrayRangeComputeImpl;
|
||||
|
||||
template <>
|
||||
struct VTKM_CONT_EXPORT ArrayRangeComputeImpl<vtkm::cont::StorageTagConstant>
|
||||
{
|
||||
template <typename T>
|
||||
VTKM_CONT vtkm::cont::ArrayHandle<vtkm::Range> operator()(
|
||||
const vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagConstant>& input,
|
||||
vtkm::cont::DeviceAdapterId) const
|
||||
{
|
||||
auto value = vtkm::make_VecFlat(input.ReadPortal().Get(0));
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Range> result;
|
||||
result.Allocate(value.GetNumberOfComponents());
|
||||
auto resultPortal = result.WritePortal();
|
||||
for (vtkm::IdComponent index = 0; index < value.GetNumberOfComponents(); ++index)
|
||||
{
|
||||
resultPortal.Set(index, vtkm::Range{ value[index], value[index] });
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
}
|
||||
} // vtkm::cont
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include <vtkm/cont/ArrayHandleImplicit.h>
|
||||
|
||||
#include <vtkm/Range.h>
|
||||
#include <vtkm/TypeTraits.h>
|
||||
#include <vtkm/VecTraits.h>
|
||||
|
||||
@ -76,27 +77,17 @@ private:
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <typename T, typename UseVecTraits = vtkm::HasVecTraits<T>>
|
||||
struct CanCountImpl;
|
||||
|
||||
template <typename T>
|
||||
struct CanCountImpl<T, std::false_type>
|
||||
{
|
||||
using TTraits = vtkm::TypeTraits<T>;
|
||||
static constexpr bool IsNumeric =
|
||||
!std::is_same<typename TTraits::NumericTag, vtkm::TypeTraitsUnknownTag>::value;
|
||||
|
||||
static constexpr bool value = IsNumeric;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct CanCountImpl<T, std::true_type>
|
||||
struct CanCountImpl
|
||||
{
|
||||
using VTraits = vtkm::VecTraits<T>;
|
||||
using BaseType = typename VTraits::BaseComponentType;
|
||||
using TTraits = vtkm::TypeTraits<BaseType>;
|
||||
static constexpr bool IsNumeric =
|
||||
!std::is_same<typename TTraits::NumericTag, vtkm::TypeTraitsUnknownTag>::value;
|
||||
static constexpr bool IsBool = std::is_same<BaseType, bool>::value;
|
||||
|
||||
static constexpr bool value = CanCountImpl<BaseType, std::false_type>::value && !IsBool;
|
||||
static constexpr bool value = IsNumeric && !IsBool;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
@ -152,6 +143,52 @@ make_ArrayHandleCounting(CountingValueType start, CountingValueType step, vtkm::
|
||||
{
|
||||
return vtkm::cont::ArrayHandleCounting<CountingValueType>(start, step, length);
|
||||
}
|
||||
|
||||
namespace internal
|
||||
{
|
||||
|
||||
template <typename S>
|
||||
struct ArrayRangeComputeImpl;
|
||||
|
||||
template <>
|
||||
struct VTKM_CONT_EXPORT ArrayRangeComputeImpl<vtkm::cont::StorageTagCounting>
|
||||
{
|
||||
template <typename T>
|
||||
VTKM_CONT vtkm::cont::ArrayHandle<vtkm::Range> operator()(
|
||||
const vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagCounting>& input,
|
||||
vtkm::cont::DeviceAdapterId) const
|
||||
{
|
||||
using Traits = vtkm::VecTraits<T>;
|
||||
vtkm::cont::ArrayHandle<vtkm::Range> result;
|
||||
result.Allocate(Traits::NUM_COMPONENTS);
|
||||
auto portal = result.WritePortal();
|
||||
if (portal.GetNumberOfValues() > 0)
|
||||
{
|
||||
T first = input.ReadPortal().Get(0);
|
||||
T last = input.ReadPortal().Get(input.GetNumberOfValues() - 1);
|
||||
for (vtkm::IdComponent cIndex = 0; cIndex < Traits::NUM_COMPONENTS; ++cIndex)
|
||||
{
|
||||
auto firstComponent = Traits::GetComponent(first, cIndex);
|
||||
auto lastComponent = Traits::GetComponent(last, cIndex);
|
||||
portal.Set(cIndex,
|
||||
vtkm::Range(vtkm::Min(firstComponent, lastComponent),
|
||||
vtkm::Max(firstComponent, lastComponent)));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Array is empty
|
||||
for (vtkm::IdComponent cIndex = 0; cIndex < Traits::NUM_COMPONENTS; ++cIndex)
|
||||
{
|
||||
portal.Set(cIndex, vtkm::Range{});
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
}
|
||||
} // namespace vtkm::cont
|
||||
|
||||
|
@ -47,7 +47,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
/// Copy constructor for any other ArrayPortalConcatenate with a portal type
|
||||
/// Copy constructor for any other ArrayPortalGroupVecVariable with a portal type
|
||||
/// that can be copied to this portal type. This allows us to do any type
|
||||
/// casting that the portals do (like the non-const to const cast).
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
@ -77,12 +77,19 @@ public:
|
||||
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
VTKM_EXEC_CONT
|
||||
void Set(vtkm::Id vtkmNotUsed(index), const ValueType& vtkmNotUsed(value)) const
|
||||
void Set(vtkm::Id index, const ValueType& value) const
|
||||
{
|
||||
// The ValueType (VecFromPortal) operates on demand. Thus, if you set
|
||||
// something in the value, it has already been passed to the array. Perhaps
|
||||
// we should check to make sure that the value used matches the location
|
||||
// you are trying to set in the array, but we don't do that.
|
||||
if ((&value.GetPortal() == &this->ComponentsPortal) &&
|
||||
(value.GetOffset() == this->OffsetsPortal.Get(index)))
|
||||
{
|
||||
// The ValueType (VecFromPortal) operates on demand. Thus, if you set
|
||||
// something in the value, it has already been passed to the array.
|
||||
}
|
||||
else
|
||||
{
|
||||
// The value comes from somewhere else. Copy data in.
|
||||
this->Get(index) = value;
|
||||
}
|
||||
}
|
||||
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
@ -237,13 +244,15 @@ public:
|
||||
/// it contains three values of Vec-like objects with the data [0,1,2,3],
|
||||
/// [4,5], and [6,7,8].
|
||||
///
|
||||
/// Note that this version of \c ArrayHandle breaks some of the assumptions
|
||||
/// about \c ArrayHandle a little bit. Typically, there is exactly one type for
|
||||
/// every value in the array, and this value is also the same between the
|
||||
/// control and execution environment. However, this class uses \c
|
||||
/// VecFromPortal it implement a Vec-like class that has a variable number of
|
||||
/// values, and this type can change between control and execution
|
||||
/// environments.
|
||||
/// Note that caution should be used with `ArrayHandleRuntimeVec` because the
|
||||
/// size of the `Vec` values is not known at compile time. Thus, the value
|
||||
/// type of this array is forced to a special `VecFromPortal` class that can cause
|
||||
/// surprises if treated as a `Vec`. In particular, the static `NUM_COMPONENTS`
|
||||
/// expression does not exist. Furthermore, new variables of type `VecFromPortal`
|
||||
/// cannot be created. This means that simple operators like `+` will not work
|
||||
/// because they require an intermediate object to be created. (Equal operators
|
||||
/// like `+=` do work because they are given an existing variable to place the
|
||||
/// output.)
|
||||
///
|
||||
/// The offsets array is often derived from a list of sizes for each of the
|
||||
/// entries. You can use the convenience function \c
|
||||
|
@ -10,6 +10,7 @@
|
||||
#ifndef vtk_m_cont_ArrayHandleIndex_h
|
||||
#define vtk_m_cont_ArrayHandleIndex_h
|
||||
|
||||
#include <vtkm/Range.h>
|
||||
#include <vtkm/cont/ArrayHandleImplicit.h>
|
||||
|
||||
namespace vtkm
|
||||
@ -71,6 +72,29 @@ VTKM_CONT inline vtkm::cont::ArrayHandleIndex make_ArrayHandleIndex(vtkm::Id len
|
||||
{
|
||||
return vtkm::cont::ArrayHandleIndex(length);
|
||||
}
|
||||
|
||||
namespace internal
|
||||
{
|
||||
|
||||
template <typename S>
|
||||
struct ArrayRangeComputeImpl;
|
||||
|
||||
template <>
|
||||
struct VTKM_CONT_EXPORT ArrayRangeComputeImpl<vtkm::cont::StorageTagIndex>
|
||||
{
|
||||
VTKM_CONT vtkm::cont::ArrayHandle<vtkm::Range> operator()(
|
||||
const vtkm::cont::ArrayHandle<vtkm::Id, vtkm::cont::StorageTagIndex>& input,
|
||||
vtkm::cont::DeviceAdapterId) const
|
||||
{
|
||||
vtkm::cont::ArrayHandle<vtkm::Range> result;
|
||||
result.Allocate(1);
|
||||
result.WritePortal().Set(0, vtkm::Range(0, input.GetNumberOfValues() - 1));
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
}
|
||||
} // namespace vtkm::cont
|
||||
|
||||
|
@ -15,8 +15,6 @@
|
||||
#include <vtkm/cont/ArrayHandleStride.h>
|
||||
#include <vtkm/cont/DeviceAdapterTag.h>
|
||||
|
||||
#include <vtkm/VecVariable.h>
|
||||
|
||||
#include <vtkm/internal/ArrayPortalValueReference.h>
|
||||
|
||||
namespace vtkm
|
||||
@ -89,7 +87,7 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T, typename = typename std::enable_if<vtkm::HasVecTraits<T>::value>::type>
|
||||
template <typename T>
|
||||
VTKM_EXEC_CONT RecombineVec& operator=(const T& src)
|
||||
{
|
||||
this->DoCopy(src);
|
||||
@ -106,7 +104,7 @@ public:
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T, typename = typename std::enable_if<vtkm::HasVecTraits<T>::value>::type>
|
||||
template <typename T>
|
||||
VTKM_EXEC_CONT RecombineVec& operator+=(const T& src)
|
||||
{
|
||||
using VTraits = vtkm::VecTraits<T>;
|
||||
@ -117,7 +115,7 @@ public:
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
template <typename T, typename = typename std::enable_if<vtkm::HasVecTraits<T>::value>::type>
|
||||
template <typename T>
|
||||
VTKM_EXEC_CONT RecombineVec& operator-=(const T& src)
|
||||
{
|
||||
using VTraits = vtkm::VecTraits<T>;
|
||||
@ -128,7 +126,7 @@ public:
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
template <typename T, typename = typename std::enable_if<vtkm::HasVecTraits<T>::value>::type>
|
||||
template <typename T>
|
||||
VTKM_EXEC_CONT RecombineVec& operator*=(const T& src)
|
||||
{
|
||||
using VTraits = vtkm::VecTraits<T>;
|
||||
@ -139,7 +137,7 @@ public:
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
template <typename T, typename = typename std::enable_if<vtkm::HasVecTraits<T>::value>::type>
|
||||
template <typename T>
|
||||
VTKM_EXEC_CONT RecombineVec& operator/=(const T& src)
|
||||
{
|
||||
using VTraits = vtkm::VecTraits<T>;
|
||||
@ -150,7 +148,7 @@ public:
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
template <typename T, typename = typename std::enable_if<vtkm::HasVecTraits<T>::value>::type>
|
||||
template <typename T>
|
||||
VTKM_EXEC_CONT RecombineVec& operator%=(const T& src)
|
||||
{
|
||||
using VTraits = vtkm::VecTraits<T>;
|
||||
@ -161,7 +159,7 @@ public:
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
template <typename T, typename = typename std::enable_if<vtkm::HasVecTraits<T>::value>::type>
|
||||
template <typename T>
|
||||
VTKM_EXEC_CONT RecombineVec& operator&=(const T& src)
|
||||
{
|
||||
using VTraits = vtkm::VecTraits<T>;
|
||||
@ -172,7 +170,7 @@ public:
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
template <typename T, typename = typename std::enable_if<vtkm::HasVecTraits<T>::value>::type>
|
||||
template <typename T>
|
||||
VTKM_EXEC_CONT RecombineVec& operator|=(const T& src)
|
||||
{
|
||||
using VTraits = vtkm::VecTraits<T>;
|
||||
@ -183,7 +181,7 @@ public:
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
template <typename T, typename = typename std::enable_if<vtkm::HasVecTraits<T>::value>::type>
|
||||
template <typename T>
|
||||
VTKM_EXEC_CONT RecombineVec& operator^=(const T& src)
|
||||
{
|
||||
using VTraits = vtkm::VecTraits<T>;
|
||||
@ -194,7 +192,7 @@ public:
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
template <typename T, typename = typename std::enable_if<vtkm::HasVecTraits<T>::value>::type>
|
||||
template <typename T>
|
||||
VTKM_EXEC_CONT RecombineVec& operator>>=(const T& src)
|
||||
{
|
||||
using VTraits = vtkm::VecTraits<T>;
|
||||
@ -205,7 +203,7 @@ public:
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
template <typename T, typename = typename std::enable_if<vtkm::HasVecTraits<T>::value>::type>
|
||||
template <typename T>
|
||||
VTKM_EXEC_CONT RecombineVec& operator<<=(const T& src)
|
||||
{
|
||||
using VTraits = vtkm::VecTraits<T>;
|
||||
@ -437,7 +435,7 @@ public:
|
||||
using ReadPortalType = vtkm::internal::ArrayPortalRecombineVec<ReadWritePortal>;
|
||||
using WritePortalType = vtkm::internal::ArrayPortalRecombineVec<ReadWritePortal>;
|
||||
|
||||
VTKM_CONT static vtkm::IdComponent NumberOfComponents(
|
||||
VTKM_CONT static vtkm::IdComponent GetNumberOfComponents(
|
||||
const std::vector<vtkm::cont::internal::Buffer>& buffers)
|
||||
{
|
||||
return static_cast<vtkm::IdComponent>(
|
||||
@ -455,7 +453,7 @@ public:
|
||||
vtkm::CopyFlag preserve,
|
||||
vtkm::cont::Token& token)
|
||||
{
|
||||
vtkm::IdComponent numComponents = NumberOfComponents(buffers);
|
||||
vtkm::IdComponent numComponents = GetNumberOfComponents(buffers);
|
||||
for (vtkm::IdComponent component = 0; component < numComponents; ++component)
|
||||
{
|
||||
SourceStorage::ResizeBuffers(
|
||||
@ -477,7 +475,7 @@ public:
|
||||
vtkm::cont::DeviceAdapterId device,
|
||||
vtkm::cont::Token& token)
|
||||
{
|
||||
vtkm::IdComponent numComponents = NumberOfComponents(buffers);
|
||||
vtkm::IdComponent numComponents = GetNumberOfComponents(buffers);
|
||||
|
||||
// The array portal needs a runtime-allocated array of portals for each component.
|
||||
// We use the vtkm::cont::internal::Buffer object to allow us to allocate memory on the
|
||||
@ -515,7 +513,7 @@ public:
|
||||
vtkm::cont::DeviceAdapterId device,
|
||||
vtkm::cont::Token& token)
|
||||
{
|
||||
vtkm::IdComponent numComponents = NumberOfComponents(buffers);
|
||||
vtkm::IdComponent numComponents = GetNumberOfComponents(buffers);
|
||||
|
||||
// The array portal needs a runtime-allocated array of portals for each component.
|
||||
// We use the vtkm::cont::internal::Buffer object to allow us to allocate memory on the
|
||||
@ -586,9 +584,13 @@ public:
|
||||
///
|
||||
/// Note that caution should be used with `ArrayHandleRecombineVec` because the
|
||||
/// size of the `Vec` values is not known at compile time. Thus, the value
|
||||
/// type of this array is forced to a `VecVariable`, which can cause surprises
|
||||
/// if treated as a `Vec`. In particular, the static `NUM_COMPONENTS` expression
|
||||
/// does not exist.
|
||||
/// type of this array is forced to a special `RecombineVec` class that can cause
|
||||
/// surprises if treated as a `Vec`. In particular, the static `NUM_COMPONENTS`
|
||||
/// expression does not exist. Furthermore, new variables of type `RecombineVec`
|
||||
/// cannot be created. This means that simple operators like `+` will not work
|
||||
/// because they require an intermediate object to be created. (Equal operators
|
||||
/// like `+=` do work because they are given an existing variable to place the
|
||||
/// output.)
|
||||
///
|
||||
template <typename ComponentType>
|
||||
class ArrayHandleRecombineVec
|
||||
@ -608,7 +610,7 @@ private:
|
||||
public:
|
||||
vtkm::IdComponent GetNumberOfComponents() const
|
||||
{
|
||||
return StorageType::NumberOfComponents(this->GetBuffers());
|
||||
return StorageType::GetNumberOfComponents(this->GetBuffers());
|
||||
}
|
||||
|
||||
vtkm::cont::ArrayHandleStride<ComponentType> GetComponentArray(
|
||||
|
504
vtkm/cont/ArrayHandleRuntimeVec.h
Normal file
504
vtkm/cont/ArrayHandleRuntimeVec.h
Normal file
@ -0,0 +1,504 @@
|
||||
//============================================================================
|
||||
// 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_cont_ArrayHandleRuntimeVec_h
|
||||
#define vtk_m_cont_ArrayHandleRuntimeVec_h
|
||||
|
||||
#include <vtkm/cont/ArrayExtractComponent.h>
|
||||
#include <vtkm/cont/ArrayHandle.h>
|
||||
#include <vtkm/cont/ArrayHandleBasic.h>
|
||||
#include <vtkm/cont/ArrayPortal.h>
|
||||
#include <vtkm/cont/ErrorBadType.h>
|
||||
|
||||
#include <vtkm/Assert.h>
|
||||
#include <vtkm/StaticAssert.h>
|
||||
#include <vtkm/VecFromPortal.h>
|
||||
#include <vtkm/VecTraits.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace internal
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
struct UnrollVecImpl
|
||||
{
|
||||
using type = vtkm::Vec<T, 1>;
|
||||
};
|
||||
|
||||
template <typename T, vtkm::IdComponent N>
|
||||
struct UnrollVecImpl<vtkm::Vec<T, N>>
|
||||
{
|
||||
using subtype = typename UnrollVecImpl<T>::type;
|
||||
using type = vtkm::Vec<typename subtype::ComponentType, subtype::NUM_COMPONENTS * N>;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
// A helper class that unrolls a nested `Vec` to a single layer `Vec`. This is similar
|
||||
// to `vtkm::VecFlat`, except that this only flattens `vtkm::Vec<T,N>` objects, and not
|
||||
// any other `Vec`-like objects. The reason is that a `vtkm::Vec<T,N>` is the same as N
|
||||
// consecutive `T` objects whereas the same may not be said about other `Vec`-like objects.
|
||||
template <typename T>
|
||||
using UnrollVec = typename detail::UnrollVecImpl<T>::type;
|
||||
|
||||
template <typename ComponentsPortalType>
|
||||
class VTKM_ALWAYS_EXPORT ArrayPortalRuntimeVec
|
||||
{
|
||||
public:
|
||||
using ComponentType = typename std::remove_const<typename ComponentsPortalType::ValueType>::type;
|
||||
using ValueType = vtkm::VecFromPortal<ComponentsPortalType>;
|
||||
|
||||
ArrayPortalRuntimeVec() = default;
|
||||
|
||||
VTKM_EXEC_CONT ArrayPortalRuntimeVec(const ComponentsPortalType& componentsPortal,
|
||||
vtkm::IdComponent numComponents)
|
||||
: ComponentsPortal(componentsPortal)
|
||||
, NumberOfComponents(numComponents)
|
||||
{
|
||||
}
|
||||
|
||||
/// Copy constructor for any other ArrayPortalRuntimeVec with a portal type
|
||||
/// that can be copied to this portal type. This allows us to do any type
|
||||
/// casting that the portals do (like the non-const to const cast).
|
||||
template <typename OtherComponentsPortalType>
|
||||
VTKM_EXEC_CONT ArrayPortalRuntimeVec(const ArrayPortalRuntimeVec<OtherComponentsPortalType>& src)
|
||||
: ComponentsPortal(src.GetComponentsPortal())
|
||||
, NumberOfComponents(src.GetNumberOfComponents())
|
||||
{
|
||||
}
|
||||
|
||||
VTKM_EXEC_CONT vtkm::Id GetNumberOfValues() const
|
||||
{
|
||||
return this->ComponentsPortal.GetNumberOfValues() / this->NumberOfComponents;
|
||||
}
|
||||
|
||||
VTKM_EXEC_CONT ValueType Get(vtkm::Id index) const
|
||||
{
|
||||
return ValueType(
|
||||
this->ComponentsPortal, this->NumberOfComponents, index * this->NumberOfComponents);
|
||||
}
|
||||
|
||||
VTKM_EXEC_CONT void Set(vtkm::Id index, const ValueType& value) const
|
||||
{
|
||||
if ((&value.GetPortal() == &this->ComponentsPortal) &&
|
||||
(value.GetOffset() == (index * this->NumberOfComponents)))
|
||||
{
|
||||
// The ValueType (VecFromPortal) operates on demand. Thus, if you set
|
||||
// something in the value, it has already been passed to the array.
|
||||
}
|
||||
else
|
||||
{
|
||||
// The value comes from somewhere else. Copy data in.
|
||||
this->Get(index) = value;
|
||||
}
|
||||
}
|
||||
|
||||
VTKM_EXEC_CONT const ComponentsPortalType& GetComponentsPortal() const
|
||||
{
|
||||
return this->ComponentsPortal;
|
||||
}
|
||||
|
||||
VTKM_EXEC_CONT vtkm::IdComponent GetNumberOfComponents() const
|
||||
{
|
||||
return this->NumberOfComponents;
|
||||
}
|
||||
|
||||
private:
|
||||
ComponentsPortalType ComponentsPortal;
|
||||
vtkm::IdComponent NumberOfComponents = 0;
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace vtkm::internal
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace cont
|
||||
{
|
||||
|
||||
struct VTKM_ALWAYS_EXPORT StorageTagRuntimeVec
|
||||
{
|
||||
};
|
||||
|
||||
namespace internal
|
||||
{
|
||||
|
||||
template <typename ComponentsPortal>
|
||||
class Storage<vtkm::VecFromPortal<ComponentsPortal>, vtkm::cont::StorageTagRuntimeVec>
|
||||
{
|
||||
using ComponentType = typename ComponentsPortal::ValueType;
|
||||
using ComponentsStorage =
|
||||
vtkm::cont::internal::Storage<ComponentType, vtkm::cont::StorageTagBasic>;
|
||||
|
||||
VTKM_STATIC_ASSERT_MSG(
|
||||
vtkm::VecTraits<ComponentType>::NUM_COMPONENTS == 1,
|
||||
"ArrayHandleRuntimeVec only supports scalars grouped into a single Vec. Nested Vecs can "
|
||||
"still be used with ArrayHandleRuntimeVec. The values are treated as flattened (like "
|
||||
"with VecFlat).");
|
||||
|
||||
using ComponentsArray = vtkm::cont::ArrayHandle<ComponentType, StorageTagBasic>;
|
||||
|
||||
VTKM_STATIC_ASSERT_MSG(
|
||||
(std::is_same<ComponentsPortal, typename ComponentsStorage::WritePortalType>::value),
|
||||
"Used invalid ComponentsPortal type with expected ComponentsStorageTag.");
|
||||
|
||||
struct Info
|
||||
{
|
||||
vtkm::IdComponent NumberOfComponents;
|
||||
};
|
||||
|
||||
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> ComponentsBuffers(
|
||||
const std::vector<vtkm::cont::internal::Buffer>& buffers)
|
||||
{
|
||||
return std::vector<vtkm::cont::internal::Buffer>(buffers.begin() + 1, buffers.end());
|
||||
}
|
||||
|
||||
public:
|
||||
using ReadPortalType =
|
||||
vtkm::internal::ArrayPortalRuntimeVec<typename ComponentsStorage::ReadPortalType>;
|
||||
using WritePortalType =
|
||||
vtkm::internal::ArrayPortalRuntimeVec<typename ComponentsStorage::WritePortalType>;
|
||||
|
||||
VTKM_CONT static vtkm::IdComponent GetNumberOfComponents(
|
||||
const std::vector<vtkm::cont::internal::Buffer>& buffers)
|
||||
{
|
||||
return buffers[0].GetMetaData<Info>().NumberOfComponents;
|
||||
}
|
||||
|
||||
VTKM_CONT static vtkm::Id GetNumberOfValues(
|
||||
const std::vector<vtkm::cont::internal::Buffer>& buffers)
|
||||
{
|
||||
return ComponentsStorage::GetNumberOfValues(ComponentsBuffers(buffers)) /
|
||||
GetNumberOfComponents(buffers);
|
||||
}
|
||||
|
||||
VTKM_CONT static void ResizeBuffers(vtkm::Id numValues,
|
||||
const std::vector<vtkm::cont::internal::Buffer>& buffers,
|
||||
vtkm::CopyFlag preserve,
|
||||
vtkm::cont::Token& token)
|
||||
{
|
||||
ComponentsStorage::ResizeBuffers(
|
||||
numValues * GetNumberOfComponents(buffers), ComponentsBuffers(buffers), preserve, token);
|
||||
}
|
||||
|
||||
VTKM_CONT static void Fill(const std::vector<vtkm::cont::internal::Buffer>&,
|
||||
const vtkm::VecFromPortal<ComponentsPortal>&,
|
||||
vtkm::Id,
|
||||
vtkm::Id,
|
||||
vtkm::cont::Token&)
|
||||
{
|
||||
throw vtkm::cont::ErrorBadType("Fill not supported for ArrayHandleRuntimeVec.");
|
||||
}
|
||||
|
||||
VTKM_CONT static ReadPortalType CreateReadPortal(
|
||||
const std::vector<vtkm::cont::internal::Buffer>& buffers,
|
||||
vtkm::cont::DeviceAdapterId device,
|
||||
vtkm::cont::Token& token)
|
||||
{
|
||||
return ReadPortalType(
|
||||
ComponentsStorage::CreateReadPortal(ComponentsBuffers(buffers), device, token),
|
||||
GetNumberOfComponents(buffers));
|
||||
}
|
||||
|
||||
VTKM_CONT static WritePortalType CreateWritePortal(
|
||||
const std::vector<vtkm::cont::internal::Buffer>& buffers,
|
||||
vtkm::cont::DeviceAdapterId device,
|
||||
vtkm::cont::Token& token)
|
||||
{
|
||||
return WritePortalType(
|
||||
ComponentsStorage::CreateWritePortal(ComponentsBuffers(buffers), device, token),
|
||||
GetNumberOfComponents(buffers));
|
||||
}
|
||||
|
||||
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers(
|
||||
vtkm::IdComponent numComponents = 1,
|
||||
const ComponentsArray& componentsArray = ComponentsArray{})
|
||||
{
|
||||
VTKM_LOG_IF_S(vtkm::cont::LogLevel::Warn,
|
||||
(componentsArray.GetNumberOfValues() % numComponents) != 0,
|
||||
"Array given to ArrayHandleRuntimeVec has size ("
|
||||
<< componentsArray.GetNumberOfValues()
|
||||
<< ") that is not divisible by the number of components selected ("
|
||||
<< numComponents << ").");
|
||||
Info info;
|
||||
info.NumberOfComponents = numComponents;
|
||||
return vtkm::cont::internal::CreateBuffers(info, componentsArray);
|
||||
}
|
||||
|
||||
VTKM_CONT static ComponentsArray GetComponentsArray(
|
||||
const std::vector<vtkm::cont::internal::Buffer>& buffers)
|
||||
{
|
||||
return ComponentsArray(ComponentsBuffers(buffers));
|
||||
}
|
||||
|
||||
VTKM_CONT static void AsArrayHandleBasic(
|
||||
const std::vector<vtkm::cont::internal::Buffer>& buffers,
|
||||
vtkm::cont::ArrayHandle<ComponentType, vtkm::cont::StorageTagBasic>& dest)
|
||||
{
|
||||
if (GetNumberOfComponents(buffers) != 1)
|
||||
{
|
||||
throw vtkm::cont::ErrorBadType(
|
||||
"Attempted to pull a scalar array from an ArrayHandleRuntime that does not hold scalars.");
|
||||
}
|
||||
dest = GetComponentsArray(buffers);
|
||||
}
|
||||
|
||||
template <vtkm::IdComponent N>
|
||||
VTKM_CONT static void AsArrayHandleBasic(
|
||||
const std::vector<vtkm::cont::internal::Buffer>& buffers,
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<ComponentType, N>, vtkm::cont::StorageTagBasic>& dest)
|
||||
{
|
||||
if (GetNumberOfComponents(buffers) != N)
|
||||
{
|
||||
throw vtkm::cont::ErrorBadType(
|
||||
"Attempted to pull an array of Vecs of the wrong size from an ArrayHandleRuntime.");
|
||||
}
|
||||
dest = vtkm::cont::ArrayHandle<vtkm::Vec<ComponentType, N>, vtkm::cont::StorageTagBasic>(
|
||||
ComponentsBuffers(buffers));
|
||||
}
|
||||
|
||||
template <typename T, vtkm::IdComponent NInner, vtkm::IdComponent NOuter>
|
||||
VTKM_CONT static void AsArrayHandleBasic(
|
||||
const std::vector<vtkm::cont::internal::Buffer>& buffers,
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Vec<T, NInner>, NOuter>, vtkm::cont::StorageTagBasic>&
|
||||
dest)
|
||||
{
|
||||
// Flatten the Vec by one level and attempt to get the array handle for that.
|
||||
vtkm::cont::ArrayHandleBasic<vtkm::Vec<T, NInner * NOuter>> squashedArray;
|
||||
AsArrayHandleBasic(buffers, squashedArray);
|
||||
// Now unsquash the array by stealling the buffers and creating an array of the right type
|
||||
dest =
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Vec<T, NInner>, NOuter>, vtkm::cont::StorageTagBasic>(
|
||||
squashedArray.GetBuffers());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
/// \brief Fancy array handle for a basic array with runtime selected vec size.
|
||||
///
|
||||
/// It is sometimes the case that you need to create an array of `Vec`s where
|
||||
/// the number of components is not known until runtime. This is problematic
|
||||
/// for normal `ArrayHandle`s because you have to specify the size of the `Vec`s
|
||||
/// as a template parameter at compile time. `ArrayHandleRuntimeVec` can be used
|
||||
/// in this case.
|
||||
///
|
||||
/// Note that caution should be used with `ArrayHandleRuntimeVec` because the
|
||||
/// size of the `Vec` values is not known at compile time. Thus, the value
|
||||
/// type of this array is forced to a special `VecFromPortal` class that can cause
|
||||
/// surprises if treated as a `Vec`. In particular, the static `NUM_COMPONENTS`
|
||||
/// expression does not exist. Furthermore, new variables of type `VecFromPortal`
|
||||
/// cannot be created. This means that simple operators like `+` will not work
|
||||
/// because they require an intermediate object to be created. (Equal operators
|
||||
/// like `+=` do work because they are given an existing variable to place the
|
||||
/// output.)
|
||||
///
|
||||
/// It is possible to provide an `ArrayHandleBasic` of the same component
|
||||
/// type as the underlying storage for this array. In this case, the array
|
||||
/// will be accessed much in the same manner as `ArrayHandleGroupVec`.
|
||||
///
|
||||
/// `ArrayHandleRuntimeVec` also allows you to convert the array to an
|
||||
/// `ArrayHandleBasic` of the appropriate `Vec` type (or `component` type).
|
||||
/// A runtime check will be performed to make sure the number of components
|
||||
/// matches.
|
||||
///
|
||||
template <typename ComponentType>
|
||||
class ArrayHandleRuntimeVec
|
||||
: public vtkm::cont::ArrayHandle<
|
||||
vtkm::VecFromPortal<typename ArrayHandleBasic<ComponentType>::WritePortalType>,
|
||||
vtkm::cont::StorageTagRuntimeVec>
|
||||
{
|
||||
public:
|
||||
VTKM_ARRAY_HANDLE_SUBCLASS(
|
||||
ArrayHandleRuntimeVec,
|
||||
(ArrayHandleRuntimeVec<ComponentType>),
|
||||
(vtkm::cont::ArrayHandle<
|
||||
vtkm::VecFromPortal<typename ArrayHandleBasic<ComponentType>::WritePortalType>,
|
||||
vtkm::cont::StorageTagRuntimeVec>));
|
||||
|
||||
private:
|
||||
using StorageType = vtkm::cont::internal::Storage<ValueType, StorageTag>;
|
||||
using ComponentsArrayType = vtkm::cont::ArrayHandle<ComponentType, StorageTagBasic>;
|
||||
|
||||
public:
|
||||
VTKM_CONT
|
||||
ArrayHandleRuntimeVec(vtkm::IdComponent numComponents,
|
||||
const ComponentsArrayType& componentsArray = ComponentsArrayType{})
|
||||
: Superclass(StorageType::CreateBuffers(numComponents, componentsArray))
|
||||
{
|
||||
}
|
||||
|
||||
VTKM_CONT vtkm::IdComponent GetNumberOfComponents() const
|
||||
{
|
||||
return StorageType::GetNumberOfComponents(this->GetBuffers());
|
||||
}
|
||||
|
||||
VTKM_CONT vtkm::cont::ArrayHandleBasic<ComponentType> GetComponentsArray() const
|
||||
{
|
||||
return StorageType::GetComponentsArray(this->GetBuffers());
|
||||
}
|
||||
|
||||
///@{
|
||||
/// \brief Converts the array to that of a basic array handle.
|
||||
///
|
||||
/// This method converts the `ArrayHandleRuntimeVec` to a simple `ArrayHandleBasic`.
|
||||
/// This is useful if the `ArrayHandleRuntimeVec` is passed to a routine that works
|
||||
/// on an array of a specific `Vec` size (or scalars). After a runtime check, the
|
||||
/// array can be converted to a typical array and used as such.
|
||||
template <typename ValueType>
|
||||
void AsArrayHandleBasic(vtkm::cont::ArrayHandle<ValueType>& array) const
|
||||
{
|
||||
StorageType::AsArrayHandleBasic(this->GetBuffers(), array);
|
||||
}
|
||||
|
||||
template <typename ArrayType>
|
||||
ArrayType AsArrayHandleBasic() const
|
||||
{
|
||||
ArrayType array;
|
||||
this->AsArrayHandleBasic(array);
|
||||
return array;
|
||||
}
|
||||
///@}
|
||||
};
|
||||
|
||||
/// \c make_ArrayHandleRuntimeVec is convenience function to generate an
|
||||
/// ArrayHandleRuntimeVec. It takes in an ArrayHandle of values and an
|
||||
/// array handle of offsets and returns an array handle with consecutive
|
||||
/// entries grouped in a Vec.
|
||||
///
|
||||
template <typename T>
|
||||
VTKM_CONT auto make_ArrayHandleRuntimeVec(
|
||||
vtkm::IdComponent numComponents,
|
||||
const vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagBasic>& componentsArray =
|
||||
vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagBasic>{})
|
||||
{
|
||||
using UnrolledVec = vtkm::internal::UnrollVec<T>;
|
||||
using ComponentType = typename UnrolledVec::ComponentType;
|
||||
|
||||
// Use some dangerous magic to convert the basic array to its base component and create
|
||||
// an ArrayHandleRuntimeVec from that.
|
||||
vtkm::cont::ArrayHandle<ComponentType, vtkm::cont::StorageTagBasic> flatComponents(
|
||||
componentsArray.GetBuffers());
|
||||
|
||||
return vtkm::cont::ArrayHandleRuntimeVec<ComponentType>(
|
||||
numComponents * UnrolledVec::NUM_COMPONENTS, flatComponents);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
VTKM_CONT auto make_ArrayHandleRuntimeVec(
|
||||
const vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagBasic>& componentsArray)
|
||||
{
|
||||
return make_ArrayHandleRuntimeVec(1, componentsArray);
|
||||
}
|
||||
|
||||
namespace internal
|
||||
{
|
||||
|
||||
template <>
|
||||
struct ArrayExtractComponentImpl<vtkm::cont::StorageTagRuntimeVec>
|
||||
{
|
||||
template <typename T>
|
||||
auto operator()(const vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagRuntimeVec>& src,
|
||||
vtkm::IdComponent componentIndex,
|
||||
vtkm::CopyFlag allowCopy) const
|
||||
{
|
||||
using ComponentType = typename T::ComponentType;
|
||||
vtkm::cont::ArrayHandleRuntimeVec<ComponentType> array{ src };
|
||||
constexpr vtkm::IdComponent NUM_SUB_COMPONENTS = vtkm::VecFlat<ComponentType>::NUM_COMPONENTS;
|
||||
vtkm::cont::ArrayHandleStride<typename vtkm::VecTraits<T>::BaseComponentType> dest =
|
||||
ArrayExtractComponentImpl<vtkm::cont::StorageTagBasic>{}(
|
||||
array.GetComponentsArray(), componentIndex % NUM_SUB_COMPONENTS, allowCopy);
|
||||
|
||||
// Adjust stride and offset to expectations of grouped values
|
||||
const vtkm::IdComponent numComponents = array.GetNumberOfComponents();
|
||||
return vtkm::cont::ArrayHandleStride<typename vtkm::VecTraits<T>::BaseComponentType>(
|
||||
dest.GetBasicArray(),
|
||||
dest.GetNumberOfValues() / numComponents,
|
||||
dest.GetStride() * numComponents,
|
||||
dest.GetOffset() + (dest.GetStride() * (componentIndex / NUM_SUB_COMPONENTS)),
|
||||
dest.GetModulo(),
|
||||
dest.GetDivisor());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
}
|
||||
} // namespace vtkm::cont
|
||||
|
||||
//=============================================================================
|
||||
// Specializations of serialization related classes
|
||||
/// @cond SERIALIZATION
|
||||
namespace vtkm
|
||||
{
|
||||
namespace cont
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
struct SerializableTypeString<vtkm::cont::ArrayHandleRuntimeVec<T>>
|
||||
{
|
||||
static VTKM_CONT const std::string& Get()
|
||||
{
|
||||
static std::string name = "AH_RuntimeVec<" + SerializableTypeString<T>::Get() + ">";
|
||||
return name;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename VecType>
|
||||
struct SerializableTypeString<vtkm::cont::ArrayHandle<VecType, vtkm::cont::StorageTagRuntimeVec>>
|
||||
: SerializableTypeString<vtkm::cont::ArrayHandleRuntimeVec<typename VecType::ComponentType>>
|
||||
{
|
||||
};
|
||||
|
||||
}
|
||||
} // vtkm::cont
|
||||
|
||||
namespace mangled_diy_namespace
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
struct Serialization<vtkm::cont::ArrayHandleRuntimeVec<T>>
|
||||
{
|
||||
private:
|
||||
using Type = vtkm::cont::ArrayHandleRuntimeVec<T>;
|
||||
using BaseType = vtkm::cont::ArrayHandle<typename Type::ValueType, typename Type::StorageTag>;
|
||||
|
||||
public:
|
||||
static VTKM_CONT void save(BinaryBuffer& bb, const BaseType& obj)
|
||||
{
|
||||
vtkmdiy::save(bb, Type(obj).GetNumberOfComponents());
|
||||
vtkmdiy::save(bb, Type(obj).GetComponentsArray());
|
||||
}
|
||||
|
||||
static VTKM_CONT void load(BinaryBuffer& bb, BaseType& obj)
|
||||
{
|
||||
vtkm::IdComponent numComponents;
|
||||
vtkm::cont::ArrayHandleBasic<T> componentArray;
|
||||
|
||||
vtkmdiy::load(bb, numComponents);
|
||||
vtkmdiy::load(bb, componentArray);
|
||||
|
||||
obj = vtkm::cont::make_ArrayHandleRuntimeVec(numComponents, componentArray);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename VecType>
|
||||
struct Serialization<vtkm::cont::ArrayHandle<VecType, vtkm::cont::StorageTagRuntimeVec>>
|
||||
: Serialization<vtkm::cont::ArrayHandleRuntimeVec<typename VecType::ComponentType>>
|
||||
{
|
||||
};
|
||||
|
||||
} // diy
|
||||
/// @endcond SERIALIZATION
|
||||
|
||||
#endif //vtk_m_cont_ArrayHandleRuntimeVec_h
|
@ -44,7 +44,6 @@ public:
|
||||
private:
|
||||
using ComponentType = typename ComponentPortalType::ValueType;
|
||||
|
||||
VTKM_STATIC_ASSERT(vtkm::HasVecTraits<ValueType>::value);
|
||||
using VTraits = vtkm::VecTraits<ValueType>;
|
||||
VTKM_STATIC_ASSERT((std::is_same<typename VTraits::ComponentType, ComponentType>::value));
|
||||
static constexpr vtkm::IdComponent NUM_COMPONENTS = VTraits::NUM_COMPONENTS;
|
||||
|
@ -86,6 +86,28 @@ ArrayExtractComponentImpl<vtkm::cont::StorageTagUniformPoints>::operator()(
|
||||
}
|
||||
}
|
||||
|
||||
VTKM_CONT vtkm::cont::ArrayHandle<vtkm::Range>
|
||||
ArrayRangeComputeImpl<vtkm::cont::StorageTagUniformPoints>::operator()(
|
||||
const vtkm::cont::ArrayHandleUniformPointCoordinates& input,
|
||||
vtkm::cont::DeviceAdapterId vtkmNotUsed(device)) const
|
||||
{
|
||||
vtkm::internal::ArrayPortalUniformPointCoordinates portal = input.ReadPortal();
|
||||
|
||||
// In this portal we know that the min value is the first entry and the
|
||||
// max value is the last entry.
|
||||
vtkm::Vec3f minimum = portal.Get(0);
|
||||
vtkm::Vec3f maximum = portal.Get(portal.GetNumberOfValues() - 1);
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Range> rangeArray;
|
||||
rangeArray.Allocate(3);
|
||||
vtkm::cont::ArrayHandle<vtkm::Range>::WritePortalType outPortal = rangeArray.WritePortal();
|
||||
outPortal.Set(0, vtkm::Range(minimum[0], maximum[0]));
|
||||
outPortal.Set(1, vtkm::Range(minimum[1], maximum[1]));
|
||||
outPortal.Set(2, vtkm::Range(minimum[2], maximum[2]));
|
||||
|
||||
return rangeArray;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
#ifndef vtk_m_cont_ArrayHandleUniformPointCoordinates_h
|
||||
#define vtk_m_cont_ArrayHandleUniformPointCoordinates_h
|
||||
|
||||
#include <vtkm/Range.h>
|
||||
#include <vtkm/cont/ArrayExtractComponent.h>
|
||||
#include <vtkm/cont/ArrayHandleImplicit.h>
|
||||
#include <vtkm/internal/ArrayPortalUniformPointCoordinates.h>
|
||||
@ -83,6 +84,17 @@ struct VTKM_CONT_EXPORT ArrayExtractComponentImpl<vtkm::cont::StorageTagUniformP
|
||||
vtkm::CopyFlag allowCopy) const;
|
||||
};
|
||||
|
||||
template <typename S>
|
||||
struct ArrayRangeComputeImpl;
|
||||
|
||||
template <>
|
||||
struct VTKM_CONT_EXPORT ArrayRangeComputeImpl<vtkm::cont::StorageTagUniformPoints>
|
||||
{
|
||||
VTKM_CONT vtkm::cont::ArrayHandle<vtkm::Range> operator()(
|
||||
const vtkm::cont::ArrayHandleUniformPointCoordinates& input,
|
||||
vtkm::cont::DeviceAdapterId device) const;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
}
|
||||
|
@ -12,118 +12,16 @@
|
||||
|
||||
#include <vtkm/TypeList.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace cont
|
||||
{
|
||||
|
||||
void ThrowArrayRangeComputeFailed()
|
||||
{
|
||||
throw vtkm::cont::ErrorExecution("Failed to run ArrayRangeComputation on any device.");
|
||||
}
|
||||
|
||||
#define VTKM_ARRAY_RANGE_COMPUTE_IMPL_T(T, Storage) \
|
||||
VTKM_CONT \
|
||||
vtkm::cont::ArrayHandle<vtkm::Range> ArrayRangeCompute( \
|
||||
const vtkm::cont::ArrayHandle<T, Storage>& input, vtkm::cont::DeviceAdapterId device) \
|
||||
{ \
|
||||
return detail::ArrayRangeComputeImpl(input, device); \
|
||||
} \
|
||||
struct SwallowSemicolon
|
||||
#define VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC(T, N, Storage) \
|
||||
VTKM_CONT \
|
||||
vtkm::cont::ArrayHandle<vtkm::Range> ArrayRangeCompute( \
|
||||
const vtkm::cont::ArrayHandle<vtkm::Vec<T, N>, Storage>& input, \
|
||||
vtkm::cont::DeviceAdapterId device) \
|
||||
{ \
|
||||
return detail::ArrayRangeComputeImpl(input, device); \
|
||||
} \
|
||||
struct SwallowSemicolon
|
||||
|
||||
#define VTKM_ARRAY_RANGE_COMPUTE_IMPL_ALL_SCALAR_T(Storage) \
|
||||
VTKM_ARRAY_RANGE_COMPUTE_IMPL_T(vtkm::Int8, Storage); \
|
||||
VTKM_ARRAY_RANGE_COMPUTE_IMPL_T(vtkm::UInt8, Storage); \
|
||||
VTKM_ARRAY_RANGE_COMPUTE_IMPL_T(vtkm::Int16, Storage); \
|
||||
VTKM_ARRAY_RANGE_COMPUTE_IMPL_T(vtkm::UInt16, Storage); \
|
||||
VTKM_ARRAY_RANGE_COMPUTE_IMPL_T(vtkm::Int32, Storage); \
|
||||
VTKM_ARRAY_RANGE_COMPUTE_IMPL_T(vtkm::UInt32, Storage); \
|
||||
VTKM_ARRAY_RANGE_COMPUTE_IMPL_T(vtkm::Int64, Storage); \
|
||||
VTKM_ARRAY_RANGE_COMPUTE_IMPL_T(vtkm::UInt64, Storage); \
|
||||
VTKM_ARRAY_RANGE_COMPUTE_IMPL_T(vtkm::Float32, Storage); \
|
||||
VTKM_ARRAY_RANGE_COMPUTE_IMPL_T(vtkm::Float64, Storage); \
|
||||
VTKM_ARRAY_RANGE_COMPUTE_IMPL_T(char, Storage); \
|
||||
VTKM_ARRAY_RANGE_COMPUTE_IMPL_T(signed VTKM_UNUSED_INT_TYPE, Storage); \
|
||||
VTKM_ARRAY_RANGE_COMPUTE_IMPL_T(unsigned VTKM_UNUSED_INT_TYPE, Storage)
|
||||
|
||||
#define VTKM_ARRAY_RANGE_COMPUTE_IMPL_ALL_VEC(N, Storage) \
|
||||
VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC(vtkm::Int8, N, Storage); \
|
||||
VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC(vtkm::UInt8, N, Storage); \
|
||||
VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC(vtkm::Int16, N, Storage); \
|
||||
VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC(vtkm::UInt16, N, Storage); \
|
||||
VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC(vtkm::Int32, N, Storage); \
|
||||
VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC(vtkm::UInt32, N, Storage); \
|
||||
VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC(vtkm::Int64, N, Storage); \
|
||||
VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC(vtkm::UInt64, N, Storage); \
|
||||
VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC(vtkm::Float32, N, Storage); \
|
||||
VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC(vtkm::Float64, N, Storage); \
|
||||
VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC(char, N, Storage); \
|
||||
VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC(signed VTKM_UNUSED_INT_TYPE, N, Storage); \
|
||||
VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC(unsigned VTKM_UNUSED_INT_TYPE, N, Storage)
|
||||
|
||||
VTKM_ARRAY_RANGE_COMPUTE_IMPL_ALL_SCALAR_T(vtkm::cont::StorageTagBasic);
|
||||
|
||||
VTKM_ARRAY_RANGE_COMPUTE_IMPL_ALL_VEC(2, vtkm::cont::StorageTagBasic);
|
||||
VTKM_ARRAY_RANGE_COMPUTE_IMPL_ALL_VEC(3, vtkm::cont::StorageTagBasic);
|
||||
VTKM_ARRAY_RANGE_COMPUTE_IMPL_ALL_VEC(4, vtkm::cont::StorageTagBasic);
|
||||
|
||||
VTKM_ARRAY_RANGE_COMPUTE_IMPL_ALL_VEC(2, vtkm::cont::StorageTagSOA);
|
||||
VTKM_ARRAY_RANGE_COMPUTE_IMPL_ALL_VEC(3, vtkm::cont::StorageTagSOA);
|
||||
VTKM_ARRAY_RANGE_COMPUTE_IMPL_ALL_VEC(4, vtkm::cont::StorageTagSOA);
|
||||
|
||||
VTKM_ARRAY_RANGE_COMPUTE_IMPL_ALL_SCALAR_T(vtkm::cont::StorageTagStride);
|
||||
|
||||
VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC(vtkm::Float32, 3, vtkm::cont::StorageTagXGCCoordinates);
|
||||
VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC(vtkm::Float64, 3, vtkm::cont::StorageTagXGCCoordinates);
|
||||
|
||||
#undef VTKM_ARRAY_RANGE_COMPUTE_IMPL_T
|
||||
#undef VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC
|
||||
#undef VTKM_ARRAY_RANGE_COMPUTE_IMPL_ALL_SCALAR_T
|
||||
#undef VTKM_ARRAY_RANGE_COMPUTE_IMPL_ALL_VEC
|
||||
|
||||
// Special implementation for regular point coordinates, which are easy
|
||||
// to determine.
|
||||
VTKM_CONT
|
||||
vtkm::cont::ArrayHandle<vtkm::Range> ArrayRangeCompute(
|
||||
const vtkm::cont::ArrayHandle<vtkm::Vec3f,
|
||||
vtkm::cont::ArrayHandleUniformPointCoordinates::StorageTag>& array,
|
||||
vtkm::cont::DeviceAdapterId)
|
||||
{
|
||||
vtkm::internal::ArrayPortalUniformPointCoordinates portal = array.ReadPortal();
|
||||
|
||||
// In this portal we know that the min value is the first entry and the
|
||||
// max value is the last entry.
|
||||
vtkm::Vec3f minimum = portal.Get(0);
|
||||
vtkm::Vec3f maximum = portal.Get(portal.GetNumberOfValues() - 1);
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Range> rangeArray;
|
||||
rangeArray.Allocate(3);
|
||||
vtkm::cont::ArrayHandle<vtkm::Range>::WritePortalType outPortal = rangeArray.WritePortal();
|
||||
outPortal.Set(0, vtkm::Range(minimum[0], maximum[0]));
|
||||
outPortal.Set(1, vtkm::Range(minimum[1], maximum[1]));
|
||||
outPortal.Set(2, vtkm::Range(minimum[2], maximum[2]));
|
||||
|
||||
return rangeArray;
|
||||
}
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Range> ArrayRangeCompute(
|
||||
const vtkm::cont::ArrayHandle<vtkm::Id, vtkm::cont::StorageTagIndex>& input,
|
||||
vtkm::cont::DeviceAdapterId)
|
||||
{
|
||||
vtkm::cont::ArrayHandle<vtkm::Range> result;
|
||||
result.Allocate(1);
|
||||
result.WritePortal().Set(0, vtkm::Range(0, input.GetNumberOfValues() - 1));
|
||||
return result;
|
||||
}
|
||||
#include <vtkm/cont/ArrayHandleBasic.h>
|
||||
#include <vtkm/cont/ArrayHandleCartesianProduct.h>
|
||||
#include <vtkm/cont/ArrayHandleCompositeVector.h>
|
||||
#include <vtkm/cont/ArrayHandleConstant.h>
|
||||
#include <vtkm/cont/ArrayHandleCounting.h>
|
||||
#include <vtkm/cont/ArrayHandleIndex.h>
|
||||
#include <vtkm/cont/ArrayHandleSOA.h>
|
||||
#include <vtkm/cont/ArrayHandleStride.h>
|
||||
#include <vtkm/cont/ArrayHandleUniformPointCoordinates.h>
|
||||
#include <vtkm/cont/ArrayHandleXGCCoordinates.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
@ -152,7 +50,7 @@ struct ComputeRangeFunctor
|
||||
vtkm::cont::DeviceAdapterId device,
|
||||
vtkm::cont::ArrayHandle<vtkm::Range>& ranges) const
|
||||
{
|
||||
ranges = vtkm::cont::ArrayRangeCompute(array, device);
|
||||
ranges = vtkm::cont::ArrayRangeComputeTemplate(array, device);
|
||||
}
|
||||
|
||||
// Used with vtkm::ListForEach to get components
|
||||
@ -172,7 +70,7 @@ struct ComputeRangeFunctor
|
||||
{
|
||||
vtkm::cont::ArrayHandleStride<T> componentArray = array.ExtractComponent<T>(componentI);
|
||||
vtkm::cont::ArrayHandle<vtkm::Range> componentRange =
|
||||
vtkm::cont::ArrayRangeCompute(componentArray, device);
|
||||
vtkm::cont::ArrayRangeComputeTemplate(componentArray, device);
|
||||
rangePortal.Set(componentI, componentRange.ReadPortal().Get(0));
|
||||
}
|
||||
success = true;
|
||||
@ -191,6 +89,21 @@ vtkm::cont::ArrayHandle<vtkm::Range> ComputeForStorage(const vtkm::cont::Unknown
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace cont
|
||||
{
|
||||
|
||||
namespace internal
|
||||
{
|
||||
|
||||
void ThrowArrayRangeComputeFailed()
|
||||
{
|
||||
throw vtkm::cont::ErrorExecution("Failed to run ArrayRangeComputation on any device.");
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Range> ArrayRangeCompute(const vtkm::cont::UnknownArrayHandle& array,
|
||||
vtkm::cont::DeviceAdapterId device)
|
||||
{
|
||||
@ -214,7 +127,7 @@ vtkm::cont::ArrayHandle<vtkm::Range> ArrayRangeCompute(const vtkm::cont::Unknown
|
||||
{
|
||||
vtkm::cont::ArrayHandleUniformPointCoordinates uniformPoints;
|
||||
array.AsArrayHandle(uniformPoints);
|
||||
return vtkm::cont::ArrayRangeCompute(uniformPoints, device);
|
||||
return vtkm::cont::ArrayRangeComputeTemplate(uniformPoints, device);
|
||||
}
|
||||
using CartesianProductStorage =
|
||||
vtkm::cont::StorageTagCartesianProduct<vtkm::cont::StorageTagBasic,
|
||||
@ -234,7 +147,7 @@ vtkm::cont::ArrayHandle<vtkm::Range> ArrayRangeCompute(const vtkm::cont::Unknown
|
||||
}
|
||||
if (array.IsStorageType<vtkm::cont::StorageTagIndex>())
|
||||
{
|
||||
return ArrayRangeCompute(array.AsArrayHandle<vtkm::cont::ArrayHandleIndex>(), device);
|
||||
return ArrayRangeComputeTemplate(array.AsArrayHandle<vtkm::cont::ArrayHandleIndex>(), device);
|
||||
}
|
||||
}
|
||||
catch (vtkm::cont::ErrorBadType&)
|
||||
|
@ -31,7 +31,6 @@ namespace vtkm
|
||||
namespace cont
|
||||
{
|
||||
|
||||
///@{
|
||||
/// \brief Compute the range of the data in an array handle.
|
||||
///
|
||||
/// Given an `ArrayHandle`, this function computes the range (min and max) of
|
||||
@ -48,179 +47,27 @@ namespace cont
|
||||
/// Note that the ArrayRangeCompute.h header file contains only precompiled overloads
|
||||
/// of ArrayRangeCompute. This is so that ArrayRangeCompute.h can be included in
|
||||
/// code that does not use a device compiler. If you need to compute array ranges
|
||||
/// for arbitrary `ArrayHandle`s not in this precompiled list, you need to include
|
||||
/// ArrayRangeComputeTemplate.h. This contains a templated version of ArrayRangeCompute
|
||||
/// that will compile for any `ArrayHandle` type not already handled.
|
||||
/// for arbitrary `ArrayHandle`s not in this precompiled list, you need to use
|
||||
/// `ArrayRangeComputeTemplate` (declared in `ArrayRangeComputeTemplate`), which
|
||||
/// will compile for any `ArrayHandle` type not already handled.
|
||||
///
|
||||
|
||||
VTKM_CONT_EXPORT vtkm::cont::ArrayHandle<vtkm::Range> ArrayRangeCompute(
|
||||
const vtkm::cont::UnknownArrayHandle& array,
|
||||
vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny{});
|
||||
|
||||
#define VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(T, Storage) \
|
||||
VTKM_CONT_EXPORT \
|
||||
VTKM_CONT \
|
||||
vtkm::cont::ArrayHandle<vtkm::Range> ArrayRangeCompute( \
|
||||
const vtkm::cont::ArrayHandle<T, Storage>& input, \
|
||||
vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny())
|
||||
#define VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(T, N, Storage) \
|
||||
VTKM_CONT_EXPORT \
|
||||
VTKM_CONT \
|
||||
vtkm::cont::ArrayHandle<vtkm::Range> ArrayRangeCompute( \
|
||||
const vtkm::cont::ArrayHandle<vtkm::Vec<T, N>, Storage>& input, \
|
||||
vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny())
|
||||
|
||||
#define VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_ALL_SCALAR_T(Storage) \
|
||||
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::Int8, Storage); \
|
||||
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::UInt8, Storage); \
|
||||
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::Int16, Storage); \
|
||||
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::UInt16, Storage); \
|
||||
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::Int32, Storage); \
|
||||
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::UInt32, Storage); \
|
||||
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::Int64, Storage); \
|
||||
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::UInt64, Storage); \
|
||||
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::Float32, Storage); \
|
||||
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::Float64, Storage); \
|
||||
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(char, Storage); \
|
||||
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(signed VTKM_UNUSED_INT_TYPE, Storage); \
|
||||
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(unsigned VTKM_UNUSED_INT_TYPE, Storage)
|
||||
|
||||
#define VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_ALL_VEC(N, Storage) \
|
||||
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::Int8, N, Storage); \
|
||||
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::UInt8, N, Storage); \
|
||||
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::Int16, N, Storage); \
|
||||
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::UInt16, N, Storage); \
|
||||
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::Int32, N, Storage); \
|
||||
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::UInt32, N, Storage); \
|
||||
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::Int64, N, Storage); \
|
||||
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::UInt64, N, Storage); \
|
||||
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::Float32, N, Storage); \
|
||||
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::Float64, N, Storage); \
|
||||
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(char, N, Storage); \
|
||||
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(signed VTKM_UNUSED_INT_TYPE, N, Storage); \
|
||||
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(unsigned VTKM_UNUSED_INT_TYPE, N, Storage)
|
||||
|
||||
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_ALL_SCALAR_T(vtkm::cont::StorageTagBasic);
|
||||
|
||||
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_ALL_VEC(2, vtkm::cont::StorageTagBasic);
|
||||
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_ALL_VEC(3, vtkm::cont::StorageTagBasic);
|
||||
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_ALL_VEC(4, vtkm::cont::StorageTagBasic);
|
||||
|
||||
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_ALL_VEC(2, vtkm::cont::StorageTagSOA);
|
||||
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_ALL_VEC(3, vtkm::cont::StorageTagSOA);
|
||||
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_ALL_VEC(4, vtkm::cont::StorageTagSOA);
|
||||
|
||||
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_ALL_SCALAR_T(vtkm::cont::StorageTagStride);
|
||||
|
||||
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::Float32, 3, vtkm::cont::StorageTagXGCCoordinates);
|
||||
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::Float64, 3, vtkm::cont::StorageTagXGCCoordinates);
|
||||
|
||||
#undef VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T
|
||||
#undef VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC
|
||||
#undef VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_ALL_SCALAR_T
|
||||
#undef VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_ALL_VEC
|
||||
|
||||
VTKM_CONT_EXPORT VTKM_CONT vtkm::cont::ArrayHandle<vtkm::Range> ArrayRangeCompute(
|
||||
const vtkm::cont::ArrayHandle<vtkm::Vec3f,
|
||||
vtkm::cont::ArrayHandleUniformPointCoordinates::StorageTag>& array,
|
||||
vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny());
|
||||
|
||||
// Implementation of cartesian products
|
||||
template <typename T, typename ST1, typename ST2, typename ST3>
|
||||
VTKM_CONT inline vtkm::cont::ArrayHandle<vtkm::Range> ArrayRangeCompute(
|
||||
const vtkm::cont::ArrayHandle<vtkm::Vec<T, 3>,
|
||||
vtkm::cont::StorageTagCartesianProduct<ST1, ST2, ST3>>& input_,
|
||||
vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny())
|
||||
namespace internal
|
||||
{
|
||||
vtkm::cont::ArrayHandle<vtkm::Range> result;
|
||||
result.Allocate(3);
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Range> componentRangeArray;
|
||||
vtkm::Range componentRange;
|
||||
|
||||
vtkm::cont::ArrayHandleCartesianProduct<vtkm::cont::ArrayHandle<T, ST1>,
|
||||
vtkm::cont::ArrayHandle<T, ST2>,
|
||||
vtkm::cont::ArrayHandle<T, ST3>>
|
||||
input = input_;
|
||||
vtkm::cont::ArrayHandle<T, ST1> firstArray = input.GetFirstArray();
|
||||
componentRangeArray = vtkm::cont::ArrayRangeCompute(firstArray, device);
|
||||
componentRange = componentRangeArray.ReadPortal().Get(0);
|
||||
result.WritePortal().Set(0, componentRange);
|
||||
|
||||
vtkm::cont::ArrayHandle<T, ST2> secondArray = input.GetSecondArray();
|
||||
componentRangeArray = vtkm::cont::ArrayRangeCompute(secondArray, device);
|
||||
componentRange = componentRangeArray.ReadPortal().Get(0);
|
||||
result.WritePortal().Set(1, componentRange);
|
||||
|
||||
vtkm::cont::ArrayHandle<T, ST3> thirdArray = input.GetThirdArray();
|
||||
componentRangeArray = vtkm::cont::ArrayRangeCompute(thirdArray, device);
|
||||
componentRange = componentRangeArray.ReadPortal().Get(0);
|
||||
result.WritePortal().Set(2, componentRange);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Implementation of constant arrays
|
||||
template <typename T>
|
||||
VTKM_CONT inline vtkm::cont::ArrayHandle<vtkm::Range> ArrayRangeCompute(
|
||||
const vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagConstant>& input,
|
||||
vtkm::cont::DeviceAdapterId vtkmNotUsed(device) = vtkm::cont::DeviceAdapterTagAny{})
|
||||
{
|
||||
using Traits = vtkm::VecTraits<T>;
|
||||
const T value = vtkm::cont::ArrayHandleConstant<T>(input).GetValue();
|
||||
vtkm::IdComponent numComponents = Traits::GetNumberOfComponents(value);
|
||||
vtkm::cont::ArrayHandle<vtkm::Range> result;
|
||||
result.Allocate(numComponents);
|
||||
auto portal = result.WritePortal();
|
||||
for (vtkm::IdComponent cIndex = 0; cIndex < numComponents; ++cIndex)
|
||||
{
|
||||
auto component = Traits::GetComponent(value, cIndex);
|
||||
portal.Set(cIndex, vtkm::Range(component, component));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Implementation of counting arrays
|
||||
template <typename T>
|
||||
VTKM_CONT inline vtkm::cont::ArrayHandle<vtkm::Range> ArrayRangeCompute(
|
||||
const vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagCounting>& input,
|
||||
vtkm::cont::DeviceAdapterId vtkmNotUsed(device) = vtkm::cont::DeviceAdapterTagAny{})
|
||||
{
|
||||
using Traits = vtkm::VecTraits<T>;
|
||||
vtkm::cont::ArrayHandle<vtkm::Range> result;
|
||||
result.Allocate(Traits::NUM_COMPONENTS);
|
||||
auto portal = result.WritePortal();
|
||||
if (portal.GetNumberOfValues() > 0)
|
||||
{
|
||||
T first = input.ReadPortal().Get(0);
|
||||
T last = input.ReadPortal().Get(input.GetNumberOfValues() - 1);
|
||||
for (vtkm::IdComponent cIndex = 0; cIndex < Traits::NUM_COMPONENTS; ++cIndex)
|
||||
{
|
||||
auto firstComponent = Traits::GetComponent(first, cIndex);
|
||||
auto lastComponent = Traits::GetComponent(last, cIndex);
|
||||
portal.Set(cIndex,
|
||||
vtkm::Range(vtkm::Min(firstComponent, lastComponent),
|
||||
vtkm::Max(firstComponent, lastComponent)));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Array is empty
|
||||
for (vtkm::IdComponent cIndex = 0; cIndex < Traits::NUM_COMPONENTS; ++cIndex)
|
||||
{
|
||||
portal.Set(cIndex, vtkm::Range{});
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Implementation of index arrays
|
||||
VTKM_CONT_EXPORT vtkm::cont::ArrayHandle<vtkm::Range> ArrayRangeCompute(
|
||||
const vtkm::cont::ArrayHandle<vtkm::Id, vtkm::cont::StorageTagIndex>& input,
|
||||
vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny{});
|
||||
///@}
|
||||
|
||||
VTKM_CONT_EXPORT void ThrowArrayRangeComputeFailed();
|
||||
|
||||
} // namespace internal
|
||||
|
||||
VTKM_DEPRECATED(2.1, "Moved to vtkm::cont::internal.")
|
||||
inline void ThrowArrayRangeComputeFailed()
|
||||
{
|
||||
internal::ThrowArrayRangeComputeFailed();
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace vtkm::cont
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <vtkm/cont/ArrayRangeCompute.h>
|
||||
|
||||
#include <vtkm/BinaryOperators.h>
|
||||
#include <vtkm/Deprecated.h>
|
||||
#include <vtkm/VecTraits.h>
|
||||
|
||||
#include <vtkm/cont/Algorithm.h>
|
||||
@ -42,8 +43,13 @@ struct ArrayRangeComputeFunctor
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
namespace internal
|
||||
{
|
||||
|
||||
template <typename T, typename S>
|
||||
inline vtkm::cont::ArrayHandle<vtkm::Range> ArrayRangeComputeImpl(
|
||||
inline vtkm::cont::ArrayHandle<vtkm::Range> ArrayRangeComputeGeneric(
|
||||
const vtkm::cont::ArrayHandle<T, S>& input,
|
||||
vtkm::cont::DeviceAdapterId device)
|
||||
{
|
||||
@ -74,7 +80,7 @@ inline vtkm::cont::ArrayHandle<vtkm::Range> ArrayRangeComputeImpl(
|
||||
initial[1] = T(std::numeric_limits<CT>::lowest());
|
||||
|
||||
const bool rangeComputed = vtkm::cont::TryExecuteOnDevice(
|
||||
device, detail::ArrayRangeComputeFunctor{}, input, initial, result);
|
||||
device, vtkm::cont::detail::ArrayRangeComputeFunctor{}, input, initial, result);
|
||||
if (!rangeComputed)
|
||||
{
|
||||
ThrowArrayRangeComputeFailed();
|
||||
@ -93,17 +99,38 @@ inline vtkm::cont::ArrayHandle<vtkm::Range> ArrayRangeComputeImpl(
|
||||
return range;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
template <typename S>
|
||||
struct ArrayRangeComputeImpl
|
||||
{
|
||||
template <typename T>
|
||||
vtkm::cont::ArrayHandle<vtkm::Range> operator()(const vtkm::cont::ArrayHandle<T, S>& input,
|
||||
vtkm::cont::DeviceAdapterId device) const
|
||||
{
|
||||
return vtkm::cont::internal::ArrayRangeComputeGeneric(input, device);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
|
||||
template <typename ArrayHandleType>
|
||||
inline vtkm::cont::ArrayHandle<vtkm::Range> ArrayRangeCompute(
|
||||
inline vtkm::cont::ArrayHandle<vtkm::Range> ArrayRangeComputeTemplate(
|
||||
const ArrayHandleType& input,
|
||||
vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny{})
|
||||
{
|
||||
VTKM_IS_ARRAY_HANDLE(ArrayHandleType);
|
||||
return detail::ArrayRangeComputeImpl(input, device);
|
||||
return internal::ArrayRangeComputeImpl<typename ArrayHandleType::StorageTag>{}(input, device);
|
||||
}
|
||||
|
||||
template <typename ArrayHandleType>
|
||||
VTKM_DEPRECATED(2.1, "Use precompiled ArrayRangeCompute or ArrayRangeComputeTemplate.")
|
||||
inline vtkm::cont::ArrayHandle<vtkm::Range> ArrayRangeCompute(
|
||||
const ArrayHandleType& input,
|
||||
vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny{})
|
||||
{
|
||||
return ArrayRangeComputeTemplate(input, device);
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace vtkm::cont
|
||||
|
||||
|
@ -38,6 +38,7 @@ set(headers
|
||||
ArrayHandleRandomStandardNormal.h
|
||||
ArrayHandleRandomUniformBits.h
|
||||
ArrayHandleRandomUniformReal.h
|
||||
ArrayHandleRuntimeVec.h
|
||||
ArrayHandleSOA.h
|
||||
ArrayHandleStride.h
|
||||
ArrayHandleSwizzle.h
|
||||
@ -94,6 +95,7 @@ set(headers
|
||||
ErrorExecution.h
|
||||
ErrorFilterExecution.h
|
||||
ErrorInternal.h
|
||||
ErrorUserAbort.h
|
||||
ExecutionAndControlObjectBase.h
|
||||
ExecutionObjectBase.h
|
||||
Field.h
|
||||
|
@ -8,6 +8,10 @@
|
||||
// PURPOSE. See the above copyright notice for more information.
|
||||
//============================================================================
|
||||
|
||||
#include <vtkm/cont/CellSetExplicit.h>
|
||||
#include <vtkm/cont/CellSetExtrude.h>
|
||||
#include <vtkm/cont/CellSetSingleType.h>
|
||||
#include <vtkm/cont/CellSetStructured.h>
|
||||
#include <vtkm/cont/DataSet.h>
|
||||
#include <vtkm/cont/ErrorBadValue.h>
|
||||
#include <vtkm/cont/Logging.h>
|
||||
@ -341,3 +345,30 @@ void DataSet::ConvertToExpected()
|
||||
|
||||
} // namespace cont
|
||||
} // namespace vtkm
|
||||
|
||||
|
||||
namespace mangled_diy_namespace
|
||||
{
|
||||
|
||||
using SerializedCellSetTypes = vtkm::ListAppend<VTKM_DEFAULT_CELL_SET_LIST,
|
||||
vtkm::List<vtkm::cont::CellSetStructured<1>,
|
||||
vtkm::cont::CellSetStructured<2>,
|
||||
vtkm::cont::CellSetStructured<3>,
|
||||
vtkm::cont::CellSetExplicit<>,
|
||||
vtkm::cont::CellSetSingleType<>,
|
||||
vtkm::cont::CellSetExtrude>>;
|
||||
using DefaultDataSetWithCellTypes = vtkm::cont::DataSetWithCellSetTypes<SerializedCellSetTypes>;
|
||||
|
||||
void Serialization<vtkm::cont::DataSet>::save(BinaryBuffer& bb, const vtkm::cont::DataSet& obj)
|
||||
{
|
||||
vtkmdiy::save(bb, DefaultDataSetWithCellTypes{ obj });
|
||||
}
|
||||
|
||||
void Serialization<vtkm::cont::DataSet>::load(BinaryBuffer& bb, vtkm::cont::DataSet& obj)
|
||||
{
|
||||
DefaultDataSetWithCellTypes data;
|
||||
vtkmdiy::load(bb, data);
|
||||
obj = data.DataSet;
|
||||
}
|
||||
|
||||
} // namespace mangled_diy_namespace
|
||||
|
@ -420,37 +420,70 @@ namespace vtkm
|
||||
namespace cont
|
||||
{
|
||||
|
||||
template <typename FieldTypeList = VTKM_DEFAULT_TYPE_LIST,
|
||||
typename CellSetTypesList = VTKM_DEFAULT_CELL_SET_LIST>
|
||||
struct SerializableDataSet
|
||||
/// \brief Specify cell sets to use when serializing a `DataSet`.
|
||||
///
|
||||
/// Usually when serializing a `DataSet`, it uses a fixed set of standard
|
||||
/// `CellSet` types to serialize. If you are writing an algorithm with a
|
||||
/// custom `CellSet`, you can specify the `CellSet`(s) as the template
|
||||
/// parameter for this class (either as a list of `CellSet`s or in a
|
||||
/// single `vtkm::List` parameter).
|
||||
///
|
||||
template <typename... CellSetTypes>
|
||||
struct DataSetWithCellSetTypes
|
||||
{
|
||||
SerializableDataSet() = default;
|
||||
vtkm::cont::DataSet DataSet;
|
||||
|
||||
explicit SerializableDataSet(const vtkm::cont::DataSet& dataset)
|
||||
DataSetWithCellSetTypes() = default;
|
||||
|
||||
explicit DataSetWithCellSetTypes(const vtkm::cont::DataSet& dataset)
|
||||
: DataSet(dataset)
|
||||
{
|
||||
}
|
||||
|
||||
vtkm::cont::DataSet DataSet;
|
||||
};
|
||||
|
||||
template <typename... CellSetTypes>
|
||||
struct DataSetWithCellSetTypes<vtkm::List<CellSetTypes...>>
|
||||
: DataSetWithCellSetTypes<CellSetTypes...>
|
||||
{
|
||||
using DataSetWithCellSetTypes<CellSetTypes...>::DataSetWithCellSetTypes;
|
||||
};
|
||||
|
||||
template <typename FieldTypeList = VTKM_DEFAULT_TYPE_LIST,
|
||||
typename CellSetTypesList = VTKM_DEFAULT_CELL_SET_LIST>
|
||||
struct VTKM_DEPRECATED(
|
||||
2.1,
|
||||
"Serialize DataSet directly or use DataSetWithCellSetTypes for weird CellSets.")
|
||||
SerializableDataSet : DataSetWithCellSetTypes<CellSetTypesList>
|
||||
{
|
||||
using DataSetWithCellSetTypes<CellSetTypesList>::DataSetWithCellSetTypes;
|
||||
};
|
||||
|
||||
}
|
||||
} // vtkm::cont
|
||||
|
||||
namespace mangled_diy_namespace
|
||||
{
|
||||
|
||||
template <typename FieldTypeList, typename CellSetTypesList>
|
||||
struct Serialization<vtkm::cont::SerializableDataSet<FieldTypeList, CellSetTypesList>>
|
||||
template <>
|
||||
struct VTKM_CONT_EXPORT Serialization<vtkm::cont::DataSet>
|
||||
{
|
||||
static VTKM_CONT void foo();
|
||||
static VTKM_CONT void save(BinaryBuffer& bb, const vtkm::cont::DataSet& obj);
|
||||
static VTKM_CONT void load(BinaryBuffer& bb, vtkm::cont::DataSet& obj);
|
||||
};
|
||||
|
||||
template <typename... CellSetTypes>
|
||||
struct Serialization<vtkm::cont::DataSetWithCellSetTypes<CellSetTypes...>>
|
||||
{
|
||||
private:
|
||||
using Type = vtkm::cont::SerializableDataSet<FieldTypeList, CellSetTypesList>;
|
||||
using Type = vtkm::cont::DataSetWithCellSetTypes<CellSetTypes...>;
|
||||
|
||||
public:
|
||||
static VTKM_CONT void save(BinaryBuffer& bb, const Type& serializable)
|
||||
{
|
||||
const auto& dataset = serializable.DataSet;
|
||||
|
||||
vtkmdiy::save(bb, dataset.GetCellSet().ResetCellSetList(CellSetTypesList{}));
|
||||
vtkmdiy::save(bb, dataset.GetCellSet().ResetCellSetList(vtkm::List<CellSetTypes...>{}));
|
||||
|
||||
vtkm::IdComponent numberOfFields = dataset.GetNumberOfFields();
|
||||
vtkmdiy::save(bb, numberOfFields);
|
||||
@ -472,7 +505,7 @@ public:
|
||||
auto& dataset = serializable.DataSet;
|
||||
dataset = {}; // clear
|
||||
|
||||
vtkm::cont::UncertainCellSet<CellSetTypesList> cells;
|
||||
vtkm::cont::UncertainCellSet<vtkm::List<CellSetTypes...>> cells;
|
||||
vtkmdiy::load(bb, cells);
|
||||
dataset.SetCellSet(cells);
|
||||
|
||||
@ -496,6 +529,20 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template <typename... CellSetTypes>
|
||||
struct Serialization<vtkm::cont::DataSetWithCellSetTypes<vtkm::List<CellSetTypes...>>>
|
||||
: Serialization<vtkm::cont::DataSetWithCellSetTypes<CellSetTypes...>>
|
||||
{
|
||||
};
|
||||
|
||||
VTKM_DEPRECATED_SUPPRESS_BEGIN
|
||||
template <typename FieldTypeList, typename CellSetTypesList>
|
||||
struct Serialization<vtkm::cont::SerializableDataSet<FieldTypeList, CellSetTypesList>>
|
||||
: Serialization<vtkm::cont::DataSetWithCellSetTypes<CellSetTypesList>>
|
||||
{
|
||||
};
|
||||
VTKM_DEPRECATED_SUPPRESS_END
|
||||
|
||||
} // diy
|
||||
/// @endcond SERIALIZATION
|
||||
|
||||
|
42
vtkm/cont/ErrorUserAbort.h
Normal file
42
vtkm/cont/ErrorUserAbort.h
Normal file
@ -0,0 +1,42 @@
|
||||
//============================================================================
|
||||
// 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_cont_ErrorUserAbort_h
|
||||
#define vtk_m_cont_ErrorUserAbort_h
|
||||
|
||||
#include <vtkm/cont/Error.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace cont
|
||||
{
|
||||
|
||||
VTKM_SILENCE_WEAK_VTABLE_WARNING_START
|
||||
|
||||
/// This class is thrown when vtk-m detects a request for aborting execution
|
||||
/// in the current thread
|
||||
///
|
||||
class VTKM_ALWAYS_EXPORT ErrorUserAbort : public Error
|
||||
{
|
||||
public:
|
||||
ErrorUserAbort()
|
||||
: Error(Message, true)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr const char* Message = "User abort detected.";
|
||||
};
|
||||
|
||||
VTKM_SILENCE_WEAK_VTABLE_WARNING_END
|
||||
|
||||
}
|
||||
} // namespace vtkm::cont
|
||||
|
||||
#endif // vtk_m_cont_ErrorUserAbort_h
|
@ -35,6 +35,7 @@ struct RuntimeDeviceTrackerInternals
|
||||
|
||||
std::array<bool, VTKM_MAX_DEVICE_ADAPTER_ID> RuntimeAllowed;
|
||||
bool ThreadFriendlyMemAlloc = false;
|
||||
std::function<bool()> AbortChecker;
|
||||
};
|
||||
|
||||
}
|
||||
@ -186,6 +187,28 @@ VTKM_CONT void RuntimeDeviceTracker::CopyStateFrom(const vtkm::cont::RuntimeDevi
|
||||
*(this->Internals) = *tracker.Internals;
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
void RuntimeDeviceTracker::SetAbortChecker(const std::function<bool()>& func)
|
||||
{
|
||||
this->Internals->AbortChecker = func;
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
bool RuntimeDeviceTracker::CheckForAbortRequest() const
|
||||
{
|
||||
if (this->Internals->AbortChecker)
|
||||
{
|
||||
return this->Internals->AbortChecker();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
void RuntimeDeviceTracker::ClearAbortChecker()
|
||||
{
|
||||
this->Internals->AbortChecker = nullptr;
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
void RuntimeDeviceTracker::PrintSummary(std::ostream& out) const
|
||||
{
|
||||
@ -228,25 +251,6 @@ ScopedRuntimeDeviceTracker::ScopedRuntimeDeviceTracker(
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::DevicesEnabled, "Entering scoped runtime region");
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
ScopedRuntimeDeviceTracker::ScopedRuntimeDeviceTracker(vtkm::cont::DeviceAdapterId device,
|
||||
RuntimeDeviceTrackerMode mode)
|
||||
: ScopedRuntimeDeviceTracker(GetRuntimeDeviceTracker())
|
||||
{
|
||||
if (mode == RuntimeDeviceTrackerMode::Force)
|
||||
{
|
||||
this->ForceDevice(device);
|
||||
}
|
||||
else if (mode == RuntimeDeviceTrackerMode::Enable)
|
||||
{
|
||||
this->ResetDevice(device);
|
||||
}
|
||||
else if (mode == RuntimeDeviceTrackerMode::Disable)
|
||||
{
|
||||
this->DisableDevice(device);
|
||||
}
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
ScopedRuntimeDeviceTracker::ScopedRuntimeDeviceTracker(
|
||||
vtkm::cont::DeviceAdapterId device,
|
||||
@ -268,6 +272,14 @@ ScopedRuntimeDeviceTracker::ScopedRuntimeDeviceTracker(
|
||||
}
|
||||
}
|
||||
|
||||
VTKM_CONT ScopedRuntimeDeviceTracker::ScopedRuntimeDeviceTracker(
|
||||
const std::function<bool()>& abortChecker,
|
||||
const vtkm::cont::RuntimeDeviceTracker& tracker)
|
||||
: ScopedRuntimeDeviceTracker(tracker)
|
||||
{
|
||||
this->SetAbortChecker(abortChecker);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
ScopedRuntimeDeviceTracker::~ScopedRuntimeDeviceTracker()
|
||||
{
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <vtkm/cont/ErrorBadDevice.h>
|
||||
#include <vtkm/cont/RuntimeDeviceInformation.h>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
namespace vtkm
|
||||
@ -123,6 +124,18 @@ public:
|
||||
///
|
||||
VTKM_CONT void CopyStateFrom(const vtkm::cont::RuntimeDeviceTracker& tracker);
|
||||
|
||||
///@{
|
||||
/// \brief Set/Clear the abort checker functor.
|
||||
///
|
||||
/// If set the abort checker functor is called by \c TryExecute before scheduling
|
||||
/// a task on a device from the associated the thread. If the functor returns
|
||||
/// \e true, an exception is thrown.
|
||||
VTKM_CONT void SetAbortChecker(const std::function<bool()>& func);
|
||||
VTKM_CONT void ClearAbortChecker();
|
||||
///@}
|
||||
|
||||
VTKM_CONT bool CheckForAbortRequest() const;
|
||||
|
||||
VTKM_CONT void PrintSummary(std::ostream& out) const;
|
||||
|
||||
private:
|
||||
@ -149,82 +162,7 @@ private:
|
||||
void LogEnabledDevices() const;
|
||||
};
|
||||
|
||||
|
||||
enum struct RuntimeDeviceTrackerMode
|
||||
{
|
||||
Force,
|
||||
Enable,
|
||||
Disable
|
||||
};
|
||||
|
||||
/// A class that can be used to determine or modify which device adapter
|
||||
/// VTK-m algorithms should be run on. This class captures the state
|
||||
/// of the per-thread device adapter and will revert any changes applied
|
||||
/// during its lifetime on destruction.
|
||||
///
|
||||
///
|
||||
struct VTKM_CONT_EXPORT ScopedRuntimeDeviceTracker : public vtkm::cont::RuntimeDeviceTracker
|
||||
{
|
||||
/// Construct a ScopedRuntimeDeviceTracker where the state of the active devices
|
||||
/// for the current thread are determined by the parameters to the constructor.
|
||||
///
|
||||
/// 'Force'
|
||||
/// - Force-Enable the provided single device adapter
|
||||
/// - Force-Enable all device adapters when using vtkm::cont::DeviceAdaterTagAny
|
||||
/// 'Enable'
|
||||
/// - Enable the provided single device adapter if it was previously disabled
|
||||
/// - Enable all device adapters that are currently disabled when using
|
||||
/// vtkm::cont::DeviceAdaterTagAny
|
||||
/// 'Disable'
|
||||
/// - Disable the provided single device adapter
|
||||
/// - Disable all device adapters when using vtkm::cont::DeviceAdaterTagAny
|
||||
///
|
||||
/// Constructor is not thread safe
|
||||
VTKM_CONT ScopedRuntimeDeviceTracker(
|
||||
vtkm::cont::DeviceAdapterId device,
|
||||
RuntimeDeviceTrackerMode mode = RuntimeDeviceTrackerMode::Force);
|
||||
|
||||
/// Construct a ScopedRuntimeDeviceTracker associated with the thread
|
||||
/// associated with the provided tracker. The active devices
|
||||
/// for the current thread are determined by the parameters to the constructor.
|
||||
///
|
||||
/// 'Force'
|
||||
/// - Force-Enable the provided single device adapter
|
||||
/// - Force-Enable all device adapters when using vtkm::cont::DeviceAdaterTagAny
|
||||
/// 'Enable'
|
||||
/// - Enable the provided single device adapter if it was previously disabled
|
||||
/// - Enable all device adapters that are currently disabled when using
|
||||
/// vtkm::cont::DeviceAdaterTagAny
|
||||
/// 'Disable'
|
||||
/// - Disable the provided single device adapter
|
||||
/// - Disable all device adapters when using vtkm::cont::DeviceAdaterTagAny
|
||||
///
|
||||
/// Any modifications to the ScopedRuntimeDeviceTracker will effect what
|
||||
/// ever thread the \c tracker is associated with, which might not be
|
||||
/// the thread which ScopedRuntimeDeviceTracker was constructed on.
|
||||
///
|
||||
/// Constructor is not thread safe
|
||||
VTKM_CONT ScopedRuntimeDeviceTracker(vtkm::cont::DeviceAdapterId device,
|
||||
RuntimeDeviceTrackerMode mode,
|
||||
const vtkm::cont::RuntimeDeviceTracker& tracker);
|
||||
|
||||
/// Construct a ScopedRuntimeDeviceTracker associated with the thread
|
||||
/// associated with the provided tracker.
|
||||
///
|
||||
/// Any modifications to the ScopedRuntimeDeviceTracker will effect what
|
||||
/// ever thread the \c tracker is associated with, which might not be
|
||||
/// the thread which ScopedRuntimeDeviceTracker was constructed on.
|
||||
///
|
||||
/// Constructor is not thread safe
|
||||
VTKM_CONT ScopedRuntimeDeviceTracker(const vtkm::cont::RuntimeDeviceTracker& tracker);
|
||||
|
||||
/// Destructor is not thread safe
|
||||
VTKM_CONT ~ScopedRuntimeDeviceTracker();
|
||||
|
||||
private:
|
||||
std::unique_ptr<detail::RuntimeDeviceTrackerInternals> SavedState;
|
||||
};
|
||||
|
||||
///----------------------------------------------------------------------------
|
||||
/// \brief Get the \c RuntimeDeviceTracker for the current thread.
|
||||
///
|
||||
/// Many features in VTK-m will attempt to run algorithms on the "best
|
||||
@ -236,6 +174,66 @@ private:
|
||||
VTKM_CONT_EXPORT
|
||||
VTKM_CONT
|
||||
vtkm::cont::RuntimeDeviceTracker& GetRuntimeDeviceTracker();
|
||||
|
||||
enum struct RuntimeDeviceTrackerMode
|
||||
{
|
||||
Force,
|
||||
Enable,
|
||||
Disable
|
||||
};
|
||||
|
||||
///----------------------------------------------------------------------------
|
||||
/// A class to create a scoped runtime device tracker object. This object captures the state
|
||||
/// of the per-thread device tracker and will revert any changes applied
|
||||
/// during its lifetime on destruction.
|
||||
///
|
||||
struct VTKM_CONT_EXPORT ScopedRuntimeDeviceTracker : public vtkm::cont::RuntimeDeviceTracker
|
||||
{
|
||||
/// Construct a ScopedRuntimeDeviceTracker associated with the thread,
|
||||
/// associated with the provided tracker (defaults to current thread's tracker).
|
||||
///
|
||||
/// Any modifications to the ScopedRuntimeDeviceTracker will effect what
|
||||
/// ever thread the \c tracker is associated with, which might not be
|
||||
/// the thread on which the ScopedRuntimeDeviceTracker was constructed.
|
||||
///
|
||||
/// Constructors are not thread safe
|
||||
/// @{
|
||||
///
|
||||
VTKM_CONT ScopedRuntimeDeviceTracker(
|
||||
const vtkm::cont::RuntimeDeviceTracker& tracker = GetRuntimeDeviceTracker());
|
||||
|
||||
/// Use this constructor to modify the state of the device adapters associated with
|
||||
/// the provided tracker. Use \p mode with \p device as follows:
|
||||
///
|
||||
/// 'Force' (default)
|
||||
/// - Force-Enable the provided single device adapter
|
||||
/// - Force-Enable all device adapters when using vtkm::cont::DeviceAdaterTagAny
|
||||
/// 'Enable'
|
||||
/// - Enable the provided single device adapter if it was previously disabled
|
||||
/// - Enable all device adapters that are currently disabled when using
|
||||
/// vtkm::cont::DeviceAdaterTagAny
|
||||
/// 'Disable'
|
||||
/// - Disable the provided single device adapter
|
||||
/// - Disable all device adapters when using vtkm::cont::DeviceAdaterTagAny
|
||||
///
|
||||
VTKM_CONT ScopedRuntimeDeviceTracker(
|
||||
vtkm::cont::DeviceAdapterId device,
|
||||
RuntimeDeviceTrackerMode mode = RuntimeDeviceTrackerMode::Force,
|
||||
const vtkm::cont::RuntimeDeviceTracker& tracker = GetRuntimeDeviceTracker());
|
||||
|
||||
/// Use this constructor to set the abort checker functor for the provided tracker.
|
||||
///
|
||||
VTKM_CONT ScopedRuntimeDeviceTracker(
|
||||
const std::function<bool()>& abortChecker,
|
||||
const vtkm::cont::RuntimeDeviceTracker& tracker = GetRuntimeDeviceTracker());
|
||||
|
||||
/// Destructor is not thread safe
|
||||
VTKM_CONT ~ScopedRuntimeDeviceTracker();
|
||||
|
||||
private:
|
||||
std::unique_ptr<detail::RuntimeDeviceTrackerInternals> SavedState;
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace vtkm::cont
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <vtkm/cont/ErrorBadType.h>
|
||||
#include <vtkm/cont/ErrorBadValue.h>
|
||||
#include <vtkm/cont/ErrorFilterExecution.h>
|
||||
#include <vtkm/cont/ErrorUserAbort.h>
|
||||
#include <vtkm/cont/RuntimeDeviceTracker.h>
|
||||
|
||||
namespace vtkm
|
||||
@ -55,6 +56,13 @@ VTKM_CONT_EXPORT void HandleTryExecuteException(vtkm::cont::DeviceAdapterId devi
|
||||
VTKM_LOG_TRYEXECUTE_FAIL("ErrorBadValue (" << e.GetMessage() << ")", functorName, deviceId);
|
||||
throw;
|
||||
}
|
||||
catch (vtkm::cont::ErrorUserAbort& e)
|
||||
{
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info,
|
||||
e.GetMessage() << " Aborting: " << functorName << ", on device "
|
||||
<< deviceId.GetName());
|
||||
throw;
|
||||
}
|
||||
catch (vtkm::cont::Error& e)
|
||||
{
|
||||
VTKM_LOG_TRYEXECUTE_FAIL(e.GetMessage(), functorName, deviceId);
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include <vtkm/cont/DeviceAdapterList.h>
|
||||
#include <vtkm/cont/DeviceAdapterTag.h>
|
||||
#include <vtkm/cont/ErrorUserAbort.h>
|
||||
#include <vtkm/cont/Logging.h>
|
||||
#include <vtkm/cont/RuntimeDeviceTracker.h>
|
||||
|
||||
@ -40,6 +41,11 @@ inline bool TryExecuteIfValid(std::true_type,
|
||||
{
|
||||
try
|
||||
{
|
||||
if (tracker.CheckForAbortRequest())
|
||||
{
|
||||
throw vtkm::cont::ErrorUserAbort{};
|
||||
}
|
||||
|
||||
return f(tag, std::forward<Args>(args)...);
|
||||
}
|
||||
catch (...)
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <vtkm/cont/ArrayHandleIndex.h>
|
||||
#include <vtkm/cont/ArrayHandlePermutation.h>
|
||||
#include <vtkm/cont/ArrayHandleReverse.h>
|
||||
#include <vtkm/cont/ArrayHandleRuntimeVec.h>
|
||||
#include <vtkm/cont/ArrayHandleSOA.h>
|
||||
#include <vtkm/cont/ArrayHandleUniformPointCoordinates.h>
|
||||
#include <vtkm/cont/ErrorBadType.h>
|
||||
@ -45,12 +46,16 @@ struct AllVecImpl<N, vtkm::List<Scalars...>>
|
||||
template <vtkm::IdComponent N>
|
||||
using AllVec = typename AllVecImpl<N, vtkm::TypeListBaseC>::type;
|
||||
|
||||
template <typename T>
|
||||
using IsBasicStorage = std::is_same<vtkm::cont::StorageTagBasic, T>;
|
||||
template <typename List>
|
||||
using RemoveBasicStorage = vtkm::ListRemoveIf<List, IsBasicStorage>;
|
||||
|
||||
using UnknownSerializationTypes =
|
||||
vtkm::ListAppend<vtkm::TypeListBaseC, AllVec<2>, AllVec<3>, AllVec<4>>;
|
||||
using UnknownSerializationStorage =
|
||||
vtkm::ListAppend<VTKM_DEFAULT_STORAGE_LIST,
|
||||
vtkm::List<vtkm::cont::StorageTagBasic,
|
||||
vtkm::cont::StorageTagCartesianProduct<vtkm::cont::StorageTagBasic,
|
||||
using UnknownSerializationSpecializedStorage =
|
||||
vtkm::ListAppend<RemoveBasicStorage<VTKM_DEFAULT_STORAGE_LIST>,
|
||||
vtkm::List<vtkm::cont::StorageTagCartesianProduct<vtkm::cont::StorageTagBasic,
|
||||
vtkm::cont::StorageTagBasic,
|
||||
vtkm::cont::StorageTagBasic>,
|
||||
vtkm::cont::StorageTagConstant,
|
||||
@ -265,7 +270,7 @@ vtkm::IdComponent UnknownArrayHandle::GetNumberOfComponents() const
|
||||
{
|
||||
if (this->Container)
|
||||
{
|
||||
return this->Container->NumberOfComponents();
|
||||
return this->Container->NumberOfComponents(this->Container->ArrayHandlePointer);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -277,7 +282,7 @@ VTKM_CONT vtkm::IdComponent UnknownArrayHandle::GetNumberOfComponentsFlat() cons
|
||||
{
|
||||
if (this->Container)
|
||||
{
|
||||
return this->Container->NumberOfComponentsFlat();
|
||||
return this->Container->NumberOfComponentsFlat(this->Container->ArrayHandlePointer);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -432,30 +437,82 @@ std::string SerializableTypeString<vtkm::cont::UnknownArrayHandle>::Get()
|
||||
}
|
||||
} // namespace vtkm::cont
|
||||
|
||||
namespace mangled_diy_namespace
|
||||
namespace
|
||||
{
|
||||
|
||||
void Serialization<vtkm::cont::UnknownArrayHandle>::save(BinaryBuffer& bb,
|
||||
const vtkm::cont::UnknownArrayHandle& obj)
|
||||
enum struct SerializedArrayType : vtkm::UInt8
|
||||
{
|
||||
BasicArray = 0,
|
||||
SpecializedStorage
|
||||
};
|
||||
|
||||
struct SaveBasicArray
|
||||
{
|
||||
template <typename ComponentType>
|
||||
VTKM_CONT void operator()(ComponentType,
|
||||
mangled_diy_namespace::BinaryBuffer& bb,
|
||||
const vtkm::cont::UnknownArrayHandle& obj,
|
||||
bool& saved)
|
||||
{
|
||||
// Basic arrays and arrays with compatible layouts can be loaed/saved as an
|
||||
// ArrayHandleRuntimeVec. Thus, we can load/save them all with one routine.
|
||||
using ArrayType = vtkm::cont::ArrayHandleRuntimeVec<ComponentType>;
|
||||
if (!saved && obj.CanConvert<ArrayType>())
|
||||
{
|
||||
ArrayType array = obj.AsArrayHandle<ArrayType>();
|
||||
vtkmdiy::save(bb, SerializedArrayType::BasicArray);
|
||||
vtkmdiy::save(bb, vtkm::cont::TypeToString<ComponentType>());
|
||||
vtkmdiy::save(bb, array);
|
||||
saved = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct LoadBasicArray
|
||||
{
|
||||
template <typename ComponentType>
|
||||
VTKM_CONT void operator()(ComponentType,
|
||||
mangled_diy_namespace::BinaryBuffer& bb,
|
||||
vtkm::cont::UnknownArrayHandle& obj,
|
||||
const std::string& componentTypeString,
|
||||
bool& loaded)
|
||||
{
|
||||
if (!loaded && (componentTypeString == vtkm::cont::TypeToString<ComponentType>()))
|
||||
{
|
||||
vtkm::cont::ArrayHandleRuntimeVec<ComponentType> array;
|
||||
vtkmdiy::load(bb, array);
|
||||
obj = array;
|
||||
loaded = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
VTKM_CONT void SaveSpecializedArray(mangled_diy_namespace::BinaryBuffer& bb,
|
||||
const vtkm::cont::UnknownArrayHandle& obj)
|
||||
{
|
||||
vtkm::IdComponent numComponents = obj.GetNumberOfComponents();
|
||||
switch (numComponents)
|
||||
{
|
||||
case 1:
|
||||
vtkmdiy::save(bb, SerializedArrayType::SpecializedStorage);
|
||||
vtkmdiy::save(bb, numComponents);
|
||||
vtkmdiy::save(bb, obj.ResetTypes<vtkm::TypeListBaseC, UnknownSerializationStorage>());
|
||||
vtkmdiy::save(bb,
|
||||
obj.ResetTypes<vtkm::TypeListBaseC, UnknownSerializationSpecializedStorage>());
|
||||
break;
|
||||
case 2:
|
||||
vtkmdiy::save(bb, SerializedArrayType::SpecializedStorage);
|
||||
vtkmdiy::save(bb, numComponents);
|
||||
vtkmdiy::save(bb, obj.ResetTypes<AllVec<2>, UnknownSerializationStorage>());
|
||||
vtkmdiy::save(bb, obj.ResetTypes<AllVec<2>, UnknownSerializationSpecializedStorage>());
|
||||
break;
|
||||
case 3:
|
||||
vtkmdiy::save(bb, SerializedArrayType::SpecializedStorage);
|
||||
vtkmdiy::save(bb, numComponents);
|
||||
vtkmdiy::save(bb, obj.ResetTypes<AllVec<3>, UnknownSerializationStorage>());
|
||||
vtkmdiy::save(bb, obj.ResetTypes<AllVec<3>, UnknownSerializationSpecializedStorage>());
|
||||
break;
|
||||
case 4:
|
||||
vtkmdiy::save(bb, SerializedArrayType::SpecializedStorage);
|
||||
vtkmdiy::save(bb, numComponents);
|
||||
vtkmdiy::save(bb, obj.ResetTypes<AllVec<4>, UnknownSerializationStorage>());
|
||||
vtkmdiy::save(bb, obj.ResetTypes<AllVec<4>, UnknownSerializationSpecializedStorage>());
|
||||
break;
|
||||
default:
|
||||
throw vtkm::cont::ErrorBadType(
|
||||
@ -465,16 +522,17 @@ void Serialization<vtkm::cont::UnknownArrayHandle>::save(BinaryBuffer& bb,
|
||||
}
|
||||
}
|
||||
|
||||
void Serialization<vtkm::cont::UnknownArrayHandle>::load(BinaryBuffer& bb,
|
||||
vtkm::cont::UnknownArrayHandle& obj)
|
||||
VTKM_CONT void LoadSpecializedArray(mangled_diy_namespace::BinaryBuffer& bb,
|
||||
vtkm::cont::UnknownArrayHandle& obj)
|
||||
{
|
||||
vtkm::IdComponent numComponents;
|
||||
vtkmdiy::load(bb, numComponents);
|
||||
|
||||
vtkm::cont::UncertainArrayHandle<vtkm::TypeListBaseC, UnknownSerializationStorage> array1;
|
||||
vtkm::cont::UncertainArrayHandle<AllVec<2>, UnknownSerializationStorage> array2;
|
||||
vtkm::cont::UncertainArrayHandle<AllVec<3>, UnknownSerializationStorage> array3;
|
||||
vtkm::cont::UncertainArrayHandle<AllVec<4>, UnknownSerializationStorage> array4;
|
||||
vtkm::cont::UncertainArrayHandle<vtkm::TypeListBaseC, UnknownSerializationSpecializedStorage>
|
||||
array1;
|
||||
vtkm::cont::UncertainArrayHandle<AllVec<2>, UnknownSerializationSpecializedStorage> array2;
|
||||
vtkm::cont::UncertainArrayHandle<AllVec<3>, UnknownSerializationSpecializedStorage> array3;
|
||||
vtkm::cont::UncertainArrayHandle<AllVec<4>, UnknownSerializationSpecializedStorage> array4;
|
||||
|
||||
switch (numComponents)
|
||||
{
|
||||
@ -499,4 +557,53 @@ void Serialization<vtkm::cont::UnknownArrayHandle>::load(BinaryBuffer& bb,
|
||||
}
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
namespace mangled_diy_namespace
|
||||
{
|
||||
|
||||
void Serialization<vtkm::cont::UnknownArrayHandle>::save(BinaryBuffer& bb,
|
||||
const vtkm::cont::UnknownArrayHandle& obj)
|
||||
{
|
||||
bool saved = false;
|
||||
|
||||
// First, try serializing basic arrays (which we can do for any Vec size).
|
||||
vtkm::ListForEach(SaveBasicArray{}, vtkm::TypeListBaseC{}, bb, obj, saved);
|
||||
|
||||
// If that did not work, try one of the specialized arrays.
|
||||
if (!saved)
|
||||
{
|
||||
SaveSpecializedArray(bb, obj);
|
||||
}
|
||||
}
|
||||
|
||||
void Serialization<vtkm::cont::UnknownArrayHandle>::load(BinaryBuffer& bb,
|
||||
vtkm::cont::UnknownArrayHandle& obj)
|
||||
{
|
||||
SerializedArrayType arrayType;
|
||||
vtkmdiy::load(bb, arrayType);
|
||||
|
||||
switch (arrayType)
|
||||
{
|
||||
case SerializedArrayType::BasicArray:
|
||||
{
|
||||
std::string componentTypeString;
|
||||
vtkmdiy::load(bb, componentTypeString);
|
||||
bool loaded = false;
|
||||
vtkm::ListForEach(
|
||||
LoadBasicArray{}, vtkm::TypeListBaseC{}, bb, obj, componentTypeString, loaded);
|
||||
if (!loaded)
|
||||
{
|
||||
throw vtkm::cont::ErrorInternal("Failed to load basic array. Unexpected buffer values.");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SerializedArrayType::SpecializedStorage:
|
||||
LoadSpecializedArray(bb, obj);
|
||||
break;
|
||||
default:
|
||||
throw vtkm::cont::ErrorInternal("Got inappropriate enumeration value for loading array.");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mangled_diy_namespace
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <vtkm/cont/ArrayHandleCast.h>
|
||||
#include <vtkm/cont/ArrayHandleMultiplexer.h>
|
||||
#include <vtkm/cont/ArrayHandleRecombineVec.h>
|
||||
#include <vtkm/cont/ArrayHandleRuntimeVec.h>
|
||||
#include <vtkm/cont/ArrayHandleStride.h>
|
||||
#include <vtkm/cont/StorageList.h>
|
||||
|
||||
@ -42,6 +43,14 @@ void UnknownAHDelete(void* mem)
|
||||
delete arrayHandle;
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
const std::vector<vtkm::cont::internal::Buffer>& UnknownAHBuffers(void* mem)
|
||||
{
|
||||
using AH = vtkm::cont::ArrayHandle<T, S>;
|
||||
AH* arrayHandle = reinterpret_cast<AH*>(mem);
|
||||
return arrayHandle->GetBuffers();
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
void* UnknownAHNewInstance()
|
||||
{
|
||||
@ -56,49 +65,86 @@ vtkm::Id UnknownAHNumberOfValues(void* mem)
|
||||
return arrayHandle->GetNumberOfValues();
|
||||
}
|
||||
|
||||
template <typename T, typename StaticSize = typename vtkm::internal::SafeVecTraits<T>::IsSizeStatic>
|
||||
struct UnknownAHNumberOfComponentsImpl;
|
||||
template <typename T>
|
||||
struct UnknownAHNumberOfComponentsImpl<T, vtkm::VecTraitsTagSizeStatic>
|
||||
// Uses SFINAE to use Storage<>::GetNumberOfComponents if it exists, or the VecTraits otherwise
|
||||
template <typename T, typename S>
|
||||
inline auto UnknownAHNumberOfComponentsImpl(void* mem)
|
||||
-> decltype(vtkm::cont::internal::Storage<T, S>::GetNumberOfComponents(
|
||||
std::vector<vtkm::cont::internal::Buffer>()))
|
||||
{
|
||||
static constexpr vtkm::IdComponent Value = vtkm::internal::SafeVecTraits<T>::NUM_COMPONENTS;
|
||||
};
|
||||
template <typename T>
|
||||
struct UnknownAHNumberOfComponentsImpl<T, vtkm::VecTraitsTagSizeVariable>
|
||||
{
|
||||
static constexpr vtkm::IdComponent Value = 0;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
vtkm::IdComponent UnknownAHNumberOfComponents()
|
||||
{
|
||||
return UnknownAHNumberOfComponentsImpl<T>::Value;
|
||||
using AH = vtkm::cont::ArrayHandle<T, S>;
|
||||
AH* arrayHandle = reinterpret_cast<AH*>(mem);
|
||||
return vtkm::cont::internal::Storage<T, S>::GetNumberOfComponents(arrayHandle->GetBuffers());
|
||||
}
|
||||
|
||||
template <typename T,
|
||||
typename = typename vtkm::internal::SafeVecTraits<T>::IsSizeStatic,
|
||||
typename = vtkm::HasVecTraits<T>>
|
||||
struct UnknownAHNumberOfComponentsFlatImpl;
|
||||
template <typename T>
|
||||
struct UnknownAHNumberOfComponentsFlatImpl<T, vtkm::VecTraitsTagSizeStatic, std::true_type>
|
||||
// Uses SFINAE to use the number of compnents in VecTraits.
|
||||
// Note that this will conflict with the above overloaded function if the storage has a
|
||||
// GetNumberOfComponents method and VecTraits has a static size. However, I cannot think
|
||||
// of a use case for the storage to report the number of components for a static data type.
|
||||
// If that happens, this implementation will need to be modified.
|
||||
template <typename T, typename S>
|
||||
inline auto UnknownAHNumberOfComponentsImpl(void*) -> decltype(vtkm::VecTraits<T>::NUM_COMPONENTS)
|
||||
{
|
||||
static constexpr vtkm::IdComponent Value = vtkm::VecFlat<T>::NUM_COMPONENTS;
|
||||
};
|
||||
template <typename T>
|
||||
struct UnknownAHNumberOfComponentsFlatImpl<T, vtkm::VecTraitsTagSizeVariable, std::true_type>
|
||||
{
|
||||
static constexpr vtkm::IdComponent Value = 0;
|
||||
};
|
||||
template <typename T>
|
||||
struct UnknownAHNumberOfComponentsFlatImpl<T, vtkm::VecTraitsTagSizeStatic, std::false_type>
|
||||
{
|
||||
static constexpr vtkm::IdComponent Value = 1;
|
||||
};
|
||||
static constexpr vtkm::IdComponent numComponents = vtkm::VecTraits<T>::NUM_COMPONENTS;
|
||||
return numComponents;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
vtkm::IdComponent UnknownAHNumberOfComponentsFlat()
|
||||
// Fallback for when there is no way to determine the number of components. (This could be
|
||||
// because each value could have a different number of components.
|
||||
template <typename T, typename S>
|
||||
inline vtkm::IdComponent UnknownAHNumberOfComponentsImpl(...)
|
||||
{
|
||||
return UnknownAHNumberOfComponentsFlatImpl<T>::Value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
vtkm::IdComponent UnknownAHNumberOfComponents(void* mem)
|
||||
{
|
||||
return UnknownAHNumberOfComponentsImpl<T, S>(mem);
|
||||
}
|
||||
|
||||
// Uses SFINAE to use Storage<>::GetNumberOfComponents if it exists, or the VecTraits otherwise
|
||||
template <typename T, typename S>
|
||||
inline auto UnknownAHNumberOfComponentsFlatImpl(void* mem)
|
||||
-> decltype(vtkm::cont::internal::Storage<T, S>::GetNumberOfComponents(
|
||||
std::vector<vtkm::cont::internal::Buffer>()))
|
||||
{
|
||||
using AH = vtkm::cont::ArrayHandle<T, S>;
|
||||
AH* arrayHandle = reinterpret_cast<AH*>(mem);
|
||||
// Making an assumption here that `T` is a `Vec`-like object that `GetNumberOfComponents`
|
||||
// will report on how many each has. Further assuming that the components of `T` are
|
||||
// static. If a future `ArrayHandle` type violates this, this code will have to become
|
||||
// more complex.
|
||||
return (vtkm::cont::internal::Storage<T, S>::GetNumberOfComponents(arrayHandle->GetBuffers()) *
|
||||
vtkm::VecFlat<typename vtkm::VecTraits<T>::ComponentType>::NUM_COMPONENTS);
|
||||
}
|
||||
|
||||
// Uses SFINAE to use the number of compnents in VecTraits.
|
||||
// Note that this will conflict with the above overloaded function if the storage has a
|
||||
// GetNumberOfComponents method and VecTraits has a static size. However, I cannot think
|
||||
// of a use case for the storage to report the number of components for a static data type.
|
||||
// If that happens, this implementation will need to be modified.
|
||||
template <typename T, typename S>
|
||||
inline auto UnknownAHNumberOfComponentsFlatImpl(void*)
|
||||
-> decltype(vtkm::VecTraits<T>::NUM_COMPONENTS)
|
||||
{
|
||||
// static constexpr vtkm::IdComponent numComponents = vtkm::VecFlat<T>::NUM_COMPONENTS;
|
||||
// return numComponents;
|
||||
return vtkm::VecFlat<T>::NUM_COMPONENTS;
|
||||
}
|
||||
|
||||
// Fallback for when there is no way to determine the number of components. (This could be
|
||||
// because each value could have a different number of components or just that VecTraits
|
||||
// are not defined.) Since it cannot be flattened, just return the same as num components.
|
||||
template <typename T, typename S>
|
||||
inline vtkm::IdComponent UnknownAHNumberOfComponentsFlatImpl(...)
|
||||
{
|
||||
return UnknownAHNumberOfComponentsImpl<T, S>(static_cast<void*>(nullptr));
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
vtkm::IdComponent UnknownAHNumberOfComponentsFlat(void* mem)
|
||||
{
|
||||
return UnknownAHNumberOfComponentsFlatImpl<T, S>(mem);
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
@ -220,6 +266,9 @@ struct VTKM_CONT_EXPORT UnknownAHContainer
|
||||
using DeleteType = void(void*);
|
||||
DeleteType* DeleteFunction;
|
||||
|
||||
using BuffersType = const std::vector<vtkm::cont::internal::Buffer>&(void*);
|
||||
BuffersType* Buffers;
|
||||
|
||||
using NewInstanceType = void*();
|
||||
NewInstanceType* NewInstance;
|
||||
|
||||
@ -230,7 +279,7 @@ struct VTKM_CONT_EXPORT UnknownAHContainer
|
||||
using NumberOfValuesType = vtkm::Id(void*);
|
||||
NumberOfValuesType* NumberOfValues;
|
||||
|
||||
using NumberOfComponentsType = vtkm::IdComponent();
|
||||
using NumberOfComponentsType = vtkm::IdComponent(void*);
|
||||
NumberOfComponentsType* NumberOfComponents;
|
||||
NumberOfComponentsType* NumberOfComponentsFlat;
|
||||
|
||||
@ -313,14 +362,13 @@ std::shared_ptr<UnknownAHContainer> UnknownAHNewInstanceBasic(vtkm::VecTraitsTag
|
||||
template <typename T>
|
||||
std::shared_ptr<UnknownAHContainer> UnknownAHNewInstanceBasic()
|
||||
{
|
||||
return UnknownAHNewInstanceBasic<T>(typename vtkm::internal::SafeVecTraits<T>::IsSizeStatic{});
|
||||
return UnknownAHNewInstanceBasic<T>(typename vtkm::VecTraits<T>::IsSizeStatic{});
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::shared_ptr<UnknownAHContainer> UnknownAHNewInstanceFloatBasic(vtkm::VecTraitsTagSizeStatic)
|
||||
{
|
||||
using FloatT = typename vtkm::internal::SafeVecTraits<T>::template ReplaceBaseComponentType<
|
||||
vtkm::FloatDefault>;
|
||||
using FloatT = typename vtkm::VecTraits<T>::template ReplaceBaseComponentType<vtkm::FloatDefault>;
|
||||
return UnknownAHContainer::Make(vtkm::cont::ArrayHandleBasic<FloatT>{});
|
||||
}
|
||||
template <typename T>
|
||||
@ -332,8 +380,7 @@ std::shared_ptr<UnknownAHContainer> UnknownAHNewInstanceFloatBasic(vtkm::VecTrai
|
||||
template <typename T>
|
||||
std::shared_ptr<UnknownAHContainer> UnknownAHNewInstanceFloatBasic()
|
||||
{
|
||||
return UnknownAHNewInstanceFloatBasic<T>(
|
||||
typename vtkm::internal::SafeVecTraits<T>::IsSizeStatic{});
|
||||
return UnknownAHNewInstanceFloatBasic<T>(typename vtkm::VecTraits<T>::IsSizeStatic{});
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
@ -342,14 +389,15 @@ inline UnknownAHContainer::UnknownAHContainer(const vtkm::cont::ArrayHandle<T, S
|
||||
, ValueType(typeid(T))
|
||||
, StorageType(typeid(S))
|
||||
, BaseComponentType(
|
||||
UnknownAHComponentInfo::Make<typename vtkm::internal::SafeVecTraits<T>::BaseComponentType>())
|
||||
UnknownAHComponentInfo::Make<typename vtkm::VecTraits<T>::BaseComponentType>())
|
||||
, DeleteFunction(detail::UnknownAHDelete<T, S>)
|
||||
, Buffers(detail::UnknownAHBuffers<T, S>)
|
||||
, NewInstance(detail::UnknownAHNewInstance<T, S>)
|
||||
, NewInstanceBasic(detail::UnknownAHNewInstanceBasic<T>)
|
||||
, NewInstanceFloatBasic(detail::UnknownAHNewInstanceFloatBasic<T>)
|
||||
, NumberOfValues(detail::UnknownAHNumberOfValues<T, S>)
|
||||
, NumberOfComponents(detail::UnknownAHNumberOfComponents<T>)
|
||||
, NumberOfComponentsFlat(detail::UnknownAHNumberOfComponentsFlat<T>)
|
||||
, NumberOfComponents(detail::UnknownAHNumberOfComponents<T, S>)
|
||||
, NumberOfComponentsFlat(detail::UnknownAHNumberOfComponentsFlat<T, S>)
|
||||
, Allocate(detail::UnknownAHAllocate<T, S>)
|
||||
, ShallowCopy(detail::UnknownAHShallowCopy<T, S>)
|
||||
, DeepCopy(detail::UnknownAHDeepCopy<T, S>)
|
||||
@ -607,13 +655,10 @@ public:
|
||||
#ifdef VTKM_MSVC
|
||||
VTKM_DEPRECATED_SUPPRESS_BEGIN
|
||||
#endif
|
||||
///@{
|
||||
/// Returns this array cast appropriately and stored in the given `ArrayHandle` type.
|
||||
/// Throws an `ErrorBadType` if the stored array cannot be stored in the given array type.
|
||||
/// Use the `CanConvert` method to determine if the array can be returned with the given type.
|
||||
///
|
||||
|
||||
private:
|
||||
template <typename T, typename S>
|
||||
VTKM_CONT void AsArrayHandle(vtkm::cont::ArrayHandle<T, S>& array) const
|
||||
VTKM_CONT void BaseAsArrayHandle(vtkm::cont::ArrayHandle<T, S>& array) const
|
||||
{
|
||||
using ArrayType = vtkm::cont::ArrayHandle<T, S>;
|
||||
if (!this->IsType<ArrayType>())
|
||||
@ -625,6 +670,21 @@ public:
|
||||
array = *reinterpret_cast<ArrayType*>(this->Container->ArrayHandlePointer);
|
||||
}
|
||||
|
||||
public:
|
||||
///@{
|
||||
/// Returns this array cast appropriately and stored in the given `ArrayHandle` type.
|
||||
/// Throws an `ErrorBadType` if the stored array cannot be stored in the given array type.
|
||||
/// Use the `CanConvert` method to determine if the array can be returned with the given type.
|
||||
///
|
||||
template <typename T, typename S>
|
||||
VTKM_CONT void AsArrayHandle(vtkm::cont::ArrayHandle<T, S>& array) const
|
||||
{
|
||||
this->BaseAsArrayHandle(array);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
VTKM_CONT void AsArrayHandle(vtkm::cont::ArrayHandle<T>& array) const;
|
||||
|
||||
template <typename T, typename... Ss>
|
||||
VTKM_CONT void AsArrayHandle(
|
||||
vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagMultiplexer<Ss...>>& array) const;
|
||||
@ -638,6 +698,26 @@ public:
|
||||
this->AsArrayHandle<ContainedArrayType>());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
VTKM_CONT void AsArrayHandle(
|
||||
vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagRuntimeVec>& array) const
|
||||
{
|
||||
using BaseT = typename T::ComponentType;
|
||||
if (this->IsStorageType<vtkm::cont::StorageTagBasic>() && this->IsBaseComponentType<BaseT>())
|
||||
{
|
||||
// Reinterpret the basic array as components, and then wrap that in a runtime vec
|
||||
// with the correct amount of components.
|
||||
vtkm::cont::ArrayHandle<BaseT, vtkm::cont::StorageTagBasic> basicArray(
|
||||
this->Container->Buffers(this->Container->ArrayHandlePointer));
|
||||
array =
|
||||
vtkm::cont::ArrayHandleRuntimeVec<BaseT>(this->GetNumberOfComponentsFlat(), basicArray);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->BaseAsArrayHandle(array);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename ArrayType>
|
||||
VTKM_CONT ArrayType AsArrayHandle() const
|
||||
{
|
||||
@ -877,6 +957,19 @@ struct UnknownArrayHandleCanConvert
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct UnknownArrayHandleCanConvert<T, vtkm::cont::StorageTagBasic>
|
||||
{
|
||||
VTKM_CONT bool operator()(const vtkm::cont::UnknownArrayHandle& array) const
|
||||
{
|
||||
using UnrolledVec = vtkm::internal::UnrollVec<T>;
|
||||
return (array.IsType<vtkm::cont::ArrayHandleBasic<T>>() ||
|
||||
(array.IsStorageType<vtkm::cont::StorageTagRuntimeVec>() &&
|
||||
array.IsBaseComponentType<typename UnrolledVec::ComponentType>() &&
|
||||
UnrolledVec::NUM_COMPONENTS == array.GetNumberOfComponentsFlat()));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TargetT, typename SourceT, typename SourceS>
|
||||
struct UnknownArrayHandleCanConvert<TargetT, vtkm::cont::StorageTagCast<SourceT, SourceS>>
|
||||
{
|
||||
@ -907,10 +1000,22 @@ struct UnknownArrayHandleCanConvert<T, vtkm::cont::StorageTagMultiplexer<Ss...>>
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct UnknownArrayHandleCanConvert<T, vtkm::cont::StorageTagRuntimeVec>
|
||||
{
|
||||
VTKM_CONT bool operator()(const vtkm::cont::UnknownArrayHandle& array) const
|
||||
{
|
||||
using BaseComponentType = typename T::ComponentType;
|
||||
return (array.IsType<vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagRuntimeVec>>() ||
|
||||
(array.IsStorageType<vtkm::cont::StorageTagBasic>() &&
|
||||
array.IsBaseComponentType<BaseComponentType>()));
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename ArrayHandleType>
|
||||
VTKM_CONT bool UnknownArrayHandle::CanConvert() const
|
||||
VTKM_CONT inline bool UnknownArrayHandle::CanConvert() const
|
||||
{
|
||||
VTKM_IS_ARRAY_HANDLE(ArrayHandleType);
|
||||
|
||||
@ -921,6 +1026,66 @@ VTKM_CONT bool UnknownArrayHandle::CanConvert() const
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <typename T,
|
||||
vtkm::IdComponent =
|
||||
vtkm::VecTraits<typename vtkm::internal::UnrollVec<T>::ComponentType>::NUM_COMPONENTS>
|
||||
struct UnknownArrayHandleRuntimeVecAsBasic
|
||||
{
|
||||
VTKM_CONT bool operator()(const vtkm::cont::UnknownArrayHandle*,
|
||||
const detail::UnknownAHContainer*,
|
||||
vtkm::cont::ArrayHandle<T>&) const
|
||||
{
|
||||
// This version only gets called if T contains a `Vec`-like object that is not a strict `Vec`.
|
||||
// This is rare but could happen. In this case, the type cannot be stored in an
|
||||
// `ArrayHandleRuntimeVec` and therefore the load can never happen, so just ignore.
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct UnknownArrayHandleRuntimeVecAsBasic<T, 1>
|
||||
{
|
||||
VTKM_CONT bool operator()(const vtkm::cont::UnknownArrayHandle* self,
|
||||
const detail::UnknownAHContainer* container,
|
||||
vtkm::cont::ArrayHandle<T>& array) const
|
||||
{
|
||||
using UnrolledVec = vtkm::internal::UnrollVec<T>;
|
||||
using ComponentType = typename UnrolledVec::ComponentType;
|
||||
if (self->IsStorageType<vtkm::cont::StorageTagRuntimeVec>() &&
|
||||
self->IsBaseComponentType<ComponentType>() &&
|
||||
UnrolledVec::NUM_COMPONENTS == self->GetNumberOfComponentsFlat())
|
||||
{
|
||||
// Pull out the components array out of the buffers. The array might not match exactly
|
||||
// the array put in, but the buffer should still be consistent with the array (which works
|
||||
// because the size of a basic array is based on the number of bytes in the buffer).
|
||||
using RuntimeVecType = typename vtkm::cont::ArrayHandleRuntimeVec<ComponentType>::ValueType;
|
||||
using StorageRuntimeVec =
|
||||
vtkm::cont::internal::Storage<RuntimeVecType, vtkm::cont::StorageTagRuntimeVec>;
|
||||
StorageRuntimeVec::AsArrayHandleBasic(container->Buffers(container->ArrayHandlePointer),
|
||||
array);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename T>
|
||||
VTKM_CONT inline void UnknownArrayHandle::AsArrayHandle(vtkm::cont::ArrayHandle<T>& array) const
|
||||
{
|
||||
if (!detail::UnknownArrayHandleRuntimeVecAsBasic<T>{}(this, this->Container.get(), array))
|
||||
{
|
||||
this->BaseAsArrayHandle(array);
|
||||
}
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
struct UnknownArrayHandleMultiplexerCastTry
|
||||
{
|
||||
template <typename T, typename S, typename... Ss>
|
||||
|
@ -36,7 +36,6 @@ struct MapPermutationWorklet : vtkm::worklet::WorkletMapField
|
||||
InputPortalType inputPortal,
|
||||
OutputType& output) const
|
||||
{
|
||||
VTKM_STATIC_ASSERT(vtkm::HasVecTraits<OutputType>::value);
|
||||
if ((permutationIndex >= 0) && (permutationIndex < inputPortal.GetNumberOfValues()))
|
||||
{
|
||||
output = inputPortal.Get(permutationIndex);
|
||||
|
@ -32,6 +32,21 @@ VTKM_THIRDPARTY_POST_INCLUDE
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#if KOKKOS_VERSION_MAJOR > 3 || (KOKKOS_VERSION_MAJOR == 3 && KOKKOS_VERSION_MINOR >= 7)
|
||||
#define VTKM_VOLATILE
|
||||
#else
|
||||
#define VTKM_VOLATILE volatile
|
||||
#endif
|
||||
|
||||
#if defined(VTKM_ENABLE_KOKKOS_THRUST) && (defined(__HIP__) || defined(__CUDA__))
|
||||
#define VTKM_USE_KOKKOS_THRUST
|
||||
#endif
|
||||
|
||||
#if defined(VTKM_USE_KOKKOS_THRUST)
|
||||
#include <thrust/device_ptr.h>
|
||||
#include <thrust/sort.h>
|
||||
#endif
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace internal
|
||||
@ -256,7 +271,7 @@ private:
|
||||
}
|
||||
|
||||
KOKKOS_INLINE_FUNCTION
|
||||
void join(volatile value_type& dst, const volatile value_type& src) const
|
||||
void join(VTKM_VOLATILE value_type& dst, const VTKM_VOLATILE value_type& src) const
|
||||
{
|
||||
dst = this->Operator(dst, src);
|
||||
}
|
||||
@ -764,6 +779,88 @@ public:
|
||||
SortImpl(values, comp, typename std::is_scalar<T>::type{});
|
||||
}
|
||||
|
||||
protected:
|
||||
// Kokkos currently (11/10/2022) does not support a sort_by_key operator
|
||||
// so instead we are using thrust if and only if HIP or CUDA are the backends for Kokkos
|
||||
#if defined(VTKM_USE_KOKKOS_THRUST)
|
||||
|
||||
template <typename T, typename U, typename BinaryCompare>
|
||||
VTKM_CONT static std::enable_if_t<(std::is_same<BinaryCompare, vtkm::SortLess>::value ||
|
||||
std::is_same<BinaryCompare, vtkm::SortGreater>::value)>
|
||||
SortByKeyImpl(vtkm::cont::ArrayHandle<T>& keys,
|
||||
vtkm::cont::ArrayHandle<U>& values,
|
||||
BinaryCompare,
|
||||
std::true_type,
|
||||
std::true_type)
|
||||
{
|
||||
vtkm::cont::Token token;
|
||||
auto keys_portal = keys.PrepareForInPlace(vtkm::cont::DeviceAdapterTagKokkos{}, token);
|
||||
auto values_portal = values.PrepareForInPlace(vtkm::cont::DeviceAdapterTagKokkos{}, token);
|
||||
|
||||
kokkos::internal::KokkosViewExec<T> keys_view(keys_portal.GetArray(),
|
||||
keys_portal.GetNumberOfValues());
|
||||
kokkos::internal::KokkosViewExec<U> values_view(values_portal.GetArray(),
|
||||
values_portal.GetNumberOfValues());
|
||||
|
||||
thrust::device_ptr<T> keys_begin(keys_view.data());
|
||||
thrust::device_ptr<T> keys_end(keys_view.data() + keys_view.size());
|
||||
thrust::device_ptr<U> values_begin(values_view.data());
|
||||
|
||||
if (std::is_same<BinaryCompare, vtkm::SortLess>::value)
|
||||
{
|
||||
thrust::sort_by_key(keys_begin, keys_end, values_begin, thrust::less<T>());
|
||||
}
|
||||
else
|
||||
{
|
||||
thrust::sort_by_key(keys_begin, keys_end, values_begin, thrust::greater<T>());
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
template <typename T,
|
||||
typename U,
|
||||
class StorageT,
|
||||
class StorageU,
|
||||
class BinaryCompare,
|
||||
typename ValidKeys,
|
||||
typename ValidValues>
|
||||
VTKM_CONT static void SortByKeyImpl(vtkm::cont::ArrayHandle<T, StorageT>& keys,
|
||||
vtkm::cont::ArrayHandle<U, StorageU>& values,
|
||||
BinaryCompare binary_compare,
|
||||
ValidKeys,
|
||||
ValidValues)
|
||||
{
|
||||
// Default to general algorithm
|
||||
Superclass::SortByKey(keys, values, binary_compare);
|
||||
}
|
||||
|
||||
public:
|
||||
template <typename T, typename U, class StorageT, class StorageU>
|
||||
VTKM_CONT static void SortByKey(vtkm::cont::ArrayHandle<T, StorageT>& keys,
|
||||
vtkm::cont::ArrayHandle<U, StorageU>& values)
|
||||
{
|
||||
// Make sure not to use the general algorithm here since
|
||||
// it will use Sort algorithm instead of SortByKey
|
||||
SortByKey(keys, values, internal::DefaultCompareFunctor());
|
||||
}
|
||||
|
||||
template <typename T, typename U, class StorageT, class StorageU, class BinaryCompare>
|
||||
VTKM_CONT static void SortByKey(vtkm::cont::ArrayHandle<T, StorageT>& keys,
|
||||
vtkm::cont::ArrayHandle<U, StorageU>& values,
|
||||
BinaryCompare binary_compare)
|
||||
{
|
||||
// If T or U are not scalar types, or the BinaryCompare is not supported
|
||||
// then the general algorithm is called, otherwise we will run thrust
|
||||
SortByKeyImpl(keys,
|
||||
values,
|
||||
binary_compare,
|
||||
typename std::is_scalar<T>::type{},
|
||||
typename std::is_scalar<U>::type{});
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
VTKM_CONT static void Synchronize()
|
||||
{
|
||||
vtkm::cont::kokkos::internal::GetExecutionSpaceInstance().fence();
|
||||
@ -794,4 +891,6 @@ public:
|
||||
}
|
||||
} // namespace vtkm::cont
|
||||
|
||||
#undef VTKM_VOLATILE
|
||||
|
||||
#endif //vtk_m_cont_kokkos_internal_DeviceAdapterAlgorithmKokkos_h
|
||||
|
@ -85,6 +85,7 @@ set(unit_tests_device
|
||||
UnitTestArrayHandleRandomStandardNormal.cxx
|
||||
UnitTestArrayHandleRandomUniformReal.cxx
|
||||
UnitTestArrayHandleRecombineVec.cxx
|
||||
UnitTestArrayHandleRuntimeVec.cxx
|
||||
UnitTestArrayHandleSOA.cxx
|
||||
UnitTestArrayHandleSwizzle.cxx
|
||||
UnitTestArrayHandleTransform.cxx
|
||||
@ -122,6 +123,12 @@ if(TARGET vtkm_filter_field_conversion)
|
||||
)
|
||||
endif()
|
||||
|
||||
if(TARGET vtkm_filter_contour)
|
||||
list(APPEND unit_tests
|
||||
UnitTestAbort.cxx
|
||||
)
|
||||
endif()
|
||||
|
||||
vtkm_unit_tests(SOURCES ${unit_tests} DEVICE_SOURCES ${unit_tests_device})
|
||||
|
||||
#add distributed tests i.e.test to run with MPI
|
||||
|
105
vtkm/cont/testing/UnitTestAbort.cxx
Normal file
105
vtkm/cont/testing/UnitTestAbort.cxx
Normal file
@ -0,0 +1,105 @@
|
||||
//============================================================================
|
||||
// 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.
|
||||
//============================================================================
|
||||
|
||||
#include <vtkm/cont/ErrorUserAbort.h>
|
||||
#include <vtkm/cont/RuntimeDeviceTracker.h>
|
||||
#include <vtkm/cont/testing/Testing.h>
|
||||
#include <vtkm/filter/contour/Contour.h>
|
||||
#include <vtkm/source/Wavelet.h>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
// A function that checks for abort request.
|
||||
// This function will be called by `TryExecute` befaure lauching a device task
|
||||
// to check if abort has been requested.
|
||||
// For this test case, we are using a simple logic of returning true for the
|
||||
// `abortAt`th check.
|
||||
// If this test is failing, one of the things to check would be to see if the
|
||||
// `Contour` filter has changed such that it no longer has atleast `abortAt`
|
||||
// task invocations.
|
||||
bool ShouldAbort()
|
||||
{
|
||||
static int abortCheckCounter = 0;
|
||||
static constexpr int abortAt = 5;
|
||||
if (++abortCheckCounter >= abortAt)
|
||||
{
|
||||
std::cout << "Abort check " << abortCheckCounter << ": true\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
std::cout << "Abort check " << abortCheckCounter << ": false\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
int TestAbort()
|
||||
{
|
||||
vtkm::source::Wavelet wavelet;
|
||||
wavelet.SetExtent(vtkm::Id3(-15), vtkm::Id3(16));
|
||||
auto input = wavelet.Execute();
|
||||
|
||||
auto range = input.GetField("RTData").GetRange().ReadPortal().Get(0);
|
||||
std::vector<vtkm::Float64> isovals;
|
||||
static constexpr int numDivs = 5;
|
||||
for (int i = 1; i < numDivs - 1; ++i)
|
||||
{
|
||||
auto v = range.Min +
|
||||
(static_cast<vtkm::Float64>(i) *
|
||||
((range.Max - range.Min) / static_cast<vtkm::Float64>(numDivs)));
|
||||
isovals.push_back(v);
|
||||
}
|
||||
|
||||
vtkm::filter::contour::Contour contour;
|
||||
contour.SetActiveField("RTData");
|
||||
contour.SetIsoValues(isovals);
|
||||
|
||||
// First we will run the filter with the abort function set
|
||||
std::cout << "Run #1 with the abort function set\n";
|
||||
try
|
||||
{
|
||||
vtkm::cont::ScopedRuntimeDeviceTracker tracker(ShouldAbort);
|
||||
|
||||
auto result = contour.Execute(input);
|
||||
|
||||
// execution shouldn't reach here
|
||||
VTKM_TEST_FAIL("Error: filter execution was not aborted. Result: ",
|
||||
result.GetNumberOfPoints(),
|
||||
" points and ",
|
||||
result.GetNumberOfCells(),
|
||||
" triangles");
|
||||
}
|
||||
catch (const vtkm::cont::ErrorUserAbort&)
|
||||
{
|
||||
std::cout << "Execution was successfully aborted\n";
|
||||
}
|
||||
|
||||
// Now run the filter without the abort function
|
||||
std::cout << "Run #2 without the abort function set\n";
|
||||
try
|
||||
{
|
||||
auto result = contour.Execute(input);
|
||||
std::cout << "Success: filter execution was not aborted. Result: " << result.GetNumberOfPoints()
|
||||
<< " points and " << result.GetNumberOfCells() << " triangles\n";
|
||||
}
|
||||
catch (const vtkm::cont::ErrorUserAbort&)
|
||||
{
|
||||
VTKM_TEST_FAIL("Execution was unexpectedly aborted");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
} // anon namespace
|
||||
|
||||
int UnitTestAbort(int argc, char* argv[])
|
||||
{
|
||||
return vtkm::cont::testing::Testing::Run(TestAbort, argc, argv);
|
||||
}
|
@ -17,6 +17,7 @@
|
||||
#include <vtkm/cont/ArrayHandleIndex.h>
|
||||
#include <vtkm/cont/ArrayHandleMultiplexer.h>
|
||||
#include <vtkm/cont/ArrayHandleReverse.h>
|
||||
#include <vtkm/cont/ArrayHandleRuntimeVec.h>
|
||||
#include <vtkm/cont/ArrayHandleSOA.h>
|
||||
#include <vtkm/cont/ArrayHandleUniformPointCoordinates.h>
|
||||
#include <vtkm/cont/ArrayHandleView.h>
|
||||
@ -34,53 +35,79 @@ namespace
|
||||
|
||||
constexpr vtkm::Id ARRAY_SIZE = 10;
|
||||
|
||||
template <typename T>
|
||||
vtkm::IdComponent GetTotalNumComponents(const T& vec)
|
||||
{
|
||||
using VTraits = vtkm::VecTraits<T>;
|
||||
if (std::is_same<typename VTraits::ComponentType, typename VTraits::BaseComponentType>::value)
|
||||
{
|
||||
return VTraits::GetNumberOfComponents(vec);
|
||||
}
|
||||
else
|
||||
{
|
||||
return VTraits::GetNumberOfComponents(vec) *
|
||||
GetTotalNumComponents(VTraits::GetComponent(vec, 0));
|
||||
}
|
||||
}
|
||||
|
||||
// VecFlat.h has something similar, but it only works with static Vec sizes. It might make sense
|
||||
// to move this somewhere else later
|
||||
template <typename BaseComponentType>
|
||||
struct GetVecFlatIndexImpl
|
||||
{
|
||||
template <typename VecType>
|
||||
VTKM_CONT BaseComponentType operator()(const VecType& vec, vtkm::IdComponent index) const
|
||||
{
|
||||
const vtkm::IdComponent subSize = GetTotalNumComponents(vec[0]);
|
||||
return (*this)(vec[index / subSize], index % subSize);
|
||||
}
|
||||
|
||||
VTKM_CONT BaseComponentType operator()(const BaseComponentType& component,
|
||||
vtkm::IdComponent index) const
|
||||
{
|
||||
VTKM_ASSERT(index == 0);
|
||||
return component;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
auto GetVecFlatIndex(const T& vec, vtkm::IdComponent index)
|
||||
{
|
||||
return GetVecFlatIndexImpl<typename vtkm::VecTraits<T>::BaseComponentType>{}(vec, index);
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
void CheckInputArray(const vtkm::cont::ArrayHandle<T, S>& originalArray,
|
||||
vtkm::CopyFlag allowCopy = vtkm::CopyFlag::Off)
|
||||
{
|
||||
//std::cout << " Checking input array type "
|
||||
// << vtkm::cont::TypeToString<vtkm::cont::ArrayHandle<T, S>>() << std::endl;
|
||||
|
||||
//std::cout << " Original array: ";
|
||||
//vtkm::cont::printSummary_ArrayHandle(originalArray, std::cout);
|
||||
|
||||
using FlatVec = vtkm::VecFlat<T>;
|
||||
using ComponentType = typename FlatVec::ComponentType;
|
||||
for (vtkm::IdComponent componentId = 0; componentId < FlatVec::NUM_COMPONENTS; ++componentId)
|
||||
auto originalPortal = originalArray.ReadPortal();
|
||||
using ComponentType = typename vtkm::VecTraits<T>::BaseComponentType;
|
||||
const vtkm::IdComponent numComponents = GetTotalNumComponents(originalPortal.Get(0));
|
||||
for (vtkm::IdComponent componentId = 0; componentId < numComponents; ++componentId)
|
||||
{
|
||||
vtkm::cont::ArrayHandleStride<ComponentType> componentArray =
|
||||
vtkm::cont::ArrayExtractComponent(originalArray, componentId, allowCopy);
|
||||
//std::cout << " Component " << componentId << ": ";
|
||||
//vtkm::cont::printSummary_ArrayHandle(componentArray, std::cout);
|
||||
|
||||
auto originalPortal = originalArray.ReadPortal();
|
||||
auto componentPortal = componentArray.ReadPortal();
|
||||
VTKM_TEST_ASSERT(originalPortal.GetNumberOfValues() == componentPortal.GetNumberOfValues());
|
||||
for (vtkm::Id arrayIndex = 0; arrayIndex < originalArray.GetNumberOfValues(); ++arrayIndex)
|
||||
{
|
||||
auto originalValue = vtkm::make_VecFlat(originalPortal.Get(arrayIndex));
|
||||
auto originalValue = GetVecFlatIndex(originalPortal.Get(arrayIndex), componentId);
|
||||
ComponentType componentValue = componentPortal.Get(arrayIndex);
|
||||
VTKM_TEST_ASSERT(test_equal(originalValue[componentId], componentValue));
|
||||
VTKM_TEST_ASSERT(test_equal(originalValue, componentValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
void CheckOutputArray(const vtkm::cont::ArrayHandle<T, S>& originalArray)
|
||||
void CheckOutputArray(
|
||||
const vtkm::cont::ArrayHandle<T, S>& originalArray,
|
||||
const vtkm::cont::ArrayHandle<T, S>& outputArray = vtkm::cont::ArrayHandle<T, S>{})
|
||||
{
|
||||
CheckInputArray(originalArray);
|
||||
|
||||
//std::cout << " Checking output array type "
|
||||
// << vtkm::cont::TypeToString<vtkm::cont::ArrayHandle<T, S>>() << std::endl;
|
||||
|
||||
//std::cout << " Original array: ";
|
||||
//vtkm::cont::printSummary_ArrayHandle(originalArray, std::cout);
|
||||
|
||||
vtkm::cont::ArrayHandle<T, S> outputArray;
|
||||
|
||||
using FlatVec = vtkm::VecFlat<T>;
|
||||
using ComponentType = typename FlatVec::ComponentType;
|
||||
constexpr vtkm::IdComponent numComponents = FlatVec::NUM_COMPONENTS;
|
||||
using ComponentType = typename vtkm::VecTraits<T>::BaseComponentType;
|
||||
const vtkm::IdComponent numComponents = GetTotalNumComponents(originalArray.ReadPortal().Get(0));
|
||||
|
||||
// Extract all the stride arrays first, and then allocate them later. This tests to
|
||||
// to make sure that the independent allocation of all the extracted arrays are consistent
|
||||
@ -115,18 +142,16 @@ void CheckOutputArray(const vtkm::cont::ArrayHandle<T, S>& originalArray)
|
||||
}
|
||||
}
|
||||
|
||||
//std::cout << " Output array: ";
|
||||
//vtkm::cont::printSummary_ArrayHandle(outputArray, std::cout);
|
||||
|
||||
auto inPortal = originalArray.ReadPortal();
|
||||
auto outPortal = outputArray.ReadPortal();
|
||||
for (vtkm::Id arrayIndex = 0; arrayIndex < originalArray.GetNumberOfValues(); ++arrayIndex)
|
||||
{
|
||||
FlatVec inValue = vtkm::make_VecFlat(inPortal.Get(arrayIndex));
|
||||
FlatVec outValue = vtkm::make_VecFlat(outPortal.Get(arrayIndex));
|
||||
auto inValue = inPortal.Get(arrayIndex);
|
||||
auto outValue = outPortal.Get(arrayIndex);
|
||||
for (vtkm::IdComponent componentId = 0; componentId < numComponents; ++componentId)
|
||||
{
|
||||
VTKM_TEST_ASSERT(test_equal(inValue[componentId], outValue[numComponents - componentId - 1]));
|
||||
VTKM_TEST_ASSERT(test_equal(GetVecFlatIndex(inValue, componentId),
|
||||
GetVecFlatIndex(outValue, numComponents - componentId - 1)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -178,9 +203,10 @@ void DoTest()
|
||||
{
|
||||
std::cout << "ArrayHandleGroupVec" << std::endl;
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec3f> array;
|
||||
array.Allocate(ARRAY_SIZE * 2);
|
||||
array.Allocate(ARRAY_SIZE * 4);
|
||||
SetPortal(array.WritePortal());
|
||||
CheckOutputArray(vtkm::cont::make_ArrayHandleGroupVec<2>(array));
|
||||
CheckOutputArray(vtkm::cont::make_ArrayHandleGroupVec<4>(array));
|
||||
}
|
||||
|
||||
{
|
||||
@ -202,6 +228,17 @@ void DoTest()
|
||||
CheckInputArray(vtkm::cont::make_ArrayHandleExtractComponent(compositeArray, 1));
|
||||
}
|
||||
|
||||
{
|
||||
std::cout << "ArrayHandleRuntimeVec" << std::endl;
|
||||
vtkm::cont::ArrayHandle<vtkm::FloatDefault> array;
|
||||
array.Allocate(ARRAY_SIZE * 4);
|
||||
SetPortal(array.WritePortal());
|
||||
CheckOutputArray(vtkm::cont::make_ArrayHandleRuntimeVec(2, array),
|
||||
vtkm::cont::ArrayHandleRuntimeVec<vtkm::FloatDefault>(2));
|
||||
CheckOutputArray(vtkm::cont::make_ArrayHandleRuntimeVec(4, array),
|
||||
vtkm::cont::ArrayHandleRuntimeVec<vtkm::FloatDefault>(4));
|
||||
}
|
||||
|
||||
{
|
||||
std::cout << "ArrayHandleCartesianProduct" << std::endl;
|
||||
vtkm::cont::ArrayHandle<vtkm::Float64> array0;
|
||||
|
248
vtkm/cont/testing/UnitTestArrayHandleRuntimeVec.cxx
Normal file
248
vtkm/cont/testing/UnitTestArrayHandleRuntimeVec.cxx
Normal file
@ -0,0 +1,248 @@
|
||||
//============================================================================
|
||||
// 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.
|
||||
//============================================================================
|
||||
|
||||
#include <vtkm/cont/ArrayHandleRuntimeVec.h>
|
||||
|
||||
#include <vtkm/cont/ArrayHandleGroupVec.h>
|
||||
#include <vtkm/cont/Invoker.h>
|
||||
|
||||
#include <vtkm/worklet/WorkletMapField.h>
|
||||
|
||||
#include <vtkm/cont/testing/Testing.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
constexpr vtkm::Id ARRAY_SIZE = 10;
|
||||
|
||||
struct UnusualType
|
||||
{
|
||||
vtkm::Id X;
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <>
|
||||
struct TestValueImpl<UnusualType>
|
||||
{
|
||||
VTKM_EXEC_CONT UnusualType operator()(vtkm::Id index) const
|
||||
{
|
||||
return { TestValue(index, decltype(UnusualType::X){}) };
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct TestEqualImpl<UnusualType, UnusualType>
|
||||
{
|
||||
VTKM_EXEC_CONT bool operator()(UnusualType value1,
|
||||
UnusualType value2,
|
||||
vtkm::Float64 tolerance) const
|
||||
{
|
||||
return test_equal(value1.X, value2.X, tolerance);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
struct PassThrough : vtkm::worklet::WorkletMapField
|
||||
{
|
||||
using ControlSignature = void(FieldIn, FieldOut);
|
||||
using ExecutionSignature = void(_1, _2);
|
||||
|
||||
template <typename InValue, typename OutValue>
|
||||
VTKM_EXEC void operator()(const InValue& inValue, OutValue& outValue) const
|
||||
{
|
||||
vtkm::IdComponent inIndex = 0;
|
||||
vtkm::IdComponent outIndex = 0;
|
||||
this->FlatCopy(inValue, inIndex, outValue, outIndex);
|
||||
}
|
||||
|
||||
template <typename InValue, typename OutValue>
|
||||
VTKM_EXEC void FlatCopy(const InValue& inValue,
|
||||
vtkm::IdComponent& inIndex,
|
||||
OutValue& outValue,
|
||||
vtkm::IdComponent& outIndex) const
|
||||
{
|
||||
using VTraitsIn = vtkm::VecTraits<InValue>;
|
||||
using VTraitsOut = vtkm::VecTraits<OutValue>;
|
||||
VTraitsOut::SetComponent(outValue, outIndex, VTraitsIn::GetComponent(inValue, inIndex));
|
||||
inIndex++;
|
||||
outIndex++;
|
||||
}
|
||||
|
||||
template <typename InComponent, vtkm::IdComponent InN, typename OutValue>
|
||||
VTKM_EXEC void FlatCopy(const vtkm::Vec<InComponent, InN>& inValue,
|
||||
vtkm::IdComponent& inIndex,
|
||||
OutValue& outValue,
|
||||
vtkm::IdComponent& outIndex) const
|
||||
{
|
||||
VTKM_ASSERT(inIndex == 0);
|
||||
for (vtkm::IdComponent i = 0; i < InN; ++i)
|
||||
{
|
||||
FlatCopy(inValue[i], inIndex, outValue, outIndex);
|
||||
inIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename InValue, typename OutComponent, vtkm::IdComponent OutN>
|
||||
VTKM_EXEC void FlatCopy(const InValue& inValue,
|
||||
vtkm::IdComponent& inIndex,
|
||||
vtkm::Vec<OutComponent, OutN>& outValue,
|
||||
vtkm::IdComponent& outIndex) const
|
||||
{
|
||||
VTKM_ASSERT(outIndex == 0);
|
||||
for (vtkm::IdComponent i = 0; i < OutN; ++i)
|
||||
{
|
||||
OutComponent outComponent;
|
||||
FlatCopy(inValue, inIndex, outComponent, outIndex);
|
||||
outValue[i] = outComponent;
|
||||
outIndex = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <vtkm::IdComponent NUM_COMPONENTS>
|
||||
struct TestRuntimeVecAsInput
|
||||
{
|
||||
template <typename ComponentType>
|
||||
VTKM_CONT void operator()(ComponentType) const
|
||||
{
|
||||
using ValueType = vtkm::Vec<ComponentType, NUM_COMPONENTS>;
|
||||
|
||||
vtkm::cont::ArrayHandle<ComponentType> baseArray;
|
||||
baseArray.Allocate(ARRAY_SIZE * NUM_COMPONENTS);
|
||||
SetPortal(baseArray.WritePortal());
|
||||
|
||||
auto runtimeVecArray = vtkm::cont::make_ArrayHandleRuntimeVec(NUM_COMPONENTS, baseArray);
|
||||
VTKM_TEST_ASSERT(runtimeVecArray.GetNumberOfValues() == ARRAY_SIZE,
|
||||
"Group array reporting wrong array size.");
|
||||
|
||||
vtkm::cont::ArrayHandle<ValueType> resultArray;
|
||||
|
||||
vtkm::cont::Invoker{}(PassThrough{}, runtimeVecArray, resultArray);
|
||||
|
||||
VTKM_TEST_ASSERT(resultArray.GetNumberOfValues() == ARRAY_SIZE, "Got bad result array size.");
|
||||
|
||||
//verify that the control portal works
|
||||
vtkm::Id totalIndex = 0;
|
||||
auto resultPortal = resultArray.ReadPortal();
|
||||
for (vtkm::Id index = 0; index < ARRAY_SIZE; ++index)
|
||||
{
|
||||
const ValueType result = resultPortal.Get(index);
|
||||
for (vtkm::IdComponent componentIndex = 0; componentIndex < NUM_COMPONENTS; componentIndex++)
|
||||
{
|
||||
const ComponentType expectedValue = TestValue(totalIndex, ComponentType());
|
||||
VTKM_TEST_ASSERT(test_equal(result[componentIndex], expectedValue),
|
||||
"Result array got wrong value.");
|
||||
totalIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
//verify that you can get the data as a basic array
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<ComponentType, NUM_COMPONENTS>> flatComponents;
|
||||
runtimeVecArray.AsArrayHandleBasic(flatComponents);
|
||||
VTKM_TEST_ASSERT(test_equal_ArrayHandles(
|
||||
flatComponents, vtkm::cont::make_ArrayHandleGroupVec<NUM_COMPONENTS>(baseArray)));
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Vec<ComponentType, 1>, NUM_COMPONENTS>>
|
||||
nestedComponents;
|
||||
runtimeVecArray.AsArrayHandleBasic(nestedComponents);
|
||||
auto flatPortal = flatComponents.ReadPortal();
|
||||
auto nestedPortal = nestedComponents.ReadPortal();
|
||||
for (vtkm::Id index = 0; index < flatPortal.GetNumberOfValues(); ++index)
|
||||
{
|
||||
VTKM_TEST_ASSERT(test_equal(vtkm::make_VecFlat(flatPortal.Get(index)),
|
||||
vtkm::make_VecFlat(nestedPortal.Get(index))));
|
||||
}
|
||||
|
||||
runtimeVecArray.ReleaseResources();
|
||||
}
|
||||
};
|
||||
|
||||
template <vtkm::IdComponent NUM_COMPONENTS>
|
||||
struct TestRuntimeVecAsOutput
|
||||
{
|
||||
template <typename ComponentType>
|
||||
VTKM_CONT void operator()(ComponentType) const
|
||||
{
|
||||
using ValueType = vtkm::Vec<ComponentType, NUM_COMPONENTS>;
|
||||
|
||||
vtkm::cont::ArrayHandle<ValueType> baseArray;
|
||||
baseArray.Allocate(ARRAY_SIZE);
|
||||
SetPortal(baseArray.WritePortal());
|
||||
|
||||
vtkm::cont::ArrayHandle<ComponentType> resultArray;
|
||||
|
||||
vtkm::cont::ArrayHandleRuntimeVec<ComponentType> runtimeVecArray(NUM_COMPONENTS, resultArray);
|
||||
|
||||
vtkm::cont::Invoker{}(PassThrough{}, baseArray, runtimeVecArray);
|
||||
|
||||
VTKM_TEST_ASSERT(runtimeVecArray.GetNumberOfValues() == ARRAY_SIZE,
|
||||
"Group array reporting wrong array size.");
|
||||
|
||||
VTKM_TEST_ASSERT(resultArray.GetNumberOfValues() == ARRAY_SIZE * NUM_COMPONENTS,
|
||||
"Got bad result array size.");
|
||||
|
||||
//verify that the control portal works
|
||||
vtkm::Id totalIndex = 0;
|
||||
auto resultPortal = resultArray.ReadPortal();
|
||||
for (vtkm::Id index = 0; index < ARRAY_SIZE; ++index)
|
||||
{
|
||||
const ValueType expectedValue = TestValue(index, ValueType());
|
||||
for (vtkm::IdComponent componentIndex = 0; componentIndex < NUM_COMPONENTS; componentIndex++)
|
||||
{
|
||||
const ComponentType result = resultPortal.Get(totalIndex);
|
||||
VTKM_TEST_ASSERT(test_equal(result, expectedValue[componentIndex]),
|
||||
"Result array got wrong value.");
|
||||
totalIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void Run()
|
||||
{
|
||||
using HandleTypesToTest =
|
||||
vtkm::List<vtkm::Id, vtkm::Vec2i_32, vtkm::FloatDefault, vtkm::Vec3f_64>;
|
||||
using ScalarTypesToTest = vtkm::List<vtkm::UInt8, vtkm::FloatDefault>;
|
||||
|
||||
std::cout << "-------------------------------------------" << std::endl;
|
||||
std::cout << "Testing ArrayHandleRuntimeVec(3) as Input" << std::endl;
|
||||
vtkm::testing::Testing::TryTypes(TestRuntimeVecAsInput<3>(), HandleTypesToTest());
|
||||
|
||||
std::cout << "-------------------------------------------" << std::endl;
|
||||
std::cout << "Testing ArrayHandleRuntimeVec(4) as Input" << std::endl;
|
||||
vtkm::testing::Testing::TryTypes(TestRuntimeVecAsInput<4>(), HandleTypesToTest());
|
||||
|
||||
std::cout << "-------------------------------------------" << std::endl;
|
||||
std::cout << "Testing ArrayHandleRuntimeVec(2) as Output" << std::endl;
|
||||
vtkm::testing::Testing::TryTypes(TestRuntimeVecAsOutput<2>(), ScalarTypesToTest());
|
||||
|
||||
std::cout << "-------------------------------------------" << std::endl;
|
||||
std::cout << "Testing ArrayHandleRuntimeVec(3) as Output" << std::endl;
|
||||
vtkm::testing::Testing::TryTypes(TestRuntimeVecAsOutput<3>(), ScalarTypesToTest());
|
||||
|
||||
std::cout << "-------------------------------------------" << std::endl;
|
||||
std::cout << "Testing ArrayHandleRuntimeVec(3) as Input with unusual type" << std::endl;
|
||||
TestRuntimeVecAsInput<3>{}(UnusualType{});
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
int UnitTestArrayHandleRuntimeVec(int argc, char* argv[])
|
||||
{
|
||||
return vtkm::cont::testing::Testing::Run(Run, argc, argv);
|
||||
}
|
@ -11,17 +11,22 @@
|
||||
#include <vtkm/cont/ArrayCopyDevice.h>
|
||||
#include <vtkm/cont/ArrayHandleBasic.h>
|
||||
#include <vtkm/cont/ArrayHandleCartesianProduct.h>
|
||||
#include <vtkm/cont/ArrayHandleCast.h>
|
||||
#include <vtkm/cont/ArrayHandleCompositeVector.h>
|
||||
#include <vtkm/cont/ArrayHandleCounting.h>
|
||||
#include <vtkm/cont/ArrayHandleExtractComponent.h>
|
||||
#include <vtkm/cont/ArrayHandleGroupVec.h>
|
||||
#include <vtkm/cont/ArrayHandleIndex.h>
|
||||
#include <vtkm/cont/ArrayHandleRandomUniformReal.h>
|
||||
#include <vtkm/cont/ArrayHandleSOA.h>
|
||||
#include <vtkm/cont/ArrayHandleStride.h>
|
||||
#include <vtkm/cont/ArrayHandleUniformPointCoordinates.h>
|
||||
#include <vtkm/cont/ArrayHandleView.h>
|
||||
#include <vtkm/cont/ArrayHandleXGCCoordinates.h>
|
||||
#include <vtkm/cont/ArrayRangeCompute.h>
|
||||
|
||||
#include <vtkm/Math.h>
|
||||
#include <vtkm/VecTraits.h>
|
||||
|
||||
#include <vtkm/cont/testing/Testing.h>
|
||||
|
||||
@ -31,12 +36,12 @@ namespace
|
||||
constexpr vtkm::Id ARRAY_SIZE = 20;
|
||||
|
||||
template <typename T, typename S>
|
||||
void CheckRange(const vtkm::cont::ArrayHandle<T, S>& array, bool checkUnknown = true)
|
||||
void VerifyRange(const vtkm::cont::ArrayHandle<T, S>& array,
|
||||
const vtkm::cont::ArrayHandle<vtkm::Range>& computedRangeArray)
|
||||
{
|
||||
using Traits = vtkm::VecTraits<T>;
|
||||
vtkm::IdComponent numComponents = Traits::NUM_COMPONENTS;
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Range> computedRangeArray = vtkm::cont::ArrayRangeCompute(array);
|
||||
VTKM_TEST_ASSERT(computedRangeArray.GetNumberOfValues() == numComponents);
|
||||
auto computedRangePortal = computedRangeArray.ReadPortal();
|
||||
|
||||
@ -54,28 +59,12 @@ void CheckRange(const vtkm::cont::ArrayHandle<T, S>& array, bool checkUnknown =
|
||||
VTKM_TEST_ASSERT(!vtkm::IsNan(computedRange.Max));
|
||||
VTKM_TEST_ASSERT(test_equal(expectedRange, computedRange));
|
||||
}
|
||||
}
|
||||
|
||||
if (checkUnknown)
|
||||
{
|
||||
computedRangeArray = vtkm::cont::ArrayRangeCompute(vtkm::cont::UnknownArrayHandle{ array });
|
||||
VTKM_TEST_ASSERT(computedRangeArray.GetNumberOfValues() == numComponents);
|
||||
computedRangePortal = computedRangeArray.ReadPortal();
|
||||
|
||||
portal = array.ReadPortal();
|
||||
for (vtkm::IdComponent component = 0; component < numComponents; ++component)
|
||||
{
|
||||
vtkm::Range computedRange = computedRangePortal.Get(component);
|
||||
vtkm::Range expectedRange;
|
||||
for (vtkm::Id index = 0; index < portal.GetNumberOfValues(); ++index)
|
||||
{
|
||||
T value = portal.Get(index);
|
||||
expectedRange.Include(Traits::GetComponent(value, component));
|
||||
}
|
||||
VTKM_TEST_ASSERT(!vtkm::IsNan(computedRange.Min));
|
||||
VTKM_TEST_ASSERT(!vtkm::IsNan(computedRange.Max));
|
||||
VTKM_TEST_ASSERT(test_equal(expectedRange, computedRange));
|
||||
}
|
||||
}
|
||||
template <typename T, typename S>
|
||||
void CheckRange(const vtkm::cont::ArrayHandle<T, S>& array)
|
||||
{
|
||||
VerifyRange(array, vtkm::cont::ArrayRangeCompute(array));
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
@ -119,7 +108,7 @@ void TestSOAArray(vtkm::TypeTraitsScalarTag)
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void TestStrideArray(vtkm::TypeTraitsScalarTag)
|
||||
void TestStrideArray()
|
||||
{
|
||||
std::cout << "Checking stride array" << std::endl;
|
||||
vtkm::cont::ArrayHandleBasic<T> array;
|
||||
@ -127,6 +116,16 @@ void TestStrideArray(vtkm::TypeTraitsScalarTag)
|
||||
CheckRange(vtkm::cont::ArrayHandleStride<T>(array, ARRAY_SIZE / 2, 2, 1));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void TestCastArray()
|
||||
{
|
||||
std::cout << "Checking cast array" << std::endl;
|
||||
using CastType = typename vtkm::VecTraits<T>::template ReplaceBaseComponentType<vtkm::Float64>;
|
||||
vtkm::cont::ArrayHandle<T> array;
|
||||
FillArray(array);
|
||||
CheckRange(vtkm::cont::make_ArrayHandleCast<CastType>(array));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void TestCartesianProduct(vtkm::TypeTraitsScalarTag)
|
||||
{
|
||||
@ -151,7 +150,7 @@ void TestCartesianProduct(vtkm::TypeTraitsVectorTag)
|
||||
template <typename T>
|
||||
void TestComposite(vtkm::TypeTraitsScalarTag)
|
||||
{
|
||||
std::cout << "Checking composite vector" << std::endl;
|
||||
std::cout << "Checking composite vector array" << std::endl;
|
||||
|
||||
vtkm::cont::ArrayHandleBasic<T> array0;
|
||||
FillArray(array0);
|
||||
@ -169,6 +168,32 @@ void TestComposite(vtkm::TypeTraitsVectorTag)
|
||||
// Skip test.
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void TestGroup(vtkm::TypeTraitsScalarTag)
|
||||
{
|
||||
std::cout << "Checking group vec array" << std::endl;
|
||||
|
||||
vtkm::cont::ArrayHandleBasic<T> array;
|
||||
FillArray(array);
|
||||
CheckRange(vtkm::cont::make_ArrayHandleGroupVec<2>(array));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void TestGroup(vtkm::TypeTraitsVectorTag)
|
||||
{
|
||||
// Skip test.
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void TestView()
|
||||
{
|
||||
std::cout << "Checking view array" << std::endl;
|
||||
|
||||
vtkm::cont::ArrayHandleBasic<T> array;
|
||||
FillArray(array);
|
||||
CheckRange(vtkm::cont::make_ArrayHandleView(array, 2, ARRAY_SIZE - 5));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void TestConstant()
|
||||
{
|
||||
@ -205,15 +230,29 @@ void TestUniformPointCoords()
|
||||
vtkm::cont::ArrayHandleUniformPointCoordinates(vtkm::Id3(ARRAY_SIZE, ARRAY_SIZE, ARRAY_SIZE)));
|
||||
}
|
||||
|
||||
void TestXGCCoordinates()
|
||||
{
|
||||
std::cout << "Checking XGC coordinates array" << std::endl;
|
||||
vtkm::cont::ArrayHandle<vtkm::FloatDefault> array;
|
||||
FillArray(array);
|
||||
CheckRange(vtkm::cont::make_ArrayHandleXGCCoordinates(array, 4, true));
|
||||
}
|
||||
|
||||
struct DoTestFunctor
|
||||
{
|
||||
template <typename T>
|
||||
void operator()(T) const
|
||||
{
|
||||
typename vtkm::TypeTraits<T>::DimensionalityTag dimensionality{};
|
||||
|
||||
TestBasicArray<T>();
|
||||
TestSOAArray<T>(typename vtkm::TypeTraits<T>::DimensionalityTag{});
|
||||
TestCartesianProduct<T>(typename vtkm::TypeTraits<T>::DimensionalityTag{});
|
||||
TestComposite<T>(typename vtkm::TypeTraits<T>::DimensionalityTag{});
|
||||
TestSOAArray<T>(dimensionality);
|
||||
TestStrideArray<T>();
|
||||
TestCastArray<T>();
|
||||
TestCartesianProduct<T>(dimensionality);
|
||||
TestComposite<T>(dimensionality);
|
||||
TestGroup<T>(dimensionality);
|
||||
TestView<T>();
|
||||
TestConstant<T>();
|
||||
TestCounting<T>(typename std::is_signed<typename vtkm::VecTraits<T>::ComponentType>::type{});
|
||||
}
|
||||
@ -226,6 +265,7 @@ void DoTest()
|
||||
std::cout << "*** Specific arrays *****************" << std::endl;
|
||||
TestIndex();
|
||||
TestUniformPointCoords();
|
||||
TestXGCCoordinates();
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
@ -24,6 +24,25 @@
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
#if defined(KOKKOS_ENABLE_SYCL)
|
||||
#define DEVICE_ASSERT_MSG(cond, message) \
|
||||
do \
|
||||
{ \
|
||||
if (!(cond)) \
|
||||
{ \
|
||||
return false; \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
#define DEVICE_ASSERT(cond) \
|
||||
do \
|
||||
{ \
|
||||
if (!(cond)) \
|
||||
{ \
|
||||
return false; \
|
||||
} \
|
||||
} while (false)
|
||||
#else
|
||||
#define DEVICE_ASSERT_MSG(cond, message) \
|
||||
do \
|
||||
{ \
|
||||
@ -47,6 +66,7 @@
|
||||
return false; \
|
||||
} \
|
||||
} while (false)
|
||||
#endif
|
||||
|
||||
// Test with some trailing bits in partial last word:
|
||||
#define NUM_BITS \
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <vtkm/cont/ArrayHandleIndex.h>
|
||||
#include <vtkm/cont/ArrayHandlePermutation.h>
|
||||
#include <vtkm/cont/ArrayHandleReverse.h>
|
||||
#include <vtkm/cont/ArrayHandleRuntimeVec.h>
|
||||
#include <vtkm/cont/ArrayHandleSOA.h>
|
||||
#include <vtkm/cont/ArrayHandleSwizzle.h>
|
||||
#include <vtkm/cont/ArrayHandleTransform.h>
|
||||
@ -303,6 +304,19 @@ struct TestArrayHandleGroupVecVariable
|
||||
}
|
||||
};
|
||||
|
||||
struct TestArrayHandleRuntimeVec
|
||||
{
|
||||
template <typename T>
|
||||
void operator()(T) const
|
||||
{
|
||||
auto numComps = RandomValue<vtkm::IdComponent>::Make(1, 5);
|
||||
auto flat = RandomArrayHandle<T>::Make(ArraySize * numComps);
|
||||
auto array = vtkm::cont::make_ArrayHandleRuntimeVec(numComps, flat);
|
||||
RunTest(array);
|
||||
RunTest(MakeTestUnknownArrayHandle(array));
|
||||
}
|
||||
};
|
||||
|
||||
void TestArrayHandleIndex()
|
||||
{
|
||||
auto size = RandomValue<vtkm::Id>::Make(2, 10);
|
||||
@ -413,6 +427,9 @@ void TestArrayHandleSerialization()
|
||||
std::cout << "Testing ArrayHandleGroupVecVariable\n";
|
||||
vtkm::testing::Testing::TryTypes(TestArrayHandleGroupVecVariable(), TestTypesList());
|
||||
|
||||
std::cout << "Testing ArrayHandleRuntimeVec\n";
|
||||
vtkm::testing::Testing::TryTypes(TestArrayHandleRuntimeVec(), TestTypesList());
|
||||
|
||||
std::cout << "Testing ArrayHandleIndex\n";
|
||||
TestArrayHandleIndex();
|
||||
|
||||
|
@ -22,16 +22,26 @@ using CellSetTypes = vtkm::List<vtkm::cont::CellSetExplicit<>,
|
||||
vtkm::cont::CellSetStructured<2>,
|
||||
vtkm::cont::CellSetStructured<3>>;
|
||||
|
||||
using DataSetWrapper = vtkm::cont::SerializableDataSet<FieldTypeList, CellSetTypes>;
|
||||
using DataSetWrapper = vtkm::cont::DataSetWithCellSetTypes<CellSetTypes>;
|
||||
|
||||
VTKM_CONT void TestEqualDataSet(const DataSetWrapper& ds1, const DataSetWrapper& ds2)
|
||||
VTKM_CONT void TestEqualDataSetWrapper(const DataSetWrapper& ds1, const DataSetWrapper& ds2)
|
||||
{
|
||||
VTKM_TEST_ASSERT(test_equal_DataSets(ds1.DataSet, ds2.DataSet, CellSetTypes{}));
|
||||
}
|
||||
|
||||
VTKM_CONT void TestEqualDataSet(const vtkm::cont::DataSet& ds1, const vtkm::cont::DataSet& ds2)
|
||||
{
|
||||
VTKM_TEST_ASSERT(test_equal_DataSets(ds1, ds2, CellSetTypes{}));
|
||||
}
|
||||
|
||||
void RunTest(const vtkm::cont::DataSet& ds)
|
||||
{
|
||||
TestSerialization(DataSetWrapper(ds), TestEqualDataSet);
|
||||
VTKM_DEPRECATED_SUPPRESS_BEGIN
|
||||
TestSerialization(vtkm::cont::SerializableDataSet<FieldTypeList, CellSetTypes>(ds),
|
||||
TestEqualDataSetWrapper);
|
||||
VTKM_DEPRECATED_SUPPRESS_END
|
||||
TestSerialization(DataSetWrapper(ds), TestEqualDataSetWrapper);
|
||||
TestSerialization(ds, TestEqualDataSet);
|
||||
}
|
||||
|
||||
void TestDataSetSerialization()
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <vtkm/cont/ArrayHandleCounting.h>
|
||||
#include <vtkm/cont/ArrayHandleGroupVecVariable.h>
|
||||
#include <vtkm/cont/ArrayHandleMultiplexer.h>
|
||||
#include <vtkm/cont/ArrayHandleRuntimeVec.h>
|
||||
|
||||
#include <vtkm/TypeTraits.h>
|
||||
|
||||
@ -542,6 +543,57 @@ void TrySetMultiplexerArray()
|
||||
CheckUnknownArray<vtkm::List<vtkm::Id>, vtkm::List<VTKM_DEFAULT_STORAGE_TAG>>(unknownArray, 1);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void TryConvertRuntimeVec()
|
||||
{
|
||||
using BasicArrayType = vtkm::cont::ArrayHandle<T>;
|
||||
using BasicComponentType = typename vtkm::VecFlat<T>::ComponentType;
|
||||
constexpr vtkm::IdComponent numFlatComponents = vtkm::VecFlat<T>::NUM_COMPONENTS;
|
||||
using RuntimeArrayType = vtkm::cont::ArrayHandleRuntimeVec<BasicComponentType>;
|
||||
|
||||
std::cout << " Get basic array as ArrayHandleRuntimeVec" << std::endl;
|
||||
BasicArrayType inputArray;
|
||||
inputArray.Allocate(ARRAY_SIZE);
|
||||
SetPortal(inputArray.WritePortal());
|
||||
|
||||
vtkm::cont::UnknownArrayHandle unknownWithBasic{ inputArray };
|
||||
VTKM_TEST_ASSERT(unknownWithBasic.GetNumberOfComponentsFlat() == numFlatComponents);
|
||||
|
||||
VTKM_TEST_ASSERT(unknownWithBasic.CanConvert<RuntimeArrayType>());
|
||||
RuntimeArrayType runtimeArray = unknownWithBasic.AsArrayHandle<RuntimeArrayType>();
|
||||
|
||||
// Hack to convert the array handle to a flat array to make it easy to check the runtime array
|
||||
vtkm::cont::ArrayHandle<vtkm::VecFlat<T>> flatInput{ inputArray.GetBuffers() };
|
||||
VTKM_TEST_ASSERT(test_equal_ArrayHandles(flatInput, runtimeArray));
|
||||
|
||||
std::cout << " Get ArrayHandleRuntimeVec as basic array" << std::endl;
|
||||
vtkm::cont::UnknownArrayHandle unknownWithRuntimeVec{ runtimeArray };
|
||||
VTKM_TEST_ASSERT(unknownWithRuntimeVec.GetNumberOfComponentsFlat() == numFlatComponents);
|
||||
|
||||
VTKM_TEST_ASSERT(unknownWithRuntimeVec.CanConvert<RuntimeArrayType>());
|
||||
VTKM_TEST_ASSERT(unknownWithRuntimeVec.CanConvert<BasicArrayType>());
|
||||
BasicArrayType outputArray = unknownWithRuntimeVec.AsArrayHandle<BasicArrayType>();
|
||||
VTKM_TEST_ASSERT(test_equal_ArrayHandles(inputArray, outputArray));
|
||||
}
|
||||
|
||||
void TryConvertRuntimeVec()
|
||||
{
|
||||
std::cout << " Scalar array." << std::endl;
|
||||
TryConvertRuntimeVec<vtkm::FloatDefault>();
|
||||
|
||||
std::cout << " Equivalent scalar." << std::endl;
|
||||
TryConvertRuntimeVec<VTKM_UNUSED_INT_TYPE>();
|
||||
|
||||
std::cout << " Basic Vec." << std::endl;
|
||||
TryConvertRuntimeVec<vtkm::Id3>();
|
||||
|
||||
std::cout << " Vec of Vecs." << std::endl;
|
||||
TryConvertRuntimeVec<vtkm::Vec<vtkm::Vec2f, 3>>();
|
||||
|
||||
std::cout << " Vec of Vecs of Vecs." << std::endl;
|
||||
TryConvertRuntimeVec<vtkm::Vec<vtkm::Vec<vtkm::Id4, 3>, 2>>();
|
||||
}
|
||||
|
||||
struct DefaultTypeFunctor
|
||||
{
|
||||
template <typename T>
|
||||
@ -573,6 +625,9 @@ void TestUnknownArrayHandle()
|
||||
|
||||
std::cout << "Try setting ArrayHandleMultiplexer" << std::endl;
|
||||
TrySetMultiplexerArray();
|
||||
|
||||
std::cout << "Try converting between ArrayHandleRuntimeVec and basic array" << std::endl;
|
||||
TryConvertRuntimeVec();
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
@ -9,6 +9,7 @@ DEPENDS
|
||||
OPTIONAL_DEPENDS
|
||||
vtkm_loguru
|
||||
TEST_OPTIONAL_DEPENDS
|
||||
vtkm_filter_contour
|
||||
vtkm_filter_field_conversion
|
||||
TEST_DEPENDS
|
||||
vtkm_source
|
||||
|
@ -40,7 +40,7 @@ void RunFilter(Filter* self, vtkm::filter::DataSetQueue& input, vtkm::filter::Da
|
||||
tracker.SetThreadFriendlyMemAlloc(prevVal);
|
||||
}
|
||||
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
Filter::~Filter() = default;
|
||||
|
||||
@ -49,6 +49,45 @@ bool Filter::CanThread() const
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Filter::SetFieldsToPass(const vtkm::filter::FieldSelection& fieldsToPass)
|
||||
{
|
||||
this->FieldsToPass = fieldsToPass;
|
||||
}
|
||||
|
||||
void Filter::SetFieldsToPass(vtkm::filter::FieldSelection&& fieldsToPass)
|
||||
{
|
||||
this->FieldsToPass = std::move(fieldsToPass);
|
||||
}
|
||||
|
||||
void Filter::SetFieldsToPass(const vtkm::filter::FieldSelection& fieldsToPass,
|
||||
vtkm::filter::FieldSelection::Mode mode)
|
||||
{
|
||||
this->FieldsToPass = fieldsToPass;
|
||||
this->FieldsToPass.SetMode(mode);
|
||||
}
|
||||
|
||||
VTKM_CONT void Filter::SetFieldsToPass(std::initializer_list<std::string> fields,
|
||||
vtkm::filter::FieldSelection::Mode mode)
|
||||
{
|
||||
this->SetFieldsToPass(vtkm::filter::FieldSelection{ fields, mode });
|
||||
}
|
||||
|
||||
void Filter::SetFieldsToPass(
|
||||
std::initializer_list<std::pair<std::string, vtkm::cont::Field::Association>> fields,
|
||||
vtkm::filter::FieldSelection::Mode mode)
|
||||
{
|
||||
this->SetFieldsToPass(vtkm::filter::FieldSelection{ fields, mode });
|
||||
}
|
||||
|
||||
void Filter::SetFieldsToPass(const std::string& fieldname,
|
||||
vtkm::cont::Field::Association association,
|
||||
vtkm::filter::FieldSelection::Mode mode)
|
||||
{
|
||||
this->SetFieldsToPass(vtkm::filter::FieldSelection{ fieldname, association, mode });
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
vtkm::cont::PartitionedDataSet Filter::DoExecutePartitions(
|
||||
const vtkm::cont::PartitionedDataSet& input)
|
||||
|
@ -263,27 +263,31 @@ public:
|
||||
///
|
||||
/// By default, all fields are passed during execution.
|
||||
///
|
||||
VTKM_CONT
|
||||
void SetFieldsToPass(const vtkm::filter::FieldSelection& fieldsToPass)
|
||||
{
|
||||
this->FieldsToPass = fieldsToPass;
|
||||
}
|
||||
VTKM_CONT void SetFieldsToPass(const vtkm::filter::FieldSelection& fieldsToPass);
|
||||
VTKM_CONT void SetFieldsToPass(vtkm::filter::FieldSelection&& fieldsToPass);
|
||||
|
||||
VTKM_CONT
|
||||
void SetFieldsToPass(const vtkm::filter::FieldSelection& fieldsToPass,
|
||||
vtkm::filter::FieldSelection::Mode mode)
|
||||
{
|
||||
this->FieldsToPass = fieldsToPass;
|
||||
this->FieldsToPass.SetMode(mode);
|
||||
}
|
||||
VTKM_DEPRECATED(2.0)
|
||||
VTKM_CONT void SetFieldsToPass(const vtkm::filter::FieldSelection& fieldsToPass,
|
||||
vtkm::filter::FieldSelection::Mode mode);
|
||||
|
||||
VTKM_CONT
|
||||
void SetFieldsToPass(
|
||||
VTKM_CONT void SetFieldsToPass(
|
||||
std::initializer_list<std::string> fields,
|
||||
vtkm::filter::FieldSelection::Mode mode = vtkm::filter::FieldSelection::Mode::Select);
|
||||
|
||||
VTKM_CONT void SetFieldsToPass(
|
||||
std::initializer_list<std::pair<std::string, vtkm::cont::Field::Association>> fields,
|
||||
vtkm::filter::FieldSelection::Mode mode = vtkm::filter::FieldSelection::Mode::Select);
|
||||
|
||||
|
||||
VTKM_CONT void SetFieldsToPass(
|
||||
const std::string& fieldname,
|
||||
vtkm::cont::Field::Association association,
|
||||
vtkm::filter::FieldSelection::Mode mode = vtkm::filter::FieldSelection::Mode::Select)
|
||||
vtkm::filter::FieldSelection::Mode mode = vtkm::filter::FieldSelection::Mode::Select);
|
||||
|
||||
VTKM_CONT void SetFieldsToPass(const std::string& fieldname,
|
||||
vtkm::filter::FieldSelection::Mode mode)
|
||||
{
|
||||
this->SetFieldsToPass({ fieldname, association }, mode);
|
||||
this->SetFieldsToPass(fieldname, vtkm::cont::Field::Association::Any, mode);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
@ -442,9 +446,12 @@ protected:
|
||||
{
|
||||
vtkm::cont::DataSet outDataSet;
|
||||
outDataSet.SetCellSet(resultCellSet);
|
||||
outDataSet.AddCoordinateSystem(resultCoordSystem);
|
||||
vtkm::filter::FieldSelection fieldSelection = this->GetFieldsToPass();
|
||||
fieldSelection.AddField(resultCoordSystem, vtkm::filter::FieldSelection::Mode::Exclude);
|
||||
if (this->GetPassCoordinateSystems() || fieldSelection.HasField(resultCoordSystem))
|
||||
{
|
||||
outDataSet.AddCoordinateSystem(resultCoordSystem);
|
||||
fieldSelection.AddField(resultCoordSystem, vtkm::filter::FieldSelection::Mode::Exclude);
|
||||
}
|
||||
this->MapFieldsOntoOutput(inDataSet, fieldSelection, outDataSet, fieldMapper);
|
||||
return outDataSet;
|
||||
}
|
||||
|
@ -29,17 +29,18 @@ bool DoMapField(vtkm::cont::DataSet& result,
|
||||
{
|
||||
if (field.IsPointField())
|
||||
{
|
||||
vtkm::cont::UnknownArrayHandle inputArray = field.GetData();
|
||||
vtkm::cont::UnknownArrayHandle outputArray = inputArray.NewInstanceBasic();
|
||||
|
||||
auto resolve = [&](const auto& concrete) {
|
||||
// use std::decay to remove const ref from the decltype of concrete.
|
||||
using T = typename std::decay_t<decltype(concrete)>::ValueType;
|
||||
vtkm::cont::ArrayHandle<T> outputArray;
|
||||
worklet.ProcessPointField(concrete, outputArray);
|
||||
result.AddPointField(field.GetName(), outputArray);
|
||||
using BaseT = typename std::decay_t<decltype(concrete)>::ValueType::ComponentType;
|
||||
auto concreteOut = outputArray.ExtractArrayFromComponents<BaseT>();
|
||||
worklet.ProcessPointField(concrete, concreteOut);
|
||||
};
|
||||
|
||||
field.GetData()
|
||||
.CastAndCallForTypesWithFloatFallback<VTKM_DEFAULT_TYPE_LIST, VTKM_DEFAULT_STORAGE_LIST>(
|
||||
resolve);
|
||||
inputArray.CastAndCallWithExtractedArray(resolve);
|
||||
result.AddPointField(field.GetName(), outputArray);
|
||||
return true;
|
||||
}
|
||||
else if (field.IsCellField())
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user