Go to file
Kenneth Moreland eda6dc39f2 Support using arrays with dynamic Vec-likes as output arrays
When you use an `ArrayHandle` as an output array in a worklet (for example,
as a `FieldOut`), the fetch operation does not read values from the array
during the `Load`. Instead, it just constructs a new object. This makes
sense as an output array is expected to have garbage in it anyway.

This is a problem for some special arrays that contain `Vec`-like objects
that are sized dynamically. For example, if you use an
`ArrayHandleGroupVecVariable`, each entry is a dynamically sized `Vec`. The
array is referenced by creating a special version of `Vec` that holds a
reference to the array portal and an index. Components are retrieved and
set by accessing the memory in the array portal. This allows us to have a
dynamically sized `Vec` in the execution environment without having to
allocate within the worklet.

The problem comes when we want to use one of these arrays with `Vec`-like
objects for an output. The typical fetch fails because you cannot construct
one of these `Vec`-like objects without an array portal to bind it to. In
these cases, we need the fetch to create the `Vec`-like object by reading
it from the array. Even though the data will be garbage, you get the
necessary buffer into the array (and nothing more).

Previously, the problem was fixed by creating partial specializations of
the `Fetch` for these `ArrayHandle`s. This worked OK as long as you were
using the array directly. However, the approach failed if the `ArrayHandle`
was wrapped in another `ArrayHandle` (for example, if an `ArrayHandleView`
was applied to an `ArrayHandleGroupVecVariable`).

To get around this problem and simplify things, the basic `Fetch` for
direct output arrays is changed to handle all cases where the values in the
`ArrayHandle` cannot be directly constructed. A compile-time check of the
array's value type is checked with `std::is_default_constructible`. If it
can be constructed, then the array is not accessed. If it cannot be
constructed, then it grabs a value out of the array.
2023-01-23 13:02:40 -07:00
.github docs: update gitlab links to include /-/ component 2020-05-26 14:48:49 -04:00
.gitlab/ci gitlab-ci: add missing platform and feature tags to ascent job 2022-12-21 09:35:53 -05:00
benchmarking Split up the filters benchmark tests 2022-12-05 13:20:22 -07:00
CMake Merge topic 'override_ctest_timeout' 2023-01-17 12:02:54 -05:00
config Output complete list of libraries for external Makefiles 2022-10-27 06:14:49 -06:00
data Merge topic 'contour-bug' 2022-09-29 13:37:12 -04:00
docs Support using arrays with dynamic Vec-likes as output arrays 2023-01-23 13:02:40 -07:00
examples Remove bad import and fix warning in ContourTreeAppDataIO.h 2023-01-16 18:26:32 -08:00
tutorial Rename NewFilter base classes to Filter 2022-12-01 13:07:56 -07:00
Utilities compare.py: add normal and t-student utest 2022-10-03 13:19:40 -04:00
vtkm Support using arrays with dynamic Vec-likes as output arrays 2023-01-23 13:02:40 -07:00
vtkmstd Have VTKM_IS_TRIVIAL* macros show types better 2021-04-02 07:37:26 -06:00
.clang-format clang-format: update configuration for 9.0 2020-08-24 11:47:55 -04:00
.gitattributes newrelease.md: templatize newrelease.md 2022-09-28 18:02:37 -04:00
.gitignore Add a point-oscillator filter + example 2018-07-18 09:33:06 -04:00
.gitlab-ci.yml CMAKE: update latest CI CMake to 3.23.4 2022-10-26 17:18:15 -04:00
.hooks-config hooks: add hook chains for development checks and LFS 2020-04-02 12:51:43 -04:00
.kitware-release.json CI: adds .kitware-release.json 2021-05-24 18:26:39 -04:00
.lfsconfig LFS: Set lfs.url upon the origin url 2021-06-24 13:26:40 -04:00
CMakeLists.txt Add cmake flag to override default ctest timeouts 2023-01-09 08:42:23 -07:00
CONTRIBUTING.md Fix example of gitlab-sync 2022-09-02 14:50:24 -06:00
CTestConfig.cmake conslidate the license statement 2019-04-17 10:57:13 -06:00
CTestCustom.cmake.in perftest: add benchmark build 2022-10-03 13:21:09 -04:00
LICENSE.txt release: update version and License 2022-12-15 19:40:38 -05:00
README.md README: Updated VTK-m example for vtkm 2.0.0 2022-12-13 15:39:48 -05:00
version.txt release: update version and License 2022-12-15 19:40:38 -05:00

