Merge branch 'master' of https://gitlab.kitware.com/vtk/vtk-m into remove_templates_from_streamline_filters

This commit is contained in:
Dave Pugmire 2022-07-25 11:52:45 -04:00
commit d2aacfc07e
693 changed files with 20362 additions and 11737 deletions

@ -206,9 +206,9 @@ stages:
- build/*.png
- build/*.pnm
- build/*.pmm
- build/junit.xml
reports:
junit:
- build/junit.xml
junit: build/junit.xml
.cmake_build_artifacts: &cmake_build_artifacts
artifacts:
@ -223,17 +223,9 @@ stages:
- build/config/
# CTest and CMake install files.
# XXX(globbing): Can be simplified with support from
# https://gitlab.com/gitlab-org/gitlab-runner/issues/4840
#
# Note: this also captures our CIState.cmake file
- build/CMakeCache.txt
- build/*.cmake
- build/*/*.cmake
- build/*/*/*.cmake
- build/*/*/*/*.cmake
- build/*/*/*/*/*.cmake
- build/*/*/*/*/*/*.cmake
- build/**/*.cmake
- build/Testing/
# CDash files.
@ -245,30 +237,22 @@ stages:
when: always
paths:
# The generated regression testing images
- build/*.png
- build/*.pnm
- build/*.pmm
- build/*/*.png
- build/*/*.pnm
- build/*/*.pmm
- build/*/*/*.png
- build/*/*/*.pnm
- build/*/*/*.pmm
- build/*/*/*/*.png
- build/*/*/*/*.pnm
- build/*/*/*/*.pmm
- build/**/*.png
- build/**/*.pnm
- build/**/*.pmm
- build/junit.xml
reports:
junit:
- build/junit.xml
junit: build/junit.xml
include:
- local: '/.gitlab/ci/ascent.yml'
- local: '/.gitlab/ci/centos7.yml'
- local: '/.gitlab/ci/centos8.yml'
- local: '/.gitlab/ci/doxygen.yml'
- local: '/.gitlab/ci/macos.yml'
- local: '/.gitlab/ci/rhel8.yml'
- local: '/.gitlab/ci/ubuntu1604.yml'
- local: '/.gitlab/ci/ubuntu1804.yml'
- local: '/.gitlab/ci/ubuntu2004.yml'
- local: '/.gitlab/ci/windows10.yml'
- local: '/.gitlab/ci/ascent.yml'

@ -74,14 +74,6 @@ test:ascent_gcc_cuda:
# Tests errors to address due to different env/arch in Ascent
# Refer to issue: https://gitlab.kitware.com/vtk/vtk-m/-/issues/652
CTEST_EXCLUSIONS: >-
UnitTestMathSERIAL
UnitTestMathCUDA
UnitTestSerialDeviceAdapter
UnitTestAverageByKeySERIAL
UnitTestKeysSERIAL
UnitTestWorkletReduceByKeySERIAL
RegressionTestAmrArraysSERIAL
RegressionTestAmrArraysCUDA
before_script:
# Prep the environment

@ -5,28 +5,27 @@ set -x
version="${1:-3.21.1}"
# We require CMake >= 3.13 in the CI to support CUDA builds
readonly -A linuxParamsByVersion=(
['3.13.5']='e2fd0080a6f0fc1ec84647acdcd8e0b4019770f48d83509e6a5b0b6ea27e5864 Linux'
['3.21.1']='bf496ce869d0aa8c1f57e4d1a2e50c8f2fb12a6cd7ccb37ad743bb88f6b76a1e linux'
)
if [ -z "${linuxParamsByVersion[$version]}" ]
then
echo "Given version ($version) is unsupported"
exit 1
fi
case "$( uname -s )" in
Linux)
shatool="sha256sum"
# We require CMake >= 3.13 in the CI to support CUDA builds
readonly -A linuxParamsByVersion=(
['3.13.5']='e2fd0080a6f0fc1ec84647acdcd8e0b4019770f48d83509e6a5b0b6ea27e5864 Linux'
['3.21.1']='bf496ce869d0aa8c1f57e4d1a2e50c8f2fb12a6cd7ccb37ad743bb88f6b76a1e linux'
)
if [ -z "${linuxParamsByVersion[$version]}" ]
then
echo "Given version ($version) is unsupported"
exit 1
fi
sha256sum=$(cut -f 1 <<<"${linuxParamsByVersion[$version]}")
platform=$(cut -f 2 <<<"${linuxParamsByVersion[$version]}")
arch="x86_64"
;;
Darwin)
shatool="shasum -a 256"
sha256sum="20dbede1d80c1ac80be2966172f8838c3d899951ac4467372f806b386d42ad3c"
sha256sum="9dc2978c4d94a44f71336fa88c15bb0eee47cf44b6ece51b10d1dfae95f82279"
platform="macos"
arch="universal"
;;

@ -101,7 +101,11 @@ foreach(option IN LISTS options)
# From turing we set the architecture using the cannonical
# CMAKE_CUDA_ARCHITECTURES
elseif(turing STREQUAL option)
set(CMAKE_CUDA_ARCHITECTURES "75" CACHE STRING "")
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.18)
set(CMAKE_CUDA_ARCHITECTURES "75" CACHE STRING "")
else()
set(VTKm_CUDA_Architecture "turing" CACHE STRING "")
endif()
elseif(hip STREQUAL option)
if(CMAKE_VERSION VERSION_LESS_EQUAL 3.20)

@ -42,12 +42,18 @@ if (test_exclusions)
set(test_exclusions "(${test_exclusions})")
endif ()
if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.21)
set(junit_args OUTPUT_JUNIT "${CTEST_BINARY_DIRECTORY}/junit.xml")
endif()
# reduced parallel level so we don't exhaust system resources
ctest_memcheck(
PARALLEL_LEVEL "4"
RETURN_VALUE test_result
EXCLUDE "${test_exclusions}"
DEFECT_COUNT defects)
DEFECT_COUNT defects
${junit_args}
)
ctest_submit(PARTS Memcheck BUILD_ID build_id)
message(STATUS "Memcheck submission build_id: ${build_id}")

@ -32,7 +32,7 @@ if (test_exclusions)
set(test_exclusions "(${test_exclusions})")
endif ()
if (CMAKE_VERSION VERSION_GREATER 3.21.0)
if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.21)
set(junit_args OUTPUT_JUNIT "${CTEST_BINARY_DIRECTORY}/junit.xml")
endif()

74
.gitlab/ci/macos.yml Normal file

@ -0,0 +1,74 @@
# Ad-hoc build that runs in macos machines
build:macos_xcode13:
extends:
- .macos_xcode13
- .macos_build_tags
- .cmake_build_macos
- .run_automatically
test:macos_xcode13:
extends:
- .macos_xcode13
- .macos_build_tags
- .cmake_test_macos
- .run_automatically
needs:
- build:macos_xcode13
dependencies:
- build:macos_xcode13
.macos_xcode13:
variables:
CMAKE_BUILD_TYPE: RelWithDebInfo
CMAKE_GENERATOR: Ninja
CC: gcc
CXX: g++
DEVELOPER_DIR: "/Applications/Xcode-13.3.app/Contents/Developer"
VTKM_SETTINGS: "64bit_floats+shared+ccache"
.cmake_build_macos:
stage: build
interruptible: true
variables:
CCACHE_BASEDIR: "$CI_PROJECT_DIR"
CCACHE_DIR: "$CI_PROJECT_DIR/ccache"
# -isystem= is not affected by CCACHE_BASEDIR, thus we must ignore it
CCACHE_IGNOREOPTIONS: "-isystem=*"
CCACHE_COMPILERCHECK: "content"
CCACHE_NOHASHDIR: "true"
CCACHE_RESHARE: "true"
before_script:
- .gitlab/ci/config/cmake.sh
- export PATH=$PWD/.gitlab/cmake/bin:$PATH
- "cmake --version"
- "cmake -V -P .gitlab/ci/config/fetch_vtkm_tags.cmake"
- "cmake -V -P .gitlab/ci/config/gitlab_ci_setup.cmake"
- "ctest -VV -S .gitlab/ci/ctest_configure.cmake"
script:
- "ctest -VV -S .gitlab/ci/ctest_build.cmake"
after_script:
- ccache -v -s
- ccache -z
extends:
- .cmake_build_artifacts
.cmake_test_macos:
stage: test
interruptible: true
before_script:
- .gitlab/ci/config/cmake.sh
- export PATH=$PWD/.gitlab/cmake/bin:$PATH
- cmake --version
script:
- "ctest $CTEST_TIMEOUT -VV -S .gitlab/ci/ctest_test.cmake"
extends:
- .cmake_test_artifacts
.macos_build_tags:
tags:
- vtk-m
- macos
- xcode-13.3
- nonconcurrent

@ -47,17 +47,9 @@
- build/config/
# CTest and CMake install files.
# XXX(globbing): Can be simplified with support from
# https://gitlab.com/gitlab-org/gitlab-runner/issues/4840
#
# Note: this also captures our CIState.cmake file
- build/CMakeCache.txt
- build/*.cmake
- build/*/*.cmake
- build/*/*/*.cmake
- build/*/*/*/*.cmake
- build/*/*/*/*/*.cmake
- build/*/*/*/*/*/*.cmake
- build/**/*.cmake
- build/Testing/
# CDash files.

