This commit is contained in:
Dave Pugmire 2023-05-30 14:28:42 -04:00
commit ff4cc5e00e
44 changed files with 892 additions and 699 deletions

@ -10,16 +10,31 @@
##
##=============================================================================
# Find the path the logs from the last configure
set(configure_warning_exceptions
".*CMake Warning at CMake/VTKmDetermineVersion.cmake.*"
)
# Find the path of the logs from the last configure
set(cnf_log_path "${CMAKE_SOURCE_DIR}/build/Testing/Temporary/LastConfigure*.log")
file(GLOB cnf_log_files ${cnf_log_path})
# Check for warnings during the configure phase
foreach(file IN LISTS cnf_log_files)
file(STRINGS ${file} lines)
string(FIND "${lines}" "Warning" line)
if (NOT ${line} EQUAL "-1")
message(FATAL_ERROR "Configure warnings detected, please check cdash-commit job")
endif()
foreach(line IN LISTS lines)
if ("${line}" MATCHES "Warning|WARNING|warning")
set(exception_matches FALSE)
foreach(exception IN LISTS configure_warning_exceptions)
if (${line} MATCHES "${exception}")
set(exception_matches TRUE)
break()
endif()
endforeach()
if (NOT exception_matches)
message(FATAL_ERROR "Configure warnings detected, please check cdash-commit job: ${line}")
endif()
endif()
endforeach()
endforeach()
# `compile_num_warnings` contains a single integer symbolizing the number of

@ -156,6 +156,25 @@ foreach(option IN LISTS options)
endforeach()
# We need to use VTKm_CUDA_Architecture for older CMake versions
if(vtkm_cuda_arch)
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.18)
if(vtkm_cuda_arch STREQUAL "maxwell")
set(CMAKE_CUDA_ARCHITECTURES "50" CACHE STRING "")
elseif(vtkm_cuda_arch STREQUAL "pascal")
set(CMAKE_CUDA_ARCHITECTURES "60" CACHE STRING "")
elseif(vtkm_cuda_arch STREQUAL "volta")
set(CMAKE_CUDA_ARCHITECTURES "70" CACHE STRING "")
elseif(vtkm_cuda_arch STREQUAL "turing")
set(CMAKE_CUDA_ARCHITECTURES "75" CACHE STRING "")
elseif(vtkm_cuda_arch STREQUAL "ampere")
set(CMAKE_CUDA_ARCHITECTURES "80" CACHE STRING "")
endif()
else()
set(VTKm_CUDA_Architecture "${vtkm_cuda_arch}" CACHE STRING "")
endif()
endif()
# Compile tutorials on all builders. The code is small and basic. And since
# it is the tutorial, it should work really well.
set(VTKm_ENABLE_TUTORIALS "ON" CACHE STRING "")
@ -181,22 +200,3 @@ endif()
if(sanitizers)
set(VTKm_USE_SANITIZER "${sanitizers}" CACHE STRING "" FORCE)
endif()
# We need to use VTKm_CUDA_Architecture for older CMake versions
if(vtkm_cuda_arch)
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.18)
if(vtkm_cuda_arch STREQUAL "maxwell")
set(CMAKE_CUDA_ARCHITECTURES "50" CACHE STRING "")
elseif(vtkm_cuda_arch STREQUAL "pascal")
set(CMAKE_CUDA_ARCHITECTURES "60" CACHE STRING "")
elseif(vtkm_cuda_arch STREQUAL "volta")
set(CMAKE_CUDA_ARCHITECTURES "70" CACHE STRING "")
elseif(vtkm_cuda_arch STREQUAL "turing")
set(CMAKE_CUDA_ARCHITECTURES "75" CACHE STRING "")
elseif(vtkm_cuda_arch STREQUAL "ampere")
set(CMAKE_CUDA_ARCHITECTURES "80" CACHE STRING "")
endif()
else()
set(VTKm_CUDA_Architecture "${vtkm_cuda_arch}" CACHE STRING "")
endif()
endif()