VTK-m

VTK-m is a toolkit of scientific visualization algorithms for emerging processor architectures. VTK-m supports the fine-grained concurrency for data analysis and visualization algorithms required to drive extreme scale computing by providing abstract models for data and execution that can be applied to a variety of algorithms across many different processor architectures.

You can find out more about the design of VTK-m on the VTK-m Wiki.

Learning Resources

  • A high-level overview is given in the IEEE Vis talk "VTK-m: Accelerating the Visualization Toolkit for Massively Threaded Architectures."

  • The VTK-m Users Guide provides extensive documentation. It is broken into multiple parts for learning and references at multiple different levels.

    • "Part 1: Getting Started" provides the introductory instruction for building VTK-m and using its high-level features.
    • "Part 2: Using VTK-m" covers the core fundamental components of VTK-m including data model, worklets, and filters.
    • "Part 3: Developing with VTK-m" covers how to develop new worklets and filters.
    • "Part 4: Advanced Development" covers topics such as new worklet types and custom device adapters.
  • A practical VTK-m Tutorial based in what users want to accomplish with VTK-m:

    • Building VTK-m and using existing VTK-m data structures and filters.
    • Algorithm development with VTK-m.
    • Writing new VTK-m filters.
  • Community discussion takes place on the VTK-m users email list.

  • Doxygen-generated reference documentation is available for both:

Contributing

There are many ways to contribute to VTK-m, with varying levels of effort.

Dependencies

VTK-m Requires:

  • C++11 Compiler. VTK-m has been confirmed to work with the following
    • GCC 5.4+
    • Clang 5.0+
    • XCode 5.0+
    • MSVC 2015+
    • Intel 17.0.4+
  • CMake
    • CMake 3.12+
    • CMake 3.13+ (for CUDA support)

Optional dependencies are:

  • CUDA Device Adapter
  • TBB Device Adapter
  • OpenMP Device Adapter
    • Requires a compiler that supports OpenMP >= 4.0.
  • OpenGL Rendering
    • The rendering module contains multiple rendering implementations including standalone rendering code. The rendering module also includes (optionally built) OpenGL rendering classes.
    • The OpenGL rendering classes require that you have a extension binding library and one rendering library. A windowing library is not needed except for some optional tests.
  • Extension Binding
  • On Screen Rendering
    • OpenGL Driver
    • Mesa Driver
  • On Screen Rendering Tests
  • Headless Rendering

VTK-m has been tested on the following configurations:c

  • On Linux
    • GCC 5.4.0, 5.4, 6.5, 7.4, 8.2, 9.2; Clang 5, 8; Intel 17.0.4; 19.0.0
    • CMake 3.12, 3.13, 3.16, 3.17
    • CUDA 9.2, 10.2, 11.0, 11.1
    • TBB 4.4 U2, 2017 U7
  • On Windows
    • Visual Studio 2015, 2017
    • CMake 3.12, 3.17
    • CUDA 10.2
    • TBB 2017 U3, 2018 U2
  • On MacOS
    • AppleClang 9.1
    • CMake 3.12
    • TBB 2018

Building

VTK-m supports all majors platforms (Windows, Linux, OSX), and uses CMake to generate all the build rules for the project. The VTK-m source code is available from the VTK-m download page or by directly cloning the VTK-m git repository.

The basic procedure for building VTK-m is to unpack the source, create a build directory, run CMake in that build directory (pointing to the source) and then build. Here are some example *nix commands for the process (individual commands may vary).

$ tar xvzf ~/Downloads/vtk-m-v2.0.0.tar.gz
$ mkdir vtkm-build
$ cd vtkm-build
$ cmake-gui ../vtk-m-v2.0.0
$ cmake --build -j .              # Runs make (or other build program)

A more detailed description of building VTK-m is available in the VTK-m Users Guide.

Example

The VTK-m source distribution includes a number of examples. The goal of the VTK-m examples is to illustrate specific VTK-m concepts in a consistent and simple format. However, these examples only cover a small portion of the capabilities of VTK-m.