@ -21,46 +21,64 @@ git submodule update --recursive --init
## Create update branch
- [ ] Create update branch `git checkout -b update-to-v@VERSION@`
<!-- if @RC@ == "-rc1"
<!-- if @RC@ == "-rc1"-->
- [ ] Bring as a second parent the history of master (Solve conflicts always
taking master's version)
```
git merge --no-ff origin/master
```
-->
<!-- endif -->
<!-- Do we have new release notes?
<!-- if not a patch release -->
- [ ] Update the major and minor version in `version.txt`:
```
echo "@MAJOR@.@MINOR@.9999" > version.txt
git add version.txt`
```
<!-- endif -->
- [ ] Update the version (not in patch releases) and date in the LICENSE.md
file `git add LICENSE.md`.
- [ ] Create commit that updates the License (and version.txt if modified):
```
git commit -m 'release: update version and License'
```
<!-- Do we have new release notes? -->
- [ ] Craft or update [changelog](#generate-change-log)
`docs/changelog/@VERSION@/release-notes.md` file.
- [ ] Create release notes commit.
```
git add docs/changelog/@VERSION@/release-notes.md
git rm docs/changelog/*.md
git commit -m 'Add release notes for @VERSION@@RC@'
git commit -m 'release: @VERSION@@RC@ release notes'
```
-->
- [ ] Update the version (not in patch releases) and date in the LICENSE.md
file.
<!-- endif -->
- [ ] Create update version commit:
```
# Create branch
git checkout -b update-to-v@VERSION@@RC@
echo @VERSION@@RC@ > version.txt
git add version.txt
# Create commit with the following template
# Nth is counted by the number of tags
# Nth is counted by the number of final release tags
git commit -m '@VERSION@@RC@ is our Nth official release of VTK-m.
The major changes to VTK-m from (previous release) can be found in:
docs/changelog/@VERSION@/release-notes.md' version.txt'
docs/changelog/@VERSION@/release-notes.md' version.txt
```
- [ ] `git tag -a -m 'VTKm @VERSION@@RC@' v@VERSION@@RC@ HEAD`
- Integrate changes to `release` branch
- [ ] Create a MR using the [release-mr script][1]
(see [notes](#notes-about-update-mr)).
<!-- if not patch release -->
- [ ] Add (or ensure) at the bottom of the description of the merge request:
`Backport: master:HEAD~1`
<!-- elseif patch release -->
- [ ] Remove (or ensure) that at the bottom of the description of the merge
request there is no `Backport` instruction.
<!-- endif -->
- [ ] Get +1
- [ ] `Do: merge`
- Push tags
@ -76,10 +94,14 @@ The major changes to VTK-m from (previous release) can be found in:
- [ ] Tag new version of the [VTK-m User Guide][2].
<!-- endif -->
- [ ] Post an [Email Announcements](#email-announcements) VTK-m mailing list.
<!-- if not patch release -->
- [ ] Ensure that the content of `version.txt` in master is
`[@MAJOR@ @MINOR@](@MAJOR@.@MINOR@.9999)`.
<!-- endif release -->
---
# Annex
# Annex
## Generate change log
Construct a `docs/changelog/@VERSION@/` folder.
@ -157,6 +179,16 @@ to the relevant `release-notes` section.
Lastly, `update-mr` can be used multiple times with different commit in the same
branch.
## Notes about version.txt
Master and release branch do not share the same version.txt scheme. In the
release branch the patch and release-candidate version is observed whereas in
master the patch field is fixed to _9999_ indicating that each of its commit is
a developing release.
- Master: `@MAJOR@.@MINOR@.9999`
- Release: `@MAJOR@.@MINOR@.@PATCH@@RC@`
## Email Announcements
Announce the new VTK-m release on the mailing list. You will need to compute

@ -13,11 +13,11 @@ include(VTKmWrappers)
function(vtkm_create_test_executable
prog_name
sources
device_sources
libraries
defines
is_mpi_test
use_mpi
enable_all_backends
use_job_pool)
vtkm_diy_use_mpi_push()
@ -41,23 +41,12 @@ function(vtkm_create_test_executable
#the creation of the test source list needs to occur before the labeling as
#cuda. This is so that we get the correctly named entry points generated
create_test_sourcelist(test_sources ${prog}.cxx ${sources} ${extraArgs})
create_test_sourcelist(test_sources ${prog}.cxx ${sources} ${device_sources} ${extraArgs})
add_executable(${prog} ${prog}.cxx ${sources})
add_executable(${prog} ${test_sources})
vtkm_add_drop_unused_function_flags(${prog})
target_compile_definitions(${prog} PRIVATE ${defines})
#determine if we have a device that requires a separate compiler enabled
set(device_lang_enabled FALSE)
if( (TARGET vtkm::cuda) OR (TARGET vtkm::kokkos_cuda) OR (TARGET vtkm::kokkos_hip))
set(device_lang_enabled TRUE)
endif()
#if all backends are enabled, we can use the device compiler to handle all possible backends.
set(device_sources)
if(device_lang_enabled AND (enable_all_backends OR (TARGET vtkm::kokkos_hip)))
set(device_sources ${sources})
endif()
vtkm_add_target_information(${prog} DEVICE_SOURCES ${device_sources})
if(NOT VTKm_USE_DEFAULT_SYMBOL_VISIBILITY)
@ -83,68 +72,89 @@ endfunction()
# (package, module, whatever you call it). Usage:
#
# vtkm_unit_tests(
# NAME
# [ NAME <name> ]
# SOURCES <source_list>
# LIBRARIES <dependent_library_list>
# DEFINES <target_compile_definitions>
# TEST_ARGS <argument_list>
# MPI
# ALL_BACKENDS
# USE_VTKM_JOB_POOL
# <options>
# [ DEVICE_SOURCES <source_list> ]
# [ LIBRARIES <dependent_library_list> ]
# [ DEFINES <target_compile_definitions> ]
# [ TEST_ARGS <argument_list> ]
# [ MPI ]
# [ BACKEND <device> ]
# [ ALL_BACKENDS ]
# [ USE_VTKM_JOB_POOL ]
# )
#
# [LIBRARIES] : extra libraries that this set of tests need to link too
# NAME : Specify the name of the testing executable. If not specified,
# UnitTests_<kitname> is used.
#
# [DEFINES] : extra defines that need to be set for all unit test sources
# SOURCES: A list of the source files. Each file is expected to contain a
# function with the same name as the source file. For example, if SOURCES
# contains `UnitTestFoo.cxx`, then `UnitTestFoo.cxx` should contain a
# function named `UnitTestFoo`. A test with this name is also added to ctest.
#
# [LABEL] : CTest Label to associate to this set of tests
# LIBRARIES: Extra libraries that this set of tests need to link to.
#
# [TEST_ARGS] : arguments that should be passed on the command line to the
# test executable
# DEFINES: Extra defines to be set for all unit test sources.
#
# [MPI] : when specified, the tests should be run in parallel if
# MPI is enabled. The tests should also be able to build and run
# When MPI is not available, i.e., they should not make explicit
# use of MPI and instead completely rely on DIY.
# [ALL_BACKENDS] : when specified, the tests would test against all enabled
# backends. Otherwise we expect the tests to manage the
# backends at runtime.
# TEST_ARGS: Arguments that should be passed on the command line to the
# test executable when executed by ctest.
#
# MPI: When specified, the tests should be run in parallel if MPI is enabled.
# The tests should also be able to build and run when MPI is not available,
# i.e., they should not make explicit use of MPI and instead completely rely
# on DIY.
#
# BACKEND: When used, a specific backend will be forced for the device.
# A `--vtkm-device` flag will be given to the command line argument with the
# specified device. When not used, a backend will be chosen.
#
# ALL_BACKENDS: When used, a separate ctest test is created for each device
# that VTK-m is compiled for. The call will add the `--vtkm-device` flag when
# running the test to force the test for a particular backend.
#
function(vtkm_unit_tests)
set(options)
set(global_options ${options} USE_VTKM_JOB_POOL MPI ALL_BACKENDS)
set(oneValueArgs BACKEND NAME LABEL)
set(multiValueArgs SOURCES LIBRARIES DEFINES TEST_ARGS)
set(multiValueArgs SOURCES DEVICE_SOURCES LIBRARIES DEFINES TEST_ARGS)
cmake_parse_arguments(VTKm_UT
"${global_options}" "${oneValueArgs}" "${multiValueArgs}"
${ARGN}
)
vtkm_parse_test_options(VTKm_UT_SOURCES "${options}" ${VTKm_UT_SOURCES})
set(per_device_command_line_arguments "NONE")
set(per_device_suffix "")
set(per_device_timeout 180)
set(per_device_serial FALSE)
set(per_device_command_line_arguments)
set(per_device_suffix)
set(per_device_timeout)
set(per_device_serial)
set(enable_all_backends ${VTKm_UT_ALL_BACKENDS})
if(enable_all_backends)
set(per_device_command_line_arguments --vtkm-device=serial)
set(per_device_suffix "SERIAL")
if (VTKm_ENABLE_CUDA)
if(NOT VTKm_UT_BACKEND)
set(enable_all_backends ${VTKm_UT_ALL_BACKENDS})
# If ALL_BACKENDS is specified, add a test for each backend. If it is not
# specified, pick a backend to use. Pick the most "specific" backend so
# that different CI builds will use different backends. This ensures that
# we do not have a test that always drops down to serial.
if(VTKm_ENABLE_CUDA AND (enable_all_backends OR NOT per_device_suffix))
list(APPEND per_device_command_line_arguments --vtkm-device=cuda)
list(APPEND per_device_suffix "CUDA")
#CUDA tests generally require more time because of kernel generation.
list(APPEND per_device_timeout 1500)
list(APPEND per_device_serial FALSE)
endif()
if (VTKm_ENABLE_TBB)
if(VTKm_ENABLE_KOKKOS AND (enable_all_backends OR NOT per_device_suffix))
list(APPEND per_device_command_line_arguments --vtkm-device=kokkos)
list(APPEND per_device_suffix "KOKKOS")
#may require more time because of kernel generation.
list(APPEND per_device_timeout 1500)
list(APPEND per_device_serial FALSE)
endif()
if(VTKm_ENABLE_TBB AND (enable_all_backends OR NOT per_device_suffix))
list(APPEND per_device_command_line_arguments --vtkm-device=tbb)
list(APPEND per_device_suffix "TBB")
list(APPEND per_device_timeout 180)
list(APPEND per_device_serial FALSE)
endif()
if (VTKm_ENABLE_OPENMP)
if(VTKm_ENABLE_OPENMP AND (enable_all_backends OR NOT per_device_suffix))
list(APPEND per_device_command_line_arguments --vtkm-device=openmp)
list(APPEND per_device_suffix "OPENMP")
list(APPEND per_device_timeout 180)
@ -154,13 +164,26 @@ function(vtkm_unit_tests)
#serially
list(APPEND per_device_serial TRUE)
endif()
if (VTKm_ENABLE_KOKKOS)
list(APPEND per_device_command_line_arguments --vtkm-device=kokkos)
list(APPEND per_device_suffix "KOKKOS")
#may require more time because of kernel generation.
list(APPEND per_device_timeout 1500)
if(enable_all_backends OR NOT per_device_suffix)
list(APPEND per_device_command_line_arguments --vtkm-device=serial)
list(APPEND per_device_suffix "SERIAL")
list(APPEND per_device_timeout 180)
list(APPEND per_device_serial FALSE)
endif()
if(NOT enable_all_backends)
# If not enabling all backends, exactly one backend should have been added.
list(LENGTH per_device_suffix number_of_devices)
if(NOT number_of_devices EQUAL 1)
message(FATAL_ERROR "Expected to pick one backend")
endif()
endif()
else()
# A specific backend was requested.
set(per_device_command_line_arguments --vtkm-device=${VTKm_UT_BACKEND})
set(per_device_suffix ${VTKm_UT_BACKEND})
set(per_device_timeout 180)
# Some devices don't like multiple tests run at the same time.
set(per_device_serial TRUE)
endif()
set(test_prog)
@ -188,33 +211,33 @@ function(vtkm_unit_tests)
vtkm_create_test_executable(
${test_prog}
"${VTKm_UT_SOURCES}"
"${VTKm_UT_DEVICE_SOURCES}"
"${VTKm_UT_LIBRARIES}"
"${VTKm_UT_DEFINES}"
ON # is_mpi_test
ON # use_mpi
${enable_all_backends}
${VTKm_UT_USE_VTKM_JOB_POOL})
endif()
if ((NOT VTKm_ENABLE_MPI) OR VTKm_ENABLE_DIY_NOMPI)
vtkm_create_test_executable(
${test_prog}
"${VTKm_UT_SOURCES}"
"${VTKm_UT_DEVICE_SOURCES}"
"${VTKm_UT_LIBRARIES}"
"${VTKm_UT_DEFINES}"
ON # is_mpi_test
OFF # use_mpi
${enable_all_backends}
${VTKm_UT_USE_VTKM_JOB_POOL})
endif()
else()
vtkm_create_test_executable(
${test_prog}
"${VTKm_UT_SOURCES}"
"${VTKm_UT_DEVICE_SOURCES}"
"${VTKm_UT_LIBRARIES}"
"${VTKm_UT_DEFINES}"
OFF # is_mpi_test
OFF # use_mpi
${enable_all_backends}
${VTKm_UT_USE_VTKM_JOB_POOL})
endif()
@ -225,19 +248,16 @@ function(vtkm_unit_tests)
#exclusive on the end ( e.g. for(i=0; i < n; ++i))
break()
endif()
if(per_device_command_line_arguments STREQUAL "NONE")
set(device_command_line_argument)
set(upper_backend ${per_device_suffix})
set(timeout ${per_device_timeout})
set(run_serial ${per_device_serial})
else()
list(GET per_device_command_line_arguments ${index} device_command_line_argument)
if(enable_all_backends)
list(GET per_device_suffix ${index} upper_backend)
list(GET per_device_timeout ${index} timeout)
list(GET per_device_serial ${index} run_serial)
else()
set(upper_backend)
endif()
list(GET per_device_command_line_arguments ${index} device_command_line_argument)
list(GET per_device_timeout ${index} timeout)
list(GET per_device_serial ${index} run_serial)
foreach (test ${VTKm_UT_SOURCES})
foreach (test ${VTKm_UT_SOURCES} ${VTKm_UT_DEVICE_SOURCES})
get_filename_component(tname ${test} NAME_WE)
if(VTKm_UT_MPI)
if (VTKm_ENABLE_MPI)

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:b70d68db818220a5c30d34b4dd14db000d6a2d7f4e117c5509f03e236186825b
size 20123

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:8012ca572ca38b64fda0f617a9471a48d268e35c12a1352ce3725e8e27577a58
size 16910

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:3ad37f93e562178c5491e06256083630ad6b5d500f9b19683a72ad91c0b4ab05
size 95406

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e500611307400dd0d618a37d4160722d471a971db4f4accb698c207259c38bb7
size 25221

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:91506c6a411f536fcf549ecdb74520d072b184d4b6e168c19f11b864db0f6bb4
size 37260

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:bb998a6d7ae70371a82e1de0778fcc0259996d0bb13bbf55bc14a9efd0f663e4
size 131853

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6658a13bb64a4921bda3ed49d2de7021cf2e31257e5b9e5bbbbfd2ad3c85c044
size 21634

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e56a995e539990ac31477dd6001bd80307e8a6337da8d27836b5cbc5eea31b8c
size 1790

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d3bfe6fda1f13176da2a934296a29c7a022e9c7803029d824aff35fa1c1a5460
size 405

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6372aec0eb79ee7c99de0e1546ff946dcfac2ea0eb7fb575fddc80decf0a438b
size 572

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:a272a8d800bca5bc879d52cb4999562378c5ac108d953634b1dbad7ad07d8c8a
size 1031

78
docs/HotFixGuide.md Normal file

@ -0,0 +1,78 @@
# HotFix Guide
## HotFix general instructions
The following instructions intend to be general case for applying hotfixes in
release branches, for more specific cases, simplified instructions are to be
found in the below sub-sections.
1. Find the oldest relevant release branch BASE to which this hotfix applies.
- Relevant release branches include: release, and release-specific
maintained branches.
2. Create a hotfix branch branching from BASE.
- if the hotfix branch already exists `git rebase --onto BASE`.
3. Open a merge-request targeting:
- master, if applies to master.
- Otherwise, release, if applies to the latest release.
- Otherwise, the most recent release-specific branch to which this hotfix
applies.
- Lastly, if none of above, BASE.
4. (If needed) If the hotfix is a backport (cherry-picked) of an existing merge-requests,
add a cross-reference each of the existing merge-request with the format of `!1234`
inside the description of the newly created merge-request.
- Cherry-pick each of the relevant commits of the existing merge-requests using
`git cherry-pick -x XXYYZZ`.
5. At the bottom of the description of the merge-request add: `Backport: branch_name`
directive for each of the branches that exists between BASE (inclusive) and
the branch that we target our merge-request (exclusive).
In the case of merge conflicts in any of the backports refer to [Kitware backport guide][1].
## HotFix for latest release and master branch only
For hotfixes that applies to release and master branch, create a branch based
off of the tip of the release branch and create a merge-request targeting master.
If the hotfix branch already exists based off of a commit in the master branch,
you can change the base branch of the hotfix branch from master to latest
release with:
```
# Assuming that both your local master and release branch are updated; and
# assuming that you are currently in your topic branch
git rebase --onto release master
```
Next, you can bring this commit to __release__ by adding the following line to
the bottom of the MR description: `Backport: release`. This directive will later
internally instruct the Kitware Robot to bring the changes of the hotfix branch
creating a merge commit in the release branch with its second parent being the
hotfix branch tip.
Lastly, the master branch history will be automatically connected with
release after the merge-request is merged as explained in
[here](#How-master-and-release-branch-are-connected).
## HotFix for release branch only
For hotfixes that only applies to release branch, whose changes are unneeded in
master, create a branch based off of the __release__ branch and create a
merge-request targeting __release__ branch. Proceed as in a regular MR.
### How master and release branch are connected
Every merge commit in the release branch will be automatically connected to
master branch by our Gitlab robot creating a merge-request using the
`-s ours` strategy, __note__ that `-s ours` strategy does not actually bring any
change to the target branch, it will solely create an empty merge commit in master
connecting release branch..
## Other cases
There are more possible case scenarios that you might encounter while attempting
to bring a hotfix to release, for further cases please refer to the
[Kitware backport guide][1] which this document is based of.
[1]: https://gitlab.kitware.com/utils/git-workflow/-/wikis/Backport-topics

@ -1,55 +0,0 @@
Release HotFix
===============
# HotFix from master branch
## On a single MR
You have created a branch from master branch and you have a MR request targeting
the __master__ branch.
You can bring this commit to __release__ by adding to any empty line of the MR
description box the following directive.
```
Backport: release
```
This will cherry-pick this commit and push it to __release__ after typing `Do:
merge` in a comment.
You must also make sure that there will not be any merge conflict with the
__release__ branch, thus you need to create an additional commit using the following
command:
```
git merge --no-ff origin/release
```
This will ensure that backport will be able to push your commit to __release__.
## On multiple MRs
1. Create one merge request sourcing your HotFix branch and targeting __master__
and merge.
2. Create one merge request sourcing __master__ and targeting __release__ and merge.
# HotFix from release branch
You have created a branch from the __release__ branch and you have a MR request
targeting __release__, you can proceed as in a regular MR.
Every merge in release will be automatically brought to master by the robot
using `-s ours` strategy.
__VERY IMPORTANT__: `-s ours` strategy does not actually bring any change to the
target branch, thus if needed you might want to bring the changes
from the HotFix to __master__ by creating a another MR which cherry-picks
the merge commit in `release` for the given HotFix.
Use the difference to first parent for the cherry-pick commit:
```
git cherry-pick -m1 -x <HASH OF COMMIT>
```

@ -3,7 +3,7 @@ Release Process
## Prologue
This document is divided in two parts:
This document is divided in two parts:
- A overview of the branching and release scheme used in VTK-m.
- A concise instructions to get started with the release process.
@ -18,10 +18,30 @@ While all of the development is performed in the master branch, once in a while
when we want to do a release, we tag a commit in master and we push it to the
release branch.
Also there are times when we want to get _Hotfix_ that affects previous releases
Also there are times when we want to get _hotfix_ that affects previous releases
to the release branch, in this case we can also push the merge request commit
with the fix into the release branch.
## Release-specific branches
Sometime we need to keep maintaining an older release which does not sit at the
tip of the release branch. For this purpose we use release-specific branches
with the name of `release-@MAJOR_VER@.@MINOR_VER@`.
To create a new release-specific branch you need someone with push access to
create a release-specific branch pointing at the latest commit of the minor
release of interest, this is, for release-1.7 it will be v1.7.1 as opposed to
v1.7.0.
There can be the case that between release X.Y and X.Y+1 there are hotfixes
commits that do not correspond to a patch tag releases. In this particular case,
create the release-specific branch pointing to the last commit before X.Y+1.
To add a hotfix to a release-specific branch, follow the instructions described
in [HotFixes](./ReleaseHotFix.md) noting that you need to adjust the branch
names from release to `release-@MAJOR_VER@.@MINOR_VER@`.
A not so simple example of how the branching scheme looks like can be found
here:
@ -29,28 +49,28 @@ here:
# → git log --graph --decorate --oneline --all
* 2e9230d (master) Merge branch 'update'
|\
|\
| * 59279dd (HEAD -> release, tag: v1.0.1) v1.0.1 2nd release of VTKm
| * b60611b Add release notes for v1.0.1
| * 9d26451 Merge branch 'master' into update
| |\
| |/
|/|
| |\
| |/
|/|
* | 75137e5 Unrelated commit
* | e982be0 Merge branch 'release'
|\|
|\|
| * f2c4eb6 Merge branch 'hotfix' into release
| |\
| |\
| | * c1c2655 Hotfix
| |/
| |/
* | e53df9e Unrelated commit
* | ec6b481 Unrelated commit
|/
|/
* 0742a47 (tag: v1.0.0) v1.0.0 1st release of VTKm
* 4fe993c Add release notes for v1.0.0
```
This will make the release branch to only contain tags and _HotFix_ merges as
This will make the release branch to only contain tags and _hotfix_ merges as
shown in here:
```git

23
docs/ReleaseRoadmap.md Normal file

@ -0,0 +1,23 @@
# Minor 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 | | Short Term* | TBD |
| 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 |
## Legend
- Version: Only counts major and minor versions, patch releases are released
unscheduled as needed.
- Date: Scheduled date for the Final Release of the corresponding release.
- Delay: Days of delay between scheduled date and release date.
- Life-cycle: The duration of the support:
- Long Term, usually maintained for one natural year, it might use a
specific-release support branch if it is not the latest release.
- Short Term, usually maintained until the next minor release, usually 3-6
months.

@ -39,33 +39,6 @@ VTK-m 1.8 Release Notes
# Core
## Remove brigand from List.h
Early in the development of VTK-m, a third party header library named
brigand was incorporated into the source code. This header file contained
the implementation of several complex meta-template programming constructs
that are useful. Furthermore, it is implemented in such a way as to compile
(relatively) quickly.
However, lately we have run into problems with brigand. First, it is not a
very active project so that it is hard to submit fixes back to the project.
Of the activity that is there, the most recent version of brigand now
requires C++17, which is not directly supported by VTK-m. Second, brigand
was added before the thridparty directory was established. This means as we
have added corrections to the brigand source code, they have not been
properly marked up in git to allow us to easily bring in changes from the
main repo. On top of all that, because of the complexity of brigand, we
often run into problems with compilers that fail in corner cases, which
makes it difficult to support.
We have already moved away from brigand quite a bit. This takes another big
step closer to removing our independence on brigand by no longer requiring
it for any of the implementation of `vtkm::List`.
Because brigand.hpp is no longer included in List.h, some uses of the
brigand header have been replaced with the implementation in List.h.
## New `vtkm::List` features
New features were added to those available in `vtkm/List.h`. These new

@ -0,0 +1,5 @@
# Fix bug with copying invalid variants
There was a bug where if you attempted to copy a `Variant` that was not
valid (i.e. did not hold an object); a seg fault could happen. This has
been changed to set the target variant to also be invalid.

@ -0,0 +1,14 @@
# Add test for array and datas that are cleaned up after finalize
It is the case that arrays might be deallocated from a device after the
device is closed. This can happen, for example, when an `ArrayHandle` is
declared globally. It gets constructed before VTK-m is initialized. This
is OK as long as you do not otherwise use it until VTK-m is initialized.
However, if you use that `ArrayHandle` to move data to a device and that
data is left on the device when the object closes, then the
`ArrayHandle` will be left holding a reference to invalid device memory
once the device is shut down. This can cause problems when the
`ArrayHandle` destructs itself and attempts to release this memory.
The VTK-m devices should gracefully handle deallocations that happen
after device shutdown.

@ -0,0 +1,15 @@
# Fix type comparison on OSX
`UnknownArrayHandle` compares `std::type_index` objects to check whether a
requested type is the same as that held in the array handle. However, it is
possible that different translation units can create different but
equivalent `std::type_info`/`std::type_index` objects. In this case, the
`==` operator might return false for two equivalent types. This can happen
on OSX.
To get around this problem, `UnknownArrayHandle` now does a more extensive
check for `std::type_info` object. It first uses the `==` operator to
compare them (as before), which usually works but can possibly return
`false` when the correct result is `true`. To check for this case, it then
compares the name for the two types and returns `true` iff the two names
are the same.

@ -0,0 +1,30 @@
# Allow ArrayHandle to have a runtime selectable number of buffers
Previously, the number of buffers held by an `ArrayHandle` had to be
determined statically at compile time by the storage. Most of the time this
is fine. However, there are some exceptions where the number of buffers
need to be selected at runtime. For example, the `ArrayHandleRecombineVec`
does not specify the number of components it uses, and it needed a hack
where it stored buffers in the metadata of another buffer, which is bad.
This change allows the number of buffers to vary at runtime (at least at
construction). The buffers were already managed in a `std::vector`. It now
no longer forces the vector to be a specific size. `GetNumberOfBuffers` was
removed from the `Storage`. Instead, if the number of buffers was not
specified at construction, an allocation of size 0 is done to create
default buffers.
The biggest change is to the interface of the storage object methods, which
now take `std::vector` instead of pointers to `Buffer` objects. This adds a
little hassle in having to copy subsets of this `vector` when a storage
object has multiple sub-arrays. But it does simplify some of the
templating.
Other changes to the `Storage` structure include requiring all objects to
include a `CreateBuffers` method that accepts no arguments. This method
will be used by `ArrayHandle` in its default constructor. Previously,
`ArrayHandle` would create the `vector` of `Buffer` objects itself, but it
now must call this method in the `Storage` to do this. (It also has a nice
side effect of allowing the `Storage` to initialize the buffer objects if
necessary. Another change was to remove the `GetNumberOfBuffers` method
(which no longer has meaning).

@ -0,0 +1,17 @@
# Divided the mesh quality filter
The original implementation of the `MeshQuality` filter created one large
kernel with a switch statement that jumped to the code of the metric
actually desired. This is problematic for a couple of reasons. First, it
takes the compiler a long time to optimize for all the inlined cases of a
large kernel. Second, it creates a larger than necessary function that has
to be loaded onto the GPU to execute.
The code was modified to move the switch statement outside of the GPU
kernel. Instead, the routine for each metric is compiled into its own
kernel. For convenience, each routine is wrapped into its own independent
filter (e.g., `MeshQualityArea`, `MeshQualityVolume`). The uber
`MeshQuality` filter still exists, and its use is still encouraged even if
you only need a particular metric. However, internally the switch statement
now occurs on the host to select the appropriate specific filter that loads
a more targeted kernel.

@ -0,0 +1,10 @@
# Added DEVICE_SOURCES to vtkm_unit_tests
The `vtkm_unit_tests` function in the CMake build now allows you to specify
which files need to be compiled with a device compiler using the
`DEVICE_SOURCES` argument. Previously, the only way to specify that unit
tests needed to be compiled with a device compiler was to use the
`ALL_BACKENDS` argument, which would automatically compile everything with
the device compiler as well as test the code on all backends.
`ALL_BACKENDS` is still supported, but it no longer changes the sources to
be compiled with the device compiler.

@ -0,0 +1,11 @@
# Do not require `VecTraits` for `UnknownArrayHandle` components
Whan an `UnknownArrayHandler` is constructed from an `ArrayHandle`, it uses
the `VecTraits` of the component type to construct its internal functions.
This meant that you could not put an `ArrayHandle` with a component type
that did not have `VecTraits` into an `UnknownArrayHandle`.
`UnknownArrayHandle` now no longer needs the components of its arrays to
have `VecTraits`. If the component type of the array does not have
`VecTraits`, it treats the components as if they are a scalar type.

@ -0,0 +1,7 @@
# Fix bug with voxels in legacy vtk files
The legacy VTK file reader for unstructured grids had a bug when reading
cells of type voxel. VTK-m does not support the voxel cell type in
unstructured grids (i.e. explicit cell sets), so it has to convert them to
hexahedron cells. A bug in the reader was mangling the cell array index
during this conversion.

@ -58,7 +58,7 @@
#include <vtkm/cont/DataSetBuilderUniform.h>
#include <vtkm/cont/Initialize.h>
#include <vtkm/filter/ContourTreeUniform.h>
#include <vtkm/filter/scalar_topology/ContourTreeUniform.h>
#include <fstream>
#include <vector>
@ -105,7 +105,7 @@ int main(int argc, char* argv[])
inDataSet.AddPointField("values", values);
// Convert 2D mesh of values into contour tree, pairs of vertex ids
vtkm::filter::ContourTreeMesh2D filter;
vtkm::filter::scalar_topology::ContourTreeMesh2D filter;
filter.SetActiveField("values");
// Output data set is pairs of saddle and peak vertex IDs
vtkm::cont::DataSet output = filter.Execute(inDataSet);

@ -58,7 +58,7 @@
#include <vtkm/cont/DataSetBuilderUniform.h>
#include <vtkm/cont/Initialize.h>
#include <vtkm/filter/ContourTreeUniform.h>
#include <vtkm/filter/scalar_topology/ContourTreeUniform.h>
#include <fstream>
#include <vector>
@ -106,7 +106,7 @@ int main(int argc, char* argv[])
inDataSet.AddPointField("values", values);
// Convert 3D mesh of values into contour tree, pairs of vertex ids
vtkm::filter::ContourTreeMesh3D filter;
vtkm::filter::scalar_topology::ContourTreeMesh3D filter;
filter.SetActiveField("values");
// Output data set is pairs of saddle and peak vertex IDs
vtkm::cont::DataSet output = filter.Execute(inDataSet);

@ -71,11 +71,11 @@
#include <vtkm/cont/Timer.h>
#include <vtkm/io/BOVDataSetReader.h>
#include <vtkm/filter/ContourTreeUniformAugmented.h>
#include <vtkm/worklet/contourtree_augmented/PrintVectors.h>
#include <vtkm/worklet/contourtree_augmented/ProcessContourTree.h>
#include <vtkm/worklet/contourtree_augmented/Types.h>
#include <vtkm/worklet/contourtree_augmented/processcontourtree/Branch.h>
#include <vtkm/filter/scalar_topology/ContourTreeUniformAugmented.h>
#include <vtkm/filter/scalar_topology/worklet/contourtree_augmented/PrintVectors.h>
#include <vtkm/filter/scalar_topology/worklet/contourtree_augmented/ProcessContourTree.h>
#include <vtkm/filter/scalar_topology/worklet/contourtree_augmented/Types.h>
#include <vtkm/filter/scalar_topology/worklet/contourtree_augmented/processcontourtree/Branch.h>
// clang-format off
VTKM_THIRDPARTY_PRE_INCLUDE
@ -644,7 +644,8 @@ int main(int argc, char* argv[])
prevTime = currTime;
// Convert the mesh of values into contour tree, pairs of vertex ids
vtkm::filter::ContourTreeAugmented filter(useMarchingCubes, computeRegularStructure);
vtkm::filter::scalar_topology::ContourTreeAugmented filter(useMarchingCubes,
computeRegularStructure);
#ifdef WITH_MPI
filter.SetSpatialDecomposition(

@ -0,0 +1,77 @@
//============================================================================
// 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.
//
// Copyright 2014 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2014 UT-Battelle, LLC.
// Copyright 2014 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
// Copyright (c) 2018, The Regents of the University of California, through
// Lawrence Berkeley National Laboratory (subject to receipt of any required approvals
// from the U.S. Dept. of Energy). All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// (1) Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// (2) Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// (3) Neither the name of the University of California, Lawrence Berkeley National
// Laboratory, U.S. Dept. of Energy nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//
//=============================================================================
//
// COMMENTS:
//
// Input is assumed to be a sequence of lines of the form:
// I Global ID of branch root
// II Value of supernode
// III Global ID of supernode
//
// All lines are assumed to have been sorted already. Because of how the
// Unix sort utility operates (textual sort), the most we can assume is that all
// supernodes corresponding to a given branch root are sorted together.
//
// We therefore do simple stream processing, identifying new branches by
// the changes in root ID.
//
//=======================================================================================
#include <vtkm/filter/scalar_topology/worklet/contourtree_distributed/BranchCompiler.h>
int main()
{ // main()
vtkm::worklet::contourtree_distributed::BranchCompiler compiler;
compiler.Parse(std::cin);
compiler.Print(std::cout);
return 0;
} // main()

@ -81,10 +81,16 @@ if (VTKm_ENABLE_MPI)
target_link_libraries(TreeCompiler vtkm_filter)
vtkm_add_target_information(TreeCompiler DROP_UNUSED_SYMBOLS)
add_executable(BranchCompiler BranchCompilerApp.cxx)
target_link_libraries(BranchCompiler vtkm_filter)
vtkm_add_target_information(BranchCompiler DROP_UNUSED_SYMBOLS)
configure_file(split_data_2d.py split_data_2d.py COPYONLY)
configure_file(split_data_3d.py split_data_3d.py COPYONLY)
configure_file(hact_test.sh hact_test.sh COPYONLY)
configure_file(hact_test_volume.sh hact_test_volume.sh COPYONLY)
configure_file(hact_test_branch_decomposition.sh hact_test_branch_decomposition.sh COPYONLY)
configure_file(testrun_branch_decomposition.sh testrun_branch_decomposition.sh COPYONLY)
configure_file(testrun.sh testrun.sh COPYONLY)
configure_file(testrun_volume.sh testrun_volume.sh COPYONLY)
endif()

@ -71,12 +71,14 @@
#include <vtkm/cont/Timer.h>
#include <vtkm/io/BOVDataSetReader.h>
#include <vtkm/filter/ContourTreeUniformDistributed.h>
#include <vtkm/worklet/contourtree_augmented/PrintVectors.h>
#include <vtkm/worklet/contourtree_augmented/ProcessContourTree.h>
#include <vtkm/worklet/contourtree_augmented/Types.h>
#include <vtkm/worklet/contourtree_distributed/HierarchicalContourTree.h>
#include <vtkm/worklet/contourtree_distributed/TreeCompiler.h>
#include <vtkm/filter/scalar_topology/ContourTreeUniformDistributed.h>
#include <vtkm/filter/scalar_topology/DistributedBranchDecompositionFilter.h>
#include <vtkm/filter/scalar_topology/worklet/branch_decomposition/HierarchicalVolumetricBranchDecomposer.h>
#include <vtkm/filter/scalar_topology/worklet/contourtree_augmented/PrintVectors.h>
#include <vtkm/filter/scalar_topology/worklet/contourtree_augmented/ProcessContourTree.h>
#include <vtkm/filter/scalar_topology/worklet/contourtree_augmented/Types.h>
#include <vtkm/filter/scalar_topology/worklet/contourtree_distributed/HierarchicalContourTree.h>
#include <vtkm/filter/scalar_topology/worklet/contourtree_distributed/TreeCompiler.h>
// clang-format off
VTKM_THIRDPARTY_PRE_INCLUDE
@ -203,6 +205,19 @@ int main(int argc, char* argv[])
augmentHierarchicalTree = true;
}
bool computeHierarchicalVolumetricBranchDecomposition = false;
if (parser.hasOption("--computeVolumeBranchDecomposition"))
{
computeHierarchicalVolumetricBranchDecomposition = true;
if (!augmentHierarchicalTree)
{
VTKM_LOG_S(vtkm::cont::LogLevel::Warn,
"Warning: --computeVolumeBranchDecomposition only "
"allowed augmentation. Enabling --augmentHierarchicalTree option.");
augmentHierarchicalTree = true;
}
}
bool useBoundaryExtremaOnly = true;
if (parser.hasOption("--useFullBoundary"))
{
@ -261,7 +276,7 @@ int main(int argc, char* argv[])
{
if (rank == 0)
{
std::cout << "ContourTreeAugmented <options> <fileName>" << std::endl;
std::cout << "ContourTreeDistributed <options> <fileName>" << std::endl;
std::cout << std::endl;
std::cout << "<fileName> Name of the input data file." << std::endl;
std::cout << "The file is expected to be ASCII with either: " << std::endl;
@ -284,6 +299,9 @@ int main(int argc, char* argv[])
<< std::endl;
std::cout << " and when using only boundary extrema." << std::endl;
std::cout << "--augmentHierarchicalTree Augment the hierarchical tree." << std::endl;
std::cout << "--computeVolumeBranchDecomposition Compute the volume branch decomposition. "
<< std::endl;
std::cout << " Requries --augmentHierarchicalTree to be set." << std::endl;
std::cout << "--preSplitFiles Input data is already pre-split into blocks." << std::endl;
std::cout << "--saveDot Save DOT files of the distributed contour tree " << std::endl
<< " computation (Default=False). " << std::endl;
@ -311,6 +329,9 @@ int main(int argc, char* argv[])
<< " mc=" << useMarchingCubes << std::endl
<< " useFullBoundary=" << !useBoundaryExtremaOnly << std::endl
<< " saveDot=" << saveDotFiles << std::endl
<< " augmentHierarchicalTree=" << augmentHierarchicalTree << std::endl
<< " computeVolumetricBranchDecomposition="
<< computeHierarchicalVolumetricBranchDecomposition << std::endl
<< " saveOutputData=" << saveOutputData << std::endl
<< " forwardSummary=" << forwardSummary << std::endl
<< " nblocks=" << numBlocks << std::endl);
@ -847,12 +868,12 @@ int main(int argc, char* argv[])
localBlockIndices,
localBlockOrigins,
localBlockSizes,
useBoundaryExtremaOnly,
useMarchingCubes,
augmentHierarchicalTree,
saveDotFiles,
timingsLogLevel,
treeLogLevel);
filter.SetUseBoundaryExtremaOnly(useBoundaryExtremaOnly);
filter.SetUseMarchingCubes(useMarchingCubes);
filter.SetAugmentHierarchicalTree(augmentHierarchicalTree);
filter.SetSaveDotFiles(saveDotFiles);
filter.SetActiveField("values");
// Execute the contour tree analysis
@ -872,35 +893,57 @@ int main(int argc, char* argv[])
{
if (augmentHierarchicalTree)
{
for (vtkm::Id ds_no = 0; ds_no < result.GetNumberOfPartitions(); ++ds_no)
if (computeHierarchicalVolumetricBranchDecomposition)
{
auto ds = result.GetPartition(ds_no);
vtkm::worklet::contourtree_augmented::IdArrayType supernodes;
ds.GetField("Supernodes").GetData().AsArrayHandle(supernodes);
vtkm::worklet::contourtree_augmented::IdArrayType superarcs;
ds.GetField("Superarcs").GetData().AsArrayHandle(superarcs);
vtkm::worklet::contourtree_augmented::IdArrayType regularNodeGlobalIds;
ds.GetField("RegularNodeGlobalIds").GetData().AsArrayHandle(regularNodeGlobalIds);
vtkm::Id totalVolume = globalSize[0] * globalSize[1] * globalSize[2];
vtkm::worklet::contourtree_augmented::IdArrayType intrinsicVolume;
ds.GetField("IntrinsicVolume").GetData().AsArrayHandle(intrinsicVolume);
vtkm::worklet::contourtree_augmented::IdArrayType dependentVolume;
ds.GetField("DependentVolume").GetData().AsArrayHandle(dependentVolume);
vtkm::filter::scalar_topology::DistributedBranchDecompositionFilter bd_filter(
blocksPerDim, globalSize, localBlockIndices, localBlockOrigins, localBlockSizes);
auto bd_result = bd_filter.Execute(result);
std::string dumpVolumesString =
vtkm::worklet::contourtree_distributed::HierarchicalContourTree<ValueType>::DumpVolumes(
supernodes,
superarcs,
regularNodeGlobalIds,
totalVolume,
intrinsicVolume,
dependentVolume);
for (vtkm::Id ds_no = 0; ds_no < result.GetNumberOfPartitions(); ++ds_no)
{
auto ds = bd_result.GetPartition(ds_no);
std::string branchDecompositionFileName = std::string("BranchDecomposition_Rank_") +
std::to_string(static_cast<int>(rank)) + std::string("_Block_") +
std::to_string(static_cast<int>(ds_no)) + std::string(".txt");
std::string volumesFileName = std::string("TreeWithVolumes_Rank_") +
std::to_string(static_cast<int>(rank)) + std::string("_Block_") +
std::to_string(static_cast<int>(ds_no)) + std::string(".txt");
std::ofstream treeStream(volumesFileName.c_str());
treeStream << dumpVolumesString;
std::ofstream treeStream(branchDecompositionFileName.c_str());
treeStream
<< vtkm::filter::scalar_topology::HierarchicalVolumetricBranchDecomposer::PrintBranches(
ds);
}
}
else
{
for (vtkm::Id ds_no = 0; ds_no < result.GetNumberOfPartitions(); ++ds_no)
{
auto ds = result.GetPartition(ds_no);
vtkm::worklet::contourtree_augmented::IdArrayType supernodes;
ds.GetField("Supernodes").GetData().AsArrayHandle(supernodes);
vtkm::worklet::contourtree_augmented::IdArrayType superarcs;
ds.GetField("Superarcs").GetData().AsArrayHandle(superarcs);
vtkm::worklet::contourtree_augmented::IdArrayType regularNodeGlobalIds;
ds.GetField("RegularNodeGlobalIds").GetData().AsArrayHandle(regularNodeGlobalIds);
vtkm::Id totalVolume = globalSize[0] * globalSize[1] * globalSize[2];
vtkm::worklet::contourtree_augmented::IdArrayType intrinsicVolume;
ds.GetField("IntrinsicVolume").GetData().AsArrayHandle(intrinsicVolume);
vtkm::worklet::contourtree_augmented::IdArrayType dependentVolume;
ds.GetField("DependentVolume").GetData().AsArrayHandle(dependentVolume);
std::string dumpVolumesString =
vtkm::worklet::contourtree_distributed::HierarchicalContourTree<ValueType>::DumpVolumes(
supernodes,
superarcs,
regularNodeGlobalIds,
totalVolume,
intrinsicVolume,
dependentVolume);
std::string volumesFileName = std::string("TreeWithVolumes_Rank_") +
std::to_string(static_cast<int>(rank)) + std::string("_Block_") +
std::to_string(static_cast<int>(ds_no)) + std::string(".txt");
std::ofstream treeStream(volumesFileName.c_str());
treeStream << dumpVolumesString;
}
}
}
else

@ -61,7 +61,7 @@
//==============================================================================
#include <stdio.h>
#include <vtkm/worklet/contourtree_distributed/TreeCompiler.h>
#include <vtkm/filter/scalar_topology/worklet/contourtree_distributed/TreeCompiler.h>
// main routine
int main(int argc, char** argv)

@ -0,0 +1,44 @@
#!/bin/sh
GTCT_DIR=${GTCT_DIR:-${HOME}/devel/parallel-peak-pruning/ContourTree/SweepAndMergeSerial/out}
RED=""
GREEN=""
NC=""
if [ -t 1 ]; then
# If stdout is a terminal, color Pass and FAIL green and red, respectively
RED=$(tput setaf 1)
GREEN=$(tput setaf 2)
NC=$(tput sgr0)
fi
echo "Removing previously generated files"
rm *.log *.dat
echo "Copying target file "$1 "into current directory"
filename=${1##*/}
fileroot=${filename%.txt}
cp $1 ${filename}
echo "Splitting data into "$2" x "$2" parts"
./split_data_2d.py ${filename} $2
rm ${filename}
echo "Running HACT"
n_parts=$(($2*$2))
# mpirun -np 4 --oversubscribe ./ContourTree_Distributed --vtkm-device Any --preSplitFiles --saveOutputData --augmentHierarchicalTree --computeVolumeBranchDecomposition --numBlocks=${n_parts} ${fileroot}_part_%d_of_${n_parts}.txt
mpirun -np 2 --oversubscribe ./ContourTree_Distributed --vtkm-device Any --preSplitFiles --saveOutputData --augmentHierarchicalTree --computeVolumeBranchDecomposition --numBlocks=${n_parts} ${fileroot}_part_%d_of_${n_parts}.txt
rm ${fileroot}_part_*_of_${n_parts}.txt
echo "Compiling Outputs"
sort -u BranchDecomposition_Rank_*.txt > outsort${fileroot}_$2x$2.txt
cat outsort${fileroot}_$2x$2.txt | ./BranchCompiler | sort > bcompile${fileroot}_$2x$2.txt
rm BranchDecomposition_Rank_*.txt outsort${fileroot}_$2x$2.txt
echo "Diffing"
echo diff bcompile${fileroot}_$2x$2.txt ${GTCT_DIR}/branch_decomposition_volume_hybrid_${fileroot}.txt
diff bcompile${fileroot}_$2x$2.txt ${GTCT_DIR}/branch_decomposition_volume_hybrid_${fileroot}.txt
if test $? -eq 0; then echo "${GREEN}Pass${NC}"; rm bcompile${fileroot}_$2x$2.txt; else echo "${RED}FAIL${NC}"; fi;
# echo "Generating Dot files"
# ./makedot.sh