@ -76,6 +76,14 @@ function(add_benchmark_test benchmark)
set(VTKm_PERF_COMPARE_JSON "${CMAKE_BINARY_DIR}/$ENV{CI_COMMIT_SHA}_${VTKm_PERF_NAME}.json")
endif()
# Only upload when we are inside a CI build and in master. We need to check
# if VTKM_BENCH_RECORDS_TOKEN is either defined or non-empty, the reason is
# that in Gitlab CI Variables for protected branches are also defined in MR
# from forks, however, they are empty.
if (DEFINED ENV{VTKM_BENCH_RECORDS_TOKEN} AND ENV{VTKM_BENCH_RECORDS_TOKEN})
set(enable_upload TRUE)
endif()
set(test_name "PerformanceTest${VTKm_PERF_NAME}")
###TEST INVOKATIONS##########################################################
@ -90,13 +98,6 @@ function(add_benchmark_test benchmark)
set_property(TEST PerformanceTestFetch PROPERTY FIXTURES_SETUP "FixturePerformanceTestSetup")
endif()
if (NOT TEST PerformanceTestCleanUp)
add_test(NAME "PerformanceTestCleanUp"
COMMAND ${CMAKE_COMMAND} -E rm -rf "${VTKm_PERF_REPO}"
)
set_property(TEST PerformanceTestCleanUp PROPERTY FIXTURES_CLEANUP "FixturePerformanceTestCleanUp")
endif()
add_test(NAME "${test_name}Run"
COMMAND ${CMAKE_COMMAND}
"-DVTKm_PERF_BENCH_DEVICE=Any"
@ -111,14 +112,6 @@ function(add_benchmark_test benchmark)
-P "${VTKm_SOURCE_DIR}/CMake/testing/VTKmPerformanceTestRun.cmake"
)
add_test(NAME "${test_name}Upload"
COMMAND ${CMAKE_COMMAND}
"-DVTKm_PERF_REPO=${VTKm_PERF_REPO}"
"-DVTKm_PERF_COMPARE_JSON=${VTKm_PERF_COMPARE_JSON}"
"-DVTKm_SOURCE_DIR=${VTKm_SOURCE_DIR}"
-P "${VTKm_SOURCE_DIR}/CMake/testing/VTKmPerformanceTestUpload.cmake"
)
add_test(NAME "${test_name}Report"
COMMAND ${CMAKE_COMMAND}
"-DVTKm_BINARY_DIR=${VTKm_BINARY_DIR}"
@ -132,27 +125,34 @@ function(add_benchmark_test benchmark)
-P "${VTKm_SOURCE_DIR}/CMake/testing/VTKmPerformanceTestReport.cmake"
)
if (enable_upload)
add_test(NAME "${test_name}Upload"
COMMAND ${CMAKE_COMMAND}
"-DVTKm_PERF_REPO=${VTKm_PERF_REPO}"
"-DVTKm_PERF_COMPARE_JSON=${VTKm_PERF_COMPARE_JSON}"
"-DVTKm_SOURCE_DIR=${VTKm_SOURCE_DIR}"
-P "${VTKm_SOURCE_DIR}/CMake/testing/VTKmPerformanceTestUpload.cmake"
)
set_tests_properties("${test_name}Upload" PROPERTIES
DEPENDS ${test_name}Report
FIXTURES_REQUIRED "FixturePerformanceTestCleanUp"
REQUIRED_FILES "${VTKm_PERF_COMPARE_JSON}"
RUN_SERIAL ON)
endif()
###TEST PROPERTIES###########################################################
set_property(TEST ${test_name}Upload PROPERTY DEPENDS ${test_name}Report)
set_property(TEST ${test_name}Report PROPERTY DEPENDS ${test_name}Run)
set_property(TEST ${test_name}Report PROPERTY FIXTURES_REQUIRED "FixturePerformanceTestSetup")
set_property(TEST ${test_name}Upload PROPERTY FIXTURES_REQUIRED "FixturePerformanceTestCleanUp")
set_tests_properties("${test_name}Report" "${test_name}Upload"
set_tests_properties("${test_name}Report"
PROPERTIES
REQUIRED_FILES "${VTKm_PERF_COMPARE_JSON}")
set_tests_properties("${test_name}Run"
"${test_name}Report"
"${test_name}Upload"
"PerformanceTestFetch"
"PerformanceTestCleanUp"
PROPERTIES RUN_SERIAL ON)
set_tests_properties(${test_name}Run PROPERTIES TIMEOUT 1800)
# Only upload when we are inside a CI build
if (NOT DEFINED ENV{CI_COMMIT_SHA} OR NOT DEFINED ENV{VTKM_BENCH_RECORDS_TOKEN})
set_tests_properties(${test_name}Upload PROPERTIES DISABLED TRUE)
endif()
endfunction()

@ -19,7 +19,7 @@ Before you begin, perform initial setup:
3. Use Git to create a local clone of the main VTK repository:
$ git clone https://gitlab.kitware.com/vtk/vtk-m.git
$ git clone git@gitlab.kitware.com:vtk/vtk-m.git
$ cd vtk-m
The main repository will be configured as your `origin` remote.
@ -32,19 +32,24 @@ Before you begin, perform initial setup:
This will prompt for your GitLab user name and configure a remote
called `gitlab` to refer to it.
5. (Optional but highly recommended.)
5. (Required to use Git LFS.)
[Using the SSH URL for the origin remote] is needed for Git LFS to work.
Do not forget to run `$ ./Utilities/SetupForDevelopment.sh` after changing
the remote URL.
6. (Optional but highly recommended.)
[Disabling git-lfs in your fork] is needed to add/modify git-lfs files.
Find the setting to disable git-lfs in your fork through your fork web UI:
Settings/General/Project Features/Git LFS; set it to off; and _save changes_.
6. (Optional but highly recommended.)
7. (Optional but highly recommended.)
[Register with the VTK-m dashboard] on Kitware's CDash instance to
better know how your code performs in regression tests. After
registering and signing in, click on "All Dashboards" link in the upper
left corner, scroll down and click "Subscribe to this project" on the
right of VTK-m.
7. (Optional but highly recommended.)
8. (Optional but highly recommended.)
[Sign up for the VTK-m mailing list] to communicate with other
developers and users.

@ -29,16 +29,18 @@ git config alias.gitlab-sync '!bash Utilities/GitSetup/git-gitlab-sync' &&
echo "Set up git gitlab-sync" &&
true
# shellcheck disable=SC2034
SetupForDevelopment=1
git config hooks.SetupForDevelopment ${SetupForDevelopment_VERSION}
# shellcheck disable=SC2154
git config hooks.SetupForDevelopment "${SetupForDevelopment_VERSION}"
# Setup VTK-m-specifc LFS config
#
# Disable lfsurl if our origin points to the main repo
OriginURL=$(git remote get-url origin)
if [[ "$OriginURL" =~ ^(https://|git@)gitlab\.kitware\.com(/|:)vtk/vtk-m\.git$ ]]
# Only set lfs.url to the ssh url
OriginURL="$(git remote get-url origin)"
if [[ "$OriginURL" =~ ^git@gitlab\.kitware\.com:vtk/vtk-m\.git$ ]]
then
# Disable this setting which overrides every remote/url lfs setting
# This setting overrides every remote/url lfs setting
git config --local lfs.url "${OriginURL}"
# Those settings are only available for newer git-lfs releases

@ -0,0 +1,12 @@
# Added support for `CastAndCallVariableVecField` in `FilterField`
The `FilterField` class provides convenience functions for subclasses to
determine the `ArrayHandle` type for scalar and vector fields. However, you
needed to know the specific size of vectors. For filters that support an
input field of any type, a new form, `CastAndCallVariableVecField` has been
added. This calls the underlying functor with an `ArrayHandleRecombineVec`
of the appropriate component type.
The `CastAndaCallVariableVecField` method also reduces the number of
instances created by having a float fallback for any component type that
does not satisfy the field types.

@ -1,3 +1,3 @@
# New Composite Vector filter
The composite vector filter combines multiple scalar fields into a single vector field. Scalar fields are selected as the active input fields, and the combined vector field is set at the output. The current composite vector filter only supports 2d and 3d scalar field composition. Users may use `vtkm::cont::make_ArrayHandleCompositeVector` to execute a more flexible scalar field composition.
The composite vector filter combines multiple scalar fields into a single vector field. Scalar fields are selected as the active input fields, and the combined vector field is set at the output.

@ -0,0 +1,5 @@
# Fix an issue with copying array from a disabled device
The internal array copy has an optimization to use the device the array
exists on to do the copy. However, if that device is disabled the copy
would fail. This problem has been fixed.

@ -0,0 +1,5 @@
# Fixed operator for IteratorFromArrayPortal
There was an error in `operator-=` for `IteratorFromArrayPortal` that went
by unnoticed. The operator is fixed and regression tests for the operators
has been added.

@ -0,0 +1,5 @@
# Implement Flying Edges for structured cellsets with rectilinear and curvilinear coordinates
When Flying Edges was introduced to compute contours of a 3D structured cellset, it could only process uniform coordinates. This limitation is now lifted : an alternative interpolation function can be used in the fourth pass of the algorithm in order to support rectilinear and curvilinear coordinate systems.
Accordingly, the `Contour` filter now calls `ContourFlyingEdges` instead of `ContourMarchingCells` for these newly supported cases.

@ -0,0 +1,7 @@
# VTKDataSetReader handles any Vec size.
The legacy VTK file reader previously only supported a specific set of Vec
lengths (i.e., 1, 2, 3, 4, 6, and 9). This is because a basic array handle
has to have the vec length compiled in. However, the new
`ArrayHandleRuntimeVec` feature is capable of reading in any vec-length and
can be leveraged to read in arbitrarily sized vectors in field arrays.

@ -0,0 +1,8 @@
# Fix new instances of ArrayHandleRuntimeVec in UnknownArrayHandle
`UnknownArrayHandle` is supposed to treat `ArrayHandleRuntimeVec` the same
as `ArrayHandleBasic`. However, the `NewInstance` methods were failing
because they need custom handling of the vec size. Special cases in the
`UnknownArrayHandle::NewInstance*()` methods have been added to fix this
problem.

@ -133,6 +133,11 @@ struct VTKM_ALWAYS_EXPORT StorageTagRuntimeVec
namespace internal
{
struct RuntimeVecMetaData
{
vtkm::IdComponent NumberOfComponents;
};
template <typename ComponentsPortal>
class Storage<vtkm::VecFromPortal<ComponentsPortal>, vtkm::cont::StorageTagRuntimeVec>
{
@ -152,10 +157,7 @@ class Storage<vtkm::VecFromPortal<ComponentsPortal>, vtkm::cont::StorageTagRunti
(std::is_same<ComponentsPortal, typename ComponentsStorage::WritePortalType>::value),
"Used invalid ComponentsPortal type with expected ComponentsStorageTag.");
struct Info
{
vtkm::IdComponent NumberOfComponents;
};
using Info = RuntimeVecMetaData;
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> ComponentsBuffers(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
@ -370,10 +372,13 @@ public:
///@}
};
/// \c make_ArrayHandleRuntimeVec is convenience function to generate an
/// ArrayHandleRuntimeVec. It takes in an ArrayHandle of values and an
/// array handle of offsets and returns an array handle with consecutive
/// entries grouped in a Vec.
/// `make_ArrayHandleRuntimeVec` is convenience function to generate an
/// `ArrayHandleRuntimeVec`. It takes the number of components stored in
/// each value's `Vec`, which must be specified on the construction of
/// the `ArrayHandleRuntimeVec`. If not specified, the number of components
/// is set to 1. `make_ArrayHandleRuntimeVec` can also optionally take an
/// existing array of components, which will be grouped into `Vec` values
/// based on the specified number of components.
///
template <typename T>
VTKM_CONT auto make_ArrayHandleRuntimeVec(
@ -400,6 +405,62 @@ VTKM_CONT auto make_ArrayHandleRuntimeVec(
return make_ArrayHandleRuntimeVec(1, componentsArray);
}
/// A convenience function for creating an `ArrayHandleRuntimeVec` from a standard C array.
///
template <typename T>
VTKM_CONT auto make_ArrayHandleRuntimeVec(vtkm::IdComponent numComponents,
const T* array,
vtkm::Id numberOfValues,
vtkm::CopyFlag copy)
{
return make_ArrayHandleRuntimeVec(numComponents,
vtkm::cont::make_ArrayHandle(array, numberOfValues, copy));
}
/// A convenience function to move a user-allocated array into an `ArrayHandleRuntimeVec`.
/// The provided array pointer will be reset to `nullptr`.
/// If the array was not allocated with the `new[]` operator, then deleter and reallocater
/// functions must be provided.
///
template <typename T>
VTKM_CONT auto make_ArrayHandleRuntimeVecMove(
vtkm::IdComponent numComponents,
T*& array,
vtkm::Id numberOfValues,
vtkm::cont::internal::BufferInfo::Deleter deleter = internal::SimpleArrayDeleter<T>,
vtkm::cont::internal::BufferInfo::Reallocater reallocater = internal::SimpleArrayReallocater<T>)
{
return make_ArrayHandleRuntimeVec(
numComponents, vtkm::cont::make_ArrayHandleMove(array, numberOfValues, deleter, reallocater));
}
/// A convenience function for creating an `ArrayHandleRuntimeVec` from an `std::vector`.
///
template <typename T, typename Allocator>
VTKM_CONT auto make_ArrayHandleRuntimeVec(vtkm::IdComponent numComponents,
const std::vector<T, Allocator>& array,
vtkm::CopyFlag copy)
{
return make_ArrayHandleRuntimeVec(numComponents, vtkm::cont::make_ArrayHandle(array, copy));
}
/// Move an `std::vector` into an `ArrayHandleRuntimeVec`.
///
template <typename T, typename Allocator>
VTKM_CONT auto make_ArrayHandleRuntimeVecMove(vtkm::IdComponent numComponents,
std::vector<T, Allocator>&& array)
{
return make_ArrayHandleRuntimeVec(numComponents, make_ArrayHandleMove(std::move(array)));
}
template <typename T, typename Allocator>
VTKM_CONT auto make_ArrayHandleRuntimeVec(vtkm::IdComponent numComponents,
std::vector<T, Allocator>&& array,
vtkm::CopyFlag vtkmNotUsed(copy))
{
return make_ArrayHandleRuntimeVecMove(numComponents, std::move(array));
}
namespace internal
{

@ -177,6 +177,16 @@ VTKM_CONT bool UnknownArrayHandle::IsValid() const
VTKM_CONT UnknownArrayHandle UnknownArrayHandle::NewInstance() const
{
if (this->IsStorageType<vtkm::cont::StorageTagRuntimeVec>())
{
// Special case for `ArrayHandleRuntimeVec`, which (1) can be used in place of
// a basic array in `UnknownArrayHandle` and (2) needs a special construction to
// capture the correct number of components. Also note that we are allowing this
// special case to be implemented in `NewInstanceBasic` because it has a better
// fallback (throw an exception rather than create a potentially incompatible
// with the wrong number of components).
return this->NewInstanceBasic();
}
UnknownArrayHandle newArray;
if (this->Container)
{
@ -188,6 +198,25 @@ VTKM_CONT UnknownArrayHandle UnknownArrayHandle::NewInstance() const
VTKM_CONT UnknownArrayHandle UnknownArrayHandle::NewInstanceBasic() const
{
UnknownArrayHandle newArray;
if (this->IsStorageType<vtkm::cont::StorageTagRuntimeVec>())
{
// Special case for `ArrayHandleRuntimeVec`, which (1) can be used in place of
// a basic array in `UnknownArrayHandle` and (2) needs a special construction to
// capture the correct number of components.
auto runtimeVecArrayCreator = [&](auto exampleComponent) {
using ComponentType = decltype(exampleComponent);
if (this->IsBaseComponentType<ComponentType>())
{
newArray =
vtkm::cont::make_ArrayHandleRuntimeVec<ComponentType>(this->GetNumberOfComponentsFlat());
}
};
vtkm::ListForEach(runtimeVecArrayCreator, vtkm::TypeListBaseC{});
if (newArray.IsValid())
{
return newArray;
}
}
if (this->Container)
{
newArray.Container = this->Container->NewInstanceBasic();
@ -197,6 +226,14 @@ VTKM_CONT UnknownArrayHandle UnknownArrayHandle::NewInstanceBasic() const
VTKM_CONT UnknownArrayHandle UnknownArrayHandle::NewInstanceFloatBasic() const
{
if (this->IsStorageType<vtkm::cont::StorageTagRuntimeVec>())
{
// Special case for `ArrayHandleRuntimeVec`, which (1) can be used in place of
// a basic array in `UnknownArrayHandle` and (2) needs a special construction to
// capture the correct number of components.
return vtkm::cont::make_ArrayHandleRuntimeVec<vtkm::FloatDefault>(
this->GetNumberOfComponentsFlat());
}
UnknownArrayHandle newArray;
if (this->Container)
{

@ -52,7 +52,8 @@ struct UnknownCopyOnDevice
// by pulling out one of the component arrays and querying that.
if (!this->Called &&
((device == vtkm::cont::DeviceAdapterTagAny{}) ||
(in.GetComponentArray(0).IsOnDevice(device))))
(in.GetComponentArray(0).IsOnDevice(device) &&
vtkm::cont::GetRuntimeDeviceTracker().CanRunOn(device))))
{
vtkm::cont::Invoker invoke(device);
invoke(CopyWorklet{}, in, out);

@ -98,7 +98,7 @@ public:
VTKM_EXEC_CONT
iter& operator-=(difference_type n)
{
this->Index += static_cast<vtkm::Id>(n);
this->Index -= static_cast<vtkm::Id>(n);
VTKM_ASSERT(this->Index >= 0);
return *this;
}

@ -199,6 +199,24 @@ void TryCopy()
TestValues(input, output);
}
{
std::cout << "unknown -> basic (different type, unsupported device)" << std::endl;
// Force the source to be on the Serial device. If the --vtkm-device argument was
// given with a different device (which is how ctest is set up if compiled with
// any device), then Serial will be turned off.
using SourceType = typename VTraits::template ReplaceComponentType<vtkm::UInt8>;
auto rawInput = MakeInputArray<SourceType>();
{
// Force moving the data to the Serial device.
vtkm::cont::Token token;
rawInput.PrepareForInput(vtkm::cont::DeviceAdapterTagSerial{}, token);
}
vtkm::cont::UnknownArrayHandle input = rawInput;
vtkm::cont::ArrayHandle<ValueType> output;
vtkm::cont::ArrayCopy(input, output);
TestValues(input, output);
}
// Test the copy methods in UnknownArrayHandle. Although this would be appropriate in
// UnitTestUnknownArrayHandle, it is easier to test copies here.
{

@ -11,6 +11,7 @@
#include <vtkm/cont/internal/IteratorFromArrayPortal.h>
#include <vtkm/VecTraits.h>
#include <vtkm/cont/ArrayHandleImplicit.h>
#include <vtkm/cont/internal/ArrayPortalFromIterators.h>
#include <vtkm/cont/testing/Testing.h>
@ -115,6 +116,74 @@ struct TemplatedTests
"Did not get correct values when writing to iterator.");
}
void TestOperators()
{
struct Functor
{
VTKM_EXEC ValueType operator()(vtkm::Id index) const { return TestValue(index, ValueType{}); }
};
Functor functor;
auto array = vtkm::cont::make_ArrayHandleImplicit(functor, ARRAY_SIZE);
auto portal = array.ReadPortal();
VTKM_TEST_ASSERT(test_equal(portal.Get(0), functor(0)));
::CheckPortal(portal);
// Normally, you would use `ArrayPortalToIterators`, but we want to test this
// class specifically.
using IteratorType = vtkm::cont::internal::IteratorFromArrayPortal<decltype(portal)>;
IteratorType begin{ portal };
IteratorType end{ portal, ARRAY_SIZE };
VTKM_TEST_ASSERT(test_equal(*begin, functor(0)));
VTKM_TEST_ASSERT(test_equal(begin[0], functor(0)));
VTKM_TEST_ASSERT(test_equal(begin[3], functor(3)));
IteratorType iter = begin;
VTKM_TEST_ASSERT(test_equal(*iter, functor(0)));
VTKM_TEST_ASSERT(test_equal(*(iter++), functor(0)));
VTKM_TEST_ASSERT(test_equal(*iter, functor(1)));
VTKM_TEST_ASSERT(test_equal(*(++iter), functor(2)));
VTKM_TEST_ASSERT(test_equal(*iter, functor(2)));
VTKM_TEST_ASSERT(test_equal(*(iter--), functor(2)));
VTKM_TEST_ASSERT(test_equal(*iter, functor(1)));
VTKM_TEST_ASSERT(test_equal(*(--iter), functor(0)));
VTKM_TEST_ASSERT(test_equal(*iter, functor(0)));
VTKM_TEST_ASSERT(test_equal(*(iter += 3), functor(3)));
VTKM_TEST_ASSERT(test_equal(*(iter -= 3), functor(0)));
VTKM_TEST_ASSERT(end - begin == ARRAY_SIZE);
VTKM_TEST_ASSERT(test_equal(*(iter + 3), functor(3)));
VTKM_TEST_ASSERT(test_equal(*(3 + iter), functor(3)));
iter += 3;
VTKM_TEST_ASSERT(test_equal(*(iter - 3), functor(0)));
VTKM_TEST_ASSERT(iter == (begin + 3));
VTKM_TEST_ASSERT(!(iter != (begin + 3)));
VTKM_TEST_ASSERT(iter != begin);
VTKM_TEST_ASSERT(!(iter == begin));
VTKM_TEST_ASSERT(!(iter < begin));
VTKM_TEST_ASSERT(!(iter < (begin + 3)));
VTKM_TEST_ASSERT((iter < end));
VTKM_TEST_ASSERT(!(iter <= begin));
VTKM_TEST_ASSERT((iter <= (begin + 3)));
VTKM_TEST_ASSERT((iter <= end));
VTKM_TEST_ASSERT((iter > begin));
VTKM_TEST_ASSERT(!(iter > (begin + 3)));
VTKM_TEST_ASSERT(!(iter > end));
VTKM_TEST_ASSERT((iter >= begin));
VTKM_TEST_ASSERT((iter >= (begin + 3)));
VTKM_TEST_ASSERT(!(iter >= end));
}
void operator()()
{
ValueType array[ARRAY_SIZE];
@ -133,6 +202,9 @@ struct TemplatedTests
std::cout << " Test write to iterator." << std::endl;
TestIteratorWrite(portal);
std::cout << " Test operators." << std::endl;
TestOperators();
}
};

@ -11,6 +11,7 @@
#include <vtkm/cont/UncertainArrayHandle.h>
#include <vtkm/cont/UnknownArrayHandle.h>
#include <vtkm/cont/ArrayCopy.h>
#include <vtkm/cont/ArrayHandleCast.h>
#include <vtkm/cont/ArrayHandleConstant.h>
#include <vtkm/cont/ArrayHandleCounting.h>
@ -543,11 +544,10 @@ void TrySetMultiplexerArray()
CheckUnknownArray<vtkm::List<vtkm::Id>, vtkm::List<VTKM_DEFAULT_STORAGE_TAG>>(unknownArray, 1);
}
template <typename T>
template <typename T, typename BasicComponentType = typename vtkm::VecFlat<T>::ComponentType>
void TryConvertRuntimeVec()
{
using BasicArrayType = vtkm::cont::ArrayHandle<T>;
using BasicComponentType = typename vtkm::VecFlat<T>::ComponentType;
constexpr vtkm::IdComponent numFlatComponents = vtkm::VecFlat<T>::NUM_COMPONENTS;
using RuntimeArrayType = vtkm::cont::ArrayHandleRuntimeVec<BasicComponentType>;
@ -574,6 +574,27 @@ void TryConvertRuntimeVec()
VTKM_TEST_ASSERT(unknownWithRuntimeVec.CanConvert<BasicArrayType>());
BasicArrayType outputArray = unknownWithRuntimeVec.AsArrayHandle<BasicArrayType>();
VTKM_TEST_ASSERT(test_equal_ArrayHandles(inputArray, outputArray));
std::cout << " Copy ArrayHandleRuntimeVec to a new instance" << std::endl;
vtkm::cont::UnknownArrayHandle unknownCopy = unknownWithRuntimeVec.NewInstance();
VTKM_TEST_ASSERT(unknownWithRuntimeVec.GetNumberOfComponentsFlat() ==
unknownCopy.GetNumberOfComponentsFlat());
vtkm::cont::ArrayCopy(unknownWithRuntimeVec, unknownCopy);
VTKM_TEST_ASSERT(test_equal_ArrayHandles(inputArray, unknownCopy));
std::cout << " Copy ArrayHandleRuntimeVec as basic array" << std::endl;
unknownCopy = unknownWithRuntimeVec.NewInstanceBasic();
VTKM_TEST_ASSERT(unknownWithRuntimeVec.GetNumberOfComponentsFlat() ==
unknownCopy.GetNumberOfComponentsFlat());
vtkm::cont::ArrayCopy(unknownWithRuntimeVec, unknownCopy);
VTKM_TEST_ASSERT(test_equal_ArrayHandles(inputArray, unknownCopy));
std::cout << " Copy ArrayHandleRuntimeVec to float array" << std::endl;
unknownCopy = unknownWithRuntimeVec.NewInstanceFloatBasic();
VTKM_TEST_ASSERT(unknownWithRuntimeVec.GetNumberOfComponentsFlat() ==
unknownCopy.GetNumberOfComponentsFlat());
vtkm::cont::ArrayCopy(unknownWithRuntimeVec, unknownCopy);
VTKM_TEST_ASSERT(test_equal_ArrayHandles(inputArray, unknownCopy));
}
void TryConvertRuntimeVec()
@ -592,6 +613,16 @@ void TryConvertRuntimeVec()
std::cout << " Vec of Vecs of Vecs." << std::endl;
TryConvertRuntimeVec<vtkm::Vec<vtkm::Vec<vtkm::Id4, 3>, 2>>();
std::cout << " Compatible but different C types." << std::endl;
if (sizeof(int) == sizeof(long))
{
TryConvertRuntimeVec<vtkm::Vec<int, 4>, long>();
}
else // assuming sizeof(long long) == sizeof(long)
{
TryConvertRuntimeVec<vtkm::Vec<long long, 4>, long>();
}
}
struct DefaultTypeFunctor

@ -13,6 +13,8 @@
#include <vtkm/filter/Filter.h>
#include <vtkm/cont/ArrayCopy.h>
namespace vtkm
{
namespace filter
@ -46,7 +48,7 @@ public:
vtkm::cont::Field::Association association = vtkm::cont::Field::Association::Any)
{
auto index_st = static_cast<std::size_t>(index);
ResizeIfNeeded(index_st);
this->ResizeIfNeeded(index_st);
this->ActiveFieldNames[index_st] = name;
this->ActiveFieldAssociation[index_st] = association;
}
@ -79,7 +81,7 @@ public:
void SetActiveCoordinateSystem(vtkm::IdComponent index, vtkm::Id coord_idx)
{
auto index_st = static_cast<std::size_t>(index);
ResizeIfNeeded(index_st);
this->ResizeIfNeeded(index_st);
this->ActiveCoordinateSystemIndices[index_st] = coord_idx;
}
@ -120,6 +122,19 @@ public:
}
///@}
/// \brief Return the number of active fields currently set.
///
/// The general interface to `FilterField` allows a user to set an arbitrary number
/// of active fields (indexed 0 and on). This method returns the number of active
/// fields that are set. Note that the filter implementation is free to ignore
/// any active fields it does not support. Also note that an active field can be
/// set to be either a named field or a coordinate system.
vtkm::IdComponent GetNumberOfActiveFields() const
{
VTKM_ASSERT(this->ActiveFieldNames.size() == this->UseCoordinateSystemAsField.size());
return static_cast<vtkm::IdComponent>(this->UseCoordinateSystemAsField.size());
}
protected:
VTKM_CONT
const vtkm::cont::Field& GetFieldFromDataSet(const vtkm::cont::DataSet& input) const
@ -147,6 +162,16 @@ protected:
}
}
///@{
/// \brief Convenience method to get the array from a filter's input scalar field.
///
/// A field filter typically gets its input fields using the internal `GetFieldFromDataSet`.
/// To use this field in a worklet, it eventually needs to be converted to an
/// `ArrayHandle`. If the input field is limited to be a scalar field, then this method
/// provides a convenient way to determine the correct array type. Like other `CastAndCall`
/// methods, it takes as input a `Field` (or `UnknownArrayHandle`) and a function/functor
/// to call with the appropriate `ArrayHandle` type.
///
template <typename Functor, typename... Args>
VTKM_CONT void CastAndCallScalarField(const vtkm::cont::UnknownArrayHandle& fieldArray,
Functor&& functor,
@ -165,6 +190,7 @@ protected:
this->CastAndCallScalarField(
field.GetData(), std::forward<Functor>(functor), std::forward<Args>(args)...);
}
///@}
private:
@ -176,6 +202,18 @@ private:
};
protected:
///@{
/// \brief Convenience method to get the array from a filter's input vector field.
///
/// A field filter typically gets its input fields using the internal `GetFieldFromDataSet`.
/// To use this field in a worklet, it eventually needs to be converted to an
/// `ArrayHandle`. If the input field is limited to be a vector field with vectors of a
/// specific size, then this method provides a convenient way to determine the correct array
/// type. Like other `CastAndCall` methods, it takes as input a `Field` (or
/// `UnknownArrayHandle`) and a function/functor to call with the appropriate `ArrayHandle`
/// type. You also have to provide the vector size as the first template argument.
/// For example `CastAndCallVecField<3>(field, functor);`.
///
template <vtkm::IdComponent VecSize, typename Functor, typename... Args>
VTKM_CONT void CastAndCallVecField(const vtkm::cont::UnknownArrayHandle& fieldArray,
Functor&& functor,
@ -195,6 +233,52 @@ protected:
this->CastAndCallVecField<VecSize>(
field.GetData(), std::forward<Functor>(functor), std::forward<Args>(args)...);
}
///@}
///@{
/// This method is like `CastAndCallVecField` except that it can be used for a
/// field of unknown vector size (or scalars). This method will call the given
/// functor with an `ArrayHandleRecombineVec`.
///
/// Note that there are limitations with using `ArrayHandleRecombineVec` within a
/// worklet. Because the size of the vectors are not known at compile time, you
/// cannot just create an intermediate `Vec` of the correct size. Typically, you
/// must allocate the output array (for example, with `ArrayHandleRuntimeVec`), and
/// the worklet must iterate over the components and store them in the prealocated
/// output.
///
template <typename Functor, typename... Args>
VTKM_CONT void CastAndCallVariableVecField(const vtkm::cont::UnknownArrayHandle& fieldArray,
Functor&& functor,
Args&&... args) const
{
if (fieldArray.IsBaseComponentType<vtkm::Float32>())
{
functor(fieldArray.ExtractArrayFromComponents<vtkm::Float32>(), std::forward<Args>(args)...);
}
else if (fieldArray.IsBaseComponentType<vtkm::Float64>())
{
functor(fieldArray.ExtractArrayFromComponents<vtkm::Float64>(), std::forward<Args>(args)...);
}
else
{
// Field component type is not directly supported. Copy to floating point array.
vtkm::cont::UnknownArrayHandle floatArray = fieldArray.NewInstanceFloatBasic();
vtkm::cont::ArrayCopy(fieldArray, floatArray);
functor(floatArray.ExtractArrayFromComponents<vtkm::FloatDefault>(),
std::forward<Args>(args)...);
}
}
template <typename Functor, typename... Args>
VTKM_CONT void CastAndCallVariableVecField(const vtkm::cont::Field& field,
Functor&& functor,
Args&&... args) const
{
this->CastAndCallVariableVecField(
field.GetData(), std::forward<Functor>(functor), std::forward<Args>(args)...);
}
///@}
/// \brief Create the output data set for `DoExecute`
///

@ -13,7 +13,7 @@
#include <vtkm/cont/ArrayCopy.h>
#include <vtkm/cont/testing/MakeTestDataSet.h>
#include <vtkm/cont/testing/Testing.h>
#include <vtkm/filter/contour/Contour.h>
#include <vtkm/filter/contour/ContourMarchingCells.h>
namespace
{
@ -72,13 +72,7 @@ void TestPointMerging()
vtkm::cont::testing::MakeTestDataSet makeDataSet;
vtkm::cont::DataSet baseData = makeDataSet.Make3DUniformDataSet3(vtkm::Id3(4, 4, 4));
//Convert the baseData implicit points to explicit points, since the contour
//filter for uniform data always does point merging
vtkm::cont::ArrayHandle<vtkm::Vec3f> newcoords;
vtkm::cont::ArrayCopy(baseData.GetCoordinateSystem().GetData(), newcoords);
baseData.AddPointField(baseData.GetCoordinateSystemName(), newcoords);
vtkm::filter::contour::Contour marchingCubes;
vtkm::filter::contour::ContourMarchingCells marchingCubes;
marchingCubes.SetIsoValue(0.05);
marchingCubes.SetMergeDuplicatePoints(false);
marchingCubes.SetActiveField("pointvar");

@ -34,11 +34,8 @@ vtkm::cont::DataSet Contour::DoExecute(const vtkm::cont::DataSet& inDataSet)
auto inCoords = inDataSet.GetCoordinateSystem(this->GetActiveCoordinateSystemIndex()).GetData();
std::unique_ptr<vtkm::filter::contour::AbstractContour> implementation;
// For now, Flying Edges is only used for 3D Structured CellSets,
// using Uniform coordinates.
if (inCellSet.template IsType<vtkm::cont::CellSetStructured<3>>() &&
inCoords.template IsType<
vtkm::cont::ArrayHandle<vtkm::Vec3f, vtkm::cont::StorageTagUniformPoints>>())
// Flying Edges is only used for 3D Structured CellSets
if (inCellSet.template IsType<vtkm::cont::CellSetStructured<3>>())
{
VTKM_LOG_S(vtkm::cont::LogLevel::Info, "Using flying edges");
implementation.reset(new vtkm::filter::contour::ContourFlyingEdges);

@ -44,13 +44,10 @@ vtkm::cont::DataSet ContourFlyingEdges::DoExecute(const vtkm::cont::DataSet& inD
const vtkm::cont::CoordinateSystem& inCoords =
inDataSet.GetCoordinateSystem(this->GetActiveCoordinateSystemIndex());
if (!inCellSet.template IsType<vtkm::cont::CellSetStructured<3>>() ||
!inCoords.GetData()
.template IsType<
vtkm::cont::ArrayHandle<vtkm::Vec3f, vtkm::cont::StorageTagUniformPoints>>())
if (!inCellSet.template IsType<vtkm::cont::CellSetStructured<3>>())
{
throw vtkm::cont::ErrorFilterExecution("This filter is only available for 3-Dimensional "
"Structured Cell Sets using uniform point coordinates.");
"Structured Cell Sets");
}
// Get the CellSet's known dynamic type
@ -74,22 +71,11 @@ vtkm::cont::DataSet ContourFlyingEdges::DoExecute(const vtkm::cont::DataSet& inD
if (this->GenerateNormals && !this->GetComputeFastNormals())
{
outputCells = worklet.Run(
ivalues,
inputCells,
inCoords.GetData().AsArrayHandle<vtkm::cont::ArrayHandleUniformPointCoordinates>(),
concrete,
vertices,
normals);
outputCells = worklet.Run(ivalues, inputCells, inCoords, concrete, vertices, normals);
}
else
{
outputCells = worklet.Run(
ivalues,
inputCells,
inCoords.GetData().AsArrayHandle<vtkm::cont::ArrayHandleUniformPointCoordinates>(),
concrete,
vertices);
outputCells = worklet.Run(ivalues, inputCells, inCoords, concrete, vertices);
}
};

@ -176,24 +176,12 @@ public:
void TestUnsupportedFlyingEdges() const
{
vtkm::cont::testing::MakeTestDataSet maker;
vtkm::cont::DataSet rectilinearDataset = maker.Make3DRectilinearDataSet0();
vtkm::cont::DataSet explicitDataSet = maker.Make3DExplicitDataSet0();
vtkm::filter::contour::ContourFlyingEdges filter;
filter.SetIsoValue(2.0);
filter.SetActiveField("pointvar");
try
{
filter.Execute(rectilinearDataset);
VTKM_TEST_FAIL("Flying Edges filter should not run on datasets with rectilinear coordinates");
}
catch (vtkm::cont::ErrorFilterExecution&)
{
std::cout << "Execution successfully aborted" << std::endl;
}
try
{
filter.Execute(explicitDataSet);
@ -205,6 +193,58 @@ public:
}
}
template <typename ContourFilterType>
void TestNonUniformStructured() const
{
auto pathname =
vtkm::cont::testing::Testing::DataPath("rectilinear/simple_rectilinear1_ascii.vtk");
vtkm::io::VTKDataSetReader reader(pathname);
vtkm::cont::DataSet rectilinearDataset = reader.ReadDataSet();
// Single-cell contour
ContourFilterType filter;
filter.SetActiveField("var");
filter.SetIsoValue(2.0);
vtkm::cont::DataSet outputSingleCell = filter.Execute(rectilinearDataset);
auto coordinates = outputSingleCell.GetCoordinateSystem()
.GetData()
.AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Vec3f>>();
VTKM_TEST_ASSERT(outputSingleCell.GetNumberOfPoints() == 3,
"Wrong number of points in rectilinear contour");
VTKM_TEST_ASSERT(outputSingleCell.GetNumberOfCells() == 1,
"Wrong number of cells in rectilinear contour");
VTKM_TEST_ASSERT(outputSingleCell.GetCellSet().GetCellShape(0) == vtkm::CELL_SHAPE_TRIANGLE,
"Wrong contour cell shape");
auto expectedCoordinates =
vtkm::cont::make_ArrayHandle<vtkm::Vec3f>({ vtkm::Vec3f{ 10.0f, -10.0f, 9.66341f },
vtkm::Vec3f{ 9.30578f, -10.0f, 10.0f },
vtkm::Vec3f{ 10.0f, -9.78842f, 10.0f } });
VTKM_TEST_ASSERT(test_equal_ArrayHandles(coordinates, expectedCoordinates),
"Wrong contour coordinates");
// Generating normals triggers a different worklet for Flying Edges pass 4,
// But it should not change anything on the contour itself.
filter.SetGenerateNormals(true);
vtkm::cont::DataSet outputNormals = filter.Execute(rectilinearDataset);
coordinates = outputNormals.GetCoordinateSystem()
.GetData()
.AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Vec3f>>();
VTKM_TEST_ASSERT(test_equal_ArrayHandles(coordinates, expectedCoordinates),
"Wrong contour coordinates");
// Full contour
filter.SetIsoValue(3.0);
filter.SetGenerateNormals(false);
vtkm::cont::DataSet output = filter.Execute(rectilinearDataset);
VTKM_TEST_ASSERT(output.GetNumberOfPoints() == 93,
"Wrong number of points in rectilinear contour");
VTKM_TEST_ASSERT(output.GetNumberOfCells() == 144,
"Wrong number of cells in rectilinear contour");
}
void operator()() const
{
this->TestContourUniformGrid<vtkm::filter::contour::Contour>(72);
@ -220,6 +260,10 @@ public:
this->TestContourWedges<vtkm::filter::contour::Contour>();
this->TestContourWedges<vtkm::filter::contour::ContourMarchingCells>();
this->TestNonUniformStructured<vtkm::filter::contour::Contour>();
this->TestNonUniformStructured<vtkm::filter::contour::ContourFlyingEdges>();
this->TestNonUniformStructured<vtkm::filter::contour::ContourMarchingCells>();
this->TestUnsupportedFlyingEdges();
}

@ -67,13 +67,14 @@ public:
// Filter called without normals generation
template <typename ValueType,
typename CoordsType,
typename StorageTagField,
typename CoordinateType,
typename StorageTagVertices>
vtkm::cont::CellSetSingleType<> Run(
const std::vector<ValueType>& isovalues,
const vtkm::cont::CellSetStructured<3>& cells,
const vtkm::cont::ArrayHandleUniformPointCoordinates& coordinateSystem,
const CoordsType& coordinateSystem,
const vtkm::cont::ArrayHandle<ValueType, StorageTagField>& input,
vtkm::cont::ArrayHandle<vtkm::Vec<CoordinateType, 3>, StorageTagVertices>& vertices)
{
@ -87,6 +88,7 @@ public:
// Filter called with normals generation
template <typename ValueType,
typename CoordsType,
typename StorageTagField,
typename CoordinateType,
typename StorageTagVertices,
@ -94,7 +96,7 @@ public:
vtkm::cont::CellSetSingleType<> Run(
const std::vector<ValueType>& isovalues,
const vtkm::cont::CellSetStructured<3>& cells,
const vtkm::cont::ArrayHandleUniformPointCoordinates& coordinateSystem,
const CoordsType& coordinateSystem,
const vtkm::cont::ArrayHandle<ValueType, StorageTagField>& input,
vtkm::cont::ArrayHandle<vtkm::Vec<CoordinateType, 3>, StorageTagVertices>& vertices,
vtkm::cont::ArrayHandle<vtkm::Vec<CoordinateType, 3>, StorageTagNormals>& normals)

@ -41,6 +41,7 @@ vtkm::Id extend_by(vtkm::cont::ArrayHandle<T, S>& handle, vtkm::Id size)
//----------------------------------------------------------------------------
template <typename ValueType,
typename CoordsType,
typename StorageTagField,
typename StorageTagVertices,
typename StorageTagNormals,
@ -48,7 +49,7 @@ template <typename ValueType,
typename NormalType>
vtkm::cont::CellSetSingleType<> execute(
const vtkm::cont::CellSetStructured<3>& cells,
const vtkm::cont::ArrayHandleUniformPointCoordinates& coordinateSystem,
const CoordsType coordinateSystem,
const std::vector<ValueType>& isovalues,
const vtkm::cont::ArrayHandle<ValueType, StorageTagField>& inputField,
vtkm::cont::ArrayHandle<vtkm::Vec<CoordinateType, 3>, StorageTagVertices>& points,
@ -56,18 +57,10 @@ vtkm::cont::CellSetSingleType<> execute(
vtkm::worklet::contour::CommonState& sharedState)
{
vtkm::cont::Invoker invoke;
vtkm::Vec3f origin, spacing;
{ //extract out the origin and spacing as these are needed for Pass4 to properly
//interpolate the new points
auto portal = coordinateSystem.ReadPortal();
origin = portal.GetOrigin();
spacing = portal.GetSpacing();
}
auto pdims = cells.GetPointDimensions();
vtkm::cont::ArrayHandle<vtkm::UInt8> edgeCases;
edgeCases.Allocate(coordinateSystem.GetNumberOfValues());
edgeCases.Allocate(coordinateSystem.GetData().GetNumberOfValues());
vtkm::cont::CellSetStructured<2> metaDataMesh2D;
vtkm::cont::ArrayHandle<vtkm::Id> metaDataLinearSums; //per point of metaDataMesh
@ -158,8 +151,7 @@ vtkm::cont::CellSetSingleType<> execute(
{
VTKM_LOG_SCOPE(vtkm::cont::LogLevel::Perf, "FlyingEdges Pass4");
launchComputePass4 pass4(
pdims, origin, spacing, multiContourCellOffset, multiContourPointOffset);
auto pass4 = launchComputePass4(pdims, multiContourCellOffset, multiContourPointOffset);
detail::extend_by(points, newPointSize);
if (sharedState.GenerateNormals)
@ -171,6 +163,7 @@ vtkm::cont::CellSetSingleType<> execute(
pass4,
newPointSize,
isoval,
coordinateSystem,
inputField,
edgeCases,
metaDataMesh2D,

@ -28,20 +28,14 @@ namespace flying_edges
struct launchComputePass4
{
vtkm::Id3 PointDims;
vtkm::Vec3f Origin;
vtkm::Vec3f Spacing;
vtkm::Id CellWriteOffset;
vtkm::Id PointWriteOffset;
launchComputePass4(const vtkm::Id3& pdims,
const vtkm::Vec3f& origin,
const vtkm::Vec3f& spacing,
vtkm::Id multiContourCellOffset,
vtkm::Id multiContourPointOffset)
: PointDims(pdims)
, Origin(origin)
, Spacing(spacing)
, CellWriteOffset(multiContourCellOffset)
, PointWriteOffset(multiContourPointOffset)
{
@ -49,6 +43,7 @@ struct launchComputePass4
template <typename DeviceAdapterTag,
typename T,
typename CoordsType,
typename StorageTagField,
typename MeshSums,
typename PointType,
@ -56,6 +51,7 @@ struct launchComputePass4
VTKM_CONT bool LaunchXAxis(DeviceAdapterTag device,
vtkm::Id vtkmNotUsed(newPointSize),
T isoval,
CoordsType coordinateSystem,
const vtkm::cont::ArrayHandle<T, StorageTagField>& inputField,
vtkm::cont::ArrayHandle<vtkm::UInt8> edgeCases,
vtkm::cont::CellSetStructured<2>& metaDataMesh2D,
@ -71,12 +67,8 @@ struct launchComputePass4
vtkm::cont::Invoker invoke(device);
if (sharedState.GenerateNormals)
{
ComputePass4XWithNormals<T> worklet4(isoval,
this->PointDims,
this->Origin,
this->Spacing,
this->CellWriteOffset,
this->PointWriteOffset);
ComputePass4XWithNormals<T> worklet4(
isoval, this->PointDims, this->CellWriteOffset, this->PointWriteOffset);
invoke(worklet4,
metaDataMesh2D,
metaDataSums,
@ -84,6 +76,7 @@ struct launchComputePass4
metaDataMax,
metaDataNumTris,
edgeCases,
coordinateSystem,
inputField,
triangle_topology,
sharedState.InterpolationEdgeIds,
@ -94,12 +87,8 @@ struct launchComputePass4
}
else
{
ComputePass4X<T> worklet4(isoval,
this->PointDims,
this->Origin,
this->Spacing,
this->CellWriteOffset,
this->PointWriteOffset);
ComputePass4X<T> worklet4(
isoval, this->PointDims, this->CellWriteOffset, this->PointWriteOffset);
invoke(worklet4,
metaDataMesh2D,
metaDataSums,
@ -107,6 +96,7 @@ struct launchComputePass4
metaDataMax,
metaDataNumTris,
edgeCases,
coordinateSystem,
inputField,
triangle_topology,
sharedState.InterpolationEdgeIds,
@ -120,6 +110,7 @@ struct launchComputePass4
template <typename DeviceAdapterTag,
typename T,
typename CoordsType,
typename StorageTagField,
typename MeshSums,
typename PointType,
@ -127,6 +118,7 @@ struct launchComputePass4
VTKM_CONT bool LaunchYAxis(DeviceAdapterTag device,
vtkm::Id newPointSize,
T isoval,
CoordsType coordinateSystem,
const vtkm::cont::ArrayHandle<T, StorageTagField>& inputField,
vtkm::cont::ArrayHandle<vtkm::UInt8> edgeCases,
vtkm::cont::CellSetStructured<2>& metaDataMesh2D,
@ -157,11 +149,8 @@ struct launchComputePass4
sharedState.CellIdMap);
//This needs to be done on array handle view ( start = this->PointWriteOffset, len = newPointSize)
ComputePass5Y<T> worklet5(this->PointDims,
this->Origin,
this->Spacing,
this->PointWriteOffset,
sharedState.GenerateNormals);
ComputePass5Y<T> worklet5(this->PointDims, this->PointWriteOffset, sharedState.GenerateNormals);
invoke(worklet5,
vtkm::cont::make_ArrayHandleView(
sharedState.InterpolationEdgeIds, this->PointWriteOffset, newPointSize),
@ -169,6 +158,7 @@ struct launchComputePass4
sharedState.InterpolationWeights, this->PointWriteOffset, newPointSize),
vtkm::cont::make_ArrayHandleView(points, this->PointWriteOffset, newPointSize),
inputField,
coordinateSystem,
normals);
return true;

@ -32,9 +32,6 @@ struct ComputePass4X : public vtkm::worklet::WorkletVisitCellsWithPoints
{
vtkm::Id3 PointDims;
vtkm::Vec3f Origin;
vtkm::Vec3f Spacing;
T IsoValue;
vtkm::Id CellWriteOffset;
@ -43,13 +40,9 @@ struct ComputePass4X : public vtkm::worklet::WorkletVisitCellsWithPoints
ComputePass4X() {}
ComputePass4X(T value,
const vtkm::Id3& pdims,
const vtkm::Vec3f& origin,
const vtkm::Vec3f& spacing,
vtkm::Id multiContourCellOffset,
vtkm::Id multiContourPointOffset)
: PointDims(pdims)
, Origin(origin)
, Spacing(spacing)
, IsoValue(value)
, CellWriteOffset(multiContourCellOffset)
, PointWriteOffset(multiContourPointOffset)
@ -62,6 +55,7 @@ struct ComputePass4X : public vtkm::worklet::WorkletVisitCellsWithPoints
FieldInPoint axis_maxs,
WholeArrayIn cell_tri_count,
WholeArrayIn edgeData,
WholeArrayIn coords,
WholeArrayIn data,
WholeArrayOut connectivity,
WholeArrayOut edgeIds,
@ -69,13 +63,14 @@ struct ComputePass4X : public vtkm::worklet::WorkletVisitCellsWithPoints
WholeArrayOut inputCellIds,
WholeArrayOut points);
using ExecutionSignature =
void(ThreadIndices, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, WorkIndex);
void(ThreadIndices, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, WorkIndex);
template <typename ThreadIndices,
typename FieldInPointId3,
typename FieldInPointId,
typename WholeTriField,
typename WholeEdgeField,
typename WholeCoordsField,
typename WholeDataField,
typename WholeConnField,
typename WholeEdgeIdField,
@ -88,6 +83,7 @@ struct ComputePass4X : public vtkm::worklet::WorkletVisitCellsWithPoints
const FieldInPointId& axis_maxs,
const WholeTriField& cellTriCount,
const WholeEdgeField& edges,
const WholeCoordsField& coords,
const WholeDataField& field,
const WholeConnField& conn,
const WholeEdgeIdField& interpolatedEdgeIds,
@ -141,6 +137,7 @@ struct ComputePass4X : public vtkm::worklet::WorkletVisitCellsWithPoints
field,
interpolatedEdgeIds,
weights,
coords,
points,
state.startPos,
increments,
@ -158,12 +155,14 @@ struct ComputePass4X : public vtkm::worklet::WorkletVisitCellsWithPoints
template <typename WholeDataField,
typename WholeIEdgeField,
typename WholeWeightField,
typename WholeCoordsField,
typename WholePointField>
VTKM_EXEC inline void Generate(const vtkm::Vec<vtkm::UInt8, 3>& boundaryStatus,
const vtkm::Id3& ijk,
const WholeDataField& field,
const WholeIEdgeField& interpolatedEdgeIds,
const WholeWeightField& weights,
const WholeCoordsField coords,
const WholePointField& points,
const vtkm::Id4& startPos,
const vtkm::Id3& incs,
@ -188,7 +187,7 @@ struct ComputePass4X : public vtkm::worklet::WorkletVisitCellsWithPoints
interpolatedEdgeIds.Set(writeIndex, pos);
weights.Set(writeIndex, static_cast<vtkm::FloatDefault>(t));
auto coord = this->InterpolateCoordinate(t, ijk, ijk + vtkm::Id3{ 1, 0, 0 });
auto coord = this->InterpolateCoordinate(coords, t, ijk, ijk + vtkm::Id3{ 1, 0, 0 });
points.Set(writeIndex, coord);
}
if (edgeUses[4])
@ -201,7 +200,7 @@ struct ComputePass4X : public vtkm::worklet::WorkletVisitCellsWithPoints
interpolatedEdgeIds.Set(writeIndex, pos);
weights.Set(writeIndex, static_cast<vtkm::FloatDefault>(t));
auto coord = this->InterpolateCoordinate(t, ijk, ijk + vtkm::Id3{ 0, 1, 0 });
auto coord = this->InterpolateCoordinate(coords, t, ijk, ijk + vtkm::Id3{ 0, 1, 0 });
points.Set(writeIndex, coord);
}
if (edgeUses[8])
@ -214,7 +213,7 @@ struct ComputePass4X : public vtkm::worklet::WorkletVisitCellsWithPoints
interpolatedEdgeIds.Set(writeIndex, pos);
weights.Set(writeIndex, static_cast<vtkm::FloatDefault>(t));
auto coord = this->InterpolateCoordinate(t, ijk, ijk + vtkm::Id3{ 0, 0, 1 });
auto coord = this->InterpolateCoordinate(coords, t, ijk, ijk + vtkm::Id3{ 0, 0, 1 });
points.Set(writeIndex, coord);
}
}
@ -231,30 +230,30 @@ struct ComputePass4X : public vtkm::worklet::WorkletVisitCellsWithPoints
const bool onZ = boundaryStatus[AxisToSum::zindex] & FlyingEdges3D::MaxBoundary;
if (onX) //+x boundary
{
this->InterpolateEdge(ijk, pos[0], incs, 5, edgeUses, edgeIds, field, interpolatedEdgeIds, weights, points);
this->InterpolateEdge(ijk, pos[0], incs, 9, edgeUses, edgeIds, field, interpolatedEdgeIds, weights, points);
this->InterpolateEdge(ijk, pos[0], incs, 5, edgeUses, edgeIds, field, interpolatedEdgeIds, weights, coords, points);
this->InterpolateEdge(ijk, pos[0], incs, 9, edgeUses, edgeIds, field, interpolatedEdgeIds, weights, coords, points);
if (onY) //+x +y
{
this->InterpolateEdge(ijk, pos[0], incs, 11, edgeUses, edgeIds, field, interpolatedEdgeIds, weights, points);
this->InterpolateEdge(ijk, pos[0], incs, 11, edgeUses, edgeIds, field, interpolatedEdgeIds, weights, coords, points);
}
if (onZ) //+x +z
{
this->InterpolateEdge(ijk, pos[0], incs, 7, edgeUses, edgeIds, field, interpolatedEdgeIds, weights, points);
this->InterpolateEdge(ijk, pos[0], incs, 7, edgeUses, edgeIds, field, interpolatedEdgeIds, weights, coords, points);
}
}
if (onY) //+y boundary
{
this->InterpolateEdge(ijk, pos[0], incs, 1, edgeUses, edgeIds, field, interpolatedEdgeIds, weights, points);
this->InterpolateEdge(ijk, pos[0], incs, 10, edgeUses, edgeIds, field, interpolatedEdgeIds, weights, points);
this->InterpolateEdge(ijk, pos[0], incs, 1, edgeUses, edgeIds, field, interpolatedEdgeIds, weights, coords, points);
this->InterpolateEdge(ijk, pos[0], incs, 10, edgeUses, edgeIds, field, interpolatedEdgeIds, weights, coords, points);
if (onZ) //+y +z boundary
{
this->InterpolateEdge(ijk, pos[0], incs, 3, edgeUses, edgeIds, field, interpolatedEdgeIds, weights, points);
this->InterpolateEdge(ijk, pos[0], incs, 3, edgeUses, edgeIds, field, interpolatedEdgeIds, weights, coords, points);
}
}
if (onZ) //+z boundary
{
this->InterpolateEdge(ijk, pos[0], incs, 2, edgeUses, edgeIds, field, interpolatedEdgeIds, weights, points);
this->InterpolateEdge(ijk, pos[0], incs, 6, edgeUses, edgeIds, field, interpolatedEdgeIds, weights, points);
this->InterpolateEdge(ijk, pos[0], incs, 2, edgeUses, edgeIds, field, interpolatedEdgeIds, weights, coords, points);
this->InterpolateEdge(ijk, pos[0], incs, 6, edgeUses, edgeIds, field, interpolatedEdgeIds, weights, coords, points);
}
// clang-format on
}
@ -264,6 +263,7 @@ struct ComputePass4X : public vtkm::worklet::WorkletVisitCellsWithPoints
template <typename WholeField,
typename WholeIEdgeField,
typename WholeWeightField,
typename WholeCoordsField,
typename WholePointField>
VTKM_EXEC inline void InterpolateEdge(const vtkm::Id3& ijk,
vtkm::Id currentIdx,
@ -274,6 +274,7 @@ struct ComputePass4X : public vtkm::worklet::WorkletVisitCellsWithPoints
const WholeField& field,
const WholeIEdgeField& interpolatedEdgeIds,
const WholeWeightField& weights,
const WholeCoordsField& coords,
const WholePointField& points) const
{
using AxisToSum = SumXAxis;
@ -300,30 +301,49 @@ struct ComputePass4X : public vtkm::worklet::WorkletVisitCellsWithPoints
T t = static_cast<T>((this->IsoValue - s0) / (s1 - s0));
weights.Set(writeIndex, static_cast<vtkm::FloatDefault>(t));
auto coord = this->InterpolateCoordinate(t, ijk + offsets1, ijk + offsets2);
auto coord = this->InterpolateCoordinate(coords, t, ijk + offsets1, ijk + offsets2);
points.Set(writeIndex, coord);
}
// Fast interpolation method for uniform coordinates
//----------------------------------------------------------------------------
inline VTKM_EXEC vtkm::Vec3f InterpolateCoordinate(T t,
const vtkm::Id3& ijk0,
const vtkm::Id3& ijk1) const
inline VTKM_EXEC vtkm::Vec3f InterpolateCoordinate(
vtkm::internal::ArrayPortalUniformPointCoordinates coords,
T t,
const vtkm::Id3& ijk0,
const vtkm::Id3& ijk1) const
{
return vtkm::Vec3f(
this->Origin[0] +
this->Spacing[0] *
coords.GetOrigin()[0] +
coords.GetSpacing()[0] *
(static_cast<vtkm::FloatDefault>(ijk0[0]) +
static_cast<vtkm::FloatDefault>(t) * static_cast<vtkm::FloatDefault>(ijk1[0] - ijk0[0])),
this->Origin[1] +
this->Spacing[1] *
coords.GetOrigin()[1] +
coords.GetSpacing()[1] *
(static_cast<vtkm::FloatDefault>(ijk0[1]) +
static_cast<vtkm::FloatDefault>(t) * static_cast<vtkm::FloatDefault>(ijk1[1] - ijk0[1])),
this->Origin[2] +
this->Spacing[2] *
coords.GetOrigin()[2] +
coords.GetSpacing()[2] *
(static_cast<vtkm::FloatDefault>(ijk0[2]) +
static_cast<vtkm::FloatDefault>(t) *
static_cast<vtkm::FloatDefault>(ijk1[2] - ijk0[2])));
}
// Interpolation for explicit coordinates
//----------------------------------------------------------------------------
template <typename CoordsPortal>
inline VTKM_EXEC vtkm::Vec3f InterpolateCoordinate(CoordsPortal coords,
T t,
const vtkm::Id3& ijk0,
const vtkm::Id3& ijk1) const
{
return (1.0f - static_cast<vtkm::FloatDefault>(t)) *
coords.Get(ijk0[0] + this->PointDims[0] * ijk0[1] +
this->PointDims[0] * this->PointDims[1] * ijk0[2]) +
static_cast<vtkm::FloatDefault>(t) *
coords.Get(ijk1[0] + this->PointDims[0] * ijk1[1] +
this->PointDims[0] * this->PointDims[1] * ijk1[2]);
}
};
}
}

@ -31,9 +31,6 @@ struct ComputePass4XWithNormals : public vtkm::worklet::WorkletVisitCellsWithPoi
{
vtkm::Id3 PointDims;
vtkm::Vec3f Origin;
vtkm::Vec3f Spacing;
T IsoValue;
vtkm::Id CellWriteOffset;
@ -42,13 +39,9 @@ struct ComputePass4XWithNormals : public vtkm::worklet::WorkletVisitCellsWithPoi
ComputePass4XWithNormals() {}
ComputePass4XWithNormals(T value,
const vtkm::Id3& pdims,
const vtkm::Vec3f& origin,
const vtkm::Vec3f& spacing,
vtkm::Id multiContourCellOffset,
vtkm::Id multiContourPointOffset)
: PointDims(pdims)
, Origin(origin)
, Spacing(spacing)
, IsoValue(value)
, CellWriteOffset(multiContourCellOffset)
, PointWriteOffset(multiContourPointOffset)
@ -61,6 +54,7 @@ struct ComputePass4XWithNormals : public vtkm::worklet::WorkletVisitCellsWithPoi
FieldInPoint axis_maxs,
WholeArrayIn cell_tri_count,
WholeArrayIn edgeData,
WholeArrayIn coords,
WholeArrayIn data,
WholeArrayOut connectivity,
WholeArrayOut edgeIds,
@ -69,13 +63,14 @@ struct ComputePass4XWithNormals : public vtkm::worklet::WorkletVisitCellsWithPoi
WholeArrayOut points,
WholeArrayOut normals);
using ExecutionSignature =
void(ThreadIndices, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, WorkIndex);
void(ThreadIndices, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, WorkIndex);
template <typename ThreadIndices,
typename FieldInPointId3,
typename FieldInPointId,
typename WholeTriField,
typename WholeEdgeField,
typename WholeCoordsField,
typename WholeDataField,
typename WholeConnField,
typename WholeEdgeIdField,
@ -89,6 +84,7 @@ struct ComputePass4XWithNormals : public vtkm::worklet::WorkletVisitCellsWithPoi
const FieldInPointId& axis_maxs,
const WholeTriField& cellTriCount,
const WholeEdgeField& edges,
const WholeCoordsField& coords,
const WholeDataField& field,
const WholeConnField& conn,
const WholeEdgeIdField& interpolatedEdgeIds,
@ -144,6 +140,7 @@ struct ComputePass4XWithNormals : public vtkm::worklet::WorkletVisitCellsWithPoi
field,
interpolatedEdgeIds,
weights,
coords,
points,
normals,
state.startPos,
@ -162,6 +159,7 @@ struct ComputePass4XWithNormals : public vtkm::worklet::WorkletVisitCellsWithPoi
template <typename WholeDataField,
typename WholeIEdgeField,
typename WholeWeightField,
typename WholeCoordsField,
typename WholePointField,
typename WholeNormalField>
VTKM_EXEC inline void Generate(const vtkm::Vec<vtkm::UInt8, 3>& boundaryStatus,
@ -169,6 +167,7 @@ struct ComputePass4XWithNormals : public vtkm::worklet::WorkletVisitCellsWithPoi
const WholeDataField& field,
const WholeIEdgeField& interpolatedEdgeIds,
const WholeWeightField& weights,
const WholeCoordsField coords,
const WholePointField& points,
const WholeNormalField& normals,
const vtkm::Id4& startPos,
@ -197,7 +196,7 @@ struct ComputePass4XWithNormals : public vtkm::worklet::WorkletVisitCellsWithPoi
weights.Set(writeIndex, static_cast<vtkm::FloatDefault>(t));
auto ijk1 = ijk + vtkm::Id3{ 1, 0, 0 };
auto coord = this->InterpolateCoordinate(t, ijk, ijk1);
auto coord = this->InterpolateCoordinate(coords, t, ijk, ijk1);
points.Set(writeIndex, coord);
//gradient generation
@ -216,7 +215,7 @@ struct ComputePass4XWithNormals : public vtkm::worklet::WorkletVisitCellsWithPoi
weights.Set(writeIndex, static_cast<vtkm::FloatDefault>(t));
auto ijk1 = ijk + vtkm::Id3{ 0, 1, 0 };
auto coord = this->InterpolateCoordinate(t, ijk, ijk1);
auto coord = this->InterpolateCoordinate(coords, t, ijk, ijk1);
points.Set(writeIndex, coord);
//gradient generation
@ -235,7 +234,7 @@ struct ComputePass4XWithNormals : public vtkm::worklet::WorkletVisitCellsWithPoi
weights.Set(writeIndex, static_cast<vtkm::FloatDefault>(t));
auto ijk1 = ijk + vtkm::Id3{ 0, 0, 1 };
auto coord = this->InterpolateCoordinate(t, ijk, ijk1);
auto coord = this->InterpolateCoordinate(coords, t, ijk, ijk1);
points.Set(writeIndex, coord);
//gradient generation
@ -258,38 +257,38 @@ struct ComputePass4XWithNormals : public vtkm::worklet::WorkletVisitCellsWithPoi
if (onX) //+x boundary
{
this->InterpolateEdge(
fullyInterior, ijk, pos[0], incs, 5, edgeUses, edgeIds, field, interpolatedEdgeIds, weights, points, normals);
fullyInterior, ijk, pos[0], incs, 5, edgeUses, edgeIds, field, interpolatedEdgeIds, weights, coords, points, normals);
this->InterpolateEdge(
fullyInterior, ijk, pos[0], incs, 9, edgeUses, edgeIds, field, interpolatedEdgeIds, weights, points, normals);
fullyInterior, ijk, pos[0], incs, 9, edgeUses, edgeIds, field, interpolatedEdgeIds, weights, coords, points, normals);
if (onY) //+x +y
{
this->InterpolateEdge(
fullyInterior, ijk, pos[0], incs, 11, edgeUses, edgeIds, field, interpolatedEdgeIds, weights, points, normals);
fullyInterior, ijk, pos[0], incs, 11, edgeUses, edgeIds, field, interpolatedEdgeIds, weights, coords, points, normals);
}
if (onZ) //+x +z
{
this->InterpolateEdge(
fullyInterior, ijk, pos[0], incs, 7, edgeUses, edgeIds, field, interpolatedEdgeIds, weights, points, normals);
fullyInterior, ijk, pos[0], incs, 7, edgeUses, edgeIds, field, interpolatedEdgeIds, weights, coords, points, normals);
}
}
if (onY) //+y boundary
{
this->InterpolateEdge(
fullyInterior, ijk, pos[0], incs, 1, edgeUses, edgeIds, field, interpolatedEdgeIds, weights, points, normals);
fullyInterior, ijk, pos[0], incs, 1, edgeUses, edgeIds, field, interpolatedEdgeIds, weights, coords, points, normals);
this->InterpolateEdge(
fullyInterior, ijk, pos[0], incs, 10, edgeUses, edgeIds, field, interpolatedEdgeIds, weights, points, normals);
fullyInterior, ijk, pos[0], incs, 10, edgeUses, edgeIds, field, interpolatedEdgeIds, weights, coords, points, normals);
if (onZ) //+y +z boundary
{
this->InterpolateEdge(
fullyInterior, ijk, pos[0], incs, 3, edgeUses, edgeIds, field, interpolatedEdgeIds, weights, points, normals);
fullyInterior, ijk, pos[0], incs, 3, edgeUses, edgeIds, field, interpolatedEdgeIds, weights, coords, points, normals);
}
}
if (onZ) //+z boundary
{
this->InterpolateEdge(
fullyInterior, ijk, pos[0], incs, 2, edgeUses, edgeIds, field, interpolatedEdgeIds, weights, points, normals);
fullyInterior, ijk, pos[0], incs, 2, edgeUses, edgeIds, field, interpolatedEdgeIds, weights, coords, points, normals);
this->InterpolateEdge(
fullyInterior, ijk, pos[0], incs, 6, edgeUses, edgeIds, field, interpolatedEdgeIds, weights, points, normals);
fullyInterior, ijk, pos[0], incs, 6, edgeUses, edgeIds, field, interpolatedEdgeIds, weights, coords, points, normals);
}
// clang-format on
}
@ -300,6 +299,7 @@ struct ComputePass4XWithNormals : public vtkm::worklet::WorkletVisitCellsWithPoi
typename WholeIEdgeField,
typename WholeWeightField,
typename WholePointField,
typename WholeCoordsField,
typename WholeNormalField>
VTKM_EXEC inline void InterpolateEdge(bool fullyInterior,
const vtkm::Id3& ijk,
@ -311,6 +311,7 @@ struct ComputePass4XWithNormals : public vtkm::worklet::WorkletVisitCellsWithPoi
const WholeField& field,
const WholeIEdgeField& interpolatedEdgeIds,
const WholeWeightField& weights,
const WholeCoordsField& coords,
const WholePointField& points,
const WholeNormalField& normals) const
{
@ -338,36 +339,55 @@ struct ComputePass4XWithNormals : public vtkm::worklet::WorkletVisitCellsWithPoi
T t = static_cast<T>((this->IsoValue - s0) / (s1 - s0));
weights.Set(writeIndex, static_cast<vtkm::FloatDefault>(t));
auto coord = this->InterpolateCoordinate(t, ijk + offsets1, ijk + offsets2);
auto coord = this->InterpolateCoordinate(coords, t, ijk + offsets1, ijk + offsets2);
points.Set(writeIndex, coord);
auto g0 = this->ComputeGradient(fullyInterior, ijk + offsets1, incs, iEdge[0], field);
auto g1 = this->ComputeGradient(fullyInterior, ijk + offsets2, incs, iEdge[1], field);
auto g0 = this->ComputeGradient(fullyInterior, ijk + offsets1, incs, iEdge[0], field);
g1 = g0 + (t * (g1 - g0));
normals.Set(writeIndex, vtkm::Normal(g1));
}
// Fast interpolation method for uniform coordinates
//----------------------------------------------------------------------------
inline VTKM_EXEC vtkm::Vec3f InterpolateCoordinate(T t,
const vtkm::Id3& ijk0,
const vtkm::Id3& ijk1) const
inline VTKM_EXEC vtkm::Vec3f InterpolateCoordinate(
const vtkm::internal::ArrayPortalUniformPointCoordinates& coords,
T t,
const vtkm::Id3& ijk0,
const vtkm::Id3& ijk1) const
{
return vtkm::Vec3f(
this->Origin[0] +
this->Spacing[0] *
coords.GetOrigin()[0] +
coords.GetSpacing()[0] *
(static_cast<vtkm::FloatDefault>(ijk0[0]) +
static_cast<vtkm::FloatDefault>(t) * static_cast<vtkm::FloatDefault>(ijk1[0] - ijk0[0])),
this->Origin[1] +
this->Spacing[1] *
coords.GetOrigin()[1] +
coords.GetSpacing()[1] *
(static_cast<vtkm::FloatDefault>(ijk0[1]) +
static_cast<vtkm::FloatDefault>(t) * static_cast<vtkm::FloatDefault>(ijk1[1] - ijk0[1])),
this->Origin[2] +
this->Spacing[2] *
coords.GetOrigin()[2] +
coords.GetSpacing()[2] *
(static_cast<vtkm::FloatDefault>(ijk0[2]) +
static_cast<vtkm::FloatDefault>(t) *
static_cast<vtkm::FloatDefault>(ijk1[2] - ijk0[2])));
}
// Interpolation for explicit coordinates
//----------------------------------------------------------------------------
template <typename CoordsPortal>
inline VTKM_EXEC vtkm::Vec3f InterpolateCoordinate(const CoordsPortal& coords,
T t,
const vtkm::Id3& ijk0,
const vtkm::Id3& ijk1) const
{
return (1.0f - static_cast<vtkm::FloatDefault>(t)) *
coords.Get(ijk0[0] + this->PointDims[0] * ijk0[1] +
this->PointDims[0] * this->PointDims[1] * ijk0[2]) +
static_cast<vtkm::FloatDefault>(t) *
coords.Get(ijk1[0] + this->PointDims[0] * ijk1[1] +
this->PointDims[0] * this->PointDims[1] * ijk1[2]);
}
//----------------------------------------------------------------------------
template <typename WholeDataField>
VTKM_EXEC vtkm::Vec3f ComputeGradient(bool fullyInterior,

@ -276,17 +276,11 @@ struct ComputePass4Y : public vtkm::worklet::WorkletVisitCellsWithPoints
template <typename T>
struct ComputePass5Y : public vtkm::worklet::WorkletMapField
{
vtkm::internal::ArrayPortalUniformPointCoordinates Coordinates;
vtkm::Id3 PointDims;
vtkm::Id NormalWriteOffset;
ComputePass5Y() {}
ComputePass5Y(const vtkm::Id3& pdims,
const vtkm::Vec3f& origin,
const vtkm::Vec3f& spacing,
vtkm::Id normalWriteOffset,
bool generateNormals)
: Coordinates(pdims, origin, spacing)
ComputePass5Y(const vtkm::Id3& pdims, vtkm::Id normalWriteOffset, bool generateNormals)
: PointDims(pdims)
, NormalWriteOffset(normalWriteOffset)
{
if (!generateNormals)
@ -299,20 +293,25 @@ struct ComputePass5Y : public vtkm::worklet::WorkletMapField
FieldIn interpWeight,
FieldOut points,
WholeArrayIn field,
WholeArrayIn coords,
WholeArrayOut normals);
using ExecutionSignature = void(_1, _2, _3, _4, _5, WorkIndex);
using ExecutionSignature = void(_1, _2, _3, _4, _5, _6, WorkIndex);
template <typename PT, typename WholeInputField, typename WholeNormalField>
template <typename PT,
typename WholeInputField,
typename WholeNormalField,
typename WholeCoordsField>
VTKM_EXEC void operator()(const vtkm::Id2& interpEdgeIds,
vtkm::FloatDefault weight,
vtkm::Vec<PT, 3>& outPoint,
const WholeInputField& field,
const WholeCoordsField& coords,
WholeNormalField& normals,
vtkm::Id oidx) const
{
{
vtkm::Vec3f point1 = this->Coordinates.Get(interpEdgeIds[0]);
vtkm::Vec3f point2 = this->Coordinates.Get(interpEdgeIds[1]);
vtkm::Vec3f point1 = coords.Get(interpEdgeIds[0]);
vtkm::Vec3f point2 = coords.Get(interpEdgeIds[1]);
outPoint = vtkm::Lerp(point1, point2, weight);
}
@ -320,15 +319,13 @@ struct ComputePass5Y : public vtkm::worklet::WorkletMapField
if (this->NormalWriteOffset >= 0)
{
vtkm::Vec<T, 3> g0, g1;
const vtkm::Id3& dims = this->Coordinates.GetDimensions();
vtkm::Id3 ijk{ interpEdgeIds[0] % dims[0],
(interpEdgeIds[0] / dims[0]) % dims[1],
interpEdgeIds[0] / (dims[0] * dims[1]) };
vtkm::Id3 ijk{ interpEdgeIds[0] % this->PointDims[0],
(interpEdgeIds[0] / this->PointDims[0]) % this->PointDims[1],
interpEdgeIds[0] / (this->PointDims[0] * this->PointDims[1]) };
vtkm::worklet::gradient::StructuredPointGradient gradient;
vtkm::exec::BoundaryState boundary(ijk, dims);
vtkm::exec::FieldNeighborhood<vtkm::internal::ArrayPortalUniformPointCoordinates>
coord_neighborhood(this->Coordinates, boundary);
vtkm::exec::BoundaryState boundary(ijk, this->PointDims);
vtkm::exec::FieldNeighborhood<WholeCoordsField> coord_neighborhood(coords, boundary);
vtkm::exec::FieldNeighborhood<WholeInputField> field_neighborhood(field, boundary);
@ -337,9 +334,9 @@ struct ComputePass5Y : public vtkm::worklet::WorkletMapField
gradient(boundary, coord_neighborhood, field_neighborhood, g0);
//compute the gradient at point 2. This optimization can be optimized
boundary.IJK = vtkm::Id3{ interpEdgeIds[1] % dims[0],
(interpEdgeIds[1] / dims[0]) % dims[1],
interpEdgeIds[1] / (dims[0] * dims[1]) };
boundary.IJK = vtkm::Id3{ interpEdgeIds[1] % this->PointDims[0],
(interpEdgeIds[1] / this->PointDims[0]) % this->PointDims[1],
interpEdgeIds[1] / (this->PointDims[0] * this->PointDims[1]) };
gradient(boundary, coord_neighborhood, field_neighborhood, g1);
vtkm::Vec3f n = vtkm::Lerp(g0, g1, weight);

@ -7,94 +7,119 @@
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#include <vtkm/cont/ArrayCopy.h>
#include <vtkm/cont/ArrayHandleCompositeVector.h>
#include <vtkm/cont/ErrorFilterExecution.h>
#include <vtkm/filter/field_transform/CompositeVectors.h>
#include <vtkm/cont/ArrayCopy.h>
#include <vtkm/cont/ArrayHandleRuntimeVec.h>
#include <vtkm/cont/ErrorFilterExecution.h>
#include <vtkm/cont/UnknownArrayHandle.h>
#include <vtkm/List.h>
#include <vtkm/TypeList.h>
namespace
{
// Extracts a component from an UnknownArrayHandle and returns the extracted component
// as an UnknownArrayHandle. Perhaps this functionality should be part of UnknownArrayHandle
// proper, but its use is probably rare. Note that this implementation makes some assumptions
// on its use in the CompositeVectors filter.
VTKM_CONT vtkm::cont::UnknownArrayHandle ExtractComponent(
const vtkm::cont::UnknownArrayHandle& array,
vtkm::IdComponent componentIndex)
{
vtkm::cont::UnknownArrayHandle extractedComponentArray;
auto resolveType = [&](auto componentExample) {
using ComponentType = decltype(componentExample);
if (array.IsBaseComponentType<ComponentType>())
{
extractedComponentArray =
array.ExtractComponent<ComponentType>(componentIndex, vtkm::CopyFlag::Off);
}
};
vtkm::ListForEach(resolveType, vtkm::TypeListBaseC{});
return extractedComponentArray;
}
} // anonymous namespace
namespace vtkm
{
namespace filter
{
namespace field_transform
{
VTKM_CONT void CompositeVectors::SetFieldNameList(const std::vector<std::string>& fieldNameList,
vtkm::cont::Field::Association association)
{
vtkm::IdComponent index = 0;
for (auto& fieldName : fieldNameList)
{
this->SetActiveField(index, fieldName, association);
++index;
}
}
VTKM_CONT vtkm::IdComponent CompositeVectors::GetNumberOfFields() const
{
return this->GetNumberOfActiveFields();
}
VTKM_CONT vtkm::cont::DataSet CompositeVectors::DoExecute(const vtkm::cont::DataSet& inDataSet)
{
vtkm::IdComponent numComponents = this->GetNumberOfFields();
if (numComponents < 1)
{
throw vtkm::cont::ErrorBadValue(
"No input fields to combine into a vector for CompositeVectors.");
}
vtkm::cont::UnknownArrayHandle outArray;
if (this->NumberOfFields < 2)
{
throw vtkm::cont::ErrorFilterExecution("FieldNameList is supposed to be larger than 2.");
}
else if (this->NumberOfFields == 2)
{
auto fieldAssociation = this->GetFieldFromDataSet(0, inDataSet).GetAssociation();
if (fieldAssociation != this->GetFieldFromDataSet(1, inDataSet).GetAssociation())
// Allocate output array to the correct type.
vtkm::cont::Field firstField = this->GetFieldFromDataSet(0, inDataSet);
vtkm::Id numValues = firstField.GetNumberOfValues();
vtkm::cont::Field::Association association = firstField.GetAssociation();
auto allocateOutput = [&](auto exampleComponent) {
using ComponentType = decltype(exampleComponent);
if (firstField.GetData().IsBaseComponentType<ComponentType>())
{
throw vtkm::cont::ErrorFilterExecution("Field 0 and Field 2 have different associations.");
outArray = vtkm::cont::ArrayHandleRuntimeVec<ComponentType>{ numComponents };
}
auto resolveType2d = [&](const auto& field0) {
using T = typename std::decay_t<decltype(field0)>::ValueType;
vtkm::cont::ArrayHandle<T> field1;
vtkm::cont::ArrayCopyShallowIfPossible(this->GetFieldFromDataSet(1, inDataSet).GetData(),
field1);
auto compositedArray = vtkm::cont::make_ArrayHandleCompositeVector(field0, field1);
using VecType = vtkm::Vec<T, 2>;
using ArrayHandleType = vtkm::cont::ArrayHandle<VecType>;
ArrayHandleType result;
vtkm::cont::ArrayCopy(compositedArray, result);
outArray = result;
};
const auto& inField0 = this->GetFieldFromDataSet(0, inDataSet);
inField0.GetData().CastAndCallForTypes<vtkm::TypeListScalarAll, VTKM_DEFAULT_STORAGE_LIST>(
resolveType2d);
}
else if (this->NumberOfFields == 3)
};
vtkm::ListForEach(allocateOutput, vtkm::TypeListBaseC{});
if (!outArray.IsValid() || (outArray.GetNumberOfComponentsFlat() != numComponents))
{
auto fieldAssociation0 = this->GetFieldFromDataSet(0, inDataSet).GetAssociation();
auto fieldAssociation1 = this->GetFieldFromDataSet(1, inDataSet).GetAssociation();
auto fieldAssociation2 = this->GetFieldFromDataSet(2, inDataSet).GetAssociation();
throw vtkm::cont::ErrorBadType("Unable to allocate output array due to unexpected type.");
}
outArray.Allocate(numValues);
if (fieldAssociation0 != fieldAssociation1 || fieldAssociation1 != fieldAssociation2 ||
fieldAssociation0 != fieldAssociation2)
// Iterate over all component fields and copy them into the output array.
for (vtkm::IdComponent componentIndex = 0; componentIndex < numComponents; ++componentIndex)
{
vtkm::cont::Field inScalarField = this->GetFieldFromDataSet(componentIndex, inDataSet);
if (inScalarField.GetData().GetNumberOfComponentsFlat() != 1)
{
throw vtkm::cont::ErrorFilterExecution(
"Field 0, Field 1 and Field 2 have different associations.");
throw vtkm::cont::ErrorBadValue("All input fields to CompositeVectors must be scalars.");
}
if (inScalarField.GetAssociation() != association)
{
throw vtkm::cont::ErrorBadValue(
"All scalar fields must have the same association (point, cell, etc.).");
}
if (inScalarField.GetNumberOfValues() != numValues)
{
throw vtkm::cont::ErrorBadValue("Inconsistent number of field values.");
}
auto resolveType3d = [&](const auto& field0) {
using T = typename std::decay_t<decltype(field0)>::ValueType;
vtkm::cont::ArrayHandle<T> field1;
vtkm::cont::ArrayCopyShallowIfPossible(this->GetFieldFromDataSet(1, inDataSet).GetData(),
field1);
vtkm::cont::ArrayHandle<T> field2;
vtkm::cont::ArrayCopyShallowIfPossible(this->GetFieldFromDataSet(2, inDataSet).GetData(),
field2);
auto compositedArray = vtkm::cont::make_ArrayHandleCompositeVector(field0, field1, field2);
using VecType = vtkm::Vec<T, 3>;
using ArrayHandleType = vtkm::cont::ArrayHandle<VecType>;
ArrayHandleType result;
// ArrayHandleCompositeVector currently does not implement the ability to
// get to values on the control side, so copy to an array that is accessible.
vtkm::cont::ArrayCopy(compositedArray, result);
outArray = result;
};
const auto& inField0 = this->GetFieldFromDataSet(0, inDataSet);
inField0.GetData().CastAndCallForTypes<vtkm::TypeListScalarAll, VTKM_DEFAULT_STORAGE_LIST>(
resolveType3d);
}
else
{
throw vtkm::cont::ErrorFilterExecution(
"Using make_ArrayHandleCompositeVector to composite vectors more than 3.");
ExtractComponent(outArray, componentIndex).DeepCopyFrom(inScalarField.GetData());
}
return this->CreateResultField(
inDataSet, this->GetOutputFieldName(), this->GetActiveFieldAssociation(), outArray);
return this->CreateResultField(inDataSet, this->GetOutputFieldName(), association, outArray);
}
} // namespace field_transform
} // namespace vtkm::filter
} // namespace vtkm

@ -20,8 +20,15 @@ namespace filter
namespace field_transform
{
/// \brief The composite vector filter combines multiple scalar fields into a single vector field.
/// Scalar fields are selected as the active input fields, and the combined vector field is set at the output.
/// \brief Combine multiple scalar fields into a single vector field.
///
/// Scalar fields are selected as the active input fields, and the combined vector
/// field is set at the output. The `SetFieldNameList` method takes a `std::vector`
/// of field names to use as the component fields. Alternately, the superclass'
/// set active field methods can be used to select the fields independently.
///
/// All of the input fields must be scalar values. The type of the first field
/// determines the type of the output vector field.
///
class VTKM_FILTER_FIELD_TRANSFORM_EXPORT CompositeVectors : public vtkm::filter::FilterField
{
@ -33,24 +40,12 @@ public:
VTKM_CONT
void SetFieldNameList(
const std::vector<std::string>& fieldNameList,
vtkm::cont::Field::Association association = vtkm::cont::Field::Association::Any)
{
vtkm::cont::Field::Association association = vtkm::cont::Field::Association::Any);
vtkm::IdComponent index = 0;
for (auto& fieldName : fieldNameList)
{
this->SetActiveField(index, fieldName, association);
++index;
}
this->NumberOfFields = static_cast<vtkm::IdComponent>(fieldNameList.size());
}
VTKM_CONT
vtkm::IdComponent GetNumberOfFields() { return this->NumberOfFields; }
VTKM_CONT vtkm::IdComponent GetNumberOfFields() const;
private:
vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& input) override;
vtkm::IdComponent NumberOfFields;
};
} // namespace field_transform
} // namespace vtkm::filter

@ -20,19 +20,19 @@ vtkm::cont::DataSet MakeDataSet(vtkm::IdComponent numArrays)
vtkm::IdComponent arrayLen = 100;
for (vtkm::IdComponent i = 0; i < numArrays; ++i)
for (vtkm::IdComponent fieldIndex = 0; fieldIndex < numArrays; ++fieldIndex)
{
std::vector<ScalarType> pointarray;
std::vector<ScalarType> cellarray;
for (vtkm::IdComponent j = 0; j < arrayLen; ++j)
for (vtkm::Id valueIndex = 0; valueIndex < arrayLen; ++valueIndex)
{
pointarray.push_back(static_cast<ScalarType>(i * 1.1 + j * 1.1));
cellarray.push_back(static_cast<ScalarType>(i * 2.1 + j * 2.1));
pointarray.push_back(static_cast<ScalarType>(fieldIndex * 1.1 + valueIndex * 1.1));
cellarray.push_back(static_cast<ScalarType>(fieldIndex * 2.1 + valueIndex * 2.1));
}
dataSet.AddPointField("pointArray" + std::to_string(i), pointarray);
dataSet.AddCellField("cellArray" + std::to_string(i), cellarray);
dataSet.AddPointField("pointArray" + std::to_string(fieldIndex), pointarray);
dataSet.AddCellField("cellArray" + std::to_string(fieldIndex), cellarray);
}
return dataSet;
@ -44,7 +44,7 @@ void CheckResults(vtkm::cont::DataSet inDataSet,
const std::string compositedName)
{
//there are only three fields for this testing , it is ok to use vtkm::IdComponent
vtkm::IdComponent dims = static_cast<vtkm::IdComponent>(FieldNames.size());
vtkm::IdComponent numComponents = static_cast<vtkm::IdComponent>(FieldNames.size());
auto compositedField = inDataSet.GetField(compositedName);
vtkm::IdComponent compositedFieldLen =
static_cast<vtkm::IdComponent>(compositedField.GetNumberOfValues());
@ -55,9 +55,9 @@ void CheckResults(vtkm::cont::DataSet inDataSet,
auto compFieldReadPortal = compFieldArrayCopy.ReadPortal();
for (vtkm::IdComponent i = 0; i < dims; i++)
for (vtkm::IdComponent componentIndex = 0; componentIndex < numComponents; componentIndex++)
{
auto field = inDataSet.GetField(FieldNames[i]);
auto field = inDataSet.GetField(FieldNames[componentIndex]);
VTKM_TEST_ASSERT(compositedField.GetAssociation() == field.GetAssociation(),
"Got bad association value.");
@ -68,11 +68,11 @@ void CheckResults(vtkm::cont::DataSet inDataSet,
field.GetData().AsArrayHandle(fieldArrayHandle);
auto fieldReadPortal = fieldArrayHandle.ReadPortal();
for (vtkm::IdComponent j = 0; j < fieldLen; j++)
for (vtkm::Id valueIndex = 0; valueIndex < fieldLen; valueIndex++)
{
auto compFieldVec = compFieldReadPortal.Get(j);
auto comFieldValue = compFieldVec[static_cast<vtkm::UInt64>(i)];
auto fieldValue = fieldReadPortal.Get(j);
auto compFieldVec = compFieldReadPortal.Get(valueIndex);
auto comFieldValue = compFieldVec[static_cast<vtkm::UInt64>(componentIndex)];
auto fieldValue = fieldReadPortal.Get(valueIndex);
VTKM_TEST_ASSERT(comFieldValue == fieldValue, "Got bad field value.");
}
}
@ -80,27 +80,30 @@ void CheckResults(vtkm::cont::DataSet inDataSet,
template <typename ScalarType, typename VecType>
void TestCompositeVectors(vtkm::IdComponent dim)
void TestCompositeVectors(vtkm::IdComponent numComponents)
{
vtkm::cont::DataSet inDataSet = MakeDataSet<ScalarType>(dim);
vtkm::cont::DataSet inDataSet = MakeDataSet<ScalarType>(numComponents);
vtkm::filter::field_transform::CompositeVectors filter;
// For the first pass (point field), we are going to use the generic `SetActiveField` method
// and let the filter figure out how many fields.
std::vector<std::string> pointFieldNames;
for (vtkm::IdComponent i = 0; i < dim; i++)
for (vtkm::IdComponent componentIndex = 0; componentIndex < numComponents; componentIndex++)
{
pointFieldNames.push_back("pointArray" + std::to_string(i));
pointFieldNames.push_back("pointArray" + std::to_string(componentIndex));
filter.SetActiveField(componentIndex, "pointArray" + std::to_string(componentIndex));
}
filter.SetFieldNameList(pointFieldNames, vtkm::cont::Field::Association::Points);
filter.SetOutputFieldName("CompositedFieldPoint");
vtkm::cont::DataSet outDataSetPointAssoci = filter.Execute(inDataSet);
CheckResults<ScalarType, VecType>(
outDataSetPointAssoci, pointFieldNames, filter.GetOutputFieldName());
// For the second pass (cell field), we will use the `SetFieldNameList` method.
std::vector<std::string> cellFieldNames;
for (vtkm::IdComponent i = 0; i < dim; i++)
for (vtkm::IdComponent componentIndex = 0; componentIndex < numComponents; componentIndex++)
{
cellFieldNames.push_back("cellArray" + std::to_string(i));
cellFieldNames.push_back("cellArray" + std::to_string(componentIndex));
}
filter.SetFieldNameList(cellFieldNames, vtkm::cont::Field::Association::Cells);
filter.SetOutputFieldName("CompositedFieldCell");
@ -114,8 +117,10 @@ void CompositeVectors()
{
TestCompositeVectors<vtkm::FloatDefault, vtkm::Vec2f>(2);
TestCompositeVectors<vtkm::FloatDefault, vtkm::Vec3f>(3);
TestCompositeVectors<vtkm::FloatDefault, vtkm::Vec<vtkm::FloatDefault, 5>>(5);
TestCompositeVectors<vtkm::Id, vtkm::Vec2i>(2);
TestCompositeVectors<vtkm::Id, vtkm::Vec3i>(3);
TestCompositeVectors<vtkm::Id, vtkm::Vec<vtkm::Id, 5>>(5);
}
} // anonymous namespace

@ -467,8 +467,12 @@ void HierarchicalAugmenter<FieldType>::RetrieveInAttachmentPoints()
template <typename FieldType>
void HierarchicalAugmenter<FieldType>::ReleaseSwapArrays()
{ // ReleaseSwapArrays()
this->OutData.ReleaseResources();
this->InData.ReleaseResources();
// Rather than explicitly delete the arrays, we are going to "forget" them and
// just release our reference count on them. If no one else is using them, the
// memory will actually be deleted. But if an array is being used, it will
// continue to be managed until it is not.
this->OutData = decltype(this->OutData){};
this->InData = decltype(this->InData){};
} // ReleaseSwapArrays()

@ -127,7 +127,10 @@ public:
blockData->HierarchicalAugmenter.PrepareOutAttachmentPoints(round);
// TODO/FIXME: Correct function? Correct round?
rp.enqueue(target, blockData->HierarchicalAugmenter.OutData);
// TODO/FIXME: Is it save to already release HierarchicalAugmenter.OutData (and InData) here. Don't we free the arrays before the other block had the chance to complete its rp.dequeue?
// Note: HierarchicalAugmenter.ReleaseSwapArrays() does not necessarily delete the
// arrays. Rather, it releases the reference to them. If, for example, the data
// for HierarchicalAugmenter.OutData is still in flight, the data will continue to
// exist until it is sent.
blockData->HierarchicalAugmenter.ReleaseSwapArrays();
}
}

@ -101,34 +101,13 @@ public:
}
/// Destructor
~HierarchicalAugmenterInOutData();
/// Clear all arrays
void ReleaseResources();
~HierarchicalAugmenterInOutData() = default;
/// Print contents fo this objects
std::string DebugPrint(std::string message, const char* fileName, long lineNum);
}; // class HierarchicalAugmenterInOutData
template <typename FieldType>
HierarchicalAugmenterInOutData<FieldType>::~HierarchicalAugmenterInOutData()
{
this->ReleaseResources();
}
// routine to release memory used for out arrays
template <typename FieldType>
void HierarchicalAugmenterInOutData<FieldType>::ReleaseResources()
{ // ReleaseResources()
this->GlobalRegularIds.ReleaseResources();
this->DataValues.ReleaseResources();
this->SupernodeIds.ReleaseResources();
this->Superparents.ReleaseResources();
this->SuperparentRounds.ReleaseResources();
this->WhichRounds.ReleaseResources();
} // ReleaseResources()
template <typename FieldType>
std::string HierarchicalAugmenterInOutData<FieldType>::DebugPrint(std::string message,
const char* fileName,

@ -78,11 +78,9 @@ VTKM_CONT DotProduct::DotProduct()
VTKM_CONT vtkm::cont::DataSet DotProduct::DoExecute(const vtkm::cont::DataSet& inDataSet)
{
vtkm::cont::Field primaryField = this->GetFieldFromDataSet(0, inDataSet);
vtkm::cont::UnknownArrayHandle primaryArray = primaryField.GetData();
vtkm::cont::Field secondaryField = this->GetFieldFromDataSet(1, inDataSet);
if (primaryArray.GetNumberOfComponentsFlat() !=
if (primaryField.GetData().GetNumberOfComponentsFlat() !=
secondaryField.GetData().GetNumberOfComponentsFlat())
{
throw vtkm::cont::ErrorFilterExecution(
@ -91,22 +89,10 @@ VTKM_CONT vtkm::cont::DataSet DotProduct::DoExecute(const vtkm::cont::DataSet& i
vtkm::cont::UnknownArrayHandle outArray;
if (primaryArray.IsBaseComponentType<vtkm::Float32>())
{
outArray =
DoDotProduct(primaryArray.ExtractArrayFromComponents<vtkm::Float32>(), secondaryField);
}
else if (primaryArray.IsBaseComponentType<vtkm::Float64>())
{
outArray =
DoDotProduct(primaryArray.ExtractArrayFromComponents<vtkm::Float64>(), secondaryField);
}
else
{
primaryArray = primaryField.GetDataAsDefaultFloat();
outArray =
DoDotProduct(primaryArray.ExtractArrayFromComponents<vtkm::FloatDefault>(), secondaryField);
}
auto resolveArray = [&](const auto& concretePrimaryField) {
outArray = DoDotProduct(concretePrimaryField, secondaryField);
};
this->CastAndCallVariableVecField(primaryField, resolveArray);
return this->CreateResultField(inDataSet,
this->GetOutputFieldName(),

@ -14,6 +14,7 @@
#include <vtkm/cont/ArrayCopy.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ArrayHandleOffsetsToNumComponents.h>
#include <vtkm/cont/ArrayHandleRuntimeVec.h>
#include <vtkm/cont/ArrayPortalToIterators.h>
#include <vtkm/cont/Logging.h>
#include <vtkm/cont/UnknownArrayHandle.h>
@ -35,162 +36,6 @@ inline void PrintVTKDataFileSummary(const vtkm::io::internal::VTKDataSetFile& df
<< std::endl;
}
// Since Fields and DataSets store data in the default UnknownArrayHandle, convert
// the data to the closest type supported by default. The following will
// need to be updated if UnknownArrayHandle or TypeListCommon changes.
template <typename T>
struct ClosestCommonType
{
using Type = T;
};
template <>
struct ClosestCommonType<vtkm::Int8>
{
using Type = vtkm::Int32;
};
template <>
struct ClosestCommonType<vtkm::UInt8>
{
using Type = vtkm::Int32;
};
template <>
struct ClosestCommonType<vtkm::Int16>
{
using Type = vtkm::Int32;
};
template <>
struct ClosestCommonType<vtkm::UInt16>
{
using Type = vtkm::Int32;
};
template <>
struct ClosestCommonType<vtkm::UInt32>
{
using Type = vtkm::Int64;
};
template <>
struct ClosestCommonType<vtkm::UInt64>
{
using Type = vtkm::Int64;
};
template <typename T>
struct ClosestFloat
{
using Type = T;
};
template <>
struct ClosestFloat<vtkm::Int8>
{
using Type = vtkm::Float32;
};
template <>
struct ClosestFloat<vtkm::UInt8>
{
using Type = vtkm::Float32;
};
template <>
struct ClosestFloat<vtkm::Int16>
{
using Type = vtkm::Float32;
};
template <>
struct ClosestFloat<vtkm::UInt16>
{
using Type = vtkm::Float32;
};
template <>
struct ClosestFloat<vtkm::Int32>
{
using Type = vtkm::Float64;
};
template <>
struct ClosestFloat<vtkm::UInt32>
{
using Type = vtkm::Float64;
};
template <>
struct ClosestFloat<vtkm::Int64>
{
using Type = vtkm::Float64;
};
template <>
struct ClosestFloat<vtkm::UInt64>
{
using Type = vtkm::Float64;
};
template <typename T>
vtkm::cont::UnknownArrayHandle CreateUnknownArrayHandle(const std::vector<T>& vec)
{
switch (vtkm::VecTraits<T>::NUM_COMPONENTS)
{
case 1:
{
using CommonType = typename ClosestCommonType<T>::Type;
constexpr bool not_same = !std::is_same<T, CommonType>::value;
if (not_same)
{
VTKM_LOG_S(vtkm::cont::LogLevel::Info,
"Type " << vtkm::io::internal::DataTypeName<T>::Name()
<< " is currently unsupported. Converting to "
<< vtkm::io::internal::DataTypeName<CommonType>::Name() << ".");
}
vtkm::cont::ArrayHandle<CommonType> output;
output.Allocate(static_cast<vtkm::Id>(vec.size()));
auto portal = output.WritePortal();
for (vtkm::Id i = 0; i < output.GetNumberOfValues(); ++i)
{
portal.Set(i, static_cast<CommonType>(vec[static_cast<std::size_t>(i)]));
}
return vtkm::cont::UnknownArrayHandle(output);
}
case 2:
case 3:
case 9:
{
constexpr auto numComps = vtkm::VecTraits<T>::NUM_COMPONENTS;
using InComponentType = typename vtkm::VecTraits<T>::ComponentType;
using OutComponentType = typename ClosestFloat<InComponentType>::Type;
using CommonType = vtkm::Vec<OutComponentType, numComps>;
constexpr bool not_same = !std::is_same<T, CommonType>::value;
if (not_same)
{
VTKM_LOG_S(vtkm::cont::LogLevel::Info,
"Type " << vtkm::io::internal::DataTypeName<InComponentType>::Name() << "["
<< vtkm::VecTraits<T>::GetNumberOfComponents(T()) << "] "
<< "is currently unsupported. Converting to "
<< vtkm::io::internal::DataTypeName<OutComponentType>::Name() << "["
<< numComps << "].");
}
vtkm::cont::ArrayHandle<CommonType> output;
output.Allocate(static_cast<vtkm::Id>(vec.size()));
auto portal = output.WritePortal();
for (vtkm::Id i = 0; i < output.GetNumberOfValues(); ++i)
{
CommonType outval = CommonType();
for (vtkm::IdComponent j = 0; j < numComps; ++j)
{
outval[j] = static_cast<OutComponentType>(
vtkm::VecTraits<T>::GetComponent(vec[static_cast<std::size_t>(i)], j));
}
portal.Set(i, outval);
}
return vtkm::cont::UnknownArrayHandle(output);
}
default:
{
VTKM_LOG_S(vtkm::cont::LogLevel::Warn, "Only 1, 2, 3, or 9 components supported. Skipping.");
return vtkm::cont::UnknownArrayHandle(vtkm::cont::ArrayHandle<vtkm::Float32>());
}
}
}
} // anonymous namespace
namespace vtkm
@ -676,27 +521,23 @@ void VTKDataSetReaderBase::ReadGlobalOrPedigreeIds(vtkm::cont::Field::Associatio
class VTKDataSetReaderBase::SkipArrayVariant
{
public:
SkipArrayVariant(VTKDataSetReaderBase* reader, std::size_t numElements)
SkipArrayVariant(VTKDataSetReaderBase* reader,
std::size_t numElements,
vtkm::IdComponent numComponents)
: Reader(reader)
, NumElements(numElements)
, TotalSize(numElements * static_cast<std::size_t>(numComponents))
{
}
template <typename T>
void operator()(T) const
{
this->Reader->SkipArray(this->NumElements, T());
}
template <typename T>
void operator()(vtkm::IdComponent numComponents, T) const
{
this->Reader->SkipArray(this->NumElements * static_cast<std::size_t>(numComponents), T());
this->Reader->SkipArray(this->TotalSize, T());
}
protected:
VTKDataSetReaderBase* Reader;
std::size_t NumElements;
std::size_t TotalSize;
};
class VTKDataSetReaderBase::ReadArrayVariant : public SkipArrayVariant
@ -705,9 +546,11 @@ public:
ReadArrayVariant(VTKDataSetReaderBase* reader,
vtkm::cont::Field::Association association,
std::size_t numElements,
vtkm::IdComponent numComponents,
vtkm::cont::UnknownArrayHandle& data)
: SkipArrayVariant(reader, numElements)
: SkipArrayVariant(reader, numElements, numComponents)
, Association(association)
, NumComponents(numComponents)
, Data(&data)
{
}
@ -715,12 +558,13 @@ public:
template <typename T>
void operator()(T) const
{
std::vector<T> buffer(this->NumElements);
std::vector<T> buffer(this->TotalSize);
this->Reader->ReadArray(buffer);
if ((this->Association != vtkm::cont::Field::Association::Cells) ||
(this->Reader->GetCellsPermutation().GetNumberOfValues() < 1))
{
*this->Data = CreateUnknownArrayHandle(buffer);
*this->Data =
vtkm::cont::make_ArrayHandleRuntimeVecMove(this->NumComponents, std::move(buffer));
}
else
{
@ -734,20 +578,14 @@ public:
std::size_t inIndex = static_cast<std::size_t>(permutation.Get(outIndex));
permutedBuffer[static_cast<std::size_t>(outIndex)] = buffer[inIndex];
}
*this->Data = CreateUnknownArrayHandle(permutedBuffer);
*this->Data =
vtkm::cont::make_ArrayHandleRuntimeVecMove(this->NumComponents, std::move(permutedBuffer));
}
}
template <typename T>
void operator()(vtkm::IdComponent numComponents, T) const
{
VTKM_LOG_S(vtkm::cont::LogLevel::Warn,
"Support for " << numComponents << " components not implemented. Skipping.");
SkipArrayVariant::operator()(numComponents, T());
}
private:
vtkm::cont::Field::Association Association;
vtkm::IdComponent NumComponents;
vtkm::cont::UnknownArrayHandle* Data;
};
@ -764,8 +602,8 @@ void VTKDataSetReaderBase::DoSkipArrayVariant(std::string dataType,
else
{
vtkm::io::internal::DataType typeId = vtkm::io::internal::DataTypeId(dataType);
vtkm::io::internal::SelectTypeAndCall(
typeId, numComponents, SkipArrayVariant(this, numElements));
vtkm::io::internal::SelectTypeAndCall(typeId,
SkipArrayVariant(this, numElements, numComponents));
}
}
@ -791,7 +629,7 @@ vtkm::cont::UnknownArrayHandle VTKDataSetReaderBase::DoReadArrayVariant(
{
vtkm::io::internal::DataType typeId = vtkm::io::internal::DataTypeId(dataType);
vtkm::io::internal::SelectTypeAndCall(
typeId, numComponents, ReadArrayVariant(this, association, numElements, data));
typeId, ReadArrayVariant(this, association, numElements, numComponents, data));
}
return data;

@ -170,73 +170,45 @@ struct DataTypeName<vtkm::Float64>
static const char* Name() { return "double"; }
};
template <typename T, typename Functor>
inline void SelectVecTypeAndCall(T, vtkm::IdComponent numComponents, const Functor& functor)
{
switch (numComponents)
{
case 1:
functor(T());
break;
case 2:
functor(vtkm::Vec<T, 2>());
break;
case 3:
functor(vtkm::Vec<T, 3>());
break;
case 4:
functor(vtkm::Vec<T, 4>());
break;
case 9:
functor(vtkm::Vec<T, 9>());
break;
default:
functor(numComponents, T());
break;
}
}
template <typename Functor>
inline void SelectTypeAndCall(DataType dtype,
vtkm::IdComponent numComponents,
const Functor& functor)
inline void SelectTypeAndCall(DataType dtype, Functor&& functor)
{
switch (dtype)
{
case DTYPE_BIT:
SelectVecTypeAndCall(DummyBitType(), numComponents, functor);
functor(DummyBitType());
break;
case DTYPE_UNSIGNED_CHAR:
SelectVecTypeAndCall(vtkm::UInt8(), numComponents, functor);
functor(vtkm::UInt8());
break;
case DTYPE_CHAR:
SelectVecTypeAndCall(vtkm::Int8(), numComponents, functor);
functor(vtkm::Int8());
break;
case DTYPE_UNSIGNED_SHORT:
SelectVecTypeAndCall(vtkm::UInt16(), numComponents, functor);
functor(vtkm::UInt16());
break;
case DTYPE_SHORT:
SelectVecTypeAndCall(vtkm::Int16(), numComponents, functor);
functor(vtkm::Int16());
break;
case DTYPE_UNSIGNED_INT:
SelectVecTypeAndCall(vtkm::UInt32(), numComponents, functor);
functor(vtkm::UInt32());
break;
case DTYPE_INT:
SelectVecTypeAndCall(vtkm::Int32(), numComponents, functor);
functor(vtkm::Int32());
break;
case DTYPE_UNSIGNED_LONG:
case DTYPE_UNSIGNED_LONG_LONG:
SelectVecTypeAndCall(vtkm::UInt64(), numComponents, functor);
functor(vtkm::UInt64());
break;
case DTYPE_LONG:
case DTYPE_LONG_LONG:
SelectVecTypeAndCall(vtkm::Int64(), numComponents, functor);
functor(vtkm::Int64());
break;
case DTYPE_FLOAT:
SelectVecTypeAndCall(vtkm::Float32(), numComponents, functor);
functor(vtkm::Float32());
break;
case DTYPE_DOUBLE:
SelectVecTypeAndCall(vtkm::Float64(), numComponents, functor);
functor(vtkm::Float64());
break;
default:
assert(false);

@ -12,6 +12,7 @@
#include <cstdio>
#include <vector>
#include <vtkm/cont/ArrayHandleSOA.h>
#include <vtkm/cont/DataSetBuilderUniform.h>
#include <vtkm/io/VTKDataSetReader.h>
#include <vtkm/io/VTKDataSetWriter.h>
@ -122,7 +123,7 @@ void CheckWrittenReadData(const vtkm::cont::DataSet& originalData,
VTKM_TEST_ASSERT(fileData.HasField(originalField.GetName(), originalField.GetAssociation()));
vtkm::cont::Field fileField =
fileData.GetField(originalField.GetName(), originalField.GetAssociation());
vtkm::cont::CastAndCall(originalField, CheckSameField{}, fileField);
VTKM_TEST_ASSERT(test_equal_ArrayHandles(originalField.GetData(), fileField.GetData()));
}
VTKM_TEST_ASSERT(fileData.GetNumberOfCoordinateSystems() > 0);
@ -261,12 +262,31 @@ void TestVTKCompoundWrite()
std::remove("chirp.vtk");
}
void TestVTKOddVecSizes()
{
vtkm::cont::DataSetBuilderUniform dsb;
vtkm::cont::DataSet dataSet = dsb.Create({ 2, 2, 2 });
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::FloatDefault, 5>> vec5Array;
vec5Array.Allocate(dataSet.GetNumberOfPoints());
SetPortal(vec5Array.WritePortal());
dataSet.AddPointField("vec5", vec5Array);
vtkm::cont::ArrayHandleSOA<vtkm::Vec<vtkm::FloatDefault, 13>> vec13Array;
vec13Array.Allocate(dataSet.GetNumberOfPoints());
SetPortal(vec13Array.WritePortal());
dataSet.AddPointField("vec13", vec13Array);
TestVTKWriteTestData("OddVecSizes", dataSet);
}
void TestVTKWrite()
{
TestVTKExplicitWrite();
TestVTKUniformWrite();
TestVTKRectilinearWrite();
TestVTKCompoundWrite();
TestVTKOddVecSizes();
}
} //Anonymous namespace

@ -13,7 +13,6 @@
#include <vtkm/cont/Timer.h>
#include <vtkm/cont/TryExecute.h>
#include <vtkm/rendering/CanvasRayTracer.h>
#include <vtkm/rendering/raytracing/Camera.h>
#include <vtkm/rendering/raytracing/Logger.h>
#include <vtkm/rendering/raytracing/RayOperations.h>
@ -22,7 +21,6 @@
#include <vtkm/rendering/raytracing/SphereIntersector.h>
#include <vtkm/rendering/raytracing/TriangleExtractor.h>
namespace vtkm
{
namespace rendering
@ -30,32 +28,25 @@ namespace rendering
struct ScalarRenderer::InternalsType
{
bool ValidDataSet;
vtkm::Int32 Width;
vtkm::Int32 Height;
vtkm::Float32 DefaultValue;
bool ValidDataSet = false;
vtkm::Int32 Width = 1024;
vtkm::Int32 Height = 1024;
vtkm::Float32 DefaultValue = vtkm::Nan32();
vtkm::cont::DataSet DataSet;
vtkm::rendering::raytracing::ScalarRenderer Tracer;
vtkm::Bounds ShapeBounds;
VTKM_CONT
InternalsType()
: ValidDataSet(false)
, Width(1024)
, Height(1024)
, DefaultValue(vtkm::Nan32())
{
}
};
ScalarRenderer::ScalarRenderer()
: Internals(new InternalsType)
: Internals(std::make_unique<InternalsType>())
{
}
ScalarRenderer::~ScalarRenderer() {}
ScalarRenderer::ScalarRenderer(ScalarRenderer&&) noexcept = default;
ScalarRenderer& ScalarRenderer::operator=(ScalarRenderer&&) noexcept = default;
ScalarRenderer::~ScalarRenderer() = default;
void ScalarRenderer::SetWidth(const vtkm::Int32 width)
void ScalarRenderer::SetWidth(vtkm::Int32 width)
{
if (width < 1)
{
@ -64,12 +55,12 @@ void ScalarRenderer::SetWidth(const vtkm::Int32 width)
Internals->Width = width;
}
void ScalarRenderer::SetDefaultValue(const vtkm::Float32 value)
void ScalarRenderer::SetDefaultValue(vtkm::Float32 value)
{
Internals->DefaultValue = value;
}
void ScalarRenderer::SetHeight(const vtkm::Int32 height)
void ScalarRenderer::SetHeight(vtkm::Int32 height)
{
if (height < 1)
{
@ -90,16 +81,15 @@ void ScalarRenderer::SetInput(vtkm::cont::DataSet& dataSet)
if (triExtractor.GetNumberOfTriangles() > 0)
{
auto triIntersector = std::make_shared<raytracing::TriangleIntersector>();
auto triIntersector = std::make_unique<raytracing::TriangleIntersector>();
triIntersector->SetData(coords, triExtractor.GetTriangles());
this->Internals->Tracer.SetShapeIntersector(triIntersector);
this->Internals->ShapeBounds = triIntersector->GetShapeBounds();
this->Internals->Tracer.SetShapeIntersector(std::move(triIntersector));
}
}
ScalarRenderer::Result ScalarRenderer::Render(const vtkm::rendering::Camera& camera)
{
if (!Internals->ValidDataSet)
{
throw vtkm::cont::ErrorBadValue("ScalarRenderer: input never set");
@ -182,7 +172,7 @@ ScalarRenderer::Result ScalarRenderer::Render(const vtkm::rendering::Camera& cam
vtkm::cont::DataSet ScalarRenderer::Result::ToDataSet()
{
if (Scalars.size() == 0)
if (Scalars.empty())
{
throw vtkm::cont::ErrorBadValue("ScalarRenderer: result empty");
}

@ -25,12 +25,19 @@ class VTKM_RENDERING_EXPORT ScalarRenderer
public:
ScalarRenderer();
// Disable copying due to unique_ptr;
ScalarRenderer(const ScalarRenderer&) = delete;
ScalarRenderer& operator=(const ScalarRenderer&) = delete;
ScalarRenderer(ScalarRenderer&&) noexcept;
ScalarRenderer& operator=(ScalarRenderer&&) noexcept;
// Default destructor implemented in source file to support PIMPL idiom.
~ScalarRenderer();
void SetInput(vtkm::cont::DataSet& dataSet);
void SetWidth(const vtkm::Int32 width);
void SetHeight(const vtkm::Int32 height);
void SetWidth(vtkm::Int32 width);
void SetHeight(vtkm::Int32 height);
void SetDefaultValue(vtkm::Float32 value);
struct VTKM_RENDERING_EXPORT Result
@ -47,10 +54,9 @@ public:
ScalarRenderer::Result Render(const vtkm::rendering::Camera& camera);
private:
struct InternalsType;
std::shared_ptr<InternalsType> Internals;
std::unique_ptr<InternalsType> Internals;
};
}
} //namespace vtkm::rendering

@ -10,15 +10,11 @@
#include <vtkm/rendering/raytracing/ScalarRenderer.h>
#include <iostream>
#include <math.h>
#include <stdio.h>
#include <vtkm/cont/ArrayHandleUniformPointCoordinates.h>
#include <vtkm/cont/ColorTable.h>
#include <vtkm/cont/Timer.h>
#include <vtkm/rendering/raytracing/Logger.h>
#include <vtkm/rendering/raytracing/RayTracingTypeDefs.h>
#include <vtkm/worklet/DispatcherMapField.h>
#include <vtkm/worklet/WorkletMapField.h>
namespace vtkm
@ -39,10 +35,10 @@ public:
{
private:
vtkm::Vec3f_32 LightPosition;
vtkm::Vec3f_32 LightAmbient;
vtkm::Vec3f_32 LightDiffuse;
vtkm::Vec3f_32 LightSpecular;
vtkm::Float32 SpecularExponent;
vtkm::Vec3f_32 LightAmbient{ .5f, .5f, .5f };
vtkm::Vec3f_32 LightDiffuse{ .7f, .7f, .7f };
vtkm::Vec3f_32 LightSpecular{ .7f, .7f, .7f };
vtkm::Float32 SpecularExponent = 20.f;
vtkm::Vec3f_32 CameraPosition;
vtkm::Vec3f_32 LookAt;
Precision MissScalar;
@ -58,31 +54,16 @@ public:
, LookAt(lookAt)
, MissScalar(missScalar)
{
//Set up some default lighting parameters for now
LightAmbient[0] = .5f;
LightAmbient[1] = .5f;
LightAmbient[2] = .5f;
LightDiffuse[0] = .7f;
LightDiffuse[1] = .7f;
LightDiffuse[2] = .7f;
LightSpecular[0] = .7f;
LightSpecular[1] = .7f;
LightSpecular[2] = .7f;
SpecularExponent = 20.f;
}
using ControlSignature = void(FieldIn, FieldIn, FieldIn, FieldOut);
using ExecutionSignature = void(_1, _2, _3, _4);
//using ExecutionSignature = void(_1, _2, _3, _4, WorkIndex);
//template <typename ShadePortalType, typename Precision>
VTKM_EXEC void operator()(const vtkm::Id& hitIdx,
const vtkm::Vec<Precision, 3>& normal,
const vtkm::Vec<Precision, 3>& intersection,
Precision& output) const //,
// const vtkm::Id& idx) const
Precision& output) const
{
if (hitIdx < 0)
{
output = MissScalar;
@ -145,7 +126,6 @@ public:
}; //class Shade
//template <typename Precision>
VTKM_CONT void run(Ray<Precision>& rays,
const vtkm::rendering::raytracing::Camera& camera,
const Precision missScalar,
@ -173,7 +153,7 @@ private:
public:
VTKM_CONT
FilterDepth(const Precision missScalar)
explicit FilterDepth(const Precision missScalar)
: MissScalar(missScalar)
{
}
@ -201,7 +181,7 @@ private:
public:
VTKM_CONT
WriteBuffer(const Precision missScalar)
explicit WriteBuffer(const Precision missScalar)
: MissScalar(missScalar)
{
}
@ -227,9 +207,6 @@ template <typename Precision>
class WriteDepthBuffer : public vtkm::worklet::WorkletMapField
{
public:
VTKM_CONT
WriteDepthBuffer() {}
typedef void ControlSignature(FieldIn, FieldOut);
typedef void ExecutionSignature(_1, _2);
@ -237,22 +214,14 @@ public:
}; //class WriteDepthBuffer
} // namespace detail
ScalarRenderer::ScalarRenderer()
: IntersectorValid(false)
void ScalarRenderer::SetShapeIntersector(std::unique_ptr<ShapeIntersector>&& intersector)
{
}
ScalarRenderer::~ScalarRenderer() {}
void ScalarRenderer::SetShapeIntersector(std::shared_ptr<ShapeIntersector> intersector)
{
Intersector = intersector;
IntersectorValid = true;
Intersector = std::move(intersector);
}
void ScalarRenderer::AddField(const vtkm::cont::Field& scalarField)
{
vtkm::cont::ArrayHandle<vtkm::Range> ranges = scalarField.GetRange();
const auto& ranges = scalarField.GetRange();
if (ranges.GetNumberOfValues() != 1)
{
throw vtkm::cont::ErrorBadValue("ScalarRenderer(AddField): field must be a scalar");
@ -295,7 +264,7 @@ void ScalarRenderer::RenderOnDevice(Ray<Precision>& rays,
{
throw vtkm::cont::ErrorBadValue("ScalarRenderer: no fields added");
}
if (!IntersectorValid)
if (!Intersector)
{
throw vtkm::cont::ErrorBadValue("ScalarRenderer: intersector never set");
}
@ -316,8 +285,6 @@ void ScalarRenderer::RenderOnDevice(Ray<Precision>& rays,
AddBuffer(rays, missScalar, Fields[f].GetName());
}
const vtkm::Int32 numChannels = 1;
ChannelBuffer<Precision> buffer(numChannels, rays.NumRays);
detail::SurfaceShade<Precision> surfaceShade;
@ -325,24 +292,20 @@ void ScalarRenderer::RenderOnDevice(Ray<Precision>& rays,
buffer.SetName("shading");
rays.Buffers.push_back(buffer);
vtkm::worklet::DispatcherMapField<detail::FilterDepth<Precision>>(
detail::FilterDepth<Precision>(missScalar))
.Invoke(rays.HitIdx, rays.Distance);
this->Invoke(detail::FilterDepth<Precision>{ missScalar }, rays.HitIdx, rays.Distance);
time = renderTimer.GetElapsedTime();
logger->CloseLogEntry(time);
} // RenderOnDevice
template <typename Precision>
void ScalarRenderer::AddBuffer(Ray<Precision>& rays, Precision missScalar, const std::string name)
void ScalarRenderer::AddBuffer(Ray<Precision>& rays, Precision missScalar, const std::string& name)
{
const vtkm::Int32 numChannels = 1;
ChannelBuffer<Precision> buffer(numChannels, rays.NumRays);
vtkm::worklet::DispatcherMapField<detail::WriteBuffer<Precision>>(
detail::WriteBuffer<Precision>(missScalar))
.Invoke(rays.HitIdx, rays.Scalar, buffer.Buffer);
this->Invoke(
detail::WriteBuffer<Precision>{ missScalar }, rays.HitIdx, rays.Scalar, buffer.Buffer);
buffer.SetName(name);
rays.Buffers.push_back(buffer);
@ -354,9 +317,7 @@ void ScalarRenderer::AddDepthBuffer(Ray<Precision>& rays)
const vtkm::Int32 numChannels = 1;
ChannelBuffer<Precision> buffer(numChannels, rays.NumRays);
vtkm::worklet::DispatcherMapField<detail::WriteDepthBuffer<Precision>>(
detail::WriteDepthBuffer<Precision>())
.Invoke(rays.Depth, buffer.Buffer);
this->Invoke(detail::WriteDepthBuffer<Precision>{}, rays.Depth, buffer.Buffer);
buffer.SetName("depth");
rays.Buffers.push_back(buffer);

@ -17,6 +17,7 @@
#include <vtkm/rendering/raytracing/Camera.h>
#include <vtkm/rendering/raytracing/TriangleIntersector.h>
namespace vtkm
{
namespace rendering
@ -26,10 +27,12 @@ namespace raytracing
class VTKM_RENDERING_EXPORT ScalarRenderer
{
private:
vtkm::cont::Invoker Invoke;
protected:
std::shared_ptr<ShapeIntersector> Intersector;
std::unique_ptr<ShapeIntersector> Intersector;
std::vector<vtkm::cont::Field> Fields;
bool IntersectorValid;
template <typename Precision>
void RenderOnDevice(Ray<Precision>& rays,
@ -37,19 +40,14 @@ protected:
vtkm::rendering::raytracing::Camera& cam);
template <typename Precision>
void AddBuffer(Ray<Precision>& rays, Precision missScalar, const std::string name);
void AddBuffer(Ray<Precision>& rays, Precision missScalar, const std::string& name);
template <typename Precision>
void AddDepthBuffer(Ray<Precision>& rays);
public:
VTKM_CONT
ScalarRenderer();
VTKM_CONT
~ScalarRenderer();
VTKM_CONT
void SetShapeIntersector(std::shared_ptr<ShapeIntersector> intersector);
void SetShapeIntersector(std::unique_ptr<ShapeIntersector>&& intersector);
VTKM_CONT
void AddField(const vtkm::cont::Field& scalarField);
@ -68,4 +66,4 @@ public:
}
}
} // namespace vtkm::rendering::raytracing
#endif //vtk_m_rendering_raytracing_RayTracer_h
#endif //vtk_m_rendering_raytracing_ScalarRenderer_h