Below is a simple example of using VTK-m to create a simple data set and use VTK-m's rendering engine to render an image and write that image to a file. It then computes an isosurface on the input data set and renders this output data set in a separate image file:

#include <vtkm/cont/Initialize.h>
#include <vtkm/source/Tangle.h>

#include <vtkm/rendering/Actor.h>
#include <vtkm/rendering/CanvasRayTracer.h>
#include <vtkm/rendering/MapperRayTracer.h>
#include <vtkm/rendering/MapperVolume.h>
#include <vtkm/rendering/MapperWireframer.h>
#include <vtkm/rendering/Scene.h>
#include <vtkm/rendering/View3D.h>

#include <vtkm/filter/contour/Contour.h>

using vtkm::rendering::CanvasRayTracer;
using vtkm::rendering::MapperRayTracer;
using vtkm::rendering::MapperVolume;
using vtkm::rendering::MapperWireframer;

int main(int argc, char* argv[])
{
  vtkm::cont::Initialize(argc, argv, vtkm::cont::InitializeOptions::Strict);

  auto tangle = vtkm::source::Tangle(vtkm::Id3{ 50, 50, 50 });
  vtkm::cont::DataSet tangleData = tangle.Execute();
  std::string fieldName = "tangle";

  // Set up a camera for rendering the input data
  vtkm::rendering::Camera camera;
  camera.SetLookAt(vtkm::Vec3f_32(0.5, 0.5, 0.5));
  camera.SetViewUp(vtkm::make_Vec(0.f, 1.f, 0.f));
  camera.SetClippingRange(1.f, 10.f);
  camera.SetFieldOfView(60.f);
  camera.SetPosition(vtkm::Vec3f_32(1.5, 1.5, 1.5));
  vtkm::cont::ColorTable colorTable("inferno");

  // Background color:
  vtkm::rendering::Color bg(0.2f, 0.2f, 0.2f, 1.0f);
  vtkm::rendering::Actor actor(tangleData.GetCellSet(),
                               tangleData.GetCoordinateSystem(),
                               tangleData.GetField(fieldName),
                               colorTable);
  vtkm::rendering::Scene scene;
  scene.AddActor(actor);
  // 2048x2048 pixels in the canvas:
  CanvasRayTracer canvas(2048, 2048);
  // Create a view and use it to render the input data using OS Mesa

  vtkm::rendering::View3D view(scene, MapperVolume(), canvas, camera, bg);
  view.Paint();
  view.SaveAs("volume.png");

  // Compute an isosurface:
  vtkm::filter::contour::Contour filter;
  // [min, max] of the tangle field is [-0.887, 24.46]:
  filter.SetIsoValue(3.0);
  filter.SetActiveField(fieldName);
  vtkm::cont::DataSet isoData = filter.Execute(tangleData);
  // Render a separate image with the output isosurface
  vtkm::rendering::Actor isoActor(
    isoData.GetCellSet(), isoData.GetCoordinateSystem(), isoData.GetField(fieldName), colorTable);
  // By default, the actor will automatically scale the scalar range of the color table to match
  // that of the data. However, we are coloring by the scalar that we just extracted a contour
  // from, so we want the scalar range to match that of the previous image.
  isoActor.SetScalarRange(actor.GetScalarRange());
  vtkm::rendering::Scene isoScene;
  isoScene.AddActor(isoActor);

  // Wireframe surface:
  vtkm::rendering::View3D isoView(isoScene, MapperWireframer(), canvas, camera, bg);
  isoView.Paint();
  isoView.SaveAs("isosurface_wireframer.png");

  // Smooth surface:
  vtkm::rendering::View3D solidView(isoScene, MapperRayTracer(), canvas, camera, bg);
  solidView.Paint();
  solidView.SaveAs("isosurface_raytracer.png");

  return 0;
}

A minimal CMakeLists.txt such as the following one can be used to build this example.

cmake_minimum_required(VERSION 3.12...3.15 FATAL_ERROR)
project(VTKmDemo CXX)

#Find the VTK-m package
find_package(VTKm REQUIRED QUIET)

if(TARGET vtkm::rendering)
  add_executable(Demo Demo.cxx)
  target_link_libraries(Demo PRIVATE vtkm::filter vtkm::rendering vtkm::source)
endif()

License

VTK-m is distributed under the OSI-approved BSD 3-clause License. See LICENSE.txt for details.