@ -0,0 +1,99 @@
#!/bin/sh
mkdir -p out
DATA_DIR=${DATA_DIR:-${HOME}/devel/parallel-peak-pruning/Data/2D}
if [ ! -d $DATA_DIR ]; then
echo "Error: Directory $DATA_DIR does not exist!"
exit 1;
fi;
echo
echo "Starting Timing Runs"
echo
echo "8x9 Test Set"
./hact_test_branch_decomposition.sh $DATA_DIR/8x9test.txt 2
./hact_test_branch_decomposition.sh $DATA_DIR/8x9test.txt 4
# ./hact_test_branch_decomposition.sh $DATA_DIR/8x9test.txt 8
echo
echo "Vancouver Test Set"
./hact_test_branch_decomposition.sh $DATA_DIR/vanc.txt 2
./hact_test_branch_decomposition.sh $DATA_DIR/vanc.txt 4
# ./hact_test_branch_decomposition.sh $DATA_DIR/vanc.txt 8
# ./hact_test_branch_decomposition.sh $DATA_DIR/vanc.txt 16
echo
echo "Vancouver SWSW Test Set"
./hact_test_branch_decomposition.sh $DATA_DIR/vancouverSWSW.txt 2
./hact_test_branch_decomposition.sh $DATA_DIR/vancouverSWSW.txt 4
./hact_test_branch_decomposition.sh $DATA_DIR/vancouverSWSW.txt 8
# ./hact_test_branch_decomposition.sh $DATA_DIR/vancouverSWSW.txt 16
echo
echo "Vancouver SWNW Test Set"
./hact_test_branch_decomposition.sh $DATA_DIR/vancouverSWNW.txt 2
./hact_test_branch_decomposition.sh $DATA_DIR/vancouverSWNW.txt 4
./hact_test_branch_decomposition.sh $DATA_DIR/vancouverSWNW.txt 8
# ./hact_test_branch_decomposition.sh $DATA_DIR/vancouverSWNW.txt 16
echo
echo "Vancouver SWSE Test Set"
./hact_test_branch_decomposition.sh $DATA_DIR/vancouverSWSE.txt 2
./hact_test_branch_decomposition.sh $DATA_DIR/vancouverSWSE.txt 4
./hact_test_branch_decomposition.sh $DATA_DIR/vancouverSWSE.txt 8
# ./hact_test_branch_decomposition.sh $DATA_DIR/vancouverSWSE.txt 16
echo
echo "Vancouver SWNE Test Set"
./hact_test_branch_decomposition.sh $DATA_DIR/vancouverSWNE.txt 2
./hact_test_branch_decomposition.sh $DATA_DIR/vancouverSWNE.txt 4
./hact_test_branch_decomposition.sh $DATA_DIR/vancouverSWNE.txt 8
# ./hact_test_branch_decomposition.sh $DATA_DIR/vancouverSWNE.txt 16
echo
echo "Vancouver NE Test Set"
./hact_test_branch_decomposition.sh $DATA_DIR/vancouverNE.txt 2
./hact_test_branch_decomposition.sh $DATA_DIR/vancouverNE.txt 4
./hact_test_branch_decomposition.sh $DATA_DIR/vancouverNE.txt 8
# ./hact_test_branch_decomposition.sh $DATA_DIR/vancouverNE.txt 16
echo
echo "Vancouver NW Test Set"
./hact_test_branch_decomposition.sh $DATA_DIR/vancouverNW.txt 2
./hact_test_branch_decomposition.sh $DATA_DIR/vancouverNW.txt 4
./hact_test_branch_decomposition.sh $DATA_DIR/vancouverNW.txt 8
# ./hact_test_branch_decomposition.sh $DATA_DIR/vancouverNW.txt 16
echo
echo "Vancouver SE Test Set"
./hact_test_branch_decomposition.sh $DATA_DIR/vancouverSE.txt 2
./hact_test_branch_decomposition.sh $DATA_DIR/vancouverSE.txt 4
./hact_test_branch_decomposition.sh $DATA_DIR/vancouverSE.txt 8
# ./hact_test_branch_decomposition.sh $DATA_DIR/vancouverSE.txt 16
echo
echo "Vancouver SW Test Set"
./hact_test_branch_decomposition.sh $DATA_DIR/vancouverSW.txt 2
./hact_test_branch_decomposition.sh $DATA_DIR/vancouverSW.txt 4
./hact_test_branch_decomposition.sh $DATA_DIR/vancouverSW.txt 8
# ./hact_test_branch_decomposition.sh $DATA_DIR/vancouverSW.txt 16
echo
echo "Icefields Test Set"
./hact_test_branch_decomposition.sh $DATA_DIR/icefield.txt 2
./hact_test_branch_decomposition.sh $DATA_DIR/icefield.txt 4
./hact_test_branch_decomposition.sh $DATA_DIR/icefield.txt 8
# ./hact_test_branch_decomposition.sh $DATA_DIR/icefield.txt 16
# ./hact_test_branch_decomposition.sh $DATA_DIR/icefield.txt 32
# ./hact_test_branch_decomposition.sh $DATA_DIR/icefield.txt 64
echo
echo "GTOPO30 Full Tiny Test Set"
./hact_test_branch_decomposition.sh $DATA_DIR/gtopo_full_tiny.txt 2
./hact_test_branch_decomposition.sh $DATA_DIR/gtopo_full_tiny.txt 4
./hact_test_branch_decomposition.sh $DATA_DIR/gtopo_full_tiny.txt 8
# ./hact_test_branch_decomposition.sh $DATA_DIR/gtopo_full_tiny.txt 16
# ./hact_test_branch_decomposition.sh $DATA_DIR/gtopo_full_tiny.txt 32
# ./hact_test_branch_decomposition.sh $DATA_DIR/gtopo_full_tiny.txt 64
echo
echo "GTOPO30 UK Tile Test Set"
./hact_test_branch_decomposition.sh $DATA_DIR/gtopo30w020n40.txt 2
./hact_test_branch_decomposition.sh $DATA_DIR/gtopo30w020n40.txt 4
./hact_test_branch_decomposition.sh $DATA_DIR/gtopo30w020n40.txt 8
# ./hact_test_branch_decomposition.sh $DATA_DIR/gtopo30w020n40.txt 16
# ./hact_test_branch_decomposition.sh $DATA_DIR/gtopo30w020n40.txt 32
# ./hact_test_branch_decomposition.sh $DATA_DIR/gtopo30w020n40.txt 64
# ./hact_test_branch_decomposition.sh $DATA_DIR/gtopo30w020n40.txt 128
# ./hact_test_branch_decomposition.sh $DATA_DIR/gtopo30w020n40.txt 256
# ./hact_test_branch_decomposition.sh $DATA_DIR/gtopo30w020n40.txt 512
echo "Done"

@ -36,11 +36,16 @@ target_link_libraries(two_filters vtkm_filter vtkm_io)
add_executable(mag_grad mag_grad.cxx)
target_link_libraries(mag_grad vtkm_filter 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
DROP_UNUSED_SYMBOLS MODIFY_CUDA_FLAGS
DEVICE_SOURCES mag_grad.cxx)
if (VTKm_ENABLE_RENDERING)
add_executable(rendering rendering.cxx)
target_link_libraries(rendering vtkm_filter vtkm_io vtkm_rendering)
endif()
endif ()
add_executable(error_handling error_handling.cxx)
target_link_libraries(error_handling vtkm_filter vtkm_io)
@ -50,46 +55,15 @@ target_link_libraries(logging vtkm_filter vtkm_io)
add_executable(point_to_cell point_to_cell.cxx)
target_link_libraries(point_to_cell vtkm_cont vtkm_filter 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)
set(tutorial_targets
io
contour
contour_two_fields
two_filters
mag_grad
error_handling
logging
point_to_cell
extract_edges
)
set(tutorial_sources
io.cxx
contour.cxx
contour_two_fields.cxx
two_filters.cxx
mag_grad.cxx
error_handling.cxx
logging.cxx
point_to_cell.cxx
extract_edges.cxx
)
if (VTKm_ENABLE_RENDERING)
list(APPEND tutorial_sources rendering.cxx)
list(APPEND tutorial_targets rendering)
endif()
vtkm_add_target_information(${tutorial_targets}
DROP_UNUSED_SYMBOLS
MODIFY_CUDA_FLAGS
DEVICE_SOURCES
${tutorial_sources})
vtkm_add_target_information(extract_edges
DROP_UNUSED_SYMBOLS MODIFY_CUDA_FLAGS
DEVICE_SOURCES extract_edges.cxx)
# Copy the data file to be adjacent to the binaries
file(GENERATE OUTPUT "$<TARGET_FILE_DIR:mag_grad>/data/kitchen.vtk" INPUT "${CMAKE_CURRENT_SOURCE_DIR}/data/kitchen.vtk")

@ -21,6 +21,8 @@
#include <vtkm/io/VTKDataSetWriter.h>
#include <vtkm/filter/FilterDataSet.h>
#include <vtkm/filter/MapFieldMergeAverage.h>
#include <vtkm/filter/MapFieldPermutation.h>
#include <vtkm/filter/contour/Contour.h>
#include <vtkm/worklet/WorkletMapTopology.h>
@ -117,95 +119,23 @@ struct EdgeIndicesWorklet : vtkm::worklet::WorkletReduceByKey
namespace
{
class ExtractEdges : public vtkm::filter::FilterDataSet<ExtractEdges>
{
public:
template <typename Policy>
VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& inData,
vtkm::filter::PolicyBase<Policy> policy);
template <typename T, typename StorageType, typename Policy>
VTKM_CONT bool DoMapField(vtkm::cont::DataSet& result,
const vtkm::cont::ArrayHandle<T, StorageType>& input,
const vtkm::filter::FieldMetadata& fieldMeta,
const vtkm::filter::PolicyBase<Policy>& policy);
private:
vtkm::worklet::ScatterCounting::OutputToInputMapType OutputToInputCellMap;
vtkm::worklet::Keys<vtkm::Id2> CellToEdgeKeys;
};
template <typename Policy>
inline VTKM_CONT vtkm::cont::DataSet ExtractEdges::DoExecute(
const vtkm::cont::DataSet& inData,
vtkm::filter::PolicyBase<Policy> policy)
{
auto inCellSet = vtkm::filter::ApplyPolicyCellSet(inData.GetCellSet(), policy, *this);
// First, count the edges in each cell.
vtkm::cont::ArrayHandle<vtkm::IdComponent> edgeCounts;
this->Invoke(CountEdgesWorklet{}, inCellSet, edgeCounts);
// Second, using these counts build a scatter that repeats a cell's visit
// for each edge in the cell.
vtkm::worklet::ScatterCounting scatter(edgeCounts);
this->OutputToInputCellMap = scatter.GetOutputToInputMap(inCellSet.GetNumberOfCells());
vtkm::worklet::ScatterCounting::VisitArrayType outputToInputEdgeMap =
scatter.GetVisitArray(inCellSet.GetNumberOfCells());
// Third, for each edge, extract a canonical id.
vtkm::cont::ArrayHandle<vtkm::Id2> canonicalIds;
this->Invoke(EdgeIdsWorklet{}, scatter, inCellSet, canonicalIds);
// Fourth, construct a Keys object to combine all like edge ids.
this->CellToEdgeKeys = vtkm::worklet::Keys<vtkm::Id2>(canonicalIds);
// Fifth, use a reduce-by-key to extract indices for each unique edge.
vtkm::cont::ArrayHandle<vtkm::Id> connectivityArray;
this->Invoke(EdgeIndicesWorklet{},
this->CellToEdgeKeys,
inCellSet,
this->OutputToInputCellMap,
outputToInputEdgeMap,
vtkm::cont::make_ArrayHandleGroupVec<2>(connectivityArray));
// Sixth, use the created connectivity array to build a cell set.
vtkm::cont::CellSetSingleType<> outCellSet;
outCellSet.Fill(inCellSet.GetNumberOfPoints(), vtkm::CELL_SHAPE_LINE, 2, connectivityArray);
vtkm::cont::DataSet outData;
outData.SetCellSet(outCellSet);
for (vtkm::IdComponent coordSystemIndex = 0;
coordSystemIndex < inData.GetNumberOfCoordinateSystems();
++coordSystemIndex)
{
outData.AddCoordinateSystem(inData.GetCoordinateSystem(coordSystemIndex));
}
return outData;
}
template <typename T, typename StorageType, typename Policy>
inline VTKM_CONT bool ExtractEdges::DoMapField(
VTKM_CONT bool DoMapField(
vtkm::cont::DataSet& result,
const vtkm::cont::ArrayHandle<T, StorageType>& inputArray,
const vtkm::filter::FieldMetadata& fieldMeta,
const vtkm::filter::PolicyBase<Policy>&)
const vtkm::cont::Field& inputField,
const vtkm::worklet::ScatterCounting::OutputToInputMapType& OutputToInputCellMap,
const vtkm::worklet::Keys<vtkm::Id2>& CellToEdgeKeys)
{
vtkm::cont::Field outputField;
if (fieldMeta.IsPointField())
if (inputField.IsFieldPoint())
{
outputField = fieldMeta.AsField(inputArray); // pass through
outputField = inputField; // pass through
}
else if (fieldMeta.IsCellField())
else if (inputField.IsFieldCell())
{
auto outputCellArray = vtkm::worklet::AverageByKey::Run(
this->CellToEdgeKeys,
vtkm::cont::make_ArrayHandlePermutation(this->OutputToInputCellMap, inputArray));
outputField = fieldMeta.AsField(outputCellArray);
vtkm::cont::Field permuted;
vtkm::filter::MapFieldPermutation(inputField, OutputToInputCellMap, permuted);
vtkm::filter::MapFieldMergeAverage(permuted, CellToEdgeKeys, outputField);
}
else
{
@ -217,6 +147,55 @@ inline VTKM_CONT bool ExtractEdges::DoMapField(
return true;
}
class ExtractEdges : public vtkm::filter::NewFilter
{
public:
VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& inData) override;
};
VTKM_CONT vtkm::cont::DataSet ExtractEdges::DoExecute(const vtkm::cont::DataSet& inData)
{
auto inCellSet = inData.GetCellSet();
// First, count the edges in each cell.
vtkm::cont::ArrayHandle<vtkm::IdComponent> edgeCounts;
this->Invoke(CountEdgesWorklet{}, inCellSet, edgeCounts);
// Second, using these counts build a scatter that repeats a cell's visit
// for each edge in the cell.
vtkm::worklet::ScatterCounting scatter(edgeCounts);
vtkm::worklet::ScatterCounting::OutputToInputMapType OutputToInputCellMap;
OutputToInputCellMap = scatter.GetOutputToInputMap(inCellSet.GetNumberOfCells());
vtkm::worklet::ScatterCounting::VisitArrayType outputToInputEdgeMap =
scatter.GetVisitArray(inCellSet.GetNumberOfCells());
// Third, for each edge, extract a canonical id.
vtkm::cont::ArrayHandle<vtkm::Id2> canonicalIds;
this->Invoke(EdgeIdsWorklet{}, scatter, inCellSet, canonicalIds);
// Fourth, construct a Keys object to combine all like edge ids.
vtkm::worklet::Keys<vtkm::Id2> CellToEdgeKeys;
CellToEdgeKeys = vtkm::worklet::Keys<vtkm::Id2>(canonicalIds);
// Fifth, use a reduce-by-key to extract indices for each unique edge.
vtkm::cont::ArrayHandle<vtkm::Id> connectivityArray;
this->Invoke(EdgeIndicesWorklet{},
CellToEdgeKeys,
inCellSet,
OutputToInputCellMap,
outputToInputEdgeMap,
vtkm::cont::make_ArrayHandleGroupVec<2>(connectivityArray));
// Sixth, use the created connectivity array to build a cell set.
vtkm::cont::CellSetSingleType<> outCellSet;
outCellSet.Fill(inCellSet.GetNumberOfPoints(), vtkm::CELL_SHAPE_LINE, 2, connectivityArray);
auto mapper = [&](auto& outDataSet, const auto& f) {
DoMapField(outDataSet, f, OutputToInputCellMap, CellToEdgeKeys);
};
return this->CreateResult(inData, outCellSet, inData.GetCoordinateSystems(), mapper);
}
}
int main(int argc, char** argv)

@ -28,29 +28,30 @@ struct ComputeMagnitude : vtkm::worklet::WorkletMapField
}
};
#include <vtkm/filter/FilterField.h>
#include <vtkm/filter/NewFilterField.h>
class FieldMagnitude : public vtkm::filter::FilterField<FieldMagnitude>
class FieldMagnitude : public vtkm::filter::NewFilterField
{
public:
using SupportedTypes = vtkm::List<vtkm::Vec3f>;
template <typename ArrayHandleType, typename Policy>
VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& inDataSet,
const ArrayHandleType& inField,
const vtkm::filter::FieldMetadata& fieldMetadata,
vtkm::filter::PolicyBase<Policy>)
VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& inDataSet) override
{
const auto& inField = this->GetFieldFromDataSet(inDataSet);
vtkm::cont::ArrayHandle<vtkm::FloatDefault> outField;
this->Invoke(ComputeMagnitude{}, inField, outField);
auto resolveType = [&](const auto& concrete) {
this->Invoke(ComputeMagnitude{}, concrete, outField);
};
this->CastAndCallVecField<3>(inField, resolveType);
std::string outFieldName = this->GetOutputFieldName();
if (outFieldName == "")
{
outFieldName = fieldMetadata.GetName() + "_magnitude";
outFieldName = inField.GetName() + "_magnitude";
}
return vtkm::filter::CreateResult(inDataSet, outField, outFieldName, fieldMetadata);
return this->CreateResultFieldCell(inDataSet, outFieldName, outField);
}
};

@ -46,46 +46,39 @@ struct ConvertPointFieldToCells : vtkm::worklet::WorkletVisitCellsWithPoints
} // namespace worklet
} // namespace vtkm
#include <vtkm/filter/FilterField.h>
#include <vtkm/filter/NewFilterField.h>
namespace vtkm
{
namespace filter
{
struct ConvertPointFieldToCells : vtkm::filter::FilterField<ConvertPointFieldToCells>
struct ConvertPointFieldToCells : vtkm::filter::NewFilterField
{
template <typename ArrayHandleType, typename Policy>
VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& inDataSet,
const ArrayHandleType& inField,
const vtkm::filter::FieldMetadata& fieldMetadata,
vtkm::filter::PolicyBase<Policy>);
VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& inDataSet) override;
};
template <typename ArrayHandleType, typename Policy>
VTKM_CONT cont::DataSet ConvertPointFieldToCells::DoExecute(
const vtkm::cont::DataSet& inDataSet,
const ArrayHandleType& inField,
const vtkm::filter::FieldMetadata& fieldMetadata,
vtkm::filter::PolicyBase<Policy> policy)
VTKM_CONT cont::DataSet ConvertPointFieldToCells::DoExecute(const vtkm::cont::DataSet& inDataSet)
{
VTKM_IS_ARRAY_HANDLE(ArrayHandleType);
const auto& inField = this->GetFieldFromDataSet(inDataSet);
using ValueType = typename ArrayHandleType::ValueType;
vtkm::cont::UnknownArrayHandle outArray;
auto resolveType = [&](const auto& concrete) {
using ValueType = typename std::decay_t<decltype(concrete)>::ValueType;
vtkm::cont::ArrayHandle<ValueType> outField;
this->Invoke(vtkm::worklet::ConvertPointFieldToCells{},
vtkm::filter::ApplyPolicyCellSet(inDataSet.GetCellSet(), policy, *this),
inField,
outField);
vtkm::cont::ArrayHandle<ValueType> outField;
this->Invoke(
vtkm::worklet::ConvertPointFieldToCells{}, inDataSet.GetCellSet(), concrete, outField);
outArray = outField;
};
this->CastAndCallScalarField(inField, resolveType);
std::string outFieldName = this->GetOutputFieldName();
if (outFieldName == "")
{
outFieldName = fieldMetadata.GetName();
outFieldName = inField.GetName();
}
return vtkm::filter::CreateResultFieldCell(inDataSet, outField, outFieldName);
return this->CreateResultFieldCell(inDataSet, outFieldName, outArray);
}
} // namespace filter

@ -12,7 +12,6 @@
#include <vtkm/cont/Initialize.h>
#include <vtkm/io/VTKDataSetReader.h>
#include <vtkm/io/VTKDataSetWriter.h>
#include <vtkm/rendering/Actor.h>
#include <vtkm/rendering/CanvasRayTracer.h>
#include <vtkm/rendering/MapperRayTracer.h>

@ -1 +1 @@
1.8.0-rc1
1.8.9999

