diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 55467aa71..54a89bd29 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -105,16 +105,36 @@ extends: - .docker_image -.only-default: &only-default - only: - - master@vtk/vtk-m - - tags@vtk/vtk-m - - merge_requests +.ubuntu2004_hip_kokkos: &ubuntu2004_hip_kokkos + image: "kitware/vtkm:ci-ubuntu2004_hip_kokkos-20210827" + extends: + - .docker_image -.only-master: &only-master - only: - - master@vtk/vtk-m +.run_automatically: &run_automatically + rules: + - if: '$CI_MERGE_REQUEST_ID' + when: on_success + - if: '$CI_PROJECT_PATH == "vtk/vtk-m"' + when: on_success + - when: never +.run_scheduled: &run_scheduled + rules: + - if: '$CI_MERGE_REQUEST_ID' + when: manual + - if: '$CI_PROJECT_PATH == "vtk/vtk-m" && $CI_COMMIT_TAG' + when: on_success + - if: '$CI_PROJECT_PATH == "vtk/vtk-m" && $CI_PIPELINE_SOURCE == "schedule"' + when: on_success + - if: '$CI_PROJECT_PATH == "vtk/vtk-m"' + when: manual + - when: never + +.run_master: &run_master + rules: + - if: '$CI_PROJECT_PATH == "vtk/vtk-m" && $CI_COMMIT_BRANCH == "master"' + when: on_success + - when: never # General Longer Term Tasks: # - Setup clang tidy as sub-pipeline @@ -189,7 +209,7 @@ stages: before_script: - *install_cmake script: - - "ctest -VV -S .gitlab/ci/ctest_test.cmake" + - "ctest $CTEST_TIMEOUT -VV -S .gitlab/ci/ctest_test.cmake" artifacts: expire_in: 24 hours when: always diff --git a/.gitlab/ci/centos7.yml b/.gitlab/ci/centos7.yml index 6cff2b105..f07f38a29 100644 --- a/.gitlab/ci/centos7.yml +++ b/.gitlab/ci/centos7.yml @@ -12,7 +12,7 @@ build:centos7_gcc73: extends: - .centos7 - .cmake_build_linux - - .only-default + - .run_automatically - .use_minimum_supported_cmake variables: CMAKE_BUILD_TYPE: RelWithDebInfo @@ -30,7 +30,7 @@ test:centos7_gcc73: extends: - .centos7 - .cmake_test_linux - - .only-default + - .run_automatically dependencies: - build:centos7_gcc73 needs: @@ -47,7 +47,7 @@ test:rhel8_test_centos7: extends: - .rhel8 - .cmake_test_linux - - .only-default + - .run_automatically variables: CTEST_EXCLUSIONS: "built_against_test_install" dependencies: diff --git a/.gitlab/ci/centos8.yml b/.gitlab/ci/centos8.yml index 7b799b431..03ca9a583 100644 --- a/.gitlab/ci/centos8.yml +++ b/.gitlab/ci/centos8.yml @@ -10,7 +10,7 @@ build:centos8_sanitizer: extends: - .centos8 - .cmake_build_linux - - .only-default + - .run_automatically variables: CMAKE_BUILD_TYPE: RelWithDebInfo CMAKE_GENERATOR: "Unix Makefiles" @@ -26,7 +26,7 @@ test:centos8_sanitizer: extends: - .centos8 - .cmake_memcheck_linux - - .only-default + - .run_automatically variables: OMP_NUM_THREADS: 4 CTEST_MEMORYCHECK_TYPE: LeakSanitizer diff --git a/.gitlab/ci/config/gitlab_ci_setup.cmake b/.gitlab/ci/config/gitlab_ci_setup.cmake index 42a44b8a7..a6ce19e03 100644 --- a/.gitlab/ci/config/gitlab_ci_setup.cmake +++ b/.gitlab/ci/config/gitlab_ci_setup.cmake @@ -63,11 +63,25 @@ if("$ENV{VTKM_CI_NIGHTLY}" STREQUAL "TRUE") set(CTEST_TRACK "Nightly") endif() -if (CTEST_CMAKE_GENERATOR STREQUAL "Unix Makefiles") +# In Make, default parallelism to number of cores. +if(CTEST_CMAKE_GENERATOR STREQUAL "Unix Makefiles") include(ProcessorCount) ProcessorCount(nproc) + + if(DEFINED ENV{CTEST_MAX_PARALLELISM}) + if(nproc GREATER $ENV{CTEST_MAX_PARALLELISM}) + set(nproc $ENV{CTEST_MAX_PARALLELISM}) + endif() + endif() + set(CTEST_BUILD_FLAGS "-j${nproc}") -endif () +endif() + +# In Ninja, we do not need to specify parallelism unless we need to restrict +# the number of threads. +if(CTEST_CMAKE_GENERATOR STREQUAL "Ninja" AND DEFINED ENV{CTEST_MAX_PARALLELISM}) + set(CTEST_BUILD_FLAGS "-j$ENV{CTEST_MAX_PARALLELISM}") +endif() if(DEFINED ENV{CTEST_MEMORYCHECK_TYPE}) set(env_value "$ENV{CTEST_MEMORYCHECK_TYPE}") diff --git a/.gitlab/ci/config/initial_config.cmake b/.gitlab/ci/config/initial_config.cmake index f3c5859c1..f20eac906 100644 --- a/.gitlab/ci/config/initial_config.cmake +++ b/.gitlab/ci/config/initial_config.cmake @@ -56,6 +56,9 @@ foreach(option IN LISTS options) elseif(use_virtuals STREQUAL option) set(VTKm_NO_DEPRECATED_VIRTUAL "OFF" CACHE STRING "") + elseif(no_testing STREQUAL option) + set(VTKm_ENABLE_TESTING OFF CACHE BOOL "") + elseif(examples STREQUAL option) set(VTKm_ENABLE_EXAMPLES "ON" CACHE STRING "") @@ -64,7 +67,7 @@ foreach(option IN LISTS options) elseif(benchmarks STREQUAL option) set(VTKm_ENABLE_BENCHMARKS "ON" CACHE STRING "") - set(ENV{CMAKE_PREFIX_PATH} "$ENV{HOME}/gbench") + set(ENV{CMAKE_PREFIX_PATH} "$ENV{CMAKE_PREFIX_PATH}:$ENV{HOME}/gbench") elseif(mpi STREQUAL option) set(VTKm_ENABLE_MPI "ON" CACHE STRING "") @@ -95,6 +98,16 @@ foreach(option IN LISTS options) elseif(turing STREQUAL option) set(VTKm_CUDA_Architecture "turing" CACHE STRING "") + + elseif(hip STREQUAL option) + if(CMAKE_VERSION VERSION_LESS_EQUAL 3.20) + message(FATAL_ERROR "VTK-m requires cmake > 3.20 to enable HIP support") + endif() + + set(CMAKE_C_COMPILER "/opt/rocm/llvm/bin/clang" CACHE FILEPATH "") + set(CMAKE_CXX_COMPILER "/opt/rocm/llvm/bin/clang++" CACHE FILEPATH "") + set(VTKm_ENABLE_KOKKOS_HIP ON CACHE STRING "") + set(CMAKE_HIP_ARCHITECTURES "gfx900" CACHE STRING "") endif() endforeach() @@ -109,6 +122,10 @@ if(SCCACHE_COMMAND) set(CMAKE_C_COMPILER_LAUNCHER "${SCCACHE_COMMAND}" CACHE STRING "") set(CMAKE_CXX_COMPILER_LAUNCHER "${SCCACHE_COMMAND}" CACHE STRING "") + if(DEFINED VTKm_ENABLE_KOKKOS_HIP) + set(CMAKE_HIP_COMPILER_LAUNCHER "${SCCACHE_COMMAND}" CACHE STRING "") + endif() + # Use VTKm_CUDA_Architecture to determine if we need CUDA sccache setup # since this will also capture when kokkos is being used with CUDA backing if(DEFINED VTKm_CUDA_Architecture) diff --git a/.gitlab/ci/docker/ubuntu2004/kokkos-hip/Dockerfile b/.gitlab/ci/docker/ubuntu2004/kokkos-hip/Dockerfile new file mode 100644 index 000000000..03521a2ba --- /dev/null +++ b/.gitlab/ci/docker/ubuntu2004/kokkos-hip/Dockerfile @@ -0,0 +1,43 @@ +FROM rocm/dev-ubuntu-20.04 +LABEL maintainer "Vicente Adolfo Bolea Sanchez" + +# Base dependencies for building VTK-m projects +RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + cmake \ + curl \ + g++ \ + git \ + git-lfs \ + libmpich-dev \ + libomp-dev \ + mpich \ + ninja-build \ + rsync \ + ssh \ + software-properties-common + +# Need to run git-lfs install manually on ubuntu based images when using the +# system packaged version +RUN git-lfs install + +# Provide CMake +ARG CMAKE_VERSION=3.21.1 +RUN mkdir /opt/cmake/ && \ + curl -L https://github.com/Kitware/CMake/releases/download/v$CMAKE_VERSION/cmake-$CMAKE_VERSION-Linux-x86_64.sh > cmake-$CMAKE_VERSION-Linux-x86_64.sh && \ + sh cmake-$CMAKE_VERSION-Linux-x86_64.sh --prefix=/opt/cmake/ --exclude-subdir --skip-license && \ + rm cmake-$CMAKE_VERSION-Linux-x86_64.sh && \ + ln -s /opt/cmake/bin/ctest /opt/cmake/bin/ctest-latest + +ENV PATH "/opt/cmake/bin:${PATH}" +ENV CMAKE_PREFIX_PATH "/opt/rocm/lib/cmake:/opt/rocm/lib:${CMAKE_PREFIX_PATH}" +ENV CMAKE_GENERATOR "Ninja" + +# Build and install Kokkos +ARG KOKKOS_VERSION=3.4.01 +COPY kokkos_cmake_config.cmake kokkos_cmake_config.cmake +RUN curl -L https://github.com/kokkos/kokkos/archive/refs/tags/$KOKKOS_VERSION.tar.gz | tar -xzf - && \ + cmake -S kokkos-$KOKKOS_VERSION -B build -C kokkos_cmake_config.cmake && \ + cmake --build build -v && \ + sudo cmake --install build + +RUN rm -rf build diff --git a/.gitlab/ci/docker/ubuntu2004/kokkos-hip/kokkos_cmake_config.cmake b/.gitlab/ci/docker/ubuntu2004/kokkos-hip/kokkos_cmake_config.cmake new file mode 100644 index 000000000..7b71f7b65 --- /dev/null +++ b/.gitlab/ci/docker/ubuntu2004/kokkos-hip/kokkos_cmake_config.cmake @@ -0,0 +1,21 @@ +##============================================================================ +## 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. +##============================================================================ + +set(CMAKE_BUILD_TYPE "release" CACHE STRING "") +set(CMAKE_INSTALL_PREFIX /opt/kokkos CACHE PATH "") +set(CMAKE_C_COMPILER /opt/rocm/llvm/bin/clang CACHE FILEPATH "") +set(CMAKE_CXX_COMPILER /opt/rocm/llvm/bin/clang++ CACHE FILEPATH "") +set(CMAKE_CXX_STANDARD "14" CACHE STRING "") +set(CMAKE_POSITION_INDEPENDENT_CODE ON CACHE BOOL "") + +set(Kokkos_ENABLE_SERIAL ON CACHE BOOL "") +set(Kokkos_ARCH_VEGA900 ON CACHE BOOL "") +set(Kokkos_ENABLE_HIP ON CACHE BOOL "") +set(Kokkos_ENABLE_HIP_RELOCATABLE_DEVICE_CODE OFF CACHE BOOL "") diff --git a/.gitlab/ci/rhel8.yml b/.gitlab/ci/rhel8.yml index 136bf8bde..75c795acb 100644 --- a/.gitlab/ci/rhel8.yml +++ b/.gitlab/ci/rhel8.yml @@ -10,7 +10,7 @@ build:rhel8: extends: - .rhel8 - .cmake_build_linux - - .only-default + - .run_automatically variables: CMAKE_GENERATOR: "Unix Makefiles" VTKM_SETTINGS: "serial+shared+64bit_floats+32bit_ids+use_virtuals" @@ -24,7 +24,7 @@ test:rhel8: extends: - .rhel8 - .cmake_test_linux - - .only-default + - .run_automatically dependencies: - build:rhel8 needs: @@ -41,7 +41,7 @@ build:rhel8_vtk_types: extends: - .rhel8 - .cmake_build_linux - - .only-default + - .run_automatically variables: CMAKE_GENERATOR: "Unix Makefiles" VTKM_SETTINGS: "serial+vtk_types" @@ -55,7 +55,7 @@ test:rhel8_vtk_types: extends: - .rhel8 - .cmake_test_linux - - .only-default + - .run_automatically dependencies: - build:rhel8_vtk_types needs: diff --git a/.gitlab/ci/ubuntu1604.yml b/.gitlab/ci/ubuntu1604.yml index 477f891cd..5ac715e6b 100644 --- a/.gitlab/ci/ubuntu1604.yml +++ b/.gitlab/ci/ubuntu1604.yml @@ -12,7 +12,7 @@ build:ubuntu1604_gcc5: extends: - .ubuntu1604_cuda - .cmake_build_linux - - .only-default + - .run_automatically - .use_minimum_supported_cmake variables: CC: "gcc-5" @@ -31,7 +31,7 @@ test:ubuntu1604_gcc5: extends: - .ubuntu1604_cuda - .cmake_test_linux - - .only-default + - .run_automatically dependencies: - build:ubuntu1604_gcc5 needs: @@ -50,7 +50,7 @@ build:ubuntu1604_gcc5_2: extends: - .ubuntu1604_cuda - .cmake_build_linux - - .only-master + - .run_master - .use_minimum_supported_cmake variables: CC: "gcc-5" @@ -69,7 +69,7 @@ test:ubuntu1804_test_ubuntu1604_gcc5_2: extends: - .ubuntu1804_cuda - .cmake_test_linux - - .only-master + - .run_master variables: CTEST_EXCLUSIONS: "built_against_test_install" dependencies: @@ -88,7 +88,7 @@ build:ubuntu1604_clang5: extends: - .ubuntu1604 - .cmake_build_linux - - .only-default + - .run_automatically - .use_minimum_supported_cmake variables: CC: "clang-5.0" @@ -105,7 +105,7 @@ test:ubuntu1604_clang5: extends: - .ubuntu1604 - .cmake_test_linux - - .only-default + - .run_automatically dependencies: - build:ubuntu1604_clang5 needs: diff --git a/.gitlab/ci/ubuntu1804.yml b/.gitlab/ci/ubuntu1804.yml index 9e09a612e..486932d9d 100644 --- a/.gitlab/ci/ubuntu1804.yml +++ b/.gitlab/ci/ubuntu1804.yml @@ -11,7 +11,7 @@ build:ubuntu1804_gcc9: extends: - .ubuntu1804 - .cmake_build_linux - - .only-default + - .run_automatically variables: CC: "gcc-9" CXX: "g++-9" @@ -27,7 +27,7 @@ test:ubuntu1804_gcc9: extends: - .ubuntu1804 - .cmake_test_linux - - .only-default + - .run_automatically variables: #Restrict OpenMP number of threads since multiple test stages #execute on the same hardware concurrently @@ -51,7 +51,7 @@ build:ubuntu1804_gcc7: extends: - .ubuntu1804_cuda - .cmake_build_linux - - .only-default + - .run_automatically variables: CC: "gcc-7" CXX: "g++-7" @@ -69,7 +69,7 @@ test:ubuntu1804_gcc7: extends: - .ubuntu1804_cuda - .cmake_test_linux - - .only-default + - .run_automatically dependencies: - build:ubuntu1804_gcc7 needs: @@ -90,8 +90,8 @@ build:ubuntu1804_clang_cuda: extends: - .ubuntu1804_cuda - .cmake_build_linux - - .only-default - # - .only-master + - .run_automatically + # - .run_master variables: CC: "clang-8" CXX: "clang++-8" @@ -109,8 +109,8 @@ test:ubuntu1804_clang_cuda: extends: - .ubuntu1804_cuda - .cmake_test_linux - - .only-default - # - .only-master + - .run_automatically + # - .run_master dependencies: - build:ubuntu1804_clang_cuda needs: @@ -127,7 +127,7 @@ build:ubuntu1804_gcc6: extends: - .ubuntu1804 - .cmake_build_linux - - .only-default + - .run_automatically variables: CC: "gcc-6" CXX: "g++-6" @@ -142,7 +142,7 @@ test:ubuntu1804_gcc6: extends: - .ubuntu1804 - .cmake_test_linux - - .only-default + - .run_automatically variables: #Restrict OpenMP number of threads since multiple test stages #execute on the same hardware concurrently @@ -163,7 +163,7 @@ build:ubuntu1804_clang8: extends: - .ubuntu1804 - .cmake_build_linux - - .only-default + - .run_automatically variables: CC: "clang-8" CXX: "clang++-8" @@ -179,7 +179,7 @@ test:ubuntu1804_clang8: extends: - .ubuntu1804 - .cmake_test_linux - - .only-default + - .run_automatically dependencies: - build:ubuntu1804_clang8 needs: @@ -198,7 +198,7 @@ build:ubuntu1804_kokkos: extends: - .ubuntu1804_cuda_kokkos - .cmake_build_linux - - .only-default + - .run_automatically variables: CMAKE_GENERATOR: "Ninja" CMAKE_BUILD_TYPE: Release @@ -215,7 +215,7 @@ test:ubuntu1804_kokkos: extends: - .ubuntu1804_cuda_kokkos - .cmake_test_linux - - .only-default + - .run_automatically dependencies: - build:ubuntu1804_kokkos needs: diff --git a/.gitlab/ci/ubuntu2004.yml b/.gitlab/ci/ubuntu2004.yml index bed966203..ad7aded76 100644 --- a/.gitlab/ci/ubuntu2004.yml +++ b/.gitlab/ci/ubuntu2004.yml @@ -7,7 +7,7 @@ build:ubuntu2004_gcc9: extends: - .ubuntu2004 - .cmake_build_linux - - .only-default + - .run_automatically variables: CMAKE_BUILD_TYPE: Debug VTKM_SETTINGS: "benchmarks+tbb+openmp+mpi+shared+hdf5" @@ -21,7 +21,7 @@ test:ubuntu2004_gcc9: extends: - .ubuntu2004 - .cmake_test_linux - - .only-default + - .run_automatically variables: #Restrict OpenMP number of threads since multiple test stages #execute on the same hardware concurrently @@ -40,7 +40,7 @@ build:ubuntu2004_kokkos: extends: - .ubuntu2004_kokkos - .cmake_build_linux - - .only-default + - .run_automatically variables: CMAKE_BUILD_TYPE: RelWithDebInfo VTKM_SETTINGS: "kokkos+shared+64bit_floats" @@ -54,8 +54,43 @@ test:ubuntu2004_kokkos: extends: - .ubuntu2004_kokkos - .cmake_test_linux - - .only-default + - .run_automatically dependencies: - build:ubuntu2004_kokkos needs: - build:ubuntu2004_kokkos + +build:ubuntu2004_hip_kokkos: + tags: + - build + - vtkm + - docker + - radeon + extends: + - .ubuntu2004_hip_kokkos + - .cmake_build_linux + - .run_scheduled + variables: + CMAKE_BUILD_TYPE: RelWithDebInfo + VTKM_SETTINGS: "benchmarks+kokkos+hip+no_virtual+no_rendering" + CMAKE_PREFIX_PATH: "/opt/rocm/lib/cmake" + CTEST_MAX_PARALLELISM: "1" + timeout: 12 hours + +test:ubuntu2004_hip_kokkos: + tags: + - build + - vtkm + - docker + - radeon + extends: + - .ubuntu2004_hip_kokkos + - .cmake_test_linux + - .run_automatically + variables: + CTEST_TIMEOUT: "30" + dependencies: + - build:ubuntu2004_hip_kokkos + needs: + - build:ubuntu2004_hip_kokkos + timeout: 3 hours diff --git a/.gitlab/ci/windows10.yml b/.gitlab/ci/windows10.yml index e0f4462e6..9955d6a54 100644 --- a/.gitlab/ci/windows10.yml +++ b/.gitlab/ci/windows10.yml @@ -93,7 +93,7 @@ build:windows_vs2019: - large-memory extends: - .cmake_build_windows - - .only-default + - .run_automatically variables: CMAKE_GENERATOR: "Ninja" CMAKE_BUILD_TYPE: Release @@ -114,7 +114,7 @@ test:windows_vs2019: - turing extends: - .cmake_test_windows - - .only-default + - .run_automatically dependencies: - build:windows_vs2019 needs: diff --git a/LICENSE.txt b/LICENSE.txt index a30962aa7..5a210aca2 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,4 +1,4 @@ -VTKm License Version 1.6 +VTKm License Version 1.7 ======================================================================== Copyright (c) 2014-2021 diff --git a/Utilities/CI/reproduce_ci_env.py b/Utilities/CI/reproduce_ci_env.py index 1792006ce..0abdc581e 100755 --- a/Utilities/CI/reproduce_ci_env.py +++ b/Utilities/CI/reproduce_ci_env.py @@ -200,9 +200,9 @@ def create_container(ci_file_path, *args): script_search_locations = [ci_state, subset, runner] for loc in script_search_locations: if 'before_script' in loc: - before_script = loc['before_script'] + before_script = [command.strip() for command in loc['before_script']] if 'script' in loc: - script = loc['script'] + script = [command.strip() for command in loc['script']] docker_template = string.Template(''' FROM $image @@ -223,10 +223,10 @@ RUN echo "$before_script" >> /setup-gitlab-env.sh && \ job_name='local-build'+runner_name, src_dir=src_dir, gitlab_env= " ".join(gitlab_env), - before_script="\n".join(before_script) - .replace('\n', '\\n\\\n') + before_script=" && ".join(before_script) + .replace('\n', ' && ') .replace('"', '\\"'), - script="\n".join(script).replace('\n', '\\n\\\n') + script=" && ".join(script).replace('\n', ' && ') .replace('"', '\\"')) # Write out the file diff --git a/benchmarking/Benchmarker.h b/benchmarking/Benchmarker.h index 6e2bc9733..deefe3bb2 100644 --- a/benchmarking/Benchmarker.h +++ b/benchmarking/Benchmarker.h @@ -10,7 +10,7 @@ #ifndef vtk_m_benchmarking_Benchmarker_h #define vtk_m_benchmarking_Benchmarker_h - +#include #include #include #include diff --git a/docs/changelog/1.7/release-notes.md b/docs/changelog/1.7/release-notes.md new file mode 100644 index 000000000..7eab5e630 --- /dev/null +++ b/docs/changelog/1.7/release-notes.md @@ -0,0 +1,437 @@ +VTK-m 1.7 Release Notes +======================= + +# Table of Contents +1. [Core](#Core) + - Add ability to convert fields to known types + - Consolidate count-to-offset algorithms + - Make field names from sources more descriptive +2. [ArrayHandle](#ArrayHandle) + - Added `ArrayCopyShallowIfPossible` + - Added copy methods to `UnknownArrayHandle` + - Allow a `const ArrayHandle` to be reallocated + - Compile `ArrayGetValues` implementation in a library + - Deprecated `VariantArrayHandle` + - Improve type reporting in `UnknownArrayHandle` +[4](4). [Control Environment](#Control-Environment) + - Compile reverse connectivity builder into vtkm_cont library +5. [Execution Environment](#Execution-Environment) + - Remove unbounded recursion +6. [Worklets and Filters](#Worklets-and-Filters) + - [GenerateIds](GenerateIds) filter + - Support scatter/mask for CellSetExtrude + - Adding ability to use cell-centered velocity fields for particle advection + - Probe always generates point fields +7. [Build](#Build) + - Filters instantiation generator + - Move .cxx from DEVICE_SOURCES to SOURCES in vktm IO library +8. [Other](#Other) + - Enable `TypeToString` for `type_info` + - Skip library versions + - Support writing binary files to legacy VTK files + +# Core + +## Add ability to convert fields to known types ## + +In VTK-m we have a constant tension between minimizing the number of +types we have to compile for (to reduce compile times and library size) +and maximizing the number of types that our filters support. +Unfortunately, if you don't compile a filter for a specific array type +(value type and storage), trying to run that filter will simply fail. + +To compromise between the two, added methods to `DataSet` and `Field` +that will automatically convert the data in the `Field` arrays to a type +that VTK-m will understand. Although this will cause an extra data copy, +it will at least prevent the program from failing, and thus make it more +feasible to reduce types. + +## Consolidate count-to-offset algorithms ## + +For no particularly good reason, there were two functions that converted +and array of counts to an array of offsets: `ConvertNumComponentsToOffsets` +and `ConvertNumIndicesToOffsets`. These functions were identical, except +one was defined in `ArrayHandleGroupVecVariable.h` and the other was +defined in `CellSetExplicit.h`. + +These two functions have been consolidated into one (which is now called +`ConvertNumComponentsToOffsets`). The consolidated function has also been +put in its own header file: `ConvertNumComponentsToOffsets.h`. + +Normally, backward compatibility would be established using deprecated +features. However, one of the things being worked on is the removal of +device-specific code (e.g. `vtkm::cont::Algorithm`) from core classes like +`CellSetExplicit` so that less code needs to use the device compiler +(especially downstream code). + +`ConvertNumComponentsToOffsets` has also been changed to provide a +pre-compiled version for common arrays. This helps with the dual goals of +compiling less device code and allowing data set builders to not have to +use the device compiler. For cases where you need to compile +`ConvertNumComponentsToOffsets` for a different kind of array, you can use +the internal `ConvertNumComponentsToOffsetsTemplate`. + +Part of this change removed unnecessary includes of `Algorithm.h` in +`ArrayHandleGroupVecVariable.h` and `CellSetExplicit.h`. This header had to +be added to some classes that were not including it themselves. + +## Make field names from sources more descriptive ## + +The VTK-m sources (like `Oscillator`, `Tangle`, and `Wavelet`) were all +creating fields with very generic names like `pointvar` or `scalars`. These +are very unhelpful names as it is impossible for downstream processes to +identify the meaning of these fields. Imagine having these data saved to a +file and then a different person trying to identify what they mean. Or +imagine dealing with more than one such source at a time and trying to +manage fields with similar or overlapping names. + +The following renames happened: + + * `Oscillator`: `scalars` -> `oscillating` + * `Tangle`: `pointvar` -> `tangle` + * `Wavelet`: `scalars` -> `RTData` (matches VTK source) + +# ArrayHandle + +## Added `ArrayCopyShallowIfPossible` ## + +Often times you have an array of an unknown type (likely from a data set), +and you need it to be of a particular type (or can make a reasonable but +uncertain assumption about it being a particular type). You really just +want a shallow copy (a reference in a concrete `ArrayHandle`) if that is +possible. + +`ArrayCopyShallowIfPossible` pulls an array of a specific type from an +`UnknownArrayHandle`. If the type is compatible, it will perform a shallow +copy. If it is not possible, a deep copy is performed to get it to the +correct type. + +## Added copy methods to `UnknownArrayHandle` ## + +`vtkm::cont::UnknownArrayHandle` now provides a set of method that allows +you to copy data from one `UnknownArrayHandle` to another. The first +method, `DeepCopyFrom`, takes a source `UnknownArrayHandle` and deep copies +the data to the called one. If the `UnknownArrayHandle` already points to a +real `ArrayHandle`, the data is copied into that `ArrayHandle`. If the +`UnknownArrayHandle` does not point to an existing `ArrayHandle`, then a +new `ArrayHandleBasic` with the same value type as the source is created +and copied into. + +The second method, `CopyShallowIfPossibleFrom` behaves similarly to +`DeepCopyFrom` except that it will perform a shallow copy if possible. That +is, if the target `UnknownArrayHandle` points to an `ArrayHandle` of the +same type as the source `UnknownArrayHandle`, then a shallow copy occurs +and the underlying `ArrayHandle` will point to the source. If the types +differ, then a deep copy is performed. If the target `UnknownArrayHandle` +does not point to an `ArrayHandle`, then the behavior is the same as the +`=` operator. + +One of the intentions of these new methods is to allow you to copy arrays +without using a device compiler (e.g. `nvcc`). Calling `ArrayCopy` requires +you to include the `ArrayCopy.h` header file, and that in turn requires +device adapter algorithms. These methods insulate you from these. + +## Allow a `const ArrayHandle` to be reallocated ## + +Previously, the `Allocate` method of `ArrayHandle` was _not_ declared as +`const`. Likewise, the methods that depended on `Allocate`, namely +`ReleaseResources` and `PrepareForOutput` were also not declared `const`. +The main consequence of this was that if an `ArrayHandle` were passed as a +constant reference argument to a method (e.g. `const ArrayHandle& arg`), +then the array could not be reallocated. + +This seems right at first blush. However, we have changed these methods to +be `const` so that you can in fact reallocate the `ArrayHandle`. This is +because the `ArrayHandle` is in principle a pointer to an array pointer. +Such a structure in C will allow you to change the pointer to the array, +and so in this context it makes sense for `ArrayHandle` to support that as +well. + +Although this distinction will certainly be confusing to users, we think +this change is correct for a variety of reasons. + + 1. This change makes the behavior of `ArrayHandle` consistent with the + behavior of `UnknownArrayHandle`. The latter needed this behavior to + allow `ArrayHandle`s to be passed as output arguments to methods that + get automatically converted to `UnknownArrayHandle`. + 2. Before this change, a `const ArrayHandle&` was still multible is many + way. In particular, it was possible to change the data in the array + even if the array could not be resized. You could still call things + like `WritePortal` and `PrepareForInOut`. The fact that you could + change it for some things and not others was confusing. The fact that + you could call `PrepareForInOut` but not `PrepareForOutput` was doubly + confusing. + 3. Passing a value by constant reference should be the same, from the + calling code's perspective, as passing by value. Although the function + can change an argument passed by value, that change is not propogated + back to the calling code. However, in the case of `ArrayHandle`, + calling by value would allow the array to be reallocated from the + calling side whereas a constant reference would prevent that. This + change makes the two behaviors consistent. + 4. The supposed assurance that the `ArrayHandle` would not be reallocated + was easy to break even accidentally. If the `ArrayHandle` was assigned + to another `ArrayHandle` (for example as a class' member or wrapped + inside of an `UnknownArrayHandle`), then the array was free to be + reallocated. + +## Compile `ArrayGetValues` implementation in a library ## + +Previously, all of the `ArrayGetValue` implementations were templated +functions that had to be built by all code that used it. That had 2 +negative consequences. + +1. The same code that scheduled jobs on any device had to be compiled many + times over. +2. Any code that used `ArrayGetValue` had to be compiled with a device + compiler. If you had non-worklet code that just wanted to get a single + value out of an array, that was a pain. + +To get around this problem, an `ArrayGetValues` function that takes +`UnknownArrayHandle`s was created. The implementation for this function is +compiled into a library. It uses `UnknownArrayHandle`'s ability to extract +a component of the array with a uniform type to reduce the number of code +paths it generates. Although there are still several code paths, they only +have to be computed once. Plus, now any code can include `ArrayGetValues.h` +and still use a basic C++ compiler. + +## Deprecated `VariantArrayHandle` ## + +`VaraintArrayHandle` has been replaced by `UnknownArrayHandle` and +`UncertainArrayHandle`. Officially made `VariantArrayHandle` deprecated and +point users to the new implementations. + +## Improve type reporting in `UnknownArrayHandle` ## + +Added features with reporting types with `UnknownArrayHandle`. First, added +a method named `GetArrayTypeName` that returns a string containing the type +of the contained array. There were already methods `GetValueType` and +`GetStorageType`, but this provides a convenience to get the whole name in +one go. + +Also improved the reporting when an `AsArrayHandle` call failed. Before, +the thrown method just reported that the `UnknownArrayHandle` could not be +converted to the given type. Now, it also reports the type actually held by +the `UnknownArrayHandle` so the user can better understand why the +conversion failed. + +# Control Environment + +## Compile reverse connectivity builder into vtkm_cont library ## + +Because `CellSetExplicit` is a templated class, the implementation of +most of its features is part of the header files. One of the things that +was included was the code to build the reverse connectivity links. That +is, it figured out which cells were incident on each point using the +standard connections of which points comprise which cells. + +Of course, building these links is non-trivial, and it used multiple +DPPs to engage the device. It meant that header had to include the +device adapter algorithms and therefore required a device compiler. We +want to minimize this where possible. + +To get around this issue, a non-templated function was added to find the +reverse connections of a `CellSetExplicit`. It does this by passing in +`UnknownArrayHandle`s for the input arrays. (The output visit-points- +with-cells arrays are standard across all template instances.) The +implementation first iterates over all `CellSetExplicit` versions in +`VTKM_DEFAULT_CELL_SETS` and attempts to retrieve arrays of those types. +In the unlikely event that none of these arrays work, it copies the data +to `ArrayHandle` and uses those. + +# Execution Environment + +## Remove unbounded recursion ## + +GPU device compilers like to determine the stack size needed for a called +kernel. This is only possible if there is no recursive function calls on +the device or at least recursive calls where the termination cannot be +found at compile time. + +Device compilers do not particularly like that. We have been getting around +this with CUDA by turning of warnings about stack sizes and setting a large +stack size during a call (which works but is dangerous). More restrictive +devices might not allow recursive calls at all. + +To fix this, we will avoid recursive calls in execution environment +(device) code. All such warnings are turned on. + +Because of this, we also should not have to worry about lengthening the +stack size, so that code is also removed. + +# Worklets and Filters + +## GenerateIds filter ## + +This filter adds a pair of fields to a `DataSet` which mirror the +indices of the points and cells, respectively. These fields are useful +for tracking the provenance of the elements of a `DataSet` as it gets +manipulated by the filters. It is also convenient for adding indices to +operations designed for fields and for testing purposes. + +## Support scatter/mask for CellSetExtrude ## + +Scheduling topology map workets for `CellSetExtrude` always worked, but the +there were indexing problems when a `Scatter` or a `Mask` was used. This +has been corrected, and now `Scatter`s and `Mask`s are supported on +topology maps on `CellSetExtrude`. + +## Adding ability to use cell-centered velocity fields for particle advection ## + +Vector fields for particle advection are not always nodal,; e.g., AMR-Wind uses +zonal vector fields to store velocity information. Previously, VTK-m filters +only supported particle advection in nodal vector fields. With this change, VTK-m +will support zonal vector fields. Users do not need to worry about changing the +way they specify inputs to the flow visualization filters. However, if users use +the particle advection worklets, they'll need to specify the associativity for +their vector fields. + +## Probe always generates point fields ## + +Previously, the `probe` filter, when probing the input's cell fields, would +store the result as the output's cell field. This is a bug since the probing is +done at the geometry's point locations, and the output gets its structure from +the `geometry`. + +This behaviour is fixed in this release. Now, irrespective of the type of the +input field being probed, the result field is always a point field. + +``` +vtkm::cont::Field field = dataset.GetField("velocity"); +vtkm::cont::Field::Association assoc = field.GetAssociation(); + +using FieldArray = vtkm::cont::ArrayHandle; +using FieldType = vtkm::worklet::particleadvection::VelocityField; + +FieldArray data; +field.GetData().AsArrayHandle(data); + +// Use this field to pass to the GridEvaluators +FieldType velocities(data, assoc); +``` + +# Build + +## Filters instantiation generator ## + +It introduces a template instantiation generator. This aims to significantly +reduce the memory usage when building _VTK-m_ filter by effectively splitting +templates instantiations across multiple files. + +How this works revolves around automatically instantiating filters template +methods inside transient instantiation files which resides solely in the build +directory. Each of those transient files contains a single explicit template +instantiation. + +Here is an example of how to produce an instantiation file. + +First, at the filter header file: + +```c++ + +// 1. Include Instantiations header +#include + +class Contour { + template + vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet&, + const vtkm::cont::ArrayHandle&, + const vtkm::filter::FieldMetadata&, + vtkm::filter::PolicyBase); +}; + +// 2. Create extern template instantiation and surround with +// VTKM_INSTANTIATION_{BEGIN,END} +VTKM_INSTANTIATION_BEGIN +extern template vtkm::cont::DataSet Contour::DoExecute( + const vtkm::cont::DataSet&, + const vtkm::cont::ArrayHandle&, + const vtkm::filter::FieldMetadata&, + vtkm::filter::PolicyBase); +VTKM_INSTANTIATION_END + +``` + +Later, in its corresponding `CMakeLists.txt` file: + +```cmake + +vtkm_add_instantiations(ContourInstantiations FILTER Contour) +vtkm_library( + NAME vtkm_filter_contour + ... + DEVICE_SOURCES ${ContourInstantiations} + ) + +``` + +After running the configure step in _CMake_, this will result in the creation of +the following transient file in the build directory: + +```c++ + +#ifndef vtkm_filter_ContourInstantiation0_cxx +#define vtkm_filter_ContourInstantiation0_cxx +#endif + +/* Needed for linking errors when no instantiations */ +int __vtkm_filter_ContourInstantiation0_cxx; + +#include +#include + +namespace vtkm +{ +namespace filter +{ + +template vtkm::cont::DataSet Contour::DoExecute( + const vtkm::cont::DataSet&, + const vtkm::cont::ArrayHandle&, + const vtkm::filter::FieldMetadata&, + vtkm::filter::PolicyBase); + +} +} + +#undef vtkm_filter_ContourInstantiation0_cxx + +``` +## Move .cxx from DEVICE_SOURCES to SOURCES in vktm io library ## + +It used to be that every .cxx file which uses ArrayHandle needs to be compiled +by the device compiler. A recent change had removed this restriction. +One exception is that user of ArrayCopy still requires device compiler. +Since most .cxx files in vtkm/io do not use ArrayCopy, they are moved +to SOURCES and are compiled by host compiler. + +# Other + +## Enable `TypeToString` for `type_info` ## + +VTK-m contains a helpful method named `vtkm::cont::TypeToString` that +either takes a type as a template argument or a `std::type_info` object and +returns a human-readable string for that type. + +The standard C++ library has an alternate for `std::type_info` named +`std::type_index`, which has the added ability to be used in a container +like `set` or `map`. The `TypeToString` overloads have been extended to +also accept a `std::type_info` and report the name of the type stored in it +(rather than the name of `type_info` itself). + + +## skip library versions ## + +The `VTKm_SKIP_LIBRARY_VERSIONS` variable is now available to skip the SONAME +and SOVERSION fields (or the equivalent for non-ELF platforms). + +Some deployments (e.g., Python wheels or Java `.jar` files) do not support +symlinks reliably and the way the libraries get loaded just leads to +unnecessary files in the packaged artifact. + +## Support writing binary files to legacy VTK files ## + +The legacy VTK file writer writes out in ASCII. This is helpful when a +human is trying to read the file. However, if you have more than a +trivial amount of data, the file can get impractically large. To get +around this, `VTKDataSetWriter` now has a flag that allows you to write +the data in binary format. diff --git a/docs/changelog/arrayhandle-mutable.const.md b/docs/changelog/arrayhandle-mutable.const.md deleted file mode 100644 index 9581fa4c9..000000000 --- a/docs/changelog/arrayhandle-mutable.const.md +++ /dev/null @@ -1,42 +0,0 @@ -# Allow a `const ArrayHandle` to be reallocated - -Previously, the `Allocate` method of `ArrayHandle` was _not_ declared as -`const`. Likewise, the methods that depended on `Allocate`, namely -`ReleaseResources` and `PrepareForOutput` were also not declared `const`. -The main consequence of this was that if an `ArrayHandle` were passed as a -constant reference argument to a method (e.g. `const ArrayHandle& arg`), -then the array could not be reallocated. - -This seems right at first blush. However, we have changed these methods to -be `const` so that you can in fact reallocate the `ArrayHandle`. This is -because the `ArrayHandle` is in principle a pointer to an array pointer. -Such a structure in C will allow you to change the pointer to the array, -and so in this context it makes sense for `ArrayHandle` to support that as -well. - -Although this distinction will certainly be confusing to users, we think -this change is correct for a variety of reasons. - - 1. This change makes the behavior of `ArrayHandle` consistent with the - behavior of `UnknownArrayHandle`. The latter needed this behavior to - allow `ArrayHandle`s to be passed as output arguments to methods that - get automatically converted to `UnknownArrayHandle`. - 2. Before this change, a `const ArrayHandle&` was still multible is many - way. In particular, it was possible to change the data in the array - even if the array could not be resized. You could still call things - like `WritePortal` and `PrepareForInOut`. The fact that you could - change it for some things and not others was confusing. The fact that - you could call `PrepareForInOut` but not `PrepareForOutput` was doubly - confusing. - 3. Passing a value by constant reference should be the same, from the - calling code's perspective, as passing by value. Although the function - can change an argument passed by value, that change is not propogated - back to the calling code. However, in the case of `ArrayHandle`, - calling by value would allow the array to be reallocated from the - calling side whereas a constant reference would prevent that. This - change makes the two behaviors consistent. - 4. The supposed assurance that the `ArrayHandle` would not be reallocated - was easy to break even accidentally. If the `ArrayHandle` was assigned - to another `ArrayHandle` (for example as a class' member or wrapped - inside of an `UnknownArrayHandle`), then the array was free to be - reallocated. diff --git a/docs/changelog/better-unknown-type-reporting.md b/docs/changelog/better-unknown-type-reporting.md deleted file mode 100644 index 6a867ade2..000000000 --- a/docs/changelog/better-unknown-type-reporting.md +++ /dev/null @@ -1,14 +0,0 @@ -# Improve type reporting in `UnknownArrayHandle` - -Added features with reporting types with `UnknownArrayHandle`. First, added -a method named `GetArrayTypeName` that returns a string containing the type -of the contained array. There were already methods `GetValueType` and -`GetStorageType`, but this provides a convenience to get the whole name in -one go. - -Also improved the reporting when an `AsArrayHandle` call failed. Before, -the thrown method just reported that the `UnknownArrayHandle` could not be -converted to the given type. Now, it also reports the type actually held by -the `UnknownArrayHandle` so the user can better understand why the -conversion failed. - diff --git a/docs/changelog/consolidate-count-to-offset.md b/docs/changelog/consolidate-count-to-offset.md deleted file mode 100644 index 76c8d20ce..000000000 --- a/docs/changelog/consolidate-count-to-offset.md +++ /dev/null @@ -1,28 +0,0 @@ -# Consolidate count-to-offset algorithms - -For no particularly good reason, there were two functions that converted -and array of counts to an array of offsets: `ConvertNumComponentsToOffsets` -and `ConvertNumIndicesToOffsets`. These functions were identical, except -one was defined in `ArrayHandleGroupVecVariable.h` and the other was -defined in `CellSetExplicit.h`. - -These two functions have been consolidated into one (which is now called -`ConvertNumComponentsToOffsets`). The consolidated function has also been -put in its own header file: `ConvertNumComponentsToOffsets.h`. - -Normally, backward compatibility would be established using deprecated -features. However, one of the things being worked on is the removal of -device-specific code (e.g. `vtkm::cont::Algorithm`) from core classes like -`CellSetExplicit` so that less code needs to use the device compiler -(especially downstream code). - -`ConvertNumComponentsToOffsets` has also been changed to provide a -pre-compiled version for common arrays. This helps with the dual goals of -compiling less device code and allowing data set builders to not have to -use the device compiler. For cases where you need to compile -`ConvertNumComponentsToOffsets` for a different kind of array, you can use -the internal `ConvertNumComponentsToOffsetsTemplate`. - -Part of this change removed unnecessary includes of `Algorithm.h` in -`ArrayHandleGroupVecVariable.h` and `CellSetExplicit.h`. This header had to -be added to some classes that were not including it themselves. diff --git a/docs/changelog/convert-to-expected.md b/docs/changelog/convert-to-expected.md deleted file mode 100644 index e139b61eb..000000000 --- a/docs/changelog/convert-to-expected.md +++ /dev/null @@ -1,13 +0,0 @@ - # Add ability to convert fields to known types - -In VTK-m we have a constant tension between minimizing the number of -types we have to compile for (to reduce compile times and library size) -and maximizing the number of types that our filters support. -Unfortunately, if you don't compile a filter for a specific array type -(value type and storage), trying to run that filter will simply fail. - -To compromise between the two, added methods to `DataSet` and `Field` -that will automatically convert the data in the `Field` arrays to a type -that VTK-m will understand. Although this will cause an extra data copy, -it will at least prevent the program from failing, and thus make it more -feasible to reduce types. diff --git a/docs/changelog/deprecate-variant-array-handle.md b/docs/changelog/deprecate-variant-array-handle.md deleted file mode 100644 index 1d40369c0..000000000 --- a/docs/changelog/deprecate-variant-array-handle.md +++ /dev/null @@ -1,5 +0,0 @@ -# Deprecated `VariantArrayHandle` - -`VaraintArrayHandle` has been replaced by `UnknownArrayHandle` and -`UncertainArrayHandle`. Officially made `VariantArrayHandle` deprecated and -point users to the new implementations. diff --git a/docs/changelog/filters-instantiations-generator.md b/docs/changelog/filters-instantiations-generator.md deleted file mode 100644 index b72f0bb5f..000000000 --- a/docs/changelog/filters-instantiations-generator.md +++ /dev/null @@ -1,85 +0,0 @@ -# Filters instantiation generator - -It introduces a template instantiation generator. This aims to significantly -reduce the memory usage when building _VTK-m_ filter by effectively splitting -templates instantiations across multiple files. - -How this works revolves around automatically instantiating filters template -methods inside transient instantiation files which resides solely in the build -directory. Each of those transient files contains a single explicit template -instantiation. - -Here is an example of how to produce an instantiation file. - -First, at the filter header file: - -```c++ - -// 1. Include Instantiations header -#include - -class Contour { - template - vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet&, - const vtkm::cont::ArrayHandle&, - const vtkm::filter::FieldMetadata&, - vtkm::filter::PolicyBase); -}; - -// 2. Create extern template instantiation and surround with -// VTKM_INSTANTIATION_{BEGIN,END} -VTKM_INSTANTIATION_BEGIN -extern template vtkm::cont::DataSet Contour::DoExecute( - const vtkm::cont::DataSet&, - const vtkm::cont::ArrayHandle&, - const vtkm::filter::FieldMetadata&, - vtkm::filter::PolicyBase); -VTKM_INSTANTIATION_END - -``` - -Later, in its corresponding `CMakeLists.txt` file: - -```cmake - -vtkm_add_instantiations(ContourInstantiations FILTER Contour) -vtkm_library( - NAME vtkm_filter_contour - ... - DEVICE_SOURCES ${ContourInstantiations} - ) - -``` - -After running the configure step in _CMake_, this will result in the creation of -the following transient file in the build directory: - -```c++ - -#ifndef vtkm_filter_ContourInstantiation0_cxx -#define vtkm_filter_ContourInstantiation0_cxx -#endif - -/* Needed for linking errors when no instantiations */ -int __vtkm_filter_ContourInstantiation0_cxx; - -#include -#include - -namespace vtkm -{ -namespace filter -{ - -template vtkm::cont::DataSet Contour::DoExecute( - const vtkm::cont::DataSet&, - const vtkm::cont::ArrayHandle&, - const vtkm::filter::FieldMetadata&, - vtkm::filter::PolicyBase); - -} -} - -#undef vtkm_filter_ContourInstantiation0_cxx - -``` diff --git a/docs/changelog/generate-ids.md b/docs/changelog/generate-ids.md deleted file mode 100644 index 8fbe0c9b0..000000000 --- a/docs/changelog/generate-ids.md +++ /dev/null @@ -1,7 +0,0 @@ -# GenerateIds filter - -This filter adds a pair of fields to a `DataSet` which mirror the -indices of the points and cells, respectively. These fields are useful -for tracking the provenance of the elements of a `DataSet` as it gets -manipulated by the filters. It is also convenient for adding indices to -operations designed for fields and for testing purposes. diff --git a/docs/changelog/no-unbounded-recursion.md b/docs/changelog/no-unbounded-recursion.md deleted file mode 100644 index c15b75665..000000000 --- a/docs/changelog/no-unbounded-recursion.md +++ /dev/null @@ -1,17 +0,0 @@ -# Remove unbounded recursion - -GPU device compilers like to determine the stack size needed for a called -kernel. This is only possible if there is no recursive function calls on -the device or at least recursive calls where the termination cannot be -found at compile time. - -Device compilers do not particularly like that. We have been getting around -this with CUDA by turning of warnings about stack sizes and setting a large -stack size during a call (which works but is dangerous). More restrictive -devices might not allow recursive calls at all. - -To fix this, we will avoid recursive calls in execution environment -(device) code. All such warnings are turned on. - -Because of this, we also should not have to worry about lengthening the -stack size, so that code is also removed. diff --git a/docs/changelog/precompiled-array-get-values.md b/docs/changelog/precompiled-array-get-values.md deleted file mode 100644 index 2512d3885..000000000 --- a/docs/changelog/precompiled-array-get-values.md +++ /dev/null @@ -1,20 +0,0 @@ -# Compile `ArrayGetValues` implementation in a library - -Previously, all of the `ArrayGetValue` implementations were templated -functions that had to be built by all code that used it. That had 2 -negative consequences. - -1. The same code that scheduled jobs on any device had to be compiled many - times over. -2. Any code that used `ArrayGetValue` had to be compiled with a device - compiler. If you had non-worklet code that just wanted to get a single - value out of an array, that was a pain. - -To get around this problem, an `ArrayGetValues` function that takes -`UnknownArrayHandle`s was created. The implementation for this function is -compiled into a library. It uses `UnknownArrayHandle`'s ability to extract -a component of the array with a uniform type to reduce the number of code -paths it generates. Although there are still several code paths, they only -have to be computed once. Plus, now any code can include `ArrayGetValues.h` -and still use a basic C++ compiler. - diff --git a/docs/changelog/reverseconnection-precompiled.md b/docs/changelog/reverseconnection-precompiled.md deleted file mode 100644 index 064eb9965..000000000 --- a/docs/changelog/reverseconnection-precompiled.md +++ /dev/null @@ -1,21 +0,0 @@ -# Compile reverse connectivity builder into vtkm_cont library - -Because `CellSetExplicit` is a templated class, the implementation of -most of its features is part of the header files. One of the things that -was included was the code to build the reverse connectivity links. That -is, it figured out which cells were incident on each point using the -standard connections of which points comprise which cells. - -Of course, building these links is non-trivial, and it used multiple -DPPs to engage the device. It meant that header had to include the -device adapter algorithms and therefore required a device compiler. We -want to minimize this where possible. - -To get around this issue, a non-templated function was added to find the -reverse connections of a `CellSetExplicit`. It does this by passing in -`UnknownArrayHandle`s for the input arrays. (The output visit-points- -with-cells arrays are standard across all template instances.) The -implementation first iterates over all `CellSetExplicit` versions in -`VTKM_DEFAULT_CELL_SETS` and attempts to retrieve arrays of those types. -In the unlikely event that none of these arrays work, it copies the data -to `ArrayHandle` and uses those. diff --git a/docs/changelog/scatter-extrude-cells.md b/docs/changelog/scatter-extrude-cells.md deleted file mode 100644 index 4fb364416..000000000 --- a/docs/changelog/scatter-extrude-cells.md +++ /dev/null @@ -1,6 +0,0 @@ -# Support scatter/mask for CellSetExtrude - -Scheduling topology map workets for `CellSetExtrude` always worked, but the -there were indexing problems when a `Scatter` or a `Mask` was used. This -has been corrected, and now `Scatter`s and `Mask`s are supported on -topology maps on `CellSetExtrude`. diff --git a/docs/changelog/shallow-copy-if-possible.md b/docs/changelog/shallow-copy-if-possible.md deleted file mode 100644 index 6ba167571..000000000 --- a/docs/changelog/shallow-copy-if-possible.md +++ /dev/null @@ -1,12 +0,0 @@ -# Added `ArrayCopyShallowIfPossible` - -Often times you have an array of an unknown type (likely from a data set), -and you need it to be of a particular type (or can make a reasonable but -uncertain assumption about it being a particular type). You really just -want a shallow copy (a reference in a concrete `ArrayHandle`) if that is -possible. - -`ArrayCopyShallowIfPossible` pulls an array of a specific type from an -`UnknownArrayHandle`. If the type is compatible, it will perform a shallow -copy. If it is not possible, a deep copy is performed to get it to the -correct type. diff --git a/docs/changelog/skip-library-versions.md b/docs/changelog/skip-library-versions.md deleted file mode 100644 index b6afae2f7..000000000 --- a/docs/changelog/skip-library-versions.md +++ /dev/null @@ -1,8 +0,0 @@ -# skip library versions - -The `VTKm_SKIP_LIBRARY_VERSIONS` variable is now available to skip the SONAME -and SOVERSION fields (or the equivalent for non-ELF platforms). - -Some deployments (e.g., Python wheels or Java `.jar` files) do not support -symlinks reliably and the way the libraries get loaded just leads to -unnecessary files in the packaged artifact. diff --git a/docs/changelog/source-field-names.md b/docs/changelog/source-field-names.md deleted file mode 100644 index dd85e10aa..000000000 --- a/docs/changelog/source-field-names.md +++ /dev/null @@ -1,16 +0,0 @@ -# Make field names from sources more descriptive - -The VTK-m sources (like `Oscillator`, `Tangle`, and `Wavelet`) were all -creating fields with very generic names like `pointvar` or `scalars`. These -are very unhelpful names as it is impossible for downstream processes to -identify the meaning of these fields. Imagine having these data saved to a -file and then a different person trying to identify what they mean. Or -imagine dealing with more than one such source at a time and trying to -manage fields with similar or overlapping names. - -The following renames happened: - - * `Oscillator`: `scalars` -> `oscillating` - * `Tangle`: `pointvar` -> `tangle` - * `Wavelet`: `scalars` -> `RTData` (matches VTK source) - diff --git a/docs/changelog/type-index-names.md b/docs/changelog/type-index-names.md deleted file mode 100644 index 599d72248..000000000 --- a/docs/changelog/type-index-names.md +++ /dev/null @@ -1,11 +0,0 @@ -# Enable `TypeToString` for `type_info` - -VTK-m contains a helpful method named `vtkm::cont::TypeToString` that -either takes a type as a template argument or a `std::type_info` object and -returns a human-readable string for that type. - -The standard C++ library has an alternate for `std::type_info` named -`std::type_index`, which has the added ability to be used in a container -like `set` or `map`. The `TypeToString` overloads have been extended to -also accept a `std::type_info` and report the name of the type stored in it -(rather than the name of `type_info` itself). diff --git a/docs/changelog/unknownarray-copy-methods.md b/docs/changelog/unknownarray-copy-methods.md deleted file mode 100644 index 27235190d..000000000 --- a/docs/changelog/unknownarray-copy-methods.md +++ /dev/null @@ -1,24 +0,0 @@ -# Added copy methods to `UnknownArrayHandle` - -`vtkm::cont::UnknownArrayHandle` now provides a set of method that allows -you to copy data from one `UnknownArrayHandle` to another. The first -method, `DeepCopyFrom`, takes a source `UnknownArrayHandle` and deep copies -the data to the called one. If the `UnknownArrayHandle` already points to a -real `ArrayHandle`, the data is copied into that `ArrayHandle`. If the -`UnknownArrayHandle` does not point to an existing `ArrayHandle`, then a -new `ArrayHandleBasic` with the same value type as the source is created -and copied into. - -The second method, `CopyShallowIfPossibleFrom` behaves similarly to -`DeepCopyFrom` except that it will perform a shallow copy if possible. That -is, if the target `UnknownArrayHandle` points to an `ArrayHandle` of the -same type as the source `UnknownArrayHandle`, then a shallow copy occurs -and the underlying `ArrayHandle` will point to the source. If the types -differ, then a deep copy is performed. If the target `UnknownArrayHandle` -does not point to an `ArrayHandle`, then the behavior is the same as the -`=` operator. - -One of the intentions of these new methods is to allow you to copy arrays -without using a device compiler (e.g. `nvcc`). Calling `ArrayCopy` requires -you to include the `ArrayCopy.h` header file, and that in turn requires -device adapter algorithms. These methods insulate you from these. diff --git a/docs/changelog/write-binary.md b/docs/changelog/write-binary.md deleted file mode 100644 index 866d07381..000000000 --- a/docs/changelog/write-binary.md +++ /dev/null @@ -1,7 +0,0 @@ -# Support writing binary files to legacy VTK files - -The legacy VTK file writer writes out in ASCII. This is helpful when a -human is trying to read the file. However, if you have more than a -trivial amount of data, the file can get impractically large. To get -around this, `VTKDataSetWriter` now has a flag that allows you to write -the data in binary format. diff --git a/version.txt b/version.txt index dc1e644a1..57dfe270d 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.6.0 +1.7.0-rc1 diff --git a/vtkm/cont/CellSetStructured.h b/vtkm/cont/CellSetStructured.h index 6e27e878c..26475b46e 100644 --- a/vtkm/cont/CellSetStructured.h +++ b/vtkm/cont/CellSetStructured.h @@ -14,7 +14,6 @@ #include #include -#include #include #include #include diff --git a/vtkm/cont/FieldRangeCompute.h b/vtkm/cont/FieldRangeCompute.h index e3bcdf647..df6b8b4b6 100644 --- a/vtkm/cont/FieldRangeCompute.h +++ b/vtkm/cont/FieldRangeCompute.h @@ -14,6 +14,8 @@ #include #include +#include + namespace vtkm { namespace cont diff --git a/vtkm/cont/StorageVirtual.cxx b/vtkm/cont/StorageVirtual.cxx index ae39fb663..d1174b5bc 100644 --- a/vtkm/cont/StorageVirtual.cxx +++ b/vtkm/cont/StorageVirtual.cxx @@ -10,8 +10,6 @@ #define vtk_m_cont_StorageVirtual_cxx #include -#include - namespace vtkm { namespace cont diff --git a/vtkm/cont/StorageVirtual.hxx b/vtkm/cont/StorageVirtual.hxx index 4ee2fed0c..9ac534818 100644 --- a/vtkm/cont/StorageVirtual.hxx +++ b/vtkm/cont/StorageVirtual.hxx @@ -10,6 +10,7 @@ #ifndef vtk_m_cont_StorageVirtual_hxx #define vtk_m_cont_StorageVirtual_hxx +#include #include #include diff --git a/vtkm/cont/Timer.cxx b/vtkm/cont/Timer.cxx index 81d1c7638..2c5f610b0 100644 --- a/vtkm/cont/Timer.cxx +++ b/vtkm/cont/Timer.cxx @@ -7,6 +7,8 @@ // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notice for more information. //============================================================================ +#include +#include #include #include #include diff --git a/vtkm/cont/Timer.h b/vtkm/cont/Timer.h index a3f41c88d..aa2ceac09 100644 --- a/vtkm/cont/Timer.h +++ b/vtkm/cont/Timer.h @@ -10,9 +10,7 @@ #ifndef vtk_m_cont_Timer_h #define vtk_m_cont_Timer_h -#include -#include -#include +#include #include diff --git a/vtkm/cont/UnknownArrayHandle.h b/vtkm/cont/UnknownArrayHandle.h index 48d4161ec..54a339f0b 100644 --- a/vtkm/cont/UnknownArrayHandle.h +++ b/vtkm/cont/UnknownArrayHandle.h @@ -33,27 +33,8 @@ namespace cont namespace detail { -#ifdef VTKM_GCC -// On rare occasion, we have seen errors like this: -// `_ZN4vtkm4cont6detailL27UnknownAHNumberOfComponentsIxEEiv' referenced in section -// `.data.rel.ro.local' of CMakeFiles/UnitTests_vtkm_cont_testing.dir/UnitTestCellSet.cxx.o: -// defined in discarded section -// `.text._ZN4vtkm4cont6detailL27UnknownAHNumberOfComponentsIxEEiv[_ZN4vtkm4cont14ArrayGetValuesINS0_15StorageTagBasicExNS0_18StorageTagCountingES2_EEvRKNS0_11ArrayHandleIxT_EERKNS4_IT0_T1_EERNS4_IS9_T2_EE]' -// of CMakeFiles/UnitTests_vtkm_cont_testing.dir/UnitTestCellSet.cxx.o -// I don't know what circumstances exactly lead up to this, but it appears that the compiler is -// being overly aggressive with removing unused symbols. In this instance, it seems to have removed -// a function actually being used. This might be a bug in the compiler (I happen to have seen it in -// gcc 8.3, 9.4, and 11.0), or it could be caused by a link-time optimizer. The problem should be -// able to be solved by explictly saying that this templated method is being used. (I can't think -// of any circumstances where this template would be instantiated but not used.) If the compiler -// knows this is being used, it should know all the templated methods internal are also used. -#define VTKM_FORCE_USED __attribute__((used)) -#else -#define VTKM_FORCE_USED -#endif - template -VTKM_FORCE_USED static void UnknownAHDelete(void* mem) +void UnknownAHDelete(void* mem) { using AH = vtkm::cont::ArrayHandle; AH* arrayHandle = reinterpret_cast(mem); @@ -61,13 +42,13 @@ VTKM_FORCE_USED static void UnknownAHDelete(void* mem) } template -VTKM_FORCE_USED static void* UnknownAHNewInstance() +void* UnknownAHNewInstance() { return new vtkm::cont::ArrayHandle; } template -VTKM_FORCE_USED static vtkm::Id UnknownAHNumberOfValues(void* mem) +vtkm::Id UnknownAHNumberOfValues(void* mem) { using AH = vtkm::cont::ArrayHandle; AH* arrayHandle = reinterpret_cast(mem); @@ -88,7 +69,7 @@ struct UnknownAHNumberOfComponentsImpl }; template -VTKM_FORCE_USED static vtkm::IdComponent UnknownAHNumberOfComponents() +vtkm::IdComponent UnknownAHNumberOfComponents() { return UnknownAHNumberOfComponentsImpl::Value; } @@ -107,16 +88,16 @@ struct UnknownAHNumberOfComponentsFlatImpl }; template -VTKM_FORCE_USED static vtkm::IdComponent UnknownAHNumberOfComponentsFlat() +vtkm::IdComponent UnknownAHNumberOfComponentsFlat() { return UnknownAHNumberOfComponentsFlatImpl::Value; } template -VTKM_FORCE_USED static void UnknownAHAllocate(void* mem, - vtkm::Id numValues, - vtkm::CopyFlag preserve, - vtkm::cont::Token& token) +void UnknownAHAllocate(void* mem, + vtkm::Id numValues, + vtkm::CopyFlag preserve, + vtkm::cont::Token& token) { using AH = vtkm::cont::ArrayHandle; AH* arrayHandle = reinterpret_cast(mem); @@ -124,7 +105,7 @@ VTKM_FORCE_USED static void UnknownAHAllocate(void* mem, } template -VTKM_FORCE_USED static void UnknownAHShallowCopy(const void* sourceMem, void* destinationMem) +void UnknownAHShallowCopy(const void* sourceMem, void* destinationMem) { using AH = vtkm::cont::ArrayHandle; const AH* source = reinterpret_cast(sourceMem); @@ -133,7 +114,7 @@ VTKM_FORCE_USED static void UnknownAHShallowCopy(const void* sourceMem, void* de } template -VTKM_FORCE_USED static std::vector +std::vector UnknownAHExtractComponent(void* mem, vtkm::IdComponent componentIndex, vtkm::CopyFlag allowCopy) { using AH = vtkm::cont::ArrayHandle; @@ -144,7 +125,7 @@ UnknownAHExtractComponent(void* mem, vtkm::IdComponent componentIndex, vtkm::Cop } template -VTKM_FORCE_USED static void UnknownAHReleaseResources(void* mem) +void UnknownAHReleaseResources(void* mem) { using AH = vtkm::cont::ArrayHandle; AH* arrayHandle = reinterpret_cast(mem); @@ -152,7 +133,7 @@ VTKM_FORCE_USED static void UnknownAHReleaseResources(void* mem) } template -VTKM_FORCE_USED static void UnknownAHReleaseResourcesExecution(void* mem) +void UnknownAHReleaseResourcesExecution(void* mem) { using AH = vtkm::cont::ArrayHandle; AH* arrayHandle = reinterpret_cast(mem); @@ -160,7 +141,7 @@ VTKM_FORCE_USED static void UnknownAHReleaseResourcesExecution(void* mem) } template -VTKM_FORCE_USED static void UnknownAHPrintSummary(void* mem, std::ostream& out, bool full) +void UnknownAHPrintSummary(void* mem, std::ostream& out, bool full) { using AH = vtkm::cont::ArrayHandle; AH* arrayHandle = reinterpret_cast(mem); @@ -300,47 +281,42 @@ private: }; template -VTKM_FORCE_USED static std::shared_ptr UnknownAHNewInstanceBasic( - vtkm::VecTraitsTagSizeStatic) +std::shared_ptr UnknownAHNewInstanceBasic(vtkm::VecTraitsTagSizeStatic) { return UnknownAHContainer::Make(vtkm::cont::ArrayHandleBasic{}); } template -VTKM_FORCE_USED static std::shared_ptr UnknownAHNewInstanceBasic( - vtkm::VecTraitsTagSizeVariable) +std::shared_ptr UnknownAHNewInstanceBasic(vtkm::VecTraitsTagSizeVariable) { throw vtkm::cont::ErrorBadType("Cannot create a basic array container from with ValueType of " + vtkm::cont::TypeToString()); } template -VTKM_FORCE_USED static std::shared_ptr UnknownAHNewInstanceBasic() +std::shared_ptr UnknownAHNewInstanceBasic() { return UnknownAHNewInstanceBasic(typename vtkm::VecTraits::IsSizeStatic{}); } template -VTKM_FORCE_USED static std::shared_ptr UnknownAHNewInstanceFloatBasic( - vtkm::VecTraitsTagSizeStatic) +std::shared_ptr UnknownAHNewInstanceFloatBasic(vtkm::VecTraitsTagSizeStatic) { using FloatT = typename vtkm::VecTraits::template ReplaceBaseComponentType; return UnknownAHContainer::Make(vtkm::cont::ArrayHandleBasic{}); } template -VTKM_FORCE_USED static std::shared_ptr UnknownAHNewInstanceFloatBasic( - vtkm::VecTraitsTagSizeVariable) +std::shared_ptr UnknownAHNewInstanceFloatBasic(vtkm::VecTraitsTagSizeVariable) { throw vtkm::cont::ErrorBadType("Cannot create a basic array container from with ValueType of " + vtkm::cont::TypeToString()); } template -VTKM_FORCE_USED static std::shared_ptr UnknownAHNewInstanceFloatBasic() +std::shared_ptr UnknownAHNewInstanceFloatBasic() { return UnknownAHNewInstanceFloatBasic(typename vtkm::VecTraits::IsSizeStatic{}); } template -VTKM_FORCE_USED inline UnknownAHContainer::UnknownAHContainer( - const vtkm::cont::ArrayHandle& array) +inline UnknownAHContainer::UnknownAHContainer(const vtkm::cont::ArrayHandle& array) : ArrayHandlePointer(new vtkm::cont::ArrayHandle(array)) , ValueType(typeid(T)) , StorageType(typeid(S)) diff --git a/vtkm/filter/Filter.h b/vtkm/filter/Filter.h index e561a7981..5efba2217 100644 --- a/vtkm/filter/Filter.h +++ b/vtkm/filter/Filter.h @@ -12,6 +12,7 @@ #include #include +#include #include #include #include diff --git a/vtkm/filter/Lagrangian.hxx b/vtkm/filter/Lagrangian.hxx index b9b129cf0..937b1c5ec 100644 --- a/vtkm/filter/Lagrangian.hxx +++ b/vtkm/filter/Lagrangian.hxx @@ -256,11 +256,6 @@ inline VTKM_CONT vtkm::cont::DataSet Lagrangian::DoExecute( vtkm::cont::ArrayCopy(BasisParticles, BasisParticlesOriginal); } - if (!fieldMeta.IsPointField()) - { - throw vtkm::cont::ErrorFilterExecution("Point field expected."); - } - if (this->writeFrequency == 0) { throw vtkm::cont::ErrorFilterExecution( @@ -284,7 +279,7 @@ inline VTKM_CONT vtkm::cont::DataSet Lagrangian::DoExecute( vtkm::worklet::ParticleAdvection particleadvection; vtkm::worklet::ParticleAdvectionResult res; - FieldType velocities(field); + FieldType velocities(field, fieldMeta.GetAssociation()); GridEvalType gridEval(coords, cells, velocities); Stepper rk4(gridEval, static_cast(this->stepSize)); diff --git a/vtkm/filter/LagrangianStructures.hxx b/vtkm/filter/LagrangianStructures.hxx index 962f4a30b..85aa41801 100644 --- a/vtkm/filter/LagrangianStructures.hxx +++ b/vtkm/filter/LagrangianStructures.hxx @@ -75,11 +75,6 @@ inline VTKM_CONT vtkm::cont::DataSet LagrangianStructures::DoExecute( const vtkm::filter::FieldMetadata& fieldMeta, const vtkm::filter::PolicyBase&) { - if (!fieldMeta.IsPointField()) - { - throw vtkm::cont::ErrorFilterExecution("Point field expected."); - } - using Structured2DType = vtkm::cont::CellSetStructured<2>; using Structured3DType = vtkm::cont::CellSetStructured<3>; @@ -137,7 +132,7 @@ inline VTKM_CONT vtkm::cont::DataSet LagrangianStructures::DoExecute( { vtkm::cont::Invoker invoke; - FieldType velocities(field); + FieldType velocities(field, fieldMeta.GetAssociation()); GridEvaluator evaluator(input.GetCoordinateSystem(), input.GetCellSet(), velocities); Stepper integrator(evaluator, stepSize); vtkm::worklet::ParticleAdvection particles; diff --git a/vtkm/filter/StreamSurface.hxx b/vtkm/filter/StreamSurface.hxx index d4512e581..aeddf1ed5 100644 --- a/vtkm/filter/StreamSurface.hxx +++ b/vtkm/filter/StreamSurface.hxx @@ -51,9 +51,6 @@ inline VTKM_CONT vtkm::cont::DataSet StreamSurface::DoExecute( const vtkm::cont::CoordinateSystem& coords = input.GetCoordinateSystem(this->GetActiveCoordinateSystemIndex()); - if (!fieldMeta.IsPointField()) - throw vtkm::cont::ErrorFilterExecution("Point field expected."); - using FieldHandle = vtkm::cont::ArrayHandle, StorageType>; using FieldType = vtkm::worklet::particleadvection::VelocityField; using GridEvalType = vtkm::worklet::particleadvection::GridEvaluator; @@ -61,7 +58,7 @@ inline VTKM_CONT vtkm::cont::DataSet StreamSurface::DoExecute( using Stepper = vtkm::worklet::particleadvection::Stepper; //compute streamlines - FieldType velocities(field); + FieldType velocities(field, fieldMeta.GetAssociation()); GridEvalType eval(coords, cells, velocities); Stepper rk4(eval, this->StepSize); diff --git a/vtkm/filter/particleadvection/DataSetIntegrator.h b/vtkm/filter/particleadvection/DataSetIntegrator.h index 31c24d52f..793c7ed9c 100644 --- a/vtkm/filter/particleadvection/DataSetIntegrator.h +++ b/vtkm/filter/particleadvection/DataSetIntegrator.h @@ -93,12 +93,13 @@ public: : DataSetIntegratorBase>>(false, id) { + using Association = vtkm::cont::Field::Association; + using FieldType = vtkm::worklet::particleadvection::VelocityField; + using EvalType = vtkm::worklet::particleadvection::GridEvaluator; + Association association = ds.GetField(fieldNm).GetAssociation(); auto fieldArray = this->GetFieldHandle(ds, fieldNm); - - using EvalType = vtkm::worklet::particleadvection::GridEvaluator< - vtkm::worklet::particleadvection::VelocityField>; - - this->Eval = std::shared_ptr(new EvalType(ds, fieldArray)); + FieldType field(fieldArray, association); + this->Eval = std::shared_ptr(new EvalType(ds, field)); } }; diff --git a/vtkm/io/CMakeLists.txt b/vtkm/io/CMakeLists.txt index 0ce968f11..758350de9 100644 --- a/vtkm/io/CMakeLists.txt +++ b/vtkm/io/CMakeLists.txt @@ -37,17 +37,10 @@ set(template_sources ) set(sources - FileUtils.cxx + BOVDataSetReader.cxx DecodePNG.cxx EncodePNG.cxx - ) - -# TODO: None of these codes actually use a device. Rather, they access ArrayHandle, and we -# currently need to ensure that ArrayHandle is correctly compiled for all devices. This is -# kind of silly, so hopefully sometime in the future you will no longer need to compile for -# devices for ArrayHandle, and this requirement will go away. -set(device_sources - BOVDataSetReader.cxx + FileUtils.cxx ImageReaderBase.cxx ImageReaderPNG.cxx ImageReaderPNM.cxx @@ -56,22 +49,26 @@ set(device_sources ImageWriterPNG.cxx ImageWriterPNM.cxx VTKDataSetReader.cxx - VTKDataSetReaderBase.cxx VTKDataSetWriter.cxx VTKPolyDataReader.cxx - VTKRectilinearGridReader.cxx VTKStructuredGridReader.cxx VTKStructuredPointsReader.cxx VTKUnstructuredGridReader.cxx ) +# These files use ArrayCopy which uses a WorkletMapField thus are required to be device_sources +set(device_sources + VTKDataSetReaderBase.cxx + VTKRectilinearGridReader.cxx + ) + if (VTKm_ENABLE_HDF5_IO) set(headers ${headers} ImageReaderHDF5.h ImageWriterHDF5.h) - set(device_sources - ${device_sources} + set(sources + ${sources} ImageReaderHDF5.cxx ImageWriterHDF5.cxx) endif () diff --git a/vtkm/io/ImageUtils.cxx b/vtkm/io/ImageUtils.cxx index 9972d7203..1c8bd847b 100644 --- a/vtkm/io/ImageUtils.cxx +++ b/vtkm/io/ImageUtils.cxx @@ -7,12 +7,14 @@ // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notice for more information. //============================================================================ -#include + +#include #include #include #include #include +#include #include #include #include diff --git a/vtkm/io/testing/UnitTestFileUtils.cxx b/vtkm/io/testing/UnitTestFileUtils.cxx index 05fe65d66..c78695d29 100644 --- a/vtkm/io/testing/UnitTestFileUtils.cxx +++ b/vtkm/io/testing/UnitTestFileUtils.cxx @@ -18,7 +18,6 @@ #include #endif -#include #include using namespace vtkm::io; diff --git a/vtkm/io/testing/UnitTestImageWriter.cxx b/vtkm/io/testing/UnitTestImageWriter.cxx index 69c32fd19..fccedeaac 100644 --- a/vtkm/io/testing/UnitTestImageWriter.cxx +++ b/vtkm/io/testing/UnitTestImageWriter.cxx @@ -13,7 +13,6 @@ #include #include #include -#include #include #include diff --git a/vtkm/rendering/CMakeLists.txt b/vtkm/rendering/CMakeLists.txt index d42414c42..09df80f46 100644 --- a/vtkm/rendering/CMakeLists.txt +++ b/vtkm/rendering/CMakeLists.txt @@ -36,6 +36,7 @@ set(headers DecodePNG.h # deprecated EncodePNG.h # deprecated LineRenderer.h + LineRendererBatcher.h MatrixHelpers.h Scene.h Mapper.h @@ -52,6 +53,7 @@ set(headers TextAnnotationBillboard.h TextAnnotationScreen.h TextRenderer.h + TextRendererBatcher.h Texture2D.h Triangulator.h View.h @@ -85,6 +87,7 @@ set(device_sources ColorLegendAnnotation.cxx ConnectivityProxy.cxx LineRenderer.cxx + LineRendererBatcher.cxx Mapper.cxx MapperConnectivity.cxx MapperCylinder.cxx @@ -99,6 +102,7 @@ set(device_sources TextAnnotationBillboard.cxx TextAnnotationScreen.cxx TextRenderer.cxx + TextRendererBatcher.cxx View.cxx View1D.cxx View2D.cxx diff --git a/vtkm/rendering/Canvas.cxx b/vtkm/rendering/Canvas.cxx index 0db7ee890..921c6590d 100644 --- a/vtkm/rendering/Canvas.cxx +++ b/vtkm/rendering/Canvas.cxx @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -224,6 +225,7 @@ struct Canvas::CanvasInternals FontTextureType FontTexture; vtkm::Matrix ModelView; vtkm::Matrix Projection; + std::shared_ptr TextBatcher; }; Canvas::Canvas(vtkm::Id width, vtkm::Id height) @@ -394,8 +396,11 @@ void Canvas::AddLine(const vtkm::Vec2f_64& point0, const vtkm::rendering::Color& color) const { vtkm::rendering::Canvas* self = const_cast(this); - LineRenderer renderer(self, vtkm::MatrixMultiply(Internals->Projection, Internals->ModelView)); + vtkm::rendering::LineRendererBatcher lineBatcher; + LineRenderer renderer( + self, vtkm::MatrixMultiply(Internals->Projection, Internals->ModelView), &lineBatcher); renderer.RenderLine(point0, point1, linewidth, color); + lineBatcher.Render(self); } void Canvas::AddLine(vtkm::Float64 x0, @@ -476,16 +481,14 @@ void Canvas::AddText(const vtkm::Matrix& transform, const std::string& text, const vtkm::Float32& depth) const { - if (!Internals->FontTexture.IsValid()) + if (!this->EnsureFontLoaded() || !this->Internals->TextBatcher) { - if (!LoadFont()) - { - return; - } + return; } vtkm::rendering::Canvas* self = const_cast(this); - TextRenderer fontRenderer(self, Internals->Font, Internals->FontTexture); + vtkm::rendering::TextRenderer fontRenderer( + self, Internals->Font, Internals->FontTexture, this->Internals->TextBatcher.get()); fontRenderer.RenderText(transform, scale, anchor, color, text, depth); } @@ -527,6 +530,40 @@ void Canvas::AddText(vtkm::Float32 x, text); } +void Canvas::BeginTextRenderingBatch() const +{ + if (!this->EnsureFontLoaded() || this->Internals->TextBatcher) + { + return; + } + + this->Internals->TextBatcher = + std::make_shared(this->Internals->FontTexture); +} + +void Canvas::EndTextRenderingBatch() const +{ + if (!this->Internals->TextBatcher) + { + return; + } + + this->Internals->TextBatcher->Render(this); + this->Internals->TextBatcher.reset(); +} + +bool Canvas::EnsureFontLoaded() const +{ + if (!Internals->FontTexture.IsValid()) + { + if (!LoadFont()) + { + return false; + } + } + return true; +} + bool Canvas::LoadFont() const { Internals->Font = BitmapFontFactory::CreateLiberation2Sans(); diff --git a/vtkm/rendering/Canvas.h b/vtkm/rendering/Canvas.h index e7afac3e6..bd54a4f36 100644 --- a/vtkm/rendering/Canvas.h +++ b/vtkm/rendering/Canvas.h @@ -204,6 +204,11 @@ public: const std::string& text, const vtkm::Float32& depth = 0) const; + VTKM_CONT + void BeginTextRenderingBatch() const; + + VTKM_CONT + void EndTextRenderingBatch() const; friend class AxisAnnotation2D; friend class ColorBarAnnotation; @@ -215,6 +220,8 @@ public: private: bool LoadFont() const; + bool EnsureFontLoaded() const; + const vtkm::Matrix& GetModelView() const; const vtkm::Matrix& GetProjection() const; diff --git a/vtkm/rendering/LineRenderer.cxx b/vtkm/rendering/LineRenderer.cxx index 3880df2da..0ccbb22a2 100644 --- a/vtkm/rendering/LineRenderer.cxx +++ b/vtkm/rendering/LineRenderer.cxx @@ -12,6 +12,7 @@ #include #include +#include #include #include @@ -21,9 +22,11 @@ namespace rendering { LineRenderer::LineRenderer(const vtkm::rendering::Canvas* canvas, - vtkm::Matrix transform) + vtkm::Matrix transform, + vtkm::rendering::LineRendererBatcher* lineBatcher) : Canvas(canvas) , Transform(transform) + , LineBatcher(lineBatcher) { } @@ -45,85 +48,7 @@ void LineRenderer::RenderLine(const vtkm::Vec3f_64& point0, { vtkm::Vec3f_32 p0 = TransformPoint(point0); vtkm::Vec3f_32 p1 = TransformPoint(point1); - - vtkm::Id x0 = static_cast(vtkm::Round(p0[0])); - vtkm::Id y0 = static_cast(vtkm::Round(p0[1])); - vtkm::Float32 z0 = static_cast(p0[2]); - vtkm::Id x1 = static_cast(vtkm::Round(p1[0])); - vtkm::Id y1 = static_cast(vtkm::Round(p1[1])); - vtkm::Float32 z1 = static_cast(p1[2]); - vtkm::Id dx = vtkm::Abs(x1 - x0), sx = x0 < x1 ? 1 : -1; - vtkm::Id dy = -vtkm::Abs(y1 - y0), sy = y0 < y1 ? 1 : -1; - vtkm::Id err = dx + dy, err2 = 0; - - const vtkm::Id xStart = x0; - const vtkm::Id yStart = y0; - const vtkm::Float32 pdist = vtkm::Sqrt(vtkm::Float32(dx * dx) + vtkm::Float32(dy * dy)); - - auto colorPortal = - vtkm::rendering::Canvas::ColorBufferType(Canvas->GetColorBuffer()).WritePortal(); - auto depthPortal = - vtkm::rendering::Canvas::DepthBufferType(Canvas->GetDepthBuffer()).WritePortal(); - vtkm::Vec4f_32 colorC = color.Components; - - while (x0 >= 0 && x0 < Canvas->GetWidth() && y0 >= 0 && y0 < Canvas->GetHeight()) - { - vtkm::Float32 deltaX = static_cast(x0 - xStart); - vtkm::Float32 deltaY = static_cast(y0 - yStart); - // Depth is wrong, but its far less wrong that it used to be. - // These depth values are in screen space, which have been - // potentially tranformed by a perspective correction. - // To interpolated the depth correctly, there must be a perspective correction. - // I haven't looked, but the wireframmer probably suffers from this too. - // Additionally, this should not happen on the CPU. Annotations take - // far longer than the the geometry. - vtkm::Float32 t = pdist == 0.f ? 1.0f : vtkm::Sqrt(deltaX * deltaX + deltaY * deltaY) / pdist; - t = vtkm::Min(1.f, vtkm::Max(0.f, t)); - vtkm::Float32 z = vtkm::Lerp(z0, z1, t); - - vtkm::Id index = y0 * Canvas->GetWidth() + x0; - vtkm::Vec4f_32 currentColor = colorPortal.Get(index); - vtkm::Float32 currentZ = depthPortal.Get(index); - bool blend = currentColor[3] < 1.f && z > currentZ; - if (currentZ > z || blend) - { - vtkm::Vec4f_32 writeColor = colorC; - vtkm::Float32 depth = z; - - if (blend) - { - // If there is any transparency, all alphas - // have been pre-mulitplied - vtkm::Float32 alpha = (1.f - currentColor[3]); - writeColor[0] = currentColor[0] + colorC[0] * alpha; - writeColor[1] = currentColor[1] + colorC[1] * alpha; - writeColor[2] = currentColor[2] + colorC[2] * alpha; - writeColor[3] = 1.f * alpha + currentColor[3]; // we are always drawing opaque lines - // keep the current z. Line z interpolation is not accurate - // Matt: this is correct. Interpolation is wrong - depth = currentZ; - } - - depthPortal.Set(index, depth); - colorPortal.Set(index, writeColor); - } - - if (x0 == x1 && y0 == y1) - { - break; - } - err2 = err * 2; - if (err2 >= dy) - { - err += dy; - x0 += sx; - } - if (err2 <= dx) - { - err += dx; - y0 += sy; - } - } + this->LineBatcher->BatchLine(p0, p1, color); } vtkm::Vec3f_32 LineRenderer::TransformPoint(const vtkm::Vec3f_64& point) const diff --git a/vtkm/rendering/LineRenderer.h b/vtkm/rendering/LineRenderer.h index a3b1d9994..247e91825 100644 --- a/vtkm/rendering/LineRenderer.h +++ b/vtkm/rendering/LineRenderer.h @@ -20,12 +20,15 @@ namespace vtkm { namespace rendering { +class LineRendererBatcher; class VTKM_RENDERING_EXPORT LineRenderer { public: VTKM_CONT - LineRenderer(const vtkm::rendering::Canvas* canvas, vtkm::Matrix transform); + LineRenderer(const vtkm::rendering::Canvas* canvas, + vtkm::Matrix transform, + vtkm::rendering::LineRendererBatcher* lineBatcher); VTKM_CONT void RenderLine(const vtkm::Vec2f_64& point0, @@ -45,6 +48,7 @@ private: const vtkm::rendering::Canvas* Canvas; vtkm::Matrix Transform; + vtkm::rendering::LineRendererBatcher* LineBatcher; }; // class LineRenderer } } // namespace vtkm::rendering diff --git a/vtkm/rendering/LineRendererBatcher.cxx b/vtkm/rendering/LineRendererBatcher.cxx new file mode 100644 index 000000000..c08e45237 --- /dev/null +++ b/vtkm/rendering/LineRendererBatcher.cxx @@ -0,0 +1,168 @@ +//============================================================================ +// 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 + +#include + +namespace vtkm +{ +namespace rendering +{ +namespace +{ +using ColorsArrayHandle = vtkm::cont::ArrayHandle; +using PointsArrayHandle = vtkm::cont::ArrayHandle; + +struct RenderLine : public vtkm::worklet::WorkletMapField +{ + using ColorBufferType = vtkm::rendering::Canvas::ColorBufferType; + using DepthBufferType = vtkm::rendering::Canvas::DepthBufferType; + + using ControlSignature = void(FieldIn, FieldIn, FieldIn, WholeArrayInOut, WholeArrayInOut); + using ExecutionSignature = void(_1, _2, _3, _4, _5); + using InputDomain = _1; + + VTKM_CONT + RenderLine() {} + + VTKM_CONT + RenderLine(vtkm::Id width, vtkm::Id height) + : Width(width) + , Height(height) + { + } + + template + VTKM_EXEC void operator()(const vtkm::Vec3f_32& start, + const vtkm::Vec3f_32& end, + const vtkm::Vec4f_32& color, + ColorBufferPortal& colorBuffer, + DepthBufferPortal& depthBuffer) const + { + vtkm::Id x0 = static_cast(vtkm::Round(start[0])); + vtkm::Id y0 = static_cast(vtkm::Round(start[1])); + vtkm::Float32 z0 = static_cast(start[2]); + vtkm::Id x1 = static_cast(vtkm::Round(end[0])); + vtkm::Id y1 = static_cast(vtkm::Round(end[1])); + vtkm::Float32 z1 = static_cast(end[2]); + vtkm::Id dx = vtkm::Abs(x1 - x0), sx = x0 < x1 ? 1 : -1; + vtkm::Id dy = -vtkm::Abs(y1 - y0), sy = y0 < y1 ? 1 : -1; + vtkm::Id err = dx + dy, err2 = 0; + + const vtkm::Id xStart = x0; + const vtkm::Id yStart = y0; + const vtkm::Float32 pdist = vtkm::Sqrt(vtkm::Float32(dx * dx) + vtkm::Float32(dy * dy)); + + while (x0 >= 0 && x0 < this->Width && y0 >= 0 && y0 < this->Height) + { + vtkm::Float32 deltaX = static_cast(x0 - xStart); + vtkm::Float32 deltaY = static_cast(y0 - yStart); + // Depth is wrong, but its far less wrong that it used to be. + // These depth values are in screen space, which have been + // potentially tranformed by a perspective correction. + // To interpolated the depth correctly, there must be a perspective correction. + // I haven't looked, but the wireframmer probably suffers from this too. + // Additionally, this should not happen on the CPU. Annotations take + // far longer than the the geometry. + vtkm::Float32 t = pdist == 0.f ? 1.0f : vtkm::Sqrt(deltaX * deltaX + deltaY * deltaY) / pdist; + t = vtkm::Min(1.f, vtkm::Max(0.f, t)); + vtkm::Float32 z = vtkm::Lerp(z0, z1, t); + + vtkm::Id index = y0 * this->Width + x0; + vtkm::Vec4f_32 currentColor = colorBuffer.Get(index); + vtkm::Float32 currentZ = depthBuffer.Get(index); + bool blend = currentColor[3] < 1.f && z > currentZ; + if (currentZ > z || blend) + { + vtkm::Vec4f_32 writeColor = color; + vtkm::Float32 depth = z; + + if (blend) + { + // If there is any transparency, all alphas + // have been pre-mulitplied + vtkm::Float32 alpha = (1.f - currentColor[3]); + writeColor[0] = currentColor[0] + color[0] * alpha; + writeColor[1] = currentColor[1] + color[1] * alpha; + writeColor[2] = currentColor[2] + color[2] * alpha; + writeColor[3] = 1.f * alpha + currentColor[3]; // we are always drawing opaque lines + // keep the current z. Line z interpolation is not accurate + // Matt: this is correct. Interpolation is wrong + depth = currentZ; + } + + depthBuffer.Set(index, depth); + colorBuffer.Set(index, writeColor); + } + + if (x0 == x1 && y0 == y1) + { + break; + } + err2 = err * 2; + if (err2 >= dy) + { + err += dy; + x0 += sx; + } + if (err2 <= dx) + { + err += dx; + y0 += sy; + } + } + } + + vtkm::Id Width; + vtkm::Id Height; +}; // struct RenderLine +} // namespace + +LineRendererBatcher::LineRendererBatcher() {} + +void LineRendererBatcher::BatchLine(const vtkm::Vec3f_64& start, + const vtkm::Vec3f_64& end, + const vtkm::rendering::Color& color) +{ + vtkm::Vec3f_32 start32(static_cast(start[0]), + static_cast(start[1]), + static_cast(start[2])); + vtkm::Vec3f_32 end32(static_cast(end[0]), + static_cast(end[1]), + static_cast(end[2])); + this->BatchLine(start32, end32, color); +} + +void LineRendererBatcher::BatchLine(const vtkm::Vec3f_32& start, + const vtkm::Vec3f_32& end, + const vtkm::rendering::Color& color) +{ + this->Starts.push_back(start); + this->Ends.push_back(end); + this->Colors.push_back(color.Components); +} + +void LineRendererBatcher::Render(const vtkm::rendering::Canvas* canvas) const +{ + PointsArrayHandle starts = vtkm::cont::make_ArrayHandle(this->Starts, vtkm::CopyFlag::Off); + PointsArrayHandle ends = vtkm::cont::make_ArrayHandle(this->Ends, vtkm::CopyFlag::Off); + ColorsArrayHandle colors = vtkm::cont::make_ArrayHandle(this->Colors, vtkm::CopyFlag::Off); + + vtkm::cont::Invoker invoker; + invoker(RenderLine(canvas->GetWidth(), canvas->GetHeight()), + starts, + ends, + colors, + canvas->GetColorBuffer(), + canvas->GetDepthBuffer()); +} +} +} // namespace vtkm::rendering diff --git a/vtkm/rendering/LineRendererBatcher.h b/vtkm/rendering/LineRendererBatcher.h new file mode 100644 index 000000000..5edc2d91d --- /dev/null +++ b/vtkm/rendering/LineRendererBatcher.h @@ -0,0 +1,52 @@ +//============================================================================ +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notice for more information. +//============================================================================ + +#ifndef vtk_m_rendering_LineRendererBatcher_h +#define vtk_m_rendering_LineRendererBatcher_h + +#include +#include + +#include +#include +#include + +namespace vtkm +{ +namespace rendering +{ + +class VTKM_RENDERING_EXPORT LineRendererBatcher +{ +public: + VTKM_CONT + LineRendererBatcher(); + + VTKM_CONT + void BatchLine(const vtkm::Vec3f_64& start, + const vtkm::Vec3f_64& end, + const vtkm::rendering::Color& color); + + VTKM_CONT + void BatchLine(const vtkm::Vec3f_32& start, + const vtkm::Vec3f_32& end, + const vtkm::rendering::Color& color); + + void Render(const vtkm::rendering::Canvas* canvas) const; + +private: + std::vector Starts; + std::vector Ends; + std::vector Colors; +}; +} +} // namespace vtkm::rendering + +#endif // vtk_m_rendering_LineRendererBatcher_h diff --git a/vtkm/rendering/TextRenderer.cxx b/vtkm/rendering/TextRenderer.cxx index 4e6742e03..587396bbd 100644 --- a/vtkm/rendering/TextRenderer.cxx +++ b/vtkm/rendering/TextRenderer.cxx @@ -12,6 +12,7 @@ #include #include +#include #include #include @@ -19,163 +20,15 @@ namespace vtkm { namespace rendering { -namespace internal -{ - -struct RenderBitmapFont : public vtkm::worklet::WorkletMapField -{ - using ColorBufferType = vtkm::rendering::Canvas::ColorBufferType; - using DepthBufferType = vtkm::rendering::Canvas::DepthBufferType; - using FontTextureType = vtkm::rendering::Canvas::FontTextureType; - - using ControlSignature = void(FieldIn, FieldIn, ExecObject, WholeArrayInOut, WholeArrayInOut); - using ExecutionSignature = void(_1, _2, _3, _4, _5); - using InputDomain = _1; - - VTKM_CONT - RenderBitmapFont() {} - - VTKM_CONT - RenderBitmapFont(const vtkm::Vec4f_32& color, - vtkm::Id width, - vtkm::Id height, - vtkm::Float32 depth) - : Color(color) - , Width(width) - , Height(height) - , Depth(depth) - { - } - - template - VTKM_EXEC void operator()(const vtkm::Vec4f_32& screenCoords, - const vtkm::Vec4f_32& textureCoords, - const FontTexture& fontTexture, - ColorBufferPortal& colorBuffer, - DepthBufferPortal& depthBuffer) const - { - vtkm::Float32 x0 = Clamp(screenCoords[0], 0.0f, static_cast(Width - 1)); - vtkm::Float32 x1 = Clamp(screenCoords[2], 0.0f, static_cast(Width - 1)); - vtkm::Float32 y0 = Clamp(screenCoords[1], 0.0f, static_cast(Height - 1)); - vtkm::Float32 y1 = Clamp(screenCoords[3], 0.0f, static_cast(Height - 1)); - // For crisp text rendering, we sample the font texture at points smaller than the pixel - // sizes. Here we sample at increments of 0.25f, and scale the reported intensities accordingly - vtkm::Float32 dx = x1 - x0, dy = y1 - y0; - for (vtkm::Float32 x = x0; x <= x1; x += 0.25f) - { - for (vtkm::Float32 y = y0; y <= y1; y += 0.25f) - { - vtkm::Float32 tu = x1 == x0 ? 1.0f : (x - x0) / dx; - vtkm::Float32 tv = y1 == y0 ? 1.0f : (y - y0) / dy; - vtkm::Float32 u = vtkm::Lerp(textureCoords[0], textureCoords[2], tu); - vtkm::Float32 v = vtkm::Lerp(textureCoords[1], textureCoords[3], tv); - vtkm::Float32 intensity = fontTexture.GetColor(u, v)[0] * 0.25f; - Plot(x, y, intensity, colorBuffer, depthBuffer); - } - } - } - - template - VTKM_EXEC void Plot(vtkm::Float32 x, - vtkm::Float32 y, - vtkm::Float32 intensity, - ColorBufferPortal& colorBuffer, - DepthBufferPortal& depthBuffer) const - { - vtkm::Id index = - static_cast(vtkm::Round(y)) * Width + static_cast(vtkm::Round(x)); - vtkm::Vec4f_32 srcColor = colorBuffer.Get(index); - vtkm::Float32 currentDepth = depthBuffer.Get(index); - bool swap = Depth > currentDepth; - - intensity = intensity * Color[3]; - vtkm::Vec4f_32 color = intensity * Color; - color[3] = intensity; - vtkm::Vec4f_32 front = color; - vtkm::Vec4f_32 back = srcColor; - - if (swap) - { - front = srcColor; - back = color; - } - - vtkm::Vec4f_32 blendedColor; - vtkm::Float32 alpha = (1.f - front[3]); - blendedColor[0] = front[0] + back[0] * alpha; - blendedColor[1] = front[1] + back[1] * alpha; - blendedColor[2] = front[2] + back[2] * alpha; - blendedColor[3] = back[3] * alpha + front[3]; - - colorBuffer.Set(index, blendedColor); - } - - VTKM_EXEC - vtkm::Float32 Clamp(vtkm::Float32 v, vtkm::Float32 min, vtkm::Float32 max) const - { - return vtkm::Min(vtkm::Max(v, min), max); - } - - vtkm::Vec4f_32 Color; - vtkm::Id Width; - vtkm::Id Height; - vtkm::Float32 Depth; -}; // struct RenderBitmapFont - -struct RenderBitmapFontExecutor -{ - using ColorBufferType = vtkm::rendering::Canvas::ColorBufferType; - using DepthBufferType = vtkm::rendering::Canvas::DepthBufferType; - using FontTextureType = vtkm::rendering::Canvas::FontTextureType; - using ScreenCoordsArrayHandle = vtkm::cont::ArrayHandle; - using TextureCoordsArrayHandle = vtkm::cont::ArrayHandle; - - VTKM_CONT - RenderBitmapFontExecutor(const ScreenCoordsArrayHandle& screenCoords, - const TextureCoordsArrayHandle& textureCoords, - const FontTextureType& fontTexture, - const vtkm::Vec4f_32& color, - const ColorBufferType& colorBuffer, - const DepthBufferType& depthBuffer, - vtkm::Id width, - vtkm::Id height, - vtkm::Float32 depth) - : ScreenCoords(screenCoords) - , TextureCoords(textureCoords) - , FontTexture(fontTexture) - , ColorBuffer(colorBuffer) - , DepthBuffer(depthBuffer) - , Worklet(color, width, height, depth) - { - } - - template - VTKM_CONT bool operator()(Device) const - { - VTKM_IS_DEVICE_ADAPTER_TAG(Device); - - vtkm::worklet::DispatcherMapField dispatcher(Worklet); - dispatcher.SetDevice(Device()); - dispatcher.Invoke( - ScreenCoords, TextureCoords, FontTexture.GetExecObjectFactory(), ColorBuffer, DepthBuffer); - return true; - } - - ScreenCoordsArrayHandle ScreenCoords; - TextureCoordsArrayHandle TextureCoords; - FontTextureType FontTexture; - ColorBufferType ColorBuffer; - DepthBufferType DepthBuffer; - RenderBitmapFont Worklet; -}; // struct RenderBitmapFontExecutor -} // namespace internal TextRenderer::TextRenderer(const vtkm::rendering::Canvas* canvas, const vtkm::rendering::BitmapFont& font, - const vtkm::rendering::Canvas::FontTextureType& fontTexture) + const vtkm::rendering::Canvas::FontTextureType& fontTexture, + vtkm::rendering::TextRendererBatcher* textBatcher) : Canvas(canvas) , Font(font) , FontTexture(fontTexture) + , TextBatcher(textBatcher) { } @@ -226,8 +79,8 @@ void TextRenderer::RenderText(const vtkm::Matrix& transform vtkm::Float32 fy = -(0.5f + 0.5f * anchor[1]); vtkm::Float32 fz = 0; - using ScreenCoordsArrayHandle = internal::RenderBitmapFontExecutor::ScreenCoordsArrayHandle; - using TextureCoordsArrayHandle = internal::RenderBitmapFontExecutor::TextureCoordsArrayHandle; + using ScreenCoordsArrayHandle = vtkm::cont::ArrayHandle; + using TextureCoordsArrayHandle = vtkm::cont::ArrayHandle; ScreenCoordsArrayHandle screenCoords; TextureCoordsArrayHandle textureCoords; { @@ -261,15 +114,7 @@ void TextRenderer::RenderText(const vtkm::Matrix& transform } } - vtkm::cont::TryExecute(internal::RenderBitmapFontExecutor(screenCoords, - textureCoords, - FontTexture, - color.Components, - Canvas->GetColorBuffer(), - Canvas->GetDepthBuffer(), - Canvas->GetWidth(), - Canvas->GetHeight(), - depth)); + this->TextBatcher->BatchText(screenCoords, textureCoords, color, depth); } } } // namespace vtkm::rendering diff --git a/vtkm/rendering/TextRenderer.h b/vtkm/rendering/TextRenderer.h index 05f44ca6e..c33ed415f 100644 --- a/vtkm/rendering/TextRenderer.h +++ b/vtkm/rendering/TextRenderer.h @@ -22,6 +22,7 @@ namespace vtkm { namespace rendering { +class TextRendererBatcher; class VTKM_RENDERING_EXPORT TextRenderer { @@ -29,7 +30,8 @@ public: VTKM_CONT TextRenderer(const vtkm::rendering::Canvas* canvas, const vtkm::rendering::BitmapFont& font, - const vtkm::rendering::Canvas::FontTextureType& fontTexture); + const vtkm::rendering::Canvas::FontTextureType& fontTexture, + vtkm::rendering::TextRendererBatcher* textBatcher); VTKM_CONT void RenderText(const vtkm::Vec2f_32& position, @@ -61,6 +63,7 @@ private: const vtkm::rendering::Canvas* Canvas; vtkm::rendering::BitmapFont Font; vtkm::rendering::Canvas::FontTextureType FontTexture; + vtkm::rendering::TextRendererBatcher* TextBatcher; }; } } // namespace vtkm::rendering diff --git a/vtkm/rendering/TextRendererBatcher.cxx b/vtkm/rendering/TextRendererBatcher.cxx new file mode 100644 index 000000000..7545017cb --- /dev/null +++ b/vtkm/rendering/TextRendererBatcher.cxx @@ -0,0 +1,166 @@ +//============================================================================ +// 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 + +#include + +namespace vtkm +{ +namespace rendering +{ +namespace +{ + +struct RenderBitmapFont : public vtkm::worklet::WorkletMapField +{ + using ColorBufferType = vtkm::rendering::Canvas::ColorBufferType; + using DepthBufferType = vtkm::rendering::Canvas::DepthBufferType; + using FontTextureType = vtkm::rendering::Canvas::FontTextureType; + + using ControlSignature = + void(FieldIn, FieldIn, FieldIn, FieldIn, ExecObject, WholeArrayInOut, WholeArrayInOut); + using ExecutionSignature = void(_1, _2, _3, _4, _5, _6, _7); + using InputDomain = _1; + + VTKM_CONT + RenderBitmapFont() {} + + VTKM_CONT + RenderBitmapFont(vtkm::Id width, vtkm::Id height) + : Width(width) + , Height(height) + { + } + + template + VTKM_EXEC void operator()(const vtkm::Vec4f_32& screenCoords, + const vtkm::Vec4f_32& textureCoords, + const vtkm::Vec4f_32& color, + const vtkm::Float32& depth, + const FontTexture& fontTexture, + ColorBufferPortal& colorBuffer, + DepthBufferPortal& depthBuffer) const + { + vtkm::Float32 x0 = Clamp(screenCoords[0], 0.0f, static_cast(Width - 1)); + vtkm::Float32 x1 = Clamp(screenCoords[2], 0.0f, static_cast(Width - 1)); + vtkm::Float32 y0 = Clamp(screenCoords[1], 0.0f, static_cast(Height - 1)); + vtkm::Float32 y1 = Clamp(screenCoords[3], 0.0f, static_cast(Height - 1)); + // For crisp text rendering, we sample the font texture at points smaller than the pixel + // sizes. Here we sample at increments of 0.25f, and scale the reported intensities accordingly + vtkm::Float32 dx = x1 - x0, dy = y1 - y0; + for (vtkm::Float32 x = x0; x <= x1; x += 0.25f) + { + for (vtkm::Float32 y = y0; y <= y1; y += 0.25f) + { + vtkm::Float32 tu = x1 == x0 ? 1.0f : (x - x0) / dx; + vtkm::Float32 tv = y1 == y0 ? 1.0f : (y - y0) / dy; + vtkm::Float32 u = vtkm::Lerp(textureCoords[0], textureCoords[2], tu); + vtkm::Float32 v = vtkm::Lerp(textureCoords[1], textureCoords[3], tv); + vtkm::Float32 intensity = fontTexture.GetColor(u, v)[0] * 0.25f; + Plot(x, y, intensity, color, depth, colorBuffer, depthBuffer); + } + } + } + + template + VTKM_EXEC void Plot(vtkm::Float32 x, + vtkm::Float32 y, + vtkm::Float32 intensity, + vtkm::Vec4f_32 color, + vtkm::Float32 depth, + ColorBufferPortal& colorBuffer, + DepthBufferPortal& depthBuffer) const + { + vtkm::Id index = + static_cast(vtkm::Round(y)) * Width + static_cast(vtkm::Round(x)); + vtkm::Vec4f_32 srcColor = colorBuffer.Get(index); + vtkm::Float32 currentDepth = depthBuffer.Get(index); + bool swap = depth > currentDepth; + + intensity = intensity * color[3]; + color = intensity * color; + color[3] = intensity; + vtkm::Vec4f_32 front = color; + vtkm::Vec4f_32 back = srcColor; + + if (swap) + { + front = srcColor; + back = color; + } + + vtkm::Vec4f_32 blendedColor; + vtkm::Float32 alpha = (1.f - front[3]); + blendedColor[0] = front[0] + back[0] * alpha; + blendedColor[1] = front[1] + back[1] * alpha; + blendedColor[2] = front[2] + back[2] * alpha; + blendedColor[3] = back[3] * alpha + front[3]; + + colorBuffer.Set(index, blendedColor); + } + + VTKM_EXEC + vtkm::Float32 Clamp(vtkm::Float32 v, vtkm::Float32 min, vtkm::Float32 max) const + { + return vtkm::Min(vtkm::Max(v, min), max); + } + + vtkm::Id Width; + vtkm::Id Height; +}; // struct RenderBitmapFont +} // namespace + +TextRendererBatcher::TextRendererBatcher( + const vtkm::rendering::Canvas::FontTextureType& fontTexture) + : FontTexture(fontTexture) +{ +} + +void TextRendererBatcher::BatchText(const ScreenCoordsArrayHandle& screenCoords, + const TextureCoordsArrayHandle& textureCoords, + const vtkm::rendering::Color& color, + const vtkm::Float32& depth) +{ + vtkm::Id textLength = screenCoords.GetNumberOfValues(); + ScreenCoordsArrayHandle::ReadPortalType screenCoordsP = screenCoords.ReadPortal(); + TextureCoordsArrayHandle::ReadPortalType textureCoordsP = textureCoords.ReadPortal(); + for (int i = 0; i < textLength; ++i) + { + this->ScreenCoords.push_back(screenCoordsP.Get(i)); + this->TextureCoords.push_back(textureCoordsP.Get(i)); + this->Colors.push_back(color.Components); + this->Depths.push_back(depth); + } +} + +void TextRendererBatcher::Render(const vtkm::rendering::Canvas* canvas) const +{ + ScreenCoordsArrayHandle screenCoords = + vtkm::cont::make_ArrayHandle(this->ScreenCoords, vtkm::CopyFlag::Off); + TextureCoordsArrayHandle textureCoords = + vtkm::cont::make_ArrayHandle(this->TextureCoords, vtkm::CopyFlag::Off); + vtkm::cont::ArrayHandle colors = + vtkm::cont::make_ArrayHandle(this->Colors, vtkm::CopyFlag::Off); + vtkm::cont::ArrayHandle depths = + vtkm::cont::make_ArrayHandle(this->Depths, vtkm::CopyFlag::Off); + + vtkm::cont::Invoker invoker; + invoker(RenderBitmapFont(canvas->GetWidth(), canvas->GetHeight()), + screenCoords, + textureCoords, + colors, + depths, + this->FontTexture.GetExecObjectFactory(), + canvas->GetColorBuffer(), + canvas->GetDepthBuffer()); +} +} +} // namespace vtkm::rendering diff --git a/vtkm/rendering/TextRendererBatcher.h b/vtkm/rendering/TextRendererBatcher.h new file mode 100644 index 000000000..b84cf0cb6 --- /dev/null +++ b/vtkm/rendering/TextRendererBatcher.h @@ -0,0 +1,65 @@ +//============================================================================ +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notice for more information. +//============================================================================ + +#ifndef vtk_m_rendering_TextRendererBatcher_h +#define vtk_m_rendering_TextRendererBatcher_h + +#include +#include + +#include +#include +#include +#include + +namespace vtkm +{ +namespace rendering +{ + +class VTKM_RENDERING_EXPORT TextRendererBatcher +{ +public: + using FontTextureType = vtkm::rendering::Canvas::FontTextureType; + using ScreenCoordsType = vtkm::Id4; + using TextureCoordsType = vtkm::Vec4f_32; + using ColorType = vtkm::Vec4f_32; + using ScreenCoordsArrayHandle = vtkm::cont::ArrayHandle; + using TextureCoordsArrayHandle = vtkm::cont::ArrayHandle; + using ColorsArrayHandle = vtkm::cont::ArrayHandle; + using DepthsArrayHandle = vtkm::cont::ArrayHandle; + + /* + VTKM_CONT + TextRendererBatcher(); + */ + + VTKM_CONT + TextRendererBatcher(const vtkm::rendering::Canvas::FontTextureType& fontTexture); + + VTKM_CONT + void BatchText(const ScreenCoordsArrayHandle& screenCoords, + const TextureCoordsArrayHandle& textureCoords, + const vtkm::rendering::Color& color, + const vtkm::Float32& depth); + + void Render(const vtkm::rendering::Canvas* canvas) const; + +private: + vtkm::rendering::Canvas::FontTextureType FontTexture; + std::vector ScreenCoords; + std::vector TextureCoords; + std::vector Colors; + std::vector Depths; +}; +} +} // namespace vtkm::rendering + +#endif // vtk_m_rendering_TextRendererBatcher_h diff --git a/vtkm/rendering/View.cxx b/vtkm/rendering/View.cxx index ec42c6dca..e3c775c64 100644 --- a/vtkm/rendering/View.cxx +++ b/vtkm/rendering/View.cxx @@ -197,10 +197,14 @@ void View::RenderAnnotations() { this->SetupForScreenSpace(); this->RenderScreenAnnotations(); + + this->GetCanvas().BeginTextRenderingBatch(); for (auto& textAnnotation : this->Internal->TextAnnotations) { textAnnotation->Render(this->GetCamera(), this->GetWorldAnnotator(), this->GetCanvas()); } + this->GetCanvas().EndTextRenderingBatch(); + for (auto& additionalAnnotation : this->Internal->AdditionalAnnotations) { additionalAnnotation(); diff --git a/vtkm/rendering/View.h b/vtkm/rendering/View.h index 439529085..ea9a358a2 100644 --- a/vtkm/rendering/View.h +++ b/vtkm/rendering/View.h @@ -99,6 +99,8 @@ public: virtual void RenderScreenAnnotations() = 0; virtual void RenderWorldAnnotations() = 0; + void RenderAnnotations(); + void SaveAs(const std::string& fileName) const; VTKM_CONT VTKM_DEPRECATED(1.6, "Use ClearTextAnnotations Instead") void ClearAnnotations(); @@ -126,7 +128,6 @@ protected: void SetupForScreenSpace(bool viewportClip = false); - void RenderAnnotations(); vtkm::rendering::Color AxisColor = vtkm::rendering::Color::white; bool WorldAnnotationsEnabled = true; diff --git a/vtkm/rendering/View1D.cxx b/vtkm/rendering/View1D.cxx index d6d1f3c33..673014b50 100644 --- a/vtkm/rendering/View1D.cxx +++ b/vtkm/rendering/View1D.cxx @@ -60,6 +60,8 @@ void View1D::RenderScreenAnnotations() viewportBottom, viewportTop); + this->GetCanvas().BeginTextRenderingBatch(); + this->GetWorldAnnotator().BeginLineRenderingBatch(); this->HorizontalAxisAnnotation.SetColor(AxisColor); this->HorizontalAxisAnnotation.SetScreenPosition( viewportLeft, viewportBottom, viewportRight, viewportBottom); @@ -88,6 +90,9 @@ void View1D::RenderScreenAnnotations() vtkm::rendering::TextAnnotation::VCenter); this->VerticalAxisAnnotation.Render( this->GetCamera(), this->GetWorldAnnotator(), this->GetCanvas()); + + this->GetWorldAnnotator().EndLineRenderingBatch(); + this->GetCanvas().EndTextRenderingBatch(); } void View1D::RenderColorLegendAnnotations() @@ -95,6 +100,8 @@ void View1D::RenderColorLegendAnnotations() if (LegendEnabled) { this->Legend.Clear(); + this->GetWorldAnnotator().BeginLineRenderingBatch(); + this->GetCanvas().BeginTextRenderingBatch(); for (int i = 0; i < this->GetScene().GetNumberOfActors(); ++i) { vtkm::rendering::Actor act = this->GetScene().GetActor(i); @@ -110,6 +117,8 @@ void View1D::RenderColorLegendAnnotations() } this->Legend.SetLabelColor(this->GetCanvas().GetForegroundColor()); this->Legend.Render(this->GetCamera(), this->GetWorldAnnotator(), this->GetCanvas()); + this->GetWorldAnnotator().EndLineRenderingBatch(); + this->GetCanvas().EndTextRenderingBatch(); } } diff --git a/vtkm/rendering/View2D.cxx b/vtkm/rendering/View2D.cxx index 2f0268726..04e6558b5 100644 --- a/vtkm/rendering/View2D.cxx +++ b/vtkm/rendering/View2D.cxx @@ -56,6 +56,8 @@ void View2D::RenderScreenAnnotations() viewportRight, viewportBottom, viewportTop); + this->GetCanvas().BeginTextRenderingBatch(); + this->GetWorldAnnotator().BeginLineRenderingBatch(); this->HorizontalAxisAnnotation.SetColor(AxisColor); this->HorizontalAxisAnnotation.SetScreenPosition( viewportLeft, viewportBottom, viewportRight, viewportBottom); @@ -91,6 +93,8 @@ void View2D::RenderScreenAnnotations() this->ColorBarAnnotation.Render( this->GetCamera(), this->GetWorldAnnotator(), this->GetCanvas()); } + this->GetWorldAnnotator().EndLineRenderingBatch(); + this->GetCanvas().EndTextRenderingBatch(); } void View2D::RenderWorldAnnotations() diff --git a/vtkm/rendering/View3D.cxx b/vtkm/rendering/View3D.cxx index 71906ca00..aa5076120 100644 --- a/vtkm/rendering/View3D.cxx +++ b/vtkm/rendering/View3D.cxx @@ -47,17 +47,22 @@ void View3D::RenderScreenAnnotations() { if (this->GetScene().GetNumberOfActors() > 0) { + this->GetCanvas().BeginTextRenderingBatch(); + this->GetWorldAnnotator().BeginLineRenderingBatch(); //this->ColorBarAnnotation.SetAxisColor(vtkm::rendering::Color(1,1,1)); this->ColorBarAnnotation.SetFieldName(this->GetScene().GetActor(0).GetScalarField().GetName()); this->ColorBarAnnotation.SetRange(this->GetScene().GetActor(0).GetScalarRange(), 5); this->ColorBarAnnotation.SetColorTable(this->GetScene().GetActor(0).GetColorTable()); this->ColorBarAnnotation.Render( this->GetCamera(), this->GetWorldAnnotator(), this->GetCanvas()); + this->GetWorldAnnotator().EndLineRenderingBatch(); + this->GetCanvas().EndTextRenderingBatch(); } } void View3D::RenderWorldAnnotations() { + this->GetCanvas().BeginTextRenderingBatch(); vtkm::Bounds bounds = this->GetScene().GetSpatialBounds(); vtkm::Float64 xmin = bounds.X.Min, xmax = bounds.X.Max; vtkm::Float64 ymin = bounds.Y.Min, ymax = bounds.Y.Max; @@ -65,9 +70,11 @@ void View3D::RenderWorldAnnotations() vtkm::Float64 dx = xmax - xmin, dy = ymax - ymin, dz = zmax - zmin; vtkm::Float64 size = vtkm::Sqrt(dx * dx + dy * dy + dz * dz); + this->GetWorldAnnotator().BeginLineRenderingBatch(); this->BoxAnnotation.SetColor(Color(.5f, .5f, .5f)); this->BoxAnnotation.SetExtents(this->GetScene().GetSpatialBounds()); this->BoxAnnotation.Render(this->GetCamera(), this->GetWorldAnnotator()); + this->GetWorldAnnotator().EndLineRenderingBatch(); vtkm::Vec3f_32 lookAt = this->GetCamera().GetLookAt(); vtkm::Vec3f_32 position = this->GetCamera().GetPosition(); @@ -86,6 +93,7 @@ void View3D::RenderWorldAnnotations() vtkm::Float64 yrel = vtkm::Abs(dy) / size; vtkm::Float64 zrel = vtkm::Abs(dz) / size; + this->GetWorldAnnotator().BeginLineRenderingBatch(); this->XAxisAnnotation.SetAxis(0); this->XAxisAnnotation.SetColor(AxisColor); this->XAxisAnnotation.SetTickInvert(xtest, ytest, ztest); @@ -121,6 +129,9 @@ void View3D::RenderWorldAnnotations() this->ZAxisAnnotation.SetLabelFontOffset(vtkm::Float32(size / 15.f)); this->ZAxisAnnotation.SetMoreOrLessTickAdjustment(zrel < .3 ? -1 : 0); this->ZAxisAnnotation.Render(this->GetCamera(), this->GetWorldAnnotator(), this->GetCanvas()); + this->GetWorldAnnotator().EndLineRenderingBatch(); + + this->GetCanvas().EndTextRenderingBatch(); } } } // namespace vtkm::rendering diff --git a/vtkm/rendering/View3D.h b/vtkm/rendering/View3D.h index c13160309..2648f1676 100644 --- a/vtkm/rendering/View3D.h +++ b/vtkm/rendering/View3D.h @@ -47,6 +47,7 @@ public: private: // 3D-specific annotations + vtkm::rendering::LineRendererBatcher LineBatcher; vtkm::rendering::BoundingBoxAnnotation BoxAnnotation; vtkm::rendering::AxisAnnotation3D XAxisAnnotation; vtkm::rendering::AxisAnnotation3D YAxisAnnotation; diff --git a/vtkm/rendering/WorldAnnotator.cxx b/vtkm/rendering/WorldAnnotator.cxx index 19f6c58d3..1e8126112 100644 --- a/vtkm/rendering/WorldAnnotator.cxx +++ b/vtkm/rendering/WorldAnnotator.cxx @@ -32,10 +32,24 @@ void WorldAnnotator::AddLine(const vtkm::Vec3f_64& point0, { vtkm::Matrix transform = vtkm::MatrixMultiply(Canvas->GetProjection(), Canvas->GetModelView()); - LineRenderer renderer(Canvas, transform); + vtkm::rendering::WorldAnnotator* self = const_cast(this); + LineRenderer renderer(Canvas, transform, &(self->LineBatcher)); renderer.RenderLine(point0, point1, lineWidth, color); } +void WorldAnnotator::BeginLineRenderingBatch() const +{ + vtkm::rendering::WorldAnnotator* self = const_cast(this); + self->LineBatcher = vtkm::rendering::LineRendererBatcher(); +} + +void WorldAnnotator::EndLineRenderingBatch() const +{ + vtkm::rendering::WorldAnnotator* self = const_cast(this); + vtkm::rendering::Canvas* canvas = const_cast(this->Canvas); + self->LineBatcher.Render(canvas); +} + void WorldAnnotator::AddText(const vtkm::Vec3f_32& origin, const vtkm::Vec3f_32& right, const vtkm::Vec3f_32& up, diff --git a/vtkm/rendering/WorldAnnotator.h b/vtkm/rendering/WorldAnnotator.h index 5d20bf87a..abb178d7b 100644 --- a/vtkm/rendering/WorldAnnotator.h +++ b/vtkm/rendering/WorldAnnotator.h @@ -15,6 +15,7 @@ #include #include #include +#include namespace vtkm { @@ -51,6 +52,12 @@ public: vtkm::make_Vec(x0, y0, z0), vtkm::make_Vec(x1, y1, z1), lineWidth, color, inFront); } + VTKM_CONT + void BeginLineRenderingBatch() const; + + VTKM_CONT + void EndLineRenderingBatch() const; + virtual void AddText(const vtkm::Vec3f_32& origin, const vtkm::Vec3f_32& right, const vtkm::Vec3f_32& up, @@ -87,6 +94,7 @@ public: private: const vtkm::rendering::Canvas* Canvas; + vtkm::rendering::LineRendererBatcher LineBatcher; }; } } //namespace vtkm::rendering diff --git a/vtkm/source/Oscillator.cxx b/vtkm/source/Oscillator.cxx index e1b0b2f82..fb80b95df 100644 --- a/vtkm/source/Oscillator.cxx +++ b/vtkm/source/Oscillator.cxx @@ -8,56 +8,188 @@ // PURPOSE. See the above copyright notice for more information. //============================================================================ #include +#include namespace vtkm { namespace source { +namespace internal +{ +struct Oscillator +{ + vtkm::Vec3f Center; + vtkm::FloatDefault Radius; + vtkm::FloatDefault Omega; + vtkm::FloatDefault Zeta; +}; + +class OscillatorSource : public vtkm::worklet::WorkletMapField +{ +public: + typedef void ControlSignature(FieldIn, FieldOut); + typedef _2 ExecutionSignature(_1); + + VTKM_CONT + void AddPeriodic(vtkm::FloatDefault x, + vtkm::FloatDefault y, + vtkm::FloatDefault z, + vtkm::FloatDefault radius, + vtkm::FloatDefault omega, + vtkm::FloatDefault zeta) + { + if (this->PeriodicOscillators.GetNumberOfComponents() < MAX_OSCILLATORS) + { + this->PeriodicOscillators.Append(Oscillator{ { x, y, z }, radius, omega, zeta }); + } + } + + VTKM_CONT + void AddDamped(vtkm::FloatDefault x, + vtkm::FloatDefault y, + vtkm::FloatDefault z, + vtkm::FloatDefault radius, + vtkm::FloatDefault omega, + vtkm::FloatDefault zeta) + { + if (this->DampedOscillators.GetNumberOfComponents() < MAX_OSCILLATORS) + { + this->DampedOscillators.Append(Oscillator{ { x, y, z }, radius, omega, zeta }); + } + } + + VTKM_CONT + void AddDecaying(vtkm::FloatDefault x, + vtkm::FloatDefault y, + vtkm::FloatDefault z, + vtkm::FloatDefault radius, + vtkm::FloatDefault omega, + vtkm::FloatDefault zeta) + { + if (this->DecayingOscillators.GetNumberOfComponents() < MAX_OSCILLATORS) + { + this->DecayingOscillators.Append(Oscillator{ { x, y, z }, radius, omega, zeta }); + } + } + + VTKM_CONT + void SetTime(vtkm::FloatDefault time) { this->Time = time; } + + VTKM_EXEC + vtkm::FloatDefault operator()(const vtkm::Vec3f& vec) const + { + vtkm::UInt8 oIdx; + vtkm::FloatDefault t0, t, result = 0; + const internal::Oscillator* oscillator; + + t0 = 0.0; + t = vtkm::FloatDefault(this->Time * 2 * 3.14159265358979323846); + + // Compute damped + for (oIdx = 0; oIdx < this->DampedOscillators.GetNumberOfComponents(); oIdx++) + { + oscillator = &this->DampedOscillators[oIdx]; + + vtkm::Vec3f delta = oscillator->Center - vec; + vtkm::FloatDefault dist2 = dot(delta, delta); + vtkm::FloatDefault dist_damp = + vtkm::Exp(-dist2 / (2 * oscillator->Radius * oscillator->Radius)); + vtkm::FloatDefault phi = vtkm::ACos(oscillator->Zeta); + vtkm::FloatDefault val = vtkm::FloatDefault( + 1. - + vtkm::Exp(-oscillator->Zeta * oscillator->Omega * t0) * + (vtkm::Sin(vtkm::Sqrt(1 - oscillator->Zeta * oscillator->Zeta) * oscillator->Omega * t + + phi) / + vtkm::Sin(phi))); + result += val * dist_damp; + } + + // Compute decaying + for (oIdx = 0; oIdx < this->DecayingOscillators.GetNumberOfComponents(); oIdx++) + { + oscillator = &this->DecayingOscillators[oIdx]; + t = t0 + 1 / oscillator->Omega; + vtkm::Vec3f delta = oscillator->Center - vec; + vtkm::FloatDefault dist2 = dot(delta, delta); + vtkm::FloatDefault dist_damp = + vtkm::Exp(-dist2 / (2 * oscillator->Radius * oscillator->Radius)); + vtkm::FloatDefault val = vtkm::Sin(t / oscillator->Omega) / (oscillator->Omega * t); + result += val * dist_damp; + } + + // Compute periodic + for (oIdx = 0; oIdx < this->PeriodicOscillators.GetNumberOfComponents(); oIdx++) + { + oscillator = &this->PeriodicOscillators[oIdx]; + t = t0 + 1 / oscillator->Omega; + vtkm::Vec3f delta = oscillator->Center - vec; + vtkm::FloatDefault dist2 = dot(delta, delta); + vtkm::FloatDefault dist_damp = + vtkm::Exp(-dist2 / (2 * oscillator->Radius * oscillator->Radius)); + vtkm::FloatDefault val = vtkm::Sin(t / oscillator->Omega); + result += val * dist_damp; + } + + // We are done... + return result; + } + +private: + static constexpr vtkm::IdComponent MAX_OSCILLATORS = 10; + vtkm::VecVariable PeriodicOscillators; + vtkm::VecVariable DampedOscillators; + vtkm::VecVariable DecayingOscillators; + vtkm::FloatDefault Time; +}; // OscillatorSource + +} // internal //----------------------------------------------------------------------------- Oscillator::Oscillator(vtkm::Id3 dims) : Dims(dims) - , Worklet() + , Worklet(std::make_unique()) { } +Oscillator::~Oscillator() = default; + //----------------------------------------------------------------------------- -void Oscillator::SetTime(vtkm::Float64 time) +void Oscillator::SetTime(vtkm::FloatDefault time) { - this->Worklet.SetTime(time); + this->Worklet->SetTime(time); } //----------------------------------------------------------------------------- -void Oscillator::AddPeriodic(vtkm::Float64 x, - vtkm::Float64 y, - vtkm::Float64 z, - vtkm::Float64 radius, - vtkm::Float64 omega, - vtkm::Float64 zeta) +void Oscillator::AddPeriodic(vtkm::FloatDefault x, + vtkm::FloatDefault y, + vtkm::FloatDefault z, + vtkm::FloatDefault radius, + vtkm::FloatDefault omega, + vtkm::FloatDefault zeta) { - this->Worklet.AddPeriodic(x, y, z, radius, omega, zeta); + this->Worklet->AddPeriodic(x, y, z, radius, omega, zeta); } //----------------------------------------------------------------------------- -void Oscillator::AddDamped(vtkm::Float64 x, - vtkm::Float64 y, - vtkm::Float64 z, - vtkm::Float64 radius, - vtkm::Float64 omega, - vtkm::Float64 zeta) +void Oscillator::AddDamped(vtkm::FloatDefault x, + vtkm::FloatDefault y, + vtkm::FloatDefault z, + vtkm::FloatDefault radius, + vtkm::FloatDefault omega, + vtkm::FloatDefault zeta) { - this->Worklet.AddDamped(x, y, z, radius, omega, zeta); + this->Worklet->AddDamped(x, y, z, radius, omega, zeta); } //----------------------------------------------------------------------------- -void Oscillator::AddDecaying(vtkm::Float64 x, - vtkm::Float64 y, - vtkm::Float64 z, - vtkm::Float64 radius, - vtkm::Float64 omega, - vtkm::Float64 zeta) +void Oscillator::AddDecaying(vtkm::FloatDefault x, + vtkm::FloatDefault y, + vtkm::FloatDefault z, + vtkm::FloatDefault radius, + vtkm::FloatDefault omega, + vtkm::FloatDefault zeta) { - this->Worklet.AddDecaying(x, y, z, radius, omega, zeta); + this->Worklet->AddDecaying(x, y, z, radius, omega, zeta); } @@ -68,8 +200,9 @@ vtkm::cont::DataSet Oscillator::Execute() const vtkm::cont::DataSet dataSet; + const vtkm::Id3 pdims{ this->Dims + vtkm::Id3{ 1, 1, 1 } }; vtkm::cont::CellSetStructured<3> cellSet; - cellSet.SetPointDimensions(this->Dims); + cellSet.SetPointDimensions(pdims); dataSet.SetCellSet(cellSet); const vtkm::Vec3f origin(0.0f, 0.0f, 0.0f); @@ -77,15 +210,12 @@ vtkm::cont::DataSet Oscillator::Execute() const 1.0f / static_cast(this->Dims[1]), 1.0f / static_cast(this->Dims[2])); - const vtkm::Id3 pdims{ this->Dims + vtkm::Id3{ 1, 1, 1 } }; vtkm::cont::ArrayHandleUniformPointCoordinates coordinates(pdims, origin, spacing); dataSet.AddCoordinateSystem(vtkm::cont::CoordinateSystem("coordinates", coordinates)); - vtkm::cont::ArrayHandle outArray; - //todo, we need to use the policy to determine the valid conversions - //that the dispatcher should do - this->Invoke(this->Worklet, coordinates, outArray); + vtkm::cont::ArrayHandle outArray; + this->Invoke(*(this->Worklet), coordinates, outArray); dataSet.AddField(vtkm::cont::make_FieldPoint("oscillating", outArray)); return dataSet; diff --git a/vtkm/source/Oscillator.h b/vtkm/source/Oscillator.h index 898cb0512..d9558d088 100644 --- a/vtkm/source/Oscillator.h +++ b/vtkm/source/Oscillator.h @@ -11,12 +11,15 @@ #define vtk_m_source_OscillatorSource_h #include -#include namespace vtkm { namespace source { +namespace internal +{ +class OscillatorSource; +} /**\brief An analytical, time-varying uniform dataset with a point based array * @@ -33,38 +36,44 @@ public: VTKM_CONT Oscillator(vtkm::Id3 dims); + // We can not declare default destructor here since compiler does not know how + // to create one for the Worklet at this point yet. However, the implementation + // in Oscillator.cxx does have ~Oscillator() = default; VTKM_CONT - void SetTime(vtkm::Float64 time); + ~Oscillator(); VTKM_CONT - void AddPeriodic(vtkm::Float64 x, - vtkm::Float64 y, - vtkm::Float64 z, - vtkm::Float64 radius, - vtkm::Float64 omega, - vtkm::Float64 zeta); + void SetTime(vtkm::FloatDefault time); VTKM_CONT - void AddDamped(vtkm::Float64 x, - vtkm::Float64 y, - vtkm::Float64 z, - vtkm::Float64 radius, - vtkm::Float64 omega, - vtkm::Float64 zeta); + void AddPeriodic(vtkm::FloatDefault x, + vtkm::FloatDefault y, + vtkm::FloatDefault z, + vtkm::FloatDefault radius, + vtkm::FloatDefault omega, + vtkm::FloatDefault zeta); VTKM_CONT - void AddDecaying(vtkm::Float64 x, - vtkm::Float64 y, - vtkm::Float64 z, - vtkm::Float64 radius, - vtkm::Float64 omega, - vtkm::Float64 zeta); + void AddDamped(vtkm::FloatDefault x, + vtkm::FloatDefault y, + vtkm::FloatDefault z, + vtkm::FloatDefault radius, + vtkm::FloatDefault omega, + vtkm::FloatDefault zeta); + + VTKM_CONT + void AddDecaying(vtkm::FloatDefault x, + vtkm::FloatDefault y, + vtkm::FloatDefault z, + vtkm::FloatDefault radius, + vtkm::FloatDefault omega, + vtkm::FloatDefault zeta); VTKM_CONT vtkm::cont::DataSet Execute() const; private: vtkm::Id3 Dims; - vtkm::worklet::OscillatorSource Worklet; + std::unique_ptr Worklet; }; } } diff --git a/vtkm/source/testing/CMakeLists.txt b/vtkm/source/testing/CMakeLists.txt index cb2db6f86..cc9f9c3bd 100644 --- a/vtkm/source/testing/CMakeLists.txt +++ b/vtkm/source/testing/CMakeLists.txt @@ -9,6 +9,7 @@ ##============================================================================ set(unit_tests + UnitTestOscillatorSource.cxx UnitTestTangleSource.cxx UnitTestWaveletSource.cxx ) @@ -16,5 +17,4 @@ set(unit_tests vtkm_unit_tests( SOURCES ${unit_tests} LIBRARIES vtkm_source - ALL_BACKENDS ) diff --git a/vtkm/source/testing/UnitTestOscillatorSource.cxx b/vtkm/source/testing/UnitTestOscillatorSource.cxx new file mode 100644 index 000000000..5ffb596bb --- /dev/null +++ b/vtkm/source/testing/UnitTestOscillatorSource.cxx @@ -0,0 +1,66 @@ +//============================================================================ +// 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 + +#include +#include + +void OscillatorSourceTest() +{ + vtkm::cont::Timer timer; + timer.Start(); + + vtkm::source::Oscillator source(vtkm::Id3{ 20, 20, 20 }); + source.SetTime(0.5); + source.AddDamped(0.25f, 0.25f, 0.25f, 0.5f, 0.1f, 0.2f); + source.AddDecaying(0.5f, 0.5f, 0.5f, 0.35f, 0.2f, 0.1f); + source.AddPeriodic(0.6f, 0.2f, 0.7f, 0.15f, 0.1f, 0.2f); + + vtkm::cont::DataSet ds = source.Execute(); + + double time = timer.GetElapsedTime(); + + std::cout << "Default oscillator took " << time << "s.\n"; + + { + auto coords = ds.GetCoordinateSystem("coordinates"); + auto data = coords.GetData(); + VTKM_TEST_ASSERT(test_equal(data.GetNumberOfValues(), 9261), "Incorrect number of points."); + } + + { + auto cells = ds.GetCellSet(); + VTKM_TEST_ASSERT(test_equal(cells.GetNumberOfCells(), 8000), "Incorrect number of cells."); + } + + // Spot check some node scalars + { + using ScalarHandleType = vtkm::cont::ArrayHandle; + + auto field = ds.GetPointField("oscillating"); + auto dynData = field.GetData(); + VTKM_TEST_ASSERT(dynData.IsType(), "Invalid scalar handle type."); + ScalarHandleType handle = dynData.AsArrayHandle(); + auto data = handle.ReadPortal(); + + VTKM_TEST_ASSERT(test_equal(data.GetNumberOfValues(), 9261), "Incorrect number of scalars."); + + VTKM_TEST_ASSERT(test_equal(data.Get(0), -0.0163996), "Incorrect scalar value."); + VTKM_TEST_ASSERT(test_equal(data.Get(16), -0.0182232), "Incorrect scalar value."); + VTKM_TEST_ASSERT(test_equal(data.Get(21), -0.0181952), "Incorrect scalar value."); + VTKM_TEST_ASSERT(test_equal(data.Get(3110), -0.0404135), "Incorrect scalar value."); + } +} + +int UnitTestOscillatorSource(int argc, char* argv[]) +{ + return vtkm::cont::testing::Testing::Run(OscillatorSourceTest, argc, argv); +} diff --git a/vtkm/source/testing/UnitTestWaveletSource.cxx b/vtkm/source/testing/UnitTestWaveletSource.cxx index a4d741eeb..8c4c0f169 100644 --- a/vtkm/source/testing/UnitTestWaveletSource.cxx +++ b/vtkm/source/testing/UnitTestWaveletSource.cxx @@ -10,7 +10,6 @@ #include -#include #include void WaveletSourceTest() diff --git a/vtkm/worklet/CMakeLists.txt b/vtkm/worklet/CMakeLists.txt index 513d5f3e5..d238db45c 100644 --- a/vtkm/worklet/CMakeLists.txt +++ b/vtkm/worklet/CMakeLists.txt @@ -57,7 +57,6 @@ set(headers OrientNormals.h OrientPointNormals.h OrientPointAndCellNormals.h - OscillatorSource.h ParticleAdvection.h PointAverage.h PointElevation.h diff --git a/vtkm/worklet/OscillatorSource.h b/vtkm/worklet/OscillatorSource.h deleted file mode 100644 index f3c0ca11e..000000000 --- a/vtkm/worklet/OscillatorSource.h +++ /dev/null @@ -1,187 +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. -//============================================================================ -#ifndef vtk_m_worklet_OscillatorSource_h -#define vtk_m_worklet_OscillatorSource_h - -#include -#include - -#define MAX_OSCILLATORS 10 - -namespace vtkm -{ -namespace worklet -{ -namespace internal -{ - -struct Oscillator -{ - void Set(vtkm::Float64 x, - vtkm::Float64 y, - vtkm::Float64 z, - vtkm::Float64 radius, - vtkm::Float64 omega, - vtkm::Float64 zeta) - { - this->Center[0] = x; - this->Center[1] = y; - this->Center[2] = z; - this->Radius = radius; - this->Omega = omega; - this->Zeta = zeta; - } - - vtkm::Vec3f_64 Center; - vtkm::Float64 Radius; - vtkm::Float64 Omega; - vtkm::Float64 Zeta; -}; -} - -class OscillatorSource : public vtkm::worklet::WorkletMapField -{ -public: - typedef void ControlSignature(FieldIn, FieldOut); - typedef _2 ExecutionSignature(_1); - - VTKM_CONT - OscillatorSource() - : NumberOfPeriodics(0) - , NumberOfDamped(0) - , NumberOfDecaying(0) - { - } - - VTKM_CONT - void AddPeriodic(vtkm::Float64 x, - vtkm::Float64 y, - vtkm::Float64 z, - vtkm::Float64 radius, - vtkm::Float64 omega, - vtkm::Float64 zeta) - { - if (this->NumberOfPeriodics < MAX_OSCILLATORS) - { - this->PeriodicOscillators[this->NumberOfPeriodics].Set(x, y, z, radius, omega, zeta); - this->NumberOfPeriodics++; - } - } - - VTKM_CONT - void AddDamped(vtkm::Float64 x, - vtkm::Float64 y, - vtkm::Float64 z, - vtkm::Float64 radius, - vtkm::Float64 omega, - vtkm::Float64 zeta) - { - if (this->NumberOfDamped < MAX_OSCILLATORS) - { - this->DampedOscillators[this->NumberOfDamped * 6].Set(x, y, z, radius, omega, zeta); - this->NumberOfDamped++; - } - } - - VTKM_CONT - void AddDecaying(vtkm::Float64 x, - vtkm::Float64 y, - vtkm::Float64 z, - vtkm::Float64 radius, - vtkm::Float64 omega, - vtkm::Float64 zeta) - { - if (this->NumberOfDecaying < MAX_OSCILLATORS) - { - this->DecayingOscillators[this->NumberOfDecaying * 6].Set(x, y, z, radius, omega, zeta); - this->NumberOfDecaying++; - } - } - - VTKM_CONT - void SetTime(vtkm::Float64 time) { this->Time = time; } - - VTKM_EXEC - vtkm::Float64 operator()(const vtkm::Vec3f_64& vec) const - { - vtkm::UInt8 oIdx; - vtkm::Float64 t0, t, result = 0; - const internal::Oscillator* oscillator; - - t0 = 0.0; - t = this->Time * 2 * 3.14159265358979323846; - - // Compute damped - for (oIdx = 0; oIdx < this->NumberOfDamped; oIdx++) - { - oscillator = &this->DampedOscillators[oIdx]; - - vtkm::Vec3f_64 delta = oscillator->Center - vec; - vtkm::Float64 dist2 = dot(delta, delta); - vtkm::Float64 dist_damp = vtkm::Exp(-dist2 / (2 * oscillator->Radius * oscillator->Radius)); - vtkm::Float64 phi = vtkm::ACos(oscillator->Zeta); - vtkm::Float64 val = 1. - - vtkm::Exp(-oscillator->Zeta * oscillator->Omega * t0) * - (vtkm::Sin(vtkm::Sqrt(1 - oscillator->Zeta * oscillator->Zeta) * oscillator->Omega * t + - phi) / - vtkm::Sin(phi)); - result += val * dist_damp; - } - - // Compute decaying - for (oIdx = 0; oIdx < this->NumberOfDecaying; oIdx++) - { - oscillator = &this->DecayingOscillators[oIdx]; - t = t0 + 1 / oscillator->Omega; - vtkm::Vec3f_64 delta = oscillator->Center - vec; - vtkm::Float64 dist2 = dot(delta, delta); - vtkm::Float64 dist_damp = vtkm::Exp(-dist2 / (2 * oscillator->Radius * oscillator->Radius)); - vtkm::Float64 val = vtkm::Sin(t / oscillator->Omega) / (oscillator->Omega * t); - result += val * dist_damp; - } - - // Compute periodic - for (oIdx = 0; oIdx < this->NumberOfPeriodics; oIdx++) - { - oscillator = &this->PeriodicOscillators[oIdx]; - t = t0 + 1 / oscillator->Omega; - vtkm::Vec3f_64 delta = oscillator->Center - vec; - vtkm::Float64 dist2 = dot(delta, delta); - vtkm::Float64 dist_damp = vtkm::Exp(-dist2 / (2 * oscillator->Radius * oscillator->Radius)); - vtkm::Float64 val = vtkm::Sin(t / oscillator->Omega); - result += val * dist_damp; - } - - // We are done... - return result; - } - - template - VTKM_EXEC vtkm::Float64 operator()(const vtkm::Vec& vec) const - { - return (*this)(vtkm::make_Vec(static_cast(vec[0]), - static_cast(vec[1]), - static_cast(vec[2]))); - } - -private: - vtkm::Vec PeriodicOscillators; - vtkm::Vec DampedOscillators; - vtkm::Vec DecayingOscillators; - vtkm::UInt8 NumberOfPeriodics; - vtkm::UInt8 NumberOfDamped; - vtkm::UInt8 NumberOfDecaying; - vtkm::Float64 Time; -}; -} - -} // namespace vtkm - -#endif // vtk_m_worklet_PointElevation_h diff --git a/vtkm/worklet/particleadvection/Field.h b/vtkm/worklet/particleadvection/Field.h index b0cf5fde0..d93358966 100644 --- a/vtkm/worklet/particleadvection/Field.h +++ b/vtkm/worklet/particleadvection/Field.h @@ -30,21 +30,36 @@ class ExecutionVelocityField { public: using FieldPortalType = typename FieldArrayType::ReadPortalType; + using Association = vtkm::cont::Field::Association; VTKM_CONT - ExecutionVelocityField(FieldArrayType velocityValues, + ExecutionVelocityField(const FieldArrayType& velocityValues, + const Association assoc, vtkm::cont::DeviceAdapterId device, vtkm::cont::Token& token) : VelocityValues(velocityValues.PrepareForInput(device, token)) + , Assoc(assoc) { } + VTKM_EXEC Association GetAssociation() const { return this->Assoc; } + + VTKM_EXEC void GetValue(const vtkm::Id cellId, vtkm::VecVariable& value) const + { + VTKM_ASSERT(this->Assoc == Association::CELL_SET); + + vtkm::Vec3f velocity = VelocityValues.Get(cellId); + value = vtkm::make_Vec(velocity); + } + VTKM_EXEC void GetValue(const vtkm::VecVariable& indices, const vtkm::Id vertices, const vtkm::Vec3f& parametric, const vtkm::UInt8 cellShape, vtkm::VecVariable& value) const { + VTKM_ASSERT(this->Assoc == Association::POINTS); + vtkm::Vec3f velocityInterp; vtkm::VecVariable velocities; for (vtkm::IdComponent i = 0; i < vertices; i++) @@ -55,6 +70,7 @@ public: private: FieldPortalType VelocityValues; + Association Assoc; }; template @@ -62,23 +78,39 @@ class ExecutionElectroMagneticField { public: using FieldPortalType = typename FieldArrayType::ReadPortalType; + using Association = vtkm::cont::Field::Association; VTKM_CONT - ExecutionElectroMagneticField(FieldArrayType electricValues, - FieldArrayType magneticValues, + ExecutionElectroMagneticField(const FieldArrayType& electricValues, + const FieldArrayType& magneticValues, + const Association assoc, vtkm::cont::DeviceAdapterId device, vtkm::cont::Token& token) : ElectricValues(electricValues.PrepareForInput(device, token)) , MagneticValues(magneticValues.PrepareForInput(device, token)) + , Assoc(assoc) { } + VTKM_EXEC Association GetAssociation() const { return this->Assoc; } + + VTKM_EXEC void GetValue(const vtkm::Id cellId, vtkm::VecVariable& value) const + { + VTKM_ASSERT(this->Assoc == Association::CELL_SET); + + auto electric = this->ElectricValues.Get(cellId); + auto magnetic = this->MagneticValues.Get(cellId); + value = vtkm::make_Vec(electric, magnetic); + } + VTKM_EXEC void GetValue(const vtkm::VecVariable& indices, const vtkm::Id vertices, const vtkm::Vec3f& parametric, const vtkm::UInt8 cellShape, vtkm::VecVariable& value) const { + VTKM_ASSERT(this->Assoc == Association::POINTS); + vtkm::Vec3f electricInterp, magneticInterp; vtkm::VecVariable electric; vtkm::VecVariable magnetic; @@ -95,6 +127,7 @@ public: private: FieldPortalType ElectricValues; FieldPortalType MagneticValues; + Association Assoc; }; template @@ -102,6 +135,7 @@ class VelocityField : public vtkm::cont::ExecutionObjectBase { public: using ExecutionType = ExecutionVelocityField; + using Association = vtkm::cont::Field::Association; VTKM_CONT VelocityField() = default; @@ -109,18 +143,29 @@ public: VTKM_CONT VelocityField(const FieldArrayType& fieldValues) : FieldValues(fieldValues) + , Assoc(vtkm::cont::Field::Association::POINTS) { } + VTKM_CONT + VelocityField(const FieldArrayType& fieldValues, const Association assoc) + : FieldValues(fieldValues) + , Assoc(assoc) + { + if (assoc == Association::ANY || assoc == Association::WHOLE_MESH) + throw("Unsupported field association"); + } + VTKM_CONT const ExecutionType PrepareForExecution(vtkm::cont::DeviceAdapterId device, vtkm::cont::Token& token) const { - return ExecutionType(this->FieldValues, device, token); + return ExecutionType(this->FieldValues, this->Assoc, device, token); } private: FieldArrayType FieldValues; + Association Assoc; }; template @@ -128,6 +173,7 @@ class ElectroMagneticField : public vtkm::cont::ExecutionObjectBase { public: using ExecutionType = ExecutionElectroMagneticField; + using Association = vtkm::cont::Field::Association; VTKM_CONT ElectroMagneticField() = default; @@ -136,6 +182,17 @@ public: ElectroMagneticField(const FieldArrayType& electricField, const FieldArrayType& magneticField) : ElectricField(electricField) , MagneticField(magneticField) + , Assoc(vtkm::cont::Field::Association::POINTS) + { + } + + VTKM_CONT + ElectroMagneticField(const FieldArrayType& electricField, + const FieldArrayType& magneticField, + const Association assoc) + : ElectricField(electricField) + , MagneticField(magneticField) + , Assoc(assoc) { } @@ -143,12 +200,13 @@ public: const ExecutionType PrepareForExecution(vtkm::cont::DeviceAdapterId device, vtkm::cont::Token& token) const { - return ExecutionType(this->ElectricField, this->MagneticField, device, token); + return ExecutionType(this->ElectricField, this->MagneticField, this->Assoc, device, token); } private: FieldArrayType ElectricField; FieldArrayType MagneticField; + Association Assoc; }; } // namespace particleadvection diff --git a/vtkm/worklet/particleadvection/GridEvaluators.h b/vtkm/worklet/particleadvection/GridEvaluators.h index 32b90dfa3..26b6eae08 100644 --- a/vtkm/worklet/particleadvection/GridEvaluators.h +++ b/vtkm/worklet/particleadvection/GridEvaluators.h @@ -125,8 +125,17 @@ public: vtkm::IdComponent nVerts; vtkm::VecVariable ptIndices; vtkm::VecVariable fieldValues; - this->InterpolationHelper.GetCellInfo(cellId, cellShape, nVerts, ptIndices); - this->Field.GetValue(ptIndices, nVerts, parametric, cellShape, out); + + if (this->Field.GetAssociation() == vtkm::cont::Field::Association::POINTS) + { + this->InterpolationHelper.GetCellInfo(cellId, cellShape, nVerts, ptIndices); + this->Field.GetValue(ptIndices, nVerts, parametric, cellShape, out); + } + else if (this->Field.GetAssociation() == vtkm::cont::Field::Association::CELL_SET) + { + this->Field.GetValue(cellId, out); + } + status.SetOk(); }