mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-09-08 13:23:51 +00:00
Merge branch 'master' into ollielo-master-patch-72902
This commit is contained in:
commit
b01ba506cf
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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}")
|
||||
|
@ -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)
|
||||
|
43
.gitlab/ci/docker/ubuntu2004/kokkos-hip/Dockerfile
Normal file
43
.gitlab/ci/docker/ubuntu2004/kokkos-hip/Dockerfile
Normal file
@ -0,0 +1,43 @@
|
||||
FROM rocm/dev-ubuntu-20.04
|
||||
LABEL maintainer "Vicente Adolfo Bolea Sanchez<vicente.bolea@kitware.com>"
|
||||
|
||||
# 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
|
@ -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 "")
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -1,4 +1,4 @@
|
||||
VTKm License Version 1.6
|
||||
VTKm License Version 1.7
|
||||
========================================================================
|
||||
|
||||
Copyright (c) 2014-2021
|
||||
|
@ -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
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
#ifndef vtk_m_benchmarking_Benchmarker_h
|
||||
#define vtk_m_benchmarking_Benchmarker_h
|
||||
|
||||
#include <sstream>
|
||||
#include <vtkm/cont/Initialize.h>
|
||||
#include <vtkm/cont/Logging.h>
|
||||
#include <vtkm/cont/RuntimeDeviceTracker.h>
|
||||
|
437
docs/changelog/1.7/release-notes.md
Normal file
437
docs/changelog/1.7/release-notes.md
Normal file
@ -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<T>& 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<vtkm::Id>` 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<vtkm::Vec3f>;
|
||||
using FieldType = vtkm::worklet::particleadvection::VelocityField<FieldType>;
|
||||
|
||||
FieldArray data;
|
||||
field.GetData().AsArrayHandle<FieldArray>(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 <vtkm/filter/Instantiations.h>
|
||||
|
||||
class Contour {
|
||||
template <typename T, typename StorageType, typename DerivedPolicy>
|
||||
vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet&,
|
||||
const vtkm::cont::ArrayHandle<T, StorageType>&,
|
||||
const vtkm::filter::FieldMetadata&,
|
||||
vtkm::filter::PolicyBase<DerivedPolicy>);
|
||||
};
|
||||
|
||||
// 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<vtkm::UInt8>&,
|
||||
const vtkm::filter::FieldMetadata&,
|
||||
vtkm::filter::PolicyBase<vtkm::filter::PolicyDefault>);
|
||||
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 <vtkm/filter/Contour.h>
|
||||
#include <vtkm/filter/Contour.hxx>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace filter
|
||||
{
|
||||
|
||||
template vtkm::cont::DataSet Contour::DoExecute(
|
||||
const vtkm::cont::DataSet&,
|
||||
const vtkm::cont::ArrayHandle<vtkm::UInt8>&,
|
||||
const vtkm::filter::FieldMetadata&,
|
||||
vtkm::filter::PolicyBase<vtkm::filter::PolicyDefault>);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#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.
|
@ -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<T>& 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.
|
@ -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.
|
||||
|
@ -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.
|
@ -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.
|
@ -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.
|
@ -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 <vtkm/filter/Instantiations.h>
|
||||
|
||||
class Contour {
|
||||
template <typename T, typename StorageType, typename DerivedPolicy>
|
||||
vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet&,
|
||||
const vtkm::cont::ArrayHandle<T, StorageType>&,
|
||||
const vtkm::filter::FieldMetadata&,
|
||||
vtkm::filter::PolicyBase<DerivedPolicy>);
|
||||
};
|
||||
|
||||
// 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<vtkm::UInt8>&,
|
||||
const vtkm::filter::FieldMetadata&,
|
||||
vtkm::filter::PolicyBase<vtkm::filter::PolicyDefault>);
|
||||
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 <vtkm/filter/Contour.h>
|
||||
#include <vtkm/filter/Contour.hxx>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace filter
|
||||
{
|
||||
|
||||
template vtkm::cont::DataSet Contour::DoExecute(
|
||||
const vtkm::cont::DataSet&,
|
||||
const vtkm::cont::ArrayHandle<vtkm::UInt8>&,
|
||||
const vtkm::filter::FieldMetadata&,
|
||||
vtkm::filter::PolicyBase<vtkm::filter::PolicyDefault>);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#undef vtkm_filter_ContourInstantiation0_cxx
|
||||
|
||||
```
|
@ -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.
|
@ -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.
|
@ -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.
|
||||
|
@ -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<vtkm::Id>` and uses those.
|
@ -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`.
|
@ -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.
|
@ -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.
|
@ -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)
|
||||
|
@ -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).
|
@ -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.
|
@ -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.
|
@ -1 +1 @@
|
||||
1.6.0
|
||||
1.7.0-rc1
|
||||
|
@ -14,7 +14,6 @@
|
||||
|
||||
#include <vtkm/TopologyElementTag.h>
|
||||
#include <vtkm/cont/CellSet.h>
|
||||
#include <vtkm/cont/DeviceAdapter.h>
|
||||
#include <vtkm/cont/ErrorBadType.h>
|
||||
#include <vtkm/exec/ConnectivityStructured.h>
|
||||
#include <vtkm/internal/ConnectivityStructuredInternals.h>
|
||||
|
@ -14,6 +14,8 @@
|
||||
#include <vtkm/cont/Field.h>
|
||||
#include <vtkm/cont/PartitionedDataSet.h>
|
||||
|
||||
#include <numeric>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace cont
|
||||
|
@ -10,8 +10,6 @@
|
||||
#define vtk_m_cont_StorageVirtual_cxx
|
||||
#include <vtkm/cont/StorageVirtual.h>
|
||||
|
||||
#include <vtkm/cont/DeviceAdapter.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace cont
|
||||
|
@ -10,6 +10,7 @@
|
||||
#ifndef vtk_m_cont_StorageVirtual_hxx
|
||||
#define vtk_m_cont_StorageVirtual_hxx
|
||||
|
||||
#include <vtkm/cont/DeviceAdapter.h>
|
||||
#include <vtkm/cont/StorageVirtual.h>
|
||||
#include <vtkm/cont/TryExecute.h>
|
||||
|
||||
|
@ -7,6 +7,8 @@
|
||||
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
// PURPOSE. See the above copyright notice for more information.
|
||||
//============================================================================
|
||||
#include <vtkm/cont/DeviceAdapter.h>
|
||||
#include <vtkm/cont/DeviceAdapterList.h>
|
||||
#include <vtkm/cont/Logging.h>
|
||||
#include <vtkm/cont/RuntimeDeviceTracker.h>
|
||||
#include <vtkm/cont/Timer.h>
|
||||
|
@ -10,9 +10,7 @@
|
||||
#ifndef vtk_m_cont_Timer_h
|
||||
#define vtk_m_cont_Timer_h
|
||||
|
||||
#include <vtkm/List.h>
|
||||
#include <vtkm/cont/DeviceAdapter.h>
|
||||
#include <vtkm/cont/DeviceAdapterList.h>
|
||||
#include <vtkm/cont/DeviceAdapterTag.h>
|
||||
|
||||
#include <vtkm/cont/vtkm_cont_export.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 <typename T, typename S>
|
||||
VTKM_FORCE_USED static void UnknownAHDelete(void* mem)
|
||||
void UnknownAHDelete(void* mem)
|
||||
{
|
||||
using AH = vtkm::cont::ArrayHandle<T, S>;
|
||||
AH* arrayHandle = reinterpret_cast<AH*>(mem);
|
||||
@ -61,13 +42,13 @@ VTKM_FORCE_USED static void UnknownAHDelete(void* mem)
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
VTKM_FORCE_USED static void* UnknownAHNewInstance()
|
||||
void* UnknownAHNewInstance()
|
||||
{
|
||||
return new vtkm::cont::ArrayHandle<T, S>;
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
VTKM_FORCE_USED static vtkm::Id UnknownAHNumberOfValues(void* mem)
|
||||
vtkm::Id UnknownAHNumberOfValues(void* mem)
|
||||
{
|
||||
using AH = vtkm::cont::ArrayHandle<T, S>;
|
||||
AH* arrayHandle = reinterpret_cast<AH*>(mem);
|
||||
@ -88,7 +69,7 @@ struct UnknownAHNumberOfComponentsImpl<T, vtkm::VecTraitsTagSizeVariable>
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
VTKM_FORCE_USED static vtkm::IdComponent UnknownAHNumberOfComponents()
|
||||
vtkm::IdComponent UnknownAHNumberOfComponents()
|
||||
{
|
||||
return UnknownAHNumberOfComponentsImpl<T>::Value;
|
||||
}
|
||||
@ -107,16 +88,16 @@ struct UnknownAHNumberOfComponentsFlatImpl<T, vtkm::VecTraitsTagSizeVariable>
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
VTKM_FORCE_USED static vtkm::IdComponent UnknownAHNumberOfComponentsFlat()
|
||||
vtkm::IdComponent UnknownAHNumberOfComponentsFlat()
|
||||
{
|
||||
return UnknownAHNumberOfComponentsFlatImpl<T>::Value;
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
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<T, S>;
|
||||
AH* arrayHandle = reinterpret_cast<AH*>(mem);
|
||||
@ -124,7 +105,7 @@ VTKM_FORCE_USED static void UnknownAHAllocate(void* mem,
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
VTKM_FORCE_USED static void UnknownAHShallowCopy(const void* sourceMem, void* destinationMem)
|
||||
void UnknownAHShallowCopy(const void* sourceMem, void* destinationMem)
|
||||
{
|
||||
using AH = vtkm::cont::ArrayHandle<T, S>;
|
||||
const AH* source = reinterpret_cast<const AH*>(sourceMem);
|
||||
@ -133,7 +114,7 @@ VTKM_FORCE_USED static void UnknownAHShallowCopy(const void* sourceMem, void* de
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
VTKM_FORCE_USED static std::vector<vtkm::cont::internal::Buffer>
|
||||
std::vector<vtkm::cont::internal::Buffer>
|
||||
UnknownAHExtractComponent(void* mem, vtkm::IdComponent componentIndex, vtkm::CopyFlag allowCopy)
|
||||
{
|
||||
using AH = vtkm::cont::ArrayHandle<T, S>;
|
||||
@ -144,7 +125,7 @@ UnknownAHExtractComponent(void* mem, vtkm::IdComponent componentIndex, vtkm::Cop
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
VTKM_FORCE_USED static void UnknownAHReleaseResources(void* mem)
|
||||
void UnknownAHReleaseResources(void* mem)
|
||||
{
|
||||
using AH = vtkm::cont::ArrayHandle<T, S>;
|
||||
AH* arrayHandle = reinterpret_cast<AH*>(mem);
|
||||
@ -152,7 +133,7 @@ VTKM_FORCE_USED static void UnknownAHReleaseResources(void* mem)
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
VTKM_FORCE_USED static void UnknownAHReleaseResourcesExecution(void* mem)
|
||||
void UnknownAHReleaseResourcesExecution(void* mem)
|
||||
{
|
||||
using AH = vtkm::cont::ArrayHandle<T, S>;
|
||||
AH* arrayHandle = reinterpret_cast<AH*>(mem);
|
||||
@ -160,7 +141,7 @@ VTKM_FORCE_USED static void UnknownAHReleaseResourcesExecution(void* mem)
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
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<T, S>;
|
||||
AH* arrayHandle = reinterpret_cast<AH*>(mem);
|
||||
@ -300,47 +281,42 @@ private:
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
VTKM_FORCE_USED static std::shared_ptr<UnknownAHContainer> UnknownAHNewInstanceBasic(
|
||||
vtkm::VecTraitsTagSizeStatic)
|
||||
std::shared_ptr<UnknownAHContainer> UnknownAHNewInstanceBasic(vtkm::VecTraitsTagSizeStatic)
|
||||
{
|
||||
return UnknownAHContainer::Make(vtkm::cont::ArrayHandleBasic<T>{});
|
||||
}
|
||||
template <typename T>
|
||||
VTKM_FORCE_USED static std::shared_ptr<UnknownAHContainer> UnknownAHNewInstanceBasic(
|
||||
vtkm::VecTraitsTagSizeVariable)
|
||||
std::shared_ptr<UnknownAHContainer> UnknownAHNewInstanceBasic(vtkm::VecTraitsTagSizeVariable)
|
||||
{
|
||||
throw vtkm::cont::ErrorBadType("Cannot create a basic array container from with ValueType of " +
|
||||
vtkm::cont::TypeToString<T>());
|
||||
}
|
||||
template <typename T>
|
||||
VTKM_FORCE_USED static std::shared_ptr<UnknownAHContainer> UnknownAHNewInstanceBasic()
|
||||
std::shared_ptr<UnknownAHContainer> UnknownAHNewInstanceBasic()
|
||||
{
|
||||
return UnknownAHNewInstanceBasic<T>(typename vtkm::VecTraits<T>::IsSizeStatic{});
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
VTKM_FORCE_USED static std::shared_ptr<UnknownAHContainer> UnknownAHNewInstanceFloatBasic(
|
||||
vtkm::VecTraitsTagSizeStatic)
|
||||
std::shared_ptr<UnknownAHContainer> UnknownAHNewInstanceFloatBasic(vtkm::VecTraitsTagSizeStatic)
|
||||
{
|
||||
using FloatT = typename vtkm::VecTraits<T>::template ReplaceBaseComponentType<vtkm::FloatDefault>;
|
||||
return UnknownAHContainer::Make(vtkm::cont::ArrayHandleBasic<FloatT>{});
|
||||
}
|
||||
template <typename T>
|
||||
VTKM_FORCE_USED static std::shared_ptr<UnknownAHContainer> UnknownAHNewInstanceFloatBasic(
|
||||
vtkm::VecTraitsTagSizeVariable)
|
||||
std::shared_ptr<UnknownAHContainer> UnknownAHNewInstanceFloatBasic(vtkm::VecTraitsTagSizeVariable)
|
||||
{
|
||||
throw vtkm::cont::ErrorBadType("Cannot create a basic array container from with ValueType of " +
|
||||
vtkm::cont::TypeToString<T>());
|
||||
}
|
||||
template <typename T>
|
||||
VTKM_FORCE_USED static std::shared_ptr<UnknownAHContainer> UnknownAHNewInstanceFloatBasic()
|
||||
std::shared_ptr<UnknownAHContainer> UnknownAHNewInstanceFloatBasic()
|
||||
{
|
||||
return UnknownAHNewInstanceFloatBasic<T>(typename vtkm::VecTraits<T>::IsSizeStatic{});
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
VTKM_FORCE_USED inline UnknownAHContainer::UnknownAHContainer(
|
||||
const vtkm::cont::ArrayHandle<T, S>& array)
|
||||
inline UnknownAHContainer::UnknownAHContainer(const vtkm::cont::ArrayHandle<T, S>& array)
|
||||
: ArrayHandlePointer(new vtkm::cont::ArrayHandle<T, S>(array))
|
||||
, ValueType(typeid(T))
|
||||
, StorageType(typeid(S))
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include <vtkm/cont/CoordinateSystem.h>
|
||||
#include <vtkm/cont/DataSet.h>
|
||||
#include <vtkm/cont/ErrorExecution.h>
|
||||
#include <vtkm/cont/Field.h>
|
||||
#include <vtkm/cont/Invoker.h>
|
||||
#include <vtkm/cont/Logging.h>
|
||||
|
@ -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<vtkm::Particle> res;
|
||||
|
||||
FieldType velocities(field);
|
||||
FieldType velocities(field, fieldMeta.GetAssociation());
|
||||
GridEvalType gridEval(coords, cells, velocities);
|
||||
Stepper rk4(gridEval, static_cast<vtkm::Float32>(this->stepSize));
|
||||
|
||||
|
@ -75,11 +75,6 @@ inline VTKM_CONT vtkm::cont::DataSet LagrangianStructures::DoExecute(
|
||||
const vtkm::filter::FieldMetadata& fieldMeta,
|
||||
const vtkm::filter::PolicyBase<DerivedPolicy>&)
|
||||
{
|
||||
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;
|
||||
|
@ -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<vtkm::Vec<T, 3>, StorageType>;
|
||||
using FieldType = vtkm::worklet::particleadvection::VelocityField<FieldHandle>;
|
||||
using GridEvalType = vtkm::worklet::particleadvection::GridEvaluator<FieldType>;
|
||||
@ -61,7 +58,7 @@ inline VTKM_CONT vtkm::cont::DataSet StreamSurface::DoExecute(
|
||||
using Stepper = vtkm::worklet::particleadvection::Stepper<RK4Type, GridEvalType>;
|
||||
|
||||
//compute streamlines
|
||||
FieldType velocities(field);
|
||||
FieldType velocities(field, fieldMeta.GetAssociation());
|
||||
GridEvalType eval(coords, cells, velocities);
|
||||
Stepper rk4(eval, this->StepSize);
|
||||
|
||||
|
@ -93,12 +93,13 @@ public:
|
||||
: DataSetIntegratorBase<vtkm::worklet::particleadvection::GridEvaluator<
|
||||
vtkm::worklet::particleadvection::VelocityField<FieldHandleType>>>(false, id)
|
||||
{
|
||||
using Association = vtkm::cont::Field::Association;
|
||||
using FieldType = vtkm::worklet::particleadvection::VelocityField<FieldHandleType>;
|
||||
using EvalType = vtkm::worklet::particleadvection::GridEvaluator<FieldType>;
|
||||
Association association = ds.GetField(fieldNm).GetAssociation();
|
||||
auto fieldArray = this->GetFieldHandle(ds, fieldNm);
|
||||
|
||||
using EvalType = vtkm::worklet::particleadvection::GridEvaluator<
|
||||
vtkm::worklet::particleadvection::VelocityField<FieldHandleType>>;
|
||||
|
||||
this->Eval = std::shared_ptr<EvalType>(new EvalType(ds, fieldArray));
|
||||
FieldType field(fieldArray, association);
|
||||
this->Eval = std::shared_ptr<EvalType>(new EvalType(ds, field));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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 ()
|
||||
|
@ -7,12 +7,14 @@
|
||||
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
// PURPOSE. See the above copyright notice for more information.
|
||||
//============================================================================
|
||||
#include <vtkm/io/ImageUtils.h>
|
||||
|
||||
#include <vtkm/cont/ErrorExecution.h>
|
||||
|
||||
#include <vtkm/io/FileUtils.h>
|
||||
#include <vtkm/io/ImageReaderBase.h>
|
||||
#include <vtkm/io/ImageReaderPNG.h>
|
||||
#include <vtkm/io/ImageReaderPNM.h>
|
||||
#include <vtkm/io/ImageUtils.h>
|
||||
#include <vtkm/io/ImageWriterBase.h>
|
||||
#include <vtkm/io/ImageWriterPNG.h>
|
||||
#include <vtkm/io/ImageWriterPNM.h>
|
||||
|
@ -18,7 +18,6 @@
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <random>
|
||||
#include <string>
|
||||
|
||||
using namespace vtkm::io;
|
||||
|
@ -13,7 +13,6 @@
|
||||
#include <vtkm/io/ImageReaderPNM.h>
|
||||
#include <vtkm/io/ImageWriterPNG.h>
|
||||
#include <vtkm/io/ImageWriterPNM.h>
|
||||
#include <vtkm/io/PixelTypes.h>
|
||||
#include <vtkm/rendering/Canvas.h>
|
||||
#include <vtkm/rendering/Color.h>
|
||||
|
||||
|
@ -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
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <vtkm/rendering/BitmapFontFactory.h>
|
||||
#include <vtkm/rendering/LineRenderer.h>
|
||||
#include <vtkm/rendering/TextRenderer.h>
|
||||
#include <vtkm/rendering/TextRendererBatcher.h>
|
||||
#include <vtkm/rendering/WorldAnnotator.h>
|
||||
#include <vtkm/worklet/DispatcherMapField.h>
|
||||
#include <vtkm/worklet/WorkletMapField.h>
|
||||
@ -224,6 +225,7 @@ struct Canvas::CanvasInternals
|
||||
FontTextureType FontTexture;
|
||||
vtkm::Matrix<vtkm::Float32, 4, 4> ModelView;
|
||||
vtkm::Matrix<vtkm::Float32, 4, 4> Projection;
|
||||
std::shared_ptr<vtkm::rendering::TextRendererBatcher> 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<vtkm::rendering::Canvas*>(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<vtkm::Float32, 4, 4>& 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<vtkm::rendering::Canvas*>(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<vtkm::rendering::TextRendererBatcher>(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();
|
||||
|
@ -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<vtkm::Float32, 4, 4>& GetModelView() const;
|
||||
|
||||
const vtkm::Matrix<vtkm::Float32, 4, 4>& GetProjection() const;
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include <vtkm/Transform3D.h>
|
||||
#include <vtkm/cont/TryExecute.h>
|
||||
#include <vtkm/rendering/LineRendererBatcher.h>
|
||||
#include <vtkm/worklet/DispatcherMapField.h>
|
||||
#include <vtkm/worklet/WorkletMapField.h>
|
||||
|
||||
@ -21,9 +22,11 @@ namespace rendering
|
||||
{
|
||||
|
||||
LineRenderer::LineRenderer(const vtkm::rendering::Canvas* canvas,
|
||||
vtkm::Matrix<vtkm::Float32, 4, 4> transform)
|
||||
vtkm::Matrix<vtkm::Float32, 4, 4> 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::Id>(vtkm::Round(p0[0]));
|
||||
vtkm::Id y0 = static_cast<vtkm::Id>(vtkm::Round(p0[1]));
|
||||
vtkm::Float32 z0 = static_cast<vtkm::Float32>(p0[2]);
|
||||
vtkm::Id x1 = static_cast<vtkm::Id>(vtkm::Round(p1[0]));
|
||||
vtkm::Id y1 = static_cast<vtkm::Id>(vtkm::Round(p1[1]));
|
||||
vtkm::Float32 z1 = static_cast<vtkm::Float32>(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<vtkm::Float32>(x0 - xStart);
|
||||
vtkm::Float32 deltaY = static_cast<vtkm::Float32>(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
|
||||
|
@ -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<vtkm::Float32, 4, 4> transform);
|
||||
LineRenderer(const vtkm::rendering::Canvas* canvas,
|
||||
vtkm::Matrix<vtkm::Float32, 4, 4> 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<vtkm::Float32, 4, 4> Transform;
|
||||
vtkm::rendering::LineRendererBatcher* LineBatcher;
|
||||
}; // class LineRenderer
|
||||
}
|
||||
} // namespace vtkm::rendering
|
||||
|
168
vtkm/rendering/LineRendererBatcher.cxx
Normal file
168
vtkm/rendering/LineRendererBatcher.cxx
Normal file
@ -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 <vtkm/rendering/LineRendererBatcher.h>
|
||||
|
||||
#include <vtkm/worklet/WorkletMapField.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace rendering
|
||||
{
|
||||
namespace
|
||||
{
|
||||
using ColorsArrayHandle = vtkm::cont::ArrayHandle<vtkm::Vec4f_32>;
|
||||
using PointsArrayHandle = vtkm::cont::ArrayHandle<vtkm::Vec3f_32>;
|
||||
|
||||
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 <typename ColorBufferPortal, typename DepthBufferPortal>
|
||||
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::Id>(vtkm::Round(start[0]));
|
||||
vtkm::Id y0 = static_cast<vtkm::Id>(vtkm::Round(start[1]));
|
||||
vtkm::Float32 z0 = static_cast<vtkm::Float32>(start[2]);
|
||||
vtkm::Id x1 = static_cast<vtkm::Id>(vtkm::Round(end[0]));
|
||||
vtkm::Id y1 = static_cast<vtkm::Id>(vtkm::Round(end[1]));
|
||||
vtkm::Float32 z1 = static_cast<vtkm::Float32>(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<vtkm::Float32>(x0 - xStart);
|
||||
vtkm::Float32 deltaY = static_cast<vtkm::Float32>(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<vtkm::Float32>(start[0]),
|
||||
static_cast<vtkm::Float32>(start[1]),
|
||||
static_cast<vtkm::Float32>(start[2]));
|
||||
vtkm::Vec3f_32 end32(static_cast<vtkm::Float32>(end[0]),
|
||||
static_cast<vtkm::Float32>(end[1]),
|
||||
static_cast<vtkm::Float32>(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
|
52
vtkm/rendering/LineRendererBatcher.h
Normal file
52
vtkm/rendering/LineRendererBatcher.h
Normal file
@ -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 <string>
|
||||
#include <vector>
|
||||
|
||||
#include <vtkm/rendering/Canvas.h>
|
||||
#include <vtkm/rendering/Color.h>
|
||||
#include <vtkm/rendering/vtkm_rendering_export.h>
|
||||
|
||||
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<vtkm::Vec3f_32> Starts;
|
||||
std::vector<vtkm::Vec3f_32> Ends;
|
||||
std::vector<vtkm::Vec4f_32> Colors;
|
||||
};
|
||||
}
|
||||
} // namespace vtkm::rendering
|
||||
|
||||
#endif // vtk_m_rendering_LineRendererBatcher_h
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include <vtkm/Transform3D.h>
|
||||
#include <vtkm/cont/TryExecute.h>
|
||||
#include <vtkm/rendering/TextRendererBatcher.h>
|
||||
#include <vtkm/worklet/DispatcherMapField.h>
|
||||
#include <vtkm/worklet/WorkletMapField.h>
|
||||
|
||||
@ -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 <typename ColorBufferPortal, typename FontTexture, typename DepthBufferPortal>
|
||||
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<vtkm::Float32>(Width - 1));
|
||||
vtkm::Float32 x1 = Clamp(screenCoords[2], 0.0f, static_cast<vtkm::Float32>(Width - 1));
|
||||
vtkm::Float32 y0 = Clamp(screenCoords[1], 0.0f, static_cast<vtkm::Float32>(Height - 1));
|
||||
vtkm::Float32 y1 = Clamp(screenCoords[3], 0.0f, static_cast<vtkm::Float32>(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 <typename ColorBufferPortal, typename DepthBufferPortal>
|
||||
VTKM_EXEC void Plot(vtkm::Float32 x,
|
||||
vtkm::Float32 y,
|
||||
vtkm::Float32 intensity,
|
||||
ColorBufferPortal& colorBuffer,
|
||||
DepthBufferPortal& depthBuffer) const
|
||||
{
|
||||
vtkm::Id index =
|
||||
static_cast<vtkm::Id>(vtkm::Round(y)) * Width + static_cast<vtkm::Id>(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<vtkm::Id4>;
|
||||
using TextureCoordsArrayHandle = vtkm::cont::ArrayHandle<vtkm::Vec4f_32>;
|
||||
|
||||
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 <typename Device>
|
||||
VTKM_CONT bool operator()(Device) const
|
||||
{
|
||||
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
|
||||
|
||||
vtkm::worklet::DispatcherMapField<RenderBitmapFont> 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<vtkm::Float32, 4, 4>& 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<vtkm::Id4>;
|
||||
using TextureCoordsArrayHandle = vtkm::cont::ArrayHandle<vtkm::Vec4f_32>;
|
||||
ScreenCoordsArrayHandle screenCoords;
|
||||
TextureCoordsArrayHandle textureCoords;
|
||||
{
|
||||
@ -261,15 +114,7 @@ void TextRenderer::RenderText(const vtkm::Matrix<vtkm::Float32, 4, 4>& 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
|
||||
|
@ -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
|
||||
|
166
vtkm/rendering/TextRendererBatcher.cxx
Normal file
166
vtkm/rendering/TextRendererBatcher.cxx
Normal file
@ -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 <vtkm/rendering/TextRendererBatcher.h>
|
||||
|
||||
#include <vtkm/worklet/WorkletMapField.h>
|
||||
|
||||
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 <typename ColorBufferPortal, typename FontTexture, typename DepthBufferPortal>
|
||||
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<vtkm::Float32>(Width - 1));
|
||||
vtkm::Float32 x1 = Clamp(screenCoords[2], 0.0f, static_cast<vtkm::Float32>(Width - 1));
|
||||
vtkm::Float32 y0 = Clamp(screenCoords[1], 0.0f, static_cast<vtkm::Float32>(Height - 1));
|
||||
vtkm::Float32 y1 = Clamp(screenCoords[3], 0.0f, static_cast<vtkm::Float32>(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 <typename ColorBufferPortal, typename DepthBufferPortal>
|
||||
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::Id>(vtkm::Round(y)) * Width + static_cast<vtkm::Id>(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<ColorType> colors =
|
||||
vtkm::cont::make_ArrayHandle(this->Colors, vtkm::CopyFlag::Off);
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32> 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
|
65
vtkm/rendering/TextRendererBatcher.h
Normal file
65
vtkm/rendering/TextRendererBatcher.h
Normal file
@ -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 <string>
|
||||
#include <vector>
|
||||
|
||||
#include <vtkm/rendering/BitmapFont.h>
|
||||
#include <vtkm/rendering/Canvas.h>
|
||||
#include <vtkm/rendering/Color.h>
|
||||
#include <vtkm/rendering/vtkm_rendering_export.h>
|
||||
|
||||
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<ScreenCoordsType>;
|
||||
using TextureCoordsArrayHandle = vtkm::cont::ArrayHandle<TextureCoordsType>;
|
||||
using ColorsArrayHandle = vtkm::cont::ArrayHandle<ColorType>;
|
||||
using DepthsArrayHandle = vtkm::cont::ArrayHandle<vtkm::Float32>;
|
||||
|
||||
/*
|
||||
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<ScreenCoordsType> ScreenCoords;
|
||||
std::vector<TextureCoordsType> TextureCoords;
|
||||
std::vector<ColorType> Colors;
|
||||
std::vector<vtkm::Float32> Depths;
|
||||
};
|
||||
}
|
||||
} // namespace vtkm::rendering
|
||||
|
||||
#endif // vtk_m_rendering_TextRendererBatcher_h
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -32,10 +32,24 @@ void WorldAnnotator::AddLine(const vtkm::Vec3f_64& point0,
|
||||
{
|
||||
vtkm::Matrix<vtkm::Float32, 4, 4> transform =
|
||||
vtkm::MatrixMultiply(Canvas->GetProjection(), Canvas->GetModelView());
|
||||
LineRenderer renderer(Canvas, transform);
|
||||
vtkm::rendering::WorldAnnotator* self = const_cast<vtkm::rendering::WorldAnnotator*>(this);
|
||||
LineRenderer renderer(Canvas, transform, &(self->LineBatcher));
|
||||
renderer.RenderLine(point0, point1, lineWidth, color);
|
||||
}
|
||||
|
||||
void WorldAnnotator::BeginLineRenderingBatch() const
|
||||
{
|
||||
vtkm::rendering::WorldAnnotator* self = const_cast<vtkm::rendering::WorldAnnotator*>(this);
|
||||
self->LineBatcher = vtkm::rendering::LineRendererBatcher();
|
||||
}
|
||||
|
||||
void WorldAnnotator::EndLineRenderingBatch() const
|
||||
{
|
||||
vtkm::rendering::WorldAnnotator* self = const_cast<vtkm::rendering::WorldAnnotator*>(this);
|
||||
vtkm::rendering::Canvas* canvas = const_cast<vtkm::rendering::Canvas*>(this->Canvas);
|
||||
self->LineBatcher.Render(canvas);
|
||||
}
|
||||
|
||||
void WorldAnnotator::AddText(const vtkm::Vec3f_32& origin,
|
||||
const vtkm::Vec3f_32& right,
|
||||
const vtkm::Vec3f_32& up,
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <vtkm/Types.h>
|
||||
#include <vtkm/rendering/Canvas.h>
|
||||
#include <vtkm/rendering/Color.h>
|
||||
#include <vtkm/rendering/LineRendererBatcher.h>
|
||||
|
||||
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
|
||||
|
@ -8,56 +8,188 @@
|
||||
// PURPOSE. See the above copyright notice for more information.
|
||||
//============================================================================
|
||||
#include <vtkm/source/Oscillator.h>
|
||||
#include <vtkm/worklet/WorkletMapField.h>
|
||||
|
||||
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<internal::Oscillator, MAX_OSCILLATORS> PeriodicOscillators;
|
||||
vtkm::VecVariable<internal::Oscillator, MAX_OSCILLATORS> DampedOscillators;
|
||||
vtkm::VecVariable<internal::Oscillator, MAX_OSCILLATORS> DecayingOscillators;
|
||||
vtkm::FloatDefault Time;
|
||||
}; // OscillatorSource
|
||||
|
||||
} // internal
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
Oscillator::Oscillator(vtkm::Id3 dims)
|
||||
: Dims(dims)
|
||||
, Worklet()
|
||||
, Worklet(std::make_unique<internal::OscillatorSource>())
|
||||
{
|
||||
}
|
||||
|
||||
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<vtkm::FloatDefault>(this->Dims[1]),
|
||||
1.0f / static_cast<vtkm::FloatDefault>(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<vtkm::Float64> 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<vtkm::FloatDefault> outArray;
|
||||
this->Invoke(*(this->Worklet), coordinates, outArray);
|
||||
dataSet.AddField(vtkm::cont::make_FieldPoint("oscillating", outArray));
|
||||
|
||||
return dataSet;
|
||||
|
@ -11,12 +11,15 @@
|
||||
#define vtk_m_source_OscillatorSource_h
|
||||
|
||||
#include <vtkm/source/Source.h>
|
||||
#include <vtkm/worklet/OscillatorSource.h>
|
||||
|
||||
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<internal::OscillatorSource> Worklet;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
)
|
||||
|
66
vtkm/source/testing/UnitTestOscillatorSource.cxx
Normal file
66
vtkm/source/testing/UnitTestOscillatorSource.cxx
Normal file
@ -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 <vtkm/source/Oscillator.h>
|
||||
|
||||
#include <vtkm/cont/Timer.h>
|
||||
#include <vtkm/cont/testing/Testing.h>
|
||||
|
||||
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<vtkm::FloatDefault>;
|
||||
|
||||
auto field = ds.GetPointField("oscillating");
|
||||
auto dynData = field.GetData();
|
||||
VTKM_TEST_ASSERT(dynData.IsType<ScalarHandleType>(), "Invalid scalar handle type.");
|
||||
ScalarHandleType handle = dynData.AsArrayHandle<ScalarHandleType>();
|
||||
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);
|
||||
}
|
@ -10,7 +10,6 @@
|
||||
|
||||
#include <vtkm/source/Wavelet.h>
|
||||
|
||||
#include <vtkm/cont/Timer.h>
|
||||
#include <vtkm/cont/testing/Testing.h>
|
||||
|
||||
void WaveletSourceTest()
|
||||
|
@ -57,7 +57,6 @@ set(headers
|
||||
OrientNormals.h
|
||||
OrientPointNormals.h
|
||||
OrientPointAndCellNormals.h
|
||||
OscillatorSource.h
|
||||
ParticleAdvection.h
|
||||
PointAverage.h
|
||||
PointElevation.h
|
||||
|
@ -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 <vtkm/Math.h>
|
||||
#include <vtkm/worklet/WorkletMapField.h>
|
||||
|
||||
#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 <typename T>
|
||||
VTKM_EXEC vtkm::Float64 operator()(const vtkm::Vec<T, 3>& vec) const
|
||||
{
|
||||
return (*this)(vtkm::make_Vec(static_cast<vtkm::Float64>(vec[0]),
|
||||
static_cast<vtkm::Float64>(vec[1]),
|
||||
static_cast<vtkm::Float64>(vec[2])));
|
||||
}
|
||||
|
||||
private:
|
||||
vtkm::Vec<internal::Oscillator, MAX_OSCILLATORS> PeriodicOscillators;
|
||||
vtkm::Vec<internal::Oscillator, MAX_OSCILLATORS> DampedOscillators;
|
||||
vtkm::Vec<internal::Oscillator, MAX_OSCILLATORS> DecayingOscillators;
|
||||
vtkm::UInt8 NumberOfPeriodics;
|
||||
vtkm::UInt8 NumberOfDamped;
|
||||
vtkm::UInt8 NumberOfDecaying;
|
||||
vtkm::Float64 Time;
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace vtkm
|
||||
|
||||
#endif // vtk_m_worklet_PointElevation_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<vtkm::Vec3f, 2>& 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<vtkm::Id, 8>& indices,
|
||||
const vtkm::Id vertices,
|
||||
const vtkm::Vec3f& parametric,
|
||||
const vtkm::UInt8 cellShape,
|
||||
vtkm::VecVariable<vtkm::Vec3f, 2>& value) const
|
||||
{
|
||||
VTKM_ASSERT(this->Assoc == Association::POINTS);
|
||||
|
||||
vtkm::Vec3f velocityInterp;
|
||||
vtkm::VecVariable<vtkm::Vec3f, 8> velocities;
|
||||
for (vtkm::IdComponent i = 0; i < vertices; i++)
|
||||
@ -55,6 +70,7 @@ public:
|
||||
|
||||
private:
|
||||
FieldPortalType VelocityValues;
|
||||
Association Assoc;
|
||||
};
|
||||
|
||||
template <typename FieldArrayType>
|
||||
@ -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<vtkm::Vec3f, 2>& 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<vtkm::Id, 8>& indices,
|
||||
const vtkm::Id vertices,
|
||||
const vtkm::Vec3f& parametric,
|
||||
const vtkm::UInt8 cellShape,
|
||||
vtkm::VecVariable<vtkm::Vec3f, 2>& value) const
|
||||
{
|
||||
VTKM_ASSERT(this->Assoc == Association::POINTS);
|
||||
|
||||
vtkm::Vec3f electricInterp, magneticInterp;
|
||||
vtkm::VecVariable<vtkm::Vec3f, 8> electric;
|
||||
vtkm::VecVariable<vtkm::Vec3f, 8> magnetic;
|
||||
@ -95,6 +127,7 @@ public:
|
||||
private:
|
||||
FieldPortalType ElectricValues;
|
||||
FieldPortalType MagneticValues;
|
||||
Association Assoc;
|
||||
};
|
||||
|
||||
template <typename FieldArrayType>
|
||||
@ -102,6 +135,7 @@ class VelocityField : public vtkm::cont::ExecutionObjectBase
|
||||
{
|
||||
public:
|
||||
using ExecutionType = ExecutionVelocityField<FieldArrayType>;
|
||||
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 <typename FieldArrayType>
|
||||
@ -128,6 +173,7 @@ class ElectroMagneticField : public vtkm::cont::ExecutionObjectBase
|
||||
{
|
||||
public:
|
||||
using ExecutionType = ExecutionElectroMagneticField<FieldArrayType>;
|
||||
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
|
||||
|
@ -125,8 +125,17 @@ public:
|
||||
vtkm::IdComponent nVerts;
|
||||
vtkm::VecVariable<vtkm::Id, 8> ptIndices;
|
||||
vtkm::VecVariable<vtkm::Vec3f, 8> 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();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user