@ -314,7 +314,7 @@ public:
/// Constructs an empty ArrayHandle.
///
VTKM_CONT ArrayHandle()
: Buffers(static_cast<std::size_t>(StorageType::GetNumberOfBuffers()))
: Buffers(StorageType::CreateBuffers())
{
}
@ -349,17 +349,10 @@ public:
VTKM_CONT ArrayHandle(const std::vector<vtkm::cont::internal::Buffer>& buffers)
: Buffers(buffers)
{
VTKM_ASSERT(static_cast<vtkm::IdComponent>(this->Buffers.size()) == this->GetNumberOfBuffers());
}
VTKM_CONT ArrayHandle(std::vector<vtkm::cont::internal::Buffer>&& buffers) noexcept
: Buffers(std::move(buffers))
{
VTKM_ASSERT(static_cast<vtkm::IdComponent>(this->Buffers.size()) == this->GetNumberOfBuffers());
}
VTKM_CONT ArrayHandle(const vtkm::cont::internal::Buffer* buffers)
: Buffers(buffers, buffers + StorageType::GetNumberOfBuffers())
{
}
///@}
@ -423,9 +416,10 @@ public:
return true; // different valuetype and/or storage
}
VTKM_CONT static constexpr vtkm::IdComponent GetNumberOfBuffers()
VTKM_DEPRECATED(1.9, "Use the size of the std::vector returned from GetBuffers.")
VTKM_CONT constexpr vtkm::IdComponent GetNumberOfBuffers()
{
return StorageType::GetNumberOfBuffers();
return static_cast<vtkm::IdComponent>(this->GetBuffers().size());
}
/// Get the storage.
@ -779,9 +773,15 @@ public:
}
}
/// Returns the internal `Buffer` structures that hold the data.
/// \brief Returns the internal `Buffer` structures that hold the data.
///
VTKM_CONT vtkm::cont::internal::Buffer* GetBuffers() const { return this->Buffers.data(); }
/// Note that great care should be taken when modifying buffers outside of the ArrayHandle.
///
VTKM_CONT const std::vector<vtkm::cont::internal::Buffer>& GetBuffers() const
{
return this->Buffers;
}
VTKM_CONT std::vector<vtkm::cont::internal::Buffer>& GetBuffers() { return this->Buffers; }
private:
mutable std::vector<vtkm::cont::internal::Buffer> Buffers;
@ -792,11 +792,13 @@ protected:
this->Buffers[static_cast<std::size_t>(index)] = buffer;
}
// BufferContainer must be an iteratable container of Buffer objects.
template <typename BufferContainer>
VTKM_CONT void SetBuffers(const BufferContainer& buffers)
VTKM_CONT void SetBuffers(const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
std::copy(buffers.begin(), buffers.end(), this->Iterators->Buffers.begin());
this->Buffers = buffers;
}
VTKM_CONT void SetBuffers(std::vector<vtkm::cont::internal::Buffer>&& buffers)
{
this->Buffers = std::move(buffers);
}
};
@ -918,6 +920,25 @@ namespace internal
namespace detail
{
VTKM_CONT inline void CreateBuffersImpl(std::vector<vtkm::cont::internal::Buffer>&);
template <typename T, typename S, typename... Args>
VTKM_CONT inline void CreateBuffersImpl(std::vector<vtkm::cont::internal::Buffer>& buffers,
const vtkm::cont::ArrayHandle<T, S>& array,
const Args&... args);
template <typename... Args>
VTKM_CONT inline void CreateBuffersImpl(std::vector<vtkm::cont::internal::Buffer>& buffers,
const vtkm::cont::internal::Buffer& buffer,
const Args&... args);
template <typename... Args>
VTKM_CONT inline void CreateBuffersImpl(std::vector<vtkm::cont::internal::Buffer>& buffers,
const std::vector<vtkm::cont::internal::Buffer>& addbuffs,
const Args&... args);
template <typename Arg0, typename... Args>
VTKM_CONT inline void CreateBuffersImpl(std::vector<vtkm::cont::internal::Buffer>& buffers,
const Arg0& arg0,
const Args&... args);
VTKM_CONT inline void CreateBuffersImpl(std::vector<vtkm::cont::internal::Buffer>&)
{
// Nothing left to add.
@ -928,9 +949,7 @@ VTKM_CONT inline void CreateBuffersImpl(std::vector<vtkm::cont::internal::Buffer
const vtkm::cont::ArrayHandle<T, S>& array,
const Args&... args)
{
vtkm::cont::internal::Buffer* arrayBuffers = array.GetBuffers();
buffers.insert(buffers.end(), arrayBuffers, arrayBuffers + array.GetNumberOfBuffers());
CreateBuffersImpl(buffers, args...);
CreateBuffersImpl(buffers, array.GetBuffers(), args...);
}
template <typename... Args>
@ -951,11 +970,6 @@ VTKM_CONT inline void CreateBuffersImpl(std::vector<vtkm::cont::internal::Buffer
CreateBuffersImpl(buffers, args...);
}
template <typename Arg0, typename... Args>
VTKM_CONT inline void CreateBuffersImpl(std::vector<vtkm::cont::internal::Buffer>& buffers,
const Arg0& arg0,
const Args&... args);
template <typename T, typename S, typename... Args>
VTKM_CONT inline void CreateBuffersResolveArrays(std::vector<vtkm::cont::internal::Buffer>& buffers,
std::true_type,
@ -1004,7 +1018,7 @@ VTKM_CONT inline void CreateBuffersImpl(std::vector<vtkm::cont::internal::Buffer
/// - `ArrayHandle`: The buffers from the `ArrayHandle` are added to the list.
/// - `Buffer`: A copy of the buffer is added to the list.
/// - `std::vector<Buffer>`: A copy of all buffers in this vector are added to the list.
/// - Anything else: A buffer with the given object attached as metadata is
/// - Anything else: A buffer with the given object attached as metadata is added to the list.
///
template <typename... Args>
VTKM_CONT inline std::vector<vtkm::cont::internal::Buffer> CreateBuffers(const Args&... args)

@ -35,10 +35,13 @@ public:
using ReadPortalType = vtkm::internal::ArrayPortalBasicRead<T>;
using WritePortalType = vtkm::internal::ArrayPortalBasicWrite<T>;
VTKM_CONT constexpr static vtkm::IdComponent GetNumberOfBuffers() { return 1; }
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers()
{
return std::vector<vtkm::cont::internal::Buffer>(1);
}
VTKM_CONT static void ResizeBuffers(vtkm::Id numValues,
vtkm::cont::internal::Buffer* buffers,
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::CopyFlag preserve,
vtkm::cont::Token& token)
{
@ -46,36 +49,43 @@ public:
vtkm::internal::NumberOfValuesToNumberOfBytes<T>(numValues), preserve, token);
}
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers)
VTKM_CONT static vtkm::Id GetNumberOfValues(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return static_cast<vtkm::Id>(buffers->GetNumberOfBytes() /
VTKM_ASSERT(buffers.size() == 1);
return static_cast<vtkm::Id>(buffers[0].GetNumberOfBytes() /
static_cast<vtkm::BufferSizeType>(sizeof(T)));
}
VTKM_CONT static void Fill(vtkm::cont::internal::Buffer* buffers,
VTKM_CONT static void Fill(const std::vector<vtkm::cont::internal::Buffer>& buffers,
const T& fillValue,
vtkm::Id startIndex,
vtkm::Id endIndex,
vtkm::cont::Token& token)
{
VTKM_ASSERT(buffers.size() == 1);
constexpr vtkm::BufferSizeType fillValueSize =
static_cast<vtkm::BufferSizeType>(sizeof(fillValue));
buffers[0].Fill(
&fillValue, fillValueSize, startIndex * fillValueSize, endIndex * fillValueSize, token);
}
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
VTKM_CONT static ReadPortalType CreateReadPortal(
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{
VTKM_ASSERT(buffers.size() == 1);
return ReadPortalType(reinterpret_cast<const T*>(buffers[0].ReadPointerDevice(device, token)),
GetNumberOfValues(buffers));
}
VTKM_CONT static WritePortalType CreateWritePortal(vtkm::cont::internal::Buffer* buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
VTKM_CONT static WritePortalType CreateWritePortal(
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{
VTKM_ASSERT(buffers.size() == 1);
return WritePortalType(reinterpret_cast<T*>(buffers[0].WritePointerDevice(device, token)),
GetNumberOfValues(buffers));
}
@ -345,7 +355,8 @@ struct Serialization<vtkm::cont::ArrayHandleBasic<T>>
vtkm::cont::internal::Buffer buffer;
vtkmdiy::load(bb, buffer);
obj = vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagBasic>(&buffer);
obj = vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagBasic>(
vtkm::cont::internal::CreateBuffers(buffer));
}
};

@ -82,10 +82,13 @@ public:
using ReadPortalType = vtkm::cont::internal::ArrayPortalBitField<BitPortalConstType>;
using WritePortalType = vtkm::cont::internal::ArrayPortalBitField<BitPortalType>;
VTKM_CONT constexpr static vtkm::IdComponent GetNumberOfBuffers() { return 1; }
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers()
{
return std::vector<vtkm::cont::internal::Buffer>(1);
}
VTKM_CONT static void ResizeBuffers(vtkm::Id numberOfBits,
vtkm::cont::internal::Buffer* buffers,
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::CopyFlag preserve,
vtkm::cont::Token& token)
{
@ -102,20 +105,23 @@ public:
buffers[0].GetMetaData<vtkm::cont::internal::BitFieldMetaData>().NumberOfBits = numberOfBits;
}
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers)
VTKM_CONT static vtkm::Id GetNumberOfValues(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
VTKM_ASSERT(buffers.size() == 1);
vtkm::Id numberOfBits =
buffers[0].GetMetaData<vtkm::cont::internal::BitFieldMetaData>().NumberOfBits;
VTKM_ASSERT((buffers[0].GetNumberOfBytes() * CHAR_BIT) >= numberOfBits);
return numberOfBits;
}
VTKM_CONT static void Fill(vtkm::cont::internal::Buffer* buffers,
VTKM_CONT static void Fill(const std::vector<vtkm::cont::internal::Buffer>& buffers,
bool fillValue,
vtkm::Id startBit,
vtkm::Id endBit,
vtkm::cont::Token& token)
{
VTKM_ASSERT(buffers.size() == 1);
constexpr vtkm::BufferSizeType wordTypeSize =
static_cast<vtkm::BufferSizeType>(sizeof(WordType));
constexpr vtkm::BufferSizeType wordNumBits = wordTypeSize * CHAR_BIT;
@ -141,10 +147,12 @@ public:
}
}
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
VTKM_CONT static ReadPortalType CreateReadPortal(
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{
VTKM_ASSERT(buffers.size() == 1);
vtkm::Id numberOfBits = GetNumberOfValues(buffers);
VTKM_ASSERT((buffers[0].GetNumberOfBytes() * CHAR_BIT) >= numberOfBits);
@ -152,10 +160,12 @@ public:
BitPortalConstType(buffers[0].ReadPointerDevice(device, token), numberOfBits));
}
VTKM_CONT static WritePortalType CreateWritePortal(const vtkm::cont::internal::Buffer* buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
VTKM_CONT static WritePortalType CreateWritePortal(
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{
VTKM_ASSERT(buffers.size() == 1);
vtkm::Id numberOfBits = GetNumberOfValues(buffers);
VTKM_ASSERT((buffers[0].GetNumberOfBytes() * CHAR_BIT) >= numberOfBits);

@ -17,6 +17,8 @@
#include <vtkm/cont/ErrorBadAllocation.h>
#include <vtkm/cont/Token.h>
#include <array>
namespace vtkm
{
namespace internal
@ -199,26 +201,27 @@ struct ArrayHandleCartesianProductTraits
template <typename T, typename ST1, typename ST2, typename ST3>
class Storage<vtkm::Vec<T, 3>, vtkm::cont::StorageTagCartesianProduct<ST1, ST2, ST3>>
{
struct Info
{
std::array<std::size_t, 4> BufferOffset;
};
using Storage1 = vtkm::cont::internal::Storage<T, ST1>;
using Storage2 = vtkm::cont::internal::Storage<T, ST2>;
using Storage3 = vtkm::cont::internal::Storage<T, ST3>;
template <typename Buffs>
VTKM_CONT constexpr static Buffs* Buffers1(Buffs* buffers)
{
return buffers;
}
using Array1 = vtkm::cont::ArrayHandle<T, ST1>;
using Array2 = vtkm::cont::ArrayHandle<T, ST2>;
using Array3 = vtkm::cont::ArrayHandle<T, ST3>;
template <typename Buffs>
VTKM_CONT constexpr static Buffs* Buffers2(Buffs* buffers)
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> GetBuffers(
const std::vector<vtkm::cont::internal::Buffer>& buffers,
std::size_t subArray)
{
return buffers + Storage1::GetNumberOfBuffers();
}
template <typename Buffs>
VTKM_CONT constexpr static Buffs* Buffers3(Buffs* buffers)
{
return buffers + Storage1::GetNumberOfBuffers() + Storage2::GetNumberOfBuffers();
Info info = buffers[0].GetMetaData<Info>();
return std::vector<vtkm::cont::internal::Buffer>(buffers.begin() +
info.BufferOffset[subArray - 1],
buffers.begin() + info.BufferOffset[subArray]);
}
public:
@ -235,20 +238,15 @@ public:
typename Storage2::WritePortalType,
typename Storage3::WritePortalType>;
VTKM_CONT constexpr static vtkm::IdComponent GetNumberOfBuffers()
VTKM_CONT static vtkm::Id GetNumberOfValues(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return Storage1::GetNumberOfBuffers() + Storage2::GetNumberOfBuffers() +
Storage3::GetNumberOfBuffers();
return (Storage1::GetNumberOfValues(GetBuffers(buffers, 1)) *
Storage2::GetNumberOfValues(GetBuffers(buffers, 2)) *
Storage3::GetNumberOfValues(GetBuffers(buffers, 3)));
}
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers)
{
return (Storage1::GetNumberOfValues(Buffers1(buffers)) *
Storage2::GetNumberOfValues(Buffers2(buffers)) *
Storage3::GetNumberOfValues(Buffers3(buffers)));
}
VTKM_CONT static void Fill(vtkm::cont::internal::Buffer* buffers,
VTKM_CONT static void Fill(const std::vector<vtkm::cont::internal::Buffer>& buffers,
const vtkm::Vec<T, 3>& fillValue,
vtkm::Id startIndex,
vtkm::Id endIndex,
@ -259,46 +257,63 @@ public:
throw vtkm::cont::ErrorBadValue(
"Fill for ArrayHandleCartesianProduct can only be used to fill entire array.");
}
Storage1::Fill(
Buffers1(buffers), fillValue[0], 0, Storage1::GetNumberOfValues(Buffers1(buffers)), token);
Storage2::Fill(
Buffers2(buffers), fillValue[1], 0, Storage2::GetNumberOfValues(Buffers2(buffers)), token);
Storage3::Fill(
Buffers3(buffers), fillValue[2], 0, Storage3::GetNumberOfValues(Buffers3(buffers)), token);
auto subBuffers = GetBuffers(buffers, 1);
Storage1::Fill(subBuffers, fillValue[0], 0, Storage1::GetNumberOfValues(subBuffers), token);
subBuffers = GetBuffers(buffers, 2);
Storage2::Fill(subBuffers, fillValue[1], 0, Storage2::GetNumberOfValues(subBuffers), token);
subBuffers = GetBuffers(buffers, 3);
Storage3::Fill(subBuffers, fillValue[2], 0, Storage3::GetNumberOfValues(subBuffers), token);
}
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
VTKM_CONT static ReadPortalType CreateReadPortal(
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{
return ReadPortalType(Storage1::CreateReadPortal(Buffers1(buffers), device, token),
Storage2::CreateReadPortal(Buffers2(buffers), device, token),
Storage3::CreateReadPortal(Buffers3(buffers), device, token));
return ReadPortalType(Storage1::CreateReadPortal(GetBuffers(buffers, 1), device, token),
Storage2::CreateReadPortal(GetBuffers(buffers, 2), device, token),
Storage3::CreateReadPortal(GetBuffers(buffers, 3), device, token));
}
VTKM_CONT static WritePortalType CreateWritePortal(vtkm::cont::internal::Buffer* buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
VTKM_CONT static WritePortalType CreateWritePortal(
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{
return WritePortalType(Storage1::CreateWritePortal(Buffers1(buffers), device, token),
Storage2::CreateWritePortal(Buffers2(buffers), device, token),
Storage3::CreateWritePortal(Buffers3(buffers), device, token));
return WritePortalType(Storage1::CreateWritePortal(GetBuffers(buffers, 1), device, token),
Storage2::CreateWritePortal(GetBuffers(buffers, 2), device, token),
Storage3::CreateWritePortal(GetBuffers(buffers, 3), device, token));
}
VTKM_CONT static vtkm::cont::ArrayHandle<T, ST1> GetArrayHandle1(
const vtkm::cont::internal::Buffer* buffers)
VTKM_CONT static Array1 GetArrayHandle1(const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return vtkm::cont::ArrayHandle<T, ST1>(Buffers1(buffers));
return Array1(GetBuffers(buffers, 1));
}
VTKM_CONT static vtkm::cont::ArrayHandle<T, ST2> GetArrayHandle2(
const vtkm::cont::internal::Buffer* buffers)
VTKM_CONT static Array2 GetArrayHandle2(const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return vtkm::cont::ArrayHandle<T, ST2>(Buffers2(buffers));
return Array2(GetBuffers(buffers, 2));
}
VTKM_CONT static vtkm::cont::ArrayHandle<T, ST3> GetArrayHandle3(
const vtkm::cont::internal::Buffer* buffers)
VTKM_CONT static Array3 GetArrayHandle3(const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return vtkm::cont::ArrayHandle<T, ST3>(Buffers3(buffers));
return Array3(GetBuffers(buffers, 3));
}
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers(
const Array1& array1 = Array1{},
const Array2& array2 = Array2{},
const Array3& array3 = Array3{})
{
const std::vector<vtkm::cont::internal::Buffer>& buffers1 = array1.GetBuffers();
const std::vector<vtkm::cont::internal::Buffer>& buffers2 = array2.GetBuffers();
const std::vector<vtkm::cont::internal::Buffer>& buffers3 = array3.GetBuffers();
Info info;
info.BufferOffset[0] = 1;
info.BufferOffset[1] = info.BufferOffset[0] + buffers1.size();
info.BufferOffset[2] = info.BufferOffset[1] + buffers2.size();
info.BufferOffset[3] = info.BufferOffset[2] + buffers3.size();
return vtkm::cont::internal::CreateBuffers(info, buffers1, buffers2, buffers3);
}
};
} // namespace internal
@ -335,7 +350,7 @@ public:
ArrayHandleCartesianProduct(const FirstHandleType& firstArray,
const SecondHandleType& secondArray,
const ThirdHandleType& thirdArray)
: Superclass(vtkm::cont::internal::CreateBuffers(firstArray, secondArray, thirdArray))
: Superclass(StorageType::CreateBuffers(firstArray, secondArray, thirdArray))
{
}

@ -20,6 +20,7 @@
#include <vtkmstd/integer_sequence.h>
#include <numeric>
#include <type_traits>
namespace vtkm
@ -169,31 +170,6 @@ struct VerifyArrayHandle
"must be a list of ArrayHandle types.");
};
template <std::size_t I>
struct BufferIndexImpl
{
template <typename... Ts>
static constexpr vtkm::IdComponent Value(vtkm::IdComponent n, Ts... remaining)
{
return n + BufferIndexImpl<I - 1>::Value(remaining...);
}
};
template <>
struct BufferIndexImpl<0>
{
template <typename... Ts>
static constexpr vtkm::IdComponent Value(Ts...)
{
return 0;
}
};
template <std::size_t I, typename... StorageTypes>
constexpr vtkm::IdComponent BufferIndex()
{
return BufferIndexImpl<I>::Value(StorageTypes::GetNumberOfBuffers()...);
}
} // end namespace compvec
} // namespace internal
@ -226,21 +202,31 @@ class Storage<vtkm::Vec<T, static_cast<vtkm::IdComponent>(sizeof...(StorageTags)
{
using ValueType = vtkm::Vec<T, static_cast<vtkm::IdComponent>(sizeof...(StorageTags))>;
struct Info
{
std::array<std::size_t, sizeof...(StorageTags) + 1> BufferOffset;
};
template <typename S>
using StorageFor = vtkm::cont::internal::Storage<T, S>;
using StorageTuple = vtkm::Tuple<StorageFor<StorageTags>...>;
template <std::size_t I>
VTKM_CONT static constexpr vtkm::IdComponent BufferIndex()
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> GetBuffers(
const std::vector<vtkm::cont::internal::Buffer>& buffers,
std::size_t subArray)
{
return compvec::BufferIndex<I, StorageFor<StorageTags>...>();
Info info = buffers[0].GetMetaData<Info>();
return std::vector<vtkm::cont::internal::Buffer>(buffers.begin() + info.BufferOffset[subArray],
buffers.begin() +
info.BufferOffset[subArray + 1]);
}
template <std::size_t I, typename Buff>
VTKM_CONT static Buff* Buffers(Buff* buffers)
template <std::size_t I>
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> Buffers(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return buffers + BufferIndex<I>();
return GetBuffers(buffers, I);
}
using IndexList = vtkmstd::make_index_sequence<sizeof...(StorageTags)>;
@ -255,19 +241,21 @@ private:
template <std::size_t... Is>
static void ResizeBuffersImpl(vtkmstd::index_sequence<Is...>,
vtkm::Id numValues,
vtkm::cont::internal::Buffer* buffers,
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::CopyFlag preserve,
vtkm::cont::Token& token)
{
std::vector<std::vector<vtkm::cont::internal::Buffer>> bufferPartitions = { Buffers<Is>(
buffers)... };
auto init_list = { (vtkm::tuple_element_t<Is, StorageTuple>::ResizeBuffers(
numValues, Buffers<Is>(buffers), preserve, token),
numValues, bufferPartitions[Is], preserve, token),
false)... };
(void)init_list;
}
template <std::size_t... Is>
static void FillImpl(vtkmstd::index_sequence<Is...>,
vtkm::cont::internal::Buffer* buffers,
const std::vector<vtkm::cont::internal::Buffer>& buffers,
const ValueType& fillValue,
vtkm::Id startIndex,
vtkm::Id endIndex,
@ -284,45 +272,43 @@ private:
}
template <std::size_t... Is>
static ReadPortalType CreateReadPortalImpl(vtkmstd::index_sequence<Is...>,
const vtkm::cont::internal::Buffer* buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
static ReadPortalType CreateReadPortalImpl(
vtkmstd::index_sequence<Is...>,
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{
return ReadPortalType(vtkm::tuple_element_t<Is, StorageTuple>::CreateReadPortal(
Buffers<Is>(buffers), device, token)...);
}
template <std::size_t... Is>
static WritePortalType CreateWritePortalImpl(vtkmstd::index_sequence<Is...>,
vtkm::cont::internal::Buffer* buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
static WritePortalType CreateWritePortalImpl(
vtkmstd::index_sequence<Is...>,
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{
return WritePortalType(vtkm::tuple_element_t<Is, StorageTuple>::CreateWritePortal(
Buffers<Is>(buffers), device, token)...);
}
public:
VTKM_CONT constexpr static vtkm::IdComponent GetNumberOfBuffers()
VTKM_CONT static vtkm::Id GetNumberOfValues(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return BufferIndex<sizeof...(StorageTags)>();
}
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers)
{
return vtkm::TupleElement<0, StorageTuple>::GetNumberOfValues(buffers);
return vtkm::TupleElement<0, StorageTuple>::GetNumberOfValues(Buffers<0>(buffers));
}
VTKM_CONT static void ResizeBuffers(vtkm::Id numValues,
vtkm::cont::internal::Buffer* buffers,
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::CopyFlag preserve,
vtkm::cont::Token& token)
{
ResizeBuffersImpl(IndexList{}, numValues, buffers, preserve, token);
}
VTKM_CONT static void Fill(vtkm::cont::internal::Buffer* buffers,
VTKM_CONT static void Fill(const std::vector<vtkm::cont::internal::Buffer>& buffers,
const ValueType& fillValue,
vtkm::Id startIndex,
vtkm::Id endIndex,
@ -331,65 +317,51 @@ public:
FillImpl(IndexList{}, buffers, fillValue, startIndex, endIndex, token);
}
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
VTKM_CONT static ReadPortalType CreateReadPortal(
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{
return CreateReadPortalImpl(IndexList{}, buffers, device, token);
}
VTKM_CONT static WritePortalType CreateWritePortal(vtkm::cont::internal::Buffer* buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
VTKM_CONT static WritePortalType CreateWritePortal(
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{
return CreateWritePortalImpl(IndexList{}, buffers, device, token);
}
private:
template <typename ArrayType>
VTKM_CONT static bool CopyBuffers(const ArrayType& array,
vtkm::cont::internal::Buffer* destBuffers)
{
vtkm::IdComponent numBuffers = array.GetNumberOfBuffers();
const vtkm::cont::internal::Buffer* srcBuffers = array.GetBuffers();
for (vtkm::IdComponent buffIndex = 0; buffIndex < numBuffers; ++buffIndex)
{
destBuffers[buffIndex] = srcBuffers[buffIndex];
}
return false; // Return value does not matter. Hopefully just thrown away by compiler.
}
template <std::size_t... Is, typename... ArrayTs>
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffersImpl(
vtkmstd::index_sequence<Is...>,
const ArrayTs... arrays)
{
std::vector<vtkm::cont::internal::Buffer> buffers(
static_cast<std::size_t>(GetNumberOfBuffers()));
auto init_list = { CopyBuffers(arrays, Buffers<Is>(&buffers.front()))... };
(void)init_list;
return buffers;
}
public:
template <typename... ArrayTs>
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers(const ArrayTs... arrays)
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers(
const vtkm::cont::ArrayHandle<T, StorageTags>&... arrays)
{
return CreateBuffersImpl(IndexList{}, arrays...);
auto numBuffers = { std::size_t{ 1 }, arrays.GetBuffers().size()... };
Info info;
std::partial_sum(numBuffers.begin(), numBuffers.end(), info.BufferOffset.begin());
return vtkm::cont::internal::CreateBuffers(info, arrays...);
}
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers()
{
return CreateBuffers(vtkm::cont::ArrayHandle<T, StorageTags>{}...);
}
private:
using ArrayTupleType = vtkm::Tuple<vtkm::cont::ArrayHandle<T, StorageTags>...>;
template <std::size_t... Is>
VTKM_CONT static ArrayTupleType GetArrayTupleImpl(vtkmstd::index_sequence<Is...>,
const vtkm::cont::internal::Buffer* buffers)
VTKM_CONT static ArrayTupleType GetArrayTupleImpl(
vtkmstd::index_sequence<Is...>,
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return ArrayTupleType(vtkm::cont::ArrayHandle<T, StorageTags>(Buffers<Is>(buffers))...);
}
public:
VTKM_CONT static ArrayTupleType GetArrayTuple(const vtkm::cont::internal::Buffer* buffers)
VTKM_CONT static ArrayTupleType GetArrayTuple(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return GetArrayTupleImpl(IndexList{}, buffers);
}
@ -400,13 +372,13 @@ template <typename T, typename StorageTag>
struct Storage<T, vtkm::cont::StorageTagCompositeVec<StorageTag>> : Storage<T, StorageTag>
{
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers(
const vtkm::cont::ArrayHandle<T, StorageTag>& array)
const vtkm::cont::ArrayHandle<T, StorageTag>& array = vtkm::cont::ArrayHandle<T, StorageTag>{})
{
return vtkm::cont::internal::CreateBuffers(array);
}
VTKM_CONT static vtkm::Tuple<vtkm::cont::ArrayHandle<T, StorageTag>> GetArrayTuple(
const vtkm::cont::internal::Buffer* buffers)
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return vtkm::cont::ArrayHandle<T, StorageTag>(buffers);
}

@ -169,16 +169,26 @@ class Storage<T, StorageTagConcatenate<ST1, ST2>>
using ArrayHandleType1 = typename detail::ConcatinateTypeArg<T, ST1>::ArrayHandle;
using ArrayHandleType2 = typename detail::ConcatinateTypeArg<T, ST2>::ArrayHandle;
template <typename Buff>
VTKM_CONT static Buff* Buffers1(Buff* buffers)
struct Info
{
return buffers;
std::size_t NumBuffers1;
std::size_t NumBuffers2;
};
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> Buffers1(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
Info info = buffers[0].GetMetaData<Info>();
return std::vector<vtkm::cont::internal::Buffer>(buffers.begin() + 1,
buffers.begin() + 1 + info.NumBuffers1);
}
template <typename Buff>
VTKM_CONT static Buff* Buffers2(Buff* buffers)
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> Buffers2(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return buffers + SourceStorage1::GetNumberOfBuffers();
Info info = buffers[0].GetMetaData<Info>();
return std::vector<vtkm::cont::internal::Buffer>(buffers.begin() + 1 + info.NumBuffers1,
buffers.end());
}
public:
@ -191,18 +201,14 @@ public:
vtkm::internal::ArrayPortalConcatenate<typename SourceStorage1::WritePortalType,
typename SourceStorage2::WritePortalType>;
VTKM_CONT static constexpr vtkm::IdComponent GetNumberOfBuffers()
{
return (SourceStorage1::GetNumberOfBuffers() + SourceStorage2::GetNumberOfBuffers());
}
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers)
VTKM_CONT static vtkm::Id GetNumberOfValues(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return (SourceStorage1::GetNumberOfValues(Buffers1(buffers)) +
SourceStorage2::GetNumberOfValues(Buffers2(buffers)));
}
VTKM_CONT static void Fill(vtkm::cont::internal::Buffer* buffers,
VTKM_CONT static void Fill(const std::vector<vtkm::cont::internal::Buffer>& buffers,
const T& fillValue,
vtkm::Id startIndex,
vtkm::Id endIndex,
@ -225,35 +231,42 @@ public:
}
}
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
VTKM_CONT static ReadPortalType CreateReadPortal(
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{
return ReadPortalType(SourceStorage1::CreateReadPortal(Buffers1(buffers), device, token),
SourceStorage2::CreateReadPortal(Buffers2(buffers), device, token));
}
VTKM_CONT static WritePortalType CreateWritePortal(vtkm::cont::internal::Buffer* buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
VTKM_CONT static WritePortalType CreateWritePortal(
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{
return WritePortalType(SourceStorage1::CreateWritePortal(Buffers1(buffers), device, token),
SourceStorage2::CreateWritePortal(Buffers2(buffers), device, token));
}
VTKM_CONT static auto CreateBuffers(const ArrayHandleType1& array1,
const ArrayHandleType2& array2)
VTKM_CONT static auto CreateBuffers(const ArrayHandleType1& array1 = ArrayHandleType1{},
const ArrayHandleType2& array2 = ArrayHandleType2{})
-> decltype(vtkm::cont::internal::CreateBuffers())
{
return vtkm::cont::internal::CreateBuffers(array1, array2);
Info info;
info.NumBuffers1 = array1.GetBuffers().size();
info.NumBuffers2 = array2.GetBuffers().size();
return vtkm::cont::internal::CreateBuffers(info, array1, array2);
}
VTKM_CONT static const ArrayHandleType1 GetArray1(const vtkm::cont::internal::Buffer* buffers)
VTKM_CONT static const ArrayHandleType1 GetArray1(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return ArrayHandleType1(Buffers1(buffers));
}
VTKM_CONT static const ArrayHandleType2 GetArray2(const vtkm::cont::internal::Buffer* buffers)
VTKM_CONT static const ArrayHandleType2 GetArray2(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return ArrayHandleType2(Buffers2(buffers));
}

@ -24,6 +24,7 @@
#include <vtkmstd/integer_sequence.h>
#include <numeric>
#include <type_traits>
#include <utility>
@ -306,35 +307,22 @@ using GetWritePortalList =
std::declval<vtkm::cont::DeviceAdapterId>(),
std::declval<vtkm::cont::Token&>())))...>;
template <vtkm::IdComponent I, typename ArrayTupleType>
struct BufferIndexImpl
{
static constexpr vtkm::IdComponent Value()
{
return BufferIndexImpl<I - 1, ArrayTupleType>::Value() +
vtkm::TupleElement<I - 1, ArrayTupleType>::GetNumberOfBuffers();
}
};
template <typename ArrayTupleType>
struct BufferIndexImpl<0, ArrayTupleType>
{
static constexpr vtkm::IdComponent Value()
{
// One buffer reserved for metadata.
return 1;
}
};
template <typename DecoratorImplT>
template <typename DecoratorImplT, std::size_t NumArrays>
struct DecoratorMetaData
{
DecoratorImplT Implementation;
vtkm::Id NumberOfValues = 0;
std::array<std::size_t, NumArrays + 1> BufferOffsets;
DecoratorMetaData(const DecoratorImplT& implementation, vtkm::Id numValues)
template <typename... ArrayTs>
DecoratorMetaData(const DecoratorImplT& implementation,
vtkm::Id numValues,
const ArrayTs... arrays)
: Implementation(implementation)
, NumberOfValues(numValues)
{
auto numBuffers = { std::size_t{ 1 }, arrays.GetBuffers().size()... };
std::partial_sum(numBuffers.begin(), numBuffers.end(), this->BufferOffsets.begin());
}
DecoratorMetaData() = default;
@ -363,26 +351,22 @@ struct DecoratorStorageTraits
// size_t integral constants that index ArrayTs:
using IndexList = vtkmstd::make_index_sequence<sizeof...(ArrayTs)>;
// Returns the index into the buffers array for the array at the given index.
template <vtkm::IdComponent I>
static constexpr vtkm::IdComponent BufferIndex()
using MetaData = DecoratorMetaData<DecoratorImplT, sizeof...(ArrayTs)>;
static MetaData& GetMetaData(const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return BufferIndexImpl<I, ArrayTupleType>::Value();
return buffers[0].GetMetaData<MetaData>();
}
// Converts a buffers array to the ArrayHandle at the given index.
template <vtkm::IdComponent I>
static vtkm::TupleElement<I, ArrayTupleType> BuffersToArray(
const vtkm::cont::internal::Buffer* buffers)
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return vtkm::TupleElement<I, ArrayTupleType>(buffers + BufferIndex<I>());
}
using MetaData = DecoratorMetaData<DecoratorImplT>;
static MetaData& GetMetaData(const vtkm::cont::internal::Buffer* buffers)
{
return buffers[0].GetMetaData<MetaData>();
const MetaData& metaData = GetMetaData(buffers);
std::vector<vtkm::cont::internal::Buffer> subBuffers(
buffers.begin() + metaData.BufferOffsets[I], buffers.begin() + metaData.BufferOffsets[I + 1]);
return vtkm::TupleElement<I, ArrayTupleType>(std::move(subBuffers));
}
// true_type/false_type depending on whether the decorator supports Allocate:
@ -440,7 +424,7 @@ struct DecoratorStorageTraits
// Static dispatch for calling AllocateSourceArrays on supported implementations:
VTKM_CONT [[noreturn]] static void CallAllocate(std::false_type,
vtkm::Id,
vtkm::cont::internal::Buffer*,
const std::vector<vtkm::cont::internal::Buffer>&,
vtkm::CopyFlag,
vtkm::cont::Token&,
ArrayTs...)
@ -450,7 +434,7 @@ struct DecoratorStorageTraits
VTKM_CONT static void CallAllocate(std::true_type,
vtkm::Id newSize,
vtkm::cont::internal::Buffer* buffers,
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::CopyFlag preserve,
vtkm::cont::Token& token,
ArrayTs... arrays)
@ -463,11 +447,12 @@ struct DecoratorStorageTraits
// Portal construction methods. These actually create portals.
template <std::size_t... Indices>
VTKM_CONT static WritePortalType CreateWritePortal(const vtkm::cont::internal::Buffer* buffers,
vtkm::Id numValues,
vtkmstd::index_sequence<Indices...>,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
VTKM_CONT static WritePortalType CreateWritePortal(
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::Id numValues,
vtkmstd::index_sequence<Indices...>,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{
return CreatePortalDecorator<WritePortalType>(
numValues,
@ -476,11 +461,12 @@ struct DecoratorStorageTraits
}
template <std::size_t... Indices>
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers,
vtkm::Id numValues,
vtkmstd::index_sequence<Indices...>,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
VTKM_CONT static ReadPortalType CreateReadPortal(
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::Id numValues,
vtkmstd::index_sequence<Indices...>,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{
return CreatePortalDecorator<ReadPortalType>(
numValues,
@ -489,11 +475,12 @@ struct DecoratorStorageTraits
}
template <std::size_t... Indices>
VTKM_CONT static void AllocateSourceArrays(vtkm::Id numValues,
vtkm::cont::internal::Buffer* buffers,
vtkm::CopyFlag preserve,
vtkm::cont::Token& token,
vtkmstd::index_sequence<Indices...>)
VTKM_CONT static void AllocateSourceArrays(
vtkm::Id numValues,
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::CopyFlag preserve,
vtkm::cont::Token& token,
vtkmstd::index_sequence<Indices...>)
{
CallAllocate(
IsAllocatable{}, numValues, buffers, preserve, token, BuffersToArray<Indices>(buffers)...);
@ -519,18 +506,14 @@ public:
using ReadPortalType = typename Traits::ReadPortalType;
using WritePortalType = typename Traits::WritePortalType;
VTKM_CONT constexpr static vtkm::IdComponent GetNumberOfBuffers()
{
return Traits::template BufferIndex<static_cast<vtkm::IdComponent>(sizeof...(ArrayTs))>();
}
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers)
VTKM_CONT static vtkm::Id GetNumberOfValues(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return Traits::GetMetaData(buffers).NumberOfValues;
}
VTKM_CONT static void ResizeBuffers(vtkm::Id numValues,
vtkm::cont::internal::Buffer* buffers,
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::CopyFlag preserve,
vtkm::cont::Token& token)
{
@ -545,17 +528,19 @@ public:
}
}
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
VTKM_CONT static ReadPortalType CreateReadPortal(
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{
return Traits::CreateReadPortal(
buffers, GetNumberOfValues(buffers), IndexList{}, device, token);
}
VTKM_CONT static WritePortalType CreateWritePortal(vtkm::cont::internal::Buffer* buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
VTKM_CONT static WritePortalType CreateWritePortal(
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{
return Traits::CreateWritePortal(
buffers, GetNumberOfValues(buffers), IndexList{}, device, token);
@ -564,7 +549,13 @@ public:
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer>
CreateBuffers(const DecoratorImplT& implementation, vtkm::Id numValues, const ArrayTs&... arrays)
{
return vtkm::cont::internal::CreateBuffers(MetaData(implementation, numValues), arrays...);
return vtkm::cont::internal::CreateBuffers(MetaData(implementation, numValues, arrays...),
arrays...);
}
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers()
{
return CreateBuffers(DecoratorImplT{}, 0, ArrayTs{}...);
}
};

@ -103,10 +103,15 @@ public:
// you actually try to use this read portal.
using ReadPortalType = vtkm::exec::internal::ArrayPortalDiscard<ValueType>;
VTKM_CONT constexpr static vtkm::IdComponent GetNumberOfBuffers() { return 1; }
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers()
{
DiscardMetaData metaData;
metaData.NumberOfValues = 0;
return vtkm::cont::internal::CreateBuffers(metaData);
}
VTKM_CONT static void ResizeBuffers(vtkm::Id numValues,
vtkm::cont::internal::Buffer* buffers,
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::CopyFlag,
vtkm::cont::Token&)
{
@ -114,12 +119,13 @@ public:
buffers[0].GetMetaData<DiscardMetaData>().NumberOfValues = numValues;
}
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers)
VTKM_CONT static vtkm::Id GetNumberOfValues(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return buffers[0].GetMetaData<DiscardMetaData>().NumberOfValues;
}
VTKM_CONT static void Fill(vtkm::cont::internal::Buffer*,
VTKM_CONT static void Fill(const std::vector<vtkm::cont::internal::Buffer>&,
const ValueType&,
vtkm::Id,
vtkm::Id,
@ -128,16 +134,17 @@ public:
// Fill is a NO-OP.
}
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer*,
VTKM_CONT static ReadPortalType CreateReadPortal(const std::vector<vtkm::cont::internal::Buffer>&,
vtkm::cont::DeviceAdapterId,
vtkm::cont::Token&)
{
throw vtkm::cont::ErrorBadValue("Cannot read from ArrayHandleDiscard.");
}
VTKM_CONT static WritePortalType CreateWritePortal(vtkm::cont::internal::Buffer* buffers,
vtkm::cont::DeviceAdapterId,
vtkm::cont::Token&)
VTKM_CONT static WritePortalType CreateWritePortal(
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::DeviceAdapterId,
vtkm::cont::Token&)
{
return WritePortalType(GetNumberOfValues(buffers));
}

@ -44,13 +44,8 @@ public:
{
}
// Copy constructor
VTKM_EXEC_CONT ArrayPortalExtractComponent(const ArrayPortalExtractComponent<PortalType>& src)
: Portal(src.Portal)
, Component(src.Component)
{
}
ArrayPortalExtractComponent(const ArrayPortalExtractComponent&) = default;
ArrayPortalExtractComponent(ArrayPortalExtractComponent&&) = default;
ArrayPortalExtractComponent& operator=(const ArrayPortalExtractComponent&) = default;
ArrayPortalExtractComponent& operator=(ArrayPortalExtractComponent&&) = default;
@ -103,15 +98,16 @@ class Storage<typename vtkm::VecTraits<typename ArrayHandleType::ValueType>::Com
using SourceStorage = vtkm::cont::internal::Storage<SourceValueType, SourceStorageTag>;
public:
VTKM_CONT static vtkm::IdComponent ComponentIndex(const vtkm::cont::internal::Buffer* buffers)
VTKM_CONT static vtkm::IdComponent ComponentIndex(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return buffers[0].GetMetaData<vtkm::IdComponent>();
}
template <typename Buff>
VTKM_CONT static Buff* SourceBuffers(Buff* buffers)
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> SourceBuffers(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return buffers + 1;
return std::vector<vtkm::cont::internal::Buffer>(buffers.begin() + 1, buffers.end());
}
using ReadPortalType =
@ -119,17 +115,13 @@ public:
using WritePortalType =
vtkm::internal::ArrayPortalExtractComponent<typename SourceStorage::WritePortalType>;
VTKM_CONT constexpr static vtkm::IdComponent GetNumberOfBuffers()
{
return SourceStorage::GetNumberOfBuffers() + 1;
}
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers)
VTKM_CONT static vtkm::Id GetNumberOfValues(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return SourceStorage::GetNumberOfValues(SourceBuffers(buffers));
}
VTKM_CONT static void Fill(vtkm::cont::internal::Buffer*,
VTKM_CONT static void Fill(const std::vector<vtkm::cont::internal::Buffer>&,
const ValueType&,
vtkm::Id,
vtkm::Id,
@ -139,31 +131,33 @@ public:
}
VTKM_CONT static void ResizeBuffers(vtkm::Id numValues,
vtkm::cont::internal::Buffer* buffers,
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::CopyFlag preserve,
vtkm::cont::Token& token)
{
SourceStorage::ResizeBuffers(numValues, SourceBuffers(buffers), preserve, token);
}
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
VTKM_CONT static ReadPortalType CreateReadPortal(
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{
return ReadPortalType(SourceStorage::CreateReadPortal(SourceBuffers(buffers), device, token),
ComponentIndex(buffers));
}
VTKM_CONT static WritePortalType CreateWritePortal(vtkm::cont::internal::Buffer* buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
VTKM_CONT static WritePortalType CreateWritePortal(
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{
return WritePortalType(SourceStorage::CreateWritePortal(SourceBuffers(buffers), device, token),
ComponentIndex(buffers));
}
VTKM_CONT static auto CreateBuffers(vtkm::IdComponent componentIndex,
const ArrayHandleType& array)
VTKM_CONT static auto CreateBuffers(vtkm::IdComponent componentIndex = 0,
const ArrayHandleType& array = ArrayHandleType{})
-> decltype(vtkm::cont::internal::CreateBuffers())
{
return vtkm::cont::internal::CreateBuffers(componentIndex, array);

@ -128,26 +128,27 @@ public:
vtkm::internal::ArrayPortalGroupVec<typename ComponentsStorage::WritePortalType,
NUM_COMPONENTS>;
VTKM_CONT constexpr static vtkm::IdComponent GetNumberOfBuffers()
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers()
{
return ComponentsStorage::GetNumberOfBuffers();
return ComponentsStorage::CreateBuffers();
}
VTKM_CONT static void ResizeBuffers(vtkm::Id numValues,
vtkm::cont::internal::Buffer* buffers,
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::CopyFlag preserve,
vtkm::cont::Token& token)
{
ComponentsStorage::ResizeBuffers(NUM_COMPONENTS * numValues, buffers, preserve, token);
}
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers)
VTKM_CONT static vtkm::Id GetNumberOfValues(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
vtkm::Id componentsSize = ComponentsStorage::GetNumberOfValues(buffers);
return componentsSize / NUM_COMPONENTS;
}
VTKM_CONT static void Fill(vtkm::cont::internal::Buffer*,
VTKM_CONT static void Fill(const std::vector<vtkm::cont::internal::Buffer>&,
const ValueType&,
vtkm::Id,
vtkm::Id,
@ -156,9 +157,10 @@ public:
throw vtkm::cont::ErrorBadType("Fill not supported for ArrayHandleGroupVec.");
}
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
VTKM_CONT static ReadPortalType CreateReadPortal(
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{
if ((ComponentsStorage::GetNumberOfValues(buffers) % NUM_COMPONENTS) != 0)
{
@ -168,9 +170,10 @@ public:
return ReadPortalType(ComponentsStorage::CreateReadPortal(buffers, device, token));
}
VTKM_CONT static WritePortalType CreateWritePortal(vtkm::cont::internal::Buffer* buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
VTKM_CONT static WritePortalType CreateWritePortal(
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{
if ((ComponentsStorage::GetNumberOfValues(buffers) % NUM_COMPONENTS) != 0)
{

@ -122,20 +122,32 @@ class Storage<vtkm::VecFromPortal<ComponentsPortal>,
using ComponentsStorage = vtkm::cont::internal::Storage<ComponentType, ComponentsStorageTag>;
using OffsetsStorage = vtkm::cont::internal::Storage<vtkm::Id, OffsetsStorageTag>;
using ComponentsArray = vtkm::cont::ArrayHandle<ComponentType, ComponentsStorageTag>;
using OffsetsArray = vtkm::cont::ArrayHandle<vtkm::Id, OffsetsStorageTag>;
VTKM_STATIC_ASSERT_MSG(
(std::is_same<ComponentsPortal, typename ComponentsStorage::WritePortalType>::value),
"Used invalid ComponentsPortal type with expected ComponentsStorageTag.");
template <typename Buff>
VTKM_CONT static Buff* ComponentsBuffers(Buff* buffers)
struct Info
{
return buffers;
std::size_t OffsetsBuffersOffset;
};
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> ComponentsBuffers(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
Info info = buffers[0].GetMetaData<Info>();
return std::vector<vtkm::cont::internal::Buffer>(buffers.begin() + 1,
buffers.begin() + info.OffsetsBuffersOffset);
}
template <typename Buff>
VTKM_CONT static Buff* OffsetsBuffers(Buff* buffers)
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> OffsetsBuffers(
const std::vector<vtkm::cont::internal::Buffer> buffers)
{
return buffers + ComponentsStorage::GetNumberOfBuffers();
Info info = buffers[0].GetMetaData<Info>();
return std::vector<vtkm::cont::internal::Buffer>(buffers.begin() + info.OffsetsBuffersOffset,
buffers.end());
}
public:
@ -148,17 +160,13 @@ public:
vtkm::internal::ArrayPortalGroupVecVariable<typename ComponentsStorage::WritePortalType,
typename OffsetsStorage::ReadPortalType>;
VTKM_CONT static vtkm::IdComponent GetNumberOfBuffers()
{
return ComponentsStorage::GetNumberOfBuffers() + OffsetsStorage::GetNumberOfBuffers();
}
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers)
VTKM_CONT static vtkm::Id GetNumberOfValues(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return OffsetsStorage::GetNumberOfValues(OffsetsBuffers(buffers)) - 1;
}
VTKM_CONT static void Fill(vtkm::cont::internal::Buffer*,
VTKM_CONT static void Fill(const std::vector<vtkm::cont::internal::Buffer>&,
const vtkm::VecFromPortal<ComponentsPortal>&,
vtkm::Id,
vtkm::Id,
@ -167,18 +175,20 @@ public:
throw vtkm::cont::ErrorBadType("Fill not supported for ArrayHandleGroupVecVariable.");
}
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
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),
OffsetsStorage::CreateReadPortal(OffsetsBuffers(buffers), device, token));
}
VTKM_CONT static WritePortalType CreateWritePortal(vtkm::cont::internal::Buffer* buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
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),
@ -186,31 +196,24 @@ public:
}
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers(
const vtkm::cont::ArrayHandle<ComponentType, ComponentsStorageTag>& componentsArray,
const vtkm::cont::ArrayHandle<vtkm::Id, OffsetsStorageTag>& offsetsArray)
const ComponentsArray& componentsArray = ComponentsArray{},
const OffsetsArray& offsetsArray = OffsetsArray{})
{
std::vector<vtkm::cont::internal::Buffer> destBuffer(
static_cast<std::size_t>(GetNumberOfBuffers()));
auto destIter = destBuffer.begin();
destIter =
std::copy_n(componentsArray.GetBuffers(), ComponentsStorage::GetNumberOfBuffers(), destIter);
destIter =
std::copy_n(offsetsArray.GetBuffers(), OffsetsStorage::GetNumberOfBuffers(), destIter);
return destBuffer;
Info info;
info.OffsetsBuffersOffset = 1 + componentsArray.GetBuffers().size();
return vtkm::cont::internal::CreateBuffers(info, componentsArray, offsetsArray);
}
VTKM_CONT static vtkm::cont::ArrayHandle<ComponentType, ComponentsStorageTag> GetComponentsArray(
const vtkm::cont::internal::Buffer* buffers)
VTKM_CONT static ComponentsArray GetComponentsArray(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return vtkm::cont::ArrayHandle<ComponentType, ComponentsStorageTag>(ComponentsBuffers(buffers));
return ComponentsArray(ComponentsBuffers(buffers));
}
VTKM_CONT static vtkm::cont::ArrayHandle<vtkm::Id, OffsetsStorageTag> GetOffsetsArray(
const vtkm::cont::internal::Buffer* buffers)
VTKM_CONT static OffsetsArray GetOffsetsArray(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return vtkm::cont::ArrayHandle<vtkm::Id, OffsetsStorageTag>(OffsetsBuffers(buffers));
return OffsetsArray(OffsetsBuffers(buffers));
}
};

@ -91,34 +91,6 @@ struct VTKM_ALWAYS_EXPORT StorageTagImplicit
namespace internal
{
template <class ArrayPortalType>
struct VTKM_ALWAYS_EXPORT
Storage<typename ArrayPortalType::ValueType, StorageTagImplicit<ArrayPortalType>>
{
VTKM_IS_TRIVIALLY_COPYABLE(ArrayPortalType);
VTKM_STORAGE_NO_RESIZE;
VTKM_STORAGE_NO_WRITE_PORTAL;
using ReadPortalType = ArrayPortalType;
// Implicit array has one buffer that should be empty (NumberOfBytes = 0), but holds
// the metadata for the array.
VTKM_CONT constexpr static vtkm::IdComponent GetNumberOfBuffers() { return 1; }
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers)
{
return buffers[0].GetMetaData<ArrayPortalType>().GetNumberOfValues();
}
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers,
vtkm::cont::DeviceAdapterId,
vtkm::cont::Token&)
{
return buffers[0].GetMetaData<ArrayPortalType>();
}
};
/// Given an array portal, returns the buffers for the `ArrayHandle` with a storage that
/// is (or is compatible with) a storage tag of `StorageTagImplicit<PortalType>`.
template <typename PortalType>
@ -141,6 +113,37 @@ VTKM_CONT inline std::vector<vtkm::cont::internal::Buffer> FunctorToArrayHandleI
vtkm::internal::ArrayPortalImplicit<FunctorType>(functor, numValues));
}
template <class ArrayPortalType>
struct VTKM_ALWAYS_EXPORT
Storage<typename ArrayPortalType::ValueType, StorageTagImplicit<ArrayPortalType>>
{
VTKM_IS_TRIVIALLY_COPYABLE(ArrayPortalType);
VTKM_STORAGE_NO_RESIZE;
VTKM_STORAGE_NO_WRITE_PORTAL;
using ReadPortalType = ArrayPortalType;
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers()
{
return vtkm::cont::internal::PortalToArrayHandleImplicitBuffers(ArrayPortalType{});
}
VTKM_CONT static vtkm::Id GetNumberOfValues(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return buffers[0].GetMetaData<ArrayPortalType>().GetNumberOfValues();
}
VTKM_CONT static ReadPortalType CreateReadPortal(
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::DeviceAdapterId,
vtkm::cont::Token&)
{
return buffers[0].GetMetaData<ArrayPortalType>();
}
};
} // namespace internal
namespace detail

@ -151,7 +151,8 @@ namespace detail
struct MultiplexerGetNumberOfValuesFunctor
{
template <typename StorageType>
VTKM_CONT vtkm::Id operator()(StorageType, const vtkm::cont::internal::Buffer* buffers) const
VTKM_CONT vtkm::Id operator()(StorageType,
const std::vector<vtkm::cont::internal::Buffer>& buffers) const
{
return StorageType::GetNumberOfValues(buffers);
}
@ -162,7 +163,7 @@ struct MultiplexerResizeBuffersFunctor
template <typename StorageType>
VTKM_CONT void operator()(StorageType,
vtkm::Id numValues,
vtkm::cont::internal::Buffer* buffers,
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::CopyFlag preserve,
vtkm::cont::Token& token) const
{
@ -174,7 +175,7 @@ struct MultiplexerFillFunctor
{
template <typename ValueType, typename StorageType>
VTKM_CONT void operator()(StorageType,
vtkm::cont::internal::Buffer* buffers,
const std::vector<vtkm::cont::internal::Buffer>& buffers,
const ValueType& fillValue,
vtkm::Id startIndex,
vtkm::Id endIndex,
@ -189,7 +190,7 @@ struct MultiplexerCreateReadPortalFunctor
{
template <typename StorageType>
VTKM_CONT ReadPortalType operator()(StorageType,
const vtkm::cont::internal::Buffer* buffers,
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token) const
{
@ -202,7 +203,7 @@ struct MultiplexerCreateWritePortalFunctor
{
template <typename StorageType>
VTKM_CONT WritePortalType operator()(StorageType,
vtkm::cont::internal::Buffer* buffers,
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token) const
{
@ -217,7 +218,7 @@ struct MultiplexerArrayHandleVariantFunctor
template <typename StorageTag>
VTKM_CONT VariantType operator()(vtkm::cont::internal::Storage<T, StorageTag>,
const vtkm::cont::internal::Buffer* buffers)
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return VariantType(vtkm::cont::ArrayHandle<T, StorageTag>(buffers));
}
@ -233,15 +234,15 @@ class Storage<ValueType, StorageTagMultiplexer<StorageTags...>>
using StorageVariant = vtkm::cont::internal::Variant<StorageFor<StorageTags>...>;
VTKM_CONT static StorageVariant Variant(const vtkm::cont::internal::Buffer* buffers)
VTKM_CONT static StorageVariant Variant(const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return buffers[0].GetMetaData<StorageVariant>();
}
template <typename Buff>
VTKM_CONT static Buff* ArrayBuffers(Buff* buffers)
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> ArrayBuffers(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return buffers + 1;
return std::vector<vtkm::cont::internal::Buffer>(buffers.begin() + 1, buffers.end());
}
public:
@ -250,19 +251,15 @@ public:
using WritePortalType =
vtkm::internal::ArrayPortalMultiplexer<typename StorageFor<StorageTags>::WritePortalType...>;
VTKM_CONT static constexpr vtkm::IdComponent GetNumberOfBuffers()
{
return std::max({ StorageFor<StorageTags>::GetNumberOfBuffers()... }) + 1;
}
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers)
VTKM_CONT static vtkm::Id GetNumberOfValues(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return Variant(buffers).CastAndCall(detail::MultiplexerGetNumberOfValuesFunctor{},
ArrayBuffers(buffers));
}
VTKM_CONT static void ResizeBuffers(vtkm::Id numValues,
vtkm::cont::internal::Buffer* buffers,
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::CopyFlag preserve,
vtkm::cont::Token& token)
{
@ -270,7 +267,7 @@ public:
detail::MultiplexerResizeBuffersFunctor{}, numValues, ArrayBuffers(buffers), preserve, token);
}
VTKM_CONT static void Fill(vtkm::cont::internal::Buffer* buffers,
VTKM_CONT static void Fill(const std::vector<vtkm::cont::internal::Buffer>& buffers,
const ValueType& fillValue,
vtkm::Id startIndex,
vtkm::Id endIndex,
@ -284,9 +281,10 @@ public:
token);
}
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
VTKM_CONT static ReadPortalType CreateReadPortal(
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{
return Variant(buffers).CastAndCall(
detail::MultiplexerCreateReadPortalFunctor<ReadPortalType>{},
@ -295,9 +293,10 @@ public:
token);
}
VTKM_CONT static WritePortalType CreateWritePortal(vtkm::cont::internal::Buffer* buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
VTKM_CONT static WritePortalType CreateWritePortal(
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{
return Variant(buffers).CastAndCall(
detail::MultiplexerCreateWritePortalFunctor<WritePortalType>{},
@ -306,7 +305,7 @@ public:
token);
}
VTKM_CONT static bool IsValid(const vtkm::cont::internal::Buffer* buffers)
VTKM_CONT static bool IsValid(const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return Variant(buffers).IsValid();
}
@ -315,21 +314,17 @@ public:
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers(const ArrayType& array)
{
VTKM_IS_ARRAY_HANDLE(ArrayType);
std::vector<vtkm::cont::internal::Buffer> buffers =
vtkm::cont::internal::CreateBuffers(StorageVariant{ array.GetStorage() }, array);
return vtkm::cont::internal::CreateBuffers(StorageVariant{ array.GetStorage() }, array);
}
// Some arrays will require different numbers of buffers. Make sure we size the buffers
// array to accomodate any such one to avoid any troubles.
std::size_t numBuffers = static_cast<std::size_t>(GetNumberOfBuffers());
VTKM_ASSERT(numBuffers >= buffers.size());
buffers.resize(numBuffers);
return buffers;
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers()
{
return vtkm::cont::internal::CreateBuffers(StorageVariant{});
}
VTKM_CONT static
typename detail::MultiplexerArrayHandleVariantFunctor<ValueType, StorageTags...>::VariantType
GetArrayHandleVariant(const vtkm::cont::internal::Buffer* buffers)
GetArrayHandleVariant(const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return Variant(buffers).CastAndCall(
detail::MultiplexerArrayHandleVariantFunctor<ValueType, StorageTags...>{},

@ -71,12 +71,13 @@ public:
using ReadPortalType =
vtkm::internal::ArrayPortalOffsetsToNumComponents<typename OffsetsStorage::ReadPortalType>;
VTKM_CONT static constexpr vtkm::IdComponent GetNumberOfBuffers()
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers()
{
return OffsetsStorage::GetNumberOfBuffers();
return OffsetsStorage::CreateBuffers();
}
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers)
VTKM_CONT static vtkm::Id GetNumberOfValues(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
vtkm::Id numOffsets = OffsetsStorage::GetNumberOfValues(buffers);
if (numOffsets < 1)
@ -87,9 +88,10 @@ public:
return numOffsets - 1;
}
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
VTKM_CONT static ReadPortalType CreateReadPortal(
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{
VTKM_ASSERT(OffsetsStorage::GetNumberOfValues(buffers) > 0);
return ReadPortalType(OffsetsStorage::CreateReadPortal(buffers, device, token));

@ -109,15 +109,27 @@ class Storage<T, vtkm::cont::StorageTagPermutation<IndexStorageTag, ValueStorage
using IndexStorage = vtkm::cont::internal::Storage<vtkm::Id, IndexStorageTag>;
using ValueStorage = vtkm::cont::internal::Storage<T, ValueStorageTag>;
template <typename Buff>
VTKM_CONT constexpr static Buff* IndexBuffers(Buff* buffers)
using IndexArray = vtkm::cont::ArrayHandle<vtkm::Id, IndexStorageTag>;
using ValueArray = vtkm::cont::ArrayHandle<T, ValueStorageTag>;
struct Info
{
return buffers;
std::size_t ValueBufferOffset;
};
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> IndexBuffers(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
Info info = buffers[0].GetMetaData<Info>();
return std::vector<vtkm::cont::internal::Buffer>(buffers.begin() + 1,
buffers.begin() + info.ValueBufferOffset);
}
template <typename Buff>
VTKM_CONT constexpr static Buff* ValueBuffers(Buff* buffers)
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> ValueBuffers(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return buffers + IndexStorage::GetNumberOfBuffers();
Info info = buffers[0].GetMetaData<Info>();
return std::vector<vtkm::cont::internal::Buffer>(buffers.begin() + info.ValueBufferOffset,
buffers.end());
}
public:
@ -130,17 +142,13 @@ public:
vtkm::internal::ArrayPortalPermutation<typename IndexStorage::ReadPortalType,
typename ValueStorage::WritePortalType>;
VTKM_CONT constexpr static vtkm::IdComponent GetNumberOfBuffers()
{
return (IndexStorage::GetNumberOfBuffers() + ValueStorage::GetNumberOfBuffers());
}
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers)
VTKM_CONT static vtkm::Id GetNumberOfValues(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return IndexStorage::GetNumberOfValues(IndexBuffers(buffers));
}
VTKM_CONT static void Fill(vtkm::cont::internal::Buffer*,
VTKM_CONT static void Fill(const std::vector<vtkm::cont::internal::Buffer>&,
const T&,
vtkm::Id,
vtkm::Id,
@ -149,33 +157,44 @@ public:
throw vtkm::cont::ErrorBadType("Fill not supported for ArrayHandlePermutation.");
}
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
VTKM_CONT static ReadPortalType CreateReadPortal(
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{
return ReadPortalType(IndexStorage::CreateReadPortal(IndexBuffers(buffers), device, token),
ValueStorage::CreateReadPortal(ValueBuffers(buffers), device, token));
}
VTKM_CONT static WritePortalType CreateWritePortal(vtkm::cont::internal::Buffer* buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
VTKM_CONT static WritePortalType CreateWritePortal(
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{
// Note: the index portal is always a read-only portal.
return WritePortalType(IndexStorage::CreateReadPortal(IndexBuffers(buffers), device, token),
ValueStorage::CreateWritePortal(ValueBuffers(buffers), device, token));
}
VTKM_CONT static vtkm::cont::ArrayHandle<vtkm::Id, IndexStorageTag> GetIndexArray(
const vtkm::cont::internal::Buffer* buffers)
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers(
const IndexArray& indexArray = IndexArray{},
const ValueArray& valueArray = ValueArray{})
{
return vtkm::cont::ArrayHandle<vtkm::Id, IndexStorageTag>(IndexBuffers(buffers));
Info info;
info.ValueBufferOffset = 1 + indexArray.GetBuffers().size();
return vtkm::cont::internal::CreateBuffers(info, indexArray, valueArray);
}
VTKM_CONT static vtkm::cont::ArrayHandle<T, ValueStorageTag> GetValueArray(
const vtkm::cont::internal::Buffer* buffers)
VTKM_CONT static IndexArray GetIndexArray(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return vtkm::cont::ArrayHandle<T, ValueStorageTag>(ValueBuffers(buffers));
return IndexArray(IndexBuffers(buffers));
}
VTKM_CONT static ValueArray GetValueArray(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return ValueArray(ValueBuffers(buffers));
}
};
@ -236,7 +255,7 @@ public:
VTKM_CONT
ArrayHandlePermutation(const IndexArrayHandleType& indexArray,
const ValueArrayHandleType& valueArray)
: Superclass(vtkm::cont::internal::CreateBuffers(indexArray, valueArray))
: Superclass(StorageType::CreateBuffers(indexArray, valueArray))
{
}

@ -355,18 +355,10 @@ struct StorageTagRecombineVec
namespace detail
{
// Note: Normally a decorating ArrayHandle holds the buffers of the arrays it is decorating
// in its list of arrays. However, the numbers of buffers is expected to be compile-time static
// and ArrayHandleRecombineVec needs to set the number of buffers at runtime. We cheat around
// this by stuffing the decorated buffers in the metadata. To make sure deep copies work
// right, a copy of the metadata results in a deep copy of the contained buffers. The
// vtkm::cont::internal::Buffer holding the metadata is not supposed to copy the metadata
// except for a deep copy (and when it is first set). If this behavior changes, there could
// be a performance degredation.
struct RecombineVecMetaData
{
mutable std::vector<vtkm::cont::internal::Buffer> PortalBuffers;
std::vector<std::vector<vtkm::cont::internal::Buffer>> ArrayBuffers;
std::vector<std::size_t> ArrayBufferOffsets;
RecombineVecMetaData() = default;
@ -374,17 +366,7 @@ struct RecombineVecMetaData
RecombineVecMetaData& operator=(const RecombineVecMetaData& src)
{
this->ArrayBuffers.resize(src.ArrayBuffers.size());
for (std::size_t arrayIndex = 0; arrayIndex < src.ArrayBuffers.size(); ++arrayIndex)
{
this->ArrayBuffers[arrayIndex].resize(src.ArrayBuffers[arrayIndex].size());
for (std::size_t bufferIndex = 0; bufferIndex < src.ArrayBuffers[arrayIndex].size();
++bufferIndex)
{
this->ArrayBuffers[arrayIndex][bufferIndex].DeepCopyFrom(
src.ArrayBuffers[arrayIndex][bufferIndex]);
}
}
this->ArrayBufferOffsets = src.ArrayBufferOffsets;
this->PortalBuffers.clear();
// Intentionally not copying portals. Portals will be recreated from proper array when requsted.
@ -414,13 +396,15 @@ class Storage<vtkm::internal::RecombineVec<ReadWritePortal>,
VTKM_STATIC_ASSERT(
(std::is_same<ReadWritePortal, detail::RecombinedPortalType<ComponentType>>::value));
template <typename Buff>
VTKM_CONT static Buff* BuffersForComponent(Buff* buffers, vtkm::IdComponent componentIndex)
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> BuffersForComponent(
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::IdComponent componentIndex)
{
return buffers[0]
.template GetMetaData<detail::RecombineVecMetaData>()
.ArrayBuffers[componentIndex]
.data();
auto& metaData = buffers[0].GetMetaData<detail::RecombineVecMetaData>();
std::size_t index = static_cast<std::size_t>(componentIndex);
return std::vector<vtkm::cont::internal::Buffer>(
buffers.begin() + metaData.ArrayBufferOffsets[index],
buffers.begin() + metaData.ArrayBufferOffsets[index + 1]);
}
public:
@ -429,20 +413,20 @@ public:
using ReadPortalType = vtkm::internal::ArrayPortalRecombineVec<ReadWritePortal>;
using WritePortalType = vtkm::internal::ArrayPortalRecombineVec<ReadWritePortal>;
VTKM_CONT static vtkm::IdComponent NumberOfComponents(const vtkm::cont::internal::Buffer* buffers)
VTKM_CONT static vtkm::IdComponent NumberOfComponents(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return static_cast<vtkm::IdComponent>(
buffers[0].GetMetaData<detail::RecombineVecMetaData>().ArrayBuffers.size());
buffers[0].GetMetaData<detail::RecombineVecMetaData>().ArrayBufferOffsets.size() - 1);
}
VTKM_CONT static vtkm::IdComponent GetNumberOfBuffers() { return 1; }
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers)
VTKM_CONT static vtkm::Id GetNumberOfValues(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return SourceStorage::GetNumberOfValues(BuffersForComponent(buffers, 0));
}
VTKM_CONT static void Fill(vtkm::cont::internal::Buffer*,
VTKM_CONT static void Fill(const std::vector<vtkm::cont::internal::Buffer>&,
const vtkm::internal::RecombineVec<ReadWritePortal>&,
vtkm::Id,
vtkm::Id,
@ -451,9 +435,10 @@ public:
throw vtkm::cont::ErrorBadType("Fill not supported for ArrayHandleRecombineVec.");
}
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
VTKM_CONT static ReadPortalType CreateReadPortal(
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{
vtkm::IdComponent numComponents = NumberOfComponents(buffers);
@ -488,9 +473,10 @@ public:
numComponents);
}
VTKM_CONT static WritePortalType CreateWritePortal(vtkm::cont::internal::Buffer* buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
VTKM_CONT static WritePortalType CreateWritePortal(
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{
vtkm::IdComponent numComponents = NumberOfComponents(buffers);
@ -525,19 +511,28 @@ public:
numComponents);
}
VTKM_CONT static ArrayType ArrayForComponent(const vtkm::cont::internal::Buffer* buffers,
vtkm::IdComponent componentIndex)
VTKM_CONT static ArrayType ArrayForComponent(
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::IdComponent componentIndex)
{
return ArrayType(BuffersForComponent(buffers, componentIndex));
}
VTKM_CONT static void AppendComponent(vtkm::cont::internal::Buffer* buffers,
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers()
{
detail::RecombineVecMetaData metaData;
metaData.ArrayBufferOffsets.push_back(1);
return vtkm::cont::internal::CreateBuffers(metaData);
}
VTKM_CONT static void AppendComponent(std::vector<vtkm::cont::internal::Buffer>& buffers,
const ArrayType& array)
{
std::vector<vtkm::cont::internal::Buffer> arrayBuffers(
array.GetBuffers(), array.GetBuffers() + SourceStorage::GetNumberOfBuffers());
buffers[0].GetMetaData<detail::RecombineVecMetaData>().ArrayBuffers.push_back(
std::move(arrayBuffers));
// Add buffers of new array to our list of buffers.
buffers.insert(buffers.end(), array.GetBuffers().begin(), array.GetBuffers().end());
// Update metadata for new offset to end.
buffers[0].GetMetaData<detail::RecombineVecMetaData>().ArrayBufferOffsets.push_back(
buffers.size());
}
};
@ -588,7 +583,9 @@ public:
void AppendComponentArray(
const vtkm::cont::ArrayHandle<ComponentType, vtkm::cont::StorageTagStride>& array)
{
StorageType::AppendComponent(this->GetBuffers(), array);
std::vector<vtkm::cont::internal::Buffer> buffers = this->GetBuffers();
StorageType::AppendComponent(buffers, array);
this->SetBuffers(std::move(buffers));
}
};

@ -128,25 +128,26 @@ public:
using ReadPortalType = ArrayPortalReverse<typename ArrayHandleType::ReadPortalType>;
using WritePortalType = ArrayPortalReverse<typename ArrayHandleType::WritePortalType>;
VTKM_CONT constexpr static vtkm::IdComponent GetNumberOfBuffers()
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers()
{
return SourceStorage::GetNumberOfBuffers();
return SourceStorage::CreateBuffers();
}
VTKM_CONT static void ResizeBuffers(vtkm::Id numValues,
vtkm::cont::internal::Buffer* buffers,
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::CopyFlag preserve,
vtkm::cont::Token& token)
{
SourceStorage::ResizeBuffers(numValues, buffers, preserve, token);
}
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers)
VTKM_CONT static vtkm::Id GetNumberOfValues(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return SourceStorage::GetNumberOfValues(buffers);
}
VTKM_CONT static void Fill(vtkm::cont::internal::Buffer* buffers,
VTKM_CONT static void Fill(const std::vector<vtkm::cont::internal::Buffer>& buffers,
const T& fillValue,
vtkm::Id startIndex,
vtkm::Id endIndex,
@ -156,16 +157,18 @@ public:
SourceStorage::Fill(buffers, fillValue, numValues - endIndex, numValues - startIndex, token);
}
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
VTKM_CONT static ReadPortalType CreateReadPortal(
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{
return ReadPortalType(SourceStorage::CreateReadPortal(buffers, device, token));
}
VTKM_CONT static WritePortalType CreateWritePortal(vtkm::cont::internal::Buffer* buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
VTKM_CONT static WritePortalType CreateWritePortal(
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{
return WritePortalType(SourceStorage::CreateWritePortal(buffers, device, token));
}

@ -140,10 +140,13 @@ public:
using WritePortalType =
vtkm::internal::ArrayPortalSOA<ValueType, vtkm::internal::ArrayPortalBasicWrite<ComponentType>>;
VTKM_CONT constexpr static vtkm::IdComponent GetNumberOfBuffers() { return NUM_COMPONENTS; }
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers()
{
return std::vector<vtkm::cont::internal::Buffer>(static_cast<std::size_t>(NUM_COMPONENTS));
}
VTKM_CONT static void ResizeBuffers(vtkm::Id numValues,
vtkm::cont::internal::Buffer* buffers,
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::CopyFlag preserve,
vtkm::cont::Token& token)
{
@ -155,14 +158,15 @@ public:
}
}
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers)
VTKM_CONT static vtkm::Id GetNumberOfValues(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
// Assume all buffers are the same size.
return static_cast<vtkm::Id>(buffers[0].GetNumberOfBytes()) /
static_cast<vtkm::Id>(sizeof(ComponentType));
}
VTKM_CONT static void Fill(vtkm::cont::internal::Buffer* buffers,
VTKM_CONT static void Fill(const std::vector<vtkm::cont::internal::Buffer>& buffers,
const ValueType& fillValue,
vtkm::Id startIndex,
vtkm::Id endIndex,
@ -179,9 +183,10 @@ public:
}
}
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
VTKM_CONT static ReadPortalType CreateReadPortal(
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{
vtkm::Id numValues = GetNumberOfValues(buffers);
ReadPortalType portal(numValues);
@ -197,9 +202,10 @@ public:
return portal;
}
VTKM_CONT static WritePortalType CreateWritePortal(vtkm::cont::internal::Buffer* buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
VTKM_CONT static WritePortalType CreateWritePortal(
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{
vtkm::Id numValues = GetNumberOfValues(buffers);
WritePortalType portal(numValues);
@ -401,7 +407,7 @@ public:
VTKM_CONT vtkm::cont::ArrayHandleBasic<ComponentType> GetArray(vtkm::IdComponent index) const
{
return ComponentArrayType(&this->GetBuffers()[index]);
return ComponentArrayType({ this->GetBuffers()[index] });
}
VTKM_CONT void SetArray(vtkm::IdComponent index, const ComponentArrayType& array)

@ -163,19 +163,18 @@ public:
using ReadPortalType = vtkm::internal::ArrayPortalStrideRead<T>;
using WritePortalType = vtkm::internal::ArrayPortalStrideWrite<T>;
VTKM_CONT static StrideInfo& GetInfo(const vtkm::cont::internal::Buffer* buffers)
VTKM_CONT static StrideInfo& GetInfo(const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return buffers[0].GetMetaData<StrideInfo>();
}
VTKM_CONT static vtkm::IdComponent GetNumberOfBuffers() { return 2; }
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers)
VTKM_CONT static vtkm::Id GetNumberOfValues(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return GetInfo(buffers).NumberOfValues;
}
VTKM_CONT static void Fill(vtkm::cont::internal::Buffer*,
VTKM_CONT static void Fill(const std::vector<vtkm::cont::internal::Buffer>&,
const T&,
vtkm::Id,
vtkm::Id,
@ -184,32 +183,35 @@ public:
throw vtkm::cont::ErrorBadType("Fill not supported for ArrayHandleStride.");
}
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
VTKM_CONT static ReadPortalType CreateReadPortal(
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{
return ReadPortalType(reinterpret_cast<const T*>(buffers[1].ReadPointerDevice(device, token)),
GetInfo(buffers));
}
VTKM_CONT static WritePortalType CreateWritePortal(vtkm::cont::internal::Buffer* buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
VTKM_CONT static WritePortalType CreateWritePortal(
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{
return WritePortalType(reinterpret_cast<T*>(buffers[1].WritePointerDevice(device, token)),
GetInfo(buffers));
}
static std::vector<vtkm::cont::internal::Buffer> CreateBuffers(
const vtkm::cont::internal::Buffer& sourceBuffer,
vtkm::internal::ArrayStrideInfo&& info)
const vtkm::cont::internal::Buffer& sourceBuffer = vtkm::cont::internal::Buffer{},
vtkm::internal::ArrayStrideInfo&& info = vtkm::internal::ArrayStrideInfo{})
{
return vtkm::cont::internal::CreateBuffers(info, sourceBuffer);
}
static vtkm::cont::ArrayHandleBasic<T> GetBasicArray(const vtkm::cont::internal::Buffer* buffers)
static vtkm::cont::ArrayHandleBasic<T> GetBasicArray(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagBasic>(buffers + 1);
return vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagBasic>({ buffers[1] });
}
};

@ -249,7 +249,11 @@ class Storage<typename StorageTagTransform<ArrayHandleType, FunctorType>::ValueT
using SourceStorage =
Storage<typename ArrayHandleType::ValueType, typename ArrayHandleType::StorageTag>;
static constexpr vtkm::IdComponent NUM_METADATA_BUFFERS = 1;
static std::vector<vtkm::cont::internal::Buffer> SourceBuffers(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return std::vector<vtkm::cont::internal::Buffer>(buffers.begin() + 1, buffers.end());
}
public:
VTKM_STORAGE_NO_RESIZE;
@ -260,54 +264,51 @@ public:
typename ArrayHandleType::ReadPortalType,
typename FunctorManager::FunctorType>;
VTKM_CONT static vtkm::IdComponent GetNumberOfBuffers()
VTKM_CONT static vtkm::Id GetNumberOfValues(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return SourceStorage::GetNumberOfBuffers() + NUM_METADATA_BUFFERS;
return SourceStorage::GetNumberOfValues(SourceBuffers(buffers));
}
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers)
{
return SourceStorage::GetNumberOfValues(buffers + NUM_METADATA_BUFFERS);
}
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
VTKM_CONT static ReadPortalType CreateReadPortal(
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{
if (device == vtkm::cont::DeviceAdapterTagUndefined{})
{
return ReadPortalType(
SourceStorage::CreateReadPortal(buffers + NUM_METADATA_BUFFERS, device, token),
buffers[0].GetMetaData<FunctorManager>().PrepareForControl());
return ReadPortalType(SourceStorage::CreateReadPortal(SourceBuffers(buffers), device, token),
buffers[0].GetMetaData<FunctorManager>().PrepareForControl());
}
else
{
return ReadPortalType(
SourceStorage::CreateReadPortal(buffers + NUM_METADATA_BUFFERS, device, token),
SourceStorage::CreateReadPortal(SourceBuffers(buffers), device, token),
buffers[0].GetMetaData<FunctorManager>().PrepareForExecution(device, token));
}
}
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers(
const ArrayHandleType& handle,
const ArrayHandleType& handle = ArrayHandleType{},
const FunctorType& functor = FunctorType())
{
return vtkm::cont::internal::CreateBuffers(FunctorManager(functor), handle);
}
VTKM_CONT static ArrayHandleType GetArray(const vtkm::cont::internal::Buffer* buffers)
VTKM_CONT static ArrayHandleType GetArray(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return vtkm::cont::ArrayHandle<typename ArrayHandleType::ValueType,
typename ArrayHandleType::StorageTag>(buffers +
NUM_METADATA_BUFFERS);
typename ArrayHandleType::StorageTag>(SourceBuffers(buffers));
}
VTKM_CONT static FunctorType GetFunctor(const vtkm::cont::internal::Buffer* buffers)
VTKM_CONT static FunctorType GetFunctor(const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return buffers[0].GetMetaData<FunctorManager>().Functor;
}
VTKM_CONT static NullFunctorType GetInverseFunctor(const vtkm::cont::internal::Buffer*)
VTKM_CONT static NullFunctorType GetInverseFunctor(
const std::vector<vtkm::cont::internal::Buffer>&)
{
return NullFunctorType{};
}
@ -325,7 +326,11 @@ class Storage<
using SourceStorage =
Storage<typename ArrayHandleType::ValueType, typename ArrayHandleType::StorageTag>;
static constexpr vtkm::IdComponent NUM_METADATA_BUFFERS = 2;
static std::vector<vtkm::cont::internal::Buffer> SourceBuffers(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return std::vector<vtkm::cont::internal::Buffer>(buffers.begin() + 2, buffers.end());
}
public:
using ReadPortalType =
@ -339,56 +344,54 @@ public:
typename FunctorManager::FunctorType,
typename InverseFunctorManager::FunctorType>;
VTKM_CONT constexpr static vtkm::IdComponent GetNumberOfBuffers()
VTKM_CONT static vtkm::Id GetNumberOfValues(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return SourceStorage::GetNumberOfBuffers() + NUM_METADATA_BUFFERS;
}
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers)
{
return SourceStorage::GetNumberOfValues(buffers + NUM_METADATA_BUFFERS);
return SourceStorage::GetNumberOfValues(SourceBuffers(buffers));
}
VTKM_CONT static void ResizeBuffers(vtkm::Id numValues,
vtkm::cont::internal::Buffer* buffers,
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::CopyFlag preserve,
vtkm::cont::Token& token)
{
SourceStorage::ResizeBuffers(numValues, buffers + NUM_METADATA_BUFFERS, preserve, token);
std::vector<vtkm::cont::internal::Buffer> sourceBuffers = SourceBuffers(buffers);
SourceStorage::ResizeBuffers(numValues, sourceBuffers, preserve, token);
}
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
VTKM_CONT static ReadPortalType CreateReadPortal(
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{
if (device == vtkm::cont::DeviceAdapterTagUndefined{})
{
return ReadPortalType(
SourceStorage::CreateReadPortal(buffers + NUM_METADATA_BUFFERS, device, token),
buffers[0].GetMetaData<FunctorManager>().PrepareForControl(),
buffers[1].GetMetaData<InverseFunctorManager>().PrepareForControl());
return ReadPortalType(SourceStorage::CreateReadPortal(SourceBuffers(buffers), device, token),
buffers[0].GetMetaData<FunctorManager>().PrepareForControl(),
buffers[1].GetMetaData<InverseFunctorManager>().PrepareForControl());
}
else
{
return ReadPortalType(
SourceStorage::CreateReadPortal(buffers + NUM_METADATA_BUFFERS, device, token),
SourceStorage::CreateReadPortal(SourceBuffers(buffers), device, token),
buffers[0].GetMetaData<FunctorManager>().PrepareForExecution(device, token),
buffers[1].GetMetaData<InverseFunctorManager>().PrepareForExecution(device, token));
}
}
VTKM_CONT static WritePortalType CreateWritePortal(vtkm::cont::internal::Buffer* buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
VTKM_CONT static WritePortalType CreateWritePortal(
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{
return WritePortalType(
SourceStorage::CreateWritePortal(buffers + NUM_METADATA_BUFFERS, device, token),
SourceStorage::CreateWritePortal(SourceBuffers(buffers), device, token),
buffers[0].GetMetaData<FunctorManager>().PrepareForExecution(device, token),
buffers[1].GetMetaData<InverseFunctorManager>().PrepareForExecution(device, token));
}
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers(
const ArrayHandleType& handle,
const ArrayHandleType& handle = ArrayHandleType{},
const FunctorType& functor = FunctorType(),
const InverseFunctorType& inverseFunctor = InverseFunctorType())
{
@ -396,19 +399,20 @@ public:
FunctorManager(functor), InverseFunctorManager(inverseFunctor), handle);
}
VTKM_CONT static ArrayHandleType GetArray(const vtkm::cont::internal::Buffer* buffers)
VTKM_CONT static ArrayHandleType GetArray(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return vtkm::cont::ArrayHandle<typename ArrayHandleType::ValueType,
typename ArrayHandleType::StorageTag>(buffers +
NUM_METADATA_BUFFERS);
typename ArrayHandleType::StorageTag>(SourceBuffers(buffers));
}
VTKM_CONT static FunctorType GetFunctor(const vtkm::cont::internal::Buffer* buffers)
VTKM_CONT static FunctorType GetFunctor(const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return buffers[0].GetMetaData<FunctorManager>().Functor;
}
VTKM_CONT static InverseFunctorType GetInverseFunctor(const vtkm::cont::internal::Buffer* buffers)
VTKM_CONT static InverseFunctorType GetInverseFunctor(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return buffers[1].GetMetaData<InverseFunctorManager>().Functor;
}

@ -143,6 +143,12 @@ class Storage<T, StorageTagView<ST>>
using ArrayHandleType = typename detail::ViewTypeArg<T, ST>::ArrayHandle;
using SourceStorage = Storage<T, ST>;
static std::vector<vtkm::cont::internal::Buffer> SourceBuffers(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return std::vector<vtkm::cont::internal::Buffer>(buffers.begin() + 1, buffers.end());
}
public:
VTKM_STORAGE_NO_RESIZE;
@ -150,25 +156,23 @@ public:
using WritePortalType =
vtkm::internal::ArrayPortalView<typename ArrayHandleType::WritePortalType>;
VTKM_CONT static constexpr vtkm::IdComponent GetNumberOfBuffers()
{
return SourceStorage::GetNumberOfBuffers() + 1;
}
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers)
VTKM_CONT static vtkm::Id GetNumberOfValues(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return buffers[0].GetMetaData<vtkm::internal::ViewIndices>().NumberOfValues;
}
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
VTKM_CONT static ReadPortalType CreateReadPortal(
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{
vtkm::internal::ViewIndices indices = buffers[0].GetMetaData<vtkm::internal::ViewIndices>();
return ReadPortalType(SourceStorage::CreateReadPortal(buffers + 1, device, token), indices);
return ReadPortalType(SourceStorage::CreateReadPortal(SourceBuffers(buffers), device, token),
indices);
}
VTKM_CONT static void Fill(vtkm::cont::internal::Buffer* buffers,
VTKM_CONT static void Fill(const std::vector<vtkm::cont::internal::Buffer>& buffers,
const T& fillValue,
vtkm::Id startIndex,
vtkm::Id endIndex,
@ -179,30 +183,36 @@ public:
vtkm::Id adjustedEndIndex = (endIndex < indices.NumberOfValues)
? endIndex + indices.StartIndex
: indices.NumberOfValues + indices.StartIndex;
SourceStorage::Fill(buffers + 1, fillValue, adjustedStartIndex, adjustedEndIndex, token);
SourceStorage::Fill(
SourceBuffers(buffers), fillValue, adjustedStartIndex, adjustedEndIndex, token);
}
VTKM_CONT static WritePortalType CreateWritePortal(vtkm::cont::internal::Buffer* buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
VTKM_CONT static WritePortalType CreateWritePortal(
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{
vtkm::internal::ViewIndices indices = buffers[0].GetMetaData<vtkm::internal::ViewIndices>();
return WritePortalType(SourceStorage::CreateWritePortal(buffers + 1, device, token), indices);
return WritePortalType(SourceStorage::CreateWritePortal(SourceBuffers(buffers), device, token),
indices);
}
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer>
CreateBuffers(vtkm::Id startIndex, vtkm::Id numValues, const ArrayHandleType& array)
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers(
vtkm::Id startIndex = 0,
vtkm::Id numValues = 0,
const ArrayHandleType& array = ArrayHandleType{})
{
return vtkm::cont::internal::CreateBuffers(vtkm::internal::ViewIndices(startIndex, numValues),
array);
}
VTKM_CONT static ArrayHandleType GetSourceArray(const vtkm::cont::internal::Buffer* buffers)
VTKM_CONT static ArrayHandleType GetSourceArray(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return ArrayHandleType(buffers + 1);
return ArrayHandleType(SourceBuffers(buffers));
}
VTKM_CONT static vtkm::Id GetStartIndex(const vtkm::cont::internal::Buffer* buffers)
VTKM_CONT static vtkm::Id GetStartIndex(const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return buffers[0].GetMetaData<vtkm::internal::ViewIndices>().StartIndex;
}

@ -170,60 +170,61 @@ class XGCCoordinatesStorageImpl
using SourceStorage = Storage<T, StorageTagBasic>; // only allow input AH to use StorageTagBasic
using MetaData = XGCCoordinatesMetaData;
static MetaData& GetMetaData(const vtkm::cont::internal::Buffer* buffers)
static MetaData& GetMetaData(const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return buffers[0].GetMetaData<MetaData>();
}
// Used to skip the metadata buffer and return only actual data buffers
template <typename Buffs>
VTKM_CONT constexpr static Buffs* SourceBuffers(Buffs* buffers)
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> SourceBuffers(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return buffers + 1;
return std::vector<vtkm::cont::internal::Buffer>(buffers.begin() + 1, buffers.end());
}
public:
using ReadPortalType =
vtkm::internal::ArrayPortalXGCCoordinates<typename SourceStorage::ReadPortalType>;
VTKM_CONT constexpr static vtkm::IdComponent GetNumberOfBuffers()
{
return SourceStorage::GetNumberOfBuffers() + 1; // To account for metadata
}
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers)
VTKM_CONT static vtkm::Id GetNumberOfValues(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return GetNumberOfValuesPerPlane(buffers) * GetNumberOfPlanesOwned(buffers);
}
VTKM_CONT static vtkm::Id GetNumberOfValuesPerPlane(const vtkm::cont::internal::Buffer* buffers)
VTKM_CONT static vtkm::Id GetNumberOfValuesPerPlane(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return SourceStorage::GetNumberOfValues(SourceBuffers(buffers)) / 2;
}
VTKM_CONT static vtkm::Id GetNumberOfPlanes(const vtkm::cont::internal::Buffer* buffers)
VTKM_CONT static vtkm::Id GetNumberOfPlanes(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return GetMetaData(buffers).NumberOfPlanes;
}
VTKM_CONT static vtkm::Id GetNumberOfPlanesOwned(const vtkm::cont::internal::Buffer* buffers)
VTKM_CONT static vtkm::Id GetNumberOfPlanesOwned(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return GetMetaData(buffers).NumberOfPlanesOwned;
}
VTKM_CONT static vtkm::Id GetPlaneStartId(const vtkm::cont::internal::Buffer* buffers)
VTKM_CONT static vtkm::Id GetPlaneStartId(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return GetMetaData(buffers).PlaneStartId;
}
VTKM_CONT static bool GetUseCylindrical(const vtkm::cont::internal::Buffer* buffers)
VTKM_CONT static bool GetUseCylindrical(const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return GetMetaData(buffers).UseCylindrical;
}
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
VTKM_CONT static ReadPortalType CreateReadPortal(
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{
return ReadPortalType(SourceStorage::CreateReadPortal(SourceBuffers(buffers), device, token),
GetNumberOfPlanes(buffers),
@ -233,7 +234,7 @@ public:
}
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers(
vtkm::cont::ArrayHandle<T> array,
const vtkm::cont::ArrayHandle<T>& array,
vtkm::Id numberOfPlanes,
vtkm::Id numberOfPlanesOwned,
vtkm::Id planeStartId,
@ -243,8 +244,13 @@ public:
MetaData(numberOfPlanes, numberOfPlanesOwned, planeStartId, useCylindrical), array);
}
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers()
{
return CreateBuffers(vtkm::cont::ArrayHandle<T>{}, 0, 0, 0, false);
}
VTKM_CONT static vtkm::cont::ArrayHandle<T> GetArrayHandle(
const vtkm::cont::internal::Buffer* buffers)
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return vtkm::cont::ArrayHandle<T>(SourceBuffers(buffers));
}

@ -129,6 +129,10 @@ struct ArrayHandleZipTraits
using Tag =
StorageTagZip<typename FirstHandleType::StorageTag, typename SecondHandleType::StorageTag>;
/// The storage type.
///
using Storage = vtkm::cont::internal::Storage<ValueType, Tag>;
/// The superclass for ArrayHandleZip.
///
using Superclass = vtkm::cont::ArrayHandle<ValueType, Tag>;
@ -141,15 +145,27 @@ class Storage<vtkm::Pair<T1, T2>, vtkm::cont::StorageTagZip<ST1, ST2>>
using SecondStorage = Storage<T2, ST2>;
using ValueType = vtkm::Pair<T1, T2>;
template <typename BufferType>
VTKM_CONT static BufferType* FirstArrayBuffers(BufferType* buffers)
using FirstArrayType = vtkm::cont::ArrayHandle<T1, ST1>;
using SecondArrayType = vtkm::cont::ArrayHandle<T2, ST2>;
struct Info
{
return buffers;
std::size_t SecondBuffersOffset;
};
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> FirstArrayBuffers(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
const Info& info = buffers[0].GetMetaData<Info>();
return std::vector<vtkm::cont::internal::Buffer>(buffers.begin() + 1,
buffers.begin() + info.SecondBuffersOffset);
}
template <typename BufferType>
VTKM_CONT static BufferType* SecondArrayBuffers(BufferType* buffers)
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> SecondArrayBuffers(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return buffers + FirstStorage::GetNumberOfBuffers();
const Info& info = buffers[0].GetMetaData<Info>();
return std::vector<vtkm::cont::internal::Buffer>(buffers.begin() + info.SecondBuffersOffset,
buffers.end());
}
public:
@ -160,13 +176,17 @@ public:
vtkm::exec::internal::ArrayPortalZip<typename FirstStorage::WritePortalType,
typename SecondStorage::WritePortalType>;
VTKM_CONT static constexpr vtkm::IdComponent GetNumberOfBuffers()
static std::vector<vtkm::cont::internal::Buffer> CreateBuffers(
const FirstArrayType& firstArray = FirstArrayType{},
const SecondArrayType& secondArray = SecondArrayType{})
{
return FirstStorage::GetNumberOfBuffers() + SecondStorage::GetNumberOfBuffers();
Info info;
info.SecondBuffersOffset = 1 + firstArray.GetBuffers().size();
return vtkm::cont::internal::CreateBuffers(info, firstArray, secondArray);
}
VTKM_CONT static void ResizeBuffers(vtkm::Id numValues,
vtkm::cont::internal::Buffer* buffers,
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::CopyFlag preserve,
vtkm::cont::Token& token)
{
@ -174,14 +194,15 @@ public:
SecondStorage::ResizeBuffers(numValues, SecondArrayBuffers(buffers), preserve, token);
}
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers)
VTKM_CONT static vtkm::Id GetNumberOfValues(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
vtkm::Id numValues = FirstStorage::GetNumberOfValues(FirstArrayBuffers(buffers));
VTKM_ASSERT(numValues == SecondStorage::GetNumberOfValues(SecondArrayBuffers(buffers)));
return numValues;
}
VTKM_CONT static void Fill(vtkm::cont::internal::Buffer* buffers,
VTKM_CONT static void Fill(const std::vector<vtkm::cont::internal::Buffer>& buffers,
const ValueType& fillValue,
vtkm::Id startIndex,
vtkm::Id endIndex,
@ -191,29 +212,31 @@ public:
SecondStorage::Fill(SecondArrayBuffers(buffers), fillValue.second, startIndex, endIndex, token);
}
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
VTKM_CONT static ReadPortalType CreateReadPortal(
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{
return ReadPortalType(
FirstStorage::CreateReadPortal(FirstArrayBuffers(buffers), device, token),
SecondStorage::CreateReadPortal(SecondArrayBuffers(buffers), device, token));
}
VTKM_CONT static WritePortalType CreateWritePortal(vtkm::cont::internal::Buffer* buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
VTKM_CONT static WritePortalType CreateWritePortal(
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{
return WritePortalType(
FirstStorage::CreateWritePortal(FirstArrayBuffers(buffers), device, token),
SecondStorage::CreateWritePortal(SecondArrayBuffers(buffers), device, token));
}
vtkm::cont::ArrayHandle<T1, ST1> GetFirstArray(const vtkm::cont::internal::Buffer* buffers)
static FirstArrayType GetFirstArray(const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return { FirstArrayBuffers(buffers) };
}
vtkm::cont::ArrayHandle<T2, ST2> GetSecondArray(const vtkm::cont::internal::Buffer* buffers)
static SecondArrayType GetSecondArray(const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return { SecondArrayBuffers(buffers) };
}
@ -236,6 +259,9 @@ class ArrayHandleZip
// template argument is not a valid ArrayHandle type.
VTKM_IS_ARRAY_HANDLE(SecondHandleType);
using StorageType =
typename internal::ArrayHandleZipTraits<FirstHandleType, SecondHandleType>::Storage;
public:
VTKM_ARRAY_HANDLE_SUBCLASS(
ArrayHandleZip,
@ -244,17 +270,14 @@ public:
VTKM_CONT
ArrayHandleZip(const FirstHandleType& firstArray, const SecondHandleType& secondArray)
: Superclass(vtkm::cont::internal::CreateBuffers(firstArray, secondArray))
: Superclass(StorageType::CreateBuffers(firstArray, secondArray))
{
}
FirstHandleType GetFirstArray() const
{
return this->GetStorage().GetFirstArray(this->GetBuffers());
}
FirstHandleType GetFirstArray() const { return StorageType::GetFirstArray(this->GetBuffers()); }
SecondHandleType GetSecondArray() const
{
return this->GetStorage().GetSecondArray(this->GetBuffers());
return StorageType::GetSecondArray(this->GetBuffers());
}
};

@ -595,7 +595,8 @@ public:
VTKM_CONT VTKM_DEPRECATED(1.6, "BitField now uses a Buffer to store data.")
ArrayHandle<vtkm::WordTypeDefault, StorageTagBasic> GetData() const
{
return vtkm::cont::ArrayHandle<vtkm::WordTypeDefault, StorageTagBasic>(&this->Buffer);
return vtkm::cont::ArrayHandle<vtkm::WordTypeDefault, StorageTagBasic>(
std::vector<vtkm::cont::internal::Buffer>(1, this->Buffer));
}
/// Return the number of bits stored by this BitField.

@ -180,6 +180,18 @@ set(sources
UnknownCellSet.cxx
)
if(VTKm_ENABLE_TESTING_LIBRARY)
list(APPEND sources
# This file should really be part of the vtkm_cont_testing library (in the testing
# subdirectory) It supports external code using deprecated functionality. In particular,
# testing/MakeTestDataSet.h now needs symbols compiled in MakeTestDataSet.cxx, but the
# deprecated behavior expects to only need to include vtkm_cont. As a workaround, add the code
# to vtkm_cont for now. This should probably be changed back to be in vtkm_cont_testing for the
# 2.0 release.
testing/MakeTestDataSet.cxx
)
endif()
# This list of sources has code that uses devices and so might need to be
# compiled with a device-specific compiler (like CUDA).
set(device_sources

@ -118,25 +118,30 @@ public:
///
using WritePortalType = vtkm::internal::ArrayPortalBasicWrite<T>;
/// \brief Returns the number of buffers required for this storage.
/// \brief Create the buffers for an empty array.
///
VTKM_CONT constexpr static vtkm::IdComponent GetNumberOfBuffers();
/// This is used by the `ArrayHandle` base class when constructed with no arguments.
/// A convenience subclass may construct the buffers in a different way based on
/// some provided objects.
///
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers();
/// \brief Resizes the array by changing the size of the buffers.
///
/// Can also modify any metadata attached to the buffers.
///
VTKM_CONT static void ResizeBuffers(vtkm::Id numValues,
vtkm::cont::internal::Buffer* buffers,
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::CopyFlag preserve,
vtkm::cont::Token& token);
/// \brief Returns the number of entries allocated in the array.
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers);
VTKM_CONT static vtkm::Id GetNumberOfValues(
const std::vector<vtkm::cont::internal::Buffer>& buffers);
/// \brief Fills the array with the given value starting and ending at the given indices.
///
VTKM_CONT static void Fill(vtkm::cont::internal::Buffer* buffers,
VTKM_CONT static void Fill(const std::vector<vtkm::cont::internal::Buffer>& buffers,
const ValueType& fillValue,
vtkm::Id startIndex,
vtkm::Id endIndex,
@ -144,15 +149,17 @@ public:
/// \brief Create a read-only portal on the specified device.
///
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token);
VTKM_CONT static ReadPortalType CreateReadPortal(
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token);
/// \brief Create a read/write portal on the specified device.
///
VTKM_CONT static WritePortalType CreateWritePortal(vtkm::cont::internal::Buffer* buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
VTKM_CONT static WritePortalType CreateWritePortal(
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
};
#endif // VTKM_DOXYGEN_ONLY
@ -175,22 +182,24 @@ struct StorageTraits<vtkm::cont::internal::Storage<T, S>>
using Tag = S;
};
#define VTKM_STORAGE_NO_RESIZE \
VTKM_CONT static void ResizeBuffers( \
vtkm::Id numValues, vtkm::cont::internal::Buffer* buffers, vtkm::CopyFlag, vtkm::cont::Token&) \
{ \
vtkm::cont::internal::detail::StorageNoResizeImpl( \
GetNumberOfValues(buffers), \
numValues, \
vtkm::cont::TypeToString<typename vtkm::cont::internal::StorageTraits<Storage>::Tag>()); \
} \
#define VTKM_STORAGE_NO_RESIZE \
VTKM_CONT static void ResizeBuffers(vtkm::Id numValues, \
const std::vector<vtkm::cont::internal::Buffer>& buffers, \
vtkm::CopyFlag, \
vtkm::cont::Token&) \
{ \
vtkm::cont::internal::detail::StorageNoResizeImpl( \
GetNumberOfValues(buffers), \
numValues, \
vtkm::cont::TypeToString<typename vtkm::cont::internal::StorageTraits<Storage>::Tag>()); \
} \
using ResizeBuffersEatComma = void
#define VTKM_STORAGE_NO_WRITE_PORTAL \
using WritePortalType = vtkm::internal::ArrayPortalDummy< \
typename vtkm::cont::internal::StorageTraits<Storage>::ValueType>; \
VTKM_CONT static void Fill( \
vtkm::cont::internal::Buffer*, \
const std::vector<vtkm::cont::internal::Buffer>&, \
const typename vtkm::cont::internal::StorageTraits<Storage>::ValueType&, \
vtkm::Id, \
vtkm::Id, \
@ -201,7 +210,9 @@ struct StorageTraits<vtkm::cont::internal::Storage<T, S>>
vtkm::cont::TypeToString<typename vtkm::cont::internal::StorageTraits<Storage>::Tag>()); \
} \
VTKM_CONT static WritePortalType CreateWritePortal( \
vtkm::cont::internal::Buffer*, vtkm::cont::DeviceAdapterId, vtkm::cont::Token&) \
const std::vector<vtkm::cont::internal::Buffer>&, \
vtkm::cont::DeviceAdapterId, \
vtkm::cont::Token&) \
{ \
throw vtkm::cont::ErrorBadAllocation( \
"Cannot write to arrays with storage type of " + \

@ -7,6 +7,7 @@
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#include <vtkm/cont/Algorithm.h>
#include <vtkm/cont/DeviceAdapter.h>
#include <vtkm/cont/DeviceAdapterList.h>
#include <vtkm/cont/Logging.h>
@ -326,5 +327,11 @@ vtkm::Float64 Timer::GetElapsedTime() const
return functor.ElapsedTime;
}
void Timer::Synchronize() const
{
vtkm::cont::Algorithm::Synchronize(this->Device);
}
}
} // namespace vtkm::cont

@ -73,15 +73,25 @@ public:
vtkm::Float64 GetElapsedTime() const;
/// Returns the device for which this timer is synchronized. If the device adapter has the same
/// id as DeviceAdapterTagAny, then the timer will synchronize all devices.
/// id as `DeviceAdapterTagAny`, then the timer will synchronize all devices.
VTKM_CONT vtkm::cont::DeviceAdapterId GetDevice() const { return this->Device; }
/// Synchronize the device(s) that this timer is monitoring without starting or stopping the
/// timer. This is useful for ensuring that external events are synchronized to this timer.
///
/// Note that this method will allways block until the device(s) finish even if the
/// `Start`/`Stop` methods do not actually block. For example, the timer for CUDA does not
/// actually wait for asynchronous operations to finish. Rather, it inserts a fence and
/// records the time as fences are encounted. But regardless, this `Synchronize` method
/// will block for the CUDA device.
VTKM_CONT void Synchronize() const;
private:
/// Some timers are ill-defined when copied, so disallow that for all timers.
VTKM_CONT Timer(const Timer&) = delete;
VTKM_CONT void operator=(const Timer&) = delete;
DeviceAdapterId Device;
vtkm::cont::DeviceAdapterId Device;
std::unique_ptr<detail::EnabledDeviceTimerImpls> Internal;
};
}

@ -26,6 +26,7 @@
#include <vtkm/cont/internal/ArrayCopyUnknown.h>
#include <cstring>
#include <sstream>
namespace
@ -108,7 +109,17 @@ VTKM_CONT bool UnknownArrayHandle::IsValueTypeImpl(std::type_index type) const
}
// Needs optimization based on platform. OSX cannot compare typeid across translation units?
return this->Container->ValueType == type;
bool typesEqual = (this->Container->ValueType == type);
// Could use optimization based on platform. OSX cannot compare typeid across translation
// units, so we have to also check the names. (Why doesn't the == operator above do that?)
// Are there other platforms that behave similarly?
if (!typesEqual)
{
typesEqual = (std::strcmp(this->Container->ValueType.name(), type.name()) == 0);
}
return typesEqual;
}
VTKM_CONT bool UnknownArrayHandle::IsStorageTypeImpl(std::type_index type) const
@ -119,7 +130,17 @@ VTKM_CONT bool UnknownArrayHandle::IsStorageTypeImpl(std::type_index type) const
}
// Needs optimization based on platform. OSX cannot compare typeid across translation units?
return this->Container->StorageType == type;
bool typesEqual = (this->Container->StorageType == type);
// Could use optimization based on platform. OSX cannot compare typeid across translation
// units, so we have to also check the names. (Why doesn't the == operator above do that?)
// Are there other platforms that behave similarly?
if (!typesEqual)
{
typesEqual = (std::strcmp(this->Container->StorageType.name(), type.name()) == 0);
}
return typesEqual;
}
VTKM_CONT bool UnknownArrayHandle::IsBaseComponentTypeImpl(

@ -136,8 +136,7 @@ UnknownAHExtractComponent(void* mem, vtkm::IdComponent componentIndex, vtkm::Cop
using AH = vtkm::cont::ArrayHandle<T, S>;
AH* arrayHandle = reinterpret_cast<AH*>(mem);
auto componentArray = vtkm::cont::ArrayExtractComponent(*arrayHandle, componentIndex, allowCopy);
vtkm::cont::internal::Buffer* buffers = componentArray.GetBuffers();
return std::vector<vtkm::cont::internal::Buffer>(buffers, buffers + 2);
return componentArray.GetBuffers();
}
template <typename T, typename S>

@ -10,16 +10,19 @@
set(unit_tests
UnitTestControlSignatureTag.cxx
UnitTestTransportArrayIn.cxx
UnitTestTransportArrayInOut.cxx
UnitTestTransportArrayOut.cxx
UnitTestTransportCellSetIn.cxx
UnitTestTransportExecObject.cxx
UnitTestTransportWholeArray.cxx
UnitTestTypeCheckArray.cxx
UnitTestTypeCheckCellSet.cxx
UnitTestTypeCheckExecObject.cxx
UnitTestTypeCheckKeys.cxx
)
vtkm_unit_tests(SOURCES ${unit_tests} DEFINES VTKM_NO_ERROR_ON_MIXED_CUDA_CXX_TAG)
set(unit_tests_device
UnitTestTransportArrayIn.cxx
UnitTestTransportArrayInOut.cxx
UnitTestTransportArrayOut.cxx
UnitTestTransportCellSetIn.cxx
UnitTestTransportExecObject.cxx
UnitTestTransportWholeArray.cxx
)
vtkm_unit_tests(SOURCES ${unit_tests} DEVICE_SOURCES ${unit_tests_device})

@ -8,6 +8,9 @@
// PURPOSE. See the above copyright notice for more information.
//============================================================================
// This test does not really need a device compiler
#define VTKM_NO_ERROR_ON_MIXED_CUDA_CXX_TAG
#include <vtkm/worklet/WorkletMapField.h>
#include <vtkm/cont/testing/Testing.h>

@ -13,7 +13,8 @@
#include <vtkm/exec/FunctorBase.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/serial/DeviceAdapterSerial.h>
#include <vtkm/cont/DeviceAdapter.h>
#include <vtkm/cont/TryExecute.h>
#include <vtkm/cont/testing/Testing.h>
@ -68,15 +69,16 @@ struct TryArrayInType
};
template <typename Device>
void TryArrayInTransport(Device)
bool TryArrayInTransport(Device device)
{
std::cout << "Trying ArrayIn transport with " << device.GetName() << std::endl;
vtkm::testing::Testing::TryTypes(TryArrayInType<Device>());
return true;
}
void TestArrayInTransport()
{
std::cout << "Trying ArrayIn transport with serial device." << std::endl;
TryArrayInTransport(vtkm::cont::DeviceAdapterTagSerial());
VTKM_TEST_ASSERT(vtkm::cont::TryExecute([](auto device) { return TryArrayInTransport(device); }));
}
} // Anonymous namespace

@ -14,6 +14,7 @@
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/DeviceAdapter.h>
#include <vtkm/cont/TryExecute.h>
#include <vtkm/cont/testing/Testing.h>
@ -78,15 +79,17 @@ struct TryArrayInOutType
};
template <typename Device>
void TryArrayInOutTransport(Device)
bool TryArrayInOutTransport(Device device)
{
std::cout << "Trying ArrayInOut transport with " << device.GetName() << std::endl;
vtkm::testing::Testing::TryTypes(TryArrayInOutType<Device>(), vtkm::TypeListCommon());
return true;
}
void TestArrayInOutTransport()
{
std::cout << "Trying ArrayInOut transport with serial device." << std::endl;
TryArrayInOutTransport(vtkm::cont::DeviceAdapterTagSerial());
VTKM_TEST_ASSERT(
vtkm::cont::TryExecute([](auto device) { return TryArrayInOutTransport(device); }));
}
} // anonymous namespace

@ -14,7 +14,8 @@
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ArrayHandleIndex.h>
#include <vtkm/cont/serial/DeviceAdapterSerial.h>
#include <vtkm/cont/DeviceAdapter.h>
#include <vtkm/cont/TryExecute.h>
#include <vtkm/cont/testing/Testing.h>
@ -67,15 +68,17 @@ struct TryArrayOutType
};
template <typename Device>
void TryArrayOutTransport(Device)
bool TryArrayOutTransport(Device device)
{
std::cout << "Trying ArrayOut transport with " << device.GetName() << std::endl;
vtkm::testing::Testing::TryTypes(TryArrayOutType<Device>());
return true;
}
void TestArrayOutTransport()
{
std::cout << "Trying ArrayOut transport with serial device." << std::endl;
TryArrayOutTransport(vtkm::cont::DeviceAdapterTagSerial());
VTKM_TEST_ASSERT(
vtkm::cont::TryExecute([](auto device) { return TryArrayOutTransport(device); }));
}
} // Anonymous namespace

@ -11,11 +11,11 @@
#include <vtkm/cont/arg/TransportTagCellSetIn.h>
#include <vtkm/cont/CellSetExplicit.h>
#include <vtkm/cont/DeviceAdapter.h>
#include <vtkm/cont/TryExecute.h>
#include <vtkm/exec/FunctorBase.h>
#include <vtkm/cont/serial/DeviceAdapterSerial.h>
#include <vtkm/cont/testing/MakeTestDataSet.h>
#include <vtkm/cont/testing/Testing.h>
@ -49,8 +49,10 @@ struct TestKernel : public vtkm::exec::FunctorBase
};
template <typename Device>
void TransportWholeCellSetIn(Device)
bool TransportWholeCellSetIn(Device device)
{
std::cout << "Trying CellSetIn transport with " << device.GetName() << std::endl;
//build a fake cell set
const int nVerts = 5;
vtkm::cont::CellSetExplicit<> contObject;
@ -78,12 +80,14 @@ void TransportWholeCellSetIn(Device)
kernel.CellSet = transport(contObject, nullptr, 1, 1, token);
vtkm::cont::DeviceAdapterAlgorithm<Device>::Schedule(kernel, 1);
return true;
}
void UnitTestCellSetIn()
{
std::cout << "Trying CellSetIn transport with serial device." << std::endl;
TransportWholeCellSetIn(vtkm::cont::DeviceAdapterTagSerial());
VTKM_TEST_ASSERT(
vtkm::cont::TryExecute([](auto device) { return TransportWholeCellSetIn(device); }));
}
} // Anonymous namespace

@ -12,15 +12,15 @@
#include <vtkm/exec/FunctorBase.h>
#include <vtkm/cont/serial/DeviceAdapterSerial.h>
#include <vtkm/cont/DeviceAdapter.h>
#include <vtkm/cont/ExecutionObjectBase.h>
#include <vtkm/cont/TryExecute.h>
#include <vtkm/cont/testing/Testing.h>
#define EXPECTED_NUMBER 42
namespace
namespace unittesttransportexecobject
{
struct NotAnExecutionObject
@ -65,8 +65,10 @@ struct TestKernel : public vtkm::exec::FunctorBase
};
template <typename Device>
void TryExecObjectTransport(Device)
bool TryExecObjectTransport(Device device)
{
std::cout << "Trying ExecObject transport with " << device.GetName() << std::endl;
TestExecutionObject contObject;
contObject.Number = EXPECTED_NUMBER;
@ -79,6 +81,8 @@ void TryExecObjectTransport(Device)
kernel.Object = transport(contObject, nullptr, 1, 1, token);
vtkm::cont::DeviceAdapterAlgorithm<Device>::Schedule(kernel, 1);
return true;
}
void TestExecObjectTransport()
@ -98,13 +102,14 @@ void TestExecObjectTransport()
VTKM_TEST_ASSERT(vtkm::cont::internal::HasPrepareForExecution<TestExecutionObject>::value,
"Bad query");
std::cout << "Trying ExecObject transport with serial device." << std::endl;
TryExecObjectTransport(vtkm::cont::DeviceAdapterTagSerial());
VTKM_TEST_ASSERT(
vtkm::cont::TryExecute([](auto device) { return TryExecObjectTransport(device); }));
}
} // Anonymous namespace
} // namespace unittesttransportexecobject
int UnitTestTransportExecObject(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(TestExecObjectTransport, argc, argv);
return vtkm::cont::testing::Testing::Run(
unittesttransportexecobject::TestExecObjectTransport, argc, argv);
}

@ -8,6 +8,9 @@
// PURPOSE. See the above copyright notice for more information.
//============================================================================
// This test does not really need a device compiler
#define VTKM_NO_ERROR_ON_MIXED_CUDA_CXX_TAG
#include <vtkm/cont/arg/TypeCheckTagArrayIn.h>
#include <vtkm/cont/arg/TypeCheckTagArrayInOut.h>
#include <vtkm/cont/arg/TypeCheckTagArrayOut.h>

@ -8,6 +8,9 @@
// PURPOSE. See the above copyright notice for more information.
//============================================================================
// This test does not really need a device compiler
#define VTKM_NO_ERROR_ON_MIXED_CUDA_CXX_TAG
#include <vtkm/cont/arg/TypeCheckTagCellSet.h>
#include <vtkm/cont/ArrayHandle.h>

@ -8,6 +8,9 @@
// PURPOSE. See the above copyright notice for more information.
//============================================================================
// This test does not really need a device compiler
#define VTKM_NO_ERROR_ON_MIXED_CUDA_CXX_TAG
#include <vtkm/cont/arg/TypeCheckTagExecObject.h>
#include <vtkm/cont/ArrayHandle.h>

@ -8,6 +8,9 @@
// PURPOSE. See the above copyright notice for more information.
//============================================================================
// This test does not really need a device compiler
#define VTKM_NO_ERROR_ON_MIXED_CUDA_CXX_TAG
#include <vtkm/cont/arg/TypeCheckTagKeys.h>
#include <vtkm/worklet/Keys.h>

@ -18,6 +18,7 @@
#include <vtkm/cont/cuda/internal/RuntimeDeviceConfigurationCuda.h>
#define NO_VTKM_MANAGED_MEMORY "NO_VTKM_MANAGED_MEMORY"
#include <cstdlib>
#include <mutex>
#include <vector>
@ -28,10 +29,12 @@ VTKM_THIRDPARTY_POST_INCLUDE
// These static vars are in an anon namespace to work around MSVC linker issues.
namespace
{
#if CUDART_VERSION >= 8000
// Has CudaAllocator::Initialize been called by any thread?
static std::once_flag IsInitialized;
#endif
static std::once_flag IsInitializedFlag;
// Used to keep track of whether the CUDA allocator has been initialized CUDA has not
// been finalized (since CUDA does not seem to track that for us).
static bool IsInitialized = false;
// Holds how VTK-m currently allocates memory.
// When VTK-m is initialized we set this based on the hardware support ( HardwareSupportsManagedMemory ).
@ -183,12 +186,28 @@ void* CudaAllocator::AllocateUnManaged(std::size_t numBytes)
void CudaAllocator::Free(void* ptr)
{
if (!IsInitialized)
{
// Since the data was successfully allocated, it is a fair assumption that the CUDA
// runtime has been finalized and a global object is trying to destroy itself. Since
// CUDA already cleaned up all memory for program exit, we can ignore this free.
return;
}
VTKM_LOG_F(vtkm::cont::LogLevel::MemExec, "Freeing CUDA allocation at %p.", ptr);
VTKM_CUDA_CALL(cudaFree(ptr));
}
void CudaAllocator::FreeDeferred(void* ptr, std::size_t numBytes)
{
if (!IsInitialized)
{
// Since the data was successfully allocated, it is a fair assumption that the CUDA
// runtime has been finalized and a global object is trying to destroy itself. Since
// CUDA already cleaned up all memory for program exit, we can ignore this free.
return;
}
static std::mutex deferredMutex;
static std::vector<void*> deferredPointers;
static std::size_t deferredSize = 0;
@ -225,12 +244,10 @@ void CudaAllocator::PrepareForControl(const void* ptr, std::size_t numBytes)
{
if (IsManagedPointer(ptr) && numBytes >= Threshold)
{
#if CUDART_VERSION >= 8000
// TODO these hints need to be benchmarked and adjusted once we start
// sharing the pointers between cont/exec
VTKM_CUDA_CALL(cudaMemAdvise(ptr, numBytes, cudaMemAdviseSetAccessedBy, cudaCpuDeviceId));
VTKM_CUDA_CALL(cudaMemPrefetchAsync(ptr, numBytes, cudaCpuDeviceId, cudaStreamPerThread));
#endif // CUDA >= 8.0
}
}
@ -238,7 +255,6 @@ void CudaAllocator::PrepareForInput(const void* ptr, std::size_t numBytes)
{
if (IsManagedPointer(ptr) && numBytes >= Threshold)
{
#if CUDART_VERSION >= 8000
vtkm::Id dev;
vtkm::cont::RuntimeDeviceInformation()
.GetRuntimeConfiguration(vtkm::cont::DeviceAdapterTagCuda())
@ -247,7 +263,6 @@ void CudaAllocator::PrepareForInput(const void* ptr, std::size_t numBytes)
// VTKM_CUDA_CALL(cudaMemAdvise(ptr, numBytes, cudaMemAdviseSetReadMostly, dev));
VTKM_CUDA_CALL(cudaMemAdvise(ptr, numBytes, cudaMemAdviseSetAccessedBy, dev));
VTKM_CUDA_CALL(cudaMemPrefetchAsync(ptr, numBytes, dev, cudaStreamPerThread));
#endif // CUDA >= 8.0
}
}
@ -255,7 +270,6 @@ void CudaAllocator::PrepareForOutput(const void* ptr, std::size_t numBytes)
{
if (IsManagedPointer(ptr) && numBytes >= Threshold)
{
#if CUDART_VERSION >= 8000
vtkm::Id dev;
vtkm::cont::RuntimeDeviceInformation()
.GetRuntimeConfiguration(vtkm::cont::DeviceAdapterTagCuda())
@ -264,7 +278,6 @@ void CudaAllocator::PrepareForOutput(const void* ptr, std::size_t numBytes)
// VTKM_CUDA_CALL(cudaMemAdvise(ptr, numBytes, cudaMemAdviseUnsetReadMostly, dev));
VTKM_CUDA_CALL(cudaMemAdvise(ptr, numBytes, cudaMemAdviseSetAccessedBy, dev));
VTKM_CUDA_CALL(cudaMemPrefetchAsync(ptr, numBytes, dev, cudaStreamPerThread));
#endif // CUDA >= 8.0
}
}
@ -272,7 +285,6 @@ void CudaAllocator::PrepareForInPlace(const void* ptr, std::size_t numBytes)
{
if (IsManagedPointer(ptr) && numBytes >= Threshold)
{
#if CUDART_VERSION >= 8000
vtkm::Id dev;
vtkm::cont::RuntimeDeviceInformation()
.GetRuntimeConfiguration(vtkm::cont::DeviceAdapterTagCuda())
@ -281,14 +293,12 @@ void CudaAllocator::PrepareForInPlace(const void* ptr, std::size_t numBytes)
// VTKM_CUDA_CALL(cudaMemAdvise(ptr, numBytes, cudaMemAdviseUnsetReadMostly, dev));
VTKM_CUDA_CALL(cudaMemAdvise(ptr, numBytes, cudaMemAdviseSetAccessedBy, dev));
VTKM_CUDA_CALL(cudaMemPrefetchAsync(ptr, numBytes, dev, cudaStreamPerThread));
#endif // CUDA >= 8.0
}
}
void CudaAllocator::Initialize()
{
#if CUDART_VERSION >= 8000
std::call_once(IsInitialized, []() {
std::call_once(IsInitializedFlag, []() {
auto cudaDeviceConfig = dynamic_cast<
vtkm::cont::internal::RuntimeDeviceConfiguration<vtkm::cont::DeviceAdapterTagCuda>&>(
vtkm::cont::RuntimeDeviceInformation{}.GetRuntimeConfiguration(
@ -334,8 +344,17 @@ void CudaAllocator::Initialize()
vtkm::cont::LogLevel::Info,
"CudaAllocator disabling managed memory due to NO_VTKM_MANAGED_MEMORY env variable");
}
// CUDA does not give any indication of whether it is still running, but we have found from
// experience that it finalizes itself during program termination. However, the user might
// have their own objects being cleaned up during termination after CUDA. We need a flag
// to catch if this happens after CUDA finalizes itself. We will set this flag to true now
// and false on termination. Because we are creating the atexit call here (after CUDA must
// have initialized itself), C++ will require our function that unsets the flag to happen
// before CUDA finalizes.
IsInitialized = true;
std::atexit([]() { IsInitialized = false; });
});
#endif
}
}
}

@ -9,30 +9,11 @@
##============================================================================
set(unit_tests
UnitTestCudaArrayHandle.cu
UnitTestCudaArrayHandleFancy.cu
UnitTestCudaArrayHandleMultiplexer.cu
UnitTestCudaBitField.cu
UnitTestCudaCellLocatorRectilinearGrid.cu
UnitTestCudaCellLocatorTwoLevel.cu
UnitTestCudaCellLocatorUniformGrid.cu
UnitTestCudaComputeRange.cu
UnitTestCudaColorTable.cu
UnitTestCudaDataSetExplicit.cu
UnitTestCudaDataSetSingleType.cu
UnitTestCudaDeviceAdapter.cu
UnitTestCudaImplicitFunction.cu
UnitTestCudaIterators.cu
UnitTestCudaMathEdgeCases.cu
UnitTestCudaShareUserProvidedManagedMemory.cu
UnitTestCudaPointLocatorSparseGrid.cu
UnitTestCudaRuntimeDeviceConfiguration.cu
)
if (NOT VTKm_NO_DEPRECATED_VIRTUAL)
set(unit_tests ${unit_tests}
UnitTestCudaVirtualObjectHandle.cu
)
endif()
vtkm_unit_tests(SOURCES ${unit_tests} LABEL "CUDA" LIBRARIES vtkm_worklet)
vtkm_unit_tests(SOURCES ${unit_tests} LABEL "CUDA" LIBRARIES vtkm_worklet BACKEND cuda)

@ -1,20 +0,0 @@
//============================================================================
// 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/cuda/DeviceAdapterCuda.h>
#include <vtkm/cont/testing/TestingArrayHandles.h>
int UnitTestCudaArrayHandle(int argc, char* argv[])
{
auto& tracker = vtkm::cont::GetRuntimeDeviceTracker();
tracker.ForceDevice(vtkm::cont::DeviceAdapterTagCuda{});
return vtkm::cont::testing::TestingArrayHandles<vtkm::cont::DeviceAdapterTagCuda>::Run(argc,
argv);
}

@ -1,23 +0,0 @@
//============================================================================
// 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/cuda/DeviceAdapterCuda.h>
#include <vtkm/cont/cuda/internal/testing/Testing.h>
#include <vtkm/cont/testing/TestingFancyArrayHandles.h>
int UnitTestCudaArrayHandleFancy(int argc, char* argv[])
{
auto& tracker = vtkm::cont::GetRuntimeDeviceTracker();
tracker.ForceDevice(vtkm::cont::DeviceAdapterTagCuda{});
int result = vtkm::cont::testing::TestingFancyArrayHandles<vtkm::cont::DeviceAdapterTagCuda>::Run(
argc, argv);
return vtkm::cont::cuda::internal::Testing::CheckCudaBeforeExit(result);
}

@ -1,20 +0,0 @@
//============================================================================
// 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/cuda/DeviceAdapterCuda.h>
#include <vtkm/cont/testing/TestingArrayHandleMultiplexer.h>
int UnitTestCudaArrayHandleMultiplexer(int argc, char* argv[])
{
auto& tracker = vtkm::cont::GetRuntimeDeviceTracker();
tracker.ForceDevice(vtkm::cont::DeviceAdapterTagCuda{});
return vtkm::cont::testing::TestingArrayHandleMultiplexer<vtkm::cont::DeviceAdapterTagCuda>::Run(
argc, argv);
}

@ -1,18 +0,0 @@
//============================================================================
// 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/cuda/DeviceAdapterCuda.h>
#include <vtkm/cont/testing/TestingBitField.h>
int UnitTestCudaBitField(int argc, char* argv[])
{
auto& tracker = vtkm::cont::GetRuntimeDeviceTracker();
tracker.ForceDevice(vtkm::cont::DeviceAdapterTagCuda{});
return vtkm::cont::testing::TestingBitField<vtkm::cont::DeviceAdapterTagCuda>::Run(argc, argv);
}

@ -1,19 +0,0 @@
//============================================================================
// 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/testing/TestingCellLocatorRectilinearGrid.h>
int UnitTestCudaCellLocatorRectilinearGrid(int argc, char* argv[])
{
auto& tracker = vtkm::cont::GetRuntimeDeviceTracker();
tracker.ForceDevice(vtkm::cont::DeviceAdapterTagCuda{});
return vtkm::cont::testing::Testing::Run(
TestingCellLocatorRectilinearGrid<vtkm::cont::DeviceAdapterTagCuda>(), argc, argv);
}

@ -1,19 +0,0 @@
//============================================================================
// 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/testing/TestingCellLocatorTwoLevel.h>
int UnitTestCudaCellLocatorTwoLevel(int argc, char* argv[])
{
auto& tracker = vtkm::cont::GetRuntimeDeviceTracker();
tracker.ForceDevice(vtkm::cont::DeviceAdapterTagCuda{});
return vtkm::cont::testing::Testing::Run(
TestingCellLocatorTwoLevel<vtkm::cont::DeviceAdapterTagCuda>, argc, argv);
}

@ -1,19 +0,0 @@
//============================================================================
// 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/testing/TestingCellLocatorUniformGrid.h>
int UnitTestCudaCellLocatorUniformGrid(int argc, char* argv[])
{
auto& tracker = vtkm::cont::GetRuntimeDeviceTracker();
tracker.ForceDevice(vtkm::cont::DeviceAdapterTagCuda{});
return vtkm::cont::testing::Testing::Run(
TestingCellLocatorUniformGrid<vtkm::cont::DeviceAdapterTagCuda>(), argc, argv);
}

@ -1,20 +0,0 @@
//============================================================================
// 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/cuda/DeviceAdapterCuda.h>
#include <vtkm/cont/testing/TestingColorTable.h>
int UnitTestCudaColorTable(int argc, char* argv[])
{
auto& tracker = vtkm::cont::GetRuntimeDeviceTracker();
tracker.ForceDevice(vtkm::cont::DeviceAdapterTagCuda{});
return vtkm::cont::testing::TestingColorTable<vtkm::cont::DeviceAdapterTagCuda>::Run(argc, argv);
}

Some files were not shown because too many files have changed in this diff Show More