mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-09-08 13:23:51 +00:00
Merge remote-tracking branch 'upstream/master' into Enhance-Testing-From-File
This commit is contained in:
commit
8579d54cb9
@ -47,7 +47,7 @@ target_compile_features(vtkm_compiler_flags INTERFACE cxx_std_11)
|
||||
# to have the smallest binary impact as they can drop any VTK-m symbol
|
||||
# they don't use.
|
||||
if(VTKM_COMPILER_IS_MSVC)
|
||||
target_compile_options(vtkm_compiler_flags INTERFACE /Gy)
|
||||
target_compile_options(vtkm_compiler_flags INTERFACE $<$<COMPILE_LANGUAGE:CXX>:/Gy>)
|
||||
if(TARGET vtkm::cuda)
|
||||
target_compile_options(vtkm_compiler_flags INTERFACE $<$<COMPILE_LANGUAGE:CUDA>:-Xcompiler="/Gy">)
|
||||
endif()
|
||||
|
@ -110,6 +110,35 @@ function(vtkm_declare_headers)
|
||||
vtkm_install_headers("${dir_prefix}" ${ARGN})
|
||||
endfunction(vtkm_declare_headers)
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
function(vtkm_setup_job_pool)
|
||||
# The VTK-m job pool is only used for components that use large amounts
|
||||
# of memory such as worklet tests, filters, and filter tests
|
||||
get_property(vtkm_pool_established
|
||||
GLOBAL PROPERTY VTKM_JOB_POOL_ESTABLISHED SET)
|
||||
if(NOT vtkm_pool_established)
|
||||
# The VTK-m filters uses large amounts of memory to compile as it does lots
|
||||
# of template expansion. To reduce the amount of tension on the machine when
|
||||
# using generators such as ninja we restrict the number of VTK-m enabled
|
||||
# compilation units to be built at the same time.
|
||||
#
|
||||
# We try to allocate a pool size where we presume each compilation process
|
||||
# will require 3GB of memory. To allow for other NON VTK-m jobs we leave at
|
||||
# least 3GB of memory as 'slop'.
|
||||
cmake_host_system_information(RESULT vtkm_mem_ QUERY TOTAL_PHYSICAL_MEMORY)
|
||||
math(EXPR vtkm_pool_size "(${vtkm_mem_}/3072)-1")
|
||||
|
||||
if (vtkm_pool_size LESS 1)
|
||||
set(vtkm_pool_size 1)
|
||||
endif ()
|
||||
|
||||
set_property(GLOBAL APPEND
|
||||
PROPERTY
|
||||
JOB_POOLS vtkm_pool=${vtkm_pool_size})
|
||||
set_property(GLOBAL PROPERTY VTKM_JOB_POOL_ESTABLISHED TRUE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# FORWARD FACING API
|
||||
|
||||
@ -313,10 +342,11 @@ endfunction()
|
||||
# SOURCES <source_list>
|
||||
# TEMPLATE_SOURCES <.hxx >
|
||||
# HEADERS <header list>
|
||||
# USE_VTKM_JOB_POOL
|
||||
# [ DEVICE_SOURCES <source_list> ]
|
||||
# )
|
||||
function(vtkm_library)
|
||||
set(options OBJECT STATIC SHARED)
|
||||
set(options OBJECT STATIC SHARED USE_VTKM_JOB_POOL)
|
||||
set(oneValueArgs NAME)
|
||||
set(multiValueArgs SOURCES HEADERS TEMPLATE_SOURCES DEVICE_SOURCES)
|
||||
cmake_parse_arguments(VTKm_LIB
|
||||
@ -357,7 +387,6 @@ function(vtkm_library)
|
||||
set_property(TARGET ${lib_name} PROPERTY LIBRARY_OUTPUT_DIRECTORY ${VTKm_LIBRARY_OUTPUT_PATH})
|
||||
set_property(TARGET ${lib_name} PROPERTY RUNTIME_OUTPUT_DIRECTORY ${VTKm_EXECUTABLE_OUTPUT_PATH})
|
||||
|
||||
|
||||
# allow the static cuda runtime find the driver (libcuda.dyllib) at runtime.
|
||||
if(APPLE)
|
||||
set_property(TARGET ${lib_name} PROPERTY BUILD_RPATH ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES})
|
||||
@ -402,4 +431,9 @@ function(vtkm_library)
|
||||
RUNTIME DESTINATION ${VTKm_INSTALL_BIN_DIR}
|
||||
)
|
||||
|
||||
if(VTKm_LIB_USE_VTKM_JOB_POOL)
|
||||
vtkm_setup_job_pool()
|
||||
set_property(TARGET ${lib_name} PROPERTY JOB_POOL_COMPILE vtkm_pool)
|
||||
endif()
|
||||
|
||||
endfunction(vtkm_library)
|
||||
|
@ -22,6 +22,7 @@ include(VTKmWrappers)
|
||||
# TEST_ARGS <argument_list>
|
||||
# MPI
|
||||
# ALL_BACKENDS
|
||||
# USE_VTKM_JOB_POOL
|
||||
# <options>
|
||||
# )
|
||||
#
|
||||
@ -46,7 +47,7 @@ function(vtkm_unit_tests)
|
||||
endif()
|
||||
|
||||
set(options)
|
||||
set(global_options ${options} MPI ALL_BACKENDS)
|
||||
set(global_options ${options} USE_VTKM_JOB_POOL MPI ALL_BACKENDS)
|
||||
set(oneValueArgs BACKEND NAME LABEL)
|
||||
set(multiValueArgs SOURCES LIBRARIES DEFINES TEST_ARGS)
|
||||
cmake_parse_arguments(VTKm_UT
|
||||
@ -143,6 +144,11 @@ function(vtkm_unit_tests)
|
||||
|
||||
target_link_libraries(${test_prog} PRIVATE vtkm_cont ${VTKm_UT_LIBRARIES})
|
||||
|
||||
if(VTKm_UT_USE_VTKM_JOB_POOL)
|
||||
vtkm_setup_job_pool()
|
||||
set_property(TARGET ${test_prog} PROPERTY JOB_POOL_COMPILE vtkm_pool)
|
||||
endif()
|
||||
|
||||
list(LENGTH per_device_command_line_arguments number_of_devices)
|
||||
foreach(index RANGE ${number_of_devices})
|
||||
if(index EQUAL number_of_devices)
|
||||
|
@ -128,12 +128,17 @@ set(VTKm_BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS})
|
||||
# and the warnings are too strict for the parent project.
|
||||
vtkm_option(VTKm_ENABLE_DEVELOPER_FLAGS "Enable compiler flags that are useful while developing VTK-m" ON)
|
||||
|
||||
# By default VTK-m would install its README.md and LICENSE.md.
|
||||
# Some application might need not to install those, hence this option.
|
||||
vtkm_option(VTKm_NO_INSTALL_README_LICENSE "disable the installation of README and LICENSE files" OFF)
|
||||
|
||||
mark_as_advanced(
|
||||
VTKm_ENABLE_LOGGING
|
||||
VTKm_NO_ASSERT
|
||||
VTKm_INSTALL_ONLY_LIBRARIES
|
||||
VTKm_USE_DEFAULT_SYMBOL_VISIBILITY
|
||||
VTKm_ENABLE_DEVELOPER_FLAGS
|
||||
VTKm_NO_INSTALL_README_LICENSE
|
||||
)
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
@ -226,6 +231,18 @@ write_basic_package_version_file(
|
||||
VERSION ${VTKm_VERSION}
|
||||
COMPATIBILITY ExactVersion )
|
||||
|
||||
# Install the readme and license files.
|
||||
if (NOT VTKm_NO_INSTALL_README_LICENSE)
|
||||
install(FILES ${VTKm_SOURCE_DIR}/README.md
|
||||
DESTINATION ${VTKm_INSTALL_SHARE_DIR}
|
||||
RENAME VTKmREADME.md
|
||||
)
|
||||
install(FILES ${VTKm_SOURCE_DIR}/LICENSE.txt
|
||||
DESTINATION ${VTKm_INSTALL_SHARE_DIR}
|
||||
RENAME VTKmLICENSE.txt
|
||||
)
|
||||
endif()
|
||||
|
||||
if(NOT VTKm_INSTALL_ONLY_LIBRARIES)
|
||||
install(
|
||||
FILES
|
||||
@ -234,16 +251,6 @@ if(NOT VTKm_INSTALL_ONLY_LIBRARIES)
|
||||
DESTINATION ${VTKm_INSTALL_CONFIG_DIR}
|
||||
)
|
||||
|
||||
# Install the readme and license files.
|
||||
install(FILES ${VTKm_SOURCE_DIR}/README.md
|
||||
DESTINATION ${VTKm_INSTALL_SHARE_DIR}
|
||||
RENAME VTKmREADME.md
|
||||
)
|
||||
install(FILES ${VTKm_SOURCE_DIR}/LICENSE.txt
|
||||
DESTINATION ${VTKm_INSTALL_SHARE_DIR}
|
||||
RENAME VTKmLICENSE.txt
|
||||
)
|
||||
|
||||
# Install helper configure files.
|
||||
install(
|
||||
FILES
|
||||
|
44
README.md
44
README.md
@ -28,6 +28,12 @@ You can find out more about the design of VTK-m on the [VTK-m Wiki].
|
||||
+ "Part 4: Advanced Development" covers topics such as new worklet
|
||||
types and custom device adapters.
|
||||
|
||||
+ A practical [VTK-m Tutorial] based in what users want to accomplish with
|
||||
VTK-m:
|
||||
+ Building VTK-m and using existing VTK-m data structures and filters.
|
||||
+ Algorithm development with VTK-m.
|
||||
+ Writing new VTK-m filters.
|
||||
|
||||
+ Community discussion takes place on the [VTK-m users email list].
|
||||
|
||||
+ Doxygen-generated nightly reference documentation is available
|
||||
@ -149,6 +155,19 @@ Below is a simple example of using VTK-m to load a VTK image file, run the
|
||||
Marching Cubes algorithm on it, and render the results to an image:
|
||||
|
||||
```cpp
|
||||
#include <vtkm/Bounds.h>
|
||||
#include <vtkm/Range.h>
|
||||
#include <vtkm/cont/ColorTable.h>
|
||||
#include <vtkm/filter/Contour.h>
|
||||
#include <vtkm/io/reader/VTKDataSetReader.h>
|
||||
#include <vtkm/rendering/Actor.h>
|
||||
#include <vtkm/rendering/Camera.h>
|
||||
#include <vtkm/rendering/CanvasRayTracer.h>
|
||||
#include <vtkm/rendering/Color.h>
|
||||
#include <vtkm/rendering/MapperRayTracer.h>
|
||||
#include <vtkm/rendering/Scene.h>
|
||||
#include <vtkm/rendering/View3D.h>
|
||||
|
||||
vtkm::io::reader::VTKDataSetReader reader("path/to/vtk_image_file");
|
||||
vtkm::cont::DataSet inputData = reader.ReadDataSet();
|
||||
std::string fieldName = "scalars";
|
||||
@ -165,21 +184,10 @@ vtkm::cont::DataSet outputData = filter.Execute(inputData);
|
||||
|
||||
// compute the bounds and extends of the input data
|
||||
vtkm::Bounds coordsBounds = inputData.GetCoordinateSystem().GetBounds();
|
||||
vtkm::Vec<vtkm::Float64,3> totalExtent( coordsBounds.X.Length(),
|
||||
coordsBounds.Y.Length(),
|
||||
coordsBounds.Z.Length() );
|
||||
vtkm::Float64 mag = vtkm::Magnitude(totalExtent);
|
||||
vtkm::Normalize(totalExtent);
|
||||
|
||||
// setup a camera and point it to towards the center of the input data
|
||||
vtkm::rendering::Camera camera;
|
||||
camera.ResetToBounds(coordsBounds);
|
||||
|
||||
camera.SetLookAt(totalExtent*(mag * .5f));
|
||||
camera.SetViewUp(vtkm::make_Vec(0.f, 1.f, 0.f));
|
||||
camera.SetClippingRange(1.f, 100.f);
|
||||
camera.SetFieldOfView(60.f);
|
||||
camera.SetPosition(totalExtent*(mag * 2.f));
|
||||
vtkm::cont::ColorTable colorTable("inferno");
|
||||
|
||||
// Create a mapper, canvas and view that will be used to render the scene
|
||||
@ -199,6 +207,19 @@ view.Paint();
|
||||
view.SaveAs("demo_output.pnm");
|
||||
```
|
||||
|
||||
A minimal CMakeLists.txt such as the following one can be used to build this
|
||||
example.
|
||||
|
||||
```CMake
|
||||
project(example)
|
||||
|
||||
set(VTKm_DIR "/somepath/lib/cmake/vtkm-XYZ")
|
||||
|
||||
find_package(VTKm REQUIRED)
|
||||
|
||||
add_executable(example example.cxx)
|
||||
target_link_libraries(example vtkm_cont vtkm_rendering)
|
||||
```
|
||||
|
||||
## License ##
|
||||
|
||||
@ -216,4 +237,5 @@ See [LICENSE.txt](LICENSE.txt) for details.
|
||||
[VTK-m Users Guide]: http://m.vtk.org/images/c/c8/VTKmUsersGuide.pdf
|
||||
[VTK-m users email list]: http://vtk.org/mailman/listinfo/vtkm
|
||||
[VTK-m Wiki]: http://m.vtk.org/
|
||||
[VTK-m Tutorial]: http://m.vtk.org/index.php/Tutorial
|
||||
[CONTRIBUTING.md]: CONTRIBUTING.md
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -8,23 +8,19 @@
|
||||
// PURPOSE. See the above copyright notice for more information.
|
||||
//============================================================================
|
||||
|
||||
#include <vtkm/TypeTraits.h>
|
||||
|
||||
#include "Benchmarker.h"
|
||||
|
||||
#include <vtkm/cont/Algorithm.h>
|
||||
#include <vtkm/cont/DeviceAdapter.h>
|
||||
#include <vtkm/cont/DeviceAdapterAlgorithm.h>
|
||||
#include <vtkm/cont/ErrorBadAllocation.h>
|
||||
#include <vtkm/cont/RuntimeDeviceTracker.h>
|
||||
#include <vtkm/cont/Timer.h>
|
||||
|
||||
#include <vtkm/cont/serial/DeviceAdapterSerial.h>
|
||||
|
||||
#include <vtkm/internal/Configure.h>
|
||||
|
||||
#include <vtkm/testing/Testing.h>
|
||||
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <vtkm/List.h>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#ifdef VTKM_ENABLE_TBB
|
||||
@ -34,145 +30,78 @@
|
||||
// For the TBB implementation, the number of threads can be customized using a
|
||||
// "NumThreads [numThreads]" argument.
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace benchmarking
|
||||
{
|
||||
|
||||
const vtkm::UInt64 COPY_SIZE_MIN = (1 << 10); // 1 KiB
|
||||
const vtkm::UInt64 COPY_SIZE_MAX = (1 << 29); // 512 MiB
|
||||
const vtkm::UInt64 COPY_SIZE_INC = 1; // Used as 'size <<= INC'
|
||||
|
||||
const size_t COL_WIDTH = 32;
|
||||
|
||||
template <typename ValueType, typename DeviceAdapter>
|
||||
struct MeasureCopySpeed
|
||||
{
|
||||
using Algo = vtkm::cont::Algorithm;
|
||||
|
||||
vtkm::cont::ArrayHandle<ValueType> Source;
|
||||
vtkm::cont::ArrayHandle<ValueType> Destination;
|
||||
vtkm::UInt64 NumBytes;
|
||||
|
||||
VTKM_CONT
|
||||
MeasureCopySpeed(vtkm::UInt64 bytes)
|
||||
: NumBytes(bytes)
|
||||
{
|
||||
vtkm::Id numValues = static_cast<vtkm::Id>(bytes / sizeof(ValueType));
|
||||
this->Source.Allocate(numValues);
|
||||
}
|
||||
|
||||
VTKM_CONT vtkm::Float64 operator()()
|
||||
{
|
||||
vtkm::cont::Timer timer{ DeviceAdapter() };
|
||||
timer.Start();
|
||||
Algo::Copy(this->Source, this->Destination);
|
||||
|
||||
return timer.GetElapsedTime();
|
||||
}
|
||||
|
||||
VTKM_CONT std::string Description() const
|
||||
{
|
||||
vtkm::UInt64 actualSize = sizeof(ValueType);
|
||||
actualSize *= static_cast<vtkm::UInt64>(this->Source.GetNumberOfValues());
|
||||
std::ostringstream out;
|
||||
out << "Copying " << vtkm::cont::GetHumanReadableSize(this->NumBytes)
|
||||
<< " (actual=" << vtkm::cont::GetHumanReadableSize(actualSize) << ") of "
|
||||
<< vtkm::testing::TypeName<ValueType>::Name() << "\n";
|
||||
return out.str();
|
||||
}
|
||||
};
|
||||
|
||||
void PrintRow(std::ostream& out, const std::string& label, const std::string& data)
|
||||
{
|
||||
out << "| " << std::setw(COL_WIDTH) << label << " | " << std::setw(COL_WIDTH) << data << " |"
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
void PrintDivider(std::ostream& out)
|
||||
{
|
||||
const std::string fillStr(COL_WIDTH, '-');
|
||||
|
||||
out << "|-" << fillStr << "-|-" << fillStr << "-|" << std::endl;
|
||||
}
|
||||
|
||||
template <typename ValueType, typename DeviceAdapter>
|
||||
void BenchmarkValueType(vtkm::cont::DeviceAdapterId id)
|
||||
{
|
||||
PrintRow(std::cout, vtkm::testing::TypeName<ValueType>::Name(), id.GetName());
|
||||
|
||||
PrintDivider(std::cout);
|
||||
|
||||
Benchmarker bench(15, 100);
|
||||
for (vtkm::UInt64 size = COPY_SIZE_MIN; size <= COPY_SIZE_MAX; size <<= COPY_SIZE_INC)
|
||||
{
|
||||
MeasureCopySpeed<ValueType, DeviceAdapter> functor(size);
|
||||
bench.Reset();
|
||||
|
||||
std::string speedStr;
|
||||
|
||||
try
|
||||
{
|
||||
bench.GatherSamples(functor);
|
||||
vtkm::Float64 speed = static_cast<Float64>(size) / stats::Mean(bench.GetSamples());
|
||||
speedStr = vtkm::cont::GetHumanReadableSize(static_cast<UInt64>(speed)) + std::string("/s");
|
||||
}
|
||||
catch (vtkm::cont::ErrorBadAllocation&)
|
||||
{
|
||||
speedStr = "[allocation too large]";
|
||||
}
|
||||
|
||||
PrintRow(std::cout, vtkm::cont::GetHumanReadableSize(size), speedStr);
|
||||
}
|
||||
|
||||
std::cout << "\n";
|
||||
}
|
||||
}
|
||||
} // end namespace vtkm::benchmarking
|
||||
|
||||
namespace
|
||||
{
|
||||
using namespace vtkm::benchmarking;
|
||||
|
||||
struct BenchmarkValueTypeFunctor
|
||||
// Make this global so benchmarks can access the current device id:
|
||||
vtkm::cont::InitializeResult Config;
|
||||
|
||||
const vtkm::UInt64 COPY_SIZE_MIN = (1 << 10); // 1 KiB
|
||||
const vtkm::UInt64 COPY_SIZE_MAX = (1 << 30); // 1 GiB
|
||||
|
||||
using TypeList = vtkm::List<vtkm::UInt8,
|
||||
vtkm::Vec2ui_8,
|
||||
vtkm::Vec3ui_8,
|
||||
vtkm::Vec4ui_8,
|
||||
vtkm::UInt32,
|
||||
vtkm::Vec2ui_32,
|
||||
vtkm::UInt64,
|
||||
vtkm::Vec2ui_64,
|
||||
vtkm::Float32,
|
||||
vtkm::Vec2f_32,
|
||||
vtkm::Float64,
|
||||
vtkm::Vec2f_64,
|
||||
vtkm::Pair<vtkm::UInt32, vtkm::Float32>,
|
||||
vtkm::Pair<vtkm::UInt32, vtkm::Float64>,
|
||||
vtkm::Pair<vtkm::UInt64, vtkm::Float32>,
|
||||
vtkm::Pair<vtkm::UInt64, vtkm::Float64>>;
|
||||
|
||||
template <typename ValueType>
|
||||
void CopySpeed(benchmark::State& state)
|
||||
{
|
||||
template <typename DeviceAdapter>
|
||||
bool operator()(DeviceAdapter id)
|
||||
const vtkm::cont::DeviceAdapterId device = Config.Device;
|
||||
const vtkm::UInt64 numBytes = static_cast<vtkm::UInt64>(state.range(0));
|
||||
const vtkm::Id numValues = static_cast<vtkm::Id>(numBytes / sizeof(ValueType));
|
||||
|
||||
state.SetLabel(vtkm::cont::GetHumanReadableSize(numBytes));
|
||||
|
||||
vtkm::cont::ArrayHandle<ValueType> src;
|
||||
vtkm::cont::ArrayHandle<ValueType> dst;
|
||||
src.Allocate(numValues);
|
||||
dst.Allocate(numValues);
|
||||
|
||||
vtkm::cont::Timer timer(device);
|
||||
for (auto _ : state)
|
||||
{
|
||||
BenchmarkValueType<vtkm::UInt8, DeviceAdapter>(id);
|
||||
BenchmarkValueType<vtkm::Vec2ui_8, DeviceAdapter>(id);
|
||||
BenchmarkValueType<vtkm::Vec3ui_8, DeviceAdapter>(id);
|
||||
BenchmarkValueType<vtkm::Vec4ui_8, DeviceAdapter>(id);
|
||||
(void)_;
|
||||
timer.Start();
|
||||
vtkm::cont::Algorithm::Copy(device, src, dst);
|
||||
timer.Stop();
|
||||
|
||||
BenchmarkValueType<vtkm::UInt32, DeviceAdapter>(id);
|
||||
BenchmarkValueType<vtkm::Vec2ui_32, DeviceAdapter>(id);
|
||||
|
||||
BenchmarkValueType<vtkm::UInt64, DeviceAdapter>(id);
|
||||
BenchmarkValueType<vtkm::Vec2ui_64, DeviceAdapter>(id);
|
||||
|
||||
BenchmarkValueType<vtkm::Float32, DeviceAdapter>(id);
|
||||
BenchmarkValueType<vtkm::Vec2f_32, DeviceAdapter>(id);
|
||||
|
||||
BenchmarkValueType<vtkm::Float64, DeviceAdapter>(id);
|
||||
BenchmarkValueType<vtkm::Vec2f_64, DeviceAdapter>(id);
|
||||
|
||||
BenchmarkValueType<vtkm::Pair<vtkm::UInt32, vtkm::Float32>, DeviceAdapter>(id);
|
||||
BenchmarkValueType<vtkm::Pair<vtkm::UInt32, vtkm::Float64>, DeviceAdapter>(id);
|
||||
BenchmarkValueType<vtkm::Pair<vtkm::UInt64, vtkm::Float32>, DeviceAdapter>(id);
|
||||
BenchmarkValueType<vtkm::Pair<vtkm::UInt64, vtkm::Float64>, DeviceAdapter>(id);
|
||||
|
||||
return true;
|
||||
state.SetIterationTime(timer.GetElapsedTime());
|
||||
}
|
||||
};
|
||||
|
||||
const int64_t iterations = static_cast<int64_t>(state.iterations());
|
||||
state.SetBytesProcessed(static_cast<int64_t>(numBytes) * iterations);
|
||||
state.SetItemsProcessed(static_cast<int64_t>(numValues) * iterations);
|
||||
}
|
||||
VTKM_BENCHMARK_TEMPLATES_OPTS(CopySpeed,
|
||||
->Range(COPY_SIZE_MIN, COPY_SIZE_MAX)
|
||||
->ArgName("Bytes"),
|
||||
TypeList);
|
||||
|
||||
} // end anon namespace
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
auto opts = vtkm::cont::InitializeOptions::RequireDevice |
|
||||
vtkm::cont::InitializeOptions::ErrorOnBadOption | vtkm::cont::InitializeOptions::AddHelp;
|
||||
auto config = vtkm::cont::Initialize(argc, argv, opts);
|
||||
// Parse VTK-m options:
|
||||
auto opts = vtkm::cont::InitializeOptions::RequireDevice | vtkm::cont::InitializeOptions::AddHelp;
|
||||
Config = vtkm::cont::Initialize(argc, argv, opts);
|
||||
|
||||
// Setup device:
|
||||
vtkm::cont::GetRuntimeDeviceTracker().ForceDevice(Config.Device);
|
||||
|
||||
// Handle NumThreads command-line arg:
|
||||
#ifdef VTKM_ENABLE_TBB
|
||||
int numThreads = tbb::task_scheduler_init::automatic;
|
||||
#endif // TBB
|
||||
@ -196,6 +125,6 @@ int main(int argc, char* argv[])
|
||||
tbb::task_scheduler_init init(numThreads);
|
||||
#endif // TBB
|
||||
|
||||
BenchmarkValueTypeFunctor functor;
|
||||
vtkm::cont::TryExecuteOnDevice(config.Device, functor);
|
||||
// handle benchmarking related args and run benchmarks:
|
||||
VTKM_EXECUTE_BENCHMARKS(argc, argv);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -14,6 +14,7 @@
|
||||
|
||||
#include <vtkm/cont/ArrayHandle.h>
|
||||
#include <vtkm/cont/DeviceAdapterAlgorithm.h>
|
||||
#include <vtkm/cont/Initialize.h>
|
||||
#include <vtkm/cont/Timer.h>
|
||||
#include <vtkm/cont/testing/MakeTestDataSet.h>
|
||||
|
||||
@ -31,114 +32,97 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace vtkm::benchmarking;
|
||||
namespace vtkm
|
||||
{
|
||||
namespace benchmarking
|
||||
namespace
|
||||
{
|
||||
|
||||
template <typename Precision, typename DeviceAdapter>
|
||||
struct BenchRayTracing
|
||||
// Hold configuration state (e.g. active device)
|
||||
vtkm::cont::InitializeResult Config;
|
||||
|
||||
void BenchRayTracing(::benchmark::State& state)
|
||||
{
|
||||
vtkm::rendering::raytracing::RayTracer Tracer;
|
||||
vtkm::rendering::raytracing::Camera RayCamera;
|
||||
vtkm::cont::ArrayHandle<vtkm::Id4> Indices;
|
||||
vtkm::rendering::raytracing::Ray<Precision> Rays;
|
||||
vtkm::cont::CoordinateSystem Coords;
|
||||
vtkm::cont::DataSet Data;
|
||||
const vtkm::Id3 dims(128, 128, 128);
|
||||
|
||||
VTKM_CONT ~BenchRayTracing() {}
|
||||
vtkm::cont::testing::MakeTestDataSet maker;
|
||||
auto dataset = maker.Make3DUniformDataSet3(dims);
|
||||
auto coords = dataset.GetCoordinateSystem();
|
||||
|
||||
VTKM_CONT BenchRayTracing()
|
||||
vtkm::rendering::Camera camera;
|
||||
vtkm::Bounds bounds = dataset.GetCoordinateSystem().GetBounds();
|
||||
camera.ResetToBounds(bounds);
|
||||
|
||||
vtkm::cont::DynamicCellSet cellset = dataset.GetCellSet();
|
||||
|
||||
vtkm::rendering::raytracing::TriangleExtractor triExtractor;
|
||||
triExtractor.ExtractCells(cellset);
|
||||
|
||||
auto triIntersector = std::make_shared<vtkm::rendering::raytracing::TriangleIntersector>(
|
||||
vtkm::rendering::raytracing::TriangleIntersector());
|
||||
|
||||
vtkm::rendering::raytracing::RayTracer tracer;
|
||||
triIntersector->SetData(coords, triExtractor.GetTriangles());
|
||||
tracer.AddShapeIntersector(triIntersector);
|
||||
|
||||
vtkm::rendering::CanvasRayTracer canvas(1920, 1080);
|
||||
vtkm::rendering::raytracing::Camera rayCamera;
|
||||
rayCamera.SetParameters(camera, canvas);
|
||||
vtkm::rendering::raytracing::Ray<vtkm::Float32> rays;
|
||||
rayCamera.CreateRays(rays, coords.GetBounds());
|
||||
|
||||
rays.Buffers.at(0).InitConst(0.f);
|
||||
|
||||
vtkm::cont::Field field = dataset.GetField("pointvar");
|
||||
vtkm::Range range = field.GetRange().ReadPortal().Get(0);
|
||||
|
||||
tracer.SetField(field, range);
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec4ui_8> temp;
|
||||
vtkm::cont::ColorTable table("cool to warm");
|
||||
table.Sample(100, temp);
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec4f_32> colors;
|
||||
colors.Allocate(100);
|
||||
auto portal = colors.WritePortal();
|
||||
auto colorPortal = temp.ReadPortal();
|
||||
constexpr vtkm::Float32 conversionToFloatSpace = (1.0f / 255.0f);
|
||||
for (vtkm::Id i = 0; i < 100; ++i)
|
||||
{
|
||||
vtkm::Id3 dims(128, 128, 128);
|
||||
vtkm::cont::testing::MakeTestDataSet maker;
|
||||
Data = maker.Make3DUniformDataSet3(dims);
|
||||
Coords = Data.GetCoordinateSystem();
|
||||
|
||||
vtkm::rendering::Camera camera;
|
||||
vtkm::Bounds bounds = Data.GetCoordinateSystem().GetBounds();
|
||||
camera.ResetToBounds(bounds);
|
||||
|
||||
vtkm::cont::DynamicCellSet cellset = Data.GetCellSet();
|
||||
|
||||
vtkm::rendering::raytracing::TriangleExtractor triExtractor;
|
||||
triExtractor.ExtractCells(cellset);
|
||||
|
||||
auto triIntersector = std::make_shared<vtkm::rendering::raytracing::TriangleIntersector>(
|
||||
vtkm::rendering::raytracing::TriangleIntersector());
|
||||
|
||||
triIntersector->SetData(Coords, triExtractor.GetTriangles());
|
||||
Tracer.AddShapeIntersector(triIntersector);
|
||||
|
||||
vtkm::rendering::CanvasRayTracer canvas(1920, 1080);
|
||||
RayCamera.SetParameters(camera, canvas);
|
||||
RayCamera.CreateRays(Rays, Coords.GetBounds());
|
||||
|
||||
Rays.Buffers.at(0).InitConst(0.f);
|
||||
|
||||
vtkm::cont::Field field = Data.GetField("pointvar");
|
||||
vtkm::Range range = field.GetRange().GetPortalConstControl().Get(0);
|
||||
|
||||
Tracer.SetField(field, range);
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec4ui_8> temp;
|
||||
vtkm::cont::ColorTable table("cool to warm");
|
||||
table.Sample(100, temp);
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec4f_32> colors;
|
||||
colors.Allocate(100);
|
||||
auto portal = colors.GetPortalControl();
|
||||
auto colorPortal = temp.GetPortalConstControl();
|
||||
constexpr vtkm::Float32 conversionToFloatSpace = (1.0f / 255.0f);
|
||||
for (vtkm::Id i = 0; i < 100; ++i)
|
||||
{
|
||||
auto color = colorPortal.Get(i);
|
||||
vtkm::Vec4f_32 t(color[0] * conversionToFloatSpace,
|
||||
color[1] * conversionToFloatSpace,
|
||||
color[2] * conversionToFloatSpace,
|
||||
color[3] * conversionToFloatSpace);
|
||||
portal.Set(i, t);
|
||||
}
|
||||
|
||||
Tracer.SetColorMap(colors);
|
||||
Tracer.Render(Rays);
|
||||
auto color = colorPortal.Get(i);
|
||||
vtkm::Vec4f_32 t(color[0] * conversionToFloatSpace,
|
||||
color[1] * conversionToFloatSpace,
|
||||
color[2] * conversionToFloatSpace,
|
||||
color[3] * conversionToFloatSpace);
|
||||
portal.Set(i, t);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
vtkm::Float64 operator()()
|
||||
tracer.SetColorMap(colors);
|
||||
tracer.Render(rays);
|
||||
|
||||
vtkm::cont::Timer timer{ Config.Device };
|
||||
for (auto _ : state)
|
||||
{
|
||||
vtkm::cont::Timer timer{ DeviceAdapter() };
|
||||
(void)_;
|
||||
timer.Start();
|
||||
rayCamera.CreateRays(rays, coords.GetBounds());
|
||||
tracer.Render(rays);
|
||||
timer.Stop();
|
||||
|
||||
RayCamera.CreateRays(Rays, Coords.GetBounds());
|
||||
try
|
||||
{
|
||||
Tracer.Render(Rays);
|
||||
}
|
||||
catch (vtkm::cont::ErrorBadValue& e)
|
||||
{
|
||||
std::cout << "exception " << e.what() << "\n";
|
||||
}
|
||||
|
||||
return timer.GetElapsedTime();
|
||||
state.SetIterationTime(timer.GetElapsedTime());
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
std::string Description() const { return "A ray tracing benchmark"; }
|
||||
};
|
||||
|
||||
VTKM_MAKE_BENCHMARK(RayTracing, BenchRayTracing);
|
||||
}
|
||||
} // end namespace vtkm::benchmarking
|
||||
|
||||
VTKM_BENCHMARK(BenchRayTracing);
|
||||
|
||||
} // end namespace vtkm::benchmarking
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
auto opts =
|
||||
vtkm::cont::InitializeOptions::DefaultAnyDevice | vtkm::cont::InitializeOptions::Strict;
|
||||
auto config = vtkm::cont::Initialize(argc, argv, opts);
|
||||
// Parse VTK-m options:
|
||||
auto opts = vtkm::cont::InitializeOptions::RequireDevice | vtkm::cont::InitializeOptions::AddHelp;
|
||||
Config = vtkm::cont::Initialize(argc, argv, opts);
|
||||
|
||||
VTKM_RUN_BENCHMARK(RayTracing, vtkm::ListTagBase<vtkm::Float32>(), config.Device);
|
||||
return 0;
|
||||
// Setup device:
|
||||
vtkm::cont::GetRuntimeDeviceTracker().ForceDevice(Config.Device);
|
||||
|
||||
// handle benchmarking related args and run benchmarks:
|
||||
VTKM_EXECUTE_BENCHMARKS(argc, argv);
|
||||
}
|
||||
|
@ -7,40 +7,37 @@
|
||||
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
// PURPOSE. See the above copyright notice for more information.
|
||||
//============================================================================
|
||||
|
||||
#include "Benchmarker.h"
|
||||
|
||||
#include <vtkm/Math.h>
|
||||
#include <vtkm/VectorAnalysis.h>
|
||||
|
||||
#include <vtkm/cont/ArrayHandle.h>
|
||||
#include <vtkm/cont/CellSetStructured.h>
|
||||
#include <vtkm/cont/Invoker.h>
|
||||
#include <vtkm/cont/Timer.h>
|
||||
|
||||
#include <vtkm/worklet/DispatcherMapField.h>
|
||||
#include <vtkm/worklet/DispatcherMapTopology.h>
|
||||
#include <vtkm/worklet/WorkletMapField.h>
|
||||
#include <vtkm/worklet/WorkletMapTopology.h>
|
||||
|
||||
#include "Benchmarker.h"
|
||||
#include <vtkm/cont/testing/Testing.h>
|
||||
|
||||
#include <cctype>
|
||||
#include <random>
|
||||
#include <string>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace benchmarking
|
||||
namespace
|
||||
{
|
||||
|
||||
#define CUBE_SIZE 256
|
||||
static const std::string DIVIDER(40, '-');
|
||||
|
||||
enum BenchmarkName
|
||||
{
|
||||
CELL_TO_POINT = 1 << 1,
|
||||
POINT_TO_CELL = 1 << 2,
|
||||
MC_CLASSIFY = 1 << 3,
|
||||
ALL = CELL_TO_POINT | POINT_TO_CELL | MC_CLASSIFY
|
||||
};
|
||||
using ValueTypes = vtkm::List<vtkm::UInt32, vtkm::Int32, vtkm::Int64, vtkm::Float32, vtkm::Float64>;
|
||||
|
||||
using ValueVariantHandle = vtkm::cont::VariantArrayHandleBase<ValueTypes>;
|
||||
|
||||
// Hold configuration state (e.g. active device)
|
||||
vtkm::cont::InitializeResult Config;
|
||||
|
||||
class AveragePointToCell : public vtkm::worklet::WorkletVisitCellsWithPoints
|
||||
{
|
||||
@ -118,376 +115,277 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
struct ValueTypes
|
||||
: vtkm::ListTagBase<vtkm::UInt32, vtkm::Int32, vtkm::Int64, vtkm::Float32, vtkm::Float64>
|
||||
template <typename T, typename Enable = void>
|
||||
struct NumberGenerator
|
||||
{
|
||||
};
|
||||
|
||||
/// This class runs a series of micro-benchmarks to measure
|
||||
/// performance of different field operations
|
||||
class BenchmarkTopologyAlgorithms
|
||||
template <typename T>
|
||||
struct NumberGenerator<T, typename std::enable_if<std::is_floating_point<T>::value>::type>
|
||||
{
|
||||
using StorageTag = vtkm::cont::StorageTagBasic;
|
||||
|
||||
using Timer = vtkm::cont::Timer;
|
||||
|
||||
using ValueVariantHandle = vtkm::cont::VariantArrayHandleBase<ValueTypes>;
|
||||
|
||||
private:
|
||||
template <typename T, typename Enable = void>
|
||||
struct NumberGenerator
|
||||
std::mt19937 rng;
|
||||
std::uniform_real_distribution<T> distribution;
|
||||
NumberGenerator(T low, T high)
|
||||
: rng()
|
||||
, distribution(low, high)
|
||||
{
|
||||
};
|
||||
}
|
||||
T next() { return distribution(rng); }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct NumberGenerator<T, typename std::enable_if<std::is_floating_point<T>::value>::type>
|
||||
template <typename T>
|
||||
struct NumberGenerator<T, typename std::enable_if<!std::is_floating_point<T>::value>::type>
|
||||
{
|
||||
std::mt19937 rng;
|
||||
std::uniform_int_distribution<T> distribution;
|
||||
|
||||
NumberGenerator(T low, T high)
|
||||
: rng()
|
||||
, distribution(low, high)
|
||||
{
|
||||
std::mt19937 rng;
|
||||
std::uniform_real_distribution<T> distribution;
|
||||
NumberGenerator(T low, T high)
|
||||
: rng()
|
||||
, distribution(low, high)
|
||||
{
|
||||
}
|
||||
T next() { return distribution(rng); }
|
||||
};
|
||||
}
|
||||
T next() { return distribution(rng); }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct NumberGenerator<T, typename std::enable_if<!std::is_floating_point<T>::value>::type>
|
||||
// Returns an extra random value.
|
||||
// Like, an additional random value.
|
||||
// Not a random value that's somehow "extra random".
|
||||
template <typename ArrayT>
|
||||
VTKM_CONT typename ArrayT::ValueType FillRandomValues(ArrayT& array,
|
||||
vtkm::Id size,
|
||||
vtkm::Float64 min,
|
||||
vtkm::Float64 max)
|
||||
{
|
||||
using ValueType = typename ArrayT::ValueType;
|
||||
|
||||
NumberGenerator<ValueType> generator{ static_cast<ValueType>(min), static_cast<ValueType>(max) };
|
||||
array.Allocate(size);
|
||||
auto portal = array.WritePortal();
|
||||
for (vtkm::Id i = 0; i < size; ++i)
|
||||
{
|
||||
std::mt19937 rng;
|
||||
std::uniform_int_distribution<T> distribution;
|
||||
portal.Set(i, generator.next());
|
||||
}
|
||||
return generator.next();
|
||||
}
|
||||
|
||||
NumberGenerator(T low, T high)
|
||||
: rng()
|
||||
, distribution(low, high)
|
||||
{
|
||||
}
|
||||
T next() { return distribution(rng); }
|
||||
};
|
||||
template <typename Value>
|
||||
struct BenchCellToPointAvgImpl
|
||||
{
|
||||
vtkm::cont::ArrayHandle<Value> Input;
|
||||
|
||||
template <typename Value, typename DeviceAdapter>
|
||||
struct BenchCellToPointAvg
|
||||
::benchmark::State& State;
|
||||
vtkm::Id CubeSize;
|
||||
vtkm::Id NumCells;
|
||||
|
||||
vtkm::cont::Timer Timer;
|
||||
vtkm::cont::Invoker Invoker;
|
||||
|
||||
VTKM_CONT
|
||||
BenchCellToPointAvgImpl(::benchmark::State& state)
|
||||
: State{ state }
|
||||
, CubeSize{ CUBE_SIZE }
|
||||
, NumCells{ (this->CubeSize - 1) * (this->CubeSize - 1) * (this->CubeSize - 1) }
|
||||
, Timer{ Config.Device }
|
||||
, Invoker{ Config.Device }
|
||||
{
|
||||
std::vector<Value> input;
|
||||
vtkm::cont::ArrayHandle<Value, StorageTag> InputHandle;
|
||||
std::size_t DomainSize;
|
||||
FillRandomValues(this->Input, this->NumCells, 1., 100.);
|
||||
|
||||
VTKM_CONT
|
||||
BenchCellToPointAvg()
|
||||
{
|
||||
NumberGenerator<Value> generator(static_cast<Value>(1.0), static_cast<Value>(100.0));
|
||||
//cube size is points in each dim
|
||||
this->DomainSize = (CUBE_SIZE - 1) * (CUBE_SIZE - 1) * (CUBE_SIZE - 1);
|
||||
this->input.resize(DomainSize);
|
||||
for (std::size_t i = 0; i < DomainSize; ++i)
|
||||
{
|
||||
this->input[i] = generator.next();
|
||||
}
|
||||
this->InputHandle = vtkm::cont::make_ArrayHandle(this->input);
|
||||
{ // Configure label:
|
||||
std::ostringstream desc;
|
||||
desc << "CubeSize:" << this->CubeSize;
|
||||
this->State.SetLabel(desc.str());
|
||||
}
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
vtkm::Float64 operator()()
|
||||
{
|
||||
vtkm::cont::CellSetStructured<3> cellSet;
|
||||
cellSet.SetPointDimensions(vtkm::Id3(CUBE_SIZE, CUBE_SIZE, CUBE_SIZE));
|
||||
vtkm::cont::ArrayHandle<Value, StorageTag> result;
|
||||
|
||||
Timer timer{ DeviceAdapter() };
|
||||
timer.Start();
|
||||
|
||||
vtkm::worklet::DispatcherMapTopology<AverageCellToPoint> dispatcher;
|
||||
dispatcher.Invoke(this->InputHandle, cellSet, result);
|
||||
|
||||
return timer.GetElapsedTime();
|
||||
}
|
||||
|
||||
virtual std::string Type() const { return std::string("Static"); }
|
||||
|
||||
VTKM_CONT
|
||||
std::string Description() const
|
||||
{
|
||||
|
||||
std::stringstream description;
|
||||
description << "Computing Cell To Point Average "
|
||||
<< "[" << this->Type() << "] "
|
||||
<< "with a domain size of: " << this->DomainSize;
|
||||
return description.str();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Value, typename DeviceAdapter>
|
||||
struct BenchCellToPointAvgDynamic : public BenchCellToPointAvg<Value, DeviceAdapter>
|
||||
template <typename BenchArrayType>
|
||||
VTKM_CONT void Run(const BenchArrayType& input)
|
||||
{
|
||||
vtkm::cont::CellSetStructured<3> cellSet;
|
||||
cellSet.SetPointDimensions(vtkm::Id3{ this->CubeSize, this->CubeSize, this->CubeSize });
|
||||
vtkm::cont::ArrayHandle<Value> result;
|
||||
|
||||
VTKM_CONT
|
||||
vtkm::Float64 operator()()
|
||||
for (auto _ : this->State)
|
||||
{
|
||||
vtkm::cont::CellSetStructured<3> cellSet;
|
||||
cellSet.SetPointDimensions(vtkm::Id3(CUBE_SIZE, CUBE_SIZE, CUBE_SIZE));
|
||||
(void)_;
|
||||
this->Timer.Start();
|
||||
this->Invoker(AverageCellToPoint{}, input, cellSet, result);
|
||||
this->Timer.Stop();
|
||||
|
||||
ValueVariantHandle dinput(this->InputHandle);
|
||||
vtkm::cont::ArrayHandle<Value, StorageTag> result;
|
||||
|
||||
Timer timer{ DeviceAdapter() };
|
||||
timer.Start();
|
||||
|
||||
vtkm::worklet::DispatcherMapTopology<AverageCellToPoint> dispatcher;
|
||||
dispatcher.Invoke(dinput, cellSet, result);
|
||||
|
||||
return timer.GetElapsedTime();
|
||||
this->State.SetIterationTime(this->Timer.GetElapsedTime());
|
||||
}
|
||||
|
||||
virtual std::string Type() const { return std::string("Dynamic"); }
|
||||
};
|
||||
|
||||
VTKM_MAKE_BENCHMARK(CellToPointAvg, BenchCellToPointAvg);
|
||||
VTKM_MAKE_BENCHMARK(CellToPointAvgDynamic, BenchCellToPointAvgDynamic);
|
||||
|
||||
template <typename Value, typename DeviceAdapter>
|
||||
struct BenchPointToCellAvg
|
||||
{
|
||||
std::vector<Value> input;
|
||||
vtkm::cont::ArrayHandle<Value, StorageTag> InputHandle;
|
||||
std::size_t DomainSize;
|
||||
|
||||
VTKM_CONT
|
||||
BenchPointToCellAvg()
|
||||
{
|
||||
NumberGenerator<Value> generator(static_cast<Value>(1.0), static_cast<Value>(100.0));
|
||||
|
||||
this->DomainSize = (CUBE_SIZE) * (CUBE_SIZE) * (CUBE_SIZE);
|
||||
this->input.resize(DomainSize);
|
||||
for (std::size_t i = 0; i < DomainSize; ++i)
|
||||
{
|
||||
this->input[i] = generator.next();
|
||||
}
|
||||
this->InputHandle = vtkm::cont::make_ArrayHandle(this->input);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
vtkm::Float64 operator()()
|
||||
{
|
||||
vtkm::cont::CellSetStructured<3> cellSet;
|
||||
cellSet.SetPointDimensions(vtkm::Id3(CUBE_SIZE, CUBE_SIZE, CUBE_SIZE));
|
||||
vtkm::cont::ArrayHandle<Value, StorageTag> result;
|
||||
|
||||
Timer timer{ DeviceAdapter() };
|
||||
timer.Start();
|
||||
|
||||
vtkm::worklet::DispatcherMapTopology<AveragePointToCell> dispatcher;
|
||||
dispatcher.Invoke(this->InputHandle, cellSet, result);
|
||||
|
||||
return timer.GetElapsedTime();
|
||||
}
|
||||
|
||||
virtual std::string Type() const { return std::string("Static"); }
|
||||
|
||||
VTKM_CONT
|
||||
std::string Description() const
|
||||
{
|
||||
|
||||
std::stringstream description;
|
||||
description << "Computing Point To Cell Average "
|
||||
<< "[" << this->Type() << "] "
|
||||
<< "with a domain size of: " << this->DomainSize;
|
||||
return description.str();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Value, typename DeviceAdapter>
|
||||
struct BenchPointToCellAvgDynamic : public BenchPointToCellAvg<Value, DeviceAdapter>
|
||||
{
|
||||
|
||||
VTKM_CONT
|
||||
vtkm::Float64 operator()()
|
||||
{
|
||||
vtkm::cont::CellSetStructured<3> cellSet;
|
||||
cellSet.SetPointDimensions(vtkm::Id3(CUBE_SIZE, CUBE_SIZE, CUBE_SIZE));
|
||||
|
||||
ValueVariantHandle dinput(this->InputHandle);
|
||||
vtkm::cont::ArrayHandle<Value, StorageTag> result;
|
||||
|
||||
Timer timer{ DeviceAdapter() };
|
||||
timer.Start();
|
||||
|
||||
vtkm::worklet::DispatcherMapTopology<AveragePointToCell> dispatcher;
|
||||
dispatcher.Invoke(dinput, cellSet, result);
|
||||
|
||||
return timer.GetElapsedTime();
|
||||
}
|
||||
|
||||
virtual std::string Type() const { return std::string("Dynamic"); }
|
||||
};
|
||||
|
||||
VTKM_MAKE_BENCHMARK(PointToCellAvg, BenchPointToCellAvg);
|
||||
VTKM_MAKE_BENCHMARK(PointToCellAvgDynamic, BenchPointToCellAvgDynamic);
|
||||
|
||||
template <typename Value, typename DeviceAdapter>
|
||||
struct BenchClassification
|
||||
{
|
||||
std::vector<Value> input;
|
||||
vtkm::cont::ArrayHandle<Value, StorageTag> InputHandle;
|
||||
Value IsoValue;
|
||||
size_t DomainSize;
|
||||
|
||||
VTKM_CONT
|
||||
BenchClassification()
|
||||
{
|
||||
NumberGenerator<Value> generator(static_cast<Value>(1.0), static_cast<Value>(100.0));
|
||||
|
||||
this->DomainSize = (CUBE_SIZE) * (CUBE_SIZE) * (CUBE_SIZE);
|
||||
this->input.resize(DomainSize);
|
||||
for (std::size_t i = 0; i < DomainSize; ++i)
|
||||
{
|
||||
this->input[i] = generator.next();
|
||||
}
|
||||
this->InputHandle = vtkm::cont::make_ArrayHandle(this->input);
|
||||
this->IsoValue = generator.next();
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
vtkm::Float64 operator()()
|
||||
{
|
||||
vtkm::cont::CellSetStructured<3> cellSet;
|
||||
cellSet.SetPointDimensions(vtkm::Id3(CUBE_SIZE, CUBE_SIZE, CUBE_SIZE));
|
||||
vtkm::cont::ArrayHandle<vtkm::IdComponent, StorageTag> result;
|
||||
|
||||
ValueVariantHandle dinput(this->InputHandle);
|
||||
|
||||
Timer timer{ DeviceAdapter() };
|
||||
timer.Start();
|
||||
|
||||
Classification<Value> worklet(this->IsoValue);
|
||||
vtkm::worklet::DispatcherMapTopology<Classification<Value>> dispatcher(worklet);
|
||||
dispatcher.Invoke(dinput, cellSet, result);
|
||||
|
||||
return timer.GetElapsedTime();
|
||||
}
|
||||
|
||||
virtual std::string Type() const { return std::string("Static"); }
|
||||
|
||||
VTKM_CONT
|
||||
std::string Description() const
|
||||
{
|
||||
|
||||
std::stringstream description;
|
||||
description << "Computing Marching Cubes Classification "
|
||||
<< "[" << this->Type() << "] "
|
||||
<< "with a domain size of: " << this->DomainSize;
|
||||
return description.str();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Value, typename DeviceAdapter>
|
||||
struct BenchClassificationDynamic : public BenchClassification<Value, DeviceAdapter>
|
||||
{
|
||||
VTKM_CONT
|
||||
vtkm::Float64 operator()()
|
||||
{
|
||||
vtkm::cont::CellSetStructured<3> cellSet;
|
||||
cellSet.SetPointDimensions(vtkm::Id3(CUBE_SIZE, CUBE_SIZE, CUBE_SIZE));
|
||||
vtkm::cont::ArrayHandle<vtkm::IdComponent, StorageTag> result;
|
||||
|
||||
Timer timer{ DeviceAdapter() };
|
||||
timer.Start();
|
||||
|
||||
Classification<Value> worklet(this->IsoValue);
|
||||
vtkm::worklet::DispatcherMapTopology<Classification<Value>> dispatcher(worklet);
|
||||
dispatcher.Invoke(this->InputHandle, cellSet, result);
|
||||
|
||||
timer.Stop();
|
||||
return timer.GetElapsedTime();
|
||||
}
|
||||
|
||||
virtual std::string Type() const { return std::string("Dynamic"); }
|
||||
};
|
||||
|
||||
VTKM_MAKE_BENCHMARK(Classification, BenchClassification);
|
||||
VTKM_MAKE_BENCHMARK(ClassificationDynamic, BenchClassificationDynamic);
|
||||
|
||||
public:
|
||||
static VTKM_CONT int Run(int benchmarks, vtkm::cont::DeviceAdapterId id)
|
||||
{
|
||||
std::cout << DIVIDER << "\nRunning Topology Algorithm benchmarks\n";
|
||||
|
||||
if (benchmarks & CELL_TO_POINT)
|
||||
{
|
||||
std::cout << DIVIDER << "\nBenchmarking Cell To Point Average\n";
|
||||
VTKM_RUN_BENCHMARK(CellToPointAvg, ValueTypes(), id);
|
||||
VTKM_RUN_BENCHMARK(CellToPointAvgDynamic, ValueTypes(), id);
|
||||
}
|
||||
|
||||
if (benchmarks & POINT_TO_CELL)
|
||||
{
|
||||
std::cout << DIVIDER << "\nBenchmarking Point to Cell Average\n";
|
||||
VTKM_RUN_BENCHMARK(PointToCellAvg, ValueTypes(), id);
|
||||
VTKM_RUN_BENCHMARK(PointToCellAvgDynamic, ValueTypes(), id);
|
||||
}
|
||||
|
||||
if (benchmarks & MC_CLASSIFY)
|
||||
{
|
||||
std::cout << DIVIDER << "\nBenchmarking Hex/Voxel MC Classification\n";
|
||||
VTKM_RUN_BENCHMARK(Classification, ValueTypes(), id);
|
||||
VTKM_RUN_BENCHMARK(ClassificationDynamic, ValueTypes(), id);
|
||||
}
|
||||
|
||||
return 0;
|
||||
// #items = #points
|
||||
const int64_t iterations = static_cast<int64_t>(this->State.iterations());
|
||||
this->State.SetItemsProcessed(static_cast<int64_t>(cellSet.GetNumberOfPoints()) * iterations);
|
||||
}
|
||||
};
|
||||
|
||||
#undef ARRAY_SIZE
|
||||
}
|
||||
} // namespace vtkm::benchmarking
|
||||
template <typename ValueType>
|
||||
void BenchCellToPointAvgStatic(::benchmark::State& state)
|
||||
{
|
||||
BenchCellToPointAvgImpl<ValueType> impl{ state };
|
||||
impl.Run(impl.Input);
|
||||
};
|
||||
VTKM_BENCHMARK_TEMPLATES(BenchCellToPointAvgStatic, ValueTypes);
|
||||
|
||||
template <typename ValueType>
|
||||
void BenchCellToPointAvgDynamic(::benchmark::State& state)
|
||||
{
|
||||
BenchCellToPointAvgImpl<ValueType> impl{ state };
|
||||
impl.Run(ValueVariantHandle{ impl.Input });
|
||||
};
|
||||
VTKM_BENCHMARK_TEMPLATES(BenchCellToPointAvgDynamic, ValueTypes);
|
||||
|
||||
template <typename Value>
|
||||
struct BenchPointToCellAvgImpl
|
||||
{
|
||||
vtkm::cont::ArrayHandle<Value> Input;
|
||||
|
||||
::benchmark::State& State;
|
||||
vtkm::Id CubeSize;
|
||||
vtkm::Id NumPoints;
|
||||
|
||||
vtkm::cont::Timer Timer;
|
||||
vtkm::cont::Invoker Invoker;
|
||||
|
||||
VTKM_CONT
|
||||
BenchPointToCellAvgImpl(::benchmark::State& state)
|
||||
: State{ state }
|
||||
, CubeSize{ CUBE_SIZE }
|
||||
, NumPoints{ (this->CubeSize) * (this->CubeSize) * (this->CubeSize) }
|
||||
, Timer{ Config.Device }
|
||||
, Invoker{ Config.Device }
|
||||
{
|
||||
FillRandomValues(this->Input, this->NumPoints, 1., 100.);
|
||||
|
||||
{ // Configure label:
|
||||
std::ostringstream desc;
|
||||
desc << "CubeSize:" << this->CubeSize;
|
||||
this->State.SetLabel(desc.str());
|
||||
}
|
||||
}
|
||||
|
||||
template <typename BenchArrayType>
|
||||
VTKM_CONT void Run(const BenchArrayType& input)
|
||||
{
|
||||
vtkm::cont::CellSetStructured<3> cellSet;
|
||||
cellSet.SetPointDimensions(vtkm::Id3{ this->CubeSize, this->CubeSize, this->CubeSize });
|
||||
vtkm::cont::ArrayHandle<Value> result;
|
||||
|
||||
for (auto _ : this->State)
|
||||
{
|
||||
(void)_;
|
||||
this->Timer.Start();
|
||||
this->Invoker(AveragePointToCell{}, input, cellSet, result);
|
||||
this->Timer.Stop();
|
||||
|
||||
this->State.SetIterationTime(this->Timer.GetElapsedTime());
|
||||
}
|
||||
|
||||
// #items = #cells
|
||||
const int64_t iterations = static_cast<int64_t>(this->State.iterations());
|
||||
this->State.SetItemsProcessed(static_cast<int64_t>(cellSet.GetNumberOfCells()) * iterations);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ValueType>
|
||||
void BenchPointToCellAvgStatic(::benchmark::State& state)
|
||||
{
|
||||
BenchPointToCellAvgImpl<ValueType> impl{ state };
|
||||
impl.Run(impl.Input);
|
||||
};
|
||||
VTKM_BENCHMARK_TEMPLATES(BenchPointToCellAvgStatic, ValueTypes);
|
||||
|
||||
template <typename ValueType>
|
||||
void BenchPointToCellAvgDynamic(::benchmark::State& state)
|
||||
{
|
||||
BenchPointToCellAvgImpl<ValueType> impl{ state };
|
||||
impl.Run(ValueVariantHandle{ impl.Input });
|
||||
};
|
||||
VTKM_BENCHMARK_TEMPLATES(BenchPointToCellAvgDynamic, ValueTypes);
|
||||
|
||||
template <typename Value>
|
||||
struct BenchClassificationImpl
|
||||
{
|
||||
vtkm::cont::ArrayHandle<Value> Input;
|
||||
|
||||
::benchmark::State& State;
|
||||
vtkm::Id CubeSize;
|
||||
vtkm::Id DomainSize;
|
||||
Value IsoValue;
|
||||
|
||||
vtkm::cont::Timer Timer;
|
||||
vtkm::cont::Invoker Invoker;
|
||||
|
||||
VTKM_CONT
|
||||
BenchClassificationImpl(::benchmark::State& state)
|
||||
: State{ state }
|
||||
, CubeSize{ CUBE_SIZE }
|
||||
, DomainSize{ this->CubeSize * this->CubeSize * this->CubeSize }
|
||||
, Timer{ Config.Device }
|
||||
, Invoker{ Config.Device }
|
||||
{
|
||||
this->IsoValue = FillRandomValues(this->Input, this->DomainSize, 1., 100.);
|
||||
|
||||
{ // Configure label:
|
||||
std::ostringstream desc;
|
||||
desc << "CubeSize:" << this->CubeSize;
|
||||
this->State.SetLabel(desc.str());
|
||||
}
|
||||
}
|
||||
|
||||
template <typename BenchArrayType>
|
||||
VTKM_CONT void Run(const BenchArrayType& input)
|
||||
{
|
||||
vtkm::cont::CellSetStructured<3> cellSet;
|
||||
cellSet.SetPointDimensions(vtkm::Id3{ this->CubeSize, this->CubeSize, this->CubeSize });
|
||||
vtkm::cont::ArrayHandle<vtkm::IdComponent> result;
|
||||
|
||||
Classification<Value> worklet(this->IsoValue);
|
||||
|
||||
for (auto _ : this->State)
|
||||
{
|
||||
(void)_;
|
||||
this->Timer.Start();
|
||||
this->Invoker(worklet, input, cellSet, result);
|
||||
this->Timer.Stop();
|
||||
|
||||
this->State.SetIterationTime(this->Timer.GetElapsedTime());
|
||||
}
|
||||
|
||||
// #items = #cells
|
||||
const int64_t iterations = static_cast<int64_t>(this->State.iterations());
|
||||
this->State.SetItemsProcessed(static_cast<int64_t>(cellSet.GetNumberOfCells()) * iterations);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ValueType>
|
||||
void BenchClassificationStatic(::benchmark::State& state)
|
||||
{
|
||||
BenchClassificationImpl<ValueType> impl{ state };
|
||||
impl.Run(impl.Input);
|
||||
};
|
||||
VTKM_BENCHMARK_TEMPLATES(BenchClassificationStatic, ValueTypes);
|
||||
|
||||
template <typename ValueType>
|
||||
void BenchClassificationDynamic(::benchmark::State& state)
|
||||
{
|
||||
BenchClassificationImpl<ValueType> impl{ state };
|
||||
impl.Run(ValueVariantHandle{ impl.Input });
|
||||
};
|
||||
VTKM_BENCHMARK_TEMPLATES(BenchClassificationDynamic, ValueTypes);
|
||||
|
||||
} // end anon namespace
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
auto opts = vtkm::cont::InitializeOptions::DefaultAnyDevice;
|
||||
auto config = vtkm::cont::Initialize(argc, argv, opts);
|
||||
// Parse VTK-m options:
|
||||
auto opts = vtkm::cont::InitializeOptions::RequireDevice | vtkm::cont::InitializeOptions::AddHelp;
|
||||
Config = vtkm::cont::Initialize(argc, argv, opts);
|
||||
|
||||
int benchmarks = 0;
|
||||
if (argc <= 1)
|
||||
{
|
||||
benchmarks = vtkm::benchmarking::ALL;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 1; i < argc; ++i)
|
||||
{
|
||||
std::string arg = argv[i];
|
||||
std::transform(arg.begin(), arg.end(), arg.begin(), [](char c) {
|
||||
return static_cast<char>(std::tolower(static_cast<unsigned char>(c)));
|
||||
});
|
||||
if (arg == "celltopoint")
|
||||
{
|
||||
benchmarks |= vtkm::benchmarking::CELL_TO_POINT;
|
||||
}
|
||||
else if (arg == "pointtocell")
|
||||
{
|
||||
benchmarks |= vtkm::benchmarking::POINT_TO_CELL;
|
||||
}
|
||||
else if (arg == "classify")
|
||||
{
|
||||
benchmarks |= vtkm::benchmarking::MC_CLASSIFY;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Unrecognized benchmark: " << argv[i] << std::endl;
|
||||
std::cerr << "USAGE: " << argv[0] << " [options] [<benchmarks>]" << std::endl;
|
||||
std::cerr << "Options are: " << std::endl;
|
||||
std::cerr << config.Usage << std::endl;
|
||||
std::cerr << "Benchmarks are one or more of the following:" << std::endl;
|
||||
std::cerr << " CellToPoint\tFind average of point data on each cell" << std::endl;
|
||||
std::cerr << " PointToCell\tFind average of cell data on each point" << std::endl;
|
||||
std::cerr << " Classify\tFind Marching Cube case of each cell" << std::endl;
|
||||
std::cerr << "If no benchmarks are specified, all are run." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Setup device:
|
||||
vtkm::cont::GetRuntimeDeviceTracker().ForceDevice(Config.Device);
|
||||
|
||||
//now actually execute the benchmarks
|
||||
|
||||
return vtkm::benchmarking::BenchmarkTopologyAlgorithms::Run(benchmarks, config.Device);
|
||||
// handle benchmarking related args and run benchmarks:
|
||||
VTKM_EXECUTE_BENCHMARKS(argc, argv);
|
||||
}
|
||||
|
@ -11,331 +11,385 @@
|
||||
#ifndef vtk_m_benchmarking_Benchmarker_h
|
||||
#define vtk_m_benchmarking_Benchmarker_h
|
||||
|
||||
#include <vtkm/ListTag.h>
|
||||
#include <vtkm/Math.h>
|
||||
#include <vtkm/cont/DeviceAdapterTag.h>
|
||||
#include <vtkm/cont/TryExecute.h>
|
||||
#include <vtkm/cont/RuntimeDeviceTracker.h>
|
||||
#include <vtkm/cont/Timer.h>
|
||||
|
||||
#include <vtkm/cont/testing/Testing.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <vtkm/internal/brigand.hpp>
|
||||
|
||||
/*
|
||||
* Writing a Benchmark
|
||||
* -------------------
|
||||
* To write a benchmark you must provide a functor that will run the operations
|
||||
* you want to time and return the run time of those operations using the timer
|
||||
* for the device. The benchmark should also be templated on the value type being
|
||||
* operated on. Then use VTKM_MAKE_BENCHMARK to generate a maker functor and
|
||||
* VTKM_RUN_BENCHMARK to run the benchmark on a list of types.
|
||||
*
|
||||
* For Example:
|
||||
*
|
||||
* template<typename Value>
|
||||
* struct BenchSilly {
|
||||
* // Setup anything that doesn't need to change per run in the constructor
|
||||
* VTKM_CONT BenchSilly(){}
|
||||
*
|
||||
* // The overloaded call operator will run the operations being timed and
|
||||
* // return the execution time
|
||||
* VTKM_CONT
|
||||
* vtkm::Float64 operator()(){
|
||||
* return 0.05;
|
||||
* }
|
||||
*
|
||||
* // The benchmark must also provide a method describing itself, this is
|
||||
* // used when printing out run time statistics
|
||||
* VTKM_CONT
|
||||
* std::string Description() const {
|
||||
* return "A silly benchmark";
|
||||
* }
|
||||
* };
|
||||
*
|
||||
* // Now use the VTKM_MAKE_BENCHMARK macro to generate a maker functor for
|
||||
* // your benchmark. This lets us generate the benchmark functor for each type
|
||||
* // we want to test
|
||||
* VTKM_MAKE_BENCHMARK(Silly, BenchSilly);
|
||||
*
|
||||
* // You can also optionally pass arguments to the constructor like so:
|
||||
* // VTKM_MAKE_BENCHMARK(Blah, BenchBlah, 1, 2, 3);
|
||||
* // Note that benchmark names (the first argument) must be unique so different
|
||||
* // parameters to the constructor should have different names
|
||||
*
|
||||
* // We can now run our benchmark using VTKM_RUN_BENCHMARK, passing the
|
||||
* // benchmark name and type list to run on
|
||||
* int main(int, char**){
|
||||
* VTKM_RUN_BENCHMARK(Silly, vtkm::ListTagBase<vtkm::Float32>());
|
||||
* return 0;
|
||||
* }
|
||||
*
|
||||
* Check out vtkm/benchmarking/BenchmarkDeviceAdapter.h for some example usage
|
||||
*/
|
||||
#include <benchmark/benchmark.h>
|
||||
|
||||
/*
|
||||
* Use the VTKM_MAKE_BENCHMARK macro to define a maker functor for your benchmark.
|
||||
* This is used to allow you to template the benchmark functor on the type being benchmarked
|
||||
* and the device adapter so you can write init code in the constructor. Then the maker will
|
||||
* return a constructed instance of your benchmark for the type being benchmarked.
|
||||
* The VA_ARGS are used to pass any extra arguments needed by your benchmark
|
||||
*/
|
||||
#define VTKM_MAKE_BENCHMARK(Name, Bench, ...) \
|
||||
struct MakeBench##Name \
|
||||
{ \
|
||||
template <typename Value, typename DeviceAdapter> \
|
||||
VTKM_CONT Bench<Value, DeviceAdapter> operator()(const Value vtkmNotUsed(v), \
|
||||
DeviceAdapter vtkmNotUsed(id)) const \
|
||||
{ \
|
||||
return Bench<Value, DeviceAdapter>(__VA_ARGS__); \
|
||||
} \
|
||||
}
|
||||
#include <ostream>
|
||||
|
||||
/*
|
||||
* Use the VTKM_RUN_BENCHMARK macro to run your benchmark on the type list passed.
|
||||
* You must have previously defined a maker functor with VTKM_MAKE_BENCHMARK that this
|
||||
* macro will look for and use
|
||||
*/
|
||||
#define VTKM_RUN_BENCHMARK(Name, Types, Id) \
|
||||
vtkm::benchmarking::BenchmarkTypes(MakeBench##Name(), (Types), (Id))
|
||||
/// \file Benchmarker.h
|
||||
/// \brief Benchmarking utilities
|
||||
///
|
||||
/// VTK-m's benchmarking framework is built on top of Google Benchmark.
|
||||
///
|
||||
/// A benchmark is now a single function, which is passed to a macro:
|
||||
///
|
||||
/// ```
|
||||
/// void MyBenchmark(::benchmark::State& state)
|
||||
/// {
|
||||
/// MyClass someClass;
|
||||
///
|
||||
/// // Optional: Add a descriptive label with additional benchmark details:
|
||||
/// state.SetLabel("Blah blah blah.");
|
||||
///
|
||||
/// // Must use a vtkm timer to properly capture eg. CUDA execution times.
|
||||
/// vtkm::cont::Timer timer;
|
||||
/// for (auto _ : state)
|
||||
/// {
|
||||
/// someClass.Reset();
|
||||
///
|
||||
/// timer.Start();
|
||||
/// someClass.DoWork();
|
||||
/// timer.Stop();
|
||||
///
|
||||
/// state.SetIterationTime(timer.GetElapsedTime());
|
||||
/// }
|
||||
///
|
||||
/// // Optional: Report items and/or bytes processed per iteration in output:
|
||||
/// state.SetItemsProcessed(state.iterations() * someClass.GetNumberOfItems());
|
||||
/// state.SetBytesProcessed(state.iterations() * someClass.GetNumberOfBytes());
|
||||
/// }
|
||||
/// }
|
||||
/// VTKM_BENCHMARK(MyBenchmark);
|
||||
/// ```
|
||||
///
|
||||
/// Google benchmark also makes it easy to implement parameter sweep benchmarks:
|
||||
///
|
||||
/// ```
|
||||
/// void MyParameterSweep(::benchmark::State& state)
|
||||
/// {
|
||||
/// // The current value in the sweep:
|
||||
/// const vtkm::Id currentValue = state.range(0);
|
||||
///
|
||||
/// MyClass someClass;
|
||||
/// someClass.SetSomeParameter(currentValue);
|
||||
///
|
||||
/// vtkm::cont::Timer timer;
|
||||
/// for (auto _ : state)
|
||||
/// {
|
||||
/// someClass.Reset();
|
||||
///
|
||||
/// timer.Start();
|
||||
/// someClass.DoWork();
|
||||
/// timer.Stop();
|
||||
///
|
||||
/// state.SetIterationTime(timer.GetElapsedTime());
|
||||
/// }
|
||||
/// }
|
||||
/// VTKM_BENCHMARK_OPTS(MyBenchmark, ->ArgName("Param")->Range(32, 1024 * 1024));
|
||||
/// ```
|
||||
///
|
||||
/// will generate and launch several benchmarks, exploring the parameter space of
|
||||
/// `SetSomeParameter` between the values of 32 and (1024*1024). The chain of
|
||||
/// functions calls in the second argument is applied to an instance of
|
||||
/// ::benchmark::internal::Benchmark. See Google Benchmark's documentation for
|
||||
/// more details.
|
||||
///
|
||||
/// For more complex benchmark configurations, the VTKM_BENCHMARK_APPLY macro
|
||||
/// accepts a function with the signature
|
||||
/// `void Func(::benchmark::internal::Benchmark*)` that may be used to generate
|
||||
/// more complex configurations.
|
||||
///
|
||||
/// To instantiate a templated benchmark across a list of types, the
|
||||
/// VTKM_BENCHMARK_TEMPLATE* macros take a vtkm::List of types as an additional
|
||||
/// parameter. The templated benchmark function will be instantiated and called
|
||||
/// for each type in the list:
|
||||
///
|
||||
/// ```
|
||||
/// template <typename T>
|
||||
/// void MyBenchmark(::benchmark::State& state)
|
||||
/// {
|
||||
/// MyClass<T> someClass;
|
||||
///
|
||||
/// // Must use a vtkm timer to properly capture eg. CUDA execution times.
|
||||
/// vtkm::cont::Timer timer;
|
||||
/// for (auto _ : state)
|
||||
/// {
|
||||
/// someClass.Reset();
|
||||
///
|
||||
/// timer.Start();
|
||||
/// someClass.DoWork();
|
||||
/// timer.Stop();
|
||||
///
|
||||
/// state.SetIterationTime(timer.GetElapsedTime());
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// VTKM_BENCHMARK_TEMPLATE(MyBenchmark, vtkm::List<vtkm::Float32, vtkm::Vec3f_32>);
|
||||
/// ```
|
||||
///
|
||||
/// The benchmarks are executed by calling the `VTKM_EXECUTE_BENCHMARKS(argc, argv)`
|
||||
/// macro from `main`. There is also a `VTKM_EXECUTE_BENCHMARKS_PREAMBLE(argc, argv, some_string)`
|
||||
/// macro that appends the contents of `some_string` to the Google Benchmark preamble.
|
||||
///
|
||||
/// If a benchmark is not compatible with some configuration, it may call
|
||||
/// `state.SkipWithError("Error message");` on the `::benchmark::State` object and return. This is
|
||||
/// useful, for instance in the filter tests when the input is not compatible with the filter.
|
||||
///
|
||||
/// When launching a benchmark executable, the following options are supported by Google Benchmark:
|
||||
///
|
||||
/// - `--benchmark_list_tests`: List all available tests.
|
||||
/// - `--benchmark_filter="[regex]"`: Only run benchmark with names that match `[regex]`.
|
||||
/// - `--benchmark_filter="-[regex]"`: Only run benchmark with names that DON'T match `[regex]`.
|
||||
/// - `--benchmark_min_time=[float]`: Make sure each benchmark repetition gathers `[float]` seconds
|
||||
/// of data.
|
||||
/// - `--benchmark_repetitions=[int]`: Run each benchmark `[int]` times and report aggregate statistics
|
||||
/// (mean, stdev, etc). A "repetition" refers to a single execution of the benchmark function, not
|
||||
/// an "iteration", which is a loop of the `for(auto _:state){...}` section.
|
||||
/// - `--benchmark_report_aggregates_only="true|false"`: If true, only the aggregate statistics are
|
||||
/// reported (affects both console and file output). Requires `--benchmark_repetitions` to be useful.
|
||||
/// - `--benchmark_display_aggregates_only="true|false"`: If true, only the aggregate statistics are
|
||||
/// printed to the terminal. Any file output will still contain all repetition info.
|
||||
/// - `--benchmark_format="console|json|csv"`: Specify terminal output format: human readable
|
||||
/// (`console`) or `csv`/`json` formats.
|
||||
/// - `--benchmark_out_format="console|json|csv"`: Specify file output format: human readable
|
||||
/// (`console`) or `csv`/`json` formats.
|
||||
/// - `--benchmark_out=[filename]`: Specify output file.
|
||||
/// - `--benchmark_color="true|false"`: Toggle color output in terminal when using `console` output.
|
||||
/// - `--benchmark_counters_tabular="true|false"`: Print counter information (e.g. bytes/sec, items/sec)
|
||||
/// in the table, rather than appending them as a label.
|
||||
///
|
||||
/// For more information and examples of practical usage, take a look at the existing benchmarks in
|
||||
/// vtk-m/benchmarking/.
|
||||
|
||||
/// \def VTKM_EXECUTE_BENCHMARKS(argc, argv)
|
||||
///
|
||||
/// Run the benchmarks defined in the current file. Benchmarks may be filtered
|
||||
/// and modified using the passed arguments; see the Google Benchmark documentation
|
||||
/// for more details.
|
||||
#define VTKM_EXECUTE_BENCHMARKS(argc, argv) vtkm::bench::detail::ExecuteBenchmarks(argc, argv)
|
||||
|
||||
/// \def VTKM_EXECUTE_BENCHMARKS_PREAMBLE(argc, argv, preamble)
|
||||
///
|
||||
/// Run the benchmarks defined in the current file. Benchmarks may be filtered
|
||||
/// and modified using the passed arguments; see the Google Benchmark documentation
|
||||
/// for more details. The `preamble` string may be used to supply additional
|
||||
/// information that will be appended to the output's preamble.
|
||||
#define VTKM_EXECUTE_BENCHMARKS_PREAMBLE(argc, argv, preamble) \
|
||||
vtkm::bench::detail::ExecuteBenchmarks(argc, argv, preamble)
|
||||
|
||||
/// \def VTKM_BENCHMARK(BenchFunc)
|
||||
///
|
||||
/// Define a simple benchmark. A single benchmark will be generated that executes
|
||||
/// `BenchFunc`. `BenchFunc` must have the signature:
|
||||
///
|
||||
/// ```
|
||||
/// void BenchFunc(::benchmark::State& state)
|
||||
/// ```
|
||||
#define VTKM_BENCHMARK(BenchFunc) BENCHMARK(BenchFunc)->UseManualTime()
|
||||
|
||||
/// \def VTKM_BENCHMARK_OPTS(BenchFunc, Args)
|
||||
///
|
||||
/// Similar to `VTKM_BENCHMARK`, but allows additional options to be specified
|
||||
/// on the `::benchmark::internal::Benchmark` object. Example usage:
|
||||
///
|
||||
/// ```
|
||||
/// VTKM_BENCHMARK_OPTS(MyBenchmark, ->ArgName("MyParam")->Range(32, 1024*1024));
|
||||
/// ```
|
||||
///
|
||||
/// Note the similarity to the raw Google Benchmark usage of
|
||||
/// `BENCHMARK(MyBenchmark)->ArgName("MyParam")->Range(32, 1024*1024);`. See
|
||||
/// the Google Benchmark documentation for more details on the available options.
|
||||
#define VTKM_BENCHMARK_OPTS(BenchFunc, options) BENCHMARK(BenchFunc)->UseManualTime() options
|
||||
|
||||
/// \def VTKM_BENCHMARK_APPLY(BenchFunc, ConfigFunc)
|
||||
///
|
||||
/// Similar to `VTKM_BENCHMARK`, but allows advanced benchmark configuration
|
||||
/// via a supplied ConfigFunc, similar to Google Benchmark's
|
||||
/// `BENCHMARK(BenchFunc)->Apply(ConfigFunc)`. `ConfigFunc` must have the
|
||||
/// signature:
|
||||
///
|
||||
/// ```
|
||||
/// void ConfigFunc(::benchmark::internal::Benchmark*);
|
||||
/// ```
|
||||
///
|
||||
/// See the Google Benchmark documentation for more details on the available options.
|
||||
#define VTKM_BENCHMARK_APPLY(BenchFunc, applyFunctor) \
|
||||
BENCHMARK(BenchFunc)->Apply(applyFunctor)->UseManualTime()
|
||||
|
||||
/// \def VTKM_BENCHMARK_TEMPLATES(BenchFunc, TypeList)
|
||||
///
|
||||
/// Define a family of benchmark that vary by template argument. A single
|
||||
/// benchmark will be generated for each type in `TypeList` (a vtkm::List of
|
||||
/// types) that executes `BenchFunc<T>`. `BenchFunc` must have the signature:
|
||||
///
|
||||
/// ```
|
||||
/// template <typename T>
|
||||
/// void BenchFunc(::benchmark::State& state)
|
||||
/// ```
|
||||
#define VTKM_BENCHMARK_TEMPLATES(BenchFunc, TypeList) \
|
||||
VTKM_BENCHMARK_TEMPLATES_APPLY(BenchFunc, vtkm::bench::detail::NullApply, TypeList)
|
||||
|
||||
/// \def VTKM_BENCHMARK_TEMPLATES_OPTS(BenchFunc, Args, TypeList)
|
||||
///
|
||||
/// Similar to `VTKM_BENCHMARK_TEMPLATES`, but allows additional options to be specified
|
||||
/// on the `::benchmark::internal::Benchmark` object. Example usage:
|
||||
///
|
||||
/// ```
|
||||
/// VTKM_BENCHMARK_TEMPLATES_OPTS(MyBenchmark,
|
||||
/// ->ArgName("MyParam")->Range(32, 1024*1024),
|
||||
/// vtkm::List<vtkm::Float32, vtkm::Vec3f_32>);
|
||||
/// ```
|
||||
#define VTKM_BENCHMARK_TEMPLATES_OPTS(BenchFunc, options, TypeList) \
|
||||
VTKM_BENCHMARK_TEMPLATES_APPLY( \
|
||||
BenchFunc, [](::benchmark::internal::Benchmark* bm) { bm options; }, TypeList)
|
||||
|
||||
/// \def VTKM_BENCHMARK_TEMPLATES_APPLY(BenchFunc, ConfigFunc, TypeList)
|
||||
///
|
||||
/// Similar to `VTKM_BENCHMARK_TEMPLATES`, but allows advanced benchmark configuration
|
||||
/// via a supplied ConfigFunc, similar to Google Benchmark's
|
||||
/// `BENCHMARK(BenchFunc)->Apply(ConfigFunc)`. `ConfigFunc` must have the
|
||||
/// signature:
|
||||
///
|
||||
/// ```
|
||||
/// void ConfigFunc(::benchmark::internal::Benchmark*);
|
||||
/// ```
|
||||
///
|
||||
/// See the Google Benchmark documentation for more details on the available options.
|
||||
#define VTKM_BENCHMARK_TEMPLATES_APPLY(BenchFunc, ApplyFunctor, TypeList) \
|
||||
namespace \
|
||||
{ /* A template function cannot be used as a template parameter, so wrap the function with \
|
||||
* a template struct to get it into the GenerateTemplateBenchmarks class. */ \
|
||||
template <typename... Ts> \
|
||||
struct VTKM_BENCHMARK_WRAPPER_NAME(BenchFunc) \
|
||||
{ \
|
||||
static ::benchmark::internal::Function* GetFunction() { return BenchFunc<Ts...>; } \
|
||||
}; \
|
||||
} /* end anon namespace */ \
|
||||
int BENCHMARK_PRIVATE_NAME(BenchFunc) = vtkm::bench::detail::GenerateTemplateBenchmarks< \
|
||||
brigand::bind<VTKM_BENCHMARK_WRAPPER_NAME(BenchFunc)>, \
|
||||
TypeList>::Register(#BenchFunc, ApplyFunctor)
|
||||
|
||||
// Internal use only:
|
||||
#define VTKM_BENCHMARK_WRAPPER_NAME(BenchFunc) \
|
||||
BENCHMARK_PRIVATE_CONCAT(_wrapper_, BenchFunc, __LINE__)
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace benchmarking
|
||||
namespace bench
|
||||
{
|
||||
namespace stats
|
||||
namespace detail
|
||||
{
|
||||
// Checks that the sequence is sorted, returns true if it's sorted, false
|
||||
// otherwise
|
||||
template <typename ForwardIt>
|
||||
bool is_sorted(ForwardIt first, ForwardIt last)
|
||||
|
||||
static inline void NullApply(::benchmark::internal::Benchmark*)
|
||||
{
|
||||
ForwardIt next = first;
|
||||
++next;
|
||||
for (; next != last; ++next, ++first)
|
||||
}
|
||||
|
||||
/// Do not use directly. The VTKM_BENCHMARK_TEMPLATES macros should be used
|
||||
/// instead.
|
||||
// TypeLists could be expanded to compute cross products if we ever have that
|
||||
// need.
|
||||
template <typename BoundBench, typename TypeLists>
|
||||
struct GenerateTemplateBenchmarks;
|
||||
|
||||
template <template <typename...> class BenchType, typename TypeList>
|
||||
struct GenerateTemplateBenchmarks<brigand::bind<BenchType>, TypeList>
|
||||
{
|
||||
private:
|
||||
template <typename T>
|
||||
using MakeBenchType = BenchType<T>;
|
||||
|
||||
using Benchmarks = brigand::transform<TypeList, brigand::bind<MakeBenchType, brigand::_1>>;
|
||||
|
||||
template <typename ApplyFunctor>
|
||||
struct RegisterImpl
|
||||
{
|
||||
if (*first > *next)
|
||||
std::string BenchName;
|
||||
ApplyFunctor Apply;
|
||||
|
||||
template <typename P>
|
||||
void operator()(brigand::type_<BenchType<P>>) const
|
||||
{
|
||||
std::ostringstream name;
|
||||
name << this->BenchName << "<" << vtkm::testing::TypeName<P>::Name() << ">";
|
||||
auto bm = ::benchmark::internal::RegisterBenchmarkInternal(
|
||||
new ::benchmark::internal::FunctionBenchmark(name.str().c_str(),
|
||||
BenchType<P>::GetFunction()));
|
||||
this->Apply(bm);
|
||||
|
||||
// Always use manual time with vtkm::cont::Timer to capture CUDA times accurately.
|
||||
bm->UseManualTime();
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
template <typename ApplyFunctor>
|
||||
static int Register(const std::string& benchName, ApplyFunctor&& apply)
|
||||
{
|
||||
brigand::for_each<Benchmarks>(
|
||||
RegisterImpl<ApplyFunctor>{ benchName, std::forward<ApplyFunctor>(apply) });
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
class VTKmConsoleReporter : public ::benchmark::ConsoleReporter
|
||||
{
|
||||
std::string UserPreamble;
|
||||
|
||||
public:
|
||||
VTKmConsoleReporter() = default;
|
||||
|
||||
explicit VTKmConsoleReporter(const std::string& preamble)
|
||||
: UserPreamble{ preamble }
|
||||
{
|
||||
}
|
||||
|
||||
bool ReportContext(const Context& context) override
|
||||
{
|
||||
if (!::benchmark::ConsoleReporter::ReportContext(context))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get the value representing the `percent` percentile of the
|
||||
// sorted samples using linear interpolation
|
||||
vtkm::Float64 PercentileValue(const std::vector<vtkm::Float64>& samples,
|
||||
const vtkm::Float64 percent)
|
||||
{
|
||||
VTKM_ASSERT(!samples.empty());
|
||||
if (samples.size() == 1)
|
||||
{
|
||||
return samples.front();
|
||||
}
|
||||
VTKM_ASSERT(percent >= 0.0);
|
||||
VTKM_ASSERT(percent <= 100.0);
|
||||
VTKM_ASSERT(vtkm::benchmarking::stats::is_sorted(samples.begin(), samples.end()));
|
||||
if (percent == 100.0)
|
||||
{
|
||||
return samples.back();
|
||||
}
|
||||
// Find the two nearest percentile values and linearly
|
||||
// interpolate between them
|
||||
const vtkm::Float64 rank = percent / 100.0 * (static_cast<vtkm::Float64>(samples.size()) - 1.0);
|
||||
const vtkm::Float64 low_rank = vtkm::Floor(rank);
|
||||
const vtkm::Float64 dist = rank - low_rank;
|
||||
const size_t k = static_cast<size_t>(low_rank);
|
||||
const vtkm::Float64 low = samples[k];
|
||||
const vtkm::Float64 high = samples[k + 1];
|
||||
return low + (high - low) * dist;
|
||||
}
|
||||
// Winsorize the samples to clean up any very extreme outliers
|
||||
// Will replace all samples below `percent` and above 100 - `percent` percentiles
|
||||
// with the value at the percentile
|
||||
// NOTE: Assumes the samples have been sorted, as we make use of PercentileValue
|
||||
void Winsorize(std::vector<vtkm::Float64>& samples, const vtkm::Float64 percent)
|
||||
{
|
||||
const vtkm::Float64 low_percentile = PercentileValue(samples, percent);
|
||||
const vtkm::Float64 high_percentile = PercentileValue(samples, 100.0 - percent);
|
||||
for (std::vector<vtkm::Float64>::iterator it = samples.begin(); it != samples.end(); ++it)
|
||||
{
|
||||
if (*it < low_percentile)
|
||||
// The rest of the preamble is printed to the error stream, so be consistent:
|
||||
auto& out = this->GetErrorStream();
|
||||
|
||||
// Print list of devices:
|
||||
out << "VTK-m Device State:\n";
|
||||
vtkm::cont::GetRuntimeDeviceTracker().PrintSummary(out);
|
||||
if (!this->UserPreamble.empty())
|
||||
{
|
||||
*it = low_percentile;
|
||||
out << this->UserPreamble << "\n";
|
||||
}
|
||||
else if (*it > high_percentile)
|
||||
{
|
||||
*it = high_percentile;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Compute the mean value of the dataset
|
||||
vtkm::Float64 Mean(const std::vector<vtkm::Float64>& samples)
|
||||
{
|
||||
vtkm::Float64 mean = 0;
|
||||
for (std::vector<vtkm::Float64>::const_iterator it = samples.begin(); it != samples.end(); ++it)
|
||||
{
|
||||
mean += *it;
|
||||
}
|
||||
return mean / static_cast<vtkm::Float64>(samples.size());
|
||||
}
|
||||
// Compute the sample variance of the samples
|
||||
vtkm::Float64 Variance(const std::vector<vtkm::Float64>& samples)
|
||||
{
|
||||
vtkm::Float64 mean = Mean(samples);
|
||||
vtkm::Float64 square_deviations = 0;
|
||||
for (std::vector<vtkm::Float64>::const_iterator it = samples.begin(); it != samples.end(); ++it)
|
||||
{
|
||||
square_deviations += vtkm::Pow(*it - mean, 2.0);
|
||||
}
|
||||
return square_deviations / (static_cast<vtkm::Float64>(samples.size()) - 1.0);
|
||||
}
|
||||
// Compute the standard deviation of the samples
|
||||
vtkm::Float64 StandardDeviation(const std::vector<vtkm::Float64>& samples)
|
||||
{
|
||||
return vtkm::Sqrt(Variance(samples));
|
||||
}
|
||||
// Compute the median absolute deviation of the dataset
|
||||
vtkm::Float64 MedianAbsDeviation(const std::vector<vtkm::Float64>& samples)
|
||||
{
|
||||
std::vector<vtkm::Float64> abs_deviations;
|
||||
abs_deviations.reserve(samples.size());
|
||||
const vtkm::Float64 median = PercentileValue(samples, 50.0);
|
||||
for (std::vector<vtkm::Float64>::const_iterator it = samples.begin(); it != samples.end(); ++it)
|
||||
{
|
||||
abs_deviations.push_back(vtkm::Abs(*it - median));
|
||||
}
|
||||
std::sort(abs_deviations.begin(), abs_deviations.end());
|
||||
return PercentileValue(abs_deviations, 50.0);
|
||||
}
|
||||
} // stats
|
||||
out.flush();
|
||||
|
||||
/*
|
||||
* The benchmarker takes a functor to benchmark and runs it multiple times,
|
||||
* printing out statistics of the run time at the end.
|
||||
* The functor passed should return the run time of the thing being benchmarked
|
||||
* in seconds, this lets us avoid including any per-run setup time in the benchmark.
|
||||
* However any one-time setup should be done in the functor's constructor
|
||||
*/
|
||||
struct Benchmarker
|
||||
{
|
||||
std::vector<vtkm::Float64> Samples;
|
||||
std::string BenchmarkName;
|
||||
|
||||
const vtkm::Float64 MaxRuntime;
|
||||
const size_t MaxIterations;
|
||||
|
||||
public:
|
||||
VTKM_CONT
|
||||
Benchmarker(vtkm::Float64 maxRuntime = 30, std::size_t maxIterations = 100)
|
||||
: MaxRuntime(maxRuntime)
|
||||
, MaxIterations(maxIterations)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Functor>
|
||||
VTKM_CONT void GatherSamples(Functor func)
|
||||
{
|
||||
this->Samples.clear();
|
||||
this->BenchmarkName = func.Description();
|
||||
|
||||
// Do a warm-up run. If the benchmark allocates any additional memory
|
||||
// eg. storage for output results, this will let it do that and
|
||||
// allow us to avoid measuring the allocation time in the actual benchmark run
|
||||
func();
|
||||
|
||||
this->Samples.reserve(this->MaxIterations);
|
||||
|
||||
// Run each benchmark for MAX_RUNTIME seconds or MAX_ITERATIONS iterations, whichever
|
||||
// takes less time. This kind of assumes that running for 500 iterations or 30s will give
|
||||
// good statistics, but if median abs dev and/or std dev are too high both these limits
|
||||
// could be increased
|
||||
size_t iter = 0;
|
||||
for (vtkm::Float64 elapsed = 0.0; elapsed < this->MaxRuntime && iter < this->MaxIterations;
|
||||
elapsed += this->Samples.back(), ++iter)
|
||||
{
|
||||
this->Samples.push_back(func());
|
||||
}
|
||||
|
||||
std::sort(this->Samples.begin(), this->Samples.end());
|
||||
stats::Winsorize(this->Samples, 5.0);
|
||||
}
|
||||
|
||||
VTKM_CONT void PrintSummary(std::ostream& out = std::cout)
|
||||
{
|
||||
out << "Benchmark \'" << this->BenchmarkName << "\' results:\n";
|
||||
|
||||
if (this->Samples.empty())
|
||||
{
|
||||
out << "\tNo samples gathered!\n";
|
||||
return;
|
||||
}
|
||||
|
||||
out << "\tnumSamples = " << this->Samples.size() << "\n"
|
||||
<< "\tmedian = " << stats::PercentileValue(this->Samples, 50.0) << "s\n"
|
||||
<< "\tmedian abs dev = " << stats::MedianAbsDeviation(this->Samples) << "s\n"
|
||||
<< "\tmean = " << stats::Mean(this->Samples) << "s\n"
|
||||
<< "\tstd dev = " << stats::StandardDeviation(this->Samples) << "s\n"
|
||||
<< "\tmin = " << this->Samples.front() << "s\n"
|
||||
<< "\tmax = " << this->Samples.back() << "s\n";
|
||||
}
|
||||
|
||||
template <typename DeviceAdapter, typename MakerFunctor, typename T>
|
||||
VTKM_CONT bool operator()(DeviceAdapter id, MakerFunctor&& makerFunctor, T t)
|
||||
{
|
||||
auto func = makerFunctor(t, id);
|
||||
std::cout << "Running '" << func.Description() << "'" << std::endl;
|
||||
this->GatherSamples(func);
|
||||
this->PrintSummary();
|
||||
return true;
|
||||
}
|
||||
|
||||
VTKM_CONT const std::vector<vtkm::Float64>& GetSamples() const { return this->Samples; }
|
||||
|
||||
VTKM_CONT void Reset()
|
||||
{
|
||||
this->Samples.clear();
|
||||
this->BenchmarkName.clear();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename MakerFunctor>
|
||||
class InternalPrintTypeAndBench
|
||||
// Returns the number of executed benchmarks:
|
||||
static inline vtkm::Id ExecuteBenchmarks(int& argc,
|
||||
char* argv[],
|
||||
const std::string& preamble = std::string{})
|
||||
{
|
||||
MakerFunctor Maker;
|
||||
|
||||
public:
|
||||
VTKM_CONT
|
||||
InternalPrintTypeAndBench(MakerFunctor maker)
|
||||
: Maker(maker)
|
||||
::benchmark::Initialize(&argc, argv);
|
||||
if (::benchmark::ReportUnrecognizedArguments(argc, argv))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
VTKM_CONT void operator()(T t, vtkm::cont::DeviceAdapterId id) const
|
||||
{
|
||||
std::cout << "*** " << vtkm::testing::TypeName<T>::Name() << " on device " << id.GetName()
|
||||
<< " ***************" << std::endl;
|
||||
Benchmarker bench;
|
||||
try
|
||||
{
|
||||
vtkm::cont::TryExecuteOnDevice(id, bench, Maker, t);
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cout << "\n"
|
||||
<< "An exception occurring during a benchmark:\n\t" << e.what() << "\n"
|
||||
<< "Attempting to continue with remaining benchmarks...\n\n";
|
||||
}
|
||||
}
|
||||
};
|
||||
VTKmConsoleReporter reporter{ preamble };
|
||||
|
||||
template <class MakerFunctor, class TypeList>
|
||||
VTKM_CONT void BenchmarkTypes(MakerFunctor&& maker, TypeList, vtkm::cont::DeviceAdapterId id)
|
||||
{
|
||||
vtkm::ListForEach(
|
||||
InternalPrintTypeAndBench<MakerFunctor>(std::forward<MakerFunctor>(maker)), TypeList(), id);
|
||||
vtkm::cont::Timer timer;
|
||||
timer.Start();
|
||||
std::size_t num = ::benchmark::RunSpecifiedBenchmarks(&reporter);
|
||||
timer.Stop();
|
||||
|
||||
reporter.GetOutputStream().flush();
|
||||
reporter.GetErrorStream().flush();
|
||||
|
||||
reporter.GetErrorStream() << "Ran " << num << " benchmarks in " << timer.GetElapsedTime()
|
||||
<< " seconds." << std::endl;
|
||||
|
||||
return static_cast<vtkm::Id>(num);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // end namespace vtkm::bench::detail
|
||||
|
||||
#endif
|
||||
|
@ -7,18 +7,24 @@
|
||||
## the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
## PURPOSE. See the above copyright notice for more information.
|
||||
##============================================================================
|
||||
|
||||
# Find Google Benchmark. Note that benchmark_DIR must be pointed at an
|
||||
# installation, not a build directory.
|
||||
find_package(benchmark REQUIRED)
|
||||
|
||||
function(add_benchmark)
|
||||
set(options)
|
||||
set(oneValueArgs NAME FILE)
|
||||
set(multiValueArgs LIBS)
|
||||
cmake_parse_arguments(VTKm_AB
|
||||
"${options}" "${oneValueArgs}" "${multiValueArgs}"
|
||||
${ARGN}
|
||||
)
|
||||
"${options}" "${oneValueArgs}" "${multiValueArgs}"
|
||||
${ARGN}
|
||||
)
|
||||
set(exe_name ${VTKm_AB_NAME})
|
||||
|
||||
add_executable(${exe_name} ${VTKm_AB_FILE})
|
||||
target_link_libraries(${exe_name} PRIVATE ${VTKm_AB_LIBS})
|
||||
target_link_libraries(${exe_name} PRIVATE benchmark::benchmark)
|
||||
vtkm_add_drop_unused_function_flags(${exe_name})
|
||||
vtkm_add_target_information(${exe_name})
|
||||
|
||||
|
24
docs/CODEOWNERS
Normal file
24
docs/CODEOWNERS
Normal file
@ -0,0 +1,24 @@
|
||||
# Subsystems have specific owners
|
||||
|
||||
|
||||
CMake/ @robertmaynard
|
||||
data/ @dpugmire
|
||||
docs/ @robertmaynard @kmorel
|
||||
examples/ @kmorel
|
||||
Utilities/ @kmorel
|
||||
vtkm/ @robertmaynard @kmorel
|
||||
vtkm/interop/ @robertmaynard
|
||||
vtkm/io/ @sujin.philip
|
||||
vtkm/rendering/ @mclarsen
|
||||
vtkm/source/ @robertmaynard @ollielo
|
||||
vtkm/testing/ @sujin.philip
|
||||
vtkm/thirdparty/ @ben.boeckel
|
||||
vtkm/worklet/cellmetrics/ @hankchilds
|
||||
vtkm/worklet/contourtree/ @oruebel @ghweber @sujin.philip
|
||||
vtkm/worklet/contourtree_augmented/ @oruebel @ghweber @sujin.philip
|
||||
vtkm/worklet/cosmotools/ @ollielo
|
||||
vtkm/worklet/lcs/ @ayenpure @dpugmire
|
||||
vtkm/worklet/moments/ @ollielo @robertmaynard
|
||||
vtkm/worklet/particleadvection @ayenpure @dpugmire
|
||||
vtkm/worklet/spatialstructure @ayenpure @kmorel
|
||||
vtkm/worklet/zfp @mclarsen
|
24
docs/changelog/arrayhandlegroupvecvariable.md
Normal file
24
docs/changelog/arrayhandlegroupvecvariable.md
Normal file
@ -0,0 +1,24 @@
|
||||
# `ArrayHandleGroupVecVariable` holds now one more offset.
|
||||
|
||||
This change affects the usage of both `ConvertNumComponentsToOffsets` and
|
||||
`make_ArrayHandleGroupVecVariable`.
|
||||
|
||||
The reason of this change is to remove a branch in
|
||||
`ArrayHandleGroupVecVariable::Get` which is used to avoid an array overflow,
|
||||
this in theory would increases the performance since at the CPU level it will
|
||||
remove penalties due to wrong branch predictions.
|
||||
|
||||
The change affects `ConvertNumComponentsToOffsets` by both:
|
||||
|
||||
1. Increasing the numbers of elements in `offsetsArray` (its second parameter)
|
||||
by one.
|
||||
|
||||
2. Setting `sourceArraySize` as the sum of all the elements plus the new one
|
||||
in `offsetsArray`
|
||||
|
||||
Note that not every specialization of `ConvertNumComponentsToOffsets` does
|
||||
return `offsetsArray`. Thus, some of them would not be affected.
|
||||
|
||||
Similarly, this change affects `make_ArrayHandleGroupVecVariable` since it
|
||||
expects its second parameter (offsetsArray) to be one element bigger than
|
||||
before.
|
72
docs/changelog/binary_search_algorithms.md
Normal file
72
docs/changelog/binary_search_algorithms.md
Normal file
@ -0,0 +1,72 @@
|
||||
# Algorithms for Control and Execution Environments
|
||||
|
||||
The `<vtkm/Algorithms.h>` header has been added to provide common STL-style
|
||||
generic algorithms that are suitable for use in both the control and execution
|
||||
environments. This is necessary as the STL algorithms in the `<algorithm>`
|
||||
header are not marked up for use in execution environments such as CUDA.
|
||||
|
||||
In addition to the markup, these algorithms have convenience overloads to
|
||||
support ArrayPortals directly, simplifying their usage with VTK-m data
|
||||
structures.
|
||||
|
||||
Currently, three related algorithms are provided: `LowerBounds`, `UpperBounds`,
|
||||
and `BinarySearch`. `BinarySearch` differs from the STL `std::binary_search`
|
||||
algorithm in that it returns an iterator (or index) to a matching element,
|
||||
rather than just a boolean indicating whether a or not key is present.
|
||||
|
||||
The new algorithm signatures are:
|
||||
|
||||
```c++
|
||||
namespace vtkm
|
||||
{
|
||||
|
||||
template <typename IterT, typename T, typename Comp>
|
||||
VTKM_EXEC_CONT
|
||||
IterT BinarySearch(IterT first, IterT last, const T& val, Comp comp);
|
||||
|
||||
template <typename IterT, typename T>
|
||||
VTKM_EXEC_CONT
|
||||
IterT BinarySearch(IterT first, IterT last, const T& val);
|
||||
|
||||
template <typename PortalT, typename T, typename Comp>
|
||||
VTKM_EXEC_CONT
|
||||
vtkm::Id BinarySearch(const PortalT& portal, const T& val, Comp comp);
|
||||
|
||||
template <typename PortalT, typename T>
|
||||
VTKM_EXEC_CONT
|
||||
vtkm::Id BinarySearch(const PortalT& portal, const T& val);
|
||||
|
||||
template <typename IterT, typename T, typename Comp>
|
||||
VTKM_EXEC_CONT
|
||||
IterT LowerBound(IterT first, IterT last, const T& val, Comp comp);
|
||||
|
||||
template <typename IterT, typename T>
|
||||
VTKM_EXEC_CONT
|
||||
IterT LowerBound(IterT first, IterT last, const T& val);
|
||||
|
||||
template <typename PortalT, typename T, typename Comp>
|
||||
VTKM_EXEC_CONT
|
||||
vtkm::Id LowerBound(const PortalT& portal, const T& val, Comp comp);
|
||||
|
||||
template <typename PortalT, typename T>
|
||||
VTKM_EXEC_CONT
|
||||
vtkm::Id LowerBound(const PortalT& portal, const T& val);
|
||||
|
||||
template <typename IterT, typename T, typename Comp>
|
||||
VTKM_EXEC_CONT
|
||||
IterT UpperBound(IterT first, IterT last, const T& val, Comp comp);
|
||||
|
||||
template <typename IterT, typename T>
|
||||
VTKM_EXEC_CONT
|
||||
IterT UpperBound(IterT first, IterT last, const T& val);
|
||||
|
||||
template <typename PortalT, typename T, typename Comp>
|
||||
VTKM_EXEC_CONT
|
||||
vtkm::Id UpperBound(const PortalT& portal, const T& val, Comp comp);
|
||||
|
||||
template <typename PortalT, typename T>
|
||||
VTKM_EXEC_CONT
|
||||
vtkm::Id UpperBound(const PortalT& portal, const T& val);
|
||||
|
||||
}
|
||||
```
|
28
docs/changelog/custom_portal_iterators.md
Normal file
28
docs/changelog/custom_portal_iterators.md
Normal file
@ -0,0 +1,28 @@
|
||||
# Portals may advertise custom iterators
|
||||
|
||||
The `ArrayPortalToIterator` utilities are used to produce STL-style iterators
|
||||
from vtk-m's `ArrayHandle` portals. By default, a facade class is constructed
|
||||
around the portal API, adapting it to an iterator interface.
|
||||
|
||||
However, some portals use iterators internally, or may be able to construct a
|
||||
lightweight iterator easily. For these, it is preferable to directly use the
|
||||
specialized iterators instead of going through the generic facade. A portal may
|
||||
now declare the following optional API to advertise that it has custom
|
||||
iterators:
|
||||
|
||||
```
|
||||
struct MyPortal
|
||||
{
|
||||
using IteratorType = ...; // alias to the portal's specialized iterator type
|
||||
IteratorType GetIteratorBegin(); // Return the begin iterator
|
||||
IteratorType GetIteratorEnd(); // Return the end iterator
|
||||
|
||||
// ...rest of ArrayPortal API...
|
||||
};
|
||||
```
|
||||
|
||||
If these members are present, `ArrayPortalToIterators` will forward the portal's
|
||||
specialized iterators instead of constructing a facade. This works when using
|
||||
the `ArrayPortalToIterators` class directly, and also with the
|
||||
`ArrayPortalToIteratorBegin` and `ArrayPortalToIteratorEnd` convenience
|
||||
functions.
|
114
docs/changelog/decorator_resizing.md
Normal file
114
docs/changelog/decorator_resizing.md
Normal file
@ -0,0 +1,114 @@
|
||||
# ArrayHandleDecorator Allocate and Shrink Support
|
||||
|
||||
`ArrayHandleDecorator` can now be resized when given an appropriate
|
||||
decorator implementation.
|
||||
|
||||
Since the mapping between the size of an `ArrayHandleDecorator` and its source
|
||||
`ArrayHandle`s is not well defined, resize operations (such as `Shrink` and
|
||||
`Allocate`) are not defined by default, and will throw an exception if called.
|
||||
|
||||
However, by implementing the methods `AllocateSourceArrays` and/or
|
||||
`ShrinkSourceArrays` on the implementation class, resizing the decorator is
|
||||
allowed. These methods are passed in a new size along with each of the
|
||||
`ArrayHandleDecorator`'s source arrays, allowing developers to control how
|
||||
the resize operation should affect the source arrays.
|
||||
|
||||
For example, the following decorator implementation can be used to create a
|
||||
resizable `ArrayHandleDecorator` that is implemented using two arrays, which
|
||||
are combined to produce values via the expression:
|
||||
|
||||
```
|
||||
[decorator value i] = [source1 value i] * 10 + [source2 value i]
|
||||
```
|
||||
|
||||
Implementation:
|
||||
|
||||
```c++
|
||||
template <typename ValueType>
|
||||
struct DecompositionDecorImpl
|
||||
{
|
||||
template <typename Portal1T, typename Portal2T>
|
||||
struct Functor
|
||||
{
|
||||
Portal1T Portal1;
|
||||
Portal2T Portal2;
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
ValueType operator()(vtkm::Id idx) const
|
||||
{
|
||||
return static_cast<ValueType>(this->Portal1.Get(idx) * 10 + this->Portal2.Get(idx));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Portal1T, typename Portal2T>
|
||||
struct InverseFunctor
|
||||
{
|
||||
Portal1T Portal1;
|
||||
Portal2T Portal2;
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
void operator()(vtkm::Id idx, const ValueType& val) const
|
||||
{
|
||||
this->Portal1.Set(idx, static_cast<ValueType>(std::floor(val / 10)));
|
||||
this->Portal2.Set(idx, static_cast<ValueType>(std::fmod(val, 10)));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Portal1T, typename Portal2T>
|
||||
VTKM_CONT Functor<typename std::decay<Portal1T>::type, typename std::decay<Portal2T>::type>
|
||||
CreateFunctor(Portal1T&& p1, Portal2T&& p2) const
|
||||
{
|
||||
return { std::forward<Portal1T>(p1), std::forward<Portal2T>(p2) };
|
||||
}
|
||||
|
||||
template <typename Portal1T, typename Portal2T>
|
||||
VTKM_CONT InverseFunctor<typename std::decay<Portal1T>::type, typename std::decay<Portal2T>::type>
|
||||
CreateInverseFunctor(Portal1T&& p1, Portal2T&& p2) const
|
||||
{
|
||||
return { std::forward<Portal1T>(p1), std::forward<Portal2T>(p2) };
|
||||
}
|
||||
|
||||
// Resize methods:
|
||||
template <typename Array1T, typename Array2T>
|
||||
VTKM_CONT
|
||||
void AllocateSourceArrays(vtkm::Id numVals, Array1T&& array1, Array2T&& array2) const
|
||||
{
|
||||
array1.Allocate(numVals);
|
||||
array2.Allocate(numVals);
|
||||
}
|
||||
|
||||
template <typename Array1T, typename Array2T>
|
||||
VTKM_CONT
|
||||
void ShrinkSourceArrays(vtkm::Id numVals, Array1T&& array1, Array2T&& array2) const
|
||||
{
|
||||
array1.Shrink(numVals);
|
||||
array2.Shrink(numVals);
|
||||
}
|
||||
};
|
||||
|
||||
// Usage:
|
||||
vtkm::cont::ArrayHandle<ValueType> a1;
|
||||
vtkm::cont::ArrayHandle<ValueType> a2;
|
||||
auto decor = vtkm::cont::make_ArrayHandleDecorator(0, DecompositionDecorImpl<ValueType>{}, a1, a2);
|
||||
|
||||
decor.Allocate(5);
|
||||
{
|
||||
auto decorPortal = decor.GetPortalControl();
|
||||
decorPortal.Set(0, 13);
|
||||
decorPortal.Set(1, 8);
|
||||
decorPortal.Set(2, 43);
|
||||
decorPortal.Set(3, 92);
|
||||
decorPortal.Set(4, 117);
|
||||
}
|
||||
|
||||
// a1: { 1, 0, 4, 9, 11 }
|
||||
// a2: { 3, 8, 3, 2, 7 }
|
||||
// decor: { 13, 8, 43, 92, 117 }
|
||||
|
||||
decor.Shrink(3);
|
||||
|
||||
// a1: { 1, 0, 4 }
|
||||
// a2: { 3, 8, 3 }
|
||||
// decor: { 13, 8, 43 }
|
||||
|
||||
```
|
97
docs/changelog/deprecation.md
Normal file
97
docs/changelog/deprecation.md
Normal file
@ -0,0 +1,97 @@
|
||||
# Add VTKM_DEPRECATED macro
|
||||
|
||||
The `VTKM_DEPRECATED` macro allows us to remove (and usually replace)
|
||||
features from VTK-m in minor releases while still following the conventions
|
||||
of semantic versioning. The idea is that when we want to remove or replace
|
||||
a feature, we first mark the old feature as deprecated. The old feature
|
||||
will continue to work, but compilers that support it will start to issue a
|
||||
warning that the use is deprecated and should stop being used. The
|
||||
deprecated features should remain viable until at least the next major
|
||||
version. At the next major version, deprecated features from the previous
|
||||
version may be removed.
|
||||
|
||||
## Declaring things deprecated
|
||||
|
||||
Classes and methods are marked deprecated using the `VTKM_DEPRECATED`
|
||||
macro. The first argument of `VTKM_DEPRECATED` should be set to the first
|
||||
version in which the feature is deprecated. For example, if the last
|
||||
released version of VTK-m was 1.5, and on the master branch a developer
|
||||
wants to deprecate a class foo, then the `VTKM_DEPRECATED` release version
|
||||
should be given as 1.6, which will be the next minor release of VTK-m. The
|
||||
second argument of `VTKM_DEPRECATED`, which is optional but highly
|
||||
encouraged, is a short message that should clue developers on how to update
|
||||
their code to the new changes. For example, it could point to the
|
||||
replacement class or method for the changed feature.
|
||||
|
||||
`VTKM_DEPRECATED` can be used to deprecate a class by adding it between the
|
||||
`struct` or `class` keyword and the class name.
|
||||
|
||||
``` cpp
|
||||
struct VTKM_DEPRECATED(1.6, "OldClass replaced with NewClass.") OldClass
|
||||
{
|
||||
};
|
||||
```
|
||||
|
||||
Aliases can similarly be depreciated, except the `VTKM_DEPRECATED` macro
|
||||
goes after the name in this case.
|
||||
|
||||
``` cpp
|
||||
using OldAlias VTKM_DEPRECATED(1.6, "Use NewClass instead.") = NewClass;
|
||||
```
|
||||
|
||||
Functions and methods are marked as deprecated by adding `VTKM_DEPRECATED`
|
||||
as a modifier before the return value.
|
||||
|
||||
``` cpp
|
||||
VTKM_EXEC_CONT
|
||||
VTKM_DEPRECATED(1.6, "You must now specify a tolerance.") void ImportantMethod(double x)
|
||||
{
|
||||
this->ImportantMethod(x, 1e-6);
|
||||
}
|
||||
```
|
||||
|
||||
`enum`s can be deprecated like classes using similar syntax.
|
||||
|
||||
``` cpp
|
||||
enum struct VTKM_DEPRECATED(1.7, "Use NewEnum instead.") OldEnum
|
||||
{
|
||||
OLD_VALUE
|
||||
};
|
||||
```
|
||||
|
||||
Individual items in an `enum` can also be marked as deprecated and
|
||||
intermixed with regular items.
|
||||
|
||||
``` cpp
|
||||
enum struct NewEnum
|
||||
{
|
||||
OLD_VALUE1 VTKM_DEPRECATED(1.7, "Use NEW_VALUE instead."),
|
||||
NEW_VALUE,
|
||||
OLD_VALUE2 VTKM_DEPRECATED(1.7) = 42
|
||||
};
|
||||
```
|
||||
|
||||
## Using deprecated items
|
||||
|
||||
Using deprecated items should work, but the compiler will give a warning.
|
||||
That is the point. However, sometimes you need to legitimately use a
|
||||
deprecated item without a warning. This is usually because you are
|
||||
implementing another deprecated item or because you have a test for a
|
||||
deprecated item (that can be easily removed with the deprecated bit). To
|
||||
support this a pair of macros, `VTKM_DEPRECATED_SUPPRESS_BEGIN` and
|
||||
`VTKM_DEPRECATED_SUPPRESS_END` are provided. Code that legitimately uses
|
||||
deprecated items should be wrapped in these macros.
|
||||
|
||||
``` cpp
|
||||
VTKM_EXEC_CONT
|
||||
VTKM_DEPRECATED(1.6, "You must now specify both a value and tolerance.")
|
||||
void ImportantMethod()
|
||||
{
|
||||
// It can be the case that to implement a deprecated method you need to
|
||||
// use other deprecated features. To do that, just temporarily suppress
|
||||
// those warnings.
|
||||
VTKM_DEPRECATED_SUPPRESS_BEGIN
|
||||
this->ImportantMethod(0.0);
|
||||
VTKM_DEPRECATED_SUPPRESS_END
|
||||
}
|
||||
```
|
133
docs/changelog/google_benchmark.md
Normal file
133
docs/changelog/google_benchmark.md
Normal file
@ -0,0 +1,133 @@
|
||||
# Updated Benchmark Framework
|
||||
|
||||
The benchmarking framework has been updated to use Google Benchmark.
|
||||
|
||||
A benchmark is now a single function, which is passed to a macro:
|
||||
|
||||
```
|
||||
void MyBenchmark(::benchmark::State& state)
|
||||
{
|
||||
MyClass someClass;
|
||||
|
||||
// Optional: Add a descriptive label with additional benchmark details:
|
||||
state.SetLabel("Blah blah blah.");
|
||||
|
||||
// Must use a vtkm timer to properly capture eg. CUDA execution times.
|
||||
vtkm::cont::Timer timer;
|
||||
for (auto _ : state)
|
||||
{
|
||||
someClass.Reset();
|
||||
|
||||
timer.Start();
|
||||
someClass.DoWork();
|
||||
timer.Stop();
|
||||
|
||||
state.SetIterationTime(timer.GetElapsedTime());
|
||||
}
|
||||
|
||||
// Optional: Report items and/or bytes processed per iteration in output:
|
||||
state.SetItemsProcessed(state.iterations() * someClass.GetNumberOfItems());
|
||||
state.SetBytesProcessed(state.iterations() * someClass.GetNumberOfBytes());
|
||||
}
|
||||
}
|
||||
VTKM_BENCHMARK(MyBenchmark);
|
||||
```
|
||||
|
||||
Google benchmark also makes it easy to implement parameter sweep benchmarks:
|
||||
|
||||
```
|
||||
void MyParameterSweep(::benchmark::State& state)
|
||||
{
|
||||
// The current value in the sweep:
|
||||
const vtkm::Id currentValue = state.range(0);
|
||||
|
||||
MyClass someClass;
|
||||
someClass.SetSomeParameter(currentValue);
|
||||
|
||||
vtkm::cont::Timer timer;
|
||||
for (auto _ : state)
|
||||
{
|
||||
someClass.Reset();
|
||||
|
||||
timer.Start();
|
||||
someClass.DoWork();
|
||||
timer.Stop();
|
||||
|
||||
state.SetIterationTime(timer.GetElapsedTime());
|
||||
}
|
||||
}
|
||||
VTKM_BENCHMARK_OPTS(MyBenchmark, ->ArgName("Param")->Range(32, 1024 * 1024));
|
||||
```
|
||||
|
||||
will generate and launch several benchmarks, exploring the parameter space of
|
||||
`SetSomeParameter` between the values of 32 and (1024*1024). The chain of
|
||||
functions calls in the second argument is applied to an instance of
|
||||
::benchmark::internal::Benchmark. See Google Benchmark's documentation for
|
||||
more details.
|
||||
|
||||
For more complex benchmark configurations, the VTKM_BENCHMARK_APPLY macro
|
||||
accepts a function with the signature
|
||||
`void Func(::benchmark::internal::Benchmark*)` that may be used to generate
|
||||
more complex configurations.
|
||||
|
||||
To instantiate a templated benchmark across a list of types, the
|
||||
VTKM_BENCHMARK_TEMPLATE* macros take a vtkm::List of types as an additional
|
||||
parameter. The templated benchmark function will be instantiated and called
|
||||
for each type in the list:
|
||||
|
||||
```
|
||||
template <typename T>
|
||||
void MyBenchmark(::benchmark::State& state)
|
||||
{
|
||||
MyClass<T> someClass;
|
||||
|
||||
// Must use a vtkm timer to properly capture eg. CUDA execution times.
|
||||
vtkm::cont::Timer timer;
|
||||
for (auto _ : state)
|
||||
{
|
||||
someClass.Reset();
|
||||
|
||||
timer.Start();
|
||||
someClass.DoWork();
|
||||
timer.Stop();
|
||||
|
||||
state.SetIterationTime(timer.GetElapsedTime());
|
||||
}
|
||||
}
|
||||
}
|
||||
VTKM_BENCHMARK_TEMPLATE(MyBenchmark, vtkm::List<vtkm::Float32, vtkm::Vec3f_32>);
|
||||
```
|
||||
|
||||
The benchmarks are executed by calling the `VTKM_EXECUTE_BENCHMARKS(argc, argv)`
|
||||
macro from `main`. There is also a `VTKM_EXECUTE_BENCHMARKS_PREAMBLE(argc, argv, some_string)`
|
||||
macro that appends the contents of `some_string` to the Google Benchmark preamble.
|
||||
|
||||
If a benchmark is not compatible with some configuration, it may call
|
||||
`state.SkipWithError("Error message");` on the `::benchmark::State` object and return. This is
|
||||
useful, for instance in the filter tests when the input is not compatible with the filter.
|
||||
|
||||
When launching a benchmark executable, the following options are supported by Google Benchmark:
|
||||
|
||||
- `--benchmark_list_tests`: List all available tests.
|
||||
- `--benchmark_filter="[regex]"`: Only run benchmark with names that match `[regex]`.
|
||||
- `--benchmark_filter="-[regex]"`: Only run benchmark with names that DON'T match `[regex]`.
|
||||
- `--benchmark_min_time=[float]`: Make sure each benchmark repetition gathers `[float]` seconds
|
||||
of data.
|
||||
- `--benchmark_repetitions=[int]`: Run each benchmark `[int]` times and report aggregate statistics
|
||||
(mean, stdev, etc). A "repetition" refers to a single execution of the benchmark function, not
|
||||
an "iteration", which is a loop of the `for(auto _:state){...}` section.
|
||||
- `--benchmark_report_aggregates_only="true|false"`: If true, only the aggregate statistics are
|
||||
reported (affects both console and file output). Requires `--benchmark_repetitions` to be useful.
|
||||
- `--benchmark_display_aggregates_only="true|false"`: If true, only the aggregate statistics are
|
||||
printed to the terminal. Any file output will still contain all repetition info.
|
||||
- `--benchmark_format="console|json|csv"`: Specify terminal output format: human readable
|
||||
(`console`) or `csv`/`json` formats.
|
||||
- `--benchmark_out_format="console|json|csv"`: Specify file output format: human readable
|
||||
(`console`) or `csv`/`json` formats.
|
||||
- `--benchmark_out=[filename]`: Specify output file.
|
||||
- `--benchmark_color="true|false"`: Toggle color output in terminal when using `console` output.
|
||||
- `--benchmark_counters_tabular="true|false"`: Print counter information (e.g. bytes/sec, items/sec)
|
||||
in the table, rather than appending them as a label.
|
||||
|
||||
For more information and examples of practical usage, take a look at the existing benchmarks in
|
||||
vtk-m/benchmarking/.
|
29
docs/changelog/list-tag-remove-if.md
Normal file
29
docs/changelog/list-tag-remove-if.md
Normal file
@ -0,0 +1,29 @@
|
||||
# Add `ListTagRemoveIf`
|
||||
|
||||
It is sometimes useful to remove types from `ListTag`s. This is especially
|
||||
the case when combining lists of types together where some of the type
|
||||
combinations may be invalid and should be removed. To handle this
|
||||
situation, a new `ListTag` type is added: `ListTagRemoveIf`.
|
||||
|
||||
`ListTagRemoveIf` is a template structure that takes two arguments. The
|
||||
first argument is another `ListTag` type to operate on. The second argument
|
||||
is a template that acts as a predicate. The predicate takes a type and
|
||||
declares a Boolean `value` that should be `true` if the type should be
|
||||
removed and `false` if the type should remain.
|
||||
|
||||
Here is an example of using `ListTagRemoveIf` to get basic types that hold
|
||||
only integral values.
|
||||
|
||||
``` cpp
|
||||
template <typename T>
|
||||
using IsRealValue =
|
||||
std::is_same<
|
||||
typename vtkm::TypeTraits<typename vtkm::VecTraits<T>::BaseComponentType>::NumericTag,
|
||||
vtkm::TypeTraitsRealTag>;
|
||||
|
||||
using MixedTypes =
|
||||
vtkm::ListTagBase<vtkm::Id, vtkm::FloatDefault, vtkm::Id3, vtkm::Vec3f>;
|
||||
|
||||
using IntegralTypes = vtkm::ListTagRemoveIf<MixedTypes, IsRealValue>;
|
||||
// IntegralTypes now equivalent to vtkm::ListTagBase<vtkm::Id, vtkm::Id3>
|
||||
```
|
55
docs/changelog/list.md
Normal file
55
docs/changelog/list.md
Normal file
@ -0,0 +1,55 @@
|
||||
# Replaced `vtkm::ListTag` with `vtkm::List`
|
||||
|
||||
The original `vtkm::ListTag` was designed when we had to support compilers
|
||||
that did not provide C++11's variadic templates. Thus, the design hides
|
||||
type lists, which were complicated to support.
|
||||
|
||||
Now that we support C++11, variadic templates are trivial and we can easily
|
||||
create templated type aliases with `using`. Thus, it is now simpler to deal
|
||||
with a template that lists types directly.
|
||||
|
||||
Hence, `vtkm::ListTag` is deprecated and `vtkm::List` is now supported. The
|
||||
main difference between the two is that whereas `vtkm::ListTag` allowed you
|
||||
to create a list by subclassing another list, `vtkm::List` cannot be
|
||||
subclassed. (Well, it can be subclassed, but the subclass ceases to be
|
||||
considered a list.) Thus, where before you would declare a list like
|
||||
|
||||
``` cpp
|
||||
struct MyList : vtkm::ListTagBase<Type1, Type2, Type3>
|
||||
{
|
||||
};
|
||||
```
|
||||
|
||||
you now make an alias
|
||||
|
||||
``` cpp
|
||||
using MyList = vtkm::List<Type1, Type2, Type3>;
|
||||
```
|
||||
|
||||
If the compiler reports the `MyList` type in an error or warning, it
|
||||
actually uses the fully qualified `vtkm::List<Type1, Type2, Type3>`.
|
||||
Although this makes errors more verbose, it makes it easier to diagnose
|
||||
problems because the types are explicitly listed.
|
||||
|
||||
The new `vtkm::List` comes with a list of utility templates to manipulate
|
||||
lists that mostly mirrors those in `vtkm::ListTag`: `VTKM_IS_LIST`,
|
||||
`ListApply`, `ListSize`, `ListAt`, `ListIndexOf`, `ListHas`, `ListAppend`,
|
||||
`ListIntersect`, `ListTransform`, `ListRemoveIf`, and `ListCross`. All of
|
||||
these utilities become `vtkm::List<>` types (where applicable), which makes
|
||||
them more consistent than the old `vtkm::ListTag` versions.
|
||||
|
||||
Thus, if you have a declaration like
|
||||
|
||||
``` cpp
|
||||
vtkm::ListAppend(vtkm::List<Type1a, Type2a>, vtkm::List<Type1b, Type2b>>
|
||||
```
|
||||
|
||||
this gets changed automatically to
|
||||
|
||||
``` cpp
|
||||
vtkm::List<Type1a, Type2a, Type1b, Type2b>
|
||||
```
|
||||
|
||||
This is in contrast to the equivalent old version, which would create a new
|
||||
type for `vtkm::ListTagAppend` in addition to the ultimate actual list it
|
||||
constructs.
|
11
docs/changelog/mask_and_scatters_3d_scheduling.md
Normal file
11
docs/changelog/mask_and_scatters_3d_scheduling.md
Normal file
@ -0,0 +1,11 @@
|
||||
# Masks and Scatters Supported for 3D Scheduling
|
||||
|
||||
Previous to this change worklets that wanted to use non-default
|
||||
`vtkm::worklet::Mask` or `vtkm::worklet::Scatter` wouldn't work when scheduled
|
||||
to run across `vtkm::cont::CellSetStructured` or other `InputDomains` that
|
||||
supported 3D scheduling.
|
||||
|
||||
This restriction was an inadvertent limitation of the VTK-m worklet scheduling
|
||||
algorithm. Lifting the restriction and providing sufficient information has
|
||||
been achieved in a manner that shouldn't degrade performance of any existing
|
||||
worklets.
|
220
docs/changelog/scoping-tokens.md
Normal file
220
docs/changelog/scoping-tokens.md
Normal file
@ -0,0 +1,220 @@
|
||||
# Scope ExecObjects with Tokens
|
||||
|
||||
When VTK-m's `ArrayHandle` was originally designed, it was assumed that the
|
||||
control environment would run on a single thread. However, multiple users
|
||||
have expressed realistic use cases in which they would like to control
|
||||
VTK-m from multiple threads (for example, to control multiple devices).
|
||||
Consequently, it is important that VTK-m's control classes work correctly
|
||||
when used simultaneously from multiple threads.
|
||||
|
||||
The original `PrepareFor*` methods of `ArrayHandle` returned an object to
|
||||
be used in the execution environment on a particular device that pointed to
|
||||
data in the array. The pointer to the data was contingent on the state of
|
||||
the `ArrayHandle` not changing. The assumption was that the calling code
|
||||
would immediately use the returned execution environment object and would
|
||||
not further change the `ArrayHandle` until done with the execution
|
||||
environment object.
|
||||
|
||||
This assumption is broken if multiple threads are running in the control
|
||||
environment. For example, if one thread has called `PrepareForInput` to get
|
||||
an execution array portal, the portal or its data could become invalid if
|
||||
another thread calls `PrepareForOutput` on the same array. Initially one
|
||||
would think that a well designed program should not share `ArrayHandle`s in
|
||||
this way, but there are good reasons to need to do so. For example, when
|
||||
using `vtkm::cont::PartitionedDataSet` where multiple partitions share a
|
||||
coordinate system (very common), it becomes unsafe to work on multiple
|
||||
blocks in parallel on different devices.
|
||||
|
||||
What we really want is the code to be able to specify more explicitly when
|
||||
the execution object is in use. Ideally, the execution object itself would
|
||||
maintain the resources it is using. However, that will not work in this
|
||||
case since the object has to pass from control to execution environment and
|
||||
back. The resource allocation will break when the object is passed to an
|
||||
offloaded device and back.
|
||||
|
||||
Because we cannot use the object itself to manage its own resources, we use
|
||||
a proxy object we are calling a `Token`. The `Token` object manages the
|
||||
scope of the return execution object. As long as the `Token` is still in
|
||||
scope, the execution object will remain valid. When the `Token` is
|
||||
destroyed (or `DetachFromAll` is called on it), then the execution object
|
||||
is no longer protected.
|
||||
|
||||
When a `Token` is attached to an `ArrayHandle` to protect an execution
|
||||
object, it's read or write mode is recorded. Multiple `Token`s can be
|
||||
attached to read the `ArrayHandle` at the same time. However, only one
|
||||
`Token` can be used to write to the `ArrayHandle`.
|
||||
|
||||
## Basic `ArrayHandle` use
|
||||
|
||||
The basic use of the `PrepareFor*` methods of `ArrayHandle` remain the
|
||||
same. The only difference is the addition of a `Token` parameter.
|
||||
|
||||
``` cpp
|
||||
template <typename Device>
|
||||
void LowLevelArray(vtkm::cont::ArrayHandle<vtkm::Float32> array, Device)
|
||||
{
|
||||
vtkm::cont::Token token;
|
||||
auto portal = array.PrepareForOutput(ARRAY_SIZE, Device{}, token);
|
||||
// At this point, array is locked from anyone else from reading or modifying
|
||||
vtkm::cont::DeviceAdapterAlgorithm<Device>::Schedule(MyKernel(portal), ARRAY_SIZE);
|
||||
|
||||
// When the function finishes, token goes out of scope and array opens up
|
||||
// for other uses.
|
||||
}
|
||||
```
|
||||
|
||||
## Execution objects
|
||||
|
||||
To make sure that execution objects are scoped correctly, many changes
|
||||
needed to be made to propagate a `Token` reference from the top of the
|
||||
scope to where the execution object is actually made. The most noticeable
|
||||
place for this was for implementations of
|
||||
`vtkm::cont::ExecutionObjectBase`. Most implementations of
|
||||
`ExecutionObjectBase` create an object that requires data from an
|
||||
`ArrayHandle`.
|
||||
|
||||
Previously, a subclass of `ExecutionObjectBase` was expected to have a
|
||||
method named `PrepareForExecution` that had a single argument: the device
|
||||
tag (or id) to make an object for. Now, subclasses of `ExecutionObjectBase`
|
||||
should have a `PrepareForExecution` that takes two arguments: the device
|
||||
and a `Token` to use for scoping the execution object.
|
||||
|
||||
``` cpp
|
||||
struct MyExecObject : vtkm::cont::ExecutionObjectBase
|
||||
{
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32> Array;
|
||||
|
||||
template <typename Device>
|
||||
VTKM_CONT
|
||||
MyExec<Device> PrepareForExecution(Device device, vtkm::cont::Token& token)
|
||||
{
|
||||
MyExec<Device> object;
|
||||
object.Portal = this->Array.PrepareForInput(device, token);
|
||||
return object;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
It actually still works to use the old style of `PrepareForExecution`.
|
||||
However, you will get a deprecation warning (on supported compilers) when
|
||||
you try to use it.
|
||||
|
||||
## Invoke and Dispatcher
|
||||
|
||||
The `Dispatcher` classes now internally define a `Token` object during the
|
||||
call to `Invoke`. (Likewise, `Invoker` will have a `Token` defined during
|
||||
its invoke.) This internal `Token` is used when preparing `ArrayHandle`s
|
||||
and `ExecutionObject`s for the execution environment. (Details in the next
|
||||
section on how that works.)
|
||||
|
||||
Because the invoke uses a `Token` to protect its arguments, it will block
|
||||
the execution of other worklets attempting to access arrays in a way that
|
||||
could cause read-write hazards. In the following example, the second
|
||||
worklet will not be able to execute until the first worklet finishes.
|
||||
|
||||
``` cpp
|
||||
vtkm::cont::Invoker invoke;
|
||||
invoke(Worklet1{}, input, intermediate);
|
||||
invoke(Worklet2{}, intermediate, output); // Will not execute until Worklet1 finishes.
|
||||
```
|
||||
|
||||
That said, invocations _can_ share arrays if their use will not cause
|
||||
read-write hazards. In particular, two invocations can both use the same
|
||||
array if they are both strictly reading from it. In the following example,
|
||||
both worklets can potentially execute at the same time.
|
||||
|
||||
``` cpp
|
||||
vtkm::cont::Invoker invoke;
|
||||
invoke(Worklet1{}, input, output1);
|
||||
invoke(Worklet2{}, input, output2); // Will not block
|
||||
```
|
||||
|
||||
The same `Token` is used for all arguments to the `Worklet`. This deatil is
|
||||
important to prevent deadlocks if the same object is used in more than one
|
||||
`Worklet` parameter. As a simple example, if a `Worklet` has a control
|
||||
signature like
|
||||
|
||||
``` cpp
|
||||
using ControlSignature = void(FieldIn, FieldOut);
|
||||
```
|
||||
|
||||
it should continue to work to use the same array as both fields.
|
||||
|
||||
``` cpp
|
||||
vtkm::cont::Invoker invoke;
|
||||
invoke(Worklet1{}, array, array);
|
||||
```
|
||||
|
||||
## Transport
|
||||
|
||||
The dispatch mechanism of worklets internally uses
|
||||
`vtkm::cont::arg::Transport` objects to automatically move data from the
|
||||
control environment to the execution environment. These `Transport` object
|
||||
now take a `Token` when doing the transportation. This all happens under
|
||||
the covers for most users.
|
||||
|
||||
## Control Portals
|
||||
|
||||
The `GetPortalConstControl` and `GetPortalControl` methods have been
|
||||
deprecated. Instead, the methods `ReadPortal` and `WritePortal` should be
|
||||
used. The calling signature is the same as their predecessors, but the
|
||||
returned portal contains a `Token` as part of its state and prevents and
|
||||
changes to the `ArrayHandle` it comes from. The `WritePortal` also prevents
|
||||
other reads from the array.
|
||||
|
||||
The advantage is that the returned portal will always be valid. However, it
|
||||
is now the case that a control portal can prevent something else from
|
||||
running. This means that control portals should drop scope as soon as
|
||||
possible. It is because of this behavior change that new methods were
|
||||
created instead of altering the old ones.
|
||||
|
||||
## Deadlocks
|
||||
|
||||
Now that portal objects from `ArrayHandle`s have finite scope (as opposed
|
||||
to able to be immediately invalidated), the scopes have the ability to
|
||||
cause operations to block. This can cause issues if the `ArrayHandle` is
|
||||
attempted to be used by multiple `Token`s at once.
|
||||
|
||||
Care should be taken to ensure that a single thread does not attempt to use
|
||||
an `ArrayHandle` two ways at the same time.
|
||||
|
||||
``` cpp
|
||||
auto portal = array.WritePortal();
|
||||
for (vtkm::Id index = 0; index < portal.GetNumberOfValues(); ++index)
|
||||
{
|
||||
portal.Set(index, /* An interesting value */);
|
||||
}
|
||||
vtkm::cont::Invoker invoke;
|
||||
invoke(MyWorklet, array); // Oops. Deadlock here.
|
||||
```
|
||||
|
||||
In this example, the last line deadlocks because `portal` is still holding
|
||||
onto `array` for writing. When the worklet is invoked, it waits for
|
||||
everything to stop writing to `array` so that it can be safely be read.
|
||||
Instead, `portal` should be properly scoped.
|
||||
|
||||
``` cpp
|
||||
{
|
||||
auto portal = array.GetPortalControl();
|
||||
for (vtkm::Id index = 0; index < portal.GetNumberOfValues(); ++index)
|
||||
{
|
||||
portal.Set(index, /* An interesting value */);
|
||||
}
|
||||
}
|
||||
vtkm::cont::Invoker invoke;
|
||||
invoke(MyWorklet, array); // Runs fine because portal left scope
|
||||
```
|
||||
|
||||
Alternately, you can call `Detach` on the portal, which will invalidate the
|
||||
portal and unlock the `ArrayHandle`.
|
||||
|
||||
``` cpp
|
||||
auto portal = array.WritePortal();
|
||||
for (vtkm::Id index = 0; index < portal.GetNumberOfValues(); ++index)
|
||||
{
|
||||
portal.Set(index, /* An interesting value */);
|
||||
}
|
||||
portal.Detach();
|
||||
vtkm::cont::Invoker invoke;
|
||||
invoke(MyWorklet, array); // Runs fine because portal detached
|
||||
```
|
234
docs/changelog/shorter-fancy-array-handle-classnames.md
Normal file
234
docs/changelog/shorter-fancy-array-handle-classnames.md
Normal file
@ -0,0 +1,234 @@
|
||||
# Shorter fancy array handle classnames
|
||||
|
||||
Many of the fancy `ArrayHandle`s use the generic builders like
|
||||
`ArrayHandleTransform` and `ArrayHandleImplicit` for their implementation.
|
||||
Such is fine, but because they use functors and other such generic items to
|
||||
template their `Storage`, you can end up with very verbose classnames. This
|
||||
is an issue for humans trying to discern classnames. It can also be an
|
||||
issue for compilers that end up with very long resolved classnames that
|
||||
might get truncated if they extend past what was expected.
|
||||
|
||||
The fix was for these classes to declare their own `Storage` tag and then
|
||||
implement their `Storage` and `ArrayTransport` classes as trivial
|
||||
subclasses of the generic `ArrayHandleImplicit` or `ArrayHandleTransport`.
|
||||
|
||||
As an added bonus, a lot of this shortening also means that storage that
|
||||
relies on other array handles now are just typed by the storage of the
|
||||
decorated type, not the array itself. This should make the types a little
|
||||
more robust.
|
||||
|
||||
Here is a list of classes that were updated.
|
||||
|
||||
#### `ArrayHandleCast<TargetT, vtkm::cont::ArrayHandle<SourceT, SourceStorage>>`
|
||||
|
||||
Old storage:
|
||||
``` cpp
|
||||
vtkm::cont::internal::StorageTagTransform<
|
||||
vtkm::cont::ArrayHandle<SourceT, SourceStorage>,
|
||||
vtkm::cont::internal::Cast<TargetT, SourceT>,
|
||||
vtkm::cont::internal::Cast<SourceT, TargetT>>
|
||||
```
|
||||
|
||||
New Storage:
|
||||
``` cpp
|
||||
vtkm::cont::StorageTagCast<SourceT, SourceStorage>
|
||||
```
|
||||
|
||||
(Developer's note: Implementing this change to `ArrayHandleCast` was a much bigger PITA than expected.)
|
||||
|
||||
#### `ArrayHandleCartesianProduct<AH1, AH2, AH3>`
|
||||
|
||||
Old storage:
|
||||
``` cpp
|
||||
vtkm::cont::internal::StorageTagCartesianProduct<
|
||||
vtkm::cont::ArrayHandle<ValueType, StorageTag1,
|
||||
vtkm::cont::ArrayHandle<ValueType, StorageTag2,
|
||||
vtkm::cont::ArrayHandle<ValueType, StorageTag3>>
|
||||
```
|
||||
|
||||
New storage:
|
||||
``` cpp
|
||||
vtkm::cont::StorageTagCartesianProduct<StorageTag1, StorageTag2, StorageTag3>
|
||||
```
|
||||
|
||||
#### `ArrayHandleCompositeVector<AH1, AH2, ...>`
|
||||
|
||||
Old storage:
|
||||
``` cpp
|
||||
vtkm::cont::internal::StorageTagCompositeVector<
|
||||
tao::tuple<
|
||||
vtkm::cont::ArrayHandle<ValueType, StorageType1>,
|
||||
vtkm::cont::ArrayHandle<ValueType, StorageType2>,
|
||||
...
|
||||
>
|
||||
>
|
||||
```
|
||||
|
||||
New storage:
|
||||
``` cpp
|
||||
vtkm::cont::StorageTagCompositeVec<StorageType1, StorageType2>
|
||||
```
|
||||
|
||||
#### `ArrayHandleConcatinate`
|
||||
|
||||
First an example with two simple types.
|
||||
|
||||
Old storage:
|
||||
``` cpp
|
||||
vtkm::cont::StorageTagConcatenate<
|
||||
vtkm::cont::ArrayHandle<ValueType, StorageTag1>,
|
||||
vtkm::cont::ArrayHandle<ValueType, StorageTag2>>
|
||||
```
|
||||
|
||||
New storage:
|
||||
``` cpp
|
||||
vtkm::cont::StorageTagConcatenate<StorageTag1, StorageTag2>
|
||||
```
|
||||
|
||||
Now a more specific example taken from the unit test of a concatination of a concatination.
|
||||
|
||||
Old storage:
|
||||
``` cpp
|
||||
vtkm::cont::StorageTagConcatenate<
|
||||
vtkm::cont::ArrayHandleConcatenate<
|
||||
vtkm::cont::ArrayHandle<ValueType, StorageTag1>,
|
||||
vtkm::cont::ArrayHandle<ValueType, StorageTag2>>,
|
||||
vtkm::cont::ArrayHandle<ValueType, StorageTag3>>
|
||||
```
|
||||
|
||||
New storage:
|
||||
``` cpp
|
||||
vtkm::cont::StorageTagConcatenate<
|
||||
vtkm::cont::StorageTagConcatenate<StorageTag1, StorageTag2>, StorageTag3>
|
||||
```
|
||||
|
||||
#### `ArrayHandleConstant`
|
||||
|
||||
Old storage:
|
||||
``` cpp
|
||||
vtkm::cont::StorageTagImplicit<
|
||||
vtkm::cont::detail::ArrayPortalImplicit<
|
||||
vtkm::cont::detail::ConstantFunctor<ValueType>>>
|
||||
```
|
||||
|
||||
New storage:
|
||||
``` cpp
|
||||
vtkm::cont::StorageTagConstant
|
||||
```
|
||||
|
||||
#### `ArrayHandleCounting`
|
||||
|
||||
Old storage:
|
||||
``` cpp
|
||||
vtkm::cont::StorageTagImplicit<vtkm::cont::internal::ArrayPortalCounting<ValueType>>
|
||||
```
|
||||
|
||||
New storage:
|
||||
``` cpp
|
||||
vtkm::cont::StorageTagCounting
|
||||
```
|
||||
|
||||
#### `ArrayHandleGroupVec`
|
||||
|
||||
Old storage:
|
||||
``` cpp
|
||||
vtkm::cont::internal::StorageTagGroupVec<
|
||||
vtkm::cont::ArrayHandle<ValueType, StorageTag>, N>
|
||||
```
|
||||
|
||||
New storage:
|
||||
``` cpp
|
||||
vtkm::cont::StorageTagGroupVec<StorageTag, N>
|
||||
```
|
||||
|
||||
#### `ArrayHandleGroupVecVariable`
|
||||
|
||||
Old storage:
|
||||
``` cpp
|
||||
vtkm::cont::internal::StorageTagGroupVecVariable<
|
||||
vtkm::cont::ArrayHandle<ValueType, StorageTag1>,
|
||||
vtkm::cont::ArrayHandle<vtkm::Id, StorageTag2>>
|
||||
```
|
||||
|
||||
New storage:
|
||||
``` cpp
|
||||
vtkm::cont::StorageTagGroupVecVariable<StorageTag1, StorageTag2>
|
||||
```
|
||||
|
||||
#### `ArrayHandleIndex`
|
||||
|
||||
Old storage:
|
||||
``` cpp
|
||||
vtkm::cont::StorageTagImplicit<
|
||||
vtkm::cont::detail::ArrayPortalImplicit<vtkm::cont::detail::IndexFunctor>>
|
||||
```
|
||||
|
||||
New storage:
|
||||
``` cpp
|
||||
vtkm::cont::StorageTagIndex
|
||||
```
|
||||
|
||||
#### `ArrayHandlePermutation`
|
||||
|
||||
Old storage:
|
||||
``` cpp
|
||||
vtkm::cont::internal::StorageTagPermutation<
|
||||
vtkm::cont::ArrayHandle<vtkm::Id, StorageTag1>,
|
||||
vtkm::cont::ArrayHandle<ValueType, StorageTag2>>
|
||||
```
|
||||
|
||||
New storage:
|
||||
``` cpp
|
||||
vtkm::cont::StorageTagPermutation<StorageTag1, StorageTag2>
|
||||
```
|
||||
|
||||
#### `ArrayHandleReverse`
|
||||
|
||||
Old storage:
|
||||
``` cpp
|
||||
vtkm::cont::StorageTagReverse<vtkm::cont::ArrayHandle<ValueType, vtkm::cont::StorageTag>>
|
||||
```
|
||||
|
||||
New storage:
|
||||
``` cpp
|
||||
vtkm::cont::StorageTagReverse<StorageTag>
|
||||
```
|
||||
|
||||
#### `ArrayHandleUniformPointCoordinates`
|
||||
|
||||
Old storage:
|
||||
``` cpp
|
||||
vtkm::cont::StorageTagImplicit<vtkm::internal::ArrayPortalUniformPointCoordinates>
|
||||
```
|
||||
|
||||
New Storage:
|
||||
``` cpp
|
||||
vtkm::cont::StorageTagUniformPoints
|
||||
```
|
||||
|
||||
#### `ArrayHandleView`
|
||||
|
||||
Old storage:
|
||||
``` cpp
|
||||
vtkm::cont::StorageTagView<vtkm::cont::ArrayHandle<ValueType, StorageTag>>
|
||||
```
|
||||
|
||||
New storage:
|
||||
``` cpp
|
||||
'vtkm::cont::StorageTagView<StorageTag>
|
||||
```
|
||||
|
||||
|
||||
#### `ArrayPortalZip`
|
||||
|
||||
Old storage:
|
||||
``` cpp
|
||||
vtkm::cont::internal::StorageTagZip<
|
||||
vtkm::cont::ArrayHandle<ValueType1, StorageTag1>,
|
||||
vtkm::cont::ArrayHandle<ValueType2, StorageTag2>>
|
||||
```
|
||||
|
||||
New storage:
|
||||
``` cpp
|
||||
vtkm::cont::StorageTagZip<StorageTag1, StorageTag2>
|
||||
```
|
@ -89,11 +89,11 @@ int main(int argc, char* argv[])
|
||||
vtkm::Id2 vdims;
|
||||
inFile >> vdims[0];
|
||||
inFile >> vdims[1];
|
||||
std::size_t nVertices = static_cast<std::size_t>(vdims[0] * vdims[1]);
|
||||
std::size_t numVertices = static_cast<std::size_t>(vdims[0] * vdims[1]);
|
||||
|
||||
// read data
|
||||
std::vector<vtkm::Float32> values(nVertices);
|
||||
for (std::size_t vertex = 0; vertex < nVertices; vertex++)
|
||||
std::vector<vtkm::Float32> values(numVertices);
|
||||
for (std::size_t vertex = 0; vertex < numVertices; vertex++)
|
||||
{
|
||||
inFile >> values[vertex];
|
||||
}
|
||||
|
@ -90,11 +90,11 @@ int main(int argc, char* argv[])
|
||||
inFile >> vdims[0];
|
||||
inFile >> vdims[1];
|
||||
inFile >> vdims[2];
|
||||
std::size_t nVertices = static_cast<std::size_t>(vdims[0] * vdims[1] * vdims[2]);
|
||||
std::size_t numVertices = static_cast<std::size_t>(vdims[0] * vdims[1] * vdims[2]);
|
||||
|
||||
// read data
|
||||
std::vector<vtkm::Float32> values(nVertices);
|
||||
for (std::size_t vertex = 0; vertex < nVertices; vertex++)
|
||||
std::vector<vtkm::Float32> values(numVertices);
|
||||
for (std::size_t vertex = 0; vertex < numVertices; vertex++)
|
||||
{
|
||||
inFile >> values[vertex];
|
||||
}
|
||||
|
@ -65,6 +65,7 @@
|
||||
#include <vtkm/cont/DataSet.h>
|
||||
#include <vtkm/cont/DataSetBuilderUniform.h>
|
||||
#include <vtkm/cont/DataSetFieldAdd.h>
|
||||
#include <vtkm/cont/Initialize.h>
|
||||
#include <vtkm/cont/RuntimeDeviceTracker.h>
|
||||
#include <vtkm/cont/Timer.h>
|
||||
#include <vtkm/filter/ContourTreeUniformAugmented.h>
|
||||
@ -91,17 +92,16 @@ VTKM_THIRDPARTY_POST_INCLUDE
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#define DEBUG_TIMING
|
||||
|
||||
using ValueType = vtkm::Float32;
|
||||
using BranchType = vtkm::worklet::contourtree_augmented::process_contourtree_inc::Branch<ValueType>;
|
||||
|
||||
namespace cppp2_ns = vtkm::worklet::contourtree_augmented;
|
||||
namespace ctaug_ns = vtkm::worklet::contourtree_augmented;
|
||||
|
||||
// Simple helper class for parsing the command line options
|
||||
class ParseCL
|
||||
@ -173,24 +173,28 @@ int main(int argc, char* argv[])
|
||||
MPI_Comm_size(comm, &size);
|
||||
int numBlocks = size;
|
||||
int blocksPerRank = 1;
|
||||
if (rank == 0)
|
||||
{
|
||||
std::cout << "Running with MPI. #ranks=" << size << std::endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
// initialize vtkm-m (e.g., logging via -v and device via the -d option)
|
||||
vtkm::cont::InitializeOptions vtkm_initialize_options =
|
||||
vtkm::cont::InitializeOptions::RequireDevice;
|
||||
vtkm::cont::InitializeResult vtkm_config =
|
||||
vtkm::cont::Initialize(argc, argv, vtkm_initialize_options);
|
||||
auto device = vtkm_config.Device;
|
||||
|
||||
#ifdef WITH_MPI
|
||||
VTKM_LOG_IF_S(vtkm::cont::LogLevel::Info, rank == 0, "Running with MPI. #ranks=" << size);
|
||||
#else
|
||||
std::cout << "Single node run" << std::endl;
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info, "Single node run");
|
||||
int rank = 0;
|
||||
#endif
|
||||
|
||||
// Setup timing
|
||||
vtkm::Float64 prevTime = 0;
|
||||
vtkm::Float64 currTime = 0;
|
||||
vtkm::cont::Timer totalTime;
|
||||
|
||||
totalTime.Start();
|
||||
if (rank == 0)
|
||||
{
|
||||
std::cout << "ContourTreePPP2Mesh <options> <fileName>" << std::endl;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////
|
||||
// Parse the command line options
|
||||
@ -214,59 +218,30 @@ int main(int argc, char* argv[])
|
||||
// We need the fully augmented tree to compute the branch decomposition
|
||||
if (computeBranchDecomposition && (computeRegularStructure != 1))
|
||||
{
|
||||
std::cout << "Regular structure is required for branch decomposition."
|
||||
" Disabling branch decomposition"
|
||||
<< std::endl;
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Warn,
|
||||
"Regular structure is required for branch decomposition."
|
||||
" Disabling branch decomposition");
|
||||
computeBranchDecomposition = false;
|
||||
}
|
||||
|
||||
std::string device("default");
|
||||
if (parser.hasOption("--device"))
|
||||
{
|
||||
device = parser.getOption("--device");
|
||||
auto& rtTracker = vtkm::cont::GetRuntimeDeviceTracker();
|
||||
if (device == "serial" && rtTracker.CanRunOn(vtkm::cont::DeviceAdapterTagSerial()))
|
||||
{
|
||||
rtTracker.ForceDevice(vtkm::cont::DeviceAdapterTagSerial());
|
||||
}
|
||||
else if (device == "openmp" && rtTracker.CanRunOn(vtkm::cont::DeviceAdapterTagOpenMP()))
|
||||
{
|
||||
rtTracker.ForceDevice(vtkm::cont::DeviceAdapterTagOpenMP());
|
||||
}
|
||||
else if (device == "tbb" && rtTracker.CanRunOn(vtkm::cont::DeviceAdapterTagTBB()))
|
||||
{
|
||||
rtTracker.ForceDevice(vtkm::cont::DeviceAdapterTagTBB());
|
||||
}
|
||||
else if (device == "cuda" && rtTracker.CanRunOn(vtkm::cont::DeviceAdapterTagCuda()))
|
||||
{
|
||||
rtTracker.ForceDevice(vtkm::cont::DeviceAdapterTagCuda());
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Invalid or unavialable device adapter: " << device << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ENABLE_SET_NUM_THREADS
|
||||
int numThreads = tbb::task_scheduler_init::default_num_threads();
|
||||
if (parser.hasOption("--numThreads"))
|
||||
{
|
||||
if (device == "default" &&
|
||||
vtkm::cont::GetRuntimeDeviceTracker().CanRunOn(vtkm::cont::DeviceAdapterTagTBB()))
|
||||
// Print warning about mismatch between the --numThreads and -d/--device opton
|
||||
VTKM_LOG_S_IF(vtkm::cont::LogLevel::Warn,
|
||||
device != vtkm::cont::DeviceAdapterTagTBB,
|
||||
"WARNING: Mismatch between --numThreads and -d/--device option."
|
||||
"numThreads option requires the use of TBB as device. "
|
||||
"Ignoring the numThread option.");
|
||||
// Set the number of threads to be used for TBB
|
||||
if (device == vtkm::cont::DeviceAdapterTagTBB)
|
||||
{
|
||||
std::cout << "--numThreads specified without device. Forcing device as tbb.";
|
||||
device = "tbb";
|
||||
vtkm::cont::GetRuntimeDeviceTracker().ForceDevice(vtkm::cont::DeviceAdapterTagTBB());
|
||||
}
|
||||
|
||||
numThreads = std::stoi(parser.getOption("--numThreads"));
|
||||
if (device != "tbb")
|
||||
{
|
||||
std::cout << "numThreads will be ignored for devices other than tbb";
|
||||
numThreads = std::stoi(parser.getOption("--numThreads"));
|
||||
tbb::task_scheduler_init schedulerInit(numThreads);
|
||||
}
|
||||
}
|
||||
tbb::task_scheduler_init schedulerInit(numThreads);
|
||||
#endif
|
||||
|
||||
// Iso value selection parameters
|
||||
@ -297,21 +272,28 @@ int main(int argc, char* argv[])
|
||||
usePersistenceSorter = false;
|
||||
if ((numLevels > 0) && (!computeBranchDecomposition))
|
||||
{
|
||||
std::cout << "Iso level selection only available when branch decomposition is enabled."
|
||||
" Disabling iso value selection"
|
||||
<< std::endl;
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Warn,
|
||||
"Iso level selection only available when branch decomposition is enabled. "
|
||||
"Disabling iso value selection");
|
||||
numLevels = 0;
|
||||
}
|
||||
|
||||
if (rank == 0 && (argc < 2 || parser.hasOption("--help") || parser.hasOption("-h")))
|
||||
{
|
||||
std::cout << "Parameter is <fileName>" << std::endl;
|
||||
std::cout << "File is expected to be ASCII with either: " << std::endl;
|
||||
std::cout << "ContourTreeAugmented <options> <fileName>" << std::endl;
|
||||
std::cout << std::endl;
|
||||
std::cout << "<fileName> Name of the input data file." << std::endl;
|
||||
std::cout << "The file is expected to be ASCII with either: " << std::endl;
|
||||
std::cout << " - xdim ydim integers for 2D or" << std::endl;
|
||||
std::cout << " - xdim ydim zdim integers for 3D" << std::endl;
|
||||
std::cout << "followed by vector data last dimension varying fastest" << std::endl;
|
||||
|
||||
std::cout << std::endl;
|
||||
std::cout << "----------------------------- VTKM Options -----------------------------"
|
||||
<< std::endl;
|
||||
std::cout << vtkm_config.Usage << std::endl;
|
||||
std::cout << std::endl;
|
||||
std::cout << "------------------------- Contour Tree Options -------------------------"
|
||||
<< std::endl;
|
||||
std::cout << "Options: (Bool options are give via int, i.e. =0 for False and =1 for True)"
|
||||
<< std::endl;
|
||||
std::cout << "--mc Use marching cubes interpolation for contour tree calculation. "
|
||||
@ -328,14 +310,13 @@ int main(int argc, char* argv[])
|
||||
"Requires --augmentTree (Default=True)"
|
||||
<< std::endl;
|
||||
std::cout << "--printCT Print the contour tree. (Default=False)" << std::endl;
|
||||
std::cout << "--device Set the device to use (serial, openmp, tbb, cuda). "
|
||||
"Use the default device if unspecified"
|
||||
<< std::endl;
|
||||
#ifdef ENABLE_SET_NUM_THREADS
|
||||
std::cout << "--numThreads Specifiy the number of threads to use. Available only with TBB."
|
||||
<< std::endl;
|
||||
#endif
|
||||
std::cout << std::endl;
|
||||
std::cout << "---------------------- Isovalue Selection Options ----------------------"
|
||||
<< std::endl;
|
||||
std::cout << "Isovalue selection options: (require --branchDecomp=1 and augmentTree=1)"
|
||||
<< std::endl;
|
||||
std::cout << "--levels=<int> Number of iso-contour levels to be used (default=0, i.e., "
|
||||
@ -352,6 +333,8 @@ int main(int argc, char* argv[])
|
||||
<< std::endl;
|
||||
std::cout << "--method=<int> Method used for selecting relevant iso-values. (default=0)"
|
||||
<< std::endl;
|
||||
std::cout << std::endl;
|
||||
|
||||
#ifdef WITH_MPI
|
||||
MPI_Finalize();
|
||||
#endif
|
||||
@ -360,31 +343,60 @@ int main(int argc, char* argv[])
|
||||
|
||||
if (rank == 0)
|
||||
{
|
||||
std::cout << "Settings:" << std::endl;
|
||||
std::cout << " filename=" << filename << std::endl;
|
||||
std::cout << " device=" << device << std::endl;
|
||||
std::cout << " mc=" << useMarchingCubes << std::endl;
|
||||
std::cout << " augmentTree=" << computeRegularStructure << std::endl;
|
||||
std::cout << " branchDecomp=" << computeBranchDecomposition << std::endl;
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info,
|
||||
std::endl
|
||||
<< " ------------ Settings -----------"
|
||||
<< std::endl
|
||||
<< " filename="
|
||||
<< filename
|
||||
<< std::endl
|
||||
<< " device="
|
||||
<< device.GetName()
|
||||
<< std::endl
|
||||
<< " mc="
|
||||
<< useMarchingCubes
|
||||
<< std::endl
|
||||
<< " augmentTree="
|
||||
<< computeRegularStructure
|
||||
<< std::endl
|
||||
<< " branchDecomp="
|
||||
<< computeBranchDecomposition
|
||||
<< std::endl
|
||||
<<
|
||||
#ifdef WITH_MPI
|
||||
std::cout << " nblocks=" << numBlocks << std::endl;
|
||||
" nblocks=" << numBlocks << std::endl
|
||||
<<
|
||||
#endif
|
||||
#ifdef ENABLE_SET_NUM_THREADS
|
||||
std::cout << " numThreads=" << numThreads << std::endl;
|
||||
" numThreads=" << numThreads << std::endl
|
||||
<<
|
||||
#endif
|
||||
std::cout << " computeIsovalues=" << (numLevels > 0) << std::endl;
|
||||
if (numLevels > 0)
|
||||
{
|
||||
std::cout << " levels=" << numLevels << std::endl;
|
||||
std::cout << " eps=" << eps << std::endl;
|
||||
std::cout << " comp" << numComp << std::endl;
|
||||
std::cout << " type=" << contourType << std::endl;
|
||||
std::cout << " method=" << contourSelectMethod << std::endl;
|
||||
std::cout << " mc=" << useMarchingCubes << std::endl;
|
||||
std::cout << " use" << (usePersistenceSorter ? "PersistenceSorter" : "VolumeSorter")
|
||||
<< std::endl;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
" computeIsovalues=" << (numLevels > 0));
|
||||
VTKM_LOG_IF_S(vtkm::cont::LogLevel::Info,
|
||||
numLevels > 0,
|
||||
std::endl
|
||||
<< " ------------ Settings Isolevel Selection -----------"
|
||||
<< std::endl
|
||||
<< " levels="
|
||||
<< numLevels
|
||||
<< std::endl
|
||||
<< " eps="
|
||||
<< eps
|
||||
<< std::endl
|
||||
<< " comp"
|
||||
<< numComp
|
||||
<< std::endl
|
||||
<< " type="
|
||||
<< contourType
|
||||
<< std::endl
|
||||
<< " method="
|
||||
<< contourSelectMethod
|
||||
<< std::endl
|
||||
<< " mc="
|
||||
<< useMarchingCubes
|
||||
<< std::endl
|
||||
<< " use"
|
||||
<< (usePersistenceSorter ? "PersistenceSorter" : "VolumeSorter"));
|
||||
}
|
||||
currTime = totalTime.GetElapsedTime();
|
||||
vtkm::Float64 startUpTime = currTime - prevTime;
|
||||
@ -449,31 +461,40 @@ int main(int argc, char* argv[])
|
||||
|
||||
// Compute the number of vertices, i.e., xdim * ydim * zdim
|
||||
unsigned short nDims = static_cast<unsigned short>(dims.size());
|
||||
std::size_t nVertices = static_cast<std::size_t>(
|
||||
std::accumulate(dims.begin(), dims.end(), 1, std::multiplies<std::size_t>()));
|
||||
std::size_t numVertices = static_cast<std::size_t>(
|
||||
std::accumulate(dims.begin(), dims.end(), std::size_t(1), std::multiplies<std::size_t>()));
|
||||
|
||||
// Print the mesh metadata
|
||||
if (rank == 0)
|
||||
{
|
||||
std::cout << "Number of dimensions: " << nDims << std::endl;
|
||||
std::cout << "Number of mesh vertices: " << nVertices << std::endl;
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info,
|
||||
std::endl
|
||||
<< " ---------------- Input Mesh Properties --------------"
|
||||
<< std::endl
|
||||
<< " Number of dimensions: "
|
||||
<< nDims
|
||||
<< std::endl
|
||||
<< " Number of mesh vertices: "
|
||||
<< numVertices
|
||||
<< std::endl);
|
||||
}
|
||||
|
||||
// Check for fatal input errors
|
||||
// Check the the number of dimensiosn is either 2D or 3D
|
||||
bool invalidNumDimensions = (nDims < 2 || nDims > 3);
|
||||
// Check if marching cubes is enabled for non 3D data
|
||||
bool invalidMCOption = (useMarchingCubes && nDims != 3);
|
||||
if (rank == 0)
|
||||
{
|
||||
if (invalidNumDimensions)
|
||||
{
|
||||
std::cout << "The input mesh is " << nDims << "D. Input data must be either 2D or 3D."
|
||||
<< std::endl;
|
||||
}
|
||||
if (invalidMCOption)
|
||||
{
|
||||
std::cout << "The input mesh is " << nDims
|
||||
<< "D. Contour tree using marching cubes only supported for 3D data." << std::endl;
|
||||
}
|
||||
}
|
||||
// Log any errors if found on rank 0
|
||||
VTKM_LOG_IF_S(vtkm::cont::LogLevel::Error,
|
||||
invalidNumDimensions && (rank == 0),
|
||||
"The input mesh is " << nDims << "D. "
|
||||
"The input data must be either 2D or 3D.");
|
||||
VTKM_LOG_IF_S(
|
||||
vtkm::cont::LogLevel::Error,
|
||||
invalidMCOption && (rank == 0),
|
||||
"The input mesh is " << nDims << "D. "
|
||||
<< "Contour tree using marching cubes is only supported for 3D data.");
|
||||
// If we found any errors in the setttings than finalize MPI and exit the execution
|
||||
if (invalidNumDimensions || invalidMCOption)
|
||||
{
|
||||
#ifdef WITH_MPI
|
||||
@ -483,8 +504,8 @@ int main(int argc, char* argv[])
|
||||
}
|
||||
|
||||
// Read data
|
||||
std::vector<ValueType> values(nVertices);
|
||||
for (std::size_t vertex = 0; vertex < nVertices; ++vertex)
|
||||
std::vector<ValueType> values(numVertices);
|
||||
for (std::size_t vertex = 0; vertex < numVertices; ++vertex)
|
||||
{
|
||||
inFile >> values[vertex];
|
||||
}
|
||||
@ -505,16 +526,16 @@ int main(int argc, char* argv[])
|
||||
if (nDims == 2)
|
||||
{
|
||||
vtkm::Id2 vdims;
|
||||
vdims[0] = static_cast<vtkm::Id>(dims[0]);
|
||||
vdims[1] = static_cast<vtkm::Id>(dims[1]);
|
||||
vdims[0] = static_cast<vtkm::Id>(dims[1]);
|
||||
vdims[1] = static_cast<vtkm::Id>(dims[0]);
|
||||
inDataSet = dsb.Create(vdims);
|
||||
}
|
||||
// 3D data
|
||||
else
|
||||
{
|
||||
vtkm::Id3 vdims;
|
||||
vdims[0] = static_cast<vtkm::Id>(dims[0]);
|
||||
vdims[1] = static_cast<vtkm::Id>(dims[1]);
|
||||
vdims[0] = static_cast<vtkm::Id>(dims[1]);
|
||||
vdims[1] = static_cast<vtkm::Id>(dims[0]);
|
||||
vdims[2] = static_cast<vtkm::Id>(dims[2]);
|
||||
inDataSet = dsb.Create(vdims);
|
||||
}
|
||||
@ -537,20 +558,19 @@ int main(int argc, char* argv[])
|
||||
localBlockIndices.Allocate(blocksPerRank);
|
||||
localBlockOrigins.Allocate(blocksPerRank);
|
||||
localBlockSizes.Allocate(blocksPerRank);
|
||||
auto localBlockIndicesPortal = localBlockIndices.GetPortalControl();
|
||||
auto localBlockOriginsPortal = localBlockOrigins.GetPortalControl();
|
||||
auto localBlockSizesPortal = localBlockSizes.GetPortalControl();
|
||||
auto localBlockIndicesPortal = localBlockIndices.WritePortal();
|
||||
auto localBlockOriginsPortal = localBlockOrigins.WritePortal();
|
||||
auto localBlockSizesPortal = localBlockSizes.WritePortal();
|
||||
|
||||
{
|
||||
vtkm::Id lastDimSize =
|
||||
(nDims == 2) ? static_cast<vtkm::Id>(dims[1]) : static_cast<vtkm::Id>(dims[2]);
|
||||
if (size > (lastDimSize / 2.))
|
||||
{
|
||||
if (rank == 0)
|
||||
{
|
||||
std::cout << "Number of ranks to large for data. Use " << lastDimSize / 2
|
||||
<< "or fewer ranks" << std::endl;
|
||||
}
|
||||
VTKM_LOG_IF_S(vtkm::cont::LogLevel::Error,
|
||||
rank == 0,
|
||||
"Number of ranks to large for data. Use " << lastDimSize / 2
|
||||
<< "or fewer ranks");
|
||||
MPI_Finalize();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
@ -629,7 +649,7 @@ int main(int argc, char* argv[])
|
||||
prevTime = currTime;
|
||||
|
||||
// Convert the mesh of values into contour tree, pairs of vertex ids
|
||||
vtkm::filter::ContourTreePPP2 filter(useMarchingCubes, computeRegularStructure);
|
||||
vtkm::filter::ContourTreeAugmented filter(useMarchingCubes, computeRegularStructure);
|
||||
|
||||
#ifdef WITH_MPI
|
||||
filter.SetSpatialDecomposition(
|
||||
@ -645,66 +665,41 @@ int main(int argc, char* argv[])
|
||||
vtkm::Float64 computeContourTreeTime = currTime - prevTime;
|
||||
prevTime = currTime;
|
||||
|
||||
#ifdef WITH_MPI
|
||||
#ifdef DEBUG_PRINT
|
||||
if (rank == 0)
|
||||
{
|
||||
std::cout << "----- rank=" << rank << " ----Final Contour Tree Data----------------------------"
|
||||
<< std::endl;
|
||||
filter.GetContourTree().PrintContent();
|
||||
vtkm::worklet::contourtree_augmented::printIndices("Mesh Sort Order", filter.GetSortOrder());
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_TIMING
|
||||
if (rank == 0)
|
||||
{
|
||||
std::cout << "----------------------- " << rank << " --------------------------------------"
|
||||
<< std::endl;
|
||||
std::cout << "-------------------Contour Tree Timings----------------------" << std::endl;
|
||||
|
||||
// Get the timings from the contour tree computation
|
||||
const std::vector<std::pair<std::string, vtkm::Float64>>& contourTreeTimings =
|
||||
filter.GetTimings();
|
||||
for (std::size_t i = 0; i < contourTreeTimings.size(); ++i)
|
||||
std::cout << std::setw(42) << std::left << contourTreeTimings[i].first << ": "
|
||||
<< contourTreeTimings[i].second << " seconds" << std::endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
////////////////////////////////////////////
|
||||
// Compute the branch decomposition
|
||||
////////////////////////////////////////////
|
||||
if (rank == 0 && computeBranchDecomposition && computeRegularStructure)
|
||||
{
|
||||
// Time branch decompostion
|
||||
vtkm::cont::Timer branchDecompTimer;
|
||||
branchDecompTimer.Start();
|
||||
// compute the volume for each hyperarc and superarc
|
||||
cppp2_ns::IdArrayType superarcIntrinsicWeight;
|
||||
cppp2_ns::IdArrayType superarcDependentWeight;
|
||||
cppp2_ns::IdArrayType supernodeTransferWeight;
|
||||
cppp2_ns::IdArrayType hyperarcDependentWeight;
|
||||
|
||||
cppp2_ns::ProcessContourTree::ComputeVolumeWeights(filter.GetContourTree(),
|
||||
ctaug_ns::IdArrayType superarcIntrinsicWeight;
|
||||
ctaug_ns::IdArrayType superarcDependentWeight;
|
||||
ctaug_ns::IdArrayType supernodeTransferWeight;
|
||||
ctaug_ns::IdArrayType hyperarcDependentWeight;
|
||||
ctaug_ns::ProcessContourTree::ComputeVolumeWeights(filter.GetContourTree(),
|
||||
filter.GetNumIterations(),
|
||||
superarcIntrinsicWeight, // (output)
|
||||
superarcDependentWeight, // (output)
|
||||
supernodeTransferWeight, // (output)
|
||||
hyperarcDependentWeight); // (output)
|
||||
std::cout << std::setw(42) << std::left << "Compute Volume Weights"
|
||||
<< ": " << branchDecompTimer.GetElapsedTime() << " seconds" << std::endl;
|
||||
// Record the timings for the branch decomposition
|
||||
std::stringstream timingsStream; // Use a string stream to log in one message
|
||||
timingsStream << std::endl;
|
||||
timingsStream << " --------------- Branch Decomposition Timings " << rank
|
||||
<< " --------------" << std::endl;
|
||||
timingsStream << " " << std::setw(38) << std::left << "Compute Volume Weights"
|
||||
<< ": " << branchDecompTimer.GetElapsedTime() << " seconds" << std::endl;
|
||||
branchDecompTimer.Start();
|
||||
|
||||
// compute the branch decomposition by volume
|
||||
cppp2_ns::IdArrayType whichBranch;
|
||||
cppp2_ns::IdArrayType branchMinimum;
|
||||
cppp2_ns::IdArrayType branchMaximum;
|
||||
cppp2_ns::IdArrayType branchSaddle;
|
||||
cppp2_ns::IdArrayType branchParent;
|
||||
|
||||
cppp2_ns::ProcessContourTree::ComputeVolumeBranchDecomposition(filter.GetContourTree(),
|
||||
ctaug_ns::IdArrayType whichBranch;
|
||||
ctaug_ns::IdArrayType branchMinimum;
|
||||
ctaug_ns::IdArrayType branchMaximum;
|
||||
ctaug_ns::IdArrayType branchSaddle;
|
||||
ctaug_ns::IdArrayType branchParent;
|
||||
ctaug_ns::ProcessContourTree::ComputeVolumeBranchDecomposition(filter.GetContourTree(),
|
||||
superarcDependentWeight,
|
||||
superarcIntrinsicWeight,
|
||||
whichBranch, // (output)
|
||||
@ -712,8 +707,10 @@ int main(int argc, char* argv[])
|
||||
branchMaximum, // (output)
|
||||
branchSaddle, // (output)
|
||||
branchParent); // (output)
|
||||
std::cout << std::setw(42) << std::left << "Compute Volume Branch Decomposition"
|
||||
<< ": " << branchDecompTimer.GetElapsedTime() << " seconds" << std::endl;
|
||||
// Record and log the branch decompostion timings
|
||||
timingsStream << " " << std::setw(38) << std::left << "Compute Volume Branch Decomposition"
|
||||
<< ": " << branchDecompTimer.GetElapsedTime() << " seconds" << std::endl;
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info, timingsStream.str());
|
||||
|
||||
//----main branch decompostion end
|
||||
//----Isovalue seleciton start
|
||||
@ -733,9 +730,9 @@ int main(int argc, char* argv[])
|
||||
|
||||
// create explicit representation of the branch decompostion from the array representation
|
||||
BranchType* branchDecompostionRoot =
|
||||
cppp2_ns::ProcessContourTree::ComputeBranchDecomposition<ValueType>(
|
||||
filter.GetContourTree().superparents,
|
||||
filter.GetContourTree().supernodes,
|
||||
ctaug_ns::ProcessContourTree::ComputeBranchDecomposition<ValueType>(
|
||||
filter.GetContourTree().Superparents,
|
||||
filter.GetContourTree().Supernodes,
|
||||
whichBranch,
|
||||
branchMinimum,
|
||||
branchMaximum,
|
||||
@ -746,11 +743,11 @@ int main(int argc, char* argv[])
|
||||
dataFieldIsSorted);
|
||||
|
||||
#ifdef DEBUG_PRINT
|
||||
branchDecompostionRoot->print(std::cout);
|
||||
branchDecompostionRoot->PrintBranchDecomposition(std::cout);
|
||||
#endif
|
||||
|
||||
// Simplify the contour tree of the branch decompostion
|
||||
branchDecompostionRoot->simplifyToSize(numComp, usePersistenceSorter);
|
||||
branchDecompostionRoot->SimplifyToSize(numComp, usePersistenceSorter);
|
||||
|
||||
// Compute the relevant iso-values
|
||||
std::vector<ValueType> isoValues;
|
||||
@ -759,7 +756,7 @@ int main(int argc, char* argv[])
|
||||
default:
|
||||
case 0:
|
||||
{
|
||||
branchDecompostionRoot->getRelevantValues(static_cast<int>(contourType), eps, isoValues);
|
||||
branchDecompostionRoot->GetRelevantValues(static_cast<int>(contourType), eps, isoValues);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
@ -767,30 +764,32 @@ int main(int argc, char* argv[])
|
||||
vtkm::worklet::contourtree_augmented::process_contourtree_inc::PiecewiseLinearFunction<
|
||||
ValueType>
|
||||
plf;
|
||||
branchDecompostionRoot->accumulateIntervals(static_cast<int>(contourType), eps, plf);
|
||||
branchDecompostionRoot->AccumulateIntervals(static_cast<int>(contourType), eps, plf);
|
||||
isoValues = plf.nLargest(static_cast<unsigned int>(numLevels));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Print the compute iso values
|
||||
std::cout << std::endl;
|
||||
std::cout << "Isovalue Suggestions" << std::endl;
|
||||
std::cout << "====================" << std::endl;
|
||||
std::stringstream isoStream; // Use a string stream to log in one message
|
||||
isoStream << std::endl;
|
||||
isoStream << " ------------------- Isovalue Suggestions --------------------" << std::endl;
|
||||
std::sort(isoValues.begin(), isoValues.end());
|
||||
std::cout << "Isovalues: ";
|
||||
isoStream << " Isovalues: ";
|
||||
for (ValueType val : isoValues)
|
||||
std::cout << val << " ";
|
||||
std::cout << std::endl;
|
||||
|
||||
{
|
||||
isoStream << val << " ";
|
||||
}
|
||||
isoStream << std::endl;
|
||||
// Unique isovalues
|
||||
std::vector<ValueType>::iterator it = std::unique(isoValues.begin(), isoValues.end());
|
||||
isoValues.resize(static_cast<std::size_t>(std::distance(isoValues.begin(), it)));
|
||||
std::cout << isoValues.size() << " Unique Isovalues: ";
|
||||
isoStream << " Unique Isovalues (" << isoValues.size() << "):";
|
||||
for (ValueType val : isoValues)
|
||||
std::cout << val << " ";
|
||||
std::cout << std::endl;
|
||||
std::cout << std::endl;
|
||||
{
|
||||
isoStream << val << " ";
|
||||
}
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info, isoStream.str());
|
||||
} //end if compute isovalue
|
||||
}
|
||||
|
||||
@ -807,13 +806,12 @@ int main(int argc, char* argv[])
|
||||
{
|
||||
std::cout << "Contour Tree" << std::endl;
|
||||
std::cout << "============" << std::endl;
|
||||
cppp2_ns::EdgePairArray saddlePeak;
|
||||
cppp2_ns::ProcessContourTree::CollectSortedSuperarcs(
|
||||
ctaug_ns::EdgePairArray saddlePeak;
|
||||
ctaug_ns::ProcessContourTree::CollectSortedSuperarcs(
|
||||
filter.GetContourTree(), filter.GetSortOrder(), saddlePeak);
|
||||
cppp2_ns::printEdgePairArray(saddlePeak);
|
||||
ctaug_ns::PrintEdgePairArray(saddlePeak);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_TIMING
|
||||
#ifdef WITH_MPI
|
||||
// Force a simple round-robin on the ranks for the summary prints. Its not perfect for MPI but
|
||||
// it works well enough to sort the summaries from the ranks for small-scale debugging.
|
||||
@ -824,52 +822,117 @@ int main(int argc, char* argv[])
|
||||
MPI_Recv(&temp, 1, MPI_INT, (rank - 1), 0, comm, &status);
|
||||
}
|
||||
#endif
|
||||
|
||||
std::cout << "---------------------------" << rank << "----------------------------------"
|
||||
<< std::endl;
|
||||
std::cout << "--------------------------Totals-----------------------------" << std::endl;
|
||||
std::cout << std::setw(42) << std::left << "Start-up"
|
||||
<< ": " << startUpTime << " seconds" << std::endl;
|
||||
std::cout << std::setw(42) << std::left << "Data Read"
|
||||
<< ": " << dataReadTime << " seconds" << std::endl;
|
||||
std::cout << std::setw(42) << std::left << "Build VTKM Dataset"
|
||||
<< ": " << buildDatasetTime << " seconds" << std::endl;
|
||||
std::cout << std::setw(42) << std::left << "Compute Contour Tree"
|
||||
<< ": " << computeContourTreeTime << " seconds" << std::endl;
|
||||
if (computeBranchDecomposition)
|
||||
{
|
||||
std::cout << std::setw(42) << std::left << "Compute Branch Decomposition"
|
||||
<< ": " << computeBranchDecompTime << " seconds" << std::endl;
|
||||
}
|
||||
currTime = totalTime.GetElapsedTime();
|
||||
//vtkm::Float64 miscTime = currTime - startUpTime - dataReadTime - buildDatasetTime - computeContourTreeTime;
|
||||
//if(computeBranchDecomposition) miscTime -= computeBranchDecompTime;
|
||||
//std::cout<<std::setw(42)<<std::left<<"Misc. Times"<<": "<<miscTime<<" seconds"<<std::endl;
|
||||
std::cout << std::setw(42) << std::left << "Total Time"
|
||||
<< ": " << currTime << " seconds" << std::endl;
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info,
|
||||
std::endl
|
||||
<< " -------------------------- Totals "
|
||||
<< rank
|
||||
<< " -----------------------------"
|
||||
<< std::endl
|
||||
<< std::setw(42)
|
||||
<< std::left
|
||||
<< " Start-up"
|
||||
<< ": "
|
||||
<< startUpTime
|
||||
<< " seconds"
|
||||
<< std::endl
|
||||
<< std::setw(42)
|
||||
<< std::left
|
||||
<< " Data Read"
|
||||
<< ": "
|
||||
<< dataReadTime
|
||||
<< " seconds"
|
||||
<< std::endl
|
||||
<< std::setw(42)
|
||||
<< std::left
|
||||
<< " Build VTKM Dataset"
|
||||
<< ": "
|
||||
<< buildDatasetTime
|
||||
<< " seconds"
|
||||
<< std::endl
|
||||
<< std::setw(42)
|
||||
<< std::left
|
||||
<< " Compute Contour Tree"
|
||||
<< ": "
|
||||
<< computeContourTreeTime
|
||||
<< " seconds"
|
||||
<< std::endl
|
||||
<< std::setw(42)
|
||||
<< std::left
|
||||
<< " Compute Branch Decomposition"
|
||||
<< ": "
|
||||
<< computeBranchDecompTime
|
||||
<< " seconds"
|
||||
<< std::endl
|
||||
<< std::setw(42)
|
||||
<< std::left
|
||||
<< " Total Time"
|
||||
<< ": "
|
||||
<< currTime
|
||||
<< " seconds");
|
||||
|
||||
std::cout << "-------------------------------------------------------------" << std::endl;
|
||||
std::cout << "----------------Contour Tree Array Sizes---------------------" << std::endl;
|
||||
const cppp2_ns::ContourTree& ct = filter.GetContourTree();
|
||||
std::cout << std::setw(42) << std::left << "#Nodes"
|
||||
<< ": " << ct.nodes.GetNumberOfValues() << std::endl;
|
||||
std::cout << std::setw(42) << std::left << "#Arcs"
|
||||
<< ": " << ct.arcs.GetNumberOfValues() << std::endl;
|
||||
std::cout << std::setw(42) << std::left << "#Superparents"
|
||||
<< ": " << ct.superparents.GetNumberOfValues() << std::endl;
|
||||
std::cout << std::setw(42) << std::left << "#Superarcs"
|
||||
<< ": " << ct.superarcs.GetNumberOfValues() << std::endl;
|
||||
std::cout << std::setw(42) << std::left << "#Supernodes"
|
||||
<< ": " << ct.supernodes.GetNumberOfValues() << std::endl;
|
||||
std::cout << std::setw(42) << std::left << "#Hyperparents"
|
||||
<< ": " << ct.hyperparents.GetNumberOfValues() << std::endl;
|
||||
std::cout << std::setw(42) << std::left << "#WhenTransferred"
|
||||
<< ": " << ct.whenTransferred.GetNumberOfValues() << std::endl;
|
||||
std::cout << std::setw(42) << std::left << "#Hypernodes"
|
||||
<< ": " << ct.hypernodes.GetNumberOfValues() << std::endl;
|
||||
std::cout << std::setw(42) << std::left << "#Hyperarcs"
|
||||
<< ": " << ct.hyperarcs.GetNumberOfValues() << std::endl;
|
||||
const ctaug_ns::ContourTree& ct = filter.GetContourTree();
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info,
|
||||
std::endl
|
||||
<< " ---------------- Contour Tree Array Sizes ---------------------"
|
||||
<< std::endl
|
||||
<< std::setw(42)
|
||||
<< std::left
|
||||
<< " #Nodes"
|
||||
<< ": "
|
||||
<< ct.Nodes.GetNumberOfValues()
|
||||
<< std::endl
|
||||
<< std::setw(42)
|
||||
<< std::left
|
||||
<< " #Arcs"
|
||||
<< ": "
|
||||
<< ct.Arcs.GetNumberOfValues()
|
||||
<< std::endl
|
||||
<< std::setw(42)
|
||||
<< std::left
|
||||
<< " #Superparents"
|
||||
<< ": "
|
||||
<< ct.Superparents.GetNumberOfValues()
|
||||
<< std::endl
|
||||
<< std::setw(42)
|
||||
<< std::left
|
||||
<< " #Superarcs"
|
||||
<< ": "
|
||||
<< ct.Superarcs.GetNumberOfValues()
|
||||
<< std::endl
|
||||
<< std::setw(42)
|
||||
<< std::left
|
||||
<< " #Supernodes"
|
||||
<< ": "
|
||||
<< ct.Supernodes.GetNumberOfValues()
|
||||
<< std::endl
|
||||
<< std::setw(42)
|
||||
<< std::left
|
||||
<< " #Hyperparents"
|
||||
<< ": "
|
||||
<< ct.Hyperparents.GetNumberOfValues()
|
||||
<< std::endl
|
||||
<< std::setw(42)
|
||||
<< std::left
|
||||
<< " #WhenTransferred"
|
||||
<< ": "
|
||||
<< ct.WhenTransferred.GetNumberOfValues()
|
||||
<< std::endl
|
||||
<< std::setw(42)
|
||||
<< std::left
|
||||
<< " #Hypernodes"
|
||||
<< ": "
|
||||
<< ct.Hypernodes.GetNumberOfValues()
|
||||
<< std::endl
|
||||
<< std::setw(42)
|
||||
<< std::left
|
||||
<< " #Hyperarcs"
|
||||
<< ": "
|
||||
<< ct.Hyperarcs.GetNumberOfValues()
|
||||
<< std::endl);
|
||||
// Flush ouput streams just to make sure everything has been logged (in particular when using MPI)
|
||||
std::cout << std::flush;
|
||||
std::cerr << std::flush;
|
||||
|
||||
#ifdef WITH_MPI
|
||||
// Let the next rank know that it is time to print their summary.
|
||||
@ -879,7 +942,6 @@ int main(int argc, char* argv[])
|
||||
MPI_Send(&message, 1, MPI_INT, (rank + 1), 0, comm);
|
||||
}
|
||||
#endif
|
||||
#endif // DEBUG_TIMING
|
||||
|
||||
#ifdef WITH_MPI
|
||||
MPI_Finalize();
|
||||
|
@ -53,7 +53,7 @@
|
||||
|
||||
struct GameOfLifePolicy : public vtkm::filter::PolicyBase<GameOfLifePolicy>
|
||||
{
|
||||
using FieldTypeList = vtkm::ListTagBase<vtkm::UInt8, vtkm::Vec4ui_8>;
|
||||
using FieldTypeList = vtkm::List<vtkm::UInt8, vtkm::Vec4ui_8>;
|
||||
};
|
||||
|
||||
struct UpdateLifeState : public vtkm::worklet::WorkletPointNeighborhood
|
||||
|
@ -47,7 +47,7 @@ class HelloField : public vtkm::filter::FilterField<HelloField>
|
||||
{
|
||||
public:
|
||||
// Specify that this filter operates on 3-vectors
|
||||
using SupportedTypes = vtkm::TypeListTagFieldVec3;
|
||||
using SupportedTypes = vtkm::TypeListFieldVec3;
|
||||
|
||||
template <typename FieldType, typename Policy>
|
||||
VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& inDataSet,
|
||||
|
@ -43,8 +43,8 @@ VTKM_CONT vtkm::cont::ArrayHandle<T> CreateArray(T min, T max, vtkm::Id numVals)
|
||||
vtkm::cont::ArrayHandle<T> handle;
|
||||
handle.Allocate(numVals);
|
||||
|
||||
std::generate(vtkm::cont::ArrayPortalToIteratorBegin(handle.GetPortalControl()),
|
||||
vtkm::cont::ArrayPortalToIteratorEnd(handle.GetPortalControl()),
|
||||
std::generate(vtkm::cont::ArrayPortalToIteratorBegin(handle.WritePortal()),
|
||||
vtkm::cont::ArrayPortalToIteratorEnd(handle.WritePortal()),
|
||||
[&]() { return static_cast<T>(dis(gen)); });
|
||||
return handle;
|
||||
}
|
||||
@ -92,7 +92,7 @@ int main(int argc, char* argv[])
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> bins;
|
||||
result.GetPartition(0).GetField("histogram").GetData().CopyTo(bins);
|
||||
auto binPortal = bins.GetPortalConstControl();
|
||||
auto binPortal = bins.ReadPortal();
|
||||
if (rank == 0)
|
||||
{
|
||||
// print histogram.
|
||||
|
@ -25,7 +25,7 @@ public:
|
||||
//currently the HistogramMPI filter only works on scalar data.
|
||||
//this mainly has to do with getting the ranges for each bin
|
||||
//would require returning a more complex value type
|
||||
using SupportedTypes = vtkm::TypeListTagScalarAll;
|
||||
using SupportedTypes = vtkm::TypeListScalarAll;
|
||||
|
||||
//Construct a HistogramMPI with a default of 10 bins
|
||||
VTKM_CONT
|
||||
|
@ -58,8 +58,8 @@ public:
|
||||
// reduce local bins first.
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> local;
|
||||
local.Allocate(numBins);
|
||||
std::fill(vtkm::cont::ArrayPortalToIteratorBegin(local.GetPortalControl()),
|
||||
vtkm::cont::ArrayPortalToIteratorEnd(local.GetPortalControl()),
|
||||
std::fill(vtkm::cont::ArrayPortalToIteratorBegin(local.WritePortal()),
|
||||
vtkm::cont::ArrayPortalToIteratorEnd(local.WritePortal()),
|
||||
static_cast<vtkm::Id>(0));
|
||||
for (const auto& lbins : this->LocalBlocks)
|
||||
{
|
||||
@ -70,8 +70,8 @@ public:
|
||||
|
||||
// converting to std::vector
|
||||
std::vector<vtkm::Id> send_buf(static_cast<std::size_t>(numBins));
|
||||
std::copy(vtkm::cont::ArrayPortalToIteratorBegin(local.GetPortalConstControl()),
|
||||
vtkm::cont::ArrayPortalToIteratorEnd(local.GetPortalConstControl()),
|
||||
std::copy(vtkm::cont::ArrayPortalToIteratorBegin(local.ReadPortal()),
|
||||
vtkm::cont::ArrayPortalToIteratorEnd(local.ReadPortal()),
|
||||
send_buf.begin());
|
||||
|
||||
std::vector<vtkm::Id> recv_buf(static_cast<std::size_t>(numBins));
|
||||
@ -88,7 +88,7 @@ public:
|
||||
local.Allocate(numBins);
|
||||
std::copy(recv_buf.begin(),
|
||||
recv_buf.end(),
|
||||
vtkm::cont::ArrayPortalToIteratorBegin(local.GetPortalControl()));
|
||||
vtkm::cont::ArrayPortalToIteratorBegin(local.WritePortal()));
|
||||
return local;
|
||||
}
|
||||
return vtkm::cont::ArrayHandle<vtkm::Id>();
|
||||
@ -158,7 +158,7 @@ inline VTKM_CONT void HistogramMPI::PreExecute(const vtkm::cont::PartitionedData
|
||||
{
|
||||
throw vtkm::cont::ErrorFilterExecution("expecting scalar field.");
|
||||
}
|
||||
this->ComputedRange = handle.GetPortalConstControl().Get(0);
|
||||
this->ComputedRange = handle.ReadPortal().Get(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -65,7 +65,7 @@ vtkm::cont::DataSet make3DRectilinearDataSet(double time)
|
||||
double vec[3];
|
||||
double loc[3] = { i * xdiff + xmin, j * ydiff + ymax, k * zdiff + zmin };
|
||||
field.calculateVelocity(loc, time, vec);
|
||||
velocityField.GetPortalControl().Set(count, vtkm::Vec3f_64(vec[0], vec[1], vec[2]));
|
||||
velocityField.WritePortal().Set(count, vtkm::Vec3f_64(vec[0], vec[1], vec[2]));
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
@ -25,8 +25,7 @@ using RuntimeTaskQueue = TaskQueue<std::function<void()>>;
|
||||
class MultiDeviceGradient : public vtkm::filter::FilterField<MultiDeviceGradient>
|
||||
{
|
||||
public:
|
||||
using SupportedTypes =
|
||||
vtkm::ListTagBase<vtkm::Float32, vtkm::Float64, vtkm::Vec3f_32, vtkm::Vec3f_64>;
|
||||
using SupportedTypes = vtkm::List<vtkm::Float32, vtkm::Float64, vtkm::Vec3f_32, vtkm::Vec3f_64>;
|
||||
|
||||
//Construct a MultiDeviceGradient and worker pool
|
||||
VTKM_CONT
|
||||
|
@ -57,20 +57,21 @@ int main(int argc, char** argv)
|
||||
|
||||
//create seeds randomly placed withing the bounding box of the data.
|
||||
vtkm::Bounds bounds = ds.GetCoordinateSystem().GetBounds();
|
||||
std::vector<vtkm::Vec3f> seeds;
|
||||
std::vector<vtkm::Particle> seeds;
|
||||
|
||||
for (int i = 0; i < numSeeds; i++)
|
||||
for (vtkm::Id i = 0; i < numSeeds; i++)
|
||||
{
|
||||
vtkm::Vec3f p;
|
||||
vtkm::Particle p;
|
||||
vtkm::FloatDefault rx = (vtkm::FloatDefault)rand() / (vtkm::FloatDefault)RAND_MAX;
|
||||
vtkm::FloatDefault ry = (vtkm::FloatDefault)rand() / (vtkm::FloatDefault)RAND_MAX;
|
||||
vtkm::FloatDefault rz = (vtkm::FloatDefault)rand() / (vtkm::FloatDefault)RAND_MAX;
|
||||
p[0] = static_cast<vtkm::FloatDefault>(bounds.X.Min + rx * bounds.X.Length());
|
||||
p[1] = static_cast<vtkm::FloatDefault>(bounds.Y.Min + ry * bounds.Y.Length());
|
||||
p[2] = static_cast<vtkm::FloatDefault>(bounds.Z.Min + rz * bounds.Z.Length());
|
||||
p.Pos[0] = static_cast<vtkm::FloatDefault>(bounds.X.Min + rx * bounds.X.Length());
|
||||
p.Pos[1] = static_cast<vtkm::FloatDefault>(bounds.Y.Min + ry * bounds.Y.Length());
|
||||
p.Pos[2] = static_cast<vtkm::FloatDefault>(bounds.Z.Min + rz * bounds.Z.Length());
|
||||
p.ID = i;
|
||||
seeds.push_back(p);
|
||||
}
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec3f> seedArray = vtkm::cont::make_ArrayHandle(seeds);
|
||||
auto seedArray = vtkm::cont::make_ArrayHandle(seeds);
|
||||
|
||||
//compute streamlines
|
||||
vtkm::filter::Streamline streamline;
|
||||
|
@ -17,3 +17,6 @@ target_link_libraries(RedistributePoints PRIVATE vtkm_filter)
|
||||
vtkm_add_target_information(RedistributePoints
|
||||
DROP_UNUSED_SYMBOLS MODIFY_CUDA_FLAGS
|
||||
DEVICE_SOURCES RedistributePoints.cxx)
|
||||
|
||||
set_property(TARGET RedistributePoints PROPERTY CUDA_VISIBILITY_PRESET "hidden")
|
||||
set_property(TARGET RedistributePoints PROPERTY CXX_VISIBILITY_PRESET "hidden")
|
||||
|
@ -70,8 +70,21 @@ int main(int argc, char** argv)
|
||||
vtkm::cont::DataSet ds2 = reader2.ReadDataSet();
|
||||
|
||||
// Use the coordinate system as seeds for performing advection
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec3f> seeds;
|
||||
vtkm::cont::ArrayCopy(ds1.GetCoordinateSystem().GetData(), seeds);
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec3f> pts;
|
||||
vtkm::cont::ArrayCopy(ds1.GetCoordinateSystem().GetData(), pts);
|
||||
vtkm::cont::ArrayHandle<vtkm::Particle> seeds;
|
||||
|
||||
vtkm::Id numPts = pts.GetNumberOfValues();
|
||||
seeds.Allocate(numPts);
|
||||
auto ptsPortal = pts.ReadPortal();
|
||||
auto seedPortal = seeds.ReadPortal();
|
||||
for (vtkm::Id i = 0; i < numPts; i++)
|
||||
{
|
||||
vtkm::Particle p;
|
||||
p.Pos = ptsPortal.Get(i);
|
||||
p.ID = i;
|
||||
seedPortal.Set(i, p);
|
||||
}
|
||||
|
||||
// Instantiate the filter by providing necessary parameters.
|
||||
// Necessary parameters are :
|
||||
|
191
vtkm/Algorithms.h
Normal file
191
vtkm/Algorithms.h
Normal file
@ -0,0 +1,191 @@
|
||||
//============================================================================
|
||||
// Copyright (c) Kitware, Inc.
|
||||
// All rights reserved.
|
||||
// See LICENSE.txt for details.
|
||||
//
|
||||
// This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
// PURPOSE. See the above copyright notice for more information.
|
||||
//============================================================================
|
||||
|
||||
#ifndef vtk_m_Algorithms_h
|
||||
#define vtk_m_Algorithms_h
|
||||
|
||||
#include <vtkm/cont/ArrayPortalToIterators.h>
|
||||
|
||||
#include <vtkm/BinaryPredicates.h>
|
||||
|
||||
#include <vtkm/internal/Configure.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
|
||||
/// Similar to std::lower_bound and std::upper_bound, but returns an iterator
|
||||
/// to any matching item (rather than a specific one). Returns @a last when
|
||||
/// @a val is not found.
|
||||
/// @{
|
||||
template <typename IterT, typename T, typename Comp>
|
||||
VTKM_EXEC_CONT IterT BinarySearch(IterT first, IterT last, const T& val, Comp comp)
|
||||
{
|
||||
auto len = last - first;
|
||||
while (len != 0)
|
||||
{
|
||||
const auto halfLen = len / 2;
|
||||
IterT mid = first + halfLen;
|
||||
if (comp(*mid, val))
|
||||
{
|
||||
first = mid + 1;
|
||||
len -= halfLen + 1;
|
||||
}
|
||||
else if (comp(val, *mid))
|
||||
{
|
||||
len = halfLen;
|
||||
}
|
||||
else
|
||||
{
|
||||
return mid; // found element
|
||||
}
|
||||
}
|
||||
return last; // did not find element
|
||||
}
|
||||
|
||||
template <typename IterT, typename T>
|
||||
VTKM_EXEC_CONT IterT BinarySearch(IterT first, IterT last, const T& val)
|
||||
{
|
||||
return vtkm::BinarySearch(first, last, val, vtkm::SortLess{});
|
||||
}
|
||||
/// @}
|
||||
|
||||
/// Similar to std::lower_bound and std::upper_bound, but returns the index of
|
||||
/// any matching item (rather than a specific one). Returns -1 when @a val is not
|
||||
/// found.
|
||||
/// @{
|
||||
template <typename PortalT, typename T, typename Comp>
|
||||
VTKM_EXEC_CONT vtkm::Id BinarySearch(const PortalT& portal, const T& val, Comp comp)
|
||||
{
|
||||
auto first = vtkm::cont::ArrayPortalToIteratorBegin(portal);
|
||||
auto last = vtkm::cont::ArrayPortalToIteratorEnd(portal);
|
||||
auto result = vtkm::BinarySearch(first, last, val, comp);
|
||||
return result == last ? static_cast<vtkm::Id>(-1) : static_cast<vtkm::Id>(result - first);
|
||||
}
|
||||
|
||||
// Return -1 if not found
|
||||
template <typename PortalT, typename T>
|
||||
VTKM_EXEC_CONT vtkm::Id BinarySearch(const PortalT& portal, const T& val)
|
||||
{
|
||||
auto first = vtkm::cont::ArrayPortalToIteratorBegin(portal);
|
||||
auto last = vtkm::cont::ArrayPortalToIteratorEnd(portal);
|
||||
auto result = vtkm::BinarySearch(first, last, val, vtkm::SortLess{});
|
||||
return result == last ? static_cast<vtkm::Id>(-1) : static_cast<vtkm::Id>(result - first);
|
||||
}
|
||||
/// @}
|
||||
|
||||
/// Implementation of std::lower_bound or std::upper_bound that is appropriate
|
||||
/// for both control and execution environments.
|
||||
/// The overloads that take portals return indices instead of iterators.
|
||||
/// @{
|
||||
template <typename IterT, typename T, typename Comp>
|
||||
VTKM_EXEC_CONT IterT LowerBound(IterT first, IterT last, const T& val, Comp comp)
|
||||
{
|
||||
#ifdef VTKM_CUDA
|
||||
auto len = last - first;
|
||||
while (len != 0)
|
||||
{
|
||||
const auto halfLen = len / 2;
|
||||
IterT mid = first + halfLen;
|
||||
if (comp(*mid, val))
|
||||
{
|
||||
first = mid + 1;
|
||||
len -= halfLen + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
len = halfLen;
|
||||
}
|
||||
}
|
||||
return first;
|
||||
#else // VTKM_CUDA
|
||||
return std::lower_bound(first, last, val, std::move(comp));
|
||||
#endif // VTKM_CUDA
|
||||
}
|
||||
|
||||
template <typename IterT, typename T>
|
||||
VTKM_EXEC_CONT IterT LowerBound(IterT first, IterT last, const T& val)
|
||||
{
|
||||
return vtkm::LowerBound(first, last, val, vtkm::SortLess{});
|
||||
}
|
||||
|
||||
template <typename PortalT, typename T, typename Comp>
|
||||
VTKM_EXEC_CONT vtkm::Id LowerBound(const PortalT& portal, const T& val, Comp comp)
|
||||
{
|
||||
auto first = vtkm::cont::ArrayPortalToIteratorBegin(portal);
|
||||
auto last = vtkm::cont::ArrayPortalToIteratorEnd(portal);
|
||||
auto result = vtkm::LowerBound(first, last, val, comp);
|
||||
return static_cast<vtkm::Id>(result - first);
|
||||
}
|
||||
|
||||
template <typename PortalT, typename T>
|
||||
VTKM_EXEC_CONT vtkm::Id LowerBound(const PortalT& portal, const T& val)
|
||||
{
|
||||
auto first = vtkm::cont::ArrayPortalToIteratorBegin(portal);
|
||||
auto last = vtkm::cont::ArrayPortalToIteratorEnd(portal);
|
||||
auto result = vtkm::LowerBound(first, last, val, vtkm::SortLess{});
|
||||
return static_cast<vtkm::Id>(result - first);
|
||||
}
|
||||
|
||||
template <typename IterT, typename T, typename Comp>
|
||||
VTKM_EXEC_CONT IterT UpperBound(IterT first, IterT last, const T& val, Comp comp)
|
||||
{
|
||||
#ifdef VTKM_CUDA
|
||||
auto len = last - first;
|
||||
while (len != 0)
|
||||
{
|
||||
const auto halfLen = len / 2;
|
||||
IterT mid = first + halfLen;
|
||||
if (!comp(val, *mid))
|
||||
{
|
||||
first = mid + 1;
|
||||
len -= halfLen + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
len = halfLen;
|
||||
}
|
||||
}
|
||||
return first;
|
||||
#else // VTKM_CUDA
|
||||
return std::upper_bound(first, last, val, std::move(comp));
|
||||
#endif // VTKM_CUDA
|
||||
}
|
||||
|
||||
template <typename IterT, typename T>
|
||||
VTKM_EXEC_CONT IterT UpperBound(IterT first, IterT last, const T& val)
|
||||
{
|
||||
return vtkm::UpperBound(first, last, val, vtkm::SortLess{});
|
||||
}
|
||||
|
||||
template <typename PortalT, typename T, typename Comp>
|
||||
VTKM_EXEC_CONT vtkm::Id UpperBound(const PortalT& portal, const T& val, Comp comp)
|
||||
{
|
||||
auto first = vtkm::cont::ArrayPortalToIteratorBegin(portal);
|
||||
auto last = vtkm::cont::ArrayPortalToIteratorEnd(portal);
|
||||
auto result = vtkm::UpperBound(first, last, val, comp);
|
||||
return static_cast<vtkm::Id>(result - first);
|
||||
}
|
||||
|
||||
template <typename PortalT, typename T>
|
||||
VTKM_EXEC_CONT vtkm::Id UpperBound(const PortalT& portal, const T& val)
|
||||
{
|
||||
auto first = vtkm::cont::ArrayPortalToIteratorBegin(portal);
|
||||
auto last = vtkm::cont::ArrayPortalToIteratorEnd(portal);
|
||||
auto result = vtkm::UpperBound(first, last, val, vtkm::SortLess{});
|
||||
return static_cast<vtkm::Id>(result - first);
|
||||
}
|
||||
/// @}
|
||||
|
||||
} // end namespace vtkm
|
||||
|
||||
#endif // vtk_m_Algorithms_h
|
@ -13,7 +13,7 @@
|
||||
|
||||
#include <vtkm/internal/Configure.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <cassert>
|
||||
|
||||
/// \def VTKM_ASSERT(condition)
|
||||
///
|
||||
@ -34,6 +34,7 @@
|
||||
#elif !defined(NDEBUG) && !defined(VTKM_NO_ASSERT)
|
||||
//Only assert if we are in debug mode and don't have VTKM_NO_ASSERT defined
|
||||
#define VTKM_ASSERT(condition) assert(condition)
|
||||
#define VTKM_ASSERTS_CHECKED
|
||||
#else
|
||||
#define VTKM_ASSERT(condition) (void)(condition)
|
||||
#endif
|
||||
|
@ -29,26 +29,48 @@ namespace vtkm
|
||||
|
||||
/// Binary Predicate that takes two arguments argument \c x, and \c y and
|
||||
/// returns sum (addition) of the two values.
|
||||
/// Note: Requires Type \p T implement the + operator.
|
||||
/// @note Requires a suitable definition of `operator+(T, U)`.
|
||||
struct Sum
|
||||
{
|
||||
template <typename T>
|
||||
VTKM_EXEC_CONT T operator()(const T& x, const T& y) const
|
||||
template <typename T, typename U>
|
||||
VTKM_EXEC_CONT auto operator()(const T& x, const U& y) const -> decltype(x + y)
|
||||
{
|
||||
return x + y;
|
||||
}
|
||||
|
||||
// If both types are the same integral type, explicitly cast the result to
|
||||
// type T to avoid narrowing conversion warnings from operations that promote
|
||||
// to int (e.g. `int operator+(char, char)`)
|
||||
template <typename T>
|
||||
VTKM_EXEC_CONT
|
||||
typename std::enable_if<std::is_integral<T>::value && sizeof(T) < sizeof(int), T>::type
|
||||
operator()(const T& x, const T& y) const
|
||||
{
|
||||
return static_cast<T>(x + y);
|
||||
}
|
||||
};
|
||||
|
||||
/// Binary Predicate that takes two arguments argument \c x, and \c y and
|
||||
/// returns product (multiplication) of the two values.
|
||||
/// Note: Requires Type \p T implement the * operator.
|
||||
/// @note Requires a suitable definition of `operator*(T, U)`.
|
||||
struct Product
|
||||
{
|
||||
template <typename T>
|
||||
VTKM_EXEC_CONT T operator()(const T& x, const T& y) const
|
||||
template <typename T, typename U>
|
||||
VTKM_EXEC_CONT auto operator()(const T& x, const U& y) const -> decltype(x * y)
|
||||
{
|
||||
return x * y;
|
||||
}
|
||||
|
||||
// If both types are the same integral type, explicitly cast the result to
|
||||
// type T to avoid narrowing conversion warnings from operations that promote
|
||||
// to int (e.g. `int operator+(char, char)`)
|
||||
template <typename T>
|
||||
VTKM_EXEC_CONT
|
||||
typename std::enable_if<std::is_integral<T>::value && sizeof(T) < sizeof(int), T>::type
|
||||
operator()(const T& x, const T& y) const
|
||||
{
|
||||
return static_cast<T>(x * y);
|
||||
}
|
||||
};
|
||||
|
||||
#if (defined(VTKM_GCC) || defined(VTKM_CLANG))
|
||||
@ -57,12 +79,13 @@ struct Product
|
||||
|
||||
/// Binary Predicate that takes two arguments argument \c x, and \c y and
|
||||
/// returns the \c x if x > y otherwise returns \c y.
|
||||
/// Note: Requires Type \p T implement the < operator.
|
||||
/// @note Requires a suitable definition of `bool operator<(T, U)` and that
|
||||
/// `T` and `U` share a common type.
|
||||
//needs to be full length to not clash with vtkm::math function Max.
|
||||
struct Maximum
|
||||
{
|
||||
template <typename T>
|
||||
VTKM_EXEC_CONT T operator()(const T& x, const T& y) const
|
||||
template <typename T, typename U>
|
||||
VTKM_EXEC_CONT typename std::common_type<T, U>::type operator()(const T& x, const U& y) const
|
||||
{
|
||||
return x < y ? y : x;
|
||||
}
|
||||
@ -70,19 +93,20 @@ struct Maximum
|
||||
|
||||
/// Binary Predicate that takes two arguments argument \c x, and \c y and
|
||||
/// returns the \c x if x < y otherwise returns \c y.
|
||||
/// Note: Requires Type \p T implement the < operator.
|
||||
/// @note Requires a suitable definition of `bool operator<(T, U)` and that
|
||||
/// `T` and `U` share a common type.
|
||||
//needs to be full length to not clash with vtkm::math function Min.
|
||||
struct Minimum
|
||||
{
|
||||
template <typename T>
|
||||
VTKM_EXEC_CONT T operator()(const T& x, const T& y) const
|
||||
template <typename T, typename U>
|
||||
VTKM_EXEC_CONT typename std::common_type<T, U>::type operator()(const T& x, const U& y) const
|
||||
{
|
||||
return x < y ? x : y;
|
||||
}
|
||||
};
|
||||
|
||||
/// Binary Predicate that takes two arguments argument \c x, and \c y and
|
||||
/// returns a vtkm::Vec<T,2> that represents the minimum and maximum values
|
||||
/// returns a vtkm::Vec<T,2> that represents the minimum and maximum values.
|
||||
/// Note: Requires Type \p T implement the vtkm::Min and vtkm::Max functions.
|
||||
template <typename T>
|
||||
struct MinAndMax
|
||||
@ -117,38 +141,71 @@ struct MinAndMax
|
||||
|
||||
/// Binary Predicate that takes two arguments argument \c x, and \c y and
|
||||
/// returns the bitwise operation <tt>x&y</tt>
|
||||
/// Note: Requires Type \p T implement the & operator.
|
||||
/// @note Requires a suitable definition of `operator&(T, U)`.
|
||||
struct BitwiseAnd
|
||||
{
|
||||
template <typename T>
|
||||
VTKM_EXEC_CONT T operator()(const T& x, const T& y) const
|
||||
template <typename T, typename U>
|
||||
VTKM_EXEC_CONT auto operator()(const T& x, const U& y) const -> decltype(x & y)
|
||||
{
|
||||
return x & y;
|
||||
}
|
||||
|
||||
// If both types are the same integral type, explicitly cast the result to
|
||||
// type T to avoid narrowing conversion warnings from operations that promote
|
||||
// to int (e.g. `int operator+(char, char)`)
|
||||
template <typename T>
|
||||
VTKM_EXEC_CONT
|
||||
typename std::enable_if<std::is_integral<T>::value && sizeof(T) < sizeof(int), T>::type
|
||||
operator()(const T& x, const T& y) const
|
||||
{
|
||||
return static_cast<T>(x & y);
|
||||
}
|
||||
};
|
||||
|
||||
/// Binary Predicate that takes two arguments argument \c x, and \c y and
|
||||
/// returns the bitwise operation <tt>x|y</tt>
|
||||
/// Note: Requires Type \p T implement the | operator.
|
||||
/// @note Requires a suitable definition of `operator&(T, U)`.
|
||||
struct BitwiseOr
|
||||
{
|
||||
template <typename T>
|
||||
VTKM_EXEC_CONT T operator()(const T& x, const T& y) const
|
||||
template <typename T, typename U>
|
||||
VTKM_EXEC_CONT auto operator()(const T& x, const U& y) const -> decltype(x | y)
|
||||
{
|
||||
return x | y;
|
||||
}
|
||||
|
||||
// If both types are the same integral type, explicitly cast the result to
|
||||
// type T to avoid narrowing conversion warnings from operations that promote
|
||||
// to int (e.g. `int operator+(char, char)`)
|
||||
template <typename T>
|
||||
VTKM_EXEC_CONT
|
||||
typename std::enable_if<std::is_integral<T>::value && sizeof(T) < sizeof(int), T>::type
|
||||
operator()(const T& x, const T& y) const
|
||||
{
|
||||
return static_cast<T>(x | y);
|
||||
}
|
||||
};
|
||||
|
||||
/// Binary Predicate that takes two arguments argument \c x, and \c y and
|
||||
/// returns the bitwise operation <tt>x^y</tt>
|
||||
/// Note: Requires Type \p T implement the ^ operator.
|
||||
/// @note Requires a suitable definition of `operator&(T, U)`.
|
||||
struct BitwiseXor
|
||||
{
|
||||
template <typename T>
|
||||
VTKM_EXEC_CONT T operator()(const T& x, const T& y) const
|
||||
template <typename T, typename U>
|
||||
VTKM_EXEC_CONT auto operator()(const T& x, const U& y) const -> decltype(x ^ y)
|
||||
{
|
||||
return x ^ y;
|
||||
}
|
||||
|
||||
// If both types are the same integral type, explicitly cast the result to
|
||||
// type T to avoid narrowing conversion warnings from operations that promote
|
||||
// to int (e.g. `int operator+(char, char)`)
|
||||
template <typename T>
|
||||
VTKM_EXEC_CONT
|
||||
typename std::enable_if<std::is_integral<T>::value && sizeof(T) < sizeof(int), T>::type
|
||||
operator()(const T& x, const T& y) const
|
||||
{
|
||||
return static_cast<T>(x ^ y);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace vtkm
|
||||
|
@ -15,37 +15,37 @@
|
||||
namespace vtkm
|
||||
{
|
||||
|
||||
/// Binary Predicate that takes two arguments argument \c x, and \c y and
|
||||
/// returns True if and only if \c x is equal to \c y.
|
||||
/// Note: Requires Type \p T implement the == operator.
|
||||
struct Equal
|
||||
{
|
||||
template <typename T>
|
||||
VTKM_EXEC_CONT bool operator()(const T& x, const T& y) const
|
||||
{
|
||||
return x == y;
|
||||
}
|
||||
};
|
||||
|
||||
/// Binary Predicate that takes two arguments argument \c x, and \c y and
|
||||
/// returns True if and only if \c x is not equal to \c y.
|
||||
/// Note: Requires Type \p T implement the != operator.
|
||||
/// @note: Requires that types T and U are comparable with !=.
|
||||
struct NotEqual
|
||||
{
|
||||
template <typename T>
|
||||
VTKM_EXEC_CONT bool operator()(const T& x, const T& y) const
|
||||
template <typename T, typename U>
|
||||
VTKM_EXEC_CONT bool operator()(const T& x, const U& y) const
|
||||
{
|
||||
return x != y;
|
||||
}
|
||||
};
|
||||
|
||||
/// Binary Predicate that takes two arguments argument \c x, and \c y and
|
||||
/// returns True if and only if \c x is equal to \c y.
|
||||
/// @note: Requires that types T and U are comparable with !=.
|
||||
struct Equal
|
||||
{
|
||||
template <typename T, typename U>
|
||||
VTKM_EXEC_CONT bool operator()(const T& x, const U& y) const
|
||||
{
|
||||
return x == y;
|
||||
}
|
||||
};
|
||||
|
||||
/// Binary Predicate that takes two arguments argument \c x, and \c y and
|
||||
/// returns True if and only if \c x is less than \c y.
|
||||
/// Note: Requires Type \p T implement the < operator.
|
||||
/// @note: Requires that types T and U are comparable with <.
|
||||
struct SortLess
|
||||
{
|
||||
template <typename T>
|
||||
VTKM_EXEC_CONT bool operator()(const T& x, const T& y) const
|
||||
template <typename T, typename U>
|
||||
VTKM_EXEC_CONT bool operator()(const T& x, const U& y) const
|
||||
{
|
||||
return x < y;
|
||||
}
|
||||
@ -53,12 +53,12 @@ struct SortLess
|
||||
|
||||
/// Binary Predicate that takes two arguments argument \c x, and \c y and
|
||||
/// returns True if and only if \c x is greater than \c y.
|
||||
/// Note: Requires Type \p T implement the < operator, as we invert the
|
||||
/// comparison
|
||||
/// @note: Requires that types T and U are comparable via operator<(U, T).
|
||||
|
||||
struct SortGreater
|
||||
{
|
||||
template <typename T>
|
||||
VTKM_EXEC_CONT bool operator()(const T& x, const T& y) const
|
||||
template <typename T, typename U>
|
||||
VTKM_EXEC_CONT bool operator()(const T& x, const U& y) const
|
||||
{
|
||||
return y < x;
|
||||
}
|
||||
@ -66,12 +66,12 @@ struct SortGreater
|
||||
|
||||
/// Binary Predicate that takes two arguments argument \c x, and \c y and
|
||||
/// returns True if and only if \c x and \c y are True.
|
||||
/// Note: Requires Type \p T to be convertible to \c bool or implement the
|
||||
/// && operator.
|
||||
/// @note: Requires that types T and U are comparable with &&.
|
||||
|
||||
struct LogicalAnd
|
||||
{
|
||||
template <typename T>
|
||||
VTKM_EXEC_CONT bool operator()(const T& x, const T& y) const
|
||||
template <typename T, typename U>
|
||||
VTKM_EXEC_CONT bool operator()(const T& x, const U& y) const
|
||||
{
|
||||
return x && y;
|
||||
}
|
||||
@ -79,12 +79,11 @@ struct LogicalAnd
|
||||
|
||||
/// Binary Predicate that takes two arguments argument \c x, and \c y and
|
||||
/// returns True if and only if \c x or \c y is True.
|
||||
/// Note: Requires Type \p T to be convertible to \c bool or implement the
|
||||
/// || operator.
|
||||
/// @note: Requires that types T and U are comparable with ||.
|
||||
struct LogicalOr
|
||||
{
|
||||
template <typename T>
|
||||
VTKM_EXEC_CONT bool operator()(const T& x, const T& y) const
|
||||
template <typename T, typename U>
|
||||
VTKM_EXEC_CONT bool operator()(const T& x, const U& y) const
|
||||
{
|
||||
return x || y;
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
#ifndef vtk_m_Bitset_h
|
||||
#define vtk_m_Bitset_h
|
||||
|
||||
#include <assert.h>
|
||||
#include <cassert>
|
||||
#include <limits>
|
||||
#include <vtkm/Types.h>
|
||||
#include <vtkm/internal/ExportMacros.h>
|
||||
@ -22,18 +22,27 @@ namespace vtkm
|
||||
/// \brief A bitmap to serve different needs.
|
||||
/// Ex. Editing particular bits in a byte(s), checkint if particular bit values
|
||||
/// are present or not. Once Cuda supports std::bitset, we should use the
|
||||
/// standard one if possible
|
||||
/// standard one if possible. Additional cast in logical operations are required
|
||||
/// to avoid compiler warnings when using 16 or 8 bit MaskType.
|
||||
template <typename MaskType>
|
||||
struct Bitset
|
||||
{
|
||||
VTKM_EXEC_CONT void set(vtkm::Id bitIndex)
|
||||
{
|
||||
this->Mask = this->Mask | (static_cast<MaskType>(1) << bitIndex);
|
||||
this->Mask = static_cast<MaskType>(this->Mask | (static_cast<MaskType>(1) << bitIndex));
|
||||
}
|
||||
|
||||
VTKM_EXEC_CONT void set(vtkm::Id bitIndex, bool val)
|
||||
{
|
||||
if (val)
|
||||
this->set(bitIndex);
|
||||
else
|
||||
this->reset(bitIndex);
|
||||
}
|
||||
|
||||
VTKM_EXEC_CONT void reset(vtkm::Id bitIndex)
|
||||
{
|
||||
this->Mask = this->Mask & ~(static_cast<MaskType>(1) << bitIndex);
|
||||
this->Mask = static_cast<MaskType>(this->Mask & ~(static_cast<MaskType>(1) << bitIndex));
|
||||
}
|
||||
|
||||
VTKM_EXEC_CONT void toggle(vtkm::Id bitIndex)
|
||||
@ -41,7 +50,7 @@ struct Bitset
|
||||
this->Mask = this->Mask ^ (static_cast<MaskType>(0) << bitIndex);
|
||||
}
|
||||
|
||||
VTKM_EXEC_CONT bool test(vtkm::Id bitIndex)
|
||||
VTKM_EXEC_CONT bool test(vtkm::Id bitIndex) const
|
||||
{
|
||||
return ((this->Mask & (static_cast<MaskType>(1) << bitIndex)) != 0);
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ vtkm_install_headers(
|
||||
vtkm ${VTKm_BINARY_INCLUDE_DIR}/${kit_dir}/Version.h)
|
||||
|
||||
set(headers
|
||||
Algorithms.h
|
||||
Assert.h
|
||||
BinaryPredicates.h
|
||||
BinaryOperators.h
|
||||
@ -25,15 +26,18 @@ set(headers
|
||||
CellClassification.h
|
||||
CellShape.h
|
||||
CellTraits.h
|
||||
Deprecated.h
|
||||
Flags.h
|
||||
Geometry.h
|
||||
Hash.h
|
||||
ImplicitFunction.h
|
||||
List.h
|
||||
ListTag.h
|
||||
Math.h
|
||||
Matrix.h
|
||||
NewtonsMethod.h
|
||||
Pair.h
|
||||
Particle.h
|
||||
Range.h
|
||||
RangeId.h
|
||||
RangeId2.h
|
||||
@ -42,6 +46,7 @@ set(headers
|
||||
Swap.h
|
||||
TopologyElementTag.h
|
||||
Transform3D.h
|
||||
TypeList.h
|
||||
TypeListTag.h
|
||||
Types.h
|
||||
TypeTraits.h
|
||||
|
142
vtkm/Deprecated.h
Normal file
142
vtkm/Deprecated.h
Normal file
@ -0,0 +1,142 @@
|
||||
//============================================================================
|
||||
// Copyright (c) Kitware, Inc.
|
||||
// All rights reserved.
|
||||
// See LICENSE.txt for details.
|
||||
//
|
||||
// This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
// PURPOSE. See the above copyright notice for more information.
|
||||
//============================================================================
|
||||
#ifndef vtk_m_Deprecated_h
|
||||
#define vtk_m_Deprecated_h
|
||||
|
||||
#include <vtkm/StaticAssert.h>
|
||||
#include <vtkm/Types.h>
|
||||
|
||||
#define VTK_M_DEPRECATED_MAKE_MESSAGE(...) \
|
||||
VTKM_EXPAND(VTK_M_DEPRECATED_MAKE_MESSAGE_IMPL(__VA_ARGS__, "", vtkm::internal::NullType{}))
|
||||
#define VTK_M_DEPRECATED_MAKE_MESSAGE_IMPL(version, message, ...) \
|
||||
message " Deprecated in version " #version "."
|
||||
|
||||
/// \def VTKM_DEPRECATED(version, message)
|
||||
///
|
||||
/// Classes and methods are marked deprecated using the `VTKM_DEPRECATED`
|
||||
/// macro. The first argument of `VTKM_DEPRECATED` should be set to the first
|
||||
/// version in which the feature is deprecated. For example, if the last
|
||||
/// released version of VTK-m was 1.5, and on the master branch a developer
|
||||
/// wants to deprecate a class foo, then the `VTKM_DEPRECATED` release version
|
||||
/// should be given as 1.6, which will be the next minor release of VTK-m. The
|
||||
/// second argument of `VTKM_DEPRECATED`, which is optional but highly
|
||||
/// encouraged, is a short message that should clue developers on how to update
|
||||
/// their code to the new changes. For example, it could point to the
|
||||
/// replacement class or method for the changed feature.
|
||||
///
|
||||
|
||||
/// \def VTKM_DEPRECATED_SUPPRESS_BEGIN
|
||||
///
|
||||
/// Begins a region of code in which warnings about using deprecated code are ignored.
|
||||
/// Such suppression is usually helpful when implementing other deprecated features.
|
||||
/// (You would think if one deprecated method used another deprecated method this
|
||||
/// would not be a warning, but it is.)
|
||||
///
|
||||
/// Any use of `VTKM_DEPRECATED_SUPPRESS_BEGIN` must be paired with a
|
||||
/// `VTKM_DEPRECATED_SUPPRESS_END`, which will re-enable warnings in subsequent code.
|
||||
///
|
||||
/// Do not use a semicolon after this macro.
|
||||
///
|
||||
|
||||
/// \def VTKM_DEPRECATED_SUPPRESS_END
|
||||
///
|
||||
/// Ends a region of code in which warnings about using deprecated code are ignored.
|
||||
/// Any use of `VTKM_DEPRECATED_SUPPRESS_BEGIN` must be paired with a
|
||||
/// `VTKM_DEPRECATED_SUPPRESS_END`.
|
||||
///
|
||||
/// Do not use a semicolon after this macro.
|
||||
///
|
||||
|
||||
// Determine whether the [[deprecated]] attribute is supported. Note that we are not
|
||||
// using other older compiler features such as __attribute__((__deprecated__)) because
|
||||
// they do not all support all [[deprecated]] uses (such as uses in enums). If
|
||||
// [[deprecated]] is supported, then VTK_M_DEPRECATED_ATTRIBUTE_SUPPORTED will get defined.
|
||||
#ifndef VTK_M_DEPRECATED_ATTRIBUTE_SUPPORTED
|
||||
|
||||
#if __cplusplus >= 201402L
|
||||
|
||||
// C++14 and better supports [[deprecated]]
|
||||
// Except in these cases:
|
||||
// - nvcc on visual studio
|
||||
#if !(defined(VTKM_MSVC) && defined(VTKM_CUDA))
|
||||
#define VTK_M_DEPRECATED_ATTRIBUTE_SUPPORTED
|
||||
#endif
|
||||
|
||||
#elif defined(VTKM_GCC)
|
||||
|
||||
// GCC has supported [[deprecated]] since version 5.0, but using it on enum was not
|
||||
// supported until 6.0. So we have to make a special case to only use it for high
|
||||
// enough revisions.
|
||||
#if __GNUC__ >= 6
|
||||
#define VTK_M_DEPRECATED_ATTRIBUTE_SUPPORTED
|
||||
#endif // Too old GCC
|
||||
|
||||
#elif defined(__has_cpp_attribute)
|
||||
|
||||
#if __has_cpp_attribute(deprecated)
|
||||
// Compiler not fully C++14 compliant, but it reports to support [[deprecated]]
|
||||
#define VTK_M_DEPRECATED_ATTRIBUTE_SUPPORTED
|
||||
#endif // __has_cpp_attribute(deprecated)
|
||||
|
||||
#elif defined(VTKM_MSVC) && (_MSC_VER >= 1900) && !defined(VTKM_CUDA)
|
||||
|
||||
#define VTK_M_DEPRECATED_ATTRIBUTE_SUPPORTED
|
||||
|
||||
#endif // no known compiler support for [[deprecated]]
|
||||
|
||||
#endif // VTK_M_DEPRECATED_ATTRIBUTE_SUPPORTED check
|
||||
|
||||
// Determine how to turn deprecated warnings on and off, generally with pragmas. If
|
||||
// deprecated warnings can be turned off and on, then VTK_M_DEPRECATED_SUPPRESS_SUPPORTED
|
||||
// is defined and the pair VTKM_DEPRECATED_SUPPRESS_BEGIN and VTKM_DEPRECATED_SUPRESS_END
|
||||
// are defined to the pragmas to disable and restore these warnings. If this support
|
||||
// cannot be determined, VTK_M_DEPRECATED_SUPPRESS_SUPPORTED is _not_ define whereas
|
||||
// VTKM_DEPRECATED_SUPPRESS_BEGIN and VTKM_DEPRECATED_SUPPRESS_END are defined to be
|
||||
// empty.
|
||||
#ifndef VTKM_DEPRECATED_SUPPRESS_SUPPORTED
|
||||
|
||||
#if defined(VTKM_GCC) || defined(VTKM_CLANG)
|
||||
|
||||
#define VTKM_DEPRECATED_SUPPRESS_SUPPORTED
|
||||
#define VTKM_DEPRECATED_SUPPRESS_BEGIN \
|
||||
_Pragma("GCC diagnostic push") _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
|
||||
#define VTKM_DEPRECATED_SUPPRESS_END _Pragma("GCC diagnostic pop")
|
||||
|
||||
#elif defined(VTKM_MSVC)
|
||||
|
||||
#define VTKM_DEPRECATED_SUPPRESS_SUPPORTED
|
||||
#define VTKM_DEPRECATED_SUPPRESS_BEGIN __pragma(warning(push)) __pragma(warning(disable : 4996))
|
||||
#define VTKM_DEPRECATED_SUPPRESS_END __pragma(warning(pop))
|
||||
|
||||
#else
|
||||
|
||||
// Other compilers probably have different pragmas for turning warnings off and on.
|
||||
// Adding more compilers to this list is fine, but the above probably capture most
|
||||
// developers and should be covered on dashboards.
|
||||
#define VTKM_DEPRECATED_SUPPRESS_BEGIN
|
||||
#define VTKM_DEPRECATED_SUPPRESS_END
|
||||
|
||||
#endif
|
||||
|
||||
#endif // VTKM_DEPRECATED_SUPPRESS_SUPPORTED check
|
||||
|
||||
#if !defined(VTKM_DEPRECATED_SUPPRESS_BEGIN) || !defined(VTKM_DEPRECATED_SUPPRESS_END)
|
||||
#error VTKM_DEPRECATED_SUPPRESS macros not properly defined.
|
||||
#endif
|
||||
|
||||
// Only actually use the [[deprecated]] attribute if the compiler supports it AND
|
||||
// we know how to suppress deprecations when necessary.
|
||||
#if defined(VTK_M_DEPRECATED_ATTRIBUTE_SUPPORTED) && defined(VTKM_DEPRECATED_SUPPRESS_SUPPORTED)
|
||||
#define VTKM_DEPRECATED(...) [[deprecated(VTK_M_DEPRECATED_MAKE_MESSAGE(__VA_ARGS__))]]
|
||||
#else
|
||||
#define VTKM_DEPRECATED(...)
|
||||
#endif
|
||||
|
||||
#endif // vtk_m_Deprecated_h
|
586
vtkm/List.h
Normal file
586
vtkm/List.h
Normal file
@ -0,0 +1,586 @@
|
||||
//============================================================================
|
||||
// Copyright (c) Kitware, Inc.
|
||||
// All rights reserved.
|
||||
// See LICENSE.txt for details.
|
||||
//
|
||||
// This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
// PURPOSE. See the above copyright notice for more information.
|
||||
//============================================================================
|
||||
#ifndef vtk_m_List_h
|
||||
#define vtk_m_List_h
|
||||
|
||||
#include <vtkm/Types.h>
|
||||
|
||||
#include <vtkm/internal/brigand.hpp>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
|
||||
template <typename... Ts>
|
||||
struct List
|
||||
{
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// This prototype is here to detect deprecated ListTag objects. When ListTags are removed, then
|
||||
// this should be removed too.
|
||||
struct ListRoot;
|
||||
}
|
||||
|
||||
namespace internal
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
struct IsListImpl
|
||||
{
|
||||
// This prototype is here to detect deprecated ListTag objects. When ListTags are removed, then
|
||||
// this should be changed to be just std::false_type.
|
||||
using type = std::is_base_of<vtkm::detail::ListRoot, T>;
|
||||
};
|
||||
|
||||
template <typename... Ts>
|
||||
struct IsListImpl<vtkm::List<Ts...>>
|
||||
{
|
||||
using type = std::true_type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
using IsList = typename vtkm::internal::IsListImpl<T>::type;
|
||||
|
||||
} // namespace internal
|
||||
|
||||
/// Checks that the argument is a proper list. This is a handy concept
|
||||
/// check for functions and classes to make sure that a template argument is
|
||||
/// actually a device adapter tag. (You can get weird errors elsewhere in the
|
||||
/// code when a mistake is made.)
|
||||
///
|
||||
#define VTKM_IS_LIST(type) \
|
||||
VTKM_STATIC_ASSERT_MSG((::vtkm::internal::IsList<type>::value), \
|
||||
"Provided type is not a valid VTK-m list type.")
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
/// list value that is used to represent a list actually matches all values
|
||||
struct UniversalTypeTag
|
||||
{
|
||||
//We never want this tag constructed, and by deleting the constructor
|
||||
//we get an error when trying to use this class with ForEach.
|
||||
UniversalTypeTag() = delete;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
namespace internal
|
||||
{
|
||||
|
||||
// This is here so that the old (deprecated) `ListTag`s can convert themselves to the new
|
||||
// `List` style and be operated on. When that deprecated functionality goes away, we can
|
||||
// probably remove `AsList` and just operate directly on the `List`s.
|
||||
template <typename T>
|
||||
struct AsListImpl;
|
||||
|
||||
template <typename... Ts>
|
||||
struct AsListImpl<vtkm::List<Ts...>>
|
||||
{
|
||||
using type = vtkm::List<Ts...>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
using AsList = typename AsListImpl<T>::type;
|
||||
}
|
||||
|
||||
/// A special tag for an empty list.
|
||||
///
|
||||
using ListEmpty = vtkm::List<>;
|
||||
|
||||
/// A special tag for a list that represents holding all potential values
|
||||
///
|
||||
/// Note: Can not be used with ForEach and some list transforms for obvious reasons.
|
||||
using ListUniversal = vtkm::List<detail::UniversalTypeTag>;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <typename T, template <typename...> class Target>
|
||||
struct ListApplyImpl;
|
||||
template <typename... Ts, template <typename...> class Target>
|
||||
struct ListApplyImpl<vtkm::List<Ts...>, Target>
|
||||
{
|
||||
using type = Target<Ts...>;
|
||||
};
|
||||
// Cannot apply the universal list.
|
||||
template <template <typename...> class Target>
|
||||
struct ListApplyImpl<vtkm::ListUniversal, Target>;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// \brief Applies the list of types to a template.
|
||||
///
|
||||
/// Given a ListTag and a templated class, returns the class instantiated with the types
|
||||
/// represented by the ListTag.
|
||||
///
|
||||
template <typename List, template <typename...> class Target>
|
||||
using ListApply = typename detail::ListApplyImpl<internal::AsList<List>, Target>::type;
|
||||
|
||||
/// Becomes an std::integral_constant containing the number of types in a list.
|
||||
///
|
||||
template <typename List>
|
||||
using ListSize =
|
||||
std::integral_constant<vtkm::IdComponent,
|
||||
vtkm::IdComponent{ brigand::size<internal::AsList<List>>::value }>;
|
||||
|
||||
/// \brief Finds the type at the given index.
|
||||
///
|
||||
/// This becomes the type of the list at the given index.
|
||||
///
|
||||
template <typename List, vtkm::IdComponent Index>
|
||||
using ListAt =
|
||||
brigand::at<internal::AsList<List>, std::integral_constant<vtkm::IdComponent, Index>>;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// This find is roughly based on the brigand::find functionality. We don't use brigand::find
|
||||
// because it has an apparent bug where if a list contains templated types, it trys to
|
||||
// apply those types as predicates, which is wrong.
|
||||
|
||||
template <vtkm::IdComponent NumSearched, typename Target, typename... Remaining>
|
||||
struct FindFirstOfType;
|
||||
|
||||
// Not found
|
||||
template <vtkm::IdComponent NumSearched, typename Target>
|
||||
struct FindFirstOfType<NumSearched, Target> : std::integral_constant<vtkm::IdComponent, -1>
|
||||
{
|
||||
};
|
||||
|
||||
// Basic search next one
|
||||
template <bool NextIsTarget, vtkm::IdComponent NumSearched, typename Target, typename... Remaining>
|
||||
struct FindFirstOfCheckHead;
|
||||
|
||||
template <vtkm::IdComponent NumSearched, typename Target, typename... Ts>
|
||||
struct FindFirstOfCheckHead<true, NumSearched, Target, Ts...>
|
||||
: std::integral_constant<vtkm::IdComponent, NumSearched>
|
||||
{
|
||||
};
|
||||
|
||||
template <vtkm::IdComponent NumSearched, typename Target, typename Next, typename... Remaining>
|
||||
struct FindFirstOfCheckHead<false, NumSearched, Target, Next, Remaining...>
|
||||
: FindFirstOfCheckHead<std::is_same<Target, Next>::value, NumSearched + 1, Target, Remaining...>
|
||||
{
|
||||
};
|
||||
|
||||
// Not found
|
||||
template <vtkm::IdComponent NumSearched, typename Target>
|
||||
struct FindFirstOfCheckHead<false, NumSearched, Target>
|
||||
: std::integral_constant<vtkm::IdComponent, -1>
|
||||
{
|
||||
};
|
||||
|
||||
template <vtkm::IdComponent NumSearched, typename Target, typename Next, typename... Remaining>
|
||||
struct FindFirstOfType<NumSearched, Target, Next, Remaining...>
|
||||
: FindFirstOfCheckHead<std::is_same<Target, Next>::value, NumSearched, Target, Remaining...>
|
||||
{
|
||||
};
|
||||
|
||||
// If there are at least 6 entries, check the first 4 to quickly narrow down
|
||||
template <bool OneInFirst4Matches, vtkm::IdComponent NumSearched, typename Target, typename... Ts>
|
||||
struct FindFirstOfSplit4;
|
||||
|
||||
template <vtkm::IdComponent NumSearched,
|
||||
typename Target,
|
||||
typename T0,
|
||||
typename T1,
|
||||
typename T2,
|
||||
typename T3,
|
||||
typename... Ts>
|
||||
struct FindFirstOfSplit4<true, NumSearched, Target, T0, T1, T2, T3, Ts...>
|
||||
: FindFirstOfCheckHead<std::is_same<Target, T0>::value, NumSearched, Target, T1, T2, T3>
|
||||
{
|
||||
};
|
||||
|
||||
template <vtkm::IdComponent NumSearched,
|
||||
typename Target,
|
||||
typename T0,
|
||||
typename T1,
|
||||
typename T2,
|
||||
typename T3,
|
||||
typename T4,
|
||||
typename... Ts>
|
||||
struct FindFirstOfSplit4<false, NumSearched, Target, T0, T1, T2, T3, T4, Ts...>
|
||||
: FindFirstOfCheckHead<std::is_same<Target, T4>::value, NumSearched + 4, Target, Ts...>
|
||||
{
|
||||
};
|
||||
|
||||
template <vtkm::IdComponent NumSearched,
|
||||
typename Target,
|
||||
typename T0,
|
||||
typename T1,
|
||||
typename T2,
|
||||
typename T3,
|
||||
typename T4,
|
||||
typename T5,
|
||||
typename... Ts>
|
||||
struct FindFirstOfType<NumSearched, Target, T0, T1, T2, T3, T4, T5, Ts...>
|
||||
: FindFirstOfSplit4<(std::is_same<Target, T0>::value || std::is_same<Target, T1>::value ||
|
||||
std::is_same<Target, T2>::value ||
|
||||
std::is_same<Target, T3>::value),
|
||||
NumSearched,
|
||||
Target,
|
||||
T0,
|
||||
T1,
|
||||
T2,
|
||||
T3,
|
||||
T4,
|
||||
T5,
|
||||
Ts...>
|
||||
{
|
||||
};
|
||||
|
||||
// If there are at least 12 entries, check the first 8 to quickly narrow down
|
||||
template <bool OneInFirst8Matches, vtkm::IdComponent NumSearched, typename Target, typename... Ts>
|
||||
struct FindFirstOfSplit8;
|
||||
|
||||
template <vtkm::IdComponent NumSearched,
|
||||
typename Target,
|
||||
typename T0,
|
||||
typename T1,
|
||||
typename T2,
|
||||
typename T3,
|
||||
typename T4,
|
||||
typename T5,
|
||||
typename T6,
|
||||
typename T7,
|
||||
typename... Ts>
|
||||
struct FindFirstOfSplit8<true, NumSearched, Target, T0, T1, T2, T3, T4, T5, T6, T7, Ts...>
|
||||
: FindFirstOfSplit4<(std::is_same<Target, T0>::value || std::is_same<Target, T1>::value ||
|
||||
std::is_same<Target, T2>::value ||
|
||||
std::is_same<Target, T3>::value),
|
||||
NumSearched,
|
||||
Target,
|
||||
T0,
|
||||
T1,
|
||||
T2,
|
||||
T3,
|
||||
T4,
|
||||
T5,
|
||||
T6,
|
||||
T7>
|
||||
{
|
||||
};
|
||||
|
||||
template <vtkm::IdComponent NumSearched,
|
||||
typename Target,
|
||||
typename T0,
|
||||
typename T1,
|
||||
typename T2,
|
||||
typename T3,
|
||||
typename T4,
|
||||
typename T5,
|
||||
typename T6,
|
||||
typename T7,
|
||||
typename... Ts>
|
||||
struct FindFirstOfSplit8<false, NumSearched, Target, T0, T1, T2, T3, T4, T5, T6, T7, Ts...>
|
||||
: FindFirstOfType<NumSearched + 8, Target, Ts...>
|
||||
{
|
||||
};
|
||||
|
||||
template <vtkm::IdComponent NumSearched,
|
||||
typename Target,
|
||||
typename T0,
|
||||
typename T1,
|
||||
typename T2,
|
||||
typename T3,
|
||||
typename T4,
|
||||
typename T5,
|
||||
typename T6,
|
||||
typename T7,
|
||||
typename T8,
|
||||
typename T9,
|
||||
typename T10,
|
||||
typename T11,
|
||||
typename... Ts>
|
||||
struct FindFirstOfType<NumSearched, Target, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, Ts...>
|
||||
: FindFirstOfSplit8<(std::is_same<Target, T0>::value || std::is_same<Target, T1>::value ||
|
||||
std::is_same<Target, T2>::value ||
|
||||
std::is_same<Target, T3>::value ||
|
||||
std::is_same<Target, T4>::value ||
|
||||
std::is_same<Target, T5>::value ||
|
||||
std::is_same<Target, T6>::value ||
|
||||
std::is_same<Target, T7>::value),
|
||||
NumSearched,
|
||||
Target,
|
||||
T0,
|
||||
T1,
|
||||
T2,
|
||||
T3,
|
||||
T4,
|
||||
T5,
|
||||
T6,
|
||||
T7,
|
||||
T8,
|
||||
T9,
|
||||
T10,
|
||||
T11,
|
||||
Ts...>
|
||||
{
|
||||
};
|
||||
|
||||
template <typename List, typename Target>
|
||||
struct ListIndexOfImpl;
|
||||
template <typename... Ts, typename Target>
|
||||
struct ListIndexOfImpl<vtkm::List<Ts...>, Target>
|
||||
{
|
||||
using type = std::integral_constant<vtkm::IdComponent, FindFirstOfType<0, Target, Ts...>::value>;
|
||||
};
|
||||
template <typename Target>
|
||||
struct ListIndexOfImpl<vtkm::ListUniversal, Target>
|
||||
{
|
||||
VTKM_STATIC_ASSERT_MSG((std::is_same<Target, void>::value && std::is_same<Target, int>::value),
|
||||
"Cannot get indices in a universal list.");
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// \brief Finds the index of a given type.
|
||||
///
|
||||
/// Becomes a `std::integral_constant` for the index of the given type. If the
|
||||
/// given type is not in the list, the value is set to -1.
|
||||
///
|
||||
template <typename List, typename T>
|
||||
using ListIndexOf = typename detail::ListIndexOfImpl<internal::AsList<List>, T>::type;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <typename List, typename T>
|
||||
struct ListHasImpl
|
||||
{
|
||||
using type = std::integral_constant<bool, (vtkm::ListIndexOf<List, T>::value >= 0)>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct ListHasImpl<vtkm::ListUniversal, T>
|
||||
{
|
||||
using type = std::true_type;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// \brief Checks to see if the given `T` is in the list pointed to by `List`.
|
||||
///
|
||||
/// Becomes `std::true_type` if the `T` is in `List`. `std::false_type` otherwise.
|
||||
///
|
||||
template <typename List, typename T>
|
||||
using ListHas = typename detail::ListHasImpl<internal::AsList<List>, T>::type;
|
||||
|
||||
#if defined(VTKM_MSVC) && (_MSC_VER < 1911)
|
||||
|
||||
// Alternate definition of ListAppend to get around an apparent issue with
|
||||
// Visual Studio 2015.
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <typename... Lists>
|
||||
struct ListAppendImpl
|
||||
{
|
||||
using type = brigand::append<internal::AsList<Lists>...>;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename... Lists>
|
||||
using ListAppend = typename detail::ListAppendImpl<Lists...>::type;
|
||||
|
||||
#else // Normal definition
|
||||
|
||||
/// Concatinates a set of lists into a single list.
|
||||
///
|
||||
/// Note that this does not work correctly with `vtkm::ListUniversal`.
|
||||
template <typename... Lists>
|
||||
using ListAppend = brigand::append<internal::AsList<Lists>...>;
|
||||
|
||||
#endif
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <bool Has, typename State, typename Element>
|
||||
struct ListIntersectTagsChoose;
|
||||
|
||||
template <typename State, typename Element>
|
||||
struct ListIntersectTagsChoose<true, State, Element>
|
||||
{
|
||||
using type = brigand::push_back<State, Element>;
|
||||
};
|
||||
|
||||
template <typename State, typename Element>
|
||||
struct ListIntersectTagsChoose<false, State, Element>
|
||||
{
|
||||
using type = State;
|
||||
};
|
||||
|
||||
template <class State, class Element, class List>
|
||||
struct ListIntersectTags
|
||||
: ListIntersectTagsChoose<vtkm::ListHas<List, Element>::value, State, Element>
|
||||
{
|
||||
};
|
||||
|
||||
template <typename List1, typename List2>
|
||||
struct ListIntersectImpl
|
||||
{
|
||||
VTKM_IS_LIST(List1);
|
||||
VTKM_IS_LIST(List2);
|
||||
|
||||
using type =
|
||||
brigand::fold<List1,
|
||||
vtkm::List<>,
|
||||
ListIntersectTags<brigand::_state, brigand::_element, brigand::pin<List2>>>;
|
||||
};
|
||||
|
||||
template <typename List1>
|
||||
struct ListIntersectImpl<List1, vtkm::ListUniversal>
|
||||
{
|
||||
VTKM_IS_LIST(List1);
|
||||
|
||||
using type = List1;
|
||||
};
|
||||
template <typename List2>
|
||||
struct ListIntersectImpl<vtkm::ListUniversal, List2>
|
||||
{
|
||||
VTKM_IS_LIST(List2);
|
||||
|
||||
using type = List2;
|
||||
};
|
||||
template <>
|
||||
struct ListIntersectImpl<vtkm::ListUniversal, vtkm::ListUniversal>
|
||||
{
|
||||
using type = vtkm::ListUniversal;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// Constructs a list containing types present in all lists.
|
||||
///
|
||||
template <typename List1, typename List2>
|
||||
using ListIntersect =
|
||||
typename detail::ListIntersectImpl<internal::AsList<List1>, internal::AsList<List2>>::type;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <typename T, template <typename> class Target>
|
||||
struct ListTransformImpl;
|
||||
template <typename... Ts, template <typename> class Target>
|
||||
struct ListTransformImpl<vtkm::List<Ts...>, Target>
|
||||
{
|
||||
using type = vtkm::List<Target<Ts>...>;
|
||||
};
|
||||
// Cannot transform the universal list.
|
||||
template <template <typename> class Target>
|
||||
struct ListTransformImpl<vtkm::ListUniversal, Target>;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// Constructs a list containing all types in a source list applied to a transform template.
|
||||
///
|
||||
template <typename List, template <typename> class Transform>
|
||||
using ListTransform = typename detail::ListTransformImpl<internal::AsList<List>, Transform>::type;
|
||||
|
||||
/// Takes an existing `List` and a predicate template that is applied to each type in the `List`.
|
||||
/// Any type in the `List` that has a value element equal to true (the equivalent of
|
||||
/// `std::true_type`), that item will be removed from the list. For example the following type
|
||||
///
|
||||
/// ```cpp
|
||||
/// vtkm::ListRemoveIf<vtkm::List<int, float, long long, double>, std::is_integral>
|
||||
/// ```
|
||||
///
|
||||
/// resolves to a `List` that is equivalent to `vtkm::List<float, double>` because
|
||||
/// `std::is_integral<int>` and `std::is_integral<long long>` resolve to `std::true_type` whereas
|
||||
/// `std::is_integral<float>` and `std::is_integral<double>` resolve to `std::false_type`.
|
||||
///
|
||||
template <typename List, template <typename> class Predicate>
|
||||
using ListRemoveIf =
|
||||
brigand::remove_if<internal::AsList<List>, brigand::bind<Predicate, brigand::_1>>;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// We want to use an initializer list as a trick to call a function once for each type, but
|
||||
// an initializer list needs a type, so create wrapper function that returns a value.
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
template <typename Functor, typename... Args>
|
||||
VTKM_EXEC_CONT inline bool ListForEachCallThrough(Functor&& f, Args&&... args)
|
||||
{
|
||||
f(std::forward<Args>(args)...);
|
||||
return false; // Return value does not matter. Hopefully just thrown away.
|
||||
}
|
||||
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
template <typename Functor, typename... Ts, typename... Args>
|
||||
VTKM_EXEC_CONT void ListForEachImpl(Functor&& f, vtkm::List<Ts...>, Args&&... args)
|
||||
{
|
||||
auto init_list = { ListForEachCallThrough(
|
||||
std::forward<Functor>(f), Ts{}, std::forward<Args>(args)...)... };
|
||||
(void)init_list;
|
||||
}
|
||||
|
||||
template <typename Functor, typename... Args>
|
||||
VTKM_EXEC_CONT void ListForEachImpl(Functor&&, vtkm::ListEmpty, Args&&...)
|
||||
{
|
||||
// No types to run functor on.
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// For each typename represented by the list, call the functor with a
|
||||
/// default instance of that type.
|
||||
///
|
||||
template <typename Functor, typename List, typename... Args>
|
||||
VTKM_EXEC_CONT void ListForEach(Functor&& f, List, Args&&... args)
|
||||
{
|
||||
detail::ListForEachImpl(
|
||||
std::forward<Functor>(f), internal::AsList<List>{}, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <typename List1, typename List2>
|
||||
struct ListCrossImpl
|
||||
{
|
||||
VTKM_IS_LIST(List1);
|
||||
VTKM_IS_LIST(List2);
|
||||
|
||||
// This is a lazy Cartesian product generator.
|
||||
// This version was settled on as being the best default
|
||||
// version as all compilers including Intel handle this
|
||||
// implementation without issue for very large cross products
|
||||
using type = brigand::reverse_fold<
|
||||
vtkm::List<List1, List2>,
|
||||
vtkm::List<vtkm::List<>>,
|
||||
brigand::lazy::join<brigand::lazy::transform<
|
||||
brigand::_2,
|
||||
brigand::defer<brigand::lazy::join<brigand::lazy::transform<
|
||||
brigand::parent<brigand::_1>,
|
||||
brigand::defer<brigand::bind<
|
||||
vtkm::List,
|
||||
brigand::lazy::push_front<brigand::_1, brigand::parent<brigand::_1>>>>>>>>>>;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// \brief Generates a list that is the cross product of two input lists.
|
||||
///
|
||||
/// The resulting list has the form of `vtkm::List<vtkm::List<A1,B1>, vtkm::List<A1,B2>,...>`
|
||||
///
|
||||
template <typename List1, typename List2>
|
||||
using ListCross =
|
||||
typename detail::ListCrossImpl<internal::AsList<List1>, internal::AsList<List2>>::type;
|
||||
|
||||
} // namespace vtkm
|
||||
|
||||
#endif //vtk_m_List_h
|
227
vtkm/ListTag.h
227
vtkm/ListTag.h
@ -10,15 +10,63 @@
|
||||
#ifndef vtk_m_ListTag_h
|
||||
#define vtk_m_ListTag_h
|
||||
|
||||
#include <vtkm/internal/ListTagDetail.h>
|
||||
#include <vtkm/Deprecated.h>
|
||||
|
||||
#include <vtkm/List.h>
|
||||
|
||||
#include <vtkm/StaticAssert.h>
|
||||
#include <vtkm/internal/ExportMacros.h>
|
||||
#include <vtkm/internal/brigand.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/// Base class that all ListTag classes inherit from. Helps identify lists
|
||||
/// in macros like VTKM_IS_LIST_TAG.
|
||||
///
|
||||
struct ListRoot
|
||||
{
|
||||
};
|
||||
|
||||
template <class... T>
|
||||
using ListBase = brigand::list<T...>;
|
||||
|
||||
/// list value that is used to represent a list actually matches all values
|
||||
struct UniversalTag
|
||||
{
|
||||
//We never want this tag constructed, and by deleting the constructor
|
||||
//we get an error when trying to use this class with ForEach.
|
||||
UniversalTag() = delete;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/// A basic tag for a list of typenames. This struct can be subclassed
|
||||
/// and still behave like a list tag.
|
||||
template <typename... ArgTypes>
|
||||
struct VTKM_DEPRECATED(1.6, "ListTagBase replace by List. Note that List cannot be subclassed.")
|
||||
ListTagBase : detail::ListRoot
|
||||
{
|
||||
using list = detail::ListBase<ArgTypes...>;
|
||||
};
|
||||
|
||||
/// A special tag for a list that represents holding all potential values
|
||||
///
|
||||
/// Note: Can not be used with ForEach for obvious reasons.
|
||||
struct VTKM_DEPRECATED(
|
||||
1.6,
|
||||
"ListTagUniversal replaced by ListUniversal. Note that ListUniversal cannot be subclassed.")
|
||||
ListTagUniversal : detail::ListRoot
|
||||
{
|
||||
using list = vtkm::detail::ListBase<vtkm::detail::UniversalTag>;
|
||||
};
|
||||
|
||||
namespace internal
|
||||
{
|
||||
@ -31,13 +79,24 @@ struct ListTagCheck : std::is_base_of<vtkm::detail::ListRoot, ListTag>
|
||||
|
||||
} // namespace internal
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <typename ListTag>
|
||||
struct VTKM_DEPRECATED(1.6, "VTKM_IS_LIST_TAG replaced with VTKM_IS_LIST.") ListTagAssert
|
||||
: internal::IsList<ListTag>
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace detal
|
||||
|
||||
/// Checks that the argument is a proper list tag. This is a handy concept
|
||||
/// check for functions and classes to make sure that a template argument is
|
||||
/// actually a device adapter tag. (You can get weird errors elsewhere in the
|
||||
/// code when a mistake is made.)
|
||||
///
|
||||
#define VTKM_IS_LIST_TAG(tag) \
|
||||
VTKM_STATIC_ASSERT_MSG((::vtkm::internal::ListTagCheck<tag>::value), \
|
||||
VTKM_STATIC_ASSERT_MSG((::vtkm::detail::ListTagAssert<tag>::value), \
|
||||
"Provided type is not a valid VTK-m list tag.")
|
||||
|
||||
namespace internal
|
||||
@ -49,8 +108,10 @@ namespace detail
|
||||
template <typename ListTag>
|
||||
struct ListTagAsBrigandListImpl
|
||||
{
|
||||
VTKM_DEPRECATED_SUPPRESS_BEGIN
|
||||
VTKM_IS_LIST_TAG(ListTag);
|
||||
using type = typename ListTag::list;
|
||||
VTKM_DEPRECATED_SUPPRESS_END
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
@ -60,6 +121,38 @@ struct ListTagAsBrigandListImpl
|
||||
template <typename ListTag>
|
||||
using ListTagAsBrigandList = typename detail::ListTagAsBrigandListImpl<ListTag>::type;
|
||||
|
||||
VTKM_DEPRECATED_SUPPRESS_BEGIN
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// Could use ListApply instead, but that causes deprecation warnings.
|
||||
template <typename List>
|
||||
struct ListAsListTagImpl;
|
||||
template <typename... Ts>
|
||||
struct ListAsListTagImpl<vtkm::List<Ts...>>
|
||||
{
|
||||
using type = vtkm::ListTagBase<Ts...>;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename List>
|
||||
using ListAsListTag = typename detail::ListAsListTagImpl<List>::type;
|
||||
VTKM_DEPRECATED_SUPPRESS_END
|
||||
|
||||
// This allows the new `List` operations work on `ListTag`s.
|
||||
template <typename T>
|
||||
struct AsListImpl
|
||||
{
|
||||
VTKM_STATIC_ASSERT_MSG(ListTagCheck<T>::value,
|
||||
"Attempted to use something that is not a List with a List operation.");
|
||||
VTKM_DEPRECATED_SUPPRESS_BEGIN
|
||||
using type = typename std::conditional<std::is_base_of<vtkm::ListTagUniversal, T>::value,
|
||||
vtkm::ListUniversal,
|
||||
brigand::wrap<ListTagAsBrigandList<T>, vtkm::List>>::type;
|
||||
VTKM_DEPRECATED_SUPPRESS_END
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
|
||||
@ -83,20 +176,15 @@ struct ListTagApplyImpl<brigand::list<Ts...>, Target>
|
||||
/// represented by the ListTag.
|
||||
///
|
||||
template <typename ListTag, template <typename...> class Target>
|
||||
using ListTagApply =
|
||||
using ListTagApply VTKM_DEPRECATED(1.6, "ListTagApply replaced by ListApply.") =
|
||||
typename detail::ListTagApplyImpl<internal::ListTagAsBrigandList<ListTag>, Target>::type;
|
||||
|
||||
/// A special tag for a list that represents holding all potential values
|
||||
///
|
||||
/// Note: Can not be used with ForEach for obvious reasons.
|
||||
struct ListTagUniversal : detail::ListRoot
|
||||
{
|
||||
using list = vtkm::detail::ListBase<vtkm::detail::UniversalTag>;
|
||||
};
|
||||
|
||||
/// A special tag for an empty list.
|
||||
///
|
||||
struct ListTagEmpty : detail::ListRoot
|
||||
struct VTKM_DEPRECATED(
|
||||
1.6,
|
||||
"ListTagEmpty replaced by ListEmpty. Note that ListEmpty cannot be subclassed.") ListTagEmpty
|
||||
: detail::ListRoot
|
||||
{
|
||||
using list = vtkm::detail::ListBase<>;
|
||||
};
|
||||
@ -104,87 +192,95 @@ struct ListTagEmpty : detail::ListRoot
|
||||
/// A tag that is a construction of two other tags joined together. This struct
|
||||
/// can be subclassed and still behave like a list tag.
|
||||
template <typename... ListTags>
|
||||
struct ListTagJoin : detail::ListRoot
|
||||
struct VTKM_DEPRECATED(
|
||||
1.6,
|
||||
"ListTagJoin replaced by ListAppend. Note that ListAppend cannot be subclassed.") ListTagJoin
|
||||
: vtkm::internal::ListAsListTag<vtkm::ListAppend<ListTags...>>
|
||||
{
|
||||
using list = typename detail::ListJoin<internal::ListTagAsBrigandList<ListTags>...>::type;
|
||||
};
|
||||
|
||||
|
||||
/// A tag that is constructed by appending \c Type to \c ListTag.
|
||||
template <typename ListTag, typename Type>
|
||||
struct ListTagAppend : detail::ListRoot
|
||||
struct VTKM_DEPRECATED(1.6,
|
||||
"ListTagAppend<List, Type> replaced by ListAppend<List, vtkm::List<Type>. "
|
||||
"Note that ListAppend cannot be subclassed.") ListTagAppend
|
||||
: vtkm::internal::ListAsListTag<vtkm::ListAppend<ListTag, vtkm::List<Type>>>
|
||||
{
|
||||
VTKM_IS_LIST_TAG(ListTag);
|
||||
using list = typename detail::ListJoin<internal::ListTagAsBrigandList<ListTag>,
|
||||
detail::ListBase<Type>>::type;
|
||||
};
|
||||
|
||||
/// Append \c Type to \c ListTag only if \c ListTag does not already contain \c Type.
|
||||
/// No checks are performed to see if \c ListTag itself has only unique elements.
|
||||
template <typename ListTag, typename Type>
|
||||
struct ListTagAppendUnique : detail::ListRoot
|
||||
struct VTKM_DEPRECATED(1.6) ListTagAppendUnique
|
||||
: std::conditional<
|
||||
vtkm::ListHas<ListTag, Type>::value,
|
||||
vtkm::internal::ListAsListTag<vtkm::internal::AsList<ListTag>>,
|
||||
vtkm::internal::ListAsListTag<vtkm::ListAppend<ListTag, vtkm::List<Type>>>>::type
|
||||
{
|
||||
VTKM_IS_LIST_TAG(ListTag);
|
||||
using list =
|
||||
typename detail::ListAppendUniqueImpl<internal::ListTagAsBrigandList<ListTag>, Type>::type;
|
||||
};
|
||||
|
||||
/// A tag that consists of elements that are found in both tags. This struct
|
||||
/// can be subclassed and still behave like a list tag.
|
||||
template <typename ListTag1, typename ListTag2>
|
||||
struct ListTagIntersect : detail::ListRoot
|
||||
struct VTKM_DEPRECATED(
|
||||
1.6,
|
||||
"ListTagIntersect replaced by ListIntersect. Note that ListIntersect cannot be subclassed.")
|
||||
ListTagIntersect : vtkm::internal::ListAsListTag<vtkm::ListIntersect<ListTag1, ListTag2>>
|
||||
{
|
||||
VTKM_IS_LIST_TAG(ListTag1);
|
||||
VTKM_IS_LIST_TAG(ListTag2);
|
||||
using list = typename detail::ListIntersect<internal::ListTagAsBrigandList<ListTag1>,
|
||||
internal::ListTagAsBrigandList<ListTag2>>::type;
|
||||
};
|
||||
|
||||
/// A list tag that consists of each item in another list tag fed into a template that takes
|
||||
/// a single parameter.
|
||||
template <typename ListTag, template <typename> class Transform>
|
||||
struct ListTagTransform : detail::ListRoot
|
||||
struct VTKM_DEPRECATED(
|
||||
1.6,
|
||||
"ListTagTransform replaced by ListTransform. Note that ListTransform cannot be subclassed.")
|
||||
ListTagTransform : vtkm::internal::ListAsListTag<vtkm::ListTransform<ListTag, Transform>>
|
||||
{
|
||||
VTKM_IS_LIST_TAG(ListTag);
|
||||
using list = brigand::transform<internal::ListTagAsBrigandList<ListTag>,
|
||||
brigand::bind<Transform, brigand::_1>>;
|
||||
};
|
||||
|
||||
/// \brief Determines the number of types in the given list.
|
||||
/// A list tag that takes an existing ListTag and a predicate template that is applied to
|
||||
/// each type in the ListTag. Any type in the ListTag that has a value element equal to true
|
||||
/// (the equivalent of std::true_type), that item will be removed from the list. For example
|
||||
/// the following type
|
||||
///
|
||||
/// There is a static member named \c value that is set to the length of the list.
|
||||
/// ```cpp
|
||||
/// vtkm::ListTagRemoveIf<vtkm::ListTagBase<int, float, long long, double>, std::is_integral>
|
||||
/// ```
|
||||
///
|
||||
template <typename ListTag>
|
||||
struct ListSize
|
||||
/// resolves to a ListTag that is equivalent to `vtkm::ListTag<float, double>` because
|
||||
/// `std::is_integral<int>` and `std::is_integral<long long>` resolve to `std::true_type`
|
||||
/// whereas `std::is_integral<float>` and `std::is_integral<double>` resolve to
|
||||
/// `std::false_type`.
|
||||
template <typename ListTag, template <typename> class Predicate>
|
||||
struct VTKM_DEPRECATED(
|
||||
1.6,
|
||||
"ListTagRemoveIf replaced by ListRemoveIf. Note that ListRemoveIf cannot be subclassed.")
|
||||
ListTagRemoveIf : vtkm::internal::ListAsListTag<vtkm::ListRemoveIf<ListTag, Predicate>>
|
||||
{
|
||||
VTKM_IS_LIST_TAG(ListTag);
|
||||
static constexpr vtkm::IdComponent value =
|
||||
detail::ListSizeImpl<internal::ListTagAsBrigandList<ListTag>>::value;
|
||||
};
|
||||
|
||||
/// For each typename represented by the list tag, call the functor with a
|
||||
/// default instance of that type.
|
||||
///
|
||||
template <typename Functor, typename ListTag, typename... Args>
|
||||
VTKM_CONT void ListForEach(Functor&& f, ListTag, Args&&... args)
|
||||
namespace detail
|
||||
{
|
||||
VTKM_IS_LIST_TAG(ListTag);
|
||||
detail::ListForEachImpl(std::forward<Functor>(f),
|
||||
internal::ListTagAsBrigandList<ListTag>{},
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// Old stlye ListCrossProduct expects brigand::list instead of vtkm::List. Transform back
|
||||
template <typename List>
|
||||
using ListToBrigand = vtkm::ListApply<List, brigand::list>;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// Generate a tag that is the cross product of two other tags. The resulting
|
||||
/// tag has the form of Tag< brigand::list<A1,B1>, brigand::list<A1,B2> .... >
|
||||
///
|
||||
template <typename ListTag1, typename ListTag2>
|
||||
struct ListCrossProduct : detail::ListRoot
|
||||
struct VTKM_DEPRECATED(
|
||||
1.6,
|
||||
"ListCrossProduct replaced by ListCross. Note that LIstCross cannot be subclassed.")
|
||||
ListCrossProduct
|
||||
: vtkm::internal::ListAsListTag<
|
||||
vtkm::ListTransform<vtkm::ListCross<ListTag1, ListTag2>, detail::ListToBrigand>>
|
||||
{
|
||||
VTKM_IS_LIST_TAG(ListTag1);
|
||||
VTKM_IS_LIST_TAG(ListTag2);
|
||||
using list =
|
||||
typename detail::ListCrossProductImpl<internal::ListTagAsBrigandList<ListTag1>,
|
||||
internal::ListTagAsBrigandList<ListTag2>>::type;
|
||||
};
|
||||
|
||||
/// \brief Checks to see if the given \c Type is in the list pointed to by \c ListTag.
|
||||
@ -193,11 +289,9 @@ struct ListCrossProduct : detail::ListRoot
|
||||
/// contained in the list and false otherwise.
|
||||
///
|
||||
template <typename ListTag, typename Type>
|
||||
struct ListContains
|
||||
struct VTKM_DEPRECATED(1.6, "ListContains replaced by ListHas.") ListContains
|
||||
: vtkm::ListHas<ListTag, Type>
|
||||
{
|
||||
VTKM_IS_LIST_TAG(ListTag);
|
||||
static constexpr bool value =
|
||||
detail::ListContainsImpl<Type, internal::ListTagAsBrigandList<ListTag>>::value;
|
||||
};
|
||||
|
||||
/// \brief Finds the type at the given index.
|
||||
@ -205,26 +299,15 @@ struct ListContains
|
||||
/// This struct contains subtype \c type that resolves to the type at the given index.
|
||||
///
|
||||
template <typename ListTag, vtkm::IdComponent Index>
|
||||
struct ListTypeAt
|
||||
struct VTKM_DEPRECATED(1.6, "ListTypeAt::type replaced by ListAt.") ListTypeAt
|
||||
{
|
||||
VTKM_DEPRECATED_SUPPRESS_BEGIN
|
||||
VTKM_IS_LIST_TAG(ListTag);
|
||||
VTKM_DEPRECATED_SUPPRESS_END
|
||||
using type = brigand::at<internal::ListTagAsBrigandList<ListTag>,
|
||||
std::integral_constant<vtkm::IdComponent, Index>>;
|
||||
};
|
||||
|
||||
/// \brief Finds the index of the given type.
|
||||
///
|
||||
/// There is a static member named \c value that is set to the index of the given type. If the
|
||||
/// given type is not in the list, the value is set to -1.
|
||||
///
|
||||
template <typename ListTag, typename Type>
|
||||
struct ListIndexOf
|
||||
{
|
||||
VTKM_IS_LIST_TAG(ListTag);
|
||||
static constexpr vtkm::IdComponent value =
|
||||
detail::ListIndexOfImpl<Type, internal::ListTagAsBrigandList<ListTag>, 0>::value;
|
||||
};
|
||||
|
||||
} // namespace vtkm
|
||||
|
||||
#endif //vtk_m_ListTag_h
|
||||
|
105
vtkm/Particle.h
Normal file
105
vtkm/Particle.h
Normal file
@ -0,0 +1,105 @@
|
||||
//============================================================================
|
||||
// Copyright (c) Kitware, Inc.
|
||||
// All rights reserved.
|
||||
// See LICENSE.txt for details.
|
||||
//
|
||||
// This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
// PURPOSE. See the above copyright notice for more information.
|
||||
//============================================================================
|
||||
#ifndef vtk_m_Particle_h
|
||||
#define vtk_m_Particle_h
|
||||
|
||||
#include <vtkm/Bitset.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
|
||||
//Bit field describing the status:
|
||||
class ParticleStatus : public vtkm::Bitset<vtkm::UInt8>
|
||||
{
|
||||
public:
|
||||
VTKM_EXEC_CONT ParticleStatus()
|
||||
{
|
||||
this->SetOk();
|
||||
this->ClearTerminate();
|
||||
}
|
||||
|
||||
VTKM_EXEC_CONT void SetOk() { this->set(this->SUCCESS_BIT); }
|
||||
VTKM_EXEC_CONT bool CheckOk() const { return this->test(this->SUCCESS_BIT); }
|
||||
|
||||
VTKM_EXEC_CONT void SetFail() { this->reset(this->SUCCESS_BIT); }
|
||||
VTKM_EXEC_CONT bool CheckFail() const { return !this->test(this->SUCCESS_BIT); }
|
||||
|
||||
VTKM_EXEC_CONT void SetTerminate() { this->set(this->TERMINATE_BIT); }
|
||||
VTKM_EXEC_CONT void ClearTerminate() { this->reset(this->TERMINATE_BIT); }
|
||||
VTKM_EXEC_CONT bool CheckTerminate() const { return this->test(this->TERMINATE_BIT); }
|
||||
|
||||
VTKM_EXEC_CONT void SetSpatialBounds() { this->set(this->SPATIAL_BOUNDS_BIT); }
|
||||
VTKM_EXEC_CONT void ClearSpatialBounds() { this->reset(this->SPATIAL_BOUNDS_BIT); }
|
||||
VTKM_EXEC_CONT bool CheckSpatialBounds() const { return this->test(this->SPATIAL_BOUNDS_BIT); }
|
||||
|
||||
VTKM_EXEC_CONT void SetTemporalBounds() { this->set(this->TEMPORAL_BOUNDS_BIT); }
|
||||
VTKM_EXEC_CONT void ClearTemporalBounds() { this->reset(this->TEMPORAL_BOUNDS_BIT); }
|
||||
VTKM_EXEC_CONT bool CheckTemporalBounds() const { return this->test(this->TEMPORAL_BOUNDS_BIT); }
|
||||
|
||||
VTKM_EXEC_CONT void SetTookAnySteps() { this->set(this->TOOK_ANY_STEPS_BIT); }
|
||||
VTKM_EXEC_CONT void ClearTookAnySteps() { this->reset(this->TOOK_ANY_STEPS_BIT); }
|
||||
VTKM_EXEC_CONT bool CheckTookAnySteps() const { return this->test(this->TOOK_ANY_STEPS_BIT); }
|
||||
|
||||
private:
|
||||
static constexpr vtkm::Id SUCCESS_BIT = 0;
|
||||
static constexpr vtkm::Id TERMINATE_BIT = 1;
|
||||
static constexpr vtkm::Id SPATIAL_BOUNDS_BIT = 2;
|
||||
static constexpr vtkm::Id TEMPORAL_BOUNDS_BIT = 3;
|
||||
static constexpr vtkm::Id TOOK_ANY_STEPS_BIT = 4;
|
||||
};
|
||||
|
||||
inline VTKM_CONT std::ostream& operator<<(std::ostream& s, const vtkm::ParticleStatus& status)
|
||||
{
|
||||
s << "[" << status.CheckOk() << " " << status.CheckTerminate() << " "
|
||||
<< status.CheckSpatialBounds() << " " << status.CheckTemporalBounds() << "]";
|
||||
return s;
|
||||
}
|
||||
|
||||
class Particle
|
||||
{
|
||||
public:
|
||||
VTKM_EXEC_CONT
|
||||
Particle() {}
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
Particle(const vtkm::Vec3f& p,
|
||||
const vtkm::Id& id,
|
||||
const vtkm::Id& numSteps = 0,
|
||||
const vtkm::ParticleStatus& status = vtkm::ParticleStatus(),
|
||||
const vtkm::FloatDefault& time = 0)
|
||||
: Pos(p)
|
||||
, ID(id)
|
||||
, NumSteps(numSteps)
|
||||
, Status(status)
|
||||
, Time(time)
|
||||
{
|
||||
}
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
Particle(const vtkm::Particle& p)
|
||||
: Pos(p.Pos)
|
||||
, ID(p.ID)
|
||||
, NumSteps(p.NumSteps)
|
||||
, Status(p.Status)
|
||||
, Time(p.Time)
|
||||
{
|
||||
}
|
||||
|
||||
vtkm::Particle& operator=(const vtkm::Particle& p) = default;
|
||||
|
||||
vtkm::Vec3f Pos;
|
||||
vtkm::Id ID = -1;
|
||||
vtkm::Id NumSteps = 0;
|
||||
vtkm::ParticleStatus Status;
|
||||
vtkm::FloatDefault Time = 0;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // vtk_m_Particle_h
|
@ -177,7 +177,7 @@ inline VTKM_CONT std::ostream& operator<<(std::ostream& stream, const vtkm::Rang
|
||||
{
|
||||
return stream << "[" << range.Min << ".." << range.Max << "]";
|
||||
} // Declared inside of vtkm namespace so that the operator work with ADL lookup
|
||||
|
||||
} // namespace vtkm
|
||||
|
||||
|
||||
#endif //vtk_m_Range_h
|
||||
|
@ -131,13 +131,12 @@ struct RangeId
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace vtkm
|
||||
|
||||
/// Helper function for printing ranges during testing
|
||||
///
|
||||
static inline VTKM_CONT std::ostream& operator<<(std::ostream& stream, const vtkm::RangeId& range)
|
||||
{
|
||||
return stream << "[" << range.Min << ".." << range.Max << ")";
|
||||
}
|
||||
} // Declared inside of vtkm namespace so that the operator work with ADL lookup
|
||||
} // namespace vtkm
|
||||
|
||||
#endif // vtk_m_RangeId_h
|
||||
|
@ -142,6 +142,32 @@ struct RangeId2
|
||||
{
|
||||
return ((this->X != range.X) || (this->Y != range.Y));
|
||||
}
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
vtkm::RangeId& operator[](IdComponent c) noexcept
|
||||
{
|
||||
if (c <= 0)
|
||||
{
|
||||
return this->X;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this->Y;
|
||||
}
|
||||
}
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
const vtkm::RangeId& operator[](IdComponent c) const noexcept
|
||||
{
|
||||
if (c <= 0)
|
||||
{
|
||||
return this->X;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this->Y;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace vtkm
|
||||
|
@ -158,15 +158,47 @@ struct RangeId3
|
||||
{
|
||||
return ((this->X != range.X) || (this->Y != range.Y) || (this->Z != range.Z));
|
||||
}
|
||||
};
|
||||
VTKM_EXEC_CONT
|
||||
vtkm::RangeId& operator[](IdComponent c) noexcept
|
||||
{
|
||||
if (c <= 0)
|
||||
{
|
||||
return this->X;
|
||||
}
|
||||
else if (c == 1)
|
||||
{
|
||||
return this->Y;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this->Z;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace vtkm
|
||||
VTKM_EXEC_CONT
|
||||
const vtkm::RangeId& operator[](IdComponent c) const noexcept
|
||||
{
|
||||
if (c <= 0)
|
||||
{
|
||||
return this->X;
|
||||
}
|
||||
else if (c == 1)
|
||||
{
|
||||
return this->Y;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this->Z;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/// Helper function for printing range during testing
|
||||
///
|
||||
static inline VTKM_CONT std::ostream& operator<<(std::ostream& stream, const vtkm::RangeId3& range)
|
||||
inline VTKM_CONT std::ostream& operator<<(std::ostream& stream, const vtkm::RangeId3& range)
|
||||
{
|
||||
return stream << "{ X:" << range.X << ", Y:" << range.Y << ", Z:" << range.Z << " }";
|
||||
}
|
||||
} // Declared inside of vtkm namespace so that the operator work with ADL lookup
|
||||
} // namespace vtkm
|
||||
|
||||
#endif //vtk_m_RangeId3_h
|
||||
|
@ -10,8 +10,8 @@
|
||||
#ifndef vtk_m_StaticAssert_h
|
||||
#define vtk_m_StaticAssert_h
|
||||
|
||||
|
||||
#include <type_traits>
|
||||
#include <vtkm/internal/Configure.h>
|
||||
|
||||
#define VTKM_STATIC_ASSERT(condition) \
|
||||
static_assert((condition), "Failed static assert: " #condition)
|
||||
|
176
vtkm/TypeList.h
Normal file
176
vtkm/TypeList.h
Normal file
@ -0,0 +1,176 @@
|
||||
//============================================================================
|
||||
// Copyright (c) Kitware, Inc.
|
||||
// All rights reserved.
|
||||
// See LICENSE.txt for details.
|
||||
//
|
||||
// This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
// PURPOSE. See the above copyright notice for more information.
|
||||
//============================================================================
|
||||
#ifndef vtk_m_TypeList_h
|
||||
#define vtk_m_TypeList_h
|
||||
|
||||
#ifndef VTKM_DEFAULT_TYPE_LIST
|
||||
#define VTKM_DEFAULT_TYPE_LIST ::vtkm::TypeListCommon
|
||||
#endif
|
||||
|
||||
#include <vtkm/List.h>
|
||||
#include <vtkm/Types.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
|
||||
/// A list containing the type vtkm::Id.
|
||||
///
|
||||
using TypeListId = vtkm::List<vtkm::Id>;
|
||||
|
||||
/// A list containing the type vtkm::Id2.
|
||||
///
|
||||
using TypeListId2 = vtkm::List<vtkm::Id2>;
|
||||
|
||||
/// A list containing the type vtkm::Id3.
|
||||
///
|
||||
using TypeListId3 = vtkm::List<vtkm::Id3>;
|
||||
|
||||
/// A list containing the type vtkm::Id4.
|
||||
///
|
||||
using TypeListId4 = vtkm::List<vtkm::Id4>;
|
||||
|
||||
/// A list containing the type vtkm::IdComponent
|
||||
///
|
||||
using TypeListIdComponent = vtkm::List<vtkm::IdComponent>;
|
||||
|
||||
/// A list containing types used to index arrays. Contains vtkm::Id, vtkm::Id2,
|
||||
/// and vtkm::Id3.
|
||||
///
|
||||
using TypeListIndex = vtkm::List<vtkm::Id, vtkm::Id2, vtkm::Id3>;
|
||||
|
||||
/// A list containing types used for scalar fields. Specifically, contains
|
||||
/// floating point numbers of different widths (i.e. vtkm::Float32 and
|
||||
/// vtkm::Float64).
|
||||
using TypeListFieldScalar = vtkm::List<vtkm::Float32, vtkm::Float64>;
|
||||
|
||||
/// A list containing types for values for fields with two dimensional
|
||||
/// vectors.
|
||||
///
|
||||
using TypeListFieldVec2 = vtkm::List<vtkm::Vec2f_32, vtkm::Vec2f_64>;
|
||||
|
||||
/// A list containing types for values for fields with three dimensional
|
||||
/// vectors.
|
||||
///
|
||||
using TypeListFieldVec3 = vtkm::List<vtkm::Vec3f_32, vtkm::Vec3f_64>;
|
||||
|
||||
/// A list containing types for values for fields with four dimensional
|
||||
/// vectors.
|
||||
///
|
||||
using TypeListFieldVec4 = vtkm::List<vtkm::Vec4f_32, vtkm::Vec4f_64>;
|
||||
|
||||
/// A list containing common types for floating-point vectors. Specifically contains
|
||||
/// floating point vectors of size 2, 3, and 4 with floating point components.
|
||||
/// Scalars are not included.
|
||||
///
|
||||
using TypeListFloatVec = vtkm::List<vtkm::Vec2f_32,
|
||||
vtkm::Vec2f_64,
|
||||
vtkm::Vec3f_32,
|
||||
vtkm::Vec3f_64,
|
||||
vtkm::Vec4f_32,
|
||||
vtkm::Vec4f_64>;
|
||||
|
||||
/// A list containing common types for values in fields. Specifically contains
|
||||
/// floating point scalars and vectors of size 2, 3, and 4 with floating point
|
||||
/// components.
|
||||
///
|
||||
using TypeListField = vtkm::List<vtkm::Float32,
|
||||
vtkm::Float64,
|
||||
vtkm::Vec2f_32,
|
||||
vtkm::Vec2f_64,
|
||||
vtkm::Vec3f_32,
|
||||
vtkm::Vec3f_64,
|
||||
vtkm::Vec4f_32,
|
||||
vtkm::Vec4f_64>;
|
||||
|
||||
/// A list of all scalars defined in vtkm/Types.h. A scalar is a type that
|
||||
/// holds a single number.
|
||||
///
|
||||
using TypeListScalarAll = vtkm::List<vtkm::Int8,
|
||||
vtkm::UInt8,
|
||||
vtkm::Int16,
|
||||
vtkm::UInt16,
|
||||
vtkm::Int32,
|
||||
vtkm::UInt32,
|
||||
vtkm::Int64,
|
||||
vtkm::UInt64,
|
||||
vtkm::Float32,
|
||||
vtkm::Float64>;
|
||||
|
||||
/// A list of the most commonly use Vec classes. Specifically, these are
|
||||
/// vectors of size 2, 3, or 4 containing either unsigned bytes, signed
|
||||
/// integers of 32 or 64 bits, or floating point values of 32 or 64 bits.
|
||||
///
|
||||
using TypeListVecCommon = vtkm::List<vtkm::Vec2ui_8,
|
||||
vtkm::Vec2i_32,
|
||||
vtkm::Vec2i_64,
|
||||
vtkm::Vec2f_32,
|
||||
vtkm::Vec2f_64,
|
||||
vtkm::Vec3ui_8,
|
||||
vtkm::Vec3i_32,
|
||||
vtkm::Vec3i_64,
|
||||
vtkm::Vec3f_32,
|
||||
vtkm::Vec3f_64,
|
||||
vtkm::Vec4ui_8,
|
||||
vtkm::Vec4i_32,
|
||||
vtkm::Vec4i_64,
|
||||
vtkm::Vec4f_32,
|
||||
vtkm::Vec4f_64>;
|
||||
|
||||
namespace internal
|
||||
{
|
||||
|
||||
/// A list of uncommon Vec classes with length up to 4. This is not much
|
||||
/// use in general, but is used when joined with \c TypeListVecCommon
|
||||
/// to get a list of all vectors up to size 4.
|
||||
///
|
||||
using TypeListVecUncommon = vtkm::List<vtkm::Vec2i_8,
|
||||
vtkm::Vec2i_16,
|
||||
vtkm::Vec2ui_16,
|
||||
vtkm::Vec2ui_32,
|
||||
vtkm::Vec2ui_64,
|
||||
vtkm::Vec3i_8,
|
||||
vtkm::Vec3i_16,
|
||||
vtkm::Vec3ui_16,
|
||||
vtkm::Vec3ui_32,
|
||||
vtkm::Vec3ui_64,
|
||||
vtkm::Vec4i_8,
|
||||
vtkm::Vec4i_16,
|
||||
vtkm::Vec4ui_16,
|
||||
vtkm::Vec4ui_32,
|
||||
vtkm::Vec4ui_64>;
|
||||
|
||||
} // namespace internal
|
||||
|
||||
/// A list of all vector classes with standard types as components and
|
||||
/// lengths between 2 and 4.
|
||||
///
|
||||
using TypeListVecAll =
|
||||
vtkm::ListAppend<vtkm::TypeListVecCommon, vtkm::internal::TypeListVecUncommon>;
|
||||
|
||||
/// A list of all basic types listed in vtkm/Types.h. Does not include all
|
||||
/// possible VTK-m types like arbitrarily typed and sized Vecs (only up to
|
||||
/// length 4) or math types like matrices.
|
||||
///
|
||||
using TypeListAll = vtkm::ListAppend<vtkm::TypeListScalarAll, vtkm::TypeListVecAll>;
|
||||
|
||||
/// A list of the most commonly used types across multiple domains. Includes
|
||||
/// integers, floating points, and 3 dimensional vectors of floating points.
|
||||
///
|
||||
using TypeListCommon = vtkm::List<vtkm::UInt8,
|
||||
vtkm::Int32,
|
||||
vtkm::Int64,
|
||||
vtkm::Float32,
|
||||
vtkm::Float64,
|
||||
vtkm::Vec3f_32,
|
||||
vtkm::Vec3f_64>;
|
||||
|
||||
} // namespace vtkm
|
||||
|
||||
#endif //vtk_m_TypeList_h
|
@ -10,207 +10,65 @@
|
||||
#ifndef vtk_m_TypeListTag_h
|
||||
#define vtk_m_TypeListTag_h
|
||||
|
||||
// Everything in this header file is deprecated and movded to TypeList.h.
|
||||
|
||||
#ifndef VTKM_DEFAULT_TYPE_LIST_TAG
|
||||
#define VTKM_DEFAULT_TYPE_LIST_TAG ::vtkm::TypeListTagCommon
|
||||
#define VTKM_DEFAULT_TYPE_LIST_TAG ::vtkm::internal::TypeListTagDefault
|
||||
#endif
|
||||
|
||||
#include <vtkm/ListTag.h>
|
||||
#include <vtkm/Types.h>
|
||||
#include <vtkm/TypeList.h>
|
||||
|
||||
#define VTK_M_OLD_TYPE_LIST_DEFINITION(name) \
|
||||
struct VTKM_ALWAYS_EXPORT \
|
||||
VTKM_DEPRECATED( \
|
||||
1.6, \
|
||||
"TypeListTag" #name " replaced by TypeList" #name ". " \
|
||||
"Note that the new TypeList" #name " cannot be subclassed.") \
|
||||
TypeListTag ## name : vtkm::internal::ListAsListTag<TypeList ## name> \
|
||||
{ \
|
||||
}
|
||||
|
||||
VTKM_DEPRECATED_SUPPRESS_BEGIN
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
|
||||
/// A list containing the type vtkm::Id.
|
||||
///
|
||||
struct VTKM_ALWAYS_EXPORT TypeListTagId : vtkm::ListTagBase<vtkm::Id>
|
||||
{
|
||||
};
|
||||
|
||||
/// A list containing the type vtkm::Id2.
|
||||
///
|
||||
struct VTKM_ALWAYS_EXPORT TypeListTagId2 : vtkm::ListTagBase<vtkm::Id2>
|
||||
{
|
||||
};
|
||||
|
||||
/// A list containing the type vtkm::Id3.
|
||||
///
|
||||
struct VTKM_ALWAYS_EXPORT TypeListTagId3 : vtkm::ListTagBase<vtkm::Id3>
|
||||
{
|
||||
};
|
||||
|
||||
/// A list containing the type vtkm::IdComponent
|
||||
///
|
||||
struct VTKM_ALWAYS_EXPORT TypeListTagIdComponent : vtkm::ListTagBase<vtkm::IdComponent>
|
||||
{
|
||||
};
|
||||
|
||||
/// A list containing types used to index arrays. Contains vtkm::Id, vtkm::Id2,
|
||||
/// and vtkm::Id3.
|
||||
///
|
||||
struct VTKM_ALWAYS_EXPORT TypeListTagIndex : vtkm::ListTagBase<vtkm::Id, vtkm::Id2, vtkm::Id3>
|
||||
{
|
||||
};
|
||||
|
||||
/// A list containing types used for scalar fields. Specifically, contains
|
||||
/// floating point numbers of different widths (i.e. vtkm::Float32 and
|
||||
/// vtkm::Float64).
|
||||
struct VTKM_ALWAYS_EXPORT TypeListTagFieldScalar : vtkm::ListTagBase<vtkm::Float32, vtkm::Float64>
|
||||
{
|
||||
};
|
||||
|
||||
/// A list containing types for values for fields with two dimensional
|
||||
/// vectors.
|
||||
///
|
||||
struct VTKM_ALWAYS_EXPORT TypeListTagFieldVec2
|
||||
: vtkm::ListTagBase<vtkm::Vec2f_32, vtkm::Vec2f_64>
|
||||
{
|
||||
};
|
||||
|
||||
/// A list containing types for values for fields with three dimensional
|
||||
/// vectors.
|
||||
///
|
||||
struct VTKM_ALWAYS_EXPORT TypeListTagFieldVec3
|
||||
: vtkm::ListTagBase<vtkm::Vec3f_32, vtkm::Vec3f_64>
|
||||
{
|
||||
};
|
||||
|
||||
/// A list containing types for values for fields with four dimensional
|
||||
/// vectors.
|
||||
///
|
||||
struct VTKM_ALWAYS_EXPORT TypeListTagFieldVec4
|
||||
: vtkm::ListTagBase<vtkm::Vec4f_32, vtkm::Vec4f_64>
|
||||
{
|
||||
};
|
||||
|
||||
/// A list containing common types for floating-point vectors. Specifically contains
|
||||
/// floating point vectors of size 2, 3, and 4 with floating point components.
|
||||
/// Scalars are not included.
|
||||
///
|
||||
struct VTKM_ALWAYS_EXPORT TypeListTagFloatVec
|
||||
: vtkm::ListTagBase<vtkm::Vec2f_32,
|
||||
vtkm::Vec2f_64,
|
||||
vtkm::Vec3f_32,
|
||||
vtkm::Vec3f_64,
|
||||
vtkm::Vec4f_32,
|
||||
vtkm::Vec4f_64>
|
||||
{
|
||||
};
|
||||
|
||||
/// A list containing common types for values in fields. Specifically contains
|
||||
/// floating point scalars and vectors of size 2, 3, and 4 with floating point
|
||||
/// components.
|
||||
///
|
||||
struct VTKM_ALWAYS_EXPORT TypeListTagField
|
||||
: vtkm::ListTagBase<vtkm::Float32,
|
||||
vtkm::Float64,
|
||||
vtkm::Vec2f_32,
|
||||
vtkm::Vec2f_64,
|
||||
vtkm::Vec3f_32,
|
||||
vtkm::Vec3f_64,
|
||||
vtkm::Vec4f_32,
|
||||
vtkm::Vec4f_64>
|
||||
{
|
||||
};
|
||||
|
||||
/// A list of all scalars defined in vtkm/Types.h. A scalar is a type that
|
||||
/// holds a single number.
|
||||
///
|
||||
struct VTKM_ALWAYS_EXPORT TypeListTagScalarAll
|
||||
: vtkm::ListTagBase<vtkm::Int8,
|
||||
vtkm::UInt8,
|
||||
vtkm::Int16,
|
||||
vtkm::UInt16,
|
||||
vtkm::Int32,
|
||||
vtkm::UInt32,
|
||||
vtkm::Int64,
|
||||
vtkm::UInt64,
|
||||
vtkm::Float32,
|
||||
vtkm::Float64>
|
||||
{
|
||||
};
|
||||
|
||||
/// A list of the most commonly use Vec classes. Specifically, these are
|
||||
/// vectors of size 2, 3, or 4 containing either unsigned bytes, signed
|
||||
/// integers of 32 or 64 bits, or floating point values of 32 or 64 bits.
|
||||
///
|
||||
struct VTKM_ALWAYS_EXPORT TypeListTagVecCommon
|
||||
: vtkm::ListTagBase<vtkm::Vec2ui_8,
|
||||
vtkm::Vec2i_32,
|
||||
vtkm::Vec2i_64,
|
||||
vtkm::Vec2f_32,
|
||||
vtkm::Vec2f_64,
|
||||
vtkm::Vec3ui_8,
|
||||
vtkm::Vec3i_32,
|
||||
vtkm::Vec3i_64,
|
||||
vtkm::Vec3f_32,
|
||||
vtkm::Vec3f_64,
|
||||
vtkm::Vec4ui_8,
|
||||
vtkm::Vec4i_32,
|
||||
vtkm::Vec4i_64,
|
||||
vtkm::Vec4f_32,
|
||||
vtkm::Vec4f_64>
|
||||
{
|
||||
};
|
||||
VTK_M_OLD_TYPE_LIST_DEFINITION(Id);
|
||||
VTK_M_OLD_TYPE_LIST_DEFINITION(Id2);
|
||||
VTK_M_OLD_TYPE_LIST_DEFINITION(Id3);
|
||||
VTK_M_OLD_TYPE_LIST_DEFINITION(IdComponent);
|
||||
VTK_M_OLD_TYPE_LIST_DEFINITION(Index);
|
||||
VTK_M_OLD_TYPE_LIST_DEFINITION(FieldScalar);
|
||||
VTK_M_OLD_TYPE_LIST_DEFINITION(FieldVec2);
|
||||
VTK_M_OLD_TYPE_LIST_DEFINITION(FieldVec3);
|
||||
VTK_M_OLD_TYPE_LIST_DEFINITION(FieldVec4);
|
||||
VTK_M_OLD_TYPE_LIST_DEFINITION(FloatVec);
|
||||
VTK_M_OLD_TYPE_LIST_DEFINITION(Field);
|
||||
VTK_M_OLD_TYPE_LIST_DEFINITION(ScalarAll);
|
||||
VTK_M_OLD_TYPE_LIST_DEFINITION(VecCommon);
|
||||
VTK_M_OLD_TYPE_LIST_DEFINITION(VecAll);
|
||||
VTK_M_OLD_TYPE_LIST_DEFINITION(All);
|
||||
VTK_M_OLD_TYPE_LIST_DEFINITION(Common);
|
||||
|
||||
namespace internal
|
||||
{
|
||||
|
||||
/// A list of uncommon Vec classes with length up to 4. This is not much
|
||||
/// use in general, but is used when joined with \c TypeListTagVecCommon
|
||||
/// to get a list of all vectors up to size 4.
|
||||
///
|
||||
struct VTKM_ALWAYS_EXPORT TypeListTagVecUncommon
|
||||
: vtkm::ListTagBase<vtkm::Vec2i_8,
|
||||
vtkm::Vec2i_16,
|
||||
vtkm::Vec2ui_16,
|
||||
vtkm::Vec2ui_32,
|
||||
vtkm::Vec2ui_64,
|
||||
vtkm::Vec3i_8,
|
||||
vtkm::Vec3i_16,
|
||||
vtkm::Vec3ui_16,
|
||||
vtkm::Vec3ui_32,
|
||||
vtkm::Vec3ui_64,
|
||||
vtkm::Vec4i_8,
|
||||
vtkm::Vec4i_16,
|
||||
vtkm::Vec4ui_16,
|
||||
vtkm::Vec4ui_32,
|
||||
vtkm::Vec4ui_64>
|
||||
VTK_M_OLD_TYPE_LIST_DEFINITION(VecUncommon);
|
||||
|
||||
// Special definition of TypeListTagCommon to give descriptive warning when
|
||||
// VTKM_DEFAULT_TYPE_LIST_TAG is used.
|
||||
struct VTKM_ALWAYS_EXPORT
|
||||
VTKM_DEPRECATED(
|
||||
1.6,
|
||||
"VTKM_DEFAULT_TYPE_LIST_TAG replaced by VTKM_DEFAULT_TYPE_LIST. "
|
||||
"Note that the new VTKM_DEFAULT_TYPE_LIST cannot be subclassed.")
|
||||
TypeListTagDefault : vtkm::internal::ListAsListTag<VTKM_DEFAULT_TYPE_LIST>
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
/// A list of all vector classes with standard types as components and
|
||||
/// lengths between 2 and 4.
|
||||
///
|
||||
struct VTKM_ALWAYS_EXPORT TypeListTagVecAll
|
||||
: vtkm::ListTagJoin<vtkm::TypeListTagVecCommon, vtkm::internal::TypeListTagVecUncommon>
|
||||
{
|
||||
};
|
||||
|
||||
/// A list of all basic types listed in vtkm/Types.h. Does not include all
|
||||
/// possible VTK-m types like arbitrarily typed and sized Vecs (only up to
|
||||
/// length 4) or math types like matrices.
|
||||
///
|
||||
struct VTKM_ALWAYS_EXPORT TypeListTagAll
|
||||
: vtkm::ListTagJoin<vtkm::TypeListTagScalarAll, vtkm::TypeListTagVecAll>
|
||||
{
|
||||
};
|
||||
|
||||
/// A list of the most commonly used types across multiple domains. Includes
|
||||
/// integers, floating points, and 3 dimensional vectors of floating points.
|
||||
///
|
||||
struct VTKM_ALWAYS_EXPORT TypeListTagCommon
|
||||
: vtkm::ListTagBase<vtkm::UInt8,
|
||||
vtkm::Int32,
|
||||
vtkm::Int64,
|
||||
vtkm::Float32,
|
||||
vtkm::Float64,
|
||||
vtkm::Vec3f_32,
|
||||
vtkm::Vec3f_64>
|
||||
{
|
||||
};
|
||||
|
||||
// Special implementation of ListContains for TypeListTagAll to always be
|
||||
// true. Although TypeListTagAll is necessarily finite, the point is to
|
||||
// be all inclusive. Besides, this should speed up the compilation when
|
||||
@ -221,6 +79,24 @@ struct ListContains<vtkm::TypeListTagAll, Type>
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
|
||||
// Special implementation of ListHas for TypeListTagAll to always be
|
||||
// true. Although TypeListTagAll is necessarily finite, the point is to
|
||||
// be all inclusive. Besides, this should speed up the compilation when
|
||||
// checking a list that should contain everything.
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<typename Type>
|
||||
struct ListHasImpl<vtkm::TypeListTagAll, Type>
|
||||
{
|
||||
using type = std::true_type;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace vtkm
|
||||
|
||||
VTKM_DEPRECATED_SUPPRESS_END
|
||||
#undef VTK_M_OLD_TYPE_LIST_DEFINITION
|
||||
|
||||
#endif //vtk_m_TypeListTag_h
|
||||
|
13
vtkm/Types.h
13
vtkm/Types.h
@ -16,6 +16,7 @@
|
||||
#include <vtkm/Assert.h>
|
||||
#include <vtkm/StaticAssert.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <type_traits>
|
||||
|
||||
@ -152,12 +153,12 @@ namespace vtkm
|
||||
//*****************************************************************************
|
||||
using Float32 = float;
|
||||
using Float64 = double;
|
||||
using Int8 = signed char;
|
||||
using UInt8 = unsigned char;
|
||||
using Int16 = short;
|
||||
using UInt16 = unsigned short;
|
||||
using Int32 = int;
|
||||
using UInt32 = unsigned int;
|
||||
using Int8 = int8_t;
|
||||
using UInt8 = uint8_t;
|
||||
using Int16 = int16_t;
|
||||
using UInt16 = uint16_t;
|
||||
using Int32 = int32_t;
|
||||
using UInt32 = uint32_t;
|
||||
|
||||
/// Represents a component ID (index of component in a vector). The number
|
||||
/// of components, being a value fixed at compile time, is generally assumed
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
#include <vtkm/cont/DeviceAdapterTag.h>
|
||||
#include <vtkm/cont/ExecutionObjectBase.h>
|
||||
#include <vtkm/cont/Token.h>
|
||||
#include <vtkm/cont/TryExecute.h>
|
||||
#include <vtkm/cont/internal/ArrayManagerExecution.h>
|
||||
|
||||
@ -26,15 +27,15 @@ namespace cont
|
||||
namespace detail
|
||||
{
|
||||
template <typename Device, typename T>
|
||||
inline auto DoPrepareArgForExec(T&& object, std::true_type)
|
||||
-> decltype(std::declval<T>().PrepareForExecution(Device()))
|
||||
inline auto DoPrepareArgForExec(T&& object, vtkm::cont::Token& token, std::true_type) -> decltype(
|
||||
vtkm::cont::internal::CallPrepareForExecution(std::forward<T>(object), Device{}, token))
|
||||
{
|
||||
VTKM_IS_EXECUTION_OBJECT(T);
|
||||
return object.PrepareForExecution(Device{});
|
||||
return vtkm::cont::internal::CallPrepareForExecution(std::forward<T>(object), Device{}, token);
|
||||
}
|
||||
|
||||
template <typename Device, typename T>
|
||||
inline T&& DoPrepareArgForExec(T&& object, std::false_type)
|
||||
inline T&& DoPrepareArgForExec(T&& object, vtkm::cont::Token&, std::false_type)
|
||||
{
|
||||
static_assert(!vtkm::cont::internal::IsExecutionObjectBase<T>::value,
|
||||
"Internal error: failed to detect execution object.");
|
||||
@ -42,12 +43,13 @@ inline T&& DoPrepareArgForExec(T&& object, std::false_type)
|
||||
}
|
||||
|
||||
template <typename Device, typename T>
|
||||
auto PrepareArgForExec(T&& object)
|
||||
auto PrepareArgForExec(T&& object, vtkm::cont::Token& token)
|
||||
-> decltype(DoPrepareArgForExec<Device>(std::forward<T>(object),
|
||||
token,
|
||||
vtkm::cont::internal::IsExecutionObjectBase<T>{}))
|
||||
{
|
||||
return DoPrepareArgForExec<Device>(std::forward<T>(object),
|
||||
vtkm::cont::internal::IsExecutionObjectBase<T>{});
|
||||
return DoPrepareArgForExec<Device>(
|
||||
std::forward<T>(object), token, vtkm::cont::internal::IsExecutionObjectBase<T>{});
|
||||
}
|
||||
|
||||
struct BitFieldToUnorderedSetFunctor
|
||||
@ -58,8 +60,9 @@ struct BitFieldToUnorderedSetFunctor
|
||||
VTKM_CONT bool operator()(Device, Args&&... args)
|
||||
{
|
||||
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
|
||||
vtkm::cont::Token token;
|
||||
this->Result = vtkm::cont::DeviceAdapterAlgorithm<Device>::BitFieldToUnorderedSet(
|
||||
PrepareArgForExec<Device>(std::forward<Args>(args))...);
|
||||
PrepareArgForExec<Device>(std::forward<Args>(args), token)...);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@ -70,8 +73,9 @@ struct CopyFunctor
|
||||
VTKM_CONT bool operator()(Device, Args&&... args) const
|
||||
{
|
||||
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
|
||||
vtkm::cont::Token token;
|
||||
vtkm::cont::DeviceAdapterAlgorithm<Device>::Copy(
|
||||
PrepareArgForExec<Device>(std::forward<Args>(args))...);
|
||||
PrepareArgForExec<Device>(std::forward<Args>(args), token)...);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@ -83,8 +87,9 @@ struct CopyIfFunctor
|
||||
VTKM_CONT bool operator()(Device, Args&&... args) const
|
||||
{
|
||||
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
|
||||
vtkm::cont::Token token;
|
||||
vtkm::cont::DeviceAdapterAlgorithm<Device>::CopyIf(
|
||||
PrepareArgForExec<Device>(std::forward<Args>(args))...);
|
||||
PrepareArgForExec<Device>(std::forward<Args>(args), token)...);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@ -102,8 +107,9 @@ struct CopySubRangeFunctor
|
||||
VTKM_CONT bool operator()(Device, Args&&... args)
|
||||
{
|
||||
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
|
||||
vtkm::cont::Token token;
|
||||
valid = vtkm::cont::DeviceAdapterAlgorithm<Device>::CopySubRange(
|
||||
PrepareArgForExec<Device>(std::forward<Args>(args))...);
|
||||
PrepareArgForExec<Device>(std::forward<Args>(args), token)...);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@ -115,8 +121,10 @@ struct CountSetBitsFunctor
|
||||
template <typename Device, typename... Args>
|
||||
VTKM_CONT bool operator()(Device, Args&&... args)
|
||||
{
|
||||
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
|
||||
vtkm::cont::Token token;
|
||||
this->PopCount = vtkm::cont::DeviceAdapterAlgorithm<Device>::CountSetBits(
|
||||
PrepareArgForExec<Device>(std::forward<Args>(args))...);
|
||||
PrepareArgForExec<Device>(std::forward<Args>(args), token)...);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@ -126,8 +134,10 @@ struct FillFunctor
|
||||
template <typename Device, typename... Args>
|
||||
VTKM_CONT bool operator()(Device, Args&&... args)
|
||||
{
|
||||
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
|
||||
vtkm::cont::Token token;
|
||||
vtkm::cont::DeviceAdapterAlgorithm<Device>::Fill(
|
||||
PrepareArgForExec<Device>(std::forward<Args>(args))...);
|
||||
PrepareArgForExec<Device>(std::forward<Args>(args), token)...);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@ -139,8 +149,9 @@ struct LowerBoundsFunctor
|
||||
VTKM_CONT bool operator()(Device, Args&&... args) const
|
||||
{
|
||||
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
|
||||
vtkm::cont::Token token;
|
||||
vtkm::cont::DeviceAdapterAlgorithm<Device>::LowerBounds(
|
||||
PrepareArgForExec<Device>(std::forward<Args>(args))...);
|
||||
PrepareArgForExec<Device>(std::forward<Args>(args), token)...);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@ -159,8 +170,9 @@ struct ReduceFunctor
|
||||
VTKM_CONT bool operator()(Device, Args&&... args)
|
||||
{
|
||||
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
|
||||
vtkm::cont::Token token;
|
||||
result = vtkm::cont::DeviceAdapterAlgorithm<Device>::Reduce(
|
||||
PrepareArgForExec<Device>(std::forward<Args>(args))...);
|
||||
PrepareArgForExec<Device>(std::forward<Args>(args), token)...);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@ -171,8 +183,9 @@ struct ReduceByKeyFunctor
|
||||
VTKM_CONT bool operator()(Device, Args&&... args) const
|
||||
{
|
||||
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
|
||||
vtkm::cont::Token token;
|
||||
vtkm::cont::DeviceAdapterAlgorithm<Device>::ReduceByKey(
|
||||
PrepareArgForExec<Device>(std::forward<Args>(args))...);
|
||||
PrepareArgForExec<Device>(std::forward<Args>(args), token)...);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@ -191,8 +204,9 @@ struct ScanInclusiveResultFunctor
|
||||
VTKM_CONT bool operator()(Device, Args&&... args)
|
||||
{
|
||||
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
|
||||
vtkm::cont::Token token;
|
||||
result = vtkm::cont::DeviceAdapterAlgorithm<Device>::ScanInclusive(
|
||||
PrepareArgForExec<Device>(std::forward<Args>(args))...);
|
||||
PrepareArgForExec<Device>(std::forward<Args>(args), token)...);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@ -275,8 +289,9 @@ struct ScanInclusiveByKeyFunctor
|
||||
VTKM_CONT bool operator()(Device, Args&&... args) const
|
||||
{
|
||||
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
|
||||
vtkm::cont::Token token;
|
||||
vtkm::cont::DeviceAdapterAlgorithm<Device>::ScanInclusiveByKey(
|
||||
PrepareArgForExec<Device>(std::forward<Args>(args))...);
|
||||
PrepareArgForExec<Device>(std::forward<Args>(args), token)...);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@ -295,8 +310,9 @@ struct ScanExclusiveFunctor
|
||||
VTKM_CONT bool operator()(Device, Args&&... args)
|
||||
{
|
||||
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
|
||||
vtkm::cont::Token token;
|
||||
result = vtkm::cont::DeviceAdapterAlgorithm<Device>::ScanExclusive(
|
||||
PrepareArgForExec<Device>(std::forward<Args>(args))...);
|
||||
PrepareArgForExec<Device>(std::forward<Args>(args), token)...);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@ -309,8 +325,9 @@ struct ScanExclusiveByKeyFunctor
|
||||
VTKM_CONT bool operator()(Device, Args&&... args) const
|
||||
{
|
||||
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
|
||||
vtkm::cont::Token token;
|
||||
vtkm::cont::DeviceAdapterAlgorithm<Device>::ScanExclusiveByKey(
|
||||
PrepareArgForExec<Device>(std::forward<Args>(args))...);
|
||||
PrepareArgForExec<Device>(std::forward<Args>(args), token)...);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@ -322,8 +339,9 @@ struct ScanExtendedFunctor
|
||||
VTKM_CONT bool operator()(Device, Args&&... args)
|
||||
{
|
||||
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
|
||||
vtkm::cont::Token token;
|
||||
vtkm::cont::DeviceAdapterAlgorithm<Device>::ScanExtended(
|
||||
PrepareArgForExec<Device>(std::forward<Args>(args))...);
|
||||
PrepareArgForExec<Device>(std::forward<Args>(args), token)...);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@ -334,8 +352,9 @@ struct ScheduleFunctor
|
||||
VTKM_CONT bool operator()(Device, Args&&... args)
|
||||
{
|
||||
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
|
||||
vtkm::cont::Token token;
|
||||
vtkm::cont::DeviceAdapterAlgorithm<Device>::Schedule(
|
||||
PrepareArgForExec<Device>(std::forward<Args>(args))...);
|
||||
PrepareArgForExec<Device>(std::forward<Args>(args), token)...);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@ -346,8 +365,9 @@ struct SortFunctor
|
||||
VTKM_CONT bool operator()(Device, Args&&... args) const
|
||||
{
|
||||
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
|
||||
vtkm::cont::Token token;
|
||||
vtkm::cont::DeviceAdapterAlgorithm<Device>::Sort(
|
||||
PrepareArgForExec<Device>(std::forward<Args>(args))...);
|
||||
PrepareArgForExec<Device>(std::forward<Args>(args), token)...);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@ -358,8 +378,9 @@ struct SortByKeyFunctor
|
||||
VTKM_CONT bool operator()(Device, Args&&... args) const
|
||||
{
|
||||
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
|
||||
vtkm::cont::Token token;
|
||||
vtkm::cont::DeviceAdapterAlgorithm<Device>::SortByKey(
|
||||
PrepareArgForExec<Device>(std::forward<Args>(args))...);
|
||||
PrepareArgForExec<Device>(std::forward<Args>(args), token)...);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@ -381,8 +402,9 @@ struct TransformFunctor
|
||||
VTKM_CONT bool operator()(Device, Args&&... args) const
|
||||
{
|
||||
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
|
||||
vtkm::cont::Token token;
|
||||
vtkm::cont::DeviceAdapterAlgorithm<Device>::Transform(
|
||||
PrepareArgForExec<Device>(std::forward<Args>(args))...);
|
||||
PrepareArgForExec<Device>(std::forward<Args>(args), token)...);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@ -393,8 +415,9 @@ struct UniqueFunctor
|
||||
VTKM_CONT bool operator()(Device, Args&&... args) const
|
||||
{
|
||||
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
|
||||
vtkm::cont::Token token;
|
||||
vtkm::cont::DeviceAdapterAlgorithm<Device>::Unique(
|
||||
PrepareArgForExec<Device>(std::forward<Args>(args))...);
|
||||
PrepareArgForExec<Device>(std::forward<Args>(args), token)...);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@ -405,8 +428,9 @@ struct UpperBoundsFunctor
|
||||
VTKM_CONT bool operator()(Device, Args&&... args) const
|
||||
{
|
||||
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
|
||||
vtkm::cont::Token token;
|
||||
vtkm::cont::DeviceAdapterAlgorithm<Device>::UpperBounds(
|
||||
PrepareArgForExec<Device>(std::forward<Args>(args))...);
|
||||
PrepareArgForExec<Device>(std::forward<Args>(args), token)...);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
@ -35,8 +35,8 @@ namespace cont
|
||||
///
|
||||
/// These functions should not be called repeatedly in a loop to fetch all
|
||||
/// values from an array handle. The much more efficient way to do this is to
|
||||
/// use the proper control-side portals (ArrayHandle::GetPortalControl() and
|
||||
/// ArrayHandle::GetPortalConstControl()).
|
||||
/// use the proper control-side portals (ArrayHandle::WritePortal() and
|
||||
/// ArrayHandle::ReadPortal()).
|
||||
///
|
||||
/// This method will attempt to copy the data using the device that the input
|
||||
/// data is already valid on. If the input data is only valid in the control
|
||||
@ -111,10 +111,10 @@ VTKM_CONT void ArrayGetValues(const vtkm::cont::ArrayHandle<vtkm::Id, SIds>& ids
|
||||
{ // Fallback to a control-side copy if the device copy fails or if the device
|
||||
// is undefined:
|
||||
const vtkm::Id numVals = ids.GetNumberOfValues();
|
||||
auto idPortal = ids.GetPortalConstControl();
|
||||
auto dataPortal = data.GetPortalConstControl();
|
||||
auto idPortal = ids.ReadPortal();
|
||||
auto dataPortal = data.ReadPortal();
|
||||
output.Allocate(numVals);
|
||||
auto outPortal = output.GetPortalControl();
|
||||
auto outPortal = output.WritePortal();
|
||||
for (vtkm::Id i = 0; i < numVals; ++i)
|
||||
{
|
||||
outPortal.Set(i, dataPortal.Get(idPortal.Get(i)));
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <vtkm/cont/vtkm_cont_export.h>
|
||||
|
||||
#include <vtkm/Assert.h>
|
||||
#include <vtkm/Deprecated.h>
|
||||
#include <vtkm/Flags.h>
|
||||
#include <vtkm/Types.h>
|
||||
|
||||
@ -23,16 +24,19 @@
|
||||
#include <vtkm/cont/Serialization.h>
|
||||
#include <vtkm/cont/Storage.h>
|
||||
#include <vtkm/cont/StorageBasic.h>
|
||||
#include <vtkm/cont/Token.h>
|
||||
|
||||
#include <vtkm/internal/ArrayPortalHelpers.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
#include <vtkm/cont/internal/ArrayHandleExecutionManager.h>
|
||||
#include <vtkm/cont/internal/ArrayPortalFromIterators.h>
|
||||
#include <vtkm/cont/internal/ArrayPortalToken.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
@ -57,24 +61,18 @@ class VTKM_CONT_EXPORT ArrayHandleBase
|
||||
/// with C++11 type_traits.
|
||||
///
|
||||
template <typename T, typename StorageTag>
|
||||
struct IsValidArrayHandle
|
||||
: std::integral_constant<bool,
|
||||
!(std::is_base_of<vtkm::cont::internal::UndefinedStorage,
|
||||
vtkm::cont::internal::Storage<T, StorageTag>>::value)>
|
||||
{
|
||||
};
|
||||
using IsValidArrayHandle =
|
||||
std::integral_constant<bool,
|
||||
!(std::is_base_of<vtkm::cont::internal::UndefinedStorage,
|
||||
vtkm::cont::internal::Storage<T, StorageTag>>::value)>;
|
||||
|
||||
/// Checks to see if the given type and storage forms a invalid array handle
|
||||
/// (some storage objects cannot support all types). This check is compatible
|
||||
/// with C++11 type_traits.
|
||||
///
|
||||
template <typename T, typename StorageTag>
|
||||
struct IsInValidArrayHandle
|
||||
: std::integral_constant<bool,
|
||||
(std::is_base_of<vtkm::cont::internal::UndefinedStorage,
|
||||
vtkm::cont::internal::Storage<T, StorageTag>>::value)>
|
||||
{
|
||||
};
|
||||
using IsInValidArrayHandle =
|
||||
std::integral_constant<bool, !IsValidArrayHandle<T, StorageTag>::value>;
|
||||
|
||||
/// Checks to see if the ArrayHandle allows writing, as some ArrayHandles
|
||||
/// (Implicit) don't support writing. These will be defined as either
|
||||
@ -84,7 +82,7 @@ struct IsInValidArrayHandle
|
||||
///
|
||||
template <typename ArrayHandle>
|
||||
using IsWritableArrayHandle =
|
||||
vtkm::internal::PortalSupportsSets<typename std::decay<ArrayHandle>::type::PortalControl>;
|
||||
vtkm::internal::PortalSupportsSets<typename std::decay<ArrayHandle>::type::WritePortalType>;
|
||||
/// @}
|
||||
|
||||
/// Checks to see if the given object is an array handle. This check is
|
||||
@ -257,12 +255,16 @@ private:
|
||||
using ExecutionManagerType =
|
||||
vtkm::cont::internal::ArrayHandleExecutionManagerBase<T, StorageTag_>;
|
||||
|
||||
using MutexType = std::mutex;
|
||||
using LockType = std::unique_lock<MutexType>;
|
||||
|
||||
public:
|
||||
using StorageType = vtkm::cont::internal::Storage<T, StorageTag_>;
|
||||
using ValueType = T;
|
||||
using StorageTag = StorageTag_;
|
||||
using PortalControl = typename StorageType::PortalType;
|
||||
using PortalConstControl = typename StorageType::PortalConstType;
|
||||
using WritePortalType = vtkm::cont::internal::ArrayPortalToken<typename StorageType::PortalType>;
|
||||
using ReadPortalType =
|
||||
vtkm::cont::internal::ArrayPortalToken<typename StorageType::PortalConstType>;
|
||||
template <typename DeviceAdapterTag>
|
||||
struct ExecutionTypes
|
||||
{
|
||||
@ -271,6 +273,11 @@ public:
|
||||
typename ExecutionManagerType::template ExecutionTypes<DeviceAdapterTag>::PortalConst;
|
||||
};
|
||||
|
||||
using PortalControl VTKM_DEPRECATED(1.6, "Use ArrayHandle::WritePortalType instead.") =
|
||||
typename StorageType::PortalType;
|
||||
using PortalConstControl VTKM_DEPRECATED(1.6, "Use ArrayHandle::ReadPortalType instead.") =
|
||||
typename StorageType::PortalConstType;
|
||||
|
||||
/// Constructs an empty ArrayHandle. Typically used for output or
|
||||
/// intermediate arrays that will be filled by a VTKm algorithm.
|
||||
///
|
||||
@ -367,17 +374,70 @@ public:
|
||||
/// Since worklet invocations are asynchronous and this routine is a synchronization point,
|
||||
/// exceptions maybe thrown for errors from previously executed worklets.
|
||||
///
|
||||
VTKM_CONT PortalControl GetPortalControl();
|
||||
/// \deprecated Use `WritePortal` instead. Note that the portal returned from `WritePortal`
|
||||
/// will disallow any other reads or writes to the array while it is in scope.
|
||||
///
|
||||
VTKM_CONT
|
||||
VTKM_DEPRECATED(1.6,
|
||||
"Use ArrayHandle::WritePortal() instead. "
|
||||
"Note that the returned portal will lock the array while it is in scope.")
|
||||
typename StorageType::PortalType GetPortalControl();
|
||||
|
||||
/// Get the array portal of the control array.
|
||||
/// Since worklet invocations are asynchronous and this routine is a synchronization point,
|
||||
/// exceptions maybe thrown for errors from previously executed worklets.
|
||||
///
|
||||
VTKM_CONT PortalConstControl GetPortalConstControl() const;
|
||||
/// \deprecated Use `ReadPortal` instead. Note that the portal returned from `ReadPortal`
|
||||
/// will disallow any writes to the array while it is in scope.
|
||||
///
|
||||
VTKM_CONT
|
||||
VTKM_DEPRECATED(1.6,
|
||||
"Use ArrayHandle::ReadPortal() instead. "
|
||||
"Note that the returned portal will lock the array while it is in scope.")
|
||||
typename StorageType::PortalConstType GetPortalConstControl() const;
|
||||
|
||||
/// \brief Get an array portal that can be used in the control environment.
|
||||
///
|
||||
/// The returned array can be used in the control environment to read values from the array. (It
|
||||
/// is not possible to write to the returned portal. That is `Get` will work on the portal, but
|
||||
/// `Set` will not.)
|
||||
///
|
||||
/// **Note:** The returned portal will prevent any writes or modifications to the array. To
|
||||
/// ensure that the data pointed to by the portal is valid, this `ArrayHandle` will be locked to
|
||||
/// any modifications while the portal remains in scope. (You can call `Detach` on the returned
|
||||
/// portal to unlock the array. However, this will invalidate the portal.)
|
||||
///
|
||||
/// **Note:** The returned portal cannot be used in the execution environment. This is because
|
||||
/// the portal will not work on some devices like GPUs. To get a portal that will work in the
|
||||
/// execution environment, use `PrepareForInput`.
|
||||
///
|
||||
VTKM_CONT ReadPortalType ReadPortal() const;
|
||||
|
||||
/// \brief Get an array portal that can be used in the control environment.
|
||||
///
|
||||
/// The returned array can be used in the control environment to reand and write values to the
|
||||
/// array.
|
||||
///
|
||||
/// **Note:** The returned portal will prevent any reads, writes, or modifications to the array.
|
||||
/// To ensure that the data pointed to by the portal is valid, this `ArrayHandle` will be locked
|
||||
/// to any modifications while the portal remains in scope. Also, to make sure that no reads get
|
||||
/// out of sync, reads other than the returned portal are also blocked. (You can call `Detach` on
|
||||
/// the returned portal to unlock the array. However, this will invalidate the portal.)
|
||||
///
|
||||
/// **Note:** The returned portal cannot be used in the execution environment. This is because
|
||||
/// the portal will not work on some devices like GPUs. To get a portal that will work in the
|
||||
/// execution environment, use `PrepareForInput`.
|
||||
///
|
||||
VTKM_CONT WritePortalType WritePortal() const;
|
||||
|
||||
/// Returns the number of entries in the array.
|
||||
///
|
||||
VTKM_CONT vtkm::Id GetNumberOfValues() const;
|
||||
VTKM_CONT vtkm::Id GetNumberOfValues() const
|
||||
{
|
||||
LockType lock = this->GetLock();
|
||||
|
||||
return this->GetNumberOfValues(lock);
|
||||
}
|
||||
|
||||
/// \brief Allocates an array large enough to hold the given number of values.
|
||||
///
|
||||
@ -390,9 +450,11 @@ public:
|
||||
VTKM_CONT
|
||||
void Allocate(vtkm::Id numberOfValues)
|
||||
{
|
||||
this->ReleaseResourcesExecutionInternal();
|
||||
this->Internals->ControlArray.Allocate(numberOfValues);
|
||||
this->Internals->ControlArrayValid = true;
|
||||
LockType lock = this->GetLock();
|
||||
this->WaitToWrite(lock, vtkm::cont::Token{});
|
||||
this->ReleaseResourcesExecutionInternal(lock);
|
||||
this->Internals->GetControlArray(lock)->Allocate(numberOfValues);
|
||||
this->Internals->SetControlArrayValid(lock, true);
|
||||
}
|
||||
|
||||
/// \brief Reduces the size of the array without changing its values.
|
||||
@ -410,37 +472,48 @@ public:
|
||||
///
|
||||
VTKM_CONT void ReleaseResourcesExecution()
|
||||
{
|
||||
LockType lock = this->GetLock();
|
||||
this->WaitToWrite(lock, vtkm::cont::Token{});
|
||||
|
||||
// Save any data in the execution environment by making sure it is synced
|
||||
// with the control environment.
|
||||
this->SyncControlArray();
|
||||
this->SyncControlArray(lock);
|
||||
|
||||
this->ReleaseResourcesExecutionInternal();
|
||||
this->ReleaseResourcesExecutionInternal(lock);
|
||||
}
|
||||
|
||||
/// Releases all resources in both the control and execution environments.
|
||||
///
|
||||
VTKM_CONT void ReleaseResources()
|
||||
{
|
||||
this->ReleaseResourcesExecutionInternal();
|
||||
LockType lock = this->GetLock();
|
||||
|
||||
if (this->Internals->ControlArrayValid)
|
||||
this->ReleaseResourcesExecutionInternal(lock);
|
||||
|
||||
if (this->Internals->IsControlArrayValid(lock))
|
||||
{
|
||||
this->Internals->ControlArray.ReleaseResources();
|
||||
this->Internals->ControlArrayValid = false;
|
||||
this->Internals->GetControlArray(lock)->ReleaseResources();
|
||||
this->Internals->SetControlArrayValid(lock, false);
|
||||
}
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
/// Prepares this array to be used as an input to an operation in the
|
||||
/// execution environment. If necessary, copies data to the execution
|
||||
/// environment. Can throw an exception if this array does not yet contain
|
||||
/// any data. Returns a portal that can be used in code running in the
|
||||
/// execution environment.
|
||||
///
|
||||
/// The `Token` object provided will be attached to this `ArrayHandle`.
|
||||
/// The returned portal is guaranteed to be valid while the `Token` is
|
||||
/// still attached and in scope. Other operations on this `ArrayHandle`
|
||||
/// that would invalidate the returned portal will block until the `Token`
|
||||
/// is released. Likewise, this method will block if another `Token` is
|
||||
/// already attached. This can potentially lead to deadlocks.
|
||||
///
|
||||
template <typename DeviceAdapterTag>
|
||||
VTKM_CONT
|
||||
typename ExecutionTypes<DeviceAdapterTag>::PortalConst PrepareForInput(DeviceAdapterTag) const;
|
||||
// clang-format on
|
||||
VTKM_CONT typename ExecutionTypes<DeviceAdapterTag>::PortalConst PrepareForInput(
|
||||
DeviceAdapterTag,
|
||||
vtkm::cont::Token& token) const;
|
||||
|
||||
/// Prepares (allocates) this array to be used as an output from an operation
|
||||
/// in the execution environment. The internal state of this class is set to
|
||||
@ -449,10 +522,16 @@ public:
|
||||
/// called). Returns a portal that can be used in code running in the
|
||||
/// execution environment.
|
||||
///
|
||||
/// The `Token` object provided will be attached to this `ArrayHandle`.
|
||||
/// The returned portal is guaranteed to be valid while the `Token` is
|
||||
/// still attached and in scope. Other operations on this `ArrayHandle`
|
||||
/// that would invalidate the returned portal will block until the `Token`
|
||||
/// is released. Likewise, this method will block if another `Token` is
|
||||
/// already attached. This can potentially lead to deadlocks.
|
||||
///
|
||||
template <typename DeviceAdapterTag>
|
||||
VTKM_CONT typename ExecutionTypes<DeviceAdapterTag>::Portal PrepareForOutput(
|
||||
vtkm::Id numberOfValues,
|
||||
DeviceAdapterTag);
|
||||
VTKM_CONT typename ExecutionTypes<DeviceAdapterTag>::Portal
|
||||
PrepareForOutput(vtkm::Id numberOfValues, DeviceAdapterTag, vtkm::cont::Token& token);
|
||||
|
||||
/// Prepares this array to be used in an in-place operation (both as input
|
||||
/// and output) in the execution environment. If necessary, copies data to
|
||||
@ -460,16 +539,55 @@ public:
|
||||
/// yet contain any data. Returns a portal that can be used in code running
|
||||
/// in the execution environment.
|
||||
///
|
||||
template <typename DeviceAdapterTag>
|
||||
VTKM_CONT typename ExecutionTypes<DeviceAdapterTag>::Portal PrepareForInPlace(DeviceAdapterTag);
|
||||
|
||||
/// Gets this array handle ready to interact with the given device. If the
|
||||
/// array handle has already interacted with this device, then this method
|
||||
/// does nothing. Although the internal state of this class can change, the
|
||||
/// method is declared const because logically the data does not.
|
||||
/// The `Token` object provided will be attached to this `ArrayHandle`.
|
||||
/// The returned portal is guaranteed to be valid while the `Token` is
|
||||
/// still attached and in scope. Other operations on this `ArrayHandle`
|
||||
/// that would invalidate the returned portal will block until the `Token`
|
||||
/// is released. Likewise, this method will block if another `Token` is
|
||||
/// already attached. This can potentially lead to deadlocks.
|
||||
///
|
||||
template <typename DeviceAdapterTag>
|
||||
VTKM_CONT void PrepareForDevice(DeviceAdapterTag) const;
|
||||
VTKM_CONT typename ExecutionTypes<DeviceAdapterTag>::Portal PrepareForInPlace(
|
||||
DeviceAdapterTag,
|
||||
vtkm::cont::Token& token);
|
||||
|
||||
template <typename DeviceAdapterTag>
|
||||
VTKM_CONT VTKM_DEPRECATED(1.6, "PrepareForInput now requires a vtkm::cont::Token object.")
|
||||
typename ExecutionTypes<DeviceAdapterTag>::PortalConst PrepareForInput(DeviceAdapterTag) const
|
||||
{
|
||||
vtkm::cont::Token token;
|
||||
return this->PrepareForInput(DeviceAdapterTag{}, token);
|
||||
}
|
||||
template <typename DeviceAdapterTag>
|
||||
VTKM_CONT VTKM_DEPRECATED(1.6, "PrepareForOutput now requires a vtkm::cont::Token object.")
|
||||
typename ExecutionTypes<DeviceAdapterTag>::Portal
|
||||
PrepareForOutput(vtkm::Id numberOfValues, DeviceAdapterTag)
|
||||
{
|
||||
vtkm::cont::Token token;
|
||||
return this->PrepareForOutput(numberOfValues, DeviceAdapterTag{}, token);
|
||||
}
|
||||
template <typename DeviceAdapterTag>
|
||||
VTKM_CONT VTKM_DEPRECATED(1.6, "PrepareForInPlace now requires a vtkm::cont::Token object.")
|
||||
typename ExecutionTypes<DeviceAdapterTag>::Portal PrepareForInPlace(DeviceAdapterTag)
|
||||
{
|
||||
vtkm::cont::Token token;
|
||||
return this->PrepareForInPlace(DeviceAdapterTag{}, token);
|
||||
}
|
||||
|
||||
/// Returns the DeviceAdapterId for the current device. If there is no device
|
||||
/// with an up-to-date copy of the data, VTKM_DEVICE_ADAPTER_UNDEFINED is
|
||||
/// returned.
|
||||
///
|
||||
/// Note that in a multithreaded environment the validity of this result can
|
||||
/// change.
|
||||
VTKM_CONT
|
||||
DeviceAdapterId GetDeviceAdapterId() const
|
||||
{
|
||||
LockType lock = this->GetLock();
|
||||
return this->Internals->IsExecutionArrayValid(lock)
|
||||
? this->Internals->GetExecutionArray(lock)->GetDeviceAdapterId()
|
||||
: DeviceAdapterTagUndefined{};
|
||||
}
|
||||
|
||||
/// Synchronizes the control array with the execution array. If either the
|
||||
/// user array or control array is already valid, this method does nothing
|
||||
@ -477,38 +595,193 @@ public:
|
||||
/// Although the internal state of this class can change, the method is
|
||||
/// declared const because logically the data does not.
|
||||
///
|
||||
VTKM_CONT void SyncControlArray() const;
|
||||
VTKM_CONT void SyncControlArray() const
|
||||
{
|
||||
LockType lock = this->GetLock();
|
||||
this->SyncControlArray(lock);
|
||||
}
|
||||
|
||||
// Probably should make this private, but ArrayHandleStreaming needs access.
|
||||
protected:
|
||||
/// Acquires a lock on the internals of this `ArrayHandle`. The calling
|
||||
/// function should keep the returned lock and let it go out of scope
|
||||
/// when the lock is no longer needed.
|
||||
///
|
||||
LockType GetLock() const { return LockType(this->Internals->Mutex); }
|
||||
|
||||
/// Returns true if read operations can currently be performed.
|
||||
///
|
||||
VTKM_CONT bool CanRead(const LockType& lock, const vtkm::cont::Token& token) const
|
||||
{
|
||||
return ((*this->Internals->GetWriteCount(lock) < 1) ||
|
||||
(token.IsAttached(this->Internals->GetWriteCount(lock))));
|
||||
}
|
||||
|
||||
//// Returns true if write operations can currently be performed.
|
||||
///
|
||||
VTKM_CONT bool CanWrite(const LockType& lock, const vtkm::cont::Token& token) const
|
||||
{
|
||||
return (((*this->Internals->GetWriteCount(lock) < 1) ||
|
||||
(token.IsAttached(this->Internals->GetWriteCount(lock)))) &&
|
||||
((*this->Internals->GetReadCount(lock) < 1) ||
|
||||
((*this->Internals->GetReadCount(lock) == 1) &&
|
||||
token.IsAttached(this->Internals->GetReadCount(lock)))));
|
||||
}
|
||||
|
||||
//// Will block the current thread until a read can be performed.
|
||||
///
|
||||
VTKM_CONT void WaitToRead(LockType& lock, const vtkm::cont::Token& token) const
|
||||
{
|
||||
// Note that if you deadlocked here, that means that you are trying to do a read operation on
|
||||
// an array where an object is writing to it. This could happen on the same thread. For
|
||||
// example, if you call `GetPortalControl()` then no other operation that can result in reading
|
||||
// or writing data in the array can happen while the resulting portal is still in scope.
|
||||
this->Internals->ConditionVariable.wait(
|
||||
lock, [&lock, &token, this] { return this->CanRead(lock, token); });
|
||||
}
|
||||
|
||||
//// Will block the current thread until a write can be performed.
|
||||
///
|
||||
VTKM_CONT void WaitToWrite(LockType& lock, const vtkm::cont::Token& token) const
|
||||
{
|
||||
// Note that if you deadlocked here, that means that you are trying to do a write operation on
|
||||
// an array where an object is reading or writing to it. This could happen on the same thread.
|
||||
// For example, if you call `GetPortalControl()` then no other operation that can result in
|
||||
// reading or writing data in the array can happen while the resulting portal is still in
|
||||
// scope.
|
||||
this->Internals->ConditionVariable.wait(
|
||||
lock, [&lock, &token, this] { return this->CanWrite(lock, token); });
|
||||
}
|
||||
|
||||
/// Gets this array handle ready to interact with the given device. If the
|
||||
/// array handle has already interacted with this device, then this method
|
||||
/// does nothing. Although the internal state of this class can change, the
|
||||
/// method is declared const because logically the data does not.
|
||||
///
|
||||
template <typename DeviceAdapterTag>
|
||||
VTKM_CONT void PrepareForDevice(LockType& lock, DeviceAdapterTag) const;
|
||||
|
||||
/// Synchronizes the control array with the execution array. If either the
|
||||
/// user array or control array is already valid, this method does nothing
|
||||
/// (because the data is already available in the control environment).
|
||||
/// Although the internal state of this class can change, the method is
|
||||
/// declared const because logically the data does not.
|
||||
///
|
||||
VTKM_CONT void SyncControlArray(LockType& lock) const;
|
||||
|
||||
vtkm::Id GetNumberOfValues(LockType& lock) const;
|
||||
|
||||
VTKM_CONT
|
||||
void ReleaseResourcesExecutionInternal()
|
||||
void ReleaseResourcesExecutionInternal(LockType& lock) const
|
||||
{
|
||||
if (this->Internals->ExecutionArrayValid)
|
||||
if (this->Internals->IsExecutionArrayValid(lock))
|
||||
{
|
||||
this->Internals->ExecutionArray->ReleaseResources();
|
||||
this->Internals->ExecutionArrayValid = false;
|
||||
this->WaitToWrite(lock, vtkm::cont::Token{});
|
||||
// Note that it is possible that while waiting someone else deleted the execution array.
|
||||
// That is why we check again.
|
||||
}
|
||||
if (this->Internals->IsExecutionArrayValid(lock))
|
||||
{
|
||||
this->Internals->GetExecutionArray(lock)->ReleaseResources();
|
||||
this->Internals->SetExecutionArrayValid(lock, false);
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the DeviceAdapterId for the current device. If there is no device
|
||||
/// with an up-to-date copy of the data, VTKM_DEVICE_ADAPTER_UNDEFINED is
|
||||
/// returned.
|
||||
VTKM_CONT
|
||||
DeviceAdapterId GetDeviceAdapterId() const
|
||||
{
|
||||
return this->Internals->ExecutionArrayValid
|
||||
? this->Internals->ExecutionArray->GetDeviceAdapterId()
|
||||
: DeviceAdapterTagUndefined{};
|
||||
}
|
||||
|
||||
struct VTKM_ALWAYS_EXPORT InternalStruct
|
||||
class VTKM_ALWAYS_EXPORT InternalStruct
|
||||
{
|
||||
mutable StorageType ControlArray;
|
||||
mutable bool ControlArrayValid;
|
||||
mutable bool ControlArrayValid = false;
|
||||
|
||||
mutable std::unique_ptr<
|
||||
vtkm::cont::internal::ArrayHandleExecutionManagerBase<ValueType, StorageTag>>
|
||||
ExecutionArray;
|
||||
mutable bool ExecutionArrayValid;
|
||||
mutable std::unique_ptr<ExecutionManagerType> ExecutionArray;
|
||||
mutable bool ExecutionArrayValid = false;
|
||||
|
||||
mutable vtkm::cont::Token::ReferenceCount ReadCount = 0;
|
||||
mutable vtkm::cont::Token::ReferenceCount WriteCount = 0;
|
||||
|
||||
VTKM_CONT void CheckLock(const LockType& lock) const
|
||||
{
|
||||
VTKM_ASSERT((lock.mutex() == &this->Mutex) && (lock.owns_lock()));
|
||||
}
|
||||
|
||||
public:
|
||||
MutexType Mutex;
|
||||
std::condition_variable ConditionVariable;
|
||||
|
||||
InternalStruct() = default;
|
||||
InternalStruct(const StorageType& storage);
|
||||
InternalStruct(StorageType&& storage);
|
||||
|
||||
#ifdef VTKM_ASSERTS_CHECKED
|
||||
~InternalStruct()
|
||||
{
|
||||
// It should not be possible to destroy this array if any tokens are still attached to it.
|
||||
LockType lock(this->Mutex);
|
||||
VTKM_ASSERT((*this->GetReadCount(lock) == 0) && (*this->GetWriteCount(lock) == 0));
|
||||
}
|
||||
#else
|
||||
~InternalStruct() = default;
|
||||
#endif
|
||||
|
||||
// To access any feature in InternalStruct, you must have locked the mutex. You have
|
||||
// to prove it by passing in a reference to a std::unique_lock.
|
||||
VTKM_CONT bool IsControlArrayValid(const LockType& lock) const
|
||||
{
|
||||
this->CheckLock(lock);
|
||||
return this->ControlArrayValid;
|
||||
}
|
||||
VTKM_CONT void SetControlArrayValid(const LockType& lock, bool value)
|
||||
{
|
||||
this->CheckLock(lock);
|
||||
this->ControlArrayValid = value;
|
||||
}
|
||||
VTKM_CONT StorageType* GetControlArray(const LockType& lock) const
|
||||
{
|
||||
this->CheckLock(lock);
|
||||
return &this->ControlArray;
|
||||
}
|
||||
|
||||
VTKM_CONT bool IsExecutionArrayValid(const LockType& lock) const
|
||||
{
|
||||
this->CheckLock(lock);
|
||||
return this->ExecutionArrayValid;
|
||||
}
|
||||
VTKM_CONT void SetExecutionArrayValid(const LockType& lock, bool value)
|
||||
{
|
||||
this->CheckLock(lock);
|
||||
this->ExecutionArrayValid = value;
|
||||
}
|
||||
VTKM_CONT ExecutionManagerType* GetExecutionArray(const LockType& lock) const
|
||||
{
|
||||
this->CheckLock(lock);
|
||||
return this->ExecutionArray.get();
|
||||
}
|
||||
VTKM_CONT void DeleteExecutionArray(const LockType& lock)
|
||||
{
|
||||
this->CheckLock(lock);
|
||||
this->ExecutionArray.reset();
|
||||
this->ExecutionArrayValid = false;
|
||||
}
|
||||
template <typename DeviceAdapterTag>
|
||||
VTKM_CONT void NewExecutionArray(const LockType& lock, DeviceAdapterTag)
|
||||
{
|
||||
VTKM_IS_DEVICE_ADAPTER_TAG(DeviceAdapterTag);
|
||||
this->CheckLock(lock);
|
||||
VTKM_ASSERT(this->ExecutionArray == nullptr);
|
||||
VTKM_ASSERT(!this->ExecutionArrayValid);
|
||||
this->ExecutionArray.reset(
|
||||
new vtkm::cont::internal::ArrayHandleExecutionManager<T, StorageTag, DeviceAdapterTag>(
|
||||
&this->ControlArray));
|
||||
}
|
||||
VTKM_CONT vtkm::cont::Token::ReferenceCount* GetReadCount(const LockType& lock) const
|
||||
{
|
||||
this->CheckLock(lock);
|
||||
return &this->ReadCount;
|
||||
}
|
||||
VTKM_CONT vtkm::cont::Token::ReferenceCount* GetWriteCount(const LockType& lock) const
|
||||
{
|
||||
this->CheckLock(lock);
|
||||
return &this->WriteCount;
|
||||
}
|
||||
};
|
||||
|
||||
VTKM_CONT
|
||||
@ -531,8 +804,7 @@ make_ArrayHandle(const T* array, vtkm::Id length, vtkm::CopyFlag copy = vtkm::Co
|
||||
{
|
||||
ArrayHandleType handle;
|
||||
handle.Allocate(length);
|
||||
std::copy(
|
||||
array, array + length, vtkm::cont::ArrayPortalToIteratorBegin(handle.GetPortalControl()));
|
||||
std::copy(array, array + length, vtkm::cont::ArrayPortalToIteratorBegin(handle.WritePortal()));
|
||||
return handle;
|
||||
}
|
||||
else
|
||||
@ -634,7 +906,7 @@ VTKM_NEVER_EXPORT VTKM_CONT inline void printSummary_ArrayHandle(
|
||||
bool full = false)
|
||||
{
|
||||
using ArrayType = vtkm::cont::ArrayHandle<T, StorageT>;
|
||||
using PortalType = typename ArrayType::PortalConstControl;
|
||||
using PortalType = typename ArrayType::ReadPortalType;
|
||||
using IsVec = typename vtkm::VecTraits<T>::HasMultipleComponents;
|
||||
|
||||
vtkm::Id sz = array.GetNumberOfValues();
|
||||
@ -642,7 +914,7 @@ VTKM_NEVER_EXPORT VTKM_CONT inline void printSummary_ArrayHandle(
|
||||
out << "valueType=" << typeid(T).name() << " storageType=" << typeid(StorageT).name()
|
||||
<< " numValues=" << sz << " bytes=" << (static_cast<size_t>(sz) * sizeof(T)) << " [";
|
||||
|
||||
PortalType portal = array.GetPortalConstControl();
|
||||
PortalType portal = array.ReadPortal();
|
||||
if (full || sz <= 7)
|
||||
{
|
||||
for (vtkm::Id i = 0; i < sz; i++)
|
||||
|
@ -18,11 +18,26 @@ namespace cont
|
||||
{
|
||||
|
||||
template <typename T, typename S>
|
||||
ArrayHandle<T, S>::ArrayHandle()
|
||||
: Internals(new InternalStruct)
|
||||
ArrayHandle<T, S>::InternalStruct::InternalStruct(
|
||||
const typename ArrayHandle<T, S>::StorageType& storage)
|
||||
: ControlArray(storage)
|
||||
, ControlArrayValid(true)
|
||||
, ExecutionArrayValid(false)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
ArrayHandle<T, S>::InternalStruct::InternalStruct(typename ArrayHandle<T, S>::StorageType&& storage)
|
||||
: ControlArray(std::move(storage))
|
||||
, ControlArrayValid(true)
|
||||
, ExecutionArrayValid(false)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
ArrayHandle<T, S>::ArrayHandle()
|
||||
: Internals(std::make_shared<InternalStruct>())
|
||||
{
|
||||
this->Internals->ControlArrayValid = false;
|
||||
this->Internals->ExecutionArrayValid = false;
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
@ -39,20 +54,14 @@ ArrayHandle<T, S>::ArrayHandle(ArrayHandle<T, S>&& src) noexcept
|
||||
|
||||
template <typename T, typename S>
|
||||
ArrayHandle<T, S>::ArrayHandle(const typename ArrayHandle<T, S>::StorageType& storage)
|
||||
: Internals(new InternalStruct)
|
||||
: Internals(std::make_shared<InternalStruct>(storage))
|
||||
{
|
||||
this->Internals->ControlArray = storage;
|
||||
this->Internals->ControlArrayValid = true;
|
||||
this->Internals->ExecutionArrayValid = false;
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
ArrayHandle<T, S>::ArrayHandle(typename ArrayHandle<T, S>::StorageType&& storage) noexcept
|
||||
: Internals(new InternalStruct)
|
||||
: Internals(std::make_shared<InternalStruct>(std::move(storage)))
|
||||
{
|
||||
this->Internals->ControlArray = std::move(storage);
|
||||
this->Internals->ControlArrayValid = true;
|
||||
this->Internals->ExecutionArrayValid = false;
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
@ -77,10 +86,12 @@ ArrayHandle<T, S>& ArrayHandle<T, S>::operator=(ArrayHandle<T, S>&& src) noexcep
|
||||
template <typename T, typename S>
|
||||
typename ArrayHandle<T, S>::StorageType& ArrayHandle<T, S>::GetStorage()
|
||||
{
|
||||
this->SyncControlArray();
|
||||
if (this->Internals->ControlArrayValid)
|
||||
LockType lock = this->GetLock();
|
||||
|
||||
this->SyncControlArray(lock);
|
||||
if (this->Internals->IsControlArrayValid(lock))
|
||||
{
|
||||
return this->Internals->ControlArray;
|
||||
return *this->Internals->GetControlArray(lock);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -92,10 +103,12 @@ typename ArrayHandle<T, S>::StorageType& ArrayHandle<T, S>::GetStorage()
|
||||
template <typename T, typename S>
|
||||
const typename ArrayHandle<T, S>::StorageType& ArrayHandle<T, S>::GetStorage() const
|
||||
{
|
||||
this->SyncControlArray();
|
||||
if (this->Internals->ControlArrayValid)
|
||||
LockType lock = this->GetLock();
|
||||
|
||||
this->SyncControlArray(lock);
|
||||
if (this->Internals->IsControlArrayValid(lock))
|
||||
{
|
||||
return this->Internals->ControlArray;
|
||||
return *this->Internals->GetControlArray(lock);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -105,16 +118,18 @@ const typename ArrayHandle<T, S>::StorageType& ArrayHandle<T, S>::GetStorage() c
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
typename ArrayHandle<T, S>::PortalControl ArrayHandle<T, S>::GetPortalControl()
|
||||
typename ArrayHandle<T, S>::StorageType::PortalType ArrayHandle<T, S>::GetPortalControl()
|
||||
{
|
||||
this->SyncControlArray();
|
||||
if (this->Internals->ControlArrayValid)
|
||||
LockType lock = this->GetLock();
|
||||
|
||||
this->SyncControlArray(lock);
|
||||
if (this->Internals->IsControlArrayValid(lock))
|
||||
{
|
||||
// If the user writes into the iterator we return, then the execution
|
||||
// array will become invalid. Play it safe and release the execution
|
||||
// resources. (Use the const version to preserve the execution array.)
|
||||
this->ReleaseResourcesExecutionInternal();
|
||||
return this->Internals->ControlArray.GetPortal();
|
||||
this->ReleaseResourcesExecutionInternal(lock);
|
||||
return this->Internals->GetControlArray(lock)->GetPortal();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -124,12 +139,15 @@ typename ArrayHandle<T, S>::PortalControl ArrayHandle<T, S>::GetPortalControl()
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
typename ArrayHandle<T, S>::PortalConstControl ArrayHandle<T, S>::GetPortalConstControl() const
|
||||
typename ArrayHandle<T, S>::StorageType::PortalConstType ArrayHandle<T, S>::GetPortalConstControl()
|
||||
const
|
||||
{
|
||||
this->SyncControlArray();
|
||||
if (this->Internals->ControlArrayValid)
|
||||
LockType lock = this->GetLock();
|
||||
|
||||
this->SyncControlArray(lock);
|
||||
if (this->Internals->IsControlArrayValid(lock))
|
||||
{
|
||||
return this->Internals->ControlArray.GetPortalConst();
|
||||
return this->Internals->GetControlArray(lock)->GetPortalConst();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -139,15 +157,62 @@ typename ArrayHandle<T, S>::PortalConstControl ArrayHandle<T, S>::GetPortalConst
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
vtkm::Id ArrayHandle<T, S>::GetNumberOfValues() const
|
||||
typename ArrayHandle<T, S>::ReadPortalType ArrayHandle<T, S>::ReadPortal() const
|
||||
{
|
||||
if (this->Internals->ControlArrayValid)
|
||||
LockType lock = this->GetLock();
|
||||
vtkm::cont::Token token;
|
||||
this->WaitToRead(lock, token);
|
||||
|
||||
this->SyncControlArray(lock);
|
||||
if (this->Internals->IsControlArrayValid(lock))
|
||||
{
|
||||
return this->Internals->ControlArray.GetNumberOfValues();
|
||||
token.Attach(
|
||||
*this, this->Internals->GetReadCount(lock), lock, &this->Internals->ConditionVariable);
|
||||
return ReadPortalType(std::move(token),
|
||||
this->Internals->GetControlArray(lock)->GetPortalConst());
|
||||
}
|
||||
else if (this->Internals->ExecutionArrayValid)
|
||||
else
|
||||
{
|
||||
return this->Internals->ExecutionArray->GetNumberOfValues();
|
||||
throw vtkm::cont::ErrorInternal(
|
||||
"ArrayHandle::SyncControlArray did not make control array valid.");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
typename ArrayHandle<T, S>::WritePortalType ArrayHandle<T, S>::WritePortal() const
|
||||
{
|
||||
LockType lock = this->GetLock();
|
||||
vtkm::cont::Token token;
|
||||
this->WaitToWrite(lock, token);
|
||||
|
||||
this->SyncControlArray(lock);
|
||||
if (this->Internals->IsControlArrayValid(lock))
|
||||
{
|
||||
// If the user writes into the iterator we return, then the execution
|
||||
// array will become invalid. Play it safe and release the execution
|
||||
// resources. (Use the const version to preserve the execution array.)
|
||||
this->ReleaseResourcesExecutionInternal(lock);
|
||||
token.Attach(
|
||||
*this, this->Internals->GetWriteCount(lock), lock, &this->Internals->ConditionVariable);
|
||||
return WritePortalType(std::move(token), this->Internals->GetControlArray(lock)->GetPortal());
|
||||
}
|
||||
else
|
||||
{
|
||||
throw vtkm::cont::ErrorInternal(
|
||||
"ArrayHandle::SyncControlArray did not make control array valid.");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
vtkm::Id ArrayHandle<T, S>::GetNumberOfValues(LockType& lock) const
|
||||
{
|
||||
if (this->Internals->IsControlArrayValid(lock))
|
||||
{
|
||||
return this->Internals->GetControlArray(lock)->GetNumberOfValues();
|
||||
}
|
||||
else if (this->Internals->IsExecutionArrayValid(lock))
|
||||
{
|
||||
return this->Internals->GetExecutionArray(lock)->GetNumberOfValues();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -162,17 +227,20 @@ void ArrayHandle<T, S>::Shrink(vtkm::Id numberOfValues)
|
||||
|
||||
if (numberOfValues > 0)
|
||||
{
|
||||
vtkm::Id originalNumberOfValues = this->GetNumberOfValues();
|
||||
LockType lock = this->GetLock();
|
||||
|
||||
vtkm::Id originalNumberOfValues = this->GetNumberOfValues(lock);
|
||||
|
||||
if (numberOfValues < originalNumberOfValues)
|
||||
{
|
||||
if (this->Internals->ControlArrayValid)
|
||||
this->WaitToWrite(lock, vtkm::cont::Token{});
|
||||
if (this->Internals->IsControlArrayValid(lock))
|
||||
{
|
||||
this->Internals->ControlArray.Shrink(numberOfValues);
|
||||
this->Internals->GetControlArray(lock)->Shrink(numberOfValues);
|
||||
}
|
||||
if (this->Internals->ExecutionArrayValid)
|
||||
if (this->Internals->IsExecutionArrayValid(lock))
|
||||
{
|
||||
this->Internals->ExecutionArray->Shrink(numberOfValues);
|
||||
this->Internals->GetExecutionArray(lock)->Shrink(numberOfValues);
|
||||
}
|
||||
}
|
||||
else if (numberOfValues == originalNumberOfValues)
|
||||
@ -184,7 +252,7 @@ void ArrayHandle<T, S>::Shrink(vtkm::Id numberOfValues)
|
||||
throw vtkm::cont::ErrorBadValue("ArrayHandle::Shrink cannot be used to grow array.");
|
||||
}
|
||||
|
||||
VTKM_ASSERT(this->GetNumberOfValues() == numberOfValues);
|
||||
VTKM_ASSERT(this->GetNumberOfValues(lock) == numberOfValues);
|
||||
}
|
||||
else // numberOfValues == 0
|
||||
{
|
||||
@ -198,24 +266,29 @@ void ArrayHandle<T, S>::Shrink(vtkm::Id numberOfValues)
|
||||
template <typename T, typename S>
|
||||
template <typename DeviceAdapterTag>
|
||||
typename ArrayHandle<T, S>::template ExecutionTypes<DeviceAdapterTag>::PortalConst
|
||||
ArrayHandle<T, S>::PrepareForInput(DeviceAdapterTag) const
|
||||
ArrayHandle<T, S>::PrepareForInput(DeviceAdapterTag device, vtkm::cont::Token& token) const
|
||||
{
|
||||
VTKM_IS_DEVICE_ADAPTER_TAG(DeviceAdapterTag);
|
||||
|
||||
if (!this->Internals->ControlArrayValid && !this->Internals->ExecutionArrayValid)
|
||||
LockType lock = this->GetLock();
|
||||
this->WaitToRead(lock, token);
|
||||
|
||||
if (!this->Internals->IsControlArrayValid(lock) && !this->Internals->IsExecutionArrayValid(lock))
|
||||
{
|
||||
// Want to use an empty array.
|
||||
// Set up ArrayHandle state so this actually works.
|
||||
this->Internals->ControlArray.Allocate(0);
|
||||
this->Internals->ControlArrayValid = true;
|
||||
this->Internals->GetControlArray(lock)->Allocate(0);
|
||||
this->Internals->SetControlArrayValid(lock, true);
|
||||
}
|
||||
|
||||
this->PrepareForDevice(DeviceAdapterTag());
|
||||
typename ExecutionTypes<DeviceAdapterTag>::PortalConst portal =
|
||||
this->Internals->ExecutionArray->PrepareForInput(!this->Internals->ExecutionArrayValid,
|
||||
DeviceAdapterTag());
|
||||
this->PrepareForDevice(lock, device);
|
||||
auto portal = this->Internals->GetExecutionArray(lock)->PrepareForInput(
|
||||
!this->Internals->IsExecutionArrayValid(lock), device, token);
|
||||
|
||||
this->Internals->ExecutionArrayValid = true;
|
||||
this->Internals->SetExecutionArrayValid(lock, true);
|
||||
|
||||
token.Attach(
|
||||
*this, this->Internals->GetReadCount(lock), lock, &this->Internals->ConditionVariable);
|
||||
|
||||
return portal;
|
||||
}
|
||||
@ -223,18 +296,23 @@ typename ArrayHandle<T, S>::template ExecutionTypes<DeviceAdapterTag>::PortalCon
|
||||
template <typename T, typename S>
|
||||
template <typename DeviceAdapterTag>
|
||||
typename ArrayHandle<T, S>::template ExecutionTypes<DeviceAdapterTag>::Portal
|
||||
ArrayHandle<T, S>::PrepareForOutput(vtkm::Id numberOfValues, DeviceAdapterTag)
|
||||
ArrayHandle<T, S>::PrepareForOutput(vtkm::Id numberOfValues,
|
||||
DeviceAdapterTag device,
|
||||
vtkm::cont::Token& token)
|
||||
{
|
||||
VTKM_IS_DEVICE_ADAPTER_TAG(DeviceAdapterTag);
|
||||
|
||||
LockType lock = this->GetLock();
|
||||
this->WaitToWrite(lock, token);
|
||||
|
||||
// Invalidate any control arrays.
|
||||
// Should the control array resource be released? Probably not a good
|
||||
// idea when shared with execution.
|
||||
this->Internals->ControlArrayValid = false;
|
||||
this->Internals->SetControlArrayValid(lock, false);
|
||||
|
||||
this->PrepareForDevice(DeviceAdapterTag());
|
||||
typename ExecutionTypes<DeviceAdapterTag>::Portal portal =
|
||||
this->Internals->ExecutionArray->PrepareForOutput(numberOfValues, DeviceAdapterTag());
|
||||
this->PrepareForDevice(lock, device);
|
||||
auto portal =
|
||||
this->Internals->GetExecutionArray(lock)->PrepareForOutput(numberOfValues, device, token);
|
||||
|
||||
// We are assuming that the calling code will fill the array using the
|
||||
// iterators we are returning, so go ahead and mark the execution array as
|
||||
@ -245,7 +323,10 @@ ArrayHandle<T, S>::PrepareForOutput(vtkm::Id numberOfValues, DeviceAdapterTag)
|
||||
// implementation the only access to the array is through the iterators
|
||||
// returned from this method, so you would have to work to invalidate this
|
||||
// assumption anyway.)
|
||||
this->Internals->ExecutionArrayValid = true;
|
||||
this->Internals->SetExecutionArrayValid(lock, true);
|
||||
|
||||
token.Attach(
|
||||
*this, this->Internals->GetWriteCount(lock), lock, &this->Internals->ConditionVariable);
|
||||
|
||||
return portal;
|
||||
}
|
||||
@ -253,40 +334,45 @@ ArrayHandle<T, S>::PrepareForOutput(vtkm::Id numberOfValues, DeviceAdapterTag)
|
||||
template <typename T, typename S>
|
||||
template <typename DeviceAdapterTag>
|
||||
typename ArrayHandle<T, S>::template ExecutionTypes<DeviceAdapterTag>::Portal
|
||||
ArrayHandle<T, S>::PrepareForInPlace(DeviceAdapterTag)
|
||||
ArrayHandle<T, S>::PrepareForInPlace(DeviceAdapterTag device, vtkm::cont::Token& token)
|
||||
{
|
||||
VTKM_IS_DEVICE_ADAPTER_TAG(DeviceAdapterTag);
|
||||
|
||||
if (!this->Internals->ControlArrayValid && !this->Internals->ExecutionArrayValid)
|
||||
LockType lock = this->GetLock();
|
||||
this->WaitToWrite(lock, token);
|
||||
|
||||
if (!this->Internals->IsControlArrayValid(lock) && !this->Internals->IsExecutionArrayValid(lock))
|
||||
{
|
||||
// Want to use an empty array.
|
||||
// Set up ArrayHandle state so this actually works.
|
||||
this->Internals->ControlArray.Allocate(0);
|
||||
this->Internals->ControlArrayValid = true;
|
||||
this->Internals->GetControlArray(lock)->Allocate(0);
|
||||
this->Internals->SetControlArrayValid(lock, true);
|
||||
}
|
||||
|
||||
this->PrepareForDevice(DeviceAdapterTag());
|
||||
typename ExecutionTypes<DeviceAdapterTag>::Portal portal =
|
||||
this->Internals->ExecutionArray->PrepareForInPlace(!this->Internals->ExecutionArrayValid,
|
||||
DeviceAdapterTag());
|
||||
this->PrepareForDevice(lock, device);
|
||||
auto portal = this->Internals->GetExecutionArray(lock)->PrepareForInPlace(
|
||||
!this->Internals->IsExecutionArrayValid(lock), device, token);
|
||||
|
||||
this->Internals->ExecutionArrayValid = true;
|
||||
this->Internals->SetExecutionArrayValid(lock, true);
|
||||
|
||||
// Invalidate any control arrays since their data will become invalid when
|
||||
// the execution data is overwritten. Don't actually release the control
|
||||
// array. It may be shared as the execution array.
|
||||
this->Internals->ControlArrayValid = false;
|
||||
this->Internals->SetControlArrayValid(lock, false);
|
||||
|
||||
token.Attach(
|
||||
*this, this->Internals->GetWriteCount(lock), lock, &this->Internals->ConditionVariable);
|
||||
|
||||
return portal;
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
template <typename DeviceAdapterTag>
|
||||
void ArrayHandle<T, S>::PrepareForDevice(DeviceAdapterTag) const
|
||||
void ArrayHandle<T, S>::PrepareForDevice(LockType& lock, DeviceAdapterTag device) const
|
||||
{
|
||||
if (this->Internals->ExecutionArray != nullptr)
|
||||
if (this->Internals->GetExecutionArray(lock) != nullptr)
|
||||
{
|
||||
if (this->Internals->ExecutionArray->IsDeviceAdapter(DeviceAdapterTag()))
|
||||
if (this->Internals->GetExecutionArray(lock)->IsDeviceAdapter(DeviceAdapterTag()))
|
||||
{
|
||||
// Already have manager for correct device adapter. Nothing to do.
|
||||
return;
|
||||
@ -294,47 +380,53 @@ void ArrayHandle<T, S>::PrepareForDevice(DeviceAdapterTag) const
|
||||
else
|
||||
{
|
||||
// Have the wrong manager. Delete the old one and create a new one
|
||||
// of the right type. (BTW, it would be possible for the array handle
|
||||
// to hold references to execution arrays on multiple devices. However,
|
||||
// there is not a clear use case for that yet and it is unclear what
|
||||
// the behavior of "dirty" arrays should be, so it is not currently
|
||||
// implemented.)
|
||||
this->SyncControlArray();
|
||||
// of the right type. (TODO: it would be possible for the array handle
|
||||
// to hold references to execution arrays on multiple devices. When data
|
||||
// are written on one devices, all the other devices should get cleared.)
|
||||
|
||||
// BUG: There is a non-zero chance that while waiting for the write lock, another thread
|
||||
// could change the ExecutionInterface, which would cause problems. In the future we should
|
||||
// support multiple devices, in which case we would not have to delete one execution array
|
||||
// to load another.
|
||||
this->WaitToWrite(lock, vtkm::cont::Token{}); // Make sure no one is reading device array
|
||||
this->SyncControlArray(lock);
|
||||
// Need to change some state that does not change the logical state from
|
||||
// an external point of view.
|
||||
this->Internals->ExecutionArray.reset();
|
||||
this->Internals->ExecutionArrayValid = false;
|
||||
this->Internals->DeleteExecutionArray(lock);
|
||||
}
|
||||
}
|
||||
|
||||
VTKM_ASSERT(this->Internals->ExecutionArray == nullptr);
|
||||
VTKM_ASSERT(!this->Internals->ExecutionArrayValid);
|
||||
// Need to change some state that does not change the logical state from
|
||||
// an external point of view.
|
||||
this->Internals->ExecutionArray.reset(
|
||||
new vtkm::cont::internal::ArrayHandleExecutionManager<T, StorageTag, DeviceAdapterTag>(
|
||||
&this->Internals->ControlArray));
|
||||
this->Internals->NewExecutionArray(lock, device);
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
void ArrayHandle<T, S>::SyncControlArray() const
|
||||
void ArrayHandle<T, S>::SyncControlArray(LockType& lock) const
|
||||
{
|
||||
if (!this->Internals->ControlArrayValid)
|
||||
if (!this->Internals->IsControlArrayValid(lock))
|
||||
{
|
||||
// It may be the case that `SyncControlArray` is called from a method that has a `Token`.
|
||||
// However, if we are here, that `Token` should not already be attached to this array.
|
||||
// If it were, then there should be no reason to move data arround (unless the `Token`
|
||||
// was used when preparing for multiple devices, which it should not be used like that).
|
||||
this->WaitToRead(lock, vtkm::cont::Token{});
|
||||
|
||||
// Need to change some state that does not change the logical state from
|
||||
// an external point of view.
|
||||
if (this->Internals->ExecutionArrayValid)
|
||||
if (this->Internals->IsExecutionArrayValid(lock))
|
||||
{
|
||||
this->Internals->ExecutionArray->RetrieveOutputData(&this->Internals->ControlArray);
|
||||
this->Internals->ControlArrayValid = true;
|
||||
this->Internals->GetExecutionArray(lock)->RetrieveOutputData(
|
||||
this->Internals->GetControlArray(lock));
|
||||
this->Internals->SetControlArrayValid(lock, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This array is in the null state (there is nothing allocated), but
|
||||
// the calling function wants to do something with the array. Put this
|
||||
// class into a valid state by allocating an array of size 0.
|
||||
this->Internals->ControlArray.Allocate(0);
|
||||
this->Internals->ControlArrayValid = true;
|
||||
this->Internals->GetControlArray(lock)->Allocate(0);
|
||||
this->Internals->SetControlArrayValid(lock, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -359,7 +451,7 @@ inline void VTKM_CONT StorageSerialization(vtkmdiy::BinaryBuffer& bb,
|
||||
vtkmdiy::save(bb, count);
|
||||
|
||||
vtkmdiy::save(bb, vtkm::Id(0)); //not a basic storage
|
||||
auto portal = obj.GetPortalConstControl();
|
||||
auto portal = obj.ReadPortal();
|
||||
for (vtkm::Id i = 0; i < count; ++i)
|
||||
{
|
||||
vtkmdiy::save(bb, portal.Get(i));
|
||||
@ -409,7 +501,7 @@ VTKM_CONT void Serialization<vtkm::cont::ArrayHandle<T>>::load(BinaryBuffer& bb,
|
||||
}
|
||||
else
|
||||
{
|
||||
auto portal = obj.GetPortalControl();
|
||||
auto portal = obj.WritePortal();
|
||||
for (vtkm::Id i = 0; i < count; ++i)
|
||||
{
|
||||
T val{};
|
||||
|
@ -88,10 +88,10 @@ public:
|
||||
VTKM_CONT Storage& operator=(Storage&&) noexcept = default;
|
||||
|
||||
VTKM_CONT
|
||||
PortalType GetPortal() { return PortalType{ this->Data.GetPortalControl() }; }
|
||||
PortalType GetPortal() { return PortalType{ this->Data.WritePortal() }; }
|
||||
|
||||
VTKM_CONT
|
||||
PortalConstType GetPortalConst() { return PortalConstType{ this->Data.GetPortalConstControl() }; }
|
||||
PortalConstType GetPortalConst() { return PortalConstType{ this->Data.ReadPortal() }; }
|
||||
|
||||
VTKM_CONT vtkm::Id GetNumberOfValues() const { return this->Data.GetNumberOfBits(); }
|
||||
VTKM_CONT void Allocate(vtkm::Id numberOfValues) { this->Data.Allocate(numberOfValues); }
|
||||
@ -129,21 +129,21 @@ public:
|
||||
vtkm::Id GetNumberOfValues() const { return this->Data.GetNumberOfBits(); }
|
||||
|
||||
VTKM_CONT
|
||||
PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData))
|
||||
PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData), vtkm::cont::Token& token)
|
||||
{
|
||||
return PortalConstExecution{ this->Data.PrepareForInput(Device{}) };
|
||||
return PortalConstExecution{ this->Data.PrepareForInput(Device{}, token) };
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
PortalExecution PrepareForInPlace(bool vtkmNotUsed(updateData))
|
||||
PortalExecution PrepareForInPlace(bool vtkmNotUsed(updateData), vtkm::cont::Token& token)
|
||||
{
|
||||
return PortalExecution{ this->Data.PrepareForInPlace(Device{}) };
|
||||
return PortalExecution{ this->Data.PrepareForInPlace(Device{}, token) };
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
PortalExecution PrepareForOutput(vtkm::Id numberOfValues)
|
||||
PortalExecution PrepareForOutput(vtkm::Id numberOfValues, vtkm::cont::Token& token)
|
||||
{
|
||||
return PortalExecution{ this->Data.PrepareForOutput(numberOfValues, Device{}) };
|
||||
return PortalExecution{ this->Data.PrepareForOutput(numberOfValues, Device{}, token) };
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
#include <vtkm/cont/ArrayHandle.h>
|
||||
#include <vtkm/cont/ErrorBadAllocation.h>
|
||||
#include <vtkm/cont/Token.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
@ -154,54 +155,69 @@ namespace vtkm
|
||||
namespace cont
|
||||
{
|
||||
|
||||
namespace internal
|
||||
{
|
||||
|
||||
template <typename FirstHandleType, typename SecondHandleType, typename ThirdHandleType>
|
||||
template <typename StorageTag1, typename StorageTag2, typename StorageTag3>
|
||||
struct VTKM_ALWAYS_EXPORT StorageTagCartesianProduct
|
||||
{
|
||||
};
|
||||
|
||||
namespace internal
|
||||
{
|
||||
|
||||
/// This helper struct defines the value type for a zip container containing
|
||||
/// the given two array handles.
|
||||
///
|
||||
template <typename FirstHandleType, typename SecondHandleType, typename ThirdHandleType>
|
||||
template <typename AH1, typename AH2, typename AH3>
|
||||
struct ArrayHandleCartesianProductTraits
|
||||
{
|
||||
VTKM_IS_ARRAY_HANDLE(AH1);
|
||||
VTKM_IS_ARRAY_HANDLE(AH2);
|
||||
VTKM_IS_ARRAY_HANDLE(AH3);
|
||||
|
||||
using ComponentType = typename AH1::ValueType;
|
||||
VTKM_STATIC_ASSERT_MSG(
|
||||
(std::is_same<ComponentType, typename AH2::ValueType>::value),
|
||||
"All arrays for ArrayHandleCartesianProduct must have the same value type. "
|
||||
"Use ArrayHandleCast as necessary to make types match.");
|
||||
VTKM_STATIC_ASSERT_MSG(
|
||||
(std::is_same<ComponentType, typename AH3::ValueType>::value),
|
||||
"All arrays for ArrayHandleCartesianProduct must have the same value type. "
|
||||
"Use ArrayHandleCast as necessary to make types match.");
|
||||
|
||||
/// The ValueType (a pair containing the value types of the two arrays).
|
||||
///
|
||||
using ValueType = vtkm::Vec<typename FirstHandleType::ValueType, 3>;
|
||||
using ValueType = vtkm::Vec<ComponentType, 3>;
|
||||
|
||||
/// The appropriately templated tag.
|
||||
///
|
||||
using Tag = StorageTagCartesianProduct<FirstHandleType, SecondHandleType, ThirdHandleType>;
|
||||
using Tag = vtkm::cont::StorageTagCartesianProduct<typename AH1::StorageTag,
|
||||
typename AH2::StorageTag,
|
||||
typename AH3::StorageTag>;
|
||||
|
||||
/// The superclass for ArrayHandleCartesianProduct.
|
||||
///
|
||||
using Superclass = vtkm::cont::ArrayHandle<ValueType, Tag>;
|
||||
};
|
||||
|
||||
template <typename FirstHandleType, typename SecondHandleType, typename ThirdHandleType>
|
||||
class Storage<vtkm::Vec<typename FirstHandleType::ValueType, 3>,
|
||||
StorageTagCartesianProduct<FirstHandleType, SecondHandleType, ThirdHandleType>>
|
||||
template <typename T, typename ST1, typename ST2, typename ST3>
|
||||
class Storage<vtkm::Vec<T, 3>, vtkm::cont::StorageTagCartesianProduct<ST1, ST2, ST3>>
|
||||
{
|
||||
VTKM_IS_ARRAY_HANDLE(FirstHandleType);
|
||||
VTKM_IS_ARRAY_HANDLE(SecondHandleType);
|
||||
VTKM_IS_ARRAY_HANDLE(ThirdHandleType);
|
||||
using AH1 = vtkm::cont::ArrayHandle<T, ST1>;
|
||||
using AH2 = vtkm::cont::ArrayHandle<T, ST2>;
|
||||
using AH3 = vtkm::cont::ArrayHandle<T, ST3>;
|
||||
|
||||
public:
|
||||
using ValueType = vtkm::Vec<typename FirstHandleType::ValueType, 3>;
|
||||
using ValueType = vtkm::Vec<typename AH1::ValueType, 3>;
|
||||
|
||||
using PortalType =
|
||||
vtkm::exec::internal::ArrayPortalCartesianProduct<ValueType,
|
||||
typename FirstHandleType::PortalControl,
|
||||
typename SecondHandleType::PortalControl,
|
||||
typename ThirdHandleType::PortalControl>;
|
||||
typename AH1::WritePortalType,
|
||||
typename AH2::WritePortalType,
|
||||
typename AH3::WritePortalType>;
|
||||
using PortalConstType =
|
||||
vtkm::exec::internal::ArrayPortalCartesianProduct<ValueType,
|
||||
typename FirstHandleType::PortalConstControl,
|
||||
typename SecondHandleType::PortalConstControl,
|
||||
typename ThirdHandleType::PortalConstControl>;
|
||||
typename AH1::ReadPortalType,
|
||||
typename AH2::ReadPortalType,
|
||||
typename AH3::ReadPortalType>;
|
||||
|
||||
VTKM_CONT
|
||||
Storage()
|
||||
@ -212,9 +228,7 @@ public:
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
Storage(const FirstHandleType& array1,
|
||||
const SecondHandleType& array2,
|
||||
const ThirdHandleType& array3)
|
||||
Storage(const AH1& array1, const AH2& array2, const AH3& array3)
|
||||
: FirstArray(array1)
|
||||
, SecondArray(array2)
|
||||
, ThirdArray(array3)
|
||||
@ -224,17 +238,16 @@ public:
|
||||
VTKM_CONT
|
||||
PortalType GetPortal()
|
||||
{
|
||||
return PortalType(this->FirstArray.GetPortalControl(),
|
||||
this->SecondArray.GetPortalControl(),
|
||||
this->ThirdArray.GetPortalControl());
|
||||
return PortalType(this->FirstArray.WritePortal(),
|
||||
this->SecondArray.WritePortal(),
|
||||
this->ThirdArray.WritePortal());
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
PortalConstType GetPortalConst() const
|
||||
{
|
||||
return PortalConstType(this->FirstArray.GetPortalConstControl(),
|
||||
this->SecondArray.GetPortalConstControl(),
|
||||
this->ThirdArray.GetPortalConstControl());
|
||||
return PortalConstType(
|
||||
this->FirstArray.ReadPortal(), this->SecondArray.ReadPortal(), this->ThirdArray.ReadPortal());
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
@ -264,33 +277,32 @@ public:
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
const FirstHandleType& GetFirstArray() const { return this->FirstArray; }
|
||||
const AH1& GetFirstArray() const { return this->FirstArray; }
|
||||
|
||||
VTKM_CONT
|
||||
const SecondHandleType& GetSecondArray() const { return this->SecondArray; }
|
||||
const AH2& GetSecondArray() const { return this->SecondArray; }
|
||||
|
||||
VTKM_CONT
|
||||
const ThirdHandleType& GetThirdArray() const { return this->ThirdArray; }
|
||||
const AH3& GetThirdArray() const { return this->ThirdArray; }
|
||||
|
||||
private:
|
||||
FirstHandleType FirstArray;
|
||||
SecondHandleType SecondArray;
|
||||
ThirdHandleType ThirdArray;
|
||||
AH1 FirstArray;
|
||||
AH2 SecondArray;
|
||||
AH3 ThirdArray;
|
||||
};
|
||||
|
||||
template <typename FirstHandleType,
|
||||
typename SecondHandleType,
|
||||
typename ThirdHandleType,
|
||||
typename Device>
|
||||
class ArrayTransfer<vtkm::Vec<typename FirstHandleType::ValueType, 3>,
|
||||
StorageTagCartesianProduct<FirstHandleType, SecondHandleType, ThirdHandleType>,
|
||||
Device>
|
||||
template <typename T, typename ST1, typename ST2, typename ST3, typename Device>
|
||||
class ArrayTransfer<vtkm::Vec<T, 3>, vtkm::cont::StorageTagCartesianProduct<ST1, ST2, ST3>, Device>
|
||||
{
|
||||
public:
|
||||
using ValueType = vtkm::Vec<typename FirstHandleType::ValueType, 3>;
|
||||
using ValueType = vtkm::Vec<T, 3>;
|
||||
|
||||
private:
|
||||
using StorageTag = StorageTagCartesianProduct<FirstHandleType, SecondHandleType, ThirdHandleType>;
|
||||
using AH1 = vtkm::cont::ArrayHandle<T, ST1>;
|
||||
using AH2 = vtkm::cont::ArrayHandle<T, ST2>;
|
||||
using AH3 = vtkm::cont::ArrayHandle<T, ST3>;
|
||||
|
||||
using StorageTag = vtkm::cont::StorageTagCartesianProduct<ST1, ST2, ST3>;
|
||||
using StorageType = vtkm::cont::internal::Storage<ValueType, StorageTag>;
|
||||
|
||||
public:
|
||||
@ -299,15 +311,15 @@ public:
|
||||
|
||||
using PortalExecution = vtkm::exec::internal::ArrayPortalCartesianProduct<
|
||||
ValueType,
|
||||
typename FirstHandleType::template ExecutionTypes<Device>::Portal,
|
||||
typename SecondHandleType::template ExecutionTypes<Device>::Portal,
|
||||
typename ThirdHandleType::template ExecutionTypes<Device>::Portal>;
|
||||
typename AH1::template ExecutionTypes<Device>::Portal,
|
||||
typename AH2::template ExecutionTypes<Device>::Portal,
|
||||
typename AH3::template ExecutionTypes<Device>::Portal>;
|
||||
|
||||
using PortalConstExecution = vtkm::exec::internal::ArrayPortalCartesianProduct<
|
||||
ValueType,
|
||||
typename FirstHandleType::template ExecutionTypes<Device>::PortalConst,
|
||||
typename SecondHandleType::template ExecutionTypes<Device>::PortalConst,
|
||||
typename ThirdHandleType::template ExecutionTypes<Device>::PortalConst>;
|
||||
typename AH1::template ExecutionTypes<Device>::PortalConst,
|
||||
typename AH2::template ExecutionTypes<Device>::PortalConst,
|
||||
typename AH3::template ExecutionTypes<Device>::PortalConst>;
|
||||
|
||||
VTKM_CONT
|
||||
ArrayTransfer(StorageType* storage)
|
||||
@ -325,15 +337,15 @@ public:
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData))
|
||||
PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData), vtkm::cont::Token& token)
|
||||
{
|
||||
return PortalConstExecution(this->FirstArray.PrepareForInput(Device()),
|
||||
this->SecondArray.PrepareForInput(Device()),
|
||||
this->ThirdArray.PrepareForInput(Device()));
|
||||
return PortalConstExecution(this->FirstArray.PrepareForInput(Device(), token),
|
||||
this->SecondArray.PrepareForInput(Device(), token),
|
||||
this->ThirdArray.PrepareForInput(Device(), token));
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
PortalExecution PrepareForInPlace(bool vtkmNotUsed(updateData))
|
||||
PortalExecution PrepareForInPlace(bool vtkmNotUsed(updateData), vtkm::cont::Token&)
|
||||
{
|
||||
throw vtkm::cont::ErrorBadAllocation(
|
||||
"Cannot write to an ArrayHandleCartesianProduct. It does not make "
|
||||
@ -341,7 +353,7 @@ public:
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
PortalExecution PrepareForOutput(vtkm::Id vtkmNotUsed(numberOfValues))
|
||||
PortalExecution PrepareForOutput(vtkm::Id vtkmNotUsed(numberOfValues), vtkm::cont::Token&)
|
||||
{
|
||||
throw vtkm::cont::ErrorBadAllocation(
|
||||
"Cannot write to an ArrayHandleCartesianProduct. It does not make "
|
||||
@ -371,9 +383,9 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
FirstHandleType FirstArray;
|
||||
SecondHandleType SecondArray;
|
||||
ThirdHandleType ThirdArray;
|
||||
AH1 FirstArray;
|
||||
AH2 SecondArray;
|
||||
AH3 ThirdArray;
|
||||
};
|
||||
} // namespace internal
|
||||
|
||||
@ -412,6 +424,13 @@ public:
|
||||
: Superclass(StorageType(firstArray, secondArray, thirdArray))
|
||||
{
|
||||
}
|
||||
|
||||
/// Implemented so that it is defined exclusively in the control environment.
|
||||
/// If there is a separate device for the execution environment (for example,
|
||||
/// with CUDA), then the automatically generated destructor could be
|
||||
/// created for all devices, and it would not be valid for all devices.
|
||||
///
|
||||
~ArrayHandleCartesianProduct() {}
|
||||
};
|
||||
|
||||
/// A convenience function for creating an ArrayHandleCartesianProduct. It takes the two
|
||||
@ -449,11 +468,12 @@ struct SerializableTypeString<vtkm::cont::ArrayHandleCartesianProduct<AH1, AH2,
|
||||
}
|
||||
};
|
||||
|
||||
template <typename AH1, typename AH2, typename AH3>
|
||||
template <typename T, typename ST1, typename ST2, typename ST3>
|
||||
struct SerializableTypeString<
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<typename AH1::ValueType, 3>,
|
||||
vtkm::cont::internal::StorageTagCartesianProduct<AH1, AH2, AH3>>>
|
||||
: SerializableTypeString<vtkm::cont::ArrayHandleCartesianProduct<AH1, AH2, AH3>>
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<T, 3>, vtkm::cont::StorageTagCartesianProduct<ST1, ST2, ST3>>>
|
||||
: SerializableTypeString<vtkm::cont::ArrayHandleCartesianProduct<vtkm::cont::ArrayHandle<T, ST1>,
|
||||
vtkm::cont::ArrayHandle<T, ST2>,
|
||||
vtkm::cont::ArrayHandle<T, ST3>>>
|
||||
{
|
||||
};
|
||||
}
|
||||
@ -492,11 +512,12 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template <typename AH1, typename AH2, typename AH3>
|
||||
template <typename T, typename ST1, typename ST2, typename ST3>
|
||||
struct Serialization<
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<typename AH1::ValueType, 3>,
|
||||
vtkm::cont::internal::StorageTagCartesianProduct<AH1, AH2, AH3>>>
|
||||
: Serialization<vtkm::cont::ArrayHandleCartesianProduct<AH1, AH2, AH3>>
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<T, 3>, vtkm::cont::StorageTagCartesianProduct<ST1, ST2, ST3>>>
|
||||
: Serialization<vtkm::cont::ArrayHandleCartesianProduct<vtkm::cont::ArrayHandle<T, ST1>,
|
||||
vtkm::cont::ArrayHandle<T, ST2>,
|
||||
vtkm::cont::ArrayHandle<T, ST3>>>
|
||||
{
|
||||
};
|
||||
} // diy
|
||||
|
@ -24,14 +24,127 @@ namespace vtkm
|
||||
namespace cont
|
||||
{
|
||||
|
||||
template <typename SourceT, typename SourceStorage>
|
||||
struct VTKM_ALWAYS_EXPORT StorageTagCast
|
||||
{
|
||||
};
|
||||
|
||||
namespace internal
|
||||
{
|
||||
|
||||
template <typename FromType, typename ToType>
|
||||
struct VTKM_ALWAYS_EXPORT Cast
|
||||
{
|
||||
// The following operator looks like it should never issue a cast warning because of
|
||||
// the static_cast (and we don't want it to issue a warning). However, if ToType is
|
||||
// an object that has a constructor that takes a value that FromType can be cast to,
|
||||
// that cast can cause a warning. For example, if FromType is vtkm::Float64 and ToType
|
||||
// is vtkm::Vec<vtkm::Float32, 3>, the static_cast will first implicitly cast the
|
||||
// Float64 to a Float32 (which causes a warning) before using the static_cast to
|
||||
// construct the Vec with the Float64. The easiest way around the problem is to
|
||||
// just disable all conversion warnings here. (The pragmas are taken from those
|
||||
// used in Types.h for the VecBase class.)
|
||||
#if (!(defined(VTKM_CUDA) && (__CUDACC_VER_MAJOR__ < 8)))
|
||||
#if (defined(VTKM_GCC) || defined(VTKM_CLANG))
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunknown-pragmas"
|
||||
#pragma GCC diagnostic ignored "-Wpragmas"
|
||||
#pragma GCC diagnostic ignored "-Wconversion"
|
||||
#pragma GCC diagnostic ignored "-Wfloat-conversion"
|
||||
#endif // gcc || clang
|
||||
#endif //not using cuda < 8
|
||||
#if defined(VTKM_MSVC)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4244)
|
||||
#endif
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
ToType operator()(const FromType& val) const { return static_cast<ToType>(val); }
|
||||
|
||||
#if (!(defined(VTKM_CUDA) && (__CUDACC_VER_MAJOR__ < 8)))
|
||||
#if (defined(VTKM_GCC) || defined(VTKM_CLANG))
|
||||
#pragma GCC diagnostic pop
|
||||
#endif // gcc || clang
|
||||
#endif // not using cuda < 8
|
||||
#if defined(VTKM_MSVC)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <typename TargetT, typename SourceT, typename SourceStorage, bool... CastFlags>
|
||||
struct ArrayHandleCastTraits;
|
||||
|
||||
template <typename TargetT, typename SourceT, typename SourceStorage>
|
||||
struct ArrayHandleCastTraits<TargetT, SourceT, SourceStorage>
|
||||
: ArrayHandleCastTraits<TargetT,
|
||||
SourceT,
|
||||
SourceStorage,
|
||||
std::is_convertible<SourceT, TargetT>::value,
|
||||
std::is_convertible<TargetT, SourceT>::value>
|
||||
{
|
||||
};
|
||||
|
||||
// Case where the forward cast is invalid, so this array is invalid.
|
||||
template <typename TargetT, typename SourceT, typename SourceStorage, bool CanCastBackward>
|
||||
struct ArrayHandleCastTraits<TargetT, SourceT, SourceStorage, false, CanCastBackward>
|
||||
{
|
||||
struct StorageSuperclass : vtkm::cont::internal::UndefinedStorage
|
||||
{
|
||||
using PortalType = vtkm::cont::internal::detail::UndefinedArrayPortal<TargetT>;
|
||||
using PortalConstType = vtkm::cont::internal::detail::UndefinedArrayPortal<TargetT>;
|
||||
};
|
||||
};
|
||||
|
||||
// Case where the forward cast is valid but the backward cast is invalid.
|
||||
template <typename TargetT, typename SourceT, typename SourceStorage>
|
||||
struct ArrayHandleCastTraits<TargetT, SourceT, SourceStorage, true, false>
|
||||
{
|
||||
using StorageTagSuperclass = StorageTagTransform<vtkm::cont::ArrayHandle<SourceT, SourceStorage>,
|
||||
vtkm::cont::internal::Cast<SourceT, TargetT>>;
|
||||
using StorageSuperclass = vtkm::cont::internal::Storage<TargetT, StorageTagSuperclass>;
|
||||
template <typename Device>
|
||||
using ArrayTransferSuperclass = ArrayTransfer<TargetT, StorageTagSuperclass, Device>;
|
||||
};
|
||||
|
||||
// Case where both forward and backward casts are valid.
|
||||
template <typename TargetT, typename SourceT, typename SourceStorage>
|
||||
struct ArrayHandleCastTraits<TargetT, SourceT, SourceStorage, true, true>
|
||||
{
|
||||
using StorageTagSuperclass = StorageTagTransform<vtkm::cont::ArrayHandle<SourceT, SourceStorage>,
|
||||
vtkm::cont::internal::Cast<SourceT, TargetT>,
|
||||
vtkm::cont::internal::Cast<TargetT, SourceT>>;
|
||||
using StorageSuperclass = vtkm::cont::internal::Storage<TargetT, StorageTagSuperclass>;
|
||||
template <typename Device>
|
||||
using ArrayTransferSuperclass = ArrayTransfer<TargetT, StorageTagSuperclass, Device>;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename TargetT, typename SourceT, typename SourceStorage>
|
||||
struct Storage<TargetT, vtkm::cont::StorageTagCast<SourceT, SourceStorage>>
|
||||
: detail::ArrayHandleCastTraits<TargetT, SourceT, SourceStorage>::StorageSuperclass
|
||||
{
|
||||
using Superclass =
|
||||
typename detail::ArrayHandleCastTraits<TargetT, SourceT, SourceStorage>::StorageSuperclass;
|
||||
|
||||
using Superclass::Superclass;
|
||||
};
|
||||
|
||||
template <typename TargetT, typename SourceT, typename SourceStorage, typename Device>
|
||||
struct ArrayTransfer<TargetT, vtkm::cont::StorageTagCast<SourceT, SourceStorage>, Device>
|
||||
: detail::ArrayHandleCastTraits<TargetT,
|
||||
SourceT,
|
||||
SourceStorage>::template ArrayTransferSuperclass<Device>
|
||||
{
|
||||
using Superclass =
|
||||
typename detail::ArrayHandleCastTraits<TargetT,
|
||||
SourceT,
|
||||
SourceStorage>::template ArrayTransferSuperclass<Device>;
|
||||
|
||||
using Superclass::Superclass;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
@ -44,24 +157,32 @@ struct VTKM_ALWAYS_EXPORT Cast
|
||||
///
|
||||
template <typename T, typename ArrayHandleType>
|
||||
class ArrayHandleCast
|
||||
: public vtkm::cont::ArrayHandleTransform<ArrayHandleType,
|
||||
internal::Cast<typename ArrayHandleType::ValueType, T>,
|
||||
internal::Cast<T, typename ArrayHandleType::ValueType>>
|
||||
: public vtkm::cont::ArrayHandle<
|
||||
T,
|
||||
StorageTagCast<typename ArrayHandleType::ValueType, typename ArrayHandleType::StorageTag>>
|
||||
{
|
||||
public:
|
||||
VTKM_ARRAY_HANDLE_SUBCLASS(
|
||||
ArrayHandleCast,
|
||||
(ArrayHandleCast<T, ArrayHandleType>),
|
||||
(vtkm::cont::ArrayHandleTransform<ArrayHandleType,
|
||||
internal::Cast<typename ArrayHandleType::ValueType, T>,
|
||||
internal::Cast<T, typename ArrayHandleType::ValueType>>));
|
||||
(vtkm::cont::ArrayHandle<
|
||||
T,
|
||||
StorageTagCast<typename ArrayHandleType::ValueType, typename ArrayHandleType::StorageTag>>));
|
||||
|
||||
ArrayHandleCast(const ArrayHandleType& handle)
|
||||
: Superclass(handle)
|
||||
ArrayHandleCast(const vtkm::cont::ArrayHandle<typename ArrayHandleType::ValueType,
|
||||
typename ArrayHandleType::StorageTag>& handle)
|
||||
: Superclass(typename Superclass::StorageType(handle))
|
||||
{
|
||||
this->ValidateTypeCast<typename ArrayHandleType::ValueType>();
|
||||
}
|
||||
|
||||
/// Implemented so that it is defined exclusively in the control environment.
|
||||
/// If there is a separate device for the execution environment (for example,
|
||||
/// with CUDA), then the automatically generated destructor could be
|
||||
/// created for all devices, and it would not be valid for all devices.
|
||||
///
|
||||
~ArrayHandleCast() {}
|
||||
|
||||
private:
|
||||
// Log warnings if type cast is valid but lossy:
|
||||
template <typename SrcValueType>
|
||||
@ -161,23 +282,21 @@ namespace vtkm
|
||||
namespace cont
|
||||
{
|
||||
|
||||
template <typename T1, typename T2>
|
||||
struct SerializableTypeString<vtkm::cont::internal::Cast<T1, T2>>
|
||||
template <typename T, typename AH>
|
||||
struct SerializableTypeString<vtkm::cont::ArrayHandleCast<T, AH>>
|
||||
{
|
||||
static VTKM_CONT const std::string& Get()
|
||||
{
|
||||
static std::string name = "AH_Cast_Functor<" + SerializableTypeString<T1>::Get() + "," +
|
||||
SerializableTypeString<T2>::Get() + ">";
|
||||
static std::string name = "AH_Cast<" + SerializableTypeString<T>::Get() + "," +
|
||||
SerializableTypeString<typename AH::ValueType>::Get() + "," +
|
||||
SerializableTypeString<typename AH::StorageTag>::Get() + ">";
|
||||
return name;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename AH>
|
||||
struct SerializableTypeString<vtkm::cont::ArrayHandleCast<T, AH>>
|
||||
: SerializableTypeString<
|
||||
vtkm::cont::ArrayHandleTransform<AH,
|
||||
vtkm::cont::internal::Cast<typename AH::ValueType, T>,
|
||||
vtkm::cont::internal::Cast<T, typename AH::ValueType>>>
|
||||
template <typename T1, typename T2, typename S>
|
||||
struct SerializableTypeString<vtkm::cont::ArrayHandle<T1, vtkm::cont::StorageTagCast<T2, S>>>
|
||||
: SerializableTypeString<vtkm::cont::ArrayHandleCast<T1, vtkm::cont::ArrayHandle<T2, S>>>
|
||||
{
|
||||
};
|
||||
}
|
||||
@ -186,20 +305,33 @@ struct SerializableTypeString<vtkm::cont::ArrayHandleCast<T, AH>>
|
||||
namespace mangled_diy_namespace
|
||||
{
|
||||
|
||||
template <typename T1, typename T2>
|
||||
struct Serialization<vtkm::cont::internal::Cast<T1, T2>>
|
||||
template <typename TargetT, typename SourceT, typename SourceStorage>
|
||||
struct Serialization<
|
||||
vtkm::cont::ArrayHandle<TargetT, vtkm::cont::StorageTagCast<SourceT, SourceStorage>>>
|
||||
{
|
||||
static VTKM_CONT void save(BinaryBuffer&, const vtkm::cont::internal::Cast<T1, T2>&) {}
|
||||
private:
|
||||
using BaseType =
|
||||
vtkm::cont::ArrayHandle<TargetT, vtkm::cont::StorageTagCast<SourceT, SourceStorage>>;
|
||||
|
||||
static VTKM_CONT void load(BinaryBuffer&, vtkm::cont::internal::Cast<T1, T2>&) {}
|
||||
public:
|
||||
static VTKM_CONT void save(BinaryBuffer& bb, const BaseType& obj)
|
||||
{
|
||||
vtkmdiy::save(bb, obj.GetStorage().GetArray());
|
||||
}
|
||||
|
||||
static VTKM_CONT void load(BinaryBuffer& bb, BaseType& obj)
|
||||
{
|
||||
vtkm::cont::ArrayHandle<SourceT, SourceStorage> array;
|
||||
vtkmdiy::load(bb, array);
|
||||
obj = BaseType(array);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename AH>
|
||||
struct Serialization<vtkm::cont::ArrayHandleCast<T, AH>>
|
||||
: Serialization<
|
||||
vtkm::cont::ArrayHandleTransform<AH,
|
||||
vtkm::cont::internal::Cast<typename AH::ValueType, T>,
|
||||
vtkm::cont::internal::Cast<T, typename AH::ValueType>>>
|
||||
template <typename TargetT, typename AH>
|
||||
struct Serialization<vtkm::cont::ArrayHandleCast<TargetT, AH>>
|
||||
: Serialization<vtkm::cont::ArrayHandle<
|
||||
TargetT,
|
||||
vtkm::cont::StorageTagCast<typename AH::ValueType, typename AH::StorageTag>>>
|
||||
{
|
||||
};
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include <vtkm/cont/ArrayHandle.h>
|
||||
|
||||
#include <vtkm/Deprecated.h>
|
||||
#include <vtkm/StaticAssert.h>
|
||||
#include <vtkm/VecTraits.h>
|
||||
|
||||
@ -59,20 +60,6 @@ struct AllAreArrayHandles
|
||||
constexpr static bool Value = AllAreArrayHandlesImpl<ArrayHandleTs...>::Value;
|
||||
};
|
||||
|
||||
// ParamsAreArrayHandles: ------------------------------------------------------
|
||||
// Same as AllAreArrayHandles, but accepts a tuple.
|
||||
template <typename T>
|
||||
struct ParamsAreArrayHandles
|
||||
{
|
||||
constexpr static bool Value = false;
|
||||
};
|
||||
|
||||
template <typename... ArrayHandleTs>
|
||||
struct ParamsAreArrayHandles<vtkmstd::tuple<ArrayHandleTs...>>
|
||||
{
|
||||
constexpr static bool Value = AllAreArrayHandlesImpl<ArrayHandleTs...>::Value;
|
||||
};
|
||||
|
||||
// GetValueType: ---------------------------------------------------------------
|
||||
// Determines the output ValueType of the objects in TupleType, a vtkmstd::tuple
|
||||
// which can contain ArrayHandles, ArrayPortals...anything with a ValueType
|
||||
@ -133,39 +120,45 @@ struct ArrayTupleForEach
|
||||
template <typename PortalTuple>
|
||||
VTKM_CONT static void GetPortalTupleControl(ArrayTuple& arrays, PortalTuple& portals)
|
||||
{
|
||||
vtkmstd::get<Index>(portals) = vtkmstd::get<Index>(arrays).GetPortalControl();
|
||||
vtkmstd::get<Index>(portals) = vtkmstd::get<Index>(arrays).WritePortal();
|
||||
Next::GetPortalTupleControl(arrays, portals);
|
||||
}
|
||||
|
||||
template <typename PortalTuple>
|
||||
VTKM_CONT static void GetPortalConstTupleControl(const ArrayTuple& arrays, PortalTuple& portals)
|
||||
{
|
||||
vtkmstd::get<Index>(portals) = vtkmstd::get<Index>(arrays).GetPortalConstControl();
|
||||
vtkmstd::get<Index>(portals) = vtkmstd::get<Index>(arrays).ReadPortal();
|
||||
Next::GetPortalConstTupleControl(arrays, portals);
|
||||
}
|
||||
|
||||
template <typename DeviceTag, typename PortalTuple>
|
||||
VTKM_CONT static void PrepareForInput(const ArrayTuple& arrays, PortalTuple& portals)
|
||||
VTKM_CONT static void PrepareForInput(const ArrayTuple& arrays,
|
||||
PortalTuple& portals,
|
||||
vtkm::cont::Token& token)
|
||||
{
|
||||
vtkmstd::get<Index>(portals) = vtkmstd::get<Index>(arrays).PrepareForInput(DeviceTag());
|
||||
Next::template PrepareForInput<DeviceTag>(arrays, portals);
|
||||
vtkmstd::get<Index>(portals) = vtkmstd::get<Index>(arrays).PrepareForInput(DeviceTag(), token);
|
||||
Next::template PrepareForInput<DeviceTag>(arrays, portals, token);
|
||||
}
|
||||
|
||||
template <typename DeviceTag, typename PortalTuple>
|
||||
VTKM_CONT static void PrepareForInPlace(ArrayTuple& arrays, PortalTuple& portals)
|
||||
VTKM_CONT static void PrepareForInPlace(ArrayTuple& arrays,
|
||||
PortalTuple& portals,
|
||||
vtkm::cont::Token& token)
|
||||
{
|
||||
vtkmstd::get<Index>(portals) = vtkmstd::get<Index>(arrays).PrepareForInPlace(DeviceTag());
|
||||
Next::template PrepareForInPlace<DeviceTag>(arrays, portals);
|
||||
vtkmstd::get<Index>(portals) =
|
||||
vtkmstd::get<Index>(arrays).PrepareForInPlace(DeviceTag(), token);
|
||||
Next::template PrepareForInPlace<DeviceTag>(arrays, portals, token);
|
||||
}
|
||||
|
||||
template <typename DeviceTag, typename PortalTuple>
|
||||
VTKM_CONT static void PrepareForOutput(ArrayTuple& arrays,
|
||||
PortalTuple& portals,
|
||||
vtkm::Id numValues)
|
||||
vtkm::Id numValues,
|
||||
vtkm::cont::Token& token)
|
||||
{
|
||||
vtkmstd::get<Index>(portals) =
|
||||
vtkmstd::get<Index>(arrays).PrepareForOutput(numValues, DeviceTag());
|
||||
Next::template PrepareForOutput<DeviceTag>(arrays, portals, numValues);
|
||||
vtkmstd::get<Index>(arrays).PrepareForOutput(numValues, DeviceTag(), token);
|
||||
Next::template PrepareForOutput<DeviceTag>(arrays, portals, numValues, token);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
@ -204,17 +197,17 @@ struct ArrayTupleForEach<Index, Index, ArrayTuple>
|
||||
}
|
||||
|
||||
template <typename DeviceTag, typename PortalTuple>
|
||||
VTKM_CONT static void PrepareForInput(const ArrayTuple&, PortalTuple&)
|
||||
VTKM_CONT static void PrepareForInput(const ArrayTuple&, PortalTuple&, vtkm::cont::Token&)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename DeviceTag, typename PortalTuple>
|
||||
VTKM_CONT static void PrepareForInPlace(ArrayTuple&, PortalTuple&)
|
||||
VTKM_CONT static void PrepareForInPlace(ArrayTuple&, PortalTuple&, vtkm::cont::Token&)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename DeviceTag, typename PortalTuple>
|
||||
VTKM_CONT static void PrepareForOutput(ArrayTuple&, PortalTuple&, vtkm::Id)
|
||||
VTKM_CONT static void PrepareForOutput(ArrayTuple&, PortalTuple&, vtkm::Id, vtkm::cont::Token&)
|
||||
{
|
||||
}
|
||||
|
||||
@ -235,10 +228,10 @@ template <typename Head, typename... Tail>
|
||||
struct PortalTupleTypeGeneratorImpl<vtkmstd::tuple<Head, Tail...>>
|
||||
{
|
||||
using Next = PortalTupleTypeGeneratorImpl<vtkmstd::tuple<Tail...>>;
|
||||
using PortalControlTuple = typename TupleTypePrepend<typename Head::PortalControl,
|
||||
using PortalControlTuple = typename TupleTypePrepend<typename Head::WritePortalType,
|
||||
typename Next::PortalControlTuple>::Type;
|
||||
using PortalConstControlTuple =
|
||||
typename TupleTypePrepend<typename Head::PortalConstControl,
|
||||
typename TupleTypePrepend<typename Head::ReadPortalType,
|
||||
typename Next::PortalConstControlTuple>::Type;
|
||||
|
||||
template <typename DeviceTag>
|
||||
@ -256,8 +249,8 @@ struct PortalTupleTypeGeneratorImpl<vtkmstd::tuple<Head, Tail...>>
|
||||
template <typename Head>
|
||||
struct PortalTupleTypeGeneratorImpl<vtkmstd::tuple<Head>>
|
||||
{
|
||||
using PortalControlTuple = vtkmstd::tuple<typename Head::PortalControl>;
|
||||
using PortalConstControlTuple = vtkmstd::tuple<typename Head::PortalConstControl>;
|
||||
using PortalControlTuple = vtkmstd::tuple<typename Head::WritePortalType>;
|
||||
using PortalConstControlTuple = vtkmstd::tuple<typename Head::ReadPortalType>;
|
||||
|
||||
template <typename DeviceTag>
|
||||
struct ExecutionTypes
|
||||
@ -315,29 +308,30 @@ public:
|
||||
|
||||
template <typename DeviceTag>
|
||||
VTKM_CONT static const typename ExecutionTypes<DeviceTag>::PortalConstTuple PrepareForInput(
|
||||
const ArrayTuple& arrays)
|
||||
const ArrayTuple& arrays,
|
||||
vtkm::cont::Token& token)
|
||||
{
|
||||
typename ExecutionTypes<DeviceTag>::PortalConstTuple portals;
|
||||
ForEachArray::template PrepareForInput<DeviceTag>(arrays, portals);
|
||||
ForEachArray::template PrepareForInput<DeviceTag>(arrays, portals, token);
|
||||
return portals;
|
||||
}
|
||||
|
||||
template <typename DeviceTag>
|
||||
VTKM_CONT static const typename ExecutionTypes<DeviceTag>::PortalTuple PrepareForInPlace(
|
||||
ArrayTuple& arrays)
|
||||
ArrayTuple& arrays,
|
||||
vtkm::cont::Token& token)
|
||||
{
|
||||
typename ExecutionTypes<DeviceTag>::PortalTuple portals;
|
||||
ForEachArray::template PrepareForInPlace<DeviceTag>(arrays, portals);
|
||||
ForEachArray::template PrepareForInPlace<DeviceTag>(arrays, portals, token);
|
||||
return portals;
|
||||
}
|
||||
|
||||
template <typename DeviceTag>
|
||||
VTKM_CONT static const typename ExecutionTypes<DeviceTag>::PortalTuple PrepareForOutput(
|
||||
ArrayTuple& arrays,
|
||||
vtkm::Id numValues)
|
||||
VTKM_CONT static const typename ExecutionTypes<DeviceTag>::PortalTuple
|
||||
PrepareForOutput(ArrayTuple& arrays, vtkm::Id numValues, vtkm::cont::Token& token)
|
||||
{
|
||||
typename ExecutionTypes<DeviceTag>::PortalTuple portals;
|
||||
ForEachArray::template PrepareForOutput<DeviceTag>(arrays, portals, numValues);
|
||||
ForEachArray::template PrepareForOutput<DeviceTag>(arrays, portals, numValues, token);
|
||||
return portals;
|
||||
}
|
||||
};
|
||||
@ -479,15 +473,54 @@ private:
|
||||
PortalTuple Portals;
|
||||
};
|
||||
|
||||
template <typename ArrayTuple>
|
||||
struct VTKM_ALWAYS_EXPORT StorageTagCompositeVector
|
||||
} // namespace internal
|
||||
|
||||
template <typename... StorageTags>
|
||||
struct VTKM_ALWAYS_EXPORT StorageTagCompositeVec
|
||||
{
|
||||
};
|
||||
|
||||
template <typename ArrayTuple>
|
||||
class Storage<typename compvec::GetValueType<ArrayTuple>::ValueType,
|
||||
StorageTagCompositeVector<ArrayTuple>>
|
||||
namespace internal
|
||||
{
|
||||
|
||||
template <typename ArrayTuple>
|
||||
struct VTKM_ALWAYS_EXPORT VTKM_DEPRECATED(1.6, "Use StorageTagCompositeVec instead.")
|
||||
StorageTagCompositeVector
|
||||
{
|
||||
};
|
||||
|
||||
template <typename... ArrayTs>
|
||||
struct CompositeVectorTraits
|
||||
{
|
||||
// Need to check this here, since this traits struct is used in the
|
||||
// ArrayHandleCompositeVector superclass definition before any other
|
||||
// static_asserts could be used.
|
||||
VTKM_STATIC_ASSERT_MSG(compvec::AllAreArrayHandles<ArrayTs...>::Value,
|
||||
"Template parameters for ArrayHandleCompositeVector "
|
||||
"must be a list of ArrayHandle types.");
|
||||
|
||||
using ValueType = typename compvec::GetValueType<vtkmstd::tuple<ArrayTs...>>::ValueType;
|
||||
using StorageTag = vtkm::cont::StorageTagCompositeVec<typename ArrayTs::StorageTag...>;
|
||||
using StorageType = Storage<ValueType, StorageTag>;
|
||||
using Superclass = ArrayHandle<ValueType, StorageTag>;
|
||||
};
|
||||
|
||||
VTKM_DEPRECATED_SUPPRESS_BEGIN
|
||||
template <typename... Arrays>
|
||||
class Storage<typename compvec::GetValueType<vtkmstd::tuple<Arrays...>>::ValueType,
|
||||
StorageTagCompositeVector<vtkmstd::tuple<Arrays...>>>
|
||||
: CompositeVectorTraits<Arrays...>::StorageType
|
||||
{
|
||||
using Superclass = typename CompositeVectorTraits<Arrays...>::StorageType;
|
||||
using Superclass::Superclass;
|
||||
};
|
||||
VTKM_DEPRECATED_SUPPRESS_END
|
||||
|
||||
template <typename T, typename... StorageTags>
|
||||
class Storage<vtkm::Vec<T, static_cast<vtkm::IdComponent>(sizeof...(StorageTags))>,
|
||||
vtkm::cont::StorageTagCompositeVec<StorageTags...>>
|
||||
{
|
||||
using ArrayTuple = vtkmstd::tuple<vtkm::cont::ArrayHandle<T, StorageTags>...>;
|
||||
using ForEachArray =
|
||||
compvec::ArrayTupleForEach<0, vtkmstd::tuple_size<ArrayTuple>::value, ArrayTuple>;
|
||||
using PortalTypes = compvec::PortalTupleTraits<ArrayTuple>;
|
||||
@ -517,6 +550,18 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
template <typename... ArrayTypes>
|
||||
VTKM_CONT Storage(const ArrayTypes&... arrays)
|
||||
: Arrays(arrays...)
|
||||
, Valid(true)
|
||||
{
|
||||
using SizeValidator = compvec::ArraySizeValidator<ArrayTuple>;
|
||||
if (!SizeValidator::Exec(this->Arrays, this->GetNumberOfValues()))
|
||||
{
|
||||
throw ErrorBadValue("All arrays must have the same number of values.");
|
||||
}
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
PortalType GetPortal()
|
||||
{
|
||||
@ -578,20 +623,39 @@ private:
|
||||
bool Valid;
|
||||
};
|
||||
|
||||
template <typename ArrayTuple, typename DeviceTag>
|
||||
class ArrayTransfer<typename compvec::GetValueType<ArrayTuple>::ValueType,
|
||||
StorageTagCompositeVector<ArrayTuple>,
|
||||
VTKM_DEPRECATED_SUPPRESS_BEGIN
|
||||
template <typename... Arrays, typename DeviceTag>
|
||||
struct ArrayTransfer<typename compvec::GetValueType<vtkmstd::tuple<Arrays...>>::ValueType,
|
||||
StorageTagCompositeVector<vtkmstd::tuple<Arrays...>>,
|
||||
DeviceTag>
|
||||
: ArrayTransfer<typename compvec::GetValueType<vtkmstd::tuple<Arrays...>>::ValueType,
|
||||
typename CompositeVectorTraits<Arrays...>::StorageType,
|
||||
DeviceTag>
|
||||
{
|
||||
using Superclass =
|
||||
ArrayTransfer<typename compvec::GetValueType<vtkmstd::tuple<Arrays...>>::ValueType,
|
||||
typename CompositeVectorTraits<Arrays...>::StorageType,
|
||||
DeviceTag>;
|
||||
using Superclass::Superclass;
|
||||
};
|
||||
VTKM_DEPRECATED_SUPPRESS_END
|
||||
|
||||
template <typename T, typename... StorageTags, typename DeviceTag>
|
||||
class ArrayTransfer<vtkm::Vec<T, static_cast<vtkm::IdComponent>(sizeof...(StorageTags))>,
|
||||
vtkm::cont::StorageTagCompositeVec<StorageTags...>,
|
||||
DeviceTag>
|
||||
{
|
||||
VTKM_IS_DEVICE_ADAPTER_TAG(DeviceTag);
|
||||
|
||||
using ArrayTuple = vtkmstd::tuple<vtkm::cont::ArrayHandle<T, StorageTags>...>;
|
||||
|
||||
public:
|
||||
using ValueType = typename compvec::GetValueType<ArrayTuple>::ValueType;
|
||||
|
||||
private:
|
||||
using ForEachArray =
|
||||
compvec::ArrayTupleForEach<0, vtkmstd::tuple_size<ArrayTuple>::value, ArrayTuple>;
|
||||
using StorageTag = StorageTagCompositeVector<ArrayTuple>;
|
||||
using StorageTag = vtkm::cont::StorageTagCompositeVec<StorageTags...>;
|
||||
using StorageType = internal::Storage<ValueType, StorageTag>;
|
||||
using ControlTraits = compvec::PortalTupleTraits<ArrayTuple>;
|
||||
using ExecutionTraits = typename ControlTraits::template ExecutionTypes<DeviceTag>;
|
||||
@ -614,24 +678,24 @@ public:
|
||||
vtkm::Id GetNumberOfValues() const { return this->Storage->GetNumberOfValues(); }
|
||||
|
||||
VTKM_CONT
|
||||
PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData)) const
|
||||
PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData), vtkm::cont::Token& token) const
|
||||
{
|
||||
return PortalConstExecution(
|
||||
ControlTraits::template PrepareForInput<DeviceTag>(this->GetArrayTuple()));
|
||||
ControlTraits::template PrepareForInput<DeviceTag>(this->GetArrayTuple(), token));
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
PortalExecution PrepareForInPlace(bool vtkmNotUsed(updateData))
|
||||
PortalExecution PrepareForInPlace(bool vtkmNotUsed(updateData), vtkm::cont::Token& token)
|
||||
{
|
||||
return PortalExecution(
|
||||
ControlTraits::template PrepareForInPlace<DeviceTag>(this->GetArrayTuple()));
|
||||
ControlTraits::template PrepareForInPlace<DeviceTag>(this->GetArrayTuple(), token));
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
PortalExecution PrepareForOutput(vtkm::Id numValues)
|
||||
PortalExecution PrepareForOutput(vtkm::Id numValues, vtkm::cont::Token& token)
|
||||
{
|
||||
return PortalExecution(
|
||||
ControlTraits::template PrepareForOutput<DeviceTag>(this->GetArrayTuple(), numValues));
|
||||
ControlTraits::template PrepareForOutput<DeviceTag>(this->GetArrayTuple(), numValues, token));
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
@ -656,22 +720,6 @@ private:
|
||||
StorageType* Storage;
|
||||
};
|
||||
|
||||
template <typename... ArrayTs>
|
||||
struct CompositeVectorTraits
|
||||
{
|
||||
// Need to check this here, since this traits struct is used in the
|
||||
// ArrayHandleCompositeVector superclass definition before any other
|
||||
// static_asserts could be used.
|
||||
VTKM_STATIC_ASSERT_MSG(compvec::AllAreArrayHandles<ArrayTs...>::Value,
|
||||
"Template parameters for ArrayHandleCompositeVector "
|
||||
"must be a list of ArrayHandle types.");
|
||||
|
||||
using ValueType = typename compvec::GetValueType<vtkmstd::tuple<ArrayTs...>>::ValueType;
|
||||
using StorageTag = StorageTagCompositeVector<vtkmstd::tuple<ArrayTs...>>;
|
||||
using StorageType = Storage<ValueType, StorageTag>;
|
||||
using Superclass = ArrayHandle<ValueType, StorageTag>;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
/// \brief An \c ArrayHandle that combines components from other arrays.
|
||||
@ -704,7 +752,7 @@ public:
|
||||
|
||||
VTKM_CONT
|
||||
ArrayHandleCompositeVector(const ArrayTs&... arrays)
|
||||
: Superclass(StorageType(vtkmstd::make_tuple(arrays...)))
|
||||
: Superclass(StorageType(arrays...))
|
||||
{
|
||||
}
|
||||
};
|
||||
@ -742,6 +790,16 @@ struct SerializableTypeString<vtkm::cont::ArrayHandleCompositeVector<AHs...>>
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename... STs>
|
||||
struct SerializableTypeString<
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<T, static_cast<vtkm::IdComponent>(sizeof...(STs))>,
|
||||
vtkm::cont::StorageTagCompositeVec<STs...>>>
|
||||
: SerializableTypeString<
|
||||
vtkm::cont::ArrayHandleCompositeVector<vtkm::cont::ArrayHandle<T, STs>...>>
|
||||
{
|
||||
};
|
||||
|
||||
VTKM_DEPRECATED_SUPPRESS_BEGIN
|
||||
template <typename... AHs>
|
||||
struct SerializableTypeString<vtkm::cont::ArrayHandle<
|
||||
typename vtkm::cont::internal::compvec::GetValueType<vtkmstd::tuple<AHs...>>::ValueType,
|
||||
@ -749,6 +807,7 @@ struct SerializableTypeString<vtkm::cont::ArrayHandle<
|
||||
: SerializableTypeString<vtkm::cont::ArrayHandleCompositeVector<AHs...>>
|
||||
{
|
||||
};
|
||||
VTKM_DEPRECATED_SUPPRESS_END
|
||||
}
|
||||
} // vtkm::cont
|
||||
|
||||
@ -831,6 +890,15 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename... STs>
|
||||
struct Serialization<
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<T, static_cast<vtkm::IdComponent>(sizeof...(STs))>,
|
||||
vtkm::cont::StorageTagCompositeVec<STs...>>>
|
||||
: Serialization<vtkm::cont::ArrayHandleCompositeVector<vtkm::cont::ArrayHandle<T, STs>...>>
|
||||
{
|
||||
};
|
||||
|
||||
VTKM_DEPRECATED_SUPPRESS_BEGIN
|
||||
template <typename... AHs>
|
||||
struct Serialization<vtkm::cont::ArrayHandle<
|
||||
typename vtkm::cont::internal::compvec::GetValueType<vtkmstd::tuple<AHs...>>::ValueType,
|
||||
@ -838,6 +906,7 @@ struct Serialization<vtkm::cont::ArrayHandle<
|
||||
: Serialization<vtkm::cont::ArrayHandleCompositeVector<AHs...>>
|
||||
{
|
||||
};
|
||||
VTKM_DEPRECATED_SUPPRESS_END
|
||||
} // diy
|
||||
/// @endcond SERIALIZATION
|
||||
|
||||
|
@ -10,6 +10,9 @@
|
||||
#ifndef vtk_m_cont_ArrayHandleConcatenate_h
|
||||
#define vtk_m_cont_ArrayHandleConcatenate_h
|
||||
|
||||
#include <vtkm/Deprecated.h>
|
||||
#include <vtkm/StaticAssert.h>
|
||||
|
||||
#include <vtkm/cont/ArrayHandle.h>
|
||||
|
||||
namespace vtkm
|
||||
@ -37,6 +40,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
VTKM_EXEC_CONT
|
||||
ArrayPortalConcatenate(const PortalType1& p1, const PortalType2& p2)
|
||||
: portal1(p1)
|
||||
@ -45,6 +49,7 @@ public:
|
||||
}
|
||||
|
||||
// Copy constructor
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
template <typename OtherP1, typename OtherP2>
|
||||
VTKM_EXEC_CONT ArrayPortalConcatenate(const ArrayPortalConcatenate<OtherP1, OtherP2>& src)
|
||||
: portal1(src.GetPortal1())
|
||||
@ -98,24 +103,64 @@ private:
|
||||
|
||||
} // namespace internal
|
||||
|
||||
template <typename ArrayHandleType1, typename ArrayHandleType2>
|
||||
class StorageTagConcatenate
|
||||
template <typename StorageTag1, typename StorageTag2>
|
||||
class VTKM_ALWAYS_EXPORT StorageTagConcatenate
|
||||
{
|
||||
};
|
||||
|
||||
namespace internal
|
||||
{
|
||||
|
||||
template <typename ArrayHandleType1, typename ArrayHandleType2>
|
||||
class Storage<typename ArrayHandleType1::ValueType,
|
||||
StorageTagConcatenate<ArrayHandleType1, ArrayHandleType2>>
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <typename T, typename ArrayOrStorage, bool IsArrayType>
|
||||
struct ConcatinateTypeArgImpl;
|
||||
|
||||
template <typename T, typename Storage>
|
||||
struct ConcatinateTypeArgImpl<T, Storage, false>
|
||||
{
|
||||
using StorageTag = Storage;
|
||||
using ArrayHandle = vtkm::cont::ArrayHandle<T, StorageTag>;
|
||||
};
|
||||
|
||||
template <typename T, typename Array>
|
||||
struct ConcatinateTypeArgImpl<T, Array, true>
|
||||
{
|
||||
VTKM_STATIC_ASSERT_MSG((std::is_same<T, typename Array::ValueType>::value),
|
||||
"Used array with wrong type in ArrayHandleConcatinate.");
|
||||
using StorageTag VTKM_DEPRECATED(
|
||||
1.6,
|
||||
"Use storage tags instead of array handles in StorageTagConcatenate.") =
|
||||
typename Array::StorageTag;
|
||||
using ArrayHandle VTKM_DEPRECATED(
|
||||
1.6,
|
||||
"Use storage tags instead of array handles in StorageTagConcatenate.") =
|
||||
vtkm::cont::ArrayHandle<T, typename Array::StorageTag>;
|
||||
};
|
||||
|
||||
template <typename T, typename ArrayOrStorage>
|
||||
struct ConcatinateTypeArg
|
||||
: ConcatinateTypeArgImpl<T,
|
||||
ArrayOrStorage,
|
||||
vtkm::cont::internal::ArrayHandleCheck<ArrayOrStorage>::type::value>
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename T, typename ST1, typename ST2>
|
||||
class Storage<T, StorageTagConcatenate<ST1, ST2>>
|
||||
{
|
||||
using ArrayHandleType1 = typename detail::ConcatinateTypeArg<T, ST1>::ArrayHandle;
|
||||
using ArrayHandleType2 = typename detail::ConcatinateTypeArg<T, ST2>::ArrayHandle;
|
||||
|
||||
public:
|
||||
using ValueType = typename ArrayHandleType1::ValueType;
|
||||
using PortalType = ArrayPortalConcatenate<typename ArrayHandleType1::PortalControl,
|
||||
typename ArrayHandleType2::PortalControl>;
|
||||
using PortalConstType = ArrayPortalConcatenate<typename ArrayHandleType1::PortalConstControl,
|
||||
typename ArrayHandleType2::PortalConstControl>;
|
||||
using ValueType = T;
|
||||
using PortalType = ArrayPortalConcatenate<typename ArrayHandleType1::WritePortalType,
|
||||
typename ArrayHandleType2::WritePortalType>;
|
||||
using PortalConstType = ArrayPortalConcatenate<typename ArrayHandleType1::ReadPortalType,
|
||||
typename ArrayHandleType2::ReadPortalType>;
|
||||
|
||||
VTKM_CONT
|
||||
Storage()
|
||||
@ -127,21 +172,22 @@ public:
|
||||
Storage(const ArrayHandleType1& a1, const ArrayHandleType2& a2)
|
||||
: array1(a1)
|
||||
, array2(a2)
|
||||
, valid(true){};
|
||||
, valid(true)
|
||||
{
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
PortalConstType GetPortalConst() const
|
||||
{
|
||||
VTKM_ASSERT(this->valid);
|
||||
return PortalConstType(this->array1.GetPortalConstControl(),
|
||||
this->array2.GetPortalConstControl());
|
||||
return PortalConstType(this->array1.ReadPortal(), this->array2.ReadPortal());
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
PortalType GetPortal()
|
||||
{
|
||||
VTKM_ASSERT(this->valid);
|
||||
return PortalType(this->array1.GetPortalControl(), this->array2.GetPortalControl());
|
||||
return PortalType(this->array1.WritePortal(), this->array2.WritePortal());
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
@ -198,16 +244,19 @@ private:
|
||||
bool valid;
|
||||
}; // class Storage
|
||||
|
||||
template <typename ArrayHandleType1, typename ArrayHandleType2, typename Device>
|
||||
class ArrayTransfer<typename ArrayHandleType1::ValueType,
|
||||
StorageTagConcatenate<ArrayHandleType1, ArrayHandleType2>,
|
||||
Device>
|
||||
template <typename T, typename ST1, typename ST2, typename Device>
|
||||
class ArrayTransfer<T, StorageTagConcatenate<ST1, ST2>, Device>
|
||||
{
|
||||
using ArrayHandleType1 = typename detail::ConcatinateTypeArg<T, ST1>::ArrayHandle;
|
||||
using ArrayHandleType2 = typename detail::ConcatinateTypeArg<T, ST2>::ArrayHandle;
|
||||
using StorageTag1 = typename detail::ConcatinateTypeArg<T, ST1>::StorageTag;
|
||||
using StorageTag2 = typename detail::ConcatinateTypeArg<T, ST2>::StorageTag;
|
||||
|
||||
public:
|
||||
using ValueType = typename ArrayHandleType1::ValueType;
|
||||
using ValueType = T;
|
||||
|
||||
private:
|
||||
using StorageTag = StorageTagConcatenate<ArrayHandleType1, ArrayHandleType2>;
|
||||
using StorageTag = StorageTagConcatenate<StorageTag1, StorageTag2>;
|
||||
using StorageType = vtkm::cont::internal::Storage<ValueType, StorageTag>;
|
||||
|
||||
public:
|
||||
@ -235,21 +284,21 @@ public:
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData))
|
||||
PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData), vtkm::cont::Token& token)
|
||||
{
|
||||
return PortalConstExecution(this->array1.PrepareForInput(Device()),
|
||||
this->array2.PrepareForInput(Device()));
|
||||
return PortalConstExecution(this->array1.PrepareForInput(Device(), token),
|
||||
this->array2.PrepareForInput(Device(), token));
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
PortalExecution PrepareForInPlace(bool vtkmNotUsed(updateData))
|
||||
PortalExecution PrepareForInPlace(bool vtkmNotUsed(updateData), vtkm::cont::Token& token)
|
||||
{
|
||||
return PortalExecution(this->array1.PrepareForInPlace(Device()),
|
||||
this->array2.PrepareForInPlace(Device()));
|
||||
return PortalExecution(this->array1.PrepareForInPlace(Device(), token),
|
||||
this->array2.PrepareForInPlace(Device(), token));
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
PortalExecution PrepareForOutput(vtkm::Id vtkmNotUsed(numberOfValues))
|
||||
PortalExecution PrepareForOutput(vtkm::Id vtkmNotUsed(numberOfValues), vtkm::cont::Token&)
|
||||
{
|
||||
throw vtkm::cont::ErrorInternal("ArrayHandleConcatenate is derived and read-only. ");
|
||||
}
|
||||
@ -295,14 +344,16 @@ namespace cont
|
||||
template <typename ArrayHandleType1, typename ArrayHandleType2>
|
||||
class ArrayHandleConcatenate
|
||||
: public vtkm::cont::ArrayHandle<typename ArrayHandleType1::ValueType,
|
||||
StorageTagConcatenate<ArrayHandleType1, ArrayHandleType2>>
|
||||
StorageTagConcatenate<typename ArrayHandleType1::StorageTag,
|
||||
typename ArrayHandleType2::StorageTag>>
|
||||
{
|
||||
public:
|
||||
VTKM_ARRAY_HANDLE_SUBCLASS(
|
||||
ArrayHandleConcatenate,
|
||||
(ArrayHandleConcatenate<ArrayHandleType1, ArrayHandleType2>),
|
||||
(vtkm::cont::ArrayHandle<typename ArrayHandleType1::ValueType,
|
||||
StorageTagConcatenate<ArrayHandleType1, ArrayHandleType2>>));
|
||||
StorageTagConcatenate<typename ArrayHandleType1::StorageTag,
|
||||
typename ArrayHandleType2::StorageTag>>));
|
||||
|
||||
protected:
|
||||
using StorageType = vtkm::cont::internal::Storage<ValueType, StorageTag>;
|
||||
@ -344,10 +395,12 @@ struct SerializableTypeString<vtkm::cont::ArrayHandleConcatenate<AH1, AH2>>
|
||||
}
|
||||
};
|
||||
|
||||
template <typename AH1, typename AH2>
|
||||
template <typename T, typename ST1, typename ST2>
|
||||
struct SerializableTypeString<
|
||||
vtkm::cont::ArrayHandle<typename AH1::ValueType, vtkm::cont::StorageTagConcatenate<AH1, AH2>>>
|
||||
: SerializableTypeString<vtkm::cont::ArrayHandleConcatenate<AH1, AH2>>
|
||||
vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagConcatenate<ST1, ST2>>>
|
||||
: SerializableTypeString<vtkm::cont::ArrayHandleConcatenate<
|
||||
typename internal::detail::ConcatinateTypeArg<T, ST1>::ArrayHandle,
|
||||
typename internal::detail::ConcatinateTypeArg<T, ST2>::ArrayHandle>>
|
||||
{
|
||||
};
|
||||
}
|
||||
@ -383,10 +436,11 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template <typename AH1, typename AH2>
|
||||
struct Serialization<
|
||||
vtkm::cont::ArrayHandle<typename AH1::ValueType, vtkm::cont::StorageTagConcatenate<AH1, AH2>>>
|
||||
: Serialization<vtkm::cont::ArrayHandleConcatenate<AH1, AH2>>
|
||||
template <typename T, typename ST1, typename ST2>
|
||||
struct Serialization<vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagConcatenate<ST1, ST2>>>
|
||||
: Serialization<vtkm::cont::ArrayHandleConcatenate<
|
||||
typename vtkm::cont::internal::detail::ConcatinateTypeArg<T, ST1>::ArrayHandle,
|
||||
typename vtkm::cont::internal::detail::ConcatinateTypeArg<T, ST2>::ArrayHandle>>
|
||||
{
|
||||
};
|
||||
} // diy
|
||||
|
@ -17,7 +17,11 @@ namespace vtkm
|
||||
namespace cont
|
||||
{
|
||||
|
||||
namespace detail
|
||||
struct VTKM_ALWAYS_EXPORT StorageTagConstant
|
||||
{
|
||||
};
|
||||
|
||||
namespace internal
|
||||
{
|
||||
|
||||
template <typename ValueType>
|
||||
@ -36,7 +40,26 @@ private:
|
||||
ValueType Value;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
template <typename T>
|
||||
using StorageTagConstantSuperclass =
|
||||
typename vtkm::cont::ArrayHandleImplicit<ConstantFunctor<T>>::StorageTag;
|
||||
|
||||
template <typename T>
|
||||
struct Storage<T, vtkm::cont::StorageTagConstant> : Storage<T, StorageTagConstantSuperclass<T>>
|
||||
{
|
||||
using Superclass = Storage<T, StorageTagConstantSuperclass<T>>;
|
||||
using Superclass::Superclass;
|
||||
};
|
||||
|
||||
template <typename T, typename Device>
|
||||
struct ArrayTransfer<T, vtkm::cont::StorageTagConstant, Device>
|
||||
: ArrayTransfer<T, StorageTagConstantSuperclass<T>, Device>
|
||||
{
|
||||
using Superclass = ArrayTransfer<T, StorageTagConstantSuperclass<T>, Device>;
|
||||
using Superclass::Superclass;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
/// \brief An array handle with a constant value.
|
||||
///
|
||||
@ -47,16 +70,17 @@ private:
|
||||
/// takes (almost) no memory.
|
||||
///
|
||||
template <typename T>
|
||||
class ArrayHandleConstant : public vtkm::cont::ArrayHandleImplicit<detail::ConstantFunctor<T>>
|
||||
class ArrayHandleConstant : public vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagConstant>
|
||||
{
|
||||
public:
|
||||
VTKM_ARRAY_HANDLE_SUBCLASS(ArrayHandleConstant,
|
||||
(ArrayHandleConstant<T>),
|
||||
(vtkm::cont::ArrayHandleImplicit<detail::ConstantFunctor<T>>));
|
||||
(vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagConstant>));
|
||||
|
||||
VTKM_CONT
|
||||
ArrayHandleConstant(T value, vtkm::Id numberOfValues = 0)
|
||||
: Superclass(detail::ConstantFunctor<T>(value), numberOfValues)
|
||||
: Superclass(
|
||||
typename Superclass::ReadPortalType(internal::ConstantFunctor<T>(value), numberOfValues))
|
||||
{
|
||||
}
|
||||
};
|
||||
@ -82,18 +106,18 @@ namespace cont
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
struct SerializableTypeString<vtkm::cont::detail::ConstantFunctor<T>>
|
||||
struct SerializableTypeString<vtkm::cont::ArrayHandleConstant<T>>
|
||||
{
|
||||
static VTKM_CONT const std::string& Get()
|
||||
{
|
||||
static std::string name = "AH_ConstantFunctor<" + SerializableTypeString<T>::Get() + ">";
|
||||
static std::string name = "AH_Constant<" + SerializableTypeString<T>::Get() + ">";
|
||||
return name;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct SerializableTypeString<vtkm::cont::ArrayHandleConstant<T>>
|
||||
: SerializableTypeString<vtkm::cont::ArrayHandleImplicit<vtkm::cont::detail::ConstantFunctor<T>>>
|
||||
struct SerializableTypeString<vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagConstant>>
|
||||
: SerializableTypeString<vtkm::cont::ArrayHandleConstant<T>>
|
||||
{
|
||||
};
|
||||
}
|
||||
@ -104,7 +128,33 @@ namespace mangled_diy_namespace
|
||||
|
||||
template <typename T>
|
||||
struct Serialization<vtkm::cont::ArrayHandleConstant<T>>
|
||||
: Serialization<vtkm::cont::ArrayHandleImplicit<vtkm::cont::detail::ConstantFunctor<T>>>
|
||||
{
|
||||
private:
|
||||
using Type = vtkm::cont::ArrayHandleConstant<T>;
|
||||
using BaseType = vtkm::cont::ArrayHandle<typename Type::ValueType, typename Type::StorageTag>;
|
||||
|
||||
public:
|
||||
static VTKM_CONT void save(BinaryBuffer& bb, const BaseType& obj)
|
||||
{
|
||||
vtkmdiy::save(bb, obj.GetNumberOfValues());
|
||||
vtkmdiy::save(bb, obj.ReadPortal().Get(0));
|
||||
}
|
||||
|
||||
static VTKM_CONT void load(BinaryBuffer& bb, BaseType& obj)
|
||||
{
|
||||
vtkm::Id count = 0;
|
||||
vtkmdiy::load(bb, count);
|
||||
|
||||
T value;
|
||||
vtkmdiy::load(bb, value);
|
||||
|
||||
obj = vtkm::cont::make_ArrayHandleConstant(value, count);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct Serialization<vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagConstant>>
|
||||
: Serialization<vtkm::cont::ArrayHandleConstant<T>>
|
||||
{
|
||||
};
|
||||
|
||||
|
@ -20,6 +20,10 @@ namespace vtkm
|
||||
namespace cont
|
||||
{
|
||||
|
||||
struct VTKM_ALWAYS_EXPORT StorageTagCounting
|
||||
{
|
||||
};
|
||||
|
||||
namespace internal
|
||||
{
|
||||
|
||||
@ -87,12 +91,23 @@ private:
|
||||
vtkm::Id NumberOfValues;
|
||||
};
|
||||
|
||||
/// A convenience class that provides a typedef to the appropriate tag for
|
||||
/// a counting storage.
|
||||
template <typename ValueType>
|
||||
struct ArrayHandleCountingTraits
|
||||
template <typename T>
|
||||
using StorageTagCountingSuperclass =
|
||||
vtkm::cont::StorageTagImplicit<internal::ArrayPortalCounting<T>>;
|
||||
|
||||
template <typename T>
|
||||
struct Storage<T, vtkm::cont::StorageTagCounting> : Storage<T, StorageTagCountingSuperclass<T>>
|
||||
{
|
||||
using Tag = vtkm::cont::StorageTagImplicit<vtkm::cont::internal::ArrayPortalCounting<ValueType>>;
|
||||
using Superclass = Storage<T, StorageTagCountingSuperclass<T>>;
|
||||
using Superclass::Superclass;
|
||||
};
|
||||
|
||||
template <typename T, typename Device>
|
||||
struct ArrayTransfer<T, vtkm::cont::StorageTagCounting, Device>
|
||||
: ArrayTransfer<T, StorageTagCountingSuperclass<T>, Device>
|
||||
{
|
||||
using Superclass = ArrayTransfer<T, StorageTagCountingSuperclass<T>, Device>;
|
||||
using Superclass::Superclass;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
@ -101,21 +116,17 @@ struct ArrayHandleCountingTraits
|
||||
/// contains a increment value, that is increment for each step between zero
|
||||
/// and the passed in length
|
||||
template <typename CountingValueType>
|
||||
class ArrayHandleCounting : public vtkm::cont::ArrayHandle<
|
||||
CountingValueType,
|
||||
typename internal::ArrayHandleCountingTraits<CountingValueType>::Tag>
|
||||
class ArrayHandleCounting
|
||||
: public vtkm::cont::ArrayHandle<CountingValueType, vtkm::cont::StorageTagCounting>
|
||||
{
|
||||
public:
|
||||
VTKM_ARRAY_HANDLE_SUBCLASS(
|
||||
ArrayHandleCounting,
|
||||
(ArrayHandleCounting<CountingValueType>),
|
||||
(vtkm::cont::ArrayHandle<
|
||||
CountingValueType,
|
||||
typename internal::ArrayHandleCountingTraits<CountingValueType>::Tag>));
|
||||
VTKM_ARRAY_HANDLE_SUBCLASS(ArrayHandleCounting,
|
||||
(ArrayHandleCounting<CountingValueType>),
|
||||
(vtkm::cont::ArrayHandle<CountingValueType, StorageTagCounting>));
|
||||
|
||||
VTKM_CONT
|
||||
ArrayHandleCounting(CountingValueType start, CountingValueType step, vtkm::Id length)
|
||||
: Superclass(typename Superclass::PortalConstControl(start, step, length))
|
||||
: Superclass(typename Superclass::ReadPortalType(start, step, length))
|
||||
{
|
||||
}
|
||||
};
|
||||
@ -150,8 +161,7 @@ struct SerializableTypeString<vtkm::cont::ArrayHandleCounting<T>>
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct SerializableTypeString<
|
||||
vtkm::cont::ArrayHandle<T, typename vtkm::cont::ArrayHandleCounting<T>::StorageTag>>
|
||||
struct SerializableTypeString<vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagCounting>>
|
||||
: SerializableTypeString<vtkm::cont::ArrayHandleCounting<T>>
|
||||
{
|
||||
};
|
||||
@ -171,7 +181,7 @@ private:
|
||||
public:
|
||||
static VTKM_CONT void save(BinaryBuffer& bb, const BaseType& obj)
|
||||
{
|
||||
auto portal = obj.GetPortalConstControl();
|
||||
auto portal = obj.ReadPortal();
|
||||
vtkmdiy::save(bb, portal.GetStart());
|
||||
vtkmdiy::save(bb, portal.GetStep());
|
||||
vtkmdiy::save(bb, portal.GetNumberOfValues());
|
||||
@ -191,8 +201,7 @@ public:
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct Serialization<
|
||||
vtkm::cont::ArrayHandle<T, typename vtkm::cont::ArrayHandleCounting<T>::StorageTag>>
|
||||
struct Serialization<vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagCounting>>
|
||||
: Serialization<vtkm::cont::ArrayHandleCounting<T>>
|
||||
{
|
||||
};
|
||||
|
@ -11,6 +11,7 @@
|
||||
#define vtk_m_ArrayHandleDecorator_h
|
||||
|
||||
#include <vtkm/cont/ArrayHandle.h>
|
||||
#include <vtkm/cont/ErrorBadType.h>
|
||||
#include <vtkm/cont/Storage.h>
|
||||
|
||||
#include <vtkm/StaticAssert.h>
|
||||
@ -26,11 +27,15 @@
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
// MSVC and CUDA and Xcode < 10 and Clang < 5 have issues with tao integer sequences
|
||||
#if defined(VTKM_MSVC) || defined(VTKM_CUDA_DEVICE_PASS) || \
|
||||
(defined(__apple_build_version__) && (__apple_build_version__ < 10000000)) || \
|
||||
(defined(VTKM_CLANG) && (__clang_major__ < 5))
|
||||
#define VTKM_USE_BRIGAND_SEQ
|
||||
// Some compilers like brigand's integer sequences.
|
||||
// Some compilers prefer tao's.
|
||||
// Brigand seems to have more support, so we'll use that as default and fallback
|
||||
// to tao when brigand fails. With C++14, we'll be able to just use the STL.
|
||||
#if !defined(VTKM_CUDA_DEVICE_PASS) && \
|
||||
(defined(VTKM_GCC) || \
|
||||
(defined(__apple_build_version__) && (__apple_build_version__ >= 10000000)) || \
|
||||
(defined(VTKM_CLANG) && (__clang_major__ >= 5)))
|
||||
#define VTKM_USE_TAO_SEQ
|
||||
#endif
|
||||
|
||||
namespace vtkm
|
||||
@ -121,11 +126,9 @@ template <typename DecoratorImplT, template <typename...> class List, typename..
|
||||
struct IsFunctorInvertibleImpl<DecoratorImplT, List<PortalTs...>>
|
||||
{
|
||||
private:
|
||||
using PortalList = brigand::list<typename std::decay<PortalTs>::type...>;
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename U = decltype(std::declval<T>().CreateInverseFunctor(std::declval<PortalTs>()...))>
|
||||
typename U = decltype(std::declval<T>().CreateInverseFunctor(std::declval<PortalTs&&>()...))>
|
||||
static std::true_type InverseExistsTest(int);
|
||||
|
||||
template <typename T>
|
||||
@ -135,6 +138,44 @@ public:
|
||||
using type = decltype(InverseExistsTest<DecoratorImplT>(0));
|
||||
};
|
||||
|
||||
// Tests whether DecoratorImplT has an AllocateSourceArrays(size, Arrays...) method.
|
||||
template <typename DecoratorImplT, typename ArrayList>
|
||||
struct IsDecoratorAllocatableImpl;
|
||||
|
||||
template <typename DecoratorImplT, template <typename...> class List, typename... ArrayTs>
|
||||
struct IsDecoratorAllocatableImpl<DecoratorImplT, List<ArrayTs...>>
|
||||
{
|
||||
private:
|
||||
template <
|
||||
typename T,
|
||||
typename U = decltype(std::declval<T>().AllocateSourceArrays(0, std::declval<ArrayTs&>()...))>
|
||||
static std::true_type Exists(int);
|
||||
template <typename T>
|
||||
static std::false_type Exists(...);
|
||||
|
||||
public:
|
||||
using type = decltype(Exists<DecoratorImplT>(0));
|
||||
};
|
||||
|
||||
// Tests whether DecoratorImplT has a ShrinkSourceArrays(size, Arrays...) method.
|
||||
template <typename DecoratorImplT, typename ArrayList>
|
||||
struct IsDecoratorShrinkableImpl;
|
||||
|
||||
template <typename DecoratorImplT, template <typename...> class List, typename... ArrayTs>
|
||||
struct IsDecoratorShrinkableImpl<DecoratorImplT, List<ArrayTs...>>
|
||||
{
|
||||
private:
|
||||
template <
|
||||
typename T,
|
||||
typename U = decltype(std::declval<T>().ShrinkSourceArrays(0, std::declval<ArrayTs&>()...))>
|
||||
static std::true_type Exists(int);
|
||||
template <typename T>
|
||||
static std::false_type Exists(...);
|
||||
|
||||
public:
|
||||
using type = decltype(Exists<DecoratorImplT>(0));
|
||||
};
|
||||
|
||||
// Deduces the type returned by DecoratorImplT::CreateFunctor when given
|
||||
// the specified portals.
|
||||
template <typename DecoratorImplT, typename PortalList>
|
||||
@ -143,7 +184,8 @@ struct GetFunctorTypeImpl;
|
||||
template <typename DecoratorImplT, template <typename...> class List, typename... PortalTs>
|
||||
struct GetFunctorTypeImpl<DecoratorImplT, List<PortalTs...>>
|
||||
{
|
||||
using type = decltype(std::declval<DecoratorImplT>().CreateFunctor(std::declval<PortalTs>()...));
|
||||
using type =
|
||||
decltype(std::declval<DecoratorImplT>().CreateFunctor(std::declval<PortalTs&&>()...));
|
||||
};
|
||||
|
||||
// Deduces the type returned by DecoratorImplT::CreateInverseFunctor when given
|
||||
@ -156,7 +198,7 @@ template <typename DecoratorImplT, template <typename...> class List, typename..
|
||||
struct GetInverseFunctorTypeImpl<std::true_type, DecoratorImplT, List<PortalTs...>>
|
||||
{
|
||||
using type =
|
||||
decltype(std::declval<DecoratorImplT>().CreateInverseFunctor(std::declval<PortalTs>()...));
|
||||
decltype(std::declval<DecoratorImplT>().CreateInverseFunctor(std::declval<PortalTs&&>()...));
|
||||
};
|
||||
|
||||
template <typename DecoratorImplT, typename PortalList>
|
||||
@ -169,49 +211,49 @@ struct GetInverseFunctorTypeImpl<std::false_type, DecoratorImplT, PortalList>
|
||||
// See note below about using non-writable portals in invertible functors.
|
||||
// We need to sub in const portals when writable ones don't exist.
|
||||
template <typename ArrayT>
|
||||
typename std::decay<ArrayT>::type::PortalControl GetPortalControlImpl(std::true_type,
|
||||
ArrayT&& array)
|
||||
typename std::decay<ArrayT>::type::WritePortalType GetPortalControlImpl(std::true_type,
|
||||
ArrayT&& array)
|
||||
{
|
||||
return array.GetPortalControl();
|
||||
return array.WritePortal();
|
||||
}
|
||||
|
||||
template <typename ArrayT>
|
||||
typename std::decay<ArrayT>::type::PortalConstControl GetPortalControlImpl(std::false_type,
|
||||
ArrayT&& array)
|
||||
typename std::decay<ArrayT>::type::ReadPortalType GetPortalControlImpl(std::false_type,
|
||||
ArrayT&& array)
|
||||
{
|
||||
return array.GetPortalConstControl();
|
||||
return array.ReadPortal();
|
||||
}
|
||||
|
||||
template <typename ArrayT, typename Device>
|
||||
typename std::decay<ArrayT>::type::template ExecutionTypes<Device>::Portal
|
||||
GetPortalInPlaceImpl(std::true_type, ArrayT&& array, Device)
|
||||
GetPortalInPlaceImpl(std::true_type, ArrayT&& array, Device, vtkm::cont::Token& token)
|
||||
{
|
||||
return array.PrepareForInPlace(Device{});
|
||||
return array.PrepareForInPlace(Device{}, token);
|
||||
}
|
||||
|
||||
template <typename ArrayT, typename Device>
|
||||
typename std::decay<ArrayT>::type::template ExecutionTypes<Device>::PortalConst
|
||||
GetPortalInPlaceImpl(std::false_type, ArrayT&& array, Device)
|
||||
GetPortalInPlaceImpl(std::false_type, ArrayT&& array, Device, vtkm::cont::Token& token)
|
||||
{
|
||||
// ArrayT is read-only -- prepare for input instead.
|
||||
return array.PrepareForInput(Device{});
|
||||
return array.PrepareForInput(Device{}, token);
|
||||
}
|
||||
|
||||
template <typename ArrayT, typename Device>
|
||||
typename std::decay<ArrayT>::type::template ExecutionTypes<Device>::Portal
|
||||
GetPortalOutputImpl(std::true_type, ArrayT&& array, Device)
|
||||
GetPortalOutputImpl(std::true_type, ArrayT&& array, Device, vtkm::cont::Token& token)
|
||||
{
|
||||
// Prepare these for inplace usage instead -- we'll likely need to read
|
||||
// from these in addition to writing.
|
||||
return array.PrepareForInPlace(Device{});
|
||||
return array.PrepareForInPlace(Device{}, token);
|
||||
}
|
||||
|
||||
template <typename ArrayT, typename Device>
|
||||
typename std::decay<ArrayT>::type::template ExecutionTypes<Device>::PortalConst
|
||||
GetPortalOutputImpl(std::false_type, ArrayT&& array, Device)
|
||||
GetPortalOutputImpl(std::false_type, ArrayT&& array, Device, vtkm::cont::Token& token)
|
||||
{
|
||||
// ArrayT is read-only -- prepare for input instead.
|
||||
return array.PrepareForInput(Device{});
|
||||
return array.PrepareForInput(Device{}, token);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
@ -223,13 +265,13 @@ GetPortalOutputImpl(std::false_type, ArrayT&& array, Device)
|
||||
// const array handles so we can at least read from them in the inverse
|
||||
// functors.
|
||||
template <typename ArrayT,
|
||||
typename Portal = typename std::decay<ArrayT>::type::PortalControl,
|
||||
typename PortalConst = typename std::decay<ArrayT>::type::PortalConstControl>
|
||||
typename Portal = typename std::decay<ArrayT>::type::WritePortalType,
|
||||
typename PortalConst = typename std::decay<ArrayT>::type::ReadPortalType>
|
||||
using GetPortalControlType =
|
||||
typename brigand::if_<vtkm::internal::PortalSupportsSets<Portal>, Portal, PortalConst>::type;
|
||||
|
||||
template <typename ArrayT>
|
||||
using GetPortalConstControlType = typename std::decay<ArrayT>::type::PortalConstControl;
|
||||
using GetPortalConstControlType = typename std::decay<ArrayT>::type::ReadPortalType;
|
||||
|
||||
template <typename ArrayT,
|
||||
typename Device,
|
||||
@ -247,40 +289,38 @@ using GetPortalConstExecutionType =
|
||||
// Get portal objects:
|
||||
// See note above -- we swap in const portals sometimes.
|
||||
template <typename ArrayT>
|
||||
GetPortalControlType<typename std::decay<ArrayT>::type> GetPortalControl(ArrayT&& array)
|
||||
GetPortalControlType<typename std::decay<ArrayT>::type> WritePortal(ArrayT&& array)
|
||||
{
|
||||
return detail::GetPortalControlImpl(IsWritableArrayHandle<ArrayT>{}, std::forward<ArrayT>(array));
|
||||
}
|
||||
|
||||
template <typename ArrayT>
|
||||
GetPortalConstControlType<typename std::decay<ArrayT>::type> GetPortalConstControl(
|
||||
const ArrayT& array)
|
||||
GetPortalConstControlType<typename std::decay<ArrayT>::type> ReadPortal(const ArrayT& array)
|
||||
{
|
||||
return array.GetPortalConstControl();
|
||||
return array.ReadPortal();
|
||||
}
|
||||
|
||||
template <typename ArrayT, typename Device>
|
||||
GetPortalConstExecutionType<typename std::decay<ArrayT>::type, Device> GetPortalInput(
|
||||
const ArrayT& array,
|
||||
Device)
|
||||
GetPortalConstExecutionType<typename std::decay<ArrayT>::type, Device>
|
||||
GetPortalInput(const ArrayT& array, Device, vtkm::cont::Token& token)
|
||||
{
|
||||
return array.PrepareForInput(Device{});
|
||||
return array.PrepareForInput(Device{}, token);
|
||||
}
|
||||
|
||||
template <typename ArrayT, typename Device>
|
||||
GetPortalExecutionType<typename std::decay<ArrayT>::type, Device> GetPortalInPlace(ArrayT&& array,
|
||||
Device)
|
||||
GetPortalExecutionType<typename std::decay<ArrayT>::type, Device>
|
||||
GetPortalInPlace(ArrayT&& array, Device, vtkm::cont::Token& token)
|
||||
{
|
||||
return detail::GetPortalInPlaceImpl(
|
||||
IsWritableArrayHandle<ArrayT>{}, std::forward<ArrayT>(array), Device{});
|
||||
IsWritableArrayHandle<ArrayT>{}, std::forward<ArrayT>(array), Device{}, token);
|
||||
}
|
||||
|
||||
template <typename ArrayT, typename Device>
|
||||
GetPortalExecutionType<typename std::decay<ArrayT>::type, Device> GetPortalOutput(ArrayT&& array,
|
||||
Device)
|
||||
GetPortalExecutionType<typename std::decay<ArrayT>::type, Device>
|
||||
GetPortalOutput(ArrayT&& array, Device, vtkm::cont::Token& token)
|
||||
{
|
||||
return detail::GetPortalOutputImpl(
|
||||
IsWritableArrayHandle<ArrayT>{}, std::forward<ArrayT>(array), Device{});
|
||||
IsWritableArrayHandle<ArrayT>{}, std::forward<ArrayT>(array), Device{}, token);
|
||||
}
|
||||
|
||||
// Equivalent to std::true_type if *any* portal in PortalList can be written to.
|
||||
@ -296,6 +336,18 @@ template <typename DecoratorImplT, typename PortalList>
|
||||
using IsFunctorInvertible =
|
||||
typename detail::IsFunctorInvertibleImpl<DecoratorImplT, PortalList>::type;
|
||||
|
||||
// Set to std::true_type if DecoratorImplT::AllocateSourceArrays can be called
|
||||
// with the supplied arrays, or std::false_type otherwise.
|
||||
template <typename DecoratorImplT, typename ArrayList>
|
||||
using IsDecoratorAllocatable =
|
||||
typename detail::IsDecoratorAllocatableImpl<DecoratorImplT, ArrayList>::type;
|
||||
|
||||
// Set to std::true_type if DecoratorImplT::ShrinkSourceArrays can be called
|
||||
// with the supplied arrays, or std::false_type otherwise.
|
||||
template <typename DecoratorImplT, typename ArrayList>
|
||||
using IsDecoratorShrinkable =
|
||||
typename detail::IsDecoratorShrinkableImpl<DecoratorImplT, ArrayList>::type;
|
||||
|
||||
// std::true_type/std::false_type depending on whether the decorator impl has a
|
||||
// CreateInversePortal method AND any of the arrays are writable.
|
||||
template <typename DecoratorImplT, typename PortalList>
|
||||
@ -324,19 +376,18 @@ using GetInverseFunctorType =
|
||||
// - So we jump through some decltype/declval hoops here to get this to work:
|
||||
template <typename... ArrayTs>
|
||||
using GetPortalConstControlList =
|
||||
brigand::list<decltype((GetPortalConstControl(std::declval<ArrayTs>())))...>;
|
||||
brigand::list<decltype((ReadPortal(std::declval<ArrayTs&>())))...>;
|
||||
|
||||
template <typename Device, typename... ArrayTs>
|
||||
using GetPortalConstExecutionList =
|
||||
brigand::list<decltype((GetPortalInput(std::declval<ArrayTs>(), Device{})))...>;
|
||||
using GetPortalConstExecutionList = brigand::list<decltype(
|
||||
(GetPortalInput(std::declval<ArrayTs&>(), Device{}, std::declval<vtkm::cont::Token&>())))...>;
|
||||
|
||||
template <typename... ArrayTs>
|
||||
using GetPortalControlList =
|
||||
brigand::list<decltype((GetPortalControl(std::declval<ArrayTs>())))...>;
|
||||
using GetPortalControlList = brigand::list<decltype((WritePortal(std::declval<ArrayTs&>())))...>;
|
||||
|
||||
template <typename Device, typename... ArrayTs>
|
||||
using GetPortalExecutionList =
|
||||
brigand::list<decltype((GetPortalInPlace(std::declval<ArrayTs>(), Device{})))...>;
|
||||
using GetPortalExecutionList = brigand::list<decltype(
|
||||
(GetPortalInPlace(std::declval<ArrayTs&>(), Device{}, std::declval<vtkm::cont::Token&>())))...>;
|
||||
|
||||
template <typename DecoratorImplT, typename... ArrayTs>
|
||||
struct DecoratorStorageTraits
|
||||
@ -359,11 +410,15 @@ struct DecoratorStorageTraits
|
||||
using ArrayTupleType = vtkmstd::tuple<ArrayTs...>;
|
||||
|
||||
// size_t integral constants that index ArrayTs:
|
||||
#ifdef VTKM_USE_BRIGAND_SEQ
|
||||
#ifndef VTKM_USE_TAO_SEQ
|
||||
using IndexList = brigand::make_sequence<brigand::size_t<0>, sizeof...(ArrayTs)>;
|
||||
#else // VTKM_USE_BRIGAND_SEQ
|
||||
#else // VTKM_USE_TAO_SEQ
|
||||
using IndexList = tao::seq::make_index_sequence<sizeof...(ArrayTs)>;
|
||||
#endif // VTKM_USE_BRIGAND_SEQ
|
||||
#endif // VTKM_USE_TAO_SEQ
|
||||
|
||||
// true_type/false_type depending on whether the decorator supports Allocate/Shrink:
|
||||
using IsAllocatable = IsDecoratorAllocatable<DecoratorImplT, ArrayList>;
|
||||
using IsShrinkable = IsDecoratorShrinkable<DecoratorImplT, ArrayList>;
|
||||
|
||||
// Portal lists:
|
||||
// NOTE we have to pass the parameter pack here instead of using ArrayList
|
||||
@ -442,7 +497,42 @@ struct DecoratorStorageTraits
|
||||
return { impl.CreateFunctor(portals...), impl.CreateInverseFunctor(portals...), numVals };
|
||||
}
|
||||
|
||||
#ifdef VTKM_USE_BRIGAND_SEQ
|
||||
// Static dispatch for calling AllocateSourceArrays on supported implementations:
|
||||
VTKM_CONT[[noreturn]] static void CallAllocate(std::false_type,
|
||||
const DecoratorImplT&,
|
||||
vtkm::Id,
|
||||
ArrayTs&...)
|
||||
{
|
||||
throw vtkm::cont::ErrorBadType("Allocate not supported by this ArrayHandleDecorator.");
|
||||
}
|
||||
|
||||
VTKM_CONT static void CallAllocate(std::true_type,
|
||||
const DecoratorImplT& impl,
|
||||
vtkm::Id newSize,
|
||||
ArrayTs&... arrays)
|
||||
{
|
||||
impl.AllocateSourceArrays(newSize, arrays...);
|
||||
}
|
||||
|
||||
// Static dispatch for calling ShrinkSourceArrays on supported implementations.
|
||||
VTKM_CONT[[noreturn]] static void CallShrink(std::false_type,
|
||||
const DecoratorImplT&,
|
||||
vtkm::Id,
|
||||
ArrayTs&...)
|
||||
{
|
||||
throw vtkm::cont::ErrorBadType("Shrink not supported by this ArrayHandleDecorator.");
|
||||
}
|
||||
|
||||
VTKM_CONT static void CallShrink(std::true_type,
|
||||
const DecoratorImplT& impl,
|
||||
vtkm::Id newSize,
|
||||
ArrayTs&... arrays)
|
||||
{
|
||||
impl.ShrinkSourceArrays(newSize, arrays...);
|
||||
}
|
||||
|
||||
|
||||
#ifndef VTKM_USE_TAO_SEQ
|
||||
// Portal construction methods. These actually create portals.
|
||||
template <template <typename...> class List, typename... Indices>
|
||||
VTKM_CONT static PortalControlType MakePortalControl(const DecoratorImplT& impl,
|
||||
@ -461,7 +551,7 @@ struct DecoratorStorageTraits
|
||||
// Indices{}.value : Works on both MSVC2015 and MSVC2017.
|
||||
//
|
||||
// Don't touch the following line unless you really, really have to.
|
||||
GetPortalControl(vtkmstd::get<Indices{}.value>(arrays))...);
|
||||
WritePortal(vtkmstd::get<Indices{}.value>(arrays))...);
|
||||
}
|
||||
|
||||
template <template <typename...> class List, typename... Indices>
|
||||
@ -475,7 +565,7 @@ struct DecoratorStorageTraits
|
||||
impl,
|
||||
// Don't touch the following line unless you really, really have to. See
|
||||
// note in MakePortalControl.
|
||||
GetPortalConstControl(vtkmstd::get<Indices{}.value>(arrays))...);
|
||||
ReadPortal(vtkmstd::get<Indices{}.value>(arrays))...);
|
||||
}
|
||||
|
||||
template <template <typename...> class List, typename... Indices, typename Device>
|
||||
@ -483,14 +573,15 @@ struct DecoratorStorageTraits
|
||||
const ArrayTupleType& arrays,
|
||||
vtkm::Id numValues,
|
||||
List<Indices...>,
|
||||
Device dev)
|
||||
Device dev,
|
||||
vtkm::cont::Token& token)
|
||||
{
|
||||
return CreatePortalDecorator<PortalConstExecutionType<Device>>(
|
||||
numValues,
|
||||
impl,
|
||||
// Don't touch the following line unless you really, really have to. See
|
||||
// note in MakePortalControl.
|
||||
GetPortalInput(vtkmstd::get<Indices{}.value>(arrays), dev)...);
|
||||
GetPortalInput(vtkmstd::get<Indices{}.value>(arrays), dev, token)...);
|
||||
}
|
||||
|
||||
template <template <typename...> class List, typename... Indices, typename Device>
|
||||
@ -498,14 +589,15 @@ struct DecoratorStorageTraits
|
||||
ArrayTupleType& arrays,
|
||||
vtkm::Id numValues,
|
||||
List<Indices...>,
|
||||
Device dev)
|
||||
Device dev,
|
||||
vtkm::cont::Token& token)
|
||||
{
|
||||
return CreatePortalDecorator<PortalExecutionType<Device>>(
|
||||
numValues,
|
||||
impl,
|
||||
// Don't touch the following line unless you really, really have to. See
|
||||
// note in MakePortalControl.
|
||||
GetPortalInPlace(vtkmstd::get<Indices{}.value>(arrays), dev)...);
|
||||
GetPortalInPlace(vtkmstd::get<Indices{}.value>(arrays), dev, token)...);
|
||||
}
|
||||
|
||||
template <template <typename...> class List, typename... Indices, typename Device>
|
||||
@ -513,17 +605,37 @@ struct DecoratorStorageTraits
|
||||
ArrayTupleType& arrays,
|
||||
vtkm::Id numValues,
|
||||
List<Indices...>,
|
||||
Device dev)
|
||||
Device dev,
|
||||
vtkm::cont::Token& token)
|
||||
{
|
||||
return CreatePortalDecorator<PortalExecutionType<Device>>(
|
||||
numValues,
|
||||
impl,
|
||||
// Don't touch the following line unless you really, really have to. See
|
||||
// note in MakePortalControl.
|
||||
GetPortalOutput(vtkmstd::get<Indices{}.value>(arrays), dev)...);
|
||||
GetPortalOutput(vtkmstd::get<Indices{}.value>(arrays), dev, token)...);
|
||||
}
|
||||
|
||||
#else // VTKM_USE_BRIGAND_SEQ
|
||||
template <template <typename...> class List, typename... Indices>
|
||||
VTKM_CONT static void AllocateSourceArrays(const DecoratorImplT& impl,
|
||||
ArrayTupleType& arrays,
|
||||
vtkm::Id numValues,
|
||||
List<Indices...>)
|
||||
{
|
||||
CallAllocate(IsAllocatable{}, impl, numValues, vtkmstd::get<Indices{}.value>(arrays)...);
|
||||
}
|
||||
|
||||
template <template <typename...> class List, typename... Indices>
|
||||
VTKM_CONT static void ShrinkSourceArrays(const DecoratorImplT& impl,
|
||||
ArrayTupleType& arrays,
|
||||
vtkm::Id numValues,
|
||||
List<Indices...>)
|
||||
{
|
||||
CallShrink(IsShrinkable{}, impl, numValues, vtkmstd::get<Indices{}.value>(arrays)...);
|
||||
}
|
||||
|
||||
#else // VTKM_USE_TAO_SEQ
|
||||
|
||||
// Portal construction methods. These actually create portals.
|
||||
template <template <typename, std::size_t...> class List, std::size_t... Indices>
|
||||
VTKM_CONT static PortalControlType MakePortalControl(const DecoratorImplT& impl,
|
||||
@ -532,7 +644,7 @@ struct DecoratorStorageTraits
|
||||
List<std::size_t, Indices...>)
|
||||
{
|
||||
return CreatePortalDecorator<PortalControlType>(
|
||||
numValues, impl, GetPortalControl(vtkmstd::get<Indices>(arrays))...);
|
||||
numValues, impl, WritePortal(vtkmstd::get<Indices>(arrays))...);
|
||||
}
|
||||
|
||||
template <template <typename, std::size_t...> class List, std::size_t... Indices>
|
||||
@ -542,7 +654,7 @@ struct DecoratorStorageTraits
|
||||
List<std::size_t, Indices...>)
|
||||
{
|
||||
return CreatePortalDecorator<PortalConstControlType>(
|
||||
numValues, impl, GetPortalConstControl(vtkmstd::get<Indices>(arrays))...);
|
||||
numValues, impl, ReadPortal(vtkmstd::get<Indices>(arrays))...);
|
||||
}
|
||||
|
||||
template <template <typename, std::size_t...> class List, std::size_t... Indices, typename Device>
|
||||
@ -550,10 +662,11 @@ struct DecoratorStorageTraits
|
||||
const ArrayTupleType& arrays,
|
||||
vtkm::Id numValues,
|
||||
List<std::size_t, Indices...>,
|
||||
Device dev)
|
||||
Device dev,
|
||||
vtkm::cont::Token& token)
|
||||
{
|
||||
return CreatePortalDecorator<PortalConstExecutionType<Device>>(
|
||||
numValues, impl, GetPortalInput(vtkmstd::get<Indices>(arrays), dev)...);
|
||||
numValues, impl, GetPortalInput(vtkmstd::get<Indices>(arrays), dev, token)...);
|
||||
}
|
||||
|
||||
template <template <typename, std::size_t...> class List, std::size_t... Indices, typename Device>
|
||||
@ -561,10 +674,11 @@ struct DecoratorStorageTraits
|
||||
ArrayTupleType& arrays,
|
||||
vtkm::Id numValues,
|
||||
List<std::size_t, Indices...>,
|
||||
Device dev)
|
||||
Device dev,
|
||||
vtkm::cont::Token& token)
|
||||
{
|
||||
return CreatePortalDecorator<PortalExecutionType<Device>>(
|
||||
numValues, impl, GetPortalInPlace(vtkmstd::get<Indices>(arrays), dev)...);
|
||||
numValues, impl, GetPortalInPlace(vtkmstd::get<Indices>(arrays), dev, token)...);
|
||||
}
|
||||
|
||||
template <template <typename, std::size_t...> class List, std::size_t... Indices, typename Device>
|
||||
@ -572,12 +686,32 @@ struct DecoratorStorageTraits
|
||||
ArrayTupleType& arrays,
|
||||
vtkm::Id numValues,
|
||||
List<std::size_t, Indices...>,
|
||||
Device dev)
|
||||
Device dev,
|
||||
vtkm::cont::Token& token)
|
||||
{
|
||||
return CreatePortalDecorator<PortalExecutionType<Device>>(
|
||||
numValues, impl, GetPortalOutput(vtkmstd::get<Indices>(arrays), dev)...);
|
||||
numValues, impl, GetPortalOutput(vtkmstd::get<Indices>(arrays), dev, token)...);
|
||||
}
|
||||
#endif // VTKM_USE_BRIGAND_SEQ
|
||||
|
||||
template <template <typename, std::size_t...> class List, std::size_t... Indices>
|
||||
VTKM_CONT static void AllocateSourceArrays(const DecoratorImplT& impl,
|
||||
ArrayTupleType& arrays,
|
||||
vtkm::Id numValues,
|
||||
List<std::size_t, Indices...>)
|
||||
{
|
||||
CallAllocate(IsAllocatable{}, impl, numValues, vtkmstd::get<Indices>(arrays)...);
|
||||
}
|
||||
|
||||
template <template <typename, std::size_t...> class List, std::size_t... Indices>
|
||||
VTKM_CONT static void ShrinkSourceArrays(const DecoratorImplT& impl,
|
||||
ArrayTupleType& arrays,
|
||||
vtkm::Id numValues,
|
||||
List<std::size_t, Indices...>)
|
||||
{
|
||||
CallShrink(IsShrinkable{}, impl, numValues, vtkmstd::get<Indices>(arrays)...);
|
||||
}
|
||||
|
||||
#endif // VTKM_USE_TAO_SEQ
|
||||
};
|
||||
|
||||
} // end namespace decor
|
||||
@ -639,18 +773,21 @@ public:
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
void Allocate(vtkm::Id)
|
||||
void Allocate(vtkm::Id numValues)
|
||||
{
|
||||
VTKM_ASSERT(this->Valid);
|
||||
// No-op. I suppose eventually we could pass numValues down to the
|
||||
// implementation class and let it do something intelligent.
|
||||
Traits::AllocateSourceArrays(this->Implementation, this->ArrayTuple, numValues, IndexList{});
|
||||
// If the above call doesn't throw, update our state.
|
||||
this->NumberOfValues = numValues;
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
void Shrink(vtkm::Id)
|
||||
void Shrink(vtkm::Id numValues)
|
||||
{
|
||||
VTKM_ASSERT(this->Valid);
|
||||
// No-op. Again, could eventually be passed down to the implementation.
|
||||
Traits::ShrinkSourceArrays(this->Implementation, this->ArrayTuple, numValues, IndexList{});
|
||||
// If the above call doesn't throw, update our state.
|
||||
this->NumberOfValues = numValues;
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
@ -737,33 +874,36 @@ public:
|
||||
vtkm::Id GetNumberOfValues() const { return this->Storage->GetNumberOfValues(); }
|
||||
|
||||
VTKM_CONT
|
||||
PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData)) const
|
||||
PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData), vtkm::cont::Token& token) const
|
||||
{
|
||||
return Traits::MakePortalInput(this->Storage->GetImplementation(),
|
||||
this->Storage->GetArrayTuple(),
|
||||
this->Storage->GetNumberOfValues(),
|
||||
IndexList{},
|
||||
Device{});
|
||||
Device{},
|
||||
token);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
PortalExecution PrepareForInPlace(bool vtkmNotUsed(updateData))
|
||||
PortalExecution PrepareForInPlace(bool vtkmNotUsed(updateData), vtkm::cont::Token& token)
|
||||
{
|
||||
return Traits::MakePortalInPlace(this->Storage->GetImplementation(),
|
||||
this->Storage->GetArrayTuple(),
|
||||
this->Storage->GetNumberOfValues(),
|
||||
IndexList{},
|
||||
Device{});
|
||||
Device{},
|
||||
token);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
PortalExecution PrepareForOutput(vtkm::Id)
|
||||
PortalExecution PrepareForOutput(vtkm::Id, vtkm::cont::Token& token)
|
||||
{
|
||||
return Traits::MakePortalOutput(this->Storage->GetImplementation(),
|
||||
this->Storage->GetArrayTuple(),
|
||||
this->Storage->GetNumberOfValues(),
|
||||
IndexList{},
|
||||
Device{});
|
||||
Device{},
|
||||
token);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
@ -775,10 +915,7 @@ public:
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
void Shrink(vtkm::Id)
|
||||
{
|
||||
// no-op
|
||||
}
|
||||
void Shrink(vtkm::Id numValues) { this->Storage->Shrink(numValues); }
|
||||
|
||||
|
||||
VTKM_CONT
|
||||
@ -809,7 +946,7 @@ private:
|
||||
/// // Takes one portal for each source array handle (only two shown).
|
||||
/// // Returns a functor that defines:
|
||||
/// //
|
||||
/// // ValueType operator()(vtkm::Id id) const;
|
||||
/// // VTKM_EXEC_CONT ValueType operator()(vtkm::Id id) const;
|
||||
/// //
|
||||
/// // which takes an index and returns a value which should be produced by
|
||||
/// // the source arrays somehow. This ValueType will be the ValueType of the
|
||||
@ -818,12 +955,13 @@ private:
|
||||
/// // Both SomeFunctor::operator() and CreateFunctor must be const.
|
||||
/// //
|
||||
/// template <typename Portal1Type, typename Portal2Type>
|
||||
/// VTKM_CONT
|
||||
/// SomeFunctor CreateFunctor(Portal1Type portal1, Portal2Type portal2) const;
|
||||
///
|
||||
/// // Takes one portal for each source array handle (only two shown).
|
||||
/// // Returns a functor that defines:
|
||||
/// //
|
||||
/// // void operator()(vtkm::Id id, ValueType val) const;
|
||||
/// // VTKM_EXEC_CONT void operator()(vtkm::Id id, ValueType val) const;
|
||||
/// //
|
||||
/// // which takes an index and a value, which should be used to modify one
|
||||
/// // or more of the source arrays.
|
||||
@ -837,9 +975,35 @@ private:
|
||||
/// // const.
|
||||
/// //
|
||||
/// template <typename Portal1Type, typename Portal2Type>
|
||||
/// VTKM_CONT
|
||||
/// SomeInverseFunctor CreateInverseFunctor(Portal1Type portal1,
|
||||
/// Portal2Type portal2) const;
|
||||
///
|
||||
/// // Given a set of ArrayHandles and a size, implement what should happen
|
||||
/// // to the source ArrayHandles when Allocate() is called on the decorator
|
||||
/// // handle.
|
||||
/// //
|
||||
/// // AllocateSourceArrays is optional; if not provided, the
|
||||
/// // ArrayHandleDecorator will throw if its Allocate method is called. If
|
||||
/// // an implementation is present and doesn't throw, the
|
||||
/// // ArrayHandleDecorator's internal state is updated to show `size` as the
|
||||
/// // number of values.
|
||||
/// template <typename Array1Type, typename Array2Type>
|
||||
/// VTKM_CONT
|
||||
/// void AllocateSourceArrays(vtkm::Id size, Array1Type array1, Array2Type array2) const;
|
||||
///
|
||||
/// // Given a set of ArrayHandles and a size, implement what should happen to
|
||||
/// // the source ArrayHandles when Shrink() is called on the decorator handle.
|
||||
/// //
|
||||
/// // ShrinkSourceArrays is optional; if not provided, the
|
||||
/// // ArrayHandleDecorator will throw if its Shrink method is called. If
|
||||
/// // an implementation is present and doesn't throw, the
|
||||
/// // ArrayHandleDecorator's internal state is updated to show `size` as the
|
||||
/// // number of values.
|
||||
/// template <typename Array1Type, typename Array2Type>
|
||||
/// VTKM_CONT
|
||||
/// void ShrinkSourceArrays(vtkm::Id size, Array1Type array1, Array2Type array2) const;
|
||||
///
|
||||
/// };
|
||||
/// ```
|
||||
///
|
||||
@ -894,6 +1058,8 @@ make_ArrayHandleDecorator(vtkm::Id numValues, DecoratorImplT&& f, ArrayTs&&... a
|
||||
}
|
||||
} // namespace vtkm::cont
|
||||
|
||||
#undef VTKM_USE_BRIGAND_SEQ
|
||||
#ifdef VTKM_USE_TAO_SEQ
|
||||
#undef VTKM_USE_TAO_SEQ
|
||||
#endif
|
||||
|
||||
#endif //vtk_m_ArrayHandleDecorator_h
|
||||
|
@ -148,21 +148,21 @@ public:
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData))
|
||||
PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData), vtkm::cont::Token&)
|
||||
{
|
||||
throw vtkm::cont::ErrorBadValue("Input access not supported: "
|
||||
"Cannot read from an ArrayHandleDiscard.");
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
PortalExecution PrepareForInPlace(bool vtkmNotUsed(updateData))
|
||||
PortalExecution PrepareForInPlace(bool vtkmNotUsed(updateData), vtkm::cont::Token&)
|
||||
{
|
||||
throw vtkm::cont::ErrorBadValue("InPlace access not supported: "
|
||||
"Cannot read from an ArrayHandleDiscard.");
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
PortalExecution PrepareForOutput(vtkm::Id numValues)
|
||||
PortalExecution PrepareForOutput(vtkm::Id numValues, vtkm::cont::Token&)
|
||||
{
|
||||
VTKM_ASSERT(this->Internal != nullptr);
|
||||
this->Internal->Allocate(numValues);
|
||||
|
@ -51,6 +51,9 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
ArrayPortalExtractComponent& operator=(const ArrayPortalExtractComponent& src) = default;
|
||||
ArrayPortalExtractComponent& operator=(ArrayPortalExtractComponent&& src) = default;
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
vtkm::Id GetNumberOfValues() const { return this->Portal.GetNumberOfValues(); }
|
||||
|
||||
@ -92,8 +95,8 @@ class Storage<typename vtkm::VecTraits<typename ArrayHandleType::ValueType>::Com
|
||||
StorageTagExtractComponent<ArrayHandleType>>
|
||||
{
|
||||
public:
|
||||
using PortalType = ArrayPortalExtractComponent<typename ArrayHandleType::PortalControl>;
|
||||
using PortalConstType = ArrayPortalExtractComponent<typename ArrayHandleType::PortalConstControl>;
|
||||
using PortalType = ArrayPortalExtractComponent<typename ArrayHandleType::WritePortalType>;
|
||||
using PortalConstType = ArrayPortalExtractComponent<typename ArrayHandleType::ReadPortalType>;
|
||||
using ValueType = typename PortalType::ValueType;
|
||||
|
||||
VTKM_CONT
|
||||
@ -116,14 +119,14 @@ public:
|
||||
PortalConstType GetPortalConst() const
|
||||
{
|
||||
VTKM_ASSERT(this->Valid);
|
||||
return PortalConstType(this->Array.GetPortalConstControl(), this->Component);
|
||||
return PortalConstType(this->Array.ReadPortal(), this->Component);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
PortalType GetPortal()
|
||||
{
|
||||
VTKM_ASSERT(this->Valid);
|
||||
return PortalType(this->Array.GetPortalControl(), this->Component);
|
||||
return PortalType(this->Array.WritePortal(), this->Component);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
@ -209,21 +212,22 @@ public:
|
||||
vtkm::Id GetNumberOfValues() const { return this->Array.GetNumberOfValues(); }
|
||||
|
||||
VTKM_CONT
|
||||
PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData))
|
||||
PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData), vtkm::cont::Token& token)
|
||||
{
|
||||
return PortalConstExecution(this->Array.PrepareForInput(Device()), this->Component);
|
||||
return PortalConstExecution(this->Array.PrepareForInput(Device(), token), this->Component);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
PortalExecution PrepareForInPlace(bool vtkmNotUsed(updateData))
|
||||
PortalExecution PrepareForInPlace(bool vtkmNotUsed(updateData), vtkm::cont::Token& token)
|
||||
{
|
||||
return PortalExecution(this->Array.PrepareForInPlace(Device()), this->Component);
|
||||
return PortalExecution(this->Array.PrepareForInPlace(Device(), token), this->Component);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
PortalExecution PrepareForOutput(vtkm::Id numberOfValues)
|
||||
PortalExecution PrepareForOutput(vtkm::Id numberOfValues, vtkm::cont::Token& token)
|
||||
{
|
||||
return PortalExecution(this->Array.PrepareForOutput(numberOfValues, Device()), this->Component);
|
||||
return PortalExecution(this->Array.PrepareForOutput(numberOfValues, Device(), token),
|
||||
this->Component);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
|
@ -109,28 +109,28 @@ namespace vtkm
|
||||
namespace cont
|
||||
{
|
||||
|
||||
namespace internal
|
||||
{
|
||||
|
||||
template <typename SourceArrayHandleType, vtkm::IdComponent NUM_COMPONENTS>
|
||||
template <typename SourceStorageTag, vtkm::IdComponent NUM_COMPONENTS>
|
||||
struct VTKM_ALWAYS_EXPORT StorageTagGroupVec
|
||||
{
|
||||
};
|
||||
|
||||
template <typename SourceArrayHandleType, vtkm::IdComponent NUM_COMPONENTS>
|
||||
class Storage<vtkm::Vec<typename SourceArrayHandleType::ValueType, NUM_COMPONENTS>,
|
||||
vtkm::cont::internal::StorageTagGroupVec<SourceArrayHandleType, NUM_COMPONENTS>>
|
||||
namespace internal
|
||||
{
|
||||
using ComponentType = typename SourceArrayHandleType::ValueType;
|
||||
|
||||
template <typename ComponentType, vtkm::IdComponent NUM_COMPONENTS, typename SourceStorageTag>
|
||||
class Storage<vtkm::Vec<ComponentType, NUM_COMPONENTS>,
|
||||
vtkm::cont::StorageTagGroupVec<SourceStorageTag, NUM_COMPONENTS>>
|
||||
{
|
||||
using SourceArrayHandleType = vtkm::cont::ArrayHandle<ComponentType, SourceStorageTag>;
|
||||
|
||||
public:
|
||||
using ValueType = vtkm::Vec<ComponentType, NUM_COMPONENTS>;
|
||||
|
||||
using PortalType =
|
||||
vtkm::exec::internal::ArrayPortalGroupVec<typename SourceArrayHandleType::PortalControl,
|
||||
vtkm::exec::internal::ArrayPortalGroupVec<typename SourceArrayHandleType::WritePortalType,
|
||||
NUM_COMPONENTS>;
|
||||
using PortalConstType =
|
||||
vtkm::exec::internal::ArrayPortalGroupVec<typename SourceArrayHandleType::PortalConstControl,
|
||||
vtkm::exec::internal::ArrayPortalGroupVec<typename SourceArrayHandleType::ReadPortalType,
|
||||
NUM_COMPONENTS>;
|
||||
|
||||
VTKM_CONT
|
||||
@ -150,14 +150,14 @@ public:
|
||||
PortalType GetPortal()
|
||||
{
|
||||
VTKM_ASSERT(this->Valid);
|
||||
return PortalType(this->SourceArray.GetPortalControl());
|
||||
return PortalType(this->SourceArray.WritePortal());
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
PortalConstType GetPortalConst() const
|
||||
{
|
||||
VTKM_ASSERT(this->Valid);
|
||||
return PortalConstType(this->SourceArray.GetPortalConstControl());
|
||||
return PortalConstType(this->SourceArray.ReadPortal());
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
@ -209,20 +209,23 @@ private:
|
||||
bool Valid;
|
||||
};
|
||||
|
||||
template <typename SourceArrayHandleType, vtkm::IdComponent NUM_COMPONENTS, typename Device>
|
||||
class ArrayTransfer<vtkm::Vec<typename SourceArrayHandleType::ValueType, NUM_COMPONENTS>,
|
||||
vtkm::cont::internal::StorageTagGroupVec<SourceArrayHandleType, NUM_COMPONENTS>,
|
||||
template <typename ComponentType,
|
||||
vtkm::IdComponent NUM_COMPONENTS,
|
||||
typename SourceStorageTag,
|
||||
typename Device>
|
||||
class ArrayTransfer<vtkm::Vec<ComponentType, NUM_COMPONENTS>,
|
||||
vtkm::cont::StorageTagGroupVec<SourceStorageTag, NUM_COMPONENTS>,
|
||||
Device>
|
||||
{
|
||||
public:
|
||||
using ComponentType = typename SourceArrayHandleType::ValueType;
|
||||
using ValueType = vtkm::Vec<ComponentType, NUM_COMPONENTS>;
|
||||
|
||||
private:
|
||||
using StorageTag =
|
||||
vtkm::cont::internal::StorageTagGroupVec<SourceArrayHandleType, NUM_COMPONENTS>;
|
||||
using StorageTag = vtkm::cont::StorageTagGroupVec<SourceStorageTag, NUM_COMPONENTS>;
|
||||
using StorageType = vtkm::cont::internal::Storage<ValueType, StorageTag>;
|
||||
|
||||
using SourceArrayHandleType = vtkm::cont::ArrayHandle<ComponentType, SourceStorageTag>;
|
||||
|
||||
public:
|
||||
using PortalControl = typename StorageType::PortalType;
|
||||
using PortalConstControl = typename StorageType::PortalConstType;
|
||||
@ -253,32 +256,32 @@ public:
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData))
|
||||
PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData), vtkm::cont::Token& token)
|
||||
{
|
||||
if (this->SourceArray.GetNumberOfValues() % NUM_COMPONENTS != 0)
|
||||
{
|
||||
throw vtkm::cont::ErrorBadValue(
|
||||
"ArrayHandleGroupVec's source array does not divide evenly into Vecs.");
|
||||
}
|
||||
return PortalConstExecution(this->SourceArray.PrepareForInput(Device()));
|
||||
return PortalConstExecution(this->SourceArray.PrepareForInput(Device(), token));
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
PortalExecution PrepareForInPlace(bool vtkmNotUsed(updateData))
|
||||
PortalExecution PrepareForInPlace(bool vtkmNotUsed(updateData), vtkm::cont::Token& token)
|
||||
{
|
||||
if (this->SourceArray.GetNumberOfValues() % NUM_COMPONENTS != 0)
|
||||
{
|
||||
throw vtkm::cont::ErrorBadValue(
|
||||
"ArrayHandleGroupVec's source array does not divide evenly into Vecs.");
|
||||
}
|
||||
return PortalExecution(this->SourceArray.PrepareForInPlace(Device()));
|
||||
return PortalExecution(this->SourceArray.PrepareForInPlace(Device(), token));
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
PortalExecution PrepareForOutput(vtkm::Id numberOfValues)
|
||||
PortalExecution PrepareForOutput(vtkm::Id numberOfValues, vtkm::cont::Token& token)
|
||||
{
|
||||
return PortalExecution(
|
||||
this->SourceArray.PrepareForOutput(numberOfValues * NUM_COMPONENTS, Device()));
|
||||
this->SourceArray.PrepareForOutput(numberOfValues * NUM_COMPONENTS, Device(), token));
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
@ -320,7 +323,7 @@ template <typename SourceArrayHandleType, vtkm::IdComponent NUM_COMPONENTS>
|
||||
class ArrayHandleGroupVec
|
||||
: public vtkm::cont::ArrayHandle<
|
||||
vtkm::Vec<typename SourceArrayHandleType::ValueType, NUM_COMPONENTS>,
|
||||
vtkm::cont::internal::StorageTagGroupVec<SourceArrayHandleType, NUM_COMPONENTS>>
|
||||
vtkm::cont::StorageTagGroupVec<typename SourceArrayHandleType::StorageTag, NUM_COMPONENTS>>
|
||||
{
|
||||
VTKM_IS_ARRAY_HANDLE(SourceArrayHandleType);
|
||||
|
||||
@ -330,7 +333,7 @@ public:
|
||||
(ArrayHandleGroupVec<SourceArrayHandleType, NUM_COMPONENTS>),
|
||||
(vtkm::cont::ArrayHandle<
|
||||
vtkm::Vec<typename SourceArrayHandleType::ValueType, NUM_COMPONENTS>,
|
||||
vtkm::cont::internal::StorageTagGroupVec<SourceArrayHandleType, NUM_COMPONENTS>>));
|
||||
vtkm::cont::StorageTagGroupVec<typename SourceArrayHandleType::StorageTag, NUM_COMPONENTS>>));
|
||||
|
||||
using ComponentType = typename SourceArrayHandleType::ValueType;
|
||||
|
||||
@ -378,11 +381,11 @@ struct SerializableTypeString<vtkm::cont::ArrayHandleGroupVec<AH, NUM_COMPS>>
|
||||
}
|
||||
};
|
||||
|
||||
template <typename AH, vtkm::IdComponent NUM_COMPS>
|
||||
template <typename T, vtkm::IdComponent NUM_COMPS, typename ST>
|
||||
struct SerializableTypeString<
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<typename AH::ValueType, NUM_COMPS>,
|
||||
vtkm::cont::internal::StorageTagGroupVec<AH, NUM_COMPS>>>
|
||||
: SerializableTypeString<vtkm::cont::ArrayHandleGroupVec<AH, NUM_COMPS>>
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<T, NUM_COMPS>, vtkm::cont::StorageTagGroupVec<ST, NUM_COMPS>>>
|
||||
: SerializableTypeString<
|
||||
vtkm::cont::ArrayHandleGroupVec<vtkm::cont::ArrayHandle<T, ST>, NUM_COMPS>>
|
||||
{
|
||||
};
|
||||
}
|
||||
@ -413,11 +416,10 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template <typename AH, vtkm::IdComponent NUM_COMPS>
|
||||
template <typename T, vtkm::IdComponent NUM_COMPS, typename ST>
|
||||
struct Serialization<
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<typename AH::ValueType, NUM_COMPS>,
|
||||
vtkm::cont::internal::StorageTagGroupVec<AH, NUM_COMPS>>>
|
||||
: Serialization<vtkm::cont::ArrayHandleGroupVec<AH, NUM_COMPS>>
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<T, NUM_COMPS>, vtkm::cont::StorageTagGroupVec<ST, NUM_COMPS>>>
|
||||
: Serialization<vtkm::cont::ArrayHandleGroupVec<vtkm::cont::ArrayHandle<T, ST>, NUM_COMPS>>
|
||||
{
|
||||
};
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
#define vtk_m_cont_ArrayHandleGroupVecVariable_h
|
||||
|
||||
#include <vtkm/cont/Algorithm.h>
|
||||
#include <vtkm/cont/ArrayGetValues.h>
|
||||
#include <vtkm/cont/ArrayHandle.h>
|
||||
#include <vtkm/cont/ArrayHandleCast.h>
|
||||
#include <vtkm/cont/ArrayPortal.h>
|
||||
@ -69,22 +70,14 @@ public:
|
||||
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
VTKM_EXEC_CONT
|
||||
vtkm::Id GetNumberOfValues() const { return this->OffsetsPortal.GetNumberOfValues(); }
|
||||
vtkm::Id GetNumberOfValues() const { return this->OffsetsPortal.GetNumberOfValues() - 1; }
|
||||
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
VTKM_EXEC_CONT
|
||||
ValueType Get(vtkm::Id index) const
|
||||
{
|
||||
vtkm::Id offsetIndex = this->OffsetsPortal.Get(index);
|
||||
vtkm::Id nextOffsetIndex;
|
||||
if (index + 1 < this->GetNumberOfValues())
|
||||
{
|
||||
nextOffsetIndex = this->OffsetsPortal.Get(index + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
nextOffsetIndex = this->SourcePortal.GetNumberOfValues();
|
||||
}
|
||||
vtkm::Id nextOffsetIndex = this->OffsetsPortal.Get(index + 1);
|
||||
|
||||
return ValueType(this->SourcePortal,
|
||||
static_cast<vtkm::IdComponent>(nextOffsetIndex - offsetIndex),
|
||||
@ -161,30 +154,35 @@ namespace vtkm
|
||||
namespace cont
|
||||
{
|
||||
|
||||
namespace internal
|
||||
{
|
||||
|
||||
template <typename SourceArrayHandleType, typename OffsetsArrayHandleType>
|
||||
template <typename SourceStorageTag, typename OffsetsStorageTag>
|
||||
struct VTKM_ALWAYS_EXPORT StorageTagGroupVecVariable
|
||||
{
|
||||
};
|
||||
|
||||
template <typename SourceArrayHandleType, typename OffsetsArrayHandleType>
|
||||
class Storage<
|
||||
vtkm::VecFromPortal<typename SourceArrayHandleType::PortalControl>,
|
||||
vtkm::cont::internal::StorageTagGroupVecVariable<SourceArrayHandleType, OffsetsArrayHandleType>>
|
||||
namespace internal
|
||||
{
|
||||
using ComponentType = typename SourceArrayHandleType::ValueType;
|
||||
|
||||
template <typename SourcePortal, typename SourceStorageTag, typename OffsetsStorageTag>
|
||||
class Storage<vtkm::VecFromPortal<SourcePortal>,
|
||||
vtkm::cont::StorageTagGroupVecVariable<SourceStorageTag, OffsetsStorageTag>>
|
||||
{
|
||||
using ComponentType = typename SourcePortal::ValueType;
|
||||
using SourceArrayHandleType = vtkm::cont::ArrayHandle<ComponentType, SourceStorageTag>;
|
||||
using OffsetsArrayHandleType = vtkm::cont::ArrayHandle<vtkm::Id, OffsetsStorageTag>;
|
||||
|
||||
VTKM_STATIC_ASSERT_MSG(
|
||||
(std::is_same<SourcePortal, typename SourceArrayHandleType::WritePortalType>::value),
|
||||
"Used invalid SourcePortal type with expected SourceStorageTag.");
|
||||
|
||||
public:
|
||||
using ValueType = vtkm::VecFromPortal<typename SourceArrayHandleType::PortalControl>;
|
||||
using ValueType = vtkm::VecFromPortal<SourcePortal>;
|
||||
|
||||
using PortalType = vtkm::exec::internal::ArrayPortalGroupVecVariable<
|
||||
typename SourceArrayHandleType::PortalControl,
|
||||
typename OffsetsArrayHandleType::PortalConstControl>;
|
||||
typename SourceArrayHandleType::WritePortalType,
|
||||
typename OffsetsArrayHandleType::ReadPortalType>;
|
||||
using PortalConstType = vtkm::exec::internal::ArrayPortalGroupVecVariable<
|
||||
typename SourceArrayHandleType::PortalConstControl,
|
||||
typename OffsetsArrayHandleType::PortalConstControl>;
|
||||
typename SourceArrayHandleType::ReadPortalType,
|
||||
typename OffsetsArrayHandleType::ReadPortalType>;
|
||||
|
||||
VTKM_CONT
|
||||
Storage()
|
||||
@ -203,22 +201,20 @@ public:
|
||||
VTKM_CONT
|
||||
PortalType GetPortal()
|
||||
{
|
||||
return PortalType(this->SourceArray.GetPortalControl(),
|
||||
this->OffsetsArray.GetPortalConstControl());
|
||||
return PortalType(this->SourceArray.WritePortal(), this->OffsetsArray.ReadPortal());
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
PortalConstType GetPortalConst() const
|
||||
{
|
||||
return PortalConstType(this->SourceArray.GetPortalConstControl(),
|
||||
this->OffsetsArray.GetPortalConstControl());
|
||||
return PortalConstType(this->SourceArray.ReadPortal(), this->OffsetsArray.ReadPortal());
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
vtkm::Id GetNumberOfValues() const
|
||||
{
|
||||
VTKM_ASSERT(this->Valid);
|
||||
return this->OffsetsArray.GetNumberOfValues();
|
||||
return this->OffsetsArray.GetNumberOfValues() - 1;
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
@ -231,7 +227,7 @@ public:
|
||||
void Shrink(vtkm::Id numberOfValues)
|
||||
{
|
||||
VTKM_ASSERT(this->Valid);
|
||||
this->OffsetsArray.Shrink(numberOfValues);
|
||||
this->OffsetsArray.Shrink(numberOfValues + 1);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
@ -266,21 +262,25 @@ private:
|
||||
bool Valid;
|
||||
};
|
||||
|
||||
template <typename SourceArrayHandleType, typename OffsetsArrayHandleType, typename Device>
|
||||
class ArrayTransfer<
|
||||
vtkm::VecFromPortal<typename SourceArrayHandleType::PortalControl>,
|
||||
vtkm::cont::internal::StorageTagGroupVecVariable<SourceArrayHandleType, OffsetsArrayHandleType>,
|
||||
Device>
|
||||
template <typename SourcePortal,
|
||||
typename SourceStorageTag,
|
||||
typename OffsetsStorageTag,
|
||||
typename Device>
|
||||
class ArrayTransfer<vtkm::VecFromPortal<SourcePortal>,
|
||||
vtkm::cont::StorageTagGroupVecVariable<SourceStorageTag, OffsetsStorageTag>,
|
||||
Device>
|
||||
{
|
||||
public:
|
||||
using ComponentType = typename SourceArrayHandleType::ValueType;
|
||||
using ValueType = vtkm::VecFromPortal<typename SourceArrayHandleType::PortalControl>;
|
||||
using ComponentType = typename SourcePortal::ValueType;
|
||||
using ValueType = vtkm::VecFromPortal<SourcePortal>;
|
||||
|
||||
private:
|
||||
using StorageTag =
|
||||
vtkm::cont::internal::StorageTagGroupVecVariable<SourceArrayHandleType, OffsetsArrayHandleType>;
|
||||
using StorageTag = vtkm::cont::StorageTagGroupVecVariable<SourceStorageTag, OffsetsStorageTag>;
|
||||
using StorageType = vtkm::cont::internal::Storage<ValueType, StorageTag>;
|
||||
|
||||
using SourceArrayHandleType = vtkm::cont::ArrayHandle<ComponentType, SourceStorageTag>;
|
||||
using OffsetsArrayHandleType = vtkm::cont::ArrayHandle<vtkm::Id, OffsetsStorageTag>;
|
||||
|
||||
public:
|
||||
using PortalControl = typename StorageType::PortalType;
|
||||
using PortalConstControl = typename StorageType::PortalConstType;
|
||||
@ -300,30 +300,30 @@ public:
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
vtkm::Id GetNumberOfValues() const { return this->OffsetsArray.GetNumberOfValues(); }
|
||||
vtkm::Id GetNumberOfValues() const { return this->OffsetsArray.GetNumberOfValues() - 1; }
|
||||
|
||||
VTKM_CONT
|
||||
PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData))
|
||||
PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData), vtkm::cont::Token& token)
|
||||
{
|
||||
return PortalConstExecution(this->SourceArray.PrepareForInput(Device()),
|
||||
this->OffsetsArray.PrepareForInput(Device()));
|
||||
return PortalConstExecution(this->SourceArray.PrepareForInput(Device(), token),
|
||||
this->OffsetsArray.PrepareForInput(Device(), token));
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
PortalExecution PrepareForInPlace(bool vtkmNotUsed(updateData))
|
||||
PortalExecution PrepareForInPlace(bool vtkmNotUsed(updateData), vtkm::cont::Token& token)
|
||||
{
|
||||
return PortalExecution(this->SourceArray.PrepareForInPlace(Device()),
|
||||
this->OffsetsArray.PrepareForInput(Device()));
|
||||
return PortalExecution(this->SourceArray.PrepareForInPlace(Device(), token),
|
||||
this->OffsetsArray.PrepareForInput(Device(), token));
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
PortalExecution PrepareForOutput(vtkm::Id numberOfValues)
|
||||
PortalExecution PrepareForOutput(vtkm::Id numberOfValues, vtkm::cont::Token& token)
|
||||
{
|
||||
// Cannot reallocate an ArrayHandleGroupVecVariable
|
||||
VTKM_ASSERT(numberOfValues == this->OffsetsArray.GetNumberOfValues());
|
||||
VTKM_ASSERT(numberOfValues == this->OffsetsArray.GetNumberOfValues() - 1);
|
||||
return PortalExecution(
|
||||
this->SourceArray.PrepareForOutput(this->SourceArray.GetNumberOfValues(), Device()),
|
||||
this->OffsetsArray.PrepareForInput(Device()));
|
||||
this->SourceArray.PrepareForOutput(this->SourceArray.GetNumberOfValues(), Device(), token),
|
||||
this->OffsetsArray.PrepareForInput(Device(), token));
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
@ -364,7 +364,7 @@ private:
|
||||
/// value contains values from the last offset to the end of the array.
|
||||
///
|
||||
/// For example, if you have an array handle with the 9 values
|
||||
/// 0,1,2,3,4,5,6,7,8 an offsets array handle with the 3 values 0,4,6 and give
|
||||
/// 0,1,2,3,4,5,6,7,8 an offsets array handle with the 4 values 0,4,6,9 and give
|
||||
/// them to an \c ArrayHandleGroupVecVariable, you get an array that looks like
|
||||
/// it contains three values of Vec-like objects with the data [0,1,2,3],
|
||||
/// [4,5], and [6,7,8].
|
||||
@ -386,21 +386,25 @@ private:
|
||||
template <typename SourceArrayHandleType, typename OffsetsArrayHandleType>
|
||||
class ArrayHandleGroupVecVariable
|
||||
: public vtkm::cont::ArrayHandle<
|
||||
vtkm::VecFromPortal<typename SourceArrayHandleType::PortalControl>,
|
||||
vtkm::cont::internal::StorageTagGroupVecVariable<SourceArrayHandleType,
|
||||
OffsetsArrayHandleType>>
|
||||
vtkm::VecFromPortal<typename SourceArrayHandleType::WritePortalType>,
|
||||
vtkm::cont::StorageTagGroupVecVariable<typename SourceArrayHandleType::StorageTag,
|
||||
typename OffsetsArrayHandleType::StorageTag>>
|
||||
{
|
||||
VTKM_IS_ARRAY_HANDLE(SourceArrayHandleType);
|
||||
VTKM_IS_ARRAY_HANDLE(OffsetsArrayHandleType);
|
||||
|
||||
VTKM_STATIC_ASSERT_MSG(
|
||||
(std::is_same<vtkm::Id, typename OffsetsArrayHandleType::ValueType>::value),
|
||||
"ArrayHandleGroupVecVariable's offsets array must contain vtkm::Id values.");
|
||||
|
||||
public:
|
||||
VTKM_ARRAY_HANDLE_SUBCLASS(
|
||||
ArrayHandleGroupVecVariable,
|
||||
(ArrayHandleGroupVecVariable<SourceArrayHandleType, OffsetsArrayHandleType>),
|
||||
(vtkm::cont::ArrayHandle<
|
||||
vtkm::VecFromPortal<typename SourceArrayHandleType::PortalControl>,
|
||||
vtkm::cont::internal::StorageTagGroupVecVariable<SourceArrayHandleType,
|
||||
OffsetsArrayHandleType>>));
|
||||
vtkm::VecFromPortal<typename SourceArrayHandleType::WritePortalType>,
|
||||
vtkm::cont::StorageTagGroupVecVariable<typename SourceArrayHandleType::StorageTag,
|
||||
typename OffsetsArrayHandleType::StorageTag>>));
|
||||
|
||||
using ComponentType = typename SourceArrayHandleType::ValueType;
|
||||
|
||||
@ -452,10 +456,12 @@ VTKM_CONT void ConvertNumComponentsToOffsets(
|
||||
vtkm::Id& sourceArraySize,
|
||||
vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny())
|
||||
{
|
||||
using namespace vtkm::cont;
|
||||
VTKM_IS_ARRAY_HANDLE(NumComponentsArrayType);
|
||||
|
||||
sourceArraySize = vtkm::cont::Algorithm::ScanExclusive(
|
||||
device, vtkm::cont::make_ArrayHandleCast<vtkm::Id>(numComponentsArray), offsetsArray);
|
||||
Algorithm::ScanExtended(device, make_ArrayHandleCast<vtkm::Id>(numComponentsArray), offsetsArray);
|
||||
|
||||
sourceArraySize = ArrayGetValue(offsetsArray.GetNumberOfValues() - 1, offsetsArray);
|
||||
}
|
||||
|
||||
template <typename NumComponentsArrayType, typename OffsetsStorage>
|
||||
@ -466,8 +472,8 @@ VTKM_CONT void ConvertNumComponentsToOffsets(
|
||||
{
|
||||
VTKM_IS_ARRAY_HANDLE(NumComponentsArrayType);
|
||||
|
||||
vtkm::Id dummy;
|
||||
vtkm::cont::ConvertNumComponentsToOffsets(numComponentsArray, offsetsArray, dummy, device);
|
||||
vtkm::cont::Algorithm::ScanExtended(
|
||||
device, vtkm::cont::make_ArrayHandleCast<vtkm::Id>(numComponentsArray), offsetsArray);
|
||||
}
|
||||
|
||||
template <typename NumComponentsArrayType>
|
||||
@ -516,11 +522,13 @@ struct SerializableTypeString<vtkm::cont::ArrayHandleGroupVecVariable<SAH, OAH>>
|
||||
}
|
||||
};
|
||||
|
||||
template <typename SAH, typename OAH>
|
||||
template <typename SP, typename SST, typename OST>
|
||||
struct SerializableTypeString<
|
||||
vtkm::cont::ArrayHandle<vtkm::VecFromPortal<typename SAH::PortalControl>,
|
||||
vtkm::cont::internal::StorageTagGroupVecVariable<SAH, OAH>>>
|
||||
: SerializableTypeString<vtkm::cont::ArrayHandleGroupVecVariable<SAH, OAH>>
|
||||
vtkm::cont::ArrayHandle<vtkm::VecFromPortal<SP>,
|
||||
vtkm::cont::StorageTagGroupVecVariable<SST, OST>>>
|
||||
: SerializableTypeString<
|
||||
vtkm::cont::ArrayHandleGroupVecVariable<vtkm::cont::ArrayHandle<typename SP::ValueType, SST>,
|
||||
vtkm::cont::ArrayHandle<vtkm::Id, OST>>>
|
||||
{
|
||||
};
|
||||
}
|
||||
@ -555,11 +563,12 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template <typename SAH, typename OAH>
|
||||
struct Serialization<
|
||||
vtkm::cont::ArrayHandle<vtkm::VecFromPortal<typename SAH::PortalControl>,
|
||||
vtkm::cont::internal::StorageTagGroupVecVariable<SAH, OAH>>>
|
||||
: Serialization<vtkm::cont::ArrayHandleGroupVecVariable<SAH, OAH>>
|
||||
template <typename SP, typename SST, typename OST>
|
||||
struct Serialization<vtkm::cont::ArrayHandle<vtkm::VecFromPortal<SP>,
|
||||
vtkm::cont::StorageTagGroupVecVariable<SST, OST>>>
|
||||
: Serialization<
|
||||
vtkm::cont::ArrayHandleGroupVecVariable<vtkm::cont::ArrayHandle<typename SP::ValueType, SST>,
|
||||
vtkm::cont::ArrayHandle<vtkm::Id, OST>>>
|
||||
{
|
||||
};
|
||||
} // diy
|
||||
|
@ -32,6 +32,7 @@ struct ArrayHandleImplicitTraits
|
||||
using ValueType = decltype(FunctorType{}(vtkm::Id{}));
|
||||
using StorageTag = vtkm::cont::StorageTagImplicit<ArrayPortalImplicit<FunctorType>>;
|
||||
using Superclass = vtkm::cont::ArrayHandle<ValueType, StorageTag>;
|
||||
using StorageType = vtkm::cont::internal::Storage<ValueType, StorageTag>;
|
||||
};
|
||||
|
||||
/// \brief An array portal that returns the result of a functor
|
||||
@ -74,12 +75,6 @@ public:
|
||||
VTKM_EXEC_CONT
|
||||
ValueType Get(vtkm::Id index) const { return this->Functor(index); }
|
||||
|
||||
using IteratorType =
|
||||
vtkm::cont::internal::IteratorFromArrayPortal<ArrayPortalImplicit<FunctorType>>;
|
||||
|
||||
VTKM_CONT
|
||||
IteratorType GetIteratorBegin() const { return IteratorType(*this); }
|
||||
|
||||
private:
|
||||
FunctorType Functor;
|
||||
vtkm::Id NumberOfValues;
|
||||
@ -108,7 +103,7 @@ public:
|
||||
|
||||
VTKM_CONT
|
||||
ArrayHandleImplicit(FunctorType functor, vtkm::Id length)
|
||||
: Superclass(typename Superclass::PortalConstControl(functor, length))
|
||||
: Superclass(typename ArrayTraits::StorageType::PortalType(functor, length))
|
||||
{
|
||||
}
|
||||
};
|
||||
@ -168,7 +163,7 @@ public:
|
||||
static VTKM_CONT void save(BinaryBuffer& bb, const BaseType& obj)
|
||||
{
|
||||
vtkmdiy::save(bb, obj.GetNumberOfValues());
|
||||
vtkmdiy::save(bb, obj.GetPortalConstControl().GetFunctor());
|
||||
vtkmdiy::save(bb, obj.ReadPortal().GetFunctor());
|
||||
}
|
||||
|
||||
static VTKM_CONT void load(BinaryBuffer& bb, BaseType& obj)
|
||||
|
@ -17,7 +17,11 @@ namespace vtkm
|
||||
namespace cont
|
||||
{
|
||||
|
||||
namespace detail
|
||||
struct VTKM_ALWAYS_EXPORT StorageTagIndex
|
||||
{
|
||||
};
|
||||
|
||||
namespace internal
|
||||
{
|
||||
|
||||
struct VTKM_ALWAYS_EXPORT IndexFunctor
|
||||
@ -26,7 +30,25 @@ struct VTKM_ALWAYS_EXPORT IndexFunctor
|
||||
vtkm::Id operator()(vtkm::Id index) const { return index; }
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
using StorageTagIndexSuperclass =
|
||||
typename vtkm::cont::ArrayHandleImplicit<IndexFunctor>::StorageTag;
|
||||
|
||||
template <>
|
||||
struct Storage<vtkm::Id, vtkm::cont::StorageTagIndex> : Storage<vtkm::Id, StorageTagIndexSuperclass>
|
||||
{
|
||||
using Superclass = Storage<vtkm::Id, StorageTagIndexSuperclass>;
|
||||
using Superclass::Superclass;
|
||||
};
|
||||
|
||||
template <typename Device>
|
||||
struct ArrayTransfer<vtkm::Id, vtkm::cont::StorageTagIndex, Device>
|
||||
: ArrayTransfer<vtkm::Id, StorageTagIndexSuperclass, Device>
|
||||
{
|
||||
using Superclass = ArrayTransfer<vtkm::Id, StorageTagIndexSuperclass, Device>;
|
||||
using Superclass::Superclass;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
/// \brief An implicit array handle containing the its own indices.
|
||||
///
|
||||
@ -34,18 +56,27 @@ struct VTKM_ALWAYS_EXPORT IndexFunctor
|
||||
/// 0, 1, 2, 3,... to a specified size. Every value in the array is the same
|
||||
/// as the index to that value.
|
||||
///
|
||||
class ArrayHandleIndex : public vtkm::cont::ArrayHandleImplicit<detail::IndexFunctor>
|
||||
class ArrayHandleIndex : public vtkm::cont::ArrayHandle<vtkm::Id, StorageTagIndex>
|
||||
{
|
||||
public:
|
||||
VTKM_ARRAY_HANDLE_SUBCLASS_NT(ArrayHandleIndex,
|
||||
(vtkm::cont::ArrayHandleImplicit<detail::IndexFunctor>));
|
||||
(vtkm::cont::ArrayHandle<vtkm::Id, StorageTagIndex>));
|
||||
|
||||
VTKM_CONT
|
||||
ArrayHandleIndex(vtkm::Id length)
|
||||
: Superclass(detail::IndexFunctor(), length)
|
||||
: Superclass(
|
||||
typename internal::Storage<vtkm::Id, StorageTagIndex>::PortalType(internal::IndexFunctor{},
|
||||
length))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/// A convenience function for creating an ArrayHandleIndex. It takes the
|
||||
/// size of the array and generates an array holding vtkm::Id from [0, size - 1]
|
||||
VTKM_CONT inline vtkm::cont::ArrayHandleIndex make_ArrayHandleIndex(vtkm::Id length)
|
||||
{
|
||||
return vtkm::cont::ArrayHandleIndex(length);
|
||||
}
|
||||
}
|
||||
} // namespace vtkm::cont
|
||||
|
||||
@ -59,14 +90,14 @@ namespace cont
|
||||
{
|
||||
|
||||
template <>
|
||||
struct SerializableTypeString<vtkm::cont::detail::IndexFunctor>
|
||||
struct SerializableTypeString<vtkm::cont::ArrayHandleIndex>
|
||||
{
|
||||
static VTKM_CONT const std::string Get() { return "AH_IndexFunctor"; }
|
||||
static VTKM_CONT const std::string Get() { return "AH_Index"; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct SerializableTypeString<vtkm::cont::ArrayHandleIndex>
|
||||
: SerializableTypeString<vtkm::cont::ArrayHandleImplicit<vtkm::cont::detail::IndexFunctor>>
|
||||
struct SerializableTypeString<vtkm::cont::ArrayHandle<vtkm::Id, vtkm::cont::StorageTagIndex>>
|
||||
: SerializableTypeString<vtkm::cont::ArrayHandleIndex>
|
||||
{
|
||||
};
|
||||
}
|
||||
@ -76,19 +107,31 @@ namespace mangled_diy_namespace
|
||||
{
|
||||
|
||||
template <>
|
||||
struct Serialization<vtkm::cont::detail::IndexFunctor>
|
||||
struct Serialization<vtkm::cont::ArrayHandleIndex>
|
||||
{
|
||||
static VTKM_CONT void save(BinaryBuffer&, const vtkm::cont::detail::IndexFunctor&) {}
|
||||
private:
|
||||
using BaseType = vtkm::cont::ArrayHandle<vtkm::Id, vtkm::cont::StorageTagIndex>;
|
||||
|
||||
static VTKM_CONT void load(BinaryBuffer&, vtkm::cont::detail::IndexFunctor&) {}
|
||||
public:
|
||||
static VTKM_CONT void save(BinaryBuffer& bb, const BaseType& obj)
|
||||
{
|
||||
vtkmdiy::save(bb, obj.GetNumberOfValues());
|
||||
}
|
||||
|
||||
static VTKM_CONT void load(BinaryBuffer& bb, BaseType& obj)
|
||||
{
|
||||
vtkm::Id length = 0;
|
||||
vtkmdiy::load(bb, length);
|
||||
|
||||
obj = vtkm::cont::ArrayHandleIndex(length);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Serialization<vtkm::cont::ArrayHandleIndex>
|
||||
: Serialization<vtkm::cont::ArrayHandleImplicit<vtkm::cont::detail::IndexFunctor>>
|
||||
struct Serialization<vtkm::cont::ArrayHandle<vtkm::Id, vtkm::cont::StorageTagIndex>>
|
||||
: Serialization<vtkm::cont::ArrayHandleIndex>
|
||||
{
|
||||
};
|
||||
|
||||
} // diy
|
||||
/// @endcond SERIALIZATION
|
||||
|
||||
|
@ -10,7 +10,6 @@
|
||||
#ifndef vtk_m_cont_ArrayHandleMultiplexer_h
|
||||
#define vtk_m_cont_ArrayHandleMultiplexer_h
|
||||
|
||||
#include <vtkm/TypeListTag.h>
|
||||
#include <vtkm/TypeTraits.h>
|
||||
|
||||
#include <vtkm/internal/Variant.h>
|
||||
@ -19,7 +18,6 @@
|
||||
#include <vtkm/cont/ArrayHandleCartesianProduct.h>
|
||||
#include <vtkm/cont/ArrayHandleCast.h>
|
||||
#include <vtkm/cont/ArrayHandleUniformPointCoordinates.h>
|
||||
#include <vtkm/cont/StorageListTag.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
@ -182,10 +180,10 @@ private:
|
||||
using StorageToArrayHandle = vtkm::cont::ArrayHandle<ValueType, S>;
|
||||
|
||||
template <typename S>
|
||||
using StorageToPortalControl = typename StorageToArrayHandle<S>::PortalControl;
|
||||
using StorageToPortalControl = typename StorageToArrayHandle<S>::WritePortalType;
|
||||
|
||||
template <typename S>
|
||||
using StorageToPortalConstControl = typename StorageToArrayHandle<S>::PortalConstControl;
|
||||
using StorageToPortalConstControl = typename StorageToArrayHandle<S>::ReadPortalType;
|
||||
|
||||
using ArrayHandleVariantType = vtkm::internal::Variant<StorageToArrayHandle<StorageTags>...>;
|
||||
ArrayHandleVariantType ArrayHandleVariant;
|
||||
@ -233,7 +231,7 @@ private:
|
||||
template <typename ArrayHandleType>
|
||||
VTKM_CONT PortalType operator()(ArrayHandleType&& array) const
|
||||
{
|
||||
return PortalType(array.GetPortalControl());
|
||||
return PortalType(array.WritePortal());
|
||||
}
|
||||
};
|
||||
|
||||
@ -242,7 +240,7 @@ private:
|
||||
template <typename ArrayHandleType>
|
||||
VTKM_CONT PortalConstType operator()(ArrayHandleType&& array) const
|
||||
{
|
||||
return PortalConstType(array.GetPortalConstControl());
|
||||
return PortalConstType(array.ReadPortal());
|
||||
}
|
||||
};
|
||||
|
||||
@ -356,20 +354,24 @@ public:
|
||||
|
||||
VTKM_CONT vtkm::Id GetNumberOfValues() const { return this->StoragePointer->GetNumberOfValues(); }
|
||||
|
||||
VTKM_CONT PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData))
|
||||
VTKM_CONT PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData),
|
||||
vtkm::cont::Token& token)
|
||||
{
|
||||
return this->StoragePointer->GetArrayHandleVariant().CastAndCall(PrepareForInputFunctor{});
|
||||
return this->StoragePointer->GetArrayHandleVariant().CastAndCall(PrepareForInputFunctor{},
|
||||
token);
|
||||
}
|
||||
|
||||
VTKM_CONT PortalExecution PrepareForInPlace(bool vtkmNotUsed(updateData))
|
||||
VTKM_CONT PortalExecution PrepareForInPlace(bool vtkmNotUsed(updateData),
|
||||
vtkm::cont::Token& token)
|
||||
{
|
||||
return this->StoragePointer->GetArrayHandleVariant().CastAndCall(PrepareForInPlaceFunctor{});
|
||||
return this->StoragePointer->GetArrayHandleVariant().CastAndCall(PrepareForInPlaceFunctor{},
|
||||
token);
|
||||
}
|
||||
|
||||
VTKM_CONT PortalExecution PrepareForOutput(vtkm::Id numberOfValues)
|
||||
VTKM_CONT PortalExecution PrepareForOutput(vtkm::Id numberOfValues, vtkm::cont::Token& token)
|
||||
{
|
||||
return this->StoragePointer->GetArrayHandleVariant().CastAndCall(PrepareForOutputFunctor{},
|
||||
numberOfValues);
|
||||
return this->StoragePointer->GetArrayHandleVariant().CastAndCall(
|
||||
PrepareForOutputFunctor{}, numberOfValues, token);
|
||||
}
|
||||
|
||||
VTKM_CONT void RetrieveOutputData(StorageType* vtkmNotUsed(storage)) const
|
||||
@ -395,27 +397,30 @@ private:
|
||||
struct PrepareForInputFunctor
|
||||
{
|
||||
template <typename ArrayHandleType>
|
||||
VTKM_CONT PortalConstExecution operator()(const ArrayHandleType& array)
|
||||
VTKM_CONT PortalConstExecution operator()(const ArrayHandleType& array,
|
||||
vtkm::cont::Token& token)
|
||||
{
|
||||
return PortalConstExecution(array.PrepareForInput(Device{}));
|
||||
return PortalConstExecution(array.PrepareForInput(Device{}, token));
|
||||
}
|
||||
};
|
||||
|
||||
struct PrepareForInPlaceFunctor
|
||||
{
|
||||
template <typename ArrayHandleType>
|
||||
VTKM_CONT PortalExecution operator()(ArrayHandleType& array)
|
||||
VTKM_CONT PortalExecution operator()(ArrayHandleType& array, vtkm::cont::Token& token)
|
||||
{
|
||||
return PortalExecution(array.PrepareForInPlace(Device{}));
|
||||
return PortalExecution(array.PrepareForInPlace(Device{}, token));
|
||||
}
|
||||
};
|
||||
|
||||
struct PrepareForOutputFunctor
|
||||
{
|
||||
template <typename ArrayHandleType>
|
||||
VTKM_CONT PortalExecution operator()(ArrayHandleType& array, vtkm::Id numberOfValues)
|
||||
VTKM_CONT PortalExecution operator()(ArrayHandleType& array,
|
||||
vtkm::Id numberOfValues,
|
||||
vtkm::cont::Token& token)
|
||||
{
|
||||
return PortalExecution(array.PrepareForOutput(numberOfValues, Device{}));
|
||||
return PortalExecution(array.PrepareForOutput(numberOfValues, Device{}, token));
|
||||
}
|
||||
};
|
||||
};
|
||||
@ -534,8 +539,22 @@ public:
|
||||
/// the list tag must be some type of \c ArrayHandle. The templated type gets aliased to
|
||||
/// an \c ArrayHandleMultiplexer that can store any of these ArrayHandle types.
|
||||
///
|
||||
/// Deprecated. Use `ArrayHandleMultiplexerFromList` instead.
|
||||
///
|
||||
template <typename ListTag>
|
||||
using ArrayHandleMultiplexerFromListTag = vtkm::ListTagApply<ListTag, ArrayHandleMultiplexer>;
|
||||
using ArrayHandleMultiplexerFromListTag VTKM_DEPRECATED(
|
||||
1.6,
|
||||
"vtkm::ListTag is no longer supported. Use vtkm::List instead.") =
|
||||
vtkm::ListApply<ListTag, ArrayHandleMultiplexer>;
|
||||
|
||||
/// \brief Converts a`vtkm::List` to an `ArrayHandleMultiplexer`
|
||||
///
|
||||
/// The argument of this template must be a `vtkm::List` and furthermore all the types in
|
||||
/// the list tag must be some type of \c ArrayHandle. The templated type gets aliased to
|
||||
/// an \c ArrayHandleMultiplexer that can store any of these ArrayHandle types.
|
||||
///
|
||||
template <typename List>
|
||||
using ArrayHandleMultiplexerFromList = vtkm::ListApply<List, ArrayHandleMultiplexer>;
|
||||
|
||||
} // namespace cont
|
||||
|
||||
|
@ -100,30 +100,35 @@ namespace vtkm
|
||||
namespace cont
|
||||
{
|
||||
|
||||
namespace internal
|
||||
{
|
||||
|
||||
template <typename IndexArrayType, typename ValueArrayType>
|
||||
template <typename IndexStorageTag, typename ValueStorageTag>
|
||||
struct VTKM_ALWAYS_EXPORT StorageTagPermutation
|
||||
{
|
||||
};
|
||||
|
||||
template <typename IndexArrayType, typename ValueArrayType>
|
||||
class Storage<typename ValueArrayType::ValueType,
|
||||
StorageTagPermutation<IndexArrayType, ValueArrayType>>
|
||||
namespace internal
|
||||
{
|
||||
VTKM_IS_ARRAY_HANDLE(IndexArrayType);
|
||||
VTKM_IS_ARRAY_HANDLE(ValueArrayType);
|
||||
|
||||
template <typename T, typename IndexStorageTag, typename ValueStorageTag>
|
||||
class Storage<T, vtkm::cont::StorageTagPermutation<IndexStorageTag, ValueStorageTag>>
|
||||
{
|
||||
VTKM_STATIC_ASSERT_MSG(
|
||||
(vtkm::cont::internal::IsValidArrayHandle<vtkm::Id, IndexStorageTag>::value),
|
||||
"Invalid index storage tag.");
|
||||
VTKM_STATIC_ASSERT_MSG((vtkm::cont::internal::IsValidArrayHandle<T, ValueStorageTag>::value),
|
||||
"Invalid value storage tag.");
|
||||
|
||||
public:
|
||||
using ValueType = typename ValueArrayType::ValueType;
|
||||
using IndexArrayType = vtkm::cont::ArrayHandle<vtkm::Id, IndexStorageTag>;
|
||||
using ValueArrayType = vtkm::cont::ArrayHandle<T, ValueStorageTag>;
|
||||
|
||||
using ValueType = T;
|
||||
|
||||
using PortalType =
|
||||
vtkm::exec::internal::ArrayPortalPermutation<typename IndexArrayType::PortalConstControl,
|
||||
typename ValueArrayType::PortalControl>;
|
||||
vtkm::exec::internal::ArrayPortalPermutation<typename IndexArrayType::ReadPortalType,
|
||||
typename ValueArrayType::WritePortalType>;
|
||||
using PortalConstType =
|
||||
vtkm::exec::internal::ArrayPortalPermutation<typename IndexArrayType::PortalConstControl,
|
||||
typename ValueArrayType::PortalConstControl>;
|
||||
vtkm::exec::internal::ArrayPortalPermutation<typename IndexArrayType::ReadPortalType,
|
||||
typename ValueArrayType::ReadPortalType>;
|
||||
|
||||
VTKM_CONT
|
||||
Storage()
|
||||
@ -143,16 +148,14 @@ public:
|
||||
PortalType GetPortal()
|
||||
{
|
||||
VTKM_ASSERT(this->Valid);
|
||||
return PortalType(this->IndexArray.GetPortalConstControl(),
|
||||
this->ValueArray.GetPortalControl());
|
||||
return PortalType(this->IndexArray.ReadPortal(), this->ValueArray.WritePortal());
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
PortalConstType GetPortalConst() const
|
||||
{
|
||||
VTKM_ASSERT(this->Valid);
|
||||
return PortalConstType(this->IndexArray.GetPortalConstControl(),
|
||||
this->ValueArray.GetPortalConstControl());
|
||||
return PortalConstType(this->IndexArray.ReadPortal(), this->ValueArray.ReadPortal());
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
@ -194,18 +197,19 @@ private:
|
||||
bool Valid;
|
||||
};
|
||||
|
||||
template <typename IndexArrayType, typename ValueArrayType, typename Device>
|
||||
class ArrayTransfer<typename ValueArrayType::ValueType,
|
||||
StorageTagPermutation<IndexArrayType, ValueArrayType>,
|
||||
Device>
|
||||
template <typename T, typename IndexStorageTag, typename ValueStorageTag, typename Device>
|
||||
class ArrayTransfer<T, StorageTagPermutation<IndexStorageTag, ValueStorageTag>, Device>
|
||||
{
|
||||
public:
|
||||
using ValueType = typename ValueArrayType::ValueType;
|
||||
using ValueType = T;
|
||||
|
||||
private:
|
||||
using StorageTag = StorageTagPermutation<IndexArrayType, ValueArrayType>;
|
||||
using StorageTag = StorageTagPermutation<IndexStorageTag, ValueStorageTag>;
|
||||
using StorageType = vtkm::cont::internal::Storage<ValueType, StorageTag>;
|
||||
|
||||
using IndexArrayType = typename StorageType::IndexArrayType;
|
||||
using ValueArrayType = typename StorageType::ValueArrayType;
|
||||
|
||||
public:
|
||||
using PortalControl = typename StorageType::PortalType;
|
||||
using PortalConstControl = typename StorageType::PortalConstType;
|
||||
@ -228,21 +232,21 @@ public:
|
||||
vtkm::Id GetNumberOfValues() const { return this->IndexArray.GetNumberOfValues(); }
|
||||
|
||||
VTKM_CONT
|
||||
PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData))
|
||||
PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData), vtkm::cont::Token& token)
|
||||
{
|
||||
return PortalConstExecution(this->IndexArray.PrepareForInput(Device()),
|
||||
this->ValueArray.PrepareForInput(Device()));
|
||||
return PortalConstExecution(this->IndexArray.PrepareForInput(Device(), token),
|
||||
this->ValueArray.PrepareForInput(Device(), token));
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
PortalExecution PrepareForInPlace(bool vtkmNotUsed(updateData))
|
||||
PortalExecution PrepareForInPlace(bool vtkmNotUsed(updateData), vtkm::cont::Token& token)
|
||||
{
|
||||
return PortalExecution(this->IndexArray.PrepareForInput(Device()),
|
||||
this->ValueArray.PrepareForInPlace(Device()));
|
||||
return PortalExecution(this->IndexArray.PrepareForInput(Device(), token),
|
||||
this->ValueArray.PrepareForInPlace(Device(), token));
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
PortalExecution PrepareForOutput(vtkm::Id numberOfValues)
|
||||
PortalExecution PrepareForOutput(vtkm::Id numberOfValues, vtkm::cont::Token& token)
|
||||
{
|
||||
if (numberOfValues != this->GetNumberOfValues())
|
||||
{
|
||||
@ -264,8 +268,8 @@ public:
|
||||
}
|
||||
|
||||
return PortalExecution(
|
||||
this->IndexArray.PrepareForInput(Device()),
|
||||
this->ValueArray.PrepareForOutput(this->ValueArray.GetNumberOfValues(), Device()));
|
||||
this->IndexArray.PrepareForInput(Device(), token),
|
||||
this->ValueArray.PrepareForOutput(this->ValueArray.GetNumberOfValues(), Device(), token));
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
@ -323,7 +327,8 @@ template <typename IndexArrayHandleType, typename ValueArrayHandleType>
|
||||
class ArrayHandlePermutation
|
||||
: public vtkm::cont::ArrayHandle<
|
||||
typename ValueArrayHandleType::ValueType,
|
||||
internal::StorageTagPermutation<IndexArrayHandleType, ValueArrayHandleType>>
|
||||
vtkm::cont::StorageTagPermutation<typename IndexArrayHandleType::StorageTag,
|
||||
typename ValueArrayHandleType::StorageTag>>
|
||||
{
|
||||
// If the following line gives a compile error, then the ArrayHandleType
|
||||
// template argument is not a valid ArrayHandle type.
|
||||
@ -336,7 +341,8 @@ public:
|
||||
(ArrayHandlePermutation<IndexArrayHandleType, ValueArrayHandleType>),
|
||||
(vtkm::cont::ArrayHandle<
|
||||
typename ValueArrayHandleType::ValueType,
|
||||
internal::StorageTagPermutation<IndexArrayHandleType, ValueArrayHandleType>>));
|
||||
vtkm::cont::StorageTagPermutation<typename IndexArrayHandleType::StorageTag,
|
||||
typename ValueArrayHandleType::StorageTag>>));
|
||||
|
||||
private:
|
||||
using StorageType = vtkm::cont::internal::Storage<ValueType, StorageTag>;
|
||||
@ -382,11 +388,12 @@ struct SerializableTypeString<vtkm::cont::ArrayHandlePermutation<IdxAH, ValAH>>
|
||||
}
|
||||
};
|
||||
|
||||
template <typename IdxAH, typename ValAH>
|
||||
template <typename T, typename IdxST, typename ValST>
|
||||
struct SerializableTypeString<
|
||||
vtkm::cont::ArrayHandle<typename ValAH::ValueType,
|
||||
vtkm::cont::internal::StorageTagPermutation<IdxAH, ValAH>>>
|
||||
: SerializableTypeString<vtkm::cont::ArrayHandlePermutation<IdxAH, ValAH>>
|
||||
vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagPermutation<IdxST, ValST>>>
|
||||
: SerializableTypeString<
|
||||
vtkm::cont::ArrayHandlePermutation<vtkm::cont::ArrayHandle<vtkm::Id, IdxST>,
|
||||
vtkm::cont::ArrayHandle<T, ValST>>>
|
||||
{
|
||||
};
|
||||
}
|
||||
@ -422,11 +429,10 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template <typename IdxAH, typename ValAH>
|
||||
struct Serialization<
|
||||
vtkm::cont::ArrayHandle<typename ValAH::ValueType,
|
||||
vtkm::cont::internal::StorageTagPermutation<IdxAH, ValAH>>>
|
||||
: Serialization<vtkm::cont::ArrayHandlePermutation<IdxAH, ValAH>>
|
||||
template <typename T, typename IdxST, typename ValST>
|
||||
struct Serialization<vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagPermutation<IdxST, ValST>>>
|
||||
: Serialization<vtkm::cont::ArrayHandlePermutation<vtkm::cont::ArrayHandle<vtkm::Id, IdxST>,
|
||||
vtkm::cont::ArrayHandle<T, ValST>>>
|
||||
{
|
||||
};
|
||||
|
||||
|
@ -15,6 +15,8 @@
|
||||
#include <vtkm/cont/ErrorBadType.h>
|
||||
#include <vtkm/cont/ErrorBadValue.h>
|
||||
|
||||
#include <vtkm/Deprecated.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace cont
|
||||
@ -70,21 +72,59 @@ private:
|
||||
};
|
||||
}
|
||||
|
||||
template <typename ArrayHandleType>
|
||||
class StorageTagReverse
|
||||
template <typename StorageTag>
|
||||
class VTKM_ALWAYS_EXPORT StorageTagReverse
|
||||
{
|
||||
};
|
||||
|
||||
namespace internal
|
||||
{
|
||||
|
||||
template <typename ArrayHandleType>
|
||||
class Storage<typename ArrayHandleType::ValueType, StorageTagReverse<ArrayHandleType>>
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <typename T, typename ArrayOrStorage, bool IsArrayType>
|
||||
struct ReverseTypeArgImpl;
|
||||
|
||||
template <typename T, typename Storage>
|
||||
struct ReverseTypeArgImpl<T, Storage, false>
|
||||
{
|
||||
using StorageTag = Storage;
|
||||
using ArrayHandle = vtkm::cont::ArrayHandle<T, StorageTag>;
|
||||
};
|
||||
|
||||
template <typename T, typename Array>
|
||||
struct ReverseTypeArgImpl<T, Array, true>
|
||||
{
|
||||
VTKM_STATIC_ASSERT_MSG((std::is_same<T, typename Array::ValueType>::value),
|
||||
"Used array with wrong type in ArrayHandleReverse.");
|
||||
using StorageTag VTKM_DEPRECATED(
|
||||
1.6,
|
||||
"Use storage tag instead of array handle in StorageTagReverse.") = typename Array::StorageTag;
|
||||
using ArrayHandle VTKM_DEPRECATED(
|
||||
1.6,
|
||||
"Use storage tag instead of array handle in StorageTagReverse.") =
|
||||
vtkm::cont::ArrayHandle<T, typename Array::StorageTag>;
|
||||
};
|
||||
|
||||
template <typename T, typename ArrayOrStorage>
|
||||
struct ReverseTypeArg
|
||||
: ReverseTypeArgImpl<T,
|
||||
ArrayOrStorage,
|
||||
vtkm::cont::internal::ArrayHandleCheck<ArrayOrStorage>::type::value>
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename T, typename ST>
|
||||
class Storage<T, StorageTagReverse<ST>>
|
||||
{
|
||||
public:
|
||||
using ValueType = typename ArrayHandleType::ValueType;
|
||||
using PortalType = ArrayPortalReverse<typename ArrayHandleType::PortalControl>;
|
||||
using PortalConstType = ArrayPortalReverse<typename ArrayHandleType::PortalConstControl>;
|
||||
using ValueType = T;
|
||||
using ArrayHandleType = typename detail::ReverseTypeArg<T, ST>::ArrayHandle;
|
||||
using PortalType = ArrayPortalReverse<typename ArrayHandleType::WritePortalType>;
|
||||
using PortalConstType = ArrayPortalReverse<typename ArrayHandleType::ReadPortalType>;
|
||||
|
||||
VTKM_CONT
|
||||
Storage()
|
||||
@ -100,13 +140,10 @@ public:
|
||||
|
||||
|
||||
VTKM_CONT
|
||||
PortalConstType GetPortalConst() const
|
||||
{
|
||||
return PortalConstType(this->Array.GetPortalConstControl());
|
||||
}
|
||||
PortalConstType GetPortalConst() const { return PortalConstType(this->Array.ReadPortal()); }
|
||||
|
||||
VTKM_CONT
|
||||
PortalType GetPortal() { return PortalType(this->Array.GetPortalControl()); }
|
||||
PortalType GetPortal() { return PortalType(this->Array.WritePortal()); }
|
||||
|
||||
VTKM_CONT
|
||||
vtkm::Id GetNumberOfValues() const { return this->Array.GetNumberOfValues(); }
|
||||
@ -132,17 +169,16 @@ private:
|
||||
ArrayHandleType Array;
|
||||
}; // class storage
|
||||
|
||||
template <typename ArrayHandleType, typename Device>
|
||||
class ArrayTransfer<typename ArrayHandleType::ValueType, StorageTagReverse<ArrayHandleType>, Device>
|
||||
template <typename T, typename ST, typename Device>
|
||||
class ArrayTransfer<T, StorageTagReverse<ST>, Device>
|
||||
{
|
||||
public:
|
||||
using ValueType = typename ArrayHandleType::ValueType;
|
||||
|
||||
private:
|
||||
using StorageTag = StorageTagReverse<ArrayHandleType>;
|
||||
using StorageType = vtkm::cont::internal::Storage<ValueType, StorageTag>;
|
||||
using StorageTag = StorageTagReverse<ST>;
|
||||
using StorageType = vtkm::cont::internal::Storage<T, StorageTag>;
|
||||
using ArrayHandleType = typename detail::ReverseTypeArg<T, ST>::ArrayHandle;
|
||||
|
||||
public:
|
||||
using ValueType = T;
|
||||
using PortalControl = typename StorageType::PortalType;
|
||||
using PortalConstControl = typename StorageType::PortalConstType;
|
||||
|
||||
@ -161,21 +197,21 @@ public:
|
||||
vtkm::Id GetNumberOfValues() const { return this->Array.GetNumberOfValues(); }
|
||||
|
||||
VTKM_CONT
|
||||
PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData))
|
||||
PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData), vtkm::cont::Token& token)
|
||||
{
|
||||
return PortalConstExecution(this->Array.PrepareForInput(Device()));
|
||||
return PortalConstExecution(this->Array.PrepareForInput(Device(), token));
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
PortalExecution PrepareForInPlace(bool vtkmNotUsed(updateData))
|
||||
PortalExecution PrepareForInPlace(bool vtkmNotUsed(updateData), vtkm::cont::Token& token)
|
||||
{
|
||||
return PortalExecution(this->Array.PrepareForInPlace(Device()));
|
||||
return PortalExecution(this->Array.PrepareForInPlace(Device(), token));
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
PortalExecution PrepareForOutput(vtkm::Id numberOfValues)
|
||||
PortalExecution PrepareForOutput(vtkm::Id numberOfValues, vtkm::cont::Token& token)
|
||||
{
|
||||
return PortalExecution(this->Array.PrepareForOutput(numberOfValues, Device()));
|
||||
return PortalExecution(this->Array.PrepareForOutput(numberOfValues, Device(), token));
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
@ -203,18 +239,17 @@ private:
|
||||
/// order (i.e. from end to beginning).
|
||||
///
|
||||
template <typename ArrayHandleType>
|
||||
class ArrayHandleReverse : public vtkm::cont::ArrayHandle<typename ArrayHandleType::ValueType,
|
||||
StorageTagReverse<ArrayHandleType>>
|
||||
class ArrayHandleReverse
|
||||
: public vtkm::cont::ArrayHandle<typename ArrayHandleType::ValueType,
|
||||
StorageTagReverse<typename ArrayHandleType::StorageTag>>
|
||||
|
||||
{
|
||||
public:
|
||||
VTKM_ARRAY_HANDLE_SUBCLASS(ArrayHandleReverse,
|
||||
(ArrayHandleReverse<ArrayHandleType>),
|
||||
(vtkm::cont::ArrayHandle<typename ArrayHandleType::ValueType,
|
||||
StorageTagReverse<ArrayHandleType>>));
|
||||
|
||||
protected:
|
||||
using StorageType = vtkm::cont::internal::Storage<ValueType, StorageTag>;
|
||||
VTKM_ARRAY_HANDLE_SUBCLASS(
|
||||
ArrayHandleReverse,
|
||||
(ArrayHandleReverse<ArrayHandleType>),
|
||||
(vtkm::cont::ArrayHandle<typename ArrayHandleType::ValueType,
|
||||
StorageTagReverse<typename ArrayHandleType::StorageTag>>));
|
||||
|
||||
public:
|
||||
ArrayHandleReverse(const ArrayHandleType& handle)
|
||||
@ -252,10 +287,9 @@ struct SerializableTypeString<vtkm::cont::ArrayHandleReverse<AH>>
|
||||
}
|
||||
};
|
||||
|
||||
template <typename AH>
|
||||
struct SerializableTypeString<
|
||||
vtkm::cont::ArrayHandle<typename AH::ValueType, vtkm::cont::StorageTagReverse<AH>>>
|
||||
: SerializableTypeString<vtkm::cont::ArrayHandleReverse<AH>>
|
||||
template <typename T, typename ST>
|
||||
struct SerializableTypeString<vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagReverse<ST>>>
|
||||
: SerializableTypeString<vtkm::cont::ArrayHandleReverse<vtkm::cont::ArrayHandle<T, ST>>>
|
||||
{
|
||||
};
|
||||
}
|
||||
@ -285,10 +319,9 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template <typename AH>
|
||||
struct Serialization<
|
||||
vtkm::cont::ArrayHandle<typename AH::ValueType, vtkm::cont::StorageTagReverse<AH>>>
|
||||
: Serialization<vtkm::cont::ArrayHandleReverse<AH>>
|
||||
template <typename T, typename ST>
|
||||
struct Serialization<vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagReverse<ST>>>
|
||||
: Serialization<vtkm::cont::ArrayHandleReverse<vtkm::cont::ArrayHandle<T, ST>>>
|
||||
{
|
||||
};
|
||||
|
||||
|
@ -182,11 +182,11 @@ struct ArrayHandleSOATraits
|
||||
using IsTrueVec = std::integral_constant<bool, (NUM_COMPONENTS > 1)>;
|
||||
|
||||
using PortalControl = typename detail::SOAPortalChooser<ValueType,
|
||||
typename BaseArrayType::PortalControl,
|
||||
typename BaseArrayType::WritePortalType,
|
||||
IsTrueVec>::Type;
|
||||
using PortalConstControl =
|
||||
typename detail::SOAPortalChooser<ValueType,
|
||||
typename BaseArrayType::PortalConstControl,
|
||||
typename BaseArrayType::ReadPortalType,
|
||||
IsTrueVec>::Type;
|
||||
|
||||
template <typename Device>
|
||||
@ -282,7 +282,7 @@ public:
|
||||
VTKM_ASSERT(this->IsValid());
|
||||
return detail::MakeSOAPortal<PortalType>(
|
||||
this->Arrays, this->GetNumberOfValues(), [](BaseArrayType& array) {
|
||||
return array.GetPortalControl();
|
||||
return array.WritePortal();
|
||||
});
|
||||
}
|
||||
|
||||
@ -291,7 +291,7 @@ public:
|
||||
VTKM_ASSERT(this->IsValid());
|
||||
return detail::MakeSOAPortal<PortalConstType>(
|
||||
this->Arrays, this->GetNumberOfValues(), [](const BaseArrayType& array) {
|
||||
return array.GetPortalConstControl();
|
||||
return array.ReadPortal();
|
||||
});
|
||||
}
|
||||
|
||||
@ -349,27 +349,29 @@ public:
|
||||
|
||||
VTKM_CONT vtkm::Id GetNumberOfValues() const { return this->Storage->GetNumberOfValues(); }
|
||||
|
||||
VTKM_CONT PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData)) const
|
||||
VTKM_CONT PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData),
|
||||
vtkm::cont::Token& token) const
|
||||
{
|
||||
return detail::MakeSOAPortal<PortalConstExecution>(
|
||||
this->Storage->GetArrays(), this->GetNumberOfValues(), [](const BaseArrayType& array) {
|
||||
return array.PrepareForInput(Device{});
|
||||
this->Storage->GetArrays(), this->GetNumberOfValues(), [&token](const BaseArrayType& array) {
|
||||
return array.PrepareForInput(Device{}, token);
|
||||
});
|
||||
}
|
||||
|
||||
VTKM_CONT PortalExecution PrepareForInPlace(bool vtkmNotUsed(updateData)) const
|
||||
VTKM_CONT PortalExecution PrepareForInPlace(bool vtkmNotUsed(updateData),
|
||||
vtkm::cont::Token& token) const
|
||||
{
|
||||
return detail::MakeSOAPortal<PortalExecution>(
|
||||
this->Storage->GetArrays(), this->GetNumberOfValues(), [](BaseArrayType& array) {
|
||||
return array.PrepareForInPlace(Device{});
|
||||
this->Storage->GetArrays(), this->GetNumberOfValues(), [&token](BaseArrayType& array) {
|
||||
return array.PrepareForInPlace(Device{}, token);
|
||||
});
|
||||
}
|
||||
|
||||
VTKM_CONT PortalExecution PrepareForOutput(vtkm::Id numValues) const
|
||||
VTKM_CONT PortalExecution PrepareForOutput(vtkm::Id numValues, vtkm::cont::Token& token) const
|
||||
{
|
||||
return detail::MakeSOAPortal<PortalExecution>(
|
||||
this->Storage->GetArrays(), numValues, [numValues](BaseArrayType& array) {
|
||||
return array.PrepareForOutput(numValues, Device{});
|
||||
this->Storage->GetArrays(), numValues, [numValues, &token](BaseArrayType& array) {
|
||||
return array.PrepareForOutput(numValues, Device{}, token);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,8 @@ public:
|
||||
using PortalType = P;
|
||||
using ValueType = typename PortalType::ValueType;
|
||||
|
||||
VTKM_CONT
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
VTKM_EXEC_CONT
|
||||
ArrayPortalStreaming()
|
||||
: InputPortal()
|
||||
, BlockIndex(0)
|
||||
@ -38,7 +39,8 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
VTKM_EXEC_CONT
|
||||
ArrayPortalStreaming(const PortalType& inputPortal,
|
||||
vtkm::Id blockIndex,
|
||||
vtkm::Id blockSize,
|
||||
@ -50,8 +52,9 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
template <typename OtherP>
|
||||
VTKM_CONT ArrayPortalStreaming(const ArrayPortalStreaming<OtherP>& src)
|
||||
VTKM_EXEC_CONT ArrayPortalStreaming(const ArrayPortalStreaming<OtherP>& src)
|
||||
: InputPortal(src.GetPortal())
|
||||
, BlockIndex(src.GetBlockIndex())
|
||||
, BlockSize(src.GetBlockSize())
|
||||
@ -59,10 +62,56 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
VTKM_EXEC_CONT
|
||||
ArrayPortalStreaming(const ArrayPortalStreaming& src)
|
||||
: InputPortal(src.InputPortal)
|
||||
, BlockIndex(src.BlockIndex)
|
||||
, BlockSize(src.BlockSize)
|
||||
, CurBlockSize(src.CurBlockSize)
|
||||
{
|
||||
}
|
||||
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
VTKM_EXEC_CONT
|
||||
ArrayPortalStreaming(const ArrayPortalStreaming&& rhs)
|
||||
: InputPortal(std::move(rhs.InputPortal))
|
||||
, BlockIndex(std::move(rhs.BlockIndex))
|
||||
, BlockSize(std::move(rhs.BlockSize))
|
||||
, CurBlockSize(std::move(rhs.CurBlockSize))
|
||||
{
|
||||
}
|
||||
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
VTKM_EXEC_CONT
|
||||
~ArrayPortalStreaming() {}
|
||||
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
VTKM_EXEC_CONT
|
||||
ArrayPortalStreaming& operator=(const ArrayPortalStreaming& src)
|
||||
{
|
||||
this->InputPortal = src.InputPortal;
|
||||
this->BlockIndex = src.BlockIndex;
|
||||
this->BlockSize = src.BlockSize;
|
||||
this->CurBlockSize = src.CurBlockSize;
|
||||
return *this;
|
||||
}
|
||||
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
VTKM_EXEC_CONT
|
||||
ArrayPortalStreaming& operator=(const ArrayPortalStreaming&& rhs)
|
||||
{
|
||||
this->InputPortal = std::move(rhs.InputPortal);
|
||||
this->BlockIndex = std::move(rhs.BlockIndex);
|
||||
this->BlockSize = std::move(rhs.BlockSize);
|
||||
this->CurBlockSize = std::move(rhs.CurBlockSize);
|
||||
return *this;
|
||||
}
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
vtkm::Id GetNumberOfValues() const { return this->CurBlockSize; }
|
||||
|
||||
VTKM_CONT
|
||||
VTKM_EXEC_CONT
|
||||
ValueType Get(vtkm::Id index) const
|
||||
{
|
||||
return this->InputPortal.Get(this->BlockIndex * this->BlockSize + index);
|
||||
@ -70,30 +119,30 @@ public:
|
||||
|
||||
template <typename Writable_ = Writable,
|
||||
typename = typename std::enable_if<Writable_::value>::type>
|
||||
VTKM_CONT void Set(vtkm::Id index, const ValueType& value) const
|
||||
VTKM_EXEC_CONT void Set(vtkm::Id index, const ValueType& value) const
|
||||
{
|
||||
this->InputPortal.Set(this->BlockIndex * this->BlockSize + index, value);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
VTKM_EXEC_CONT
|
||||
const PortalType& GetPortal() const { return this->InputPortal; }
|
||||
|
||||
VTKM_CONT
|
||||
VTKM_EXEC_CONT
|
||||
void SetBlockSize(vtkm::Id blockSize) { this->BlockSize = blockSize; }
|
||||
|
||||
VTKM_CONT
|
||||
VTKM_EXEC_CONT
|
||||
void SetBlockIndex(vtkm::Id blockIndex) { this->BlockIndex = blockIndex; }
|
||||
|
||||
VTKM_CONT
|
||||
VTKM_EXEC_CONT
|
||||
void SetCurBlockSize(vtkm::Id curBlockSize) { this->CurBlockSize = curBlockSize; }
|
||||
|
||||
VTKM_CONT
|
||||
VTKM_EXEC_CONT
|
||||
vtkm::Id GetBlockSize() { return this->BlockSize; }
|
||||
|
||||
VTKM_CONT
|
||||
VTKM_EXEC_CONT
|
||||
vtkm::Id GetBlockIndex() { return this->BlockIndex; }
|
||||
|
||||
VTKM_CONT
|
||||
VTKM_EXEC_CONT
|
||||
vtkm::Id GetCurBlockSize() { return this->CurBlockSize; }
|
||||
|
||||
private:
|
||||
@ -119,10 +168,13 @@ class Storage<typename ArrayHandleInputType::ValueType, StorageTagStreaming<Arra
|
||||
public:
|
||||
using ValueType = typename ArrayHandleInputType::ValueType;
|
||||
|
||||
using PortalType =
|
||||
vtkm::cont::internal::ArrayPortalStreaming<typename ArrayHandleInputType::PortalControl>;
|
||||
using PortalType = vtkm::cont::internal::ArrayPortalStreaming<
|
||||
typename vtkm::cont::internal::Storage<typename ArrayHandleInputType::ValueType,
|
||||
typename ArrayHandleInputType::StorageTag>::PortalType>;
|
||||
using PortalConstType =
|
||||
vtkm::cont::internal::ArrayPortalStreaming<typename ArrayHandleInputType::PortalConstControl>;
|
||||
vtkm::cont::internal::ArrayPortalStreaming<typename vtkm::cont::internal::Storage<
|
||||
typename ArrayHandleInputType::ValueType,
|
||||
typename ArrayHandleInputType::StorageTag>::PortalConstType>;
|
||||
|
||||
VTKM_CONT
|
||||
Storage()
|
||||
@ -147,15 +199,14 @@ public:
|
||||
PortalType GetPortal()
|
||||
{
|
||||
VTKM_ASSERT(this->Valid);
|
||||
return PortalType(this->InputArray.GetPortalControl(), BlockSize, BlockIndex, CurBlockSize);
|
||||
return PortalType(this->InputArray.WritePortal(), BlockSize, BlockIndex, CurBlockSize);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
PortalConstType GetPortalConst() const
|
||||
{
|
||||
VTKM_ASSERT(this->Valid);
|
||||
return PortalConstType(
|
||||
this->InputArray.GetPortalConstControl(), BlockSize, BlockIndex, CurBlockSize);
|
||||
return PortalConstType(this->InputArray.ReadPortal(), BlockSize, BlockIndex, CurBlockSize);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
@ -238,17 +289,19 @@ public:
|
||||
const vtkm::Id curBlockSize)
|
||||
: Superclass(StorageType(inputArray, blockIndex, blockSize, curBlockSize))
|
||||
{
|
||||
this->GetPortalConstControl().SetBlockIndex(blockIndex);
|
||||
this->GetPortalConstControl().SetBlockSize(blockSize);
|
||||
this->GetPortalConstControl().SetCurBlockSize(curBlockSize);
|
||||
this->ReadPortal().SetBlockIndex(blockIndex);
|
||||
this->ReadPortal().SetBlockSize(blockSize);
|
||||
this->ReadPortal().SetCurBlockSize(curBlockSize);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
void AllocateFullArray(vtkm::Id numberOfValues)
|
||||
{
|
||||
this->ReleaseResourcesExecutionInternal();
|
||||
this->Internals->ControlArray.AllocateFullArray(numberOfValues);
|
||||
this->Internals->ControlArrayValid = true;
|
||||
auto lock = this->GetLock();
|
||||
|
||||
this->ReleaseResourcesExecutionInternal(lock);
|
||||
this->Internals->GetControlArray(lock)->AllocateFullArray(numberOfValues);
|
||||
this->Internals->SetControlArrayValid(lock, true);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -144,6 +144,9 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
ArrayPortalSwizzle& operator=(const ArrayPortalSwizzle& src) = default;
|
||||
ArrayPortalSwizzle& operator=(ArrayPortalSwizzle&& src) = default;
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
vtkm::Id GetNumberOfValues() const { return this->Portal.GetNumberOfValues(); }
|
||||
|
||||
@ -192,9 +195,9 @@ class Storage<typename ResizeVectorType<typename ArrayHandleType::ValueType, Out
|
||||
|
||||
public:
|
||||
using PortalType =
|
||||
ArrayPortalSwizzle<typename ArrayHandleType::PortalControl, ArrayHandleType, OutSize>;
|
||||
ArrayPortalSwizzle<typename ArrayHandleType::WritePortalType, ArrayHandleType, OutSize>;
|
||||
using PortalConstType =
|
||||
ArrayPortalSwizzle<typename ArrayHandleType::PortalConstControl, ArrayHandleType, OutSize>;
|
||||
ArrayPortalSwizzle<typename ArrayHandleType::ReadPortalType, ArrayHandleType, OutSize>;
|
||||
using MapType = typename Traits::MapType;
|
||||
using ValueType = typename Traits::OutValueType;
|
||||
|
||||
@ -217,14 +220,14 @@ public:
|
||||
PortalConstType GetPortalConst() const
|
||||
{
|
||||
VTKM_ASSERT(this->Valid);
|
||||
return PortalConstType(this->Array.GetPortalConstControl(), this->Map);
|
||||
return PortalConstType(this->Array.ReadPortal(), this->Map);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
PortalType GetPortal()
|
||||
{
|
||||
VTKM_ASSERT(this->Valid);
|
||||
return PortalType(this->Array.GetPortalControl(), this->Map);
|
||||
return PortalType(this->Array.WritePortal(), this->Map);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
@ -306,21 +309,22 @@ public:
|
||||
vtkm::Id GetNumberOfValues() const { return this->Array.GetNumberOfValues(); }
|
||||
|
||||
VTKM_CONT
|
||||
PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData))
|
||||
PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData), vtkm::cont::Token& token)
|
||||
{
|
||||
return PortalConstExecution(this->Array.PrepareForInput(DeviceTag()), this->Map);
|
||||
return PortalConstExecution(this->Array.PrepareForInput(DeviceTag(), token), this->Map);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
PortalExecution PrepareForInPlace(bool vtkmNotUsed(updateData))
|
||||
PortalExecution PrepareForInPlace(bool vtkmNotUsed(updateData), vtkm::cont::Token& token)
|
||||
{
|
||||
return PortalExecution(this->Array.PrepareForInPlace(DeviceTag()), this->Map);
|
||||
return PortalExecution(this->Array.PrepareForInPlace(DeviceTag(), token), this->Map);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
PortalExecution PrepareForOutput(vtkm::Id numberOfValues)
|
||||
PortalExecution PrepareForOutput(vtkm::Id numberOfValues, vtkm::cont::Token& token)
|
||||
{
|
||||
return PortalExecution(this->Array.PrepareForOutput(numberOfValues, DeviceTag()), this->Map);
|
||||
return PortalExecution(this->Array.PrepareForOutput(numberOfValues, DeviceTag(), token),
|
||||
this->Map);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
|
@ -189,7 +189,7 @@ struct TransformFunctorManagerImpl<ProvidedFunctorType, std::false_type>
|
||||
ProvidedFunctorType PrepareForControl() const { return this->Functor; }
|
||||
|
||||
template <typename Device>
|
||||
VTKM_CONT ProvidedFunctorType PrepareForExecution(Device) const
|
||||
VTKM_CONT ProvidedFunctorType PrepareForExecution(Device, vtkm::cont::Token&) const
|
||||
{
|
||||
return this->Functor;
|
||||
}
|
||||
@ -202,7 +202,8 @@ struct TransformFunctorManagerImpl<ProvidedFunctorType, std::true_type>
|
||||
|
||||
ProvidedFunctorType Functor;
|
||||
// using FunctorType = decltype(std::declval<ProvidedFunctorType>().PrepareForControl());
|
||||
using FunctorType = decltype(Functor.PrepareForControl());
|
||||
// using FunctorType = decltype(Functor.PrepareForControl());
|
||||
using FunctorType = vtkm::cont::internal::ControlObjectType<ProvidedFunctorType>;
|
||||
|
||||
TransformFunctorManagerImpl() = default;
|
||||
|
||||
@ -213,16 +214,17 @@ struct TransformFunctorManagerImpl<ProvidedFunctorType, std::true_type>
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
auto PrepareForControl() const -> decltype(this->Functor.PrepareForControl())
|
||||
auto PrepareForControl() const
|
||||
-> decltype(vtkm::cont::internal::CallPrepareForControl(this->Functor))
|
||||
{
|
||||
return this->Functor.PrepareForControl();
|
||||
return vtkm::cont::internal::CallPrepareForControl(this->Functor);
|
||||
}
|
||||
|
||||
template <typename Device>
|
||||
VTKM_CONT auto PrepareForExecution(Device device) const
|
||||
-> decltype(this->Functor.PrepareForExecution(device))
|
||||
VTKM_CONT auto PrepareForExecution(Device device, vtkm::cont::Token& token) const
|
||||
-> decltype(vtkm::cont::internal::CallPrepareForExecution(this->Functor, device, token))
|
||||
{
|
||||
return this->Functor.PrepareForExecution(device);
|
||||
return vtkm::cont::internal::CallPrepareForExecution(this->Functor, device, token);
|
||||
}
|
||||
};
|
||||
|
||||
@ -271,7 +273,7 @@ public:
|
||||
|
||||
using PortalConstType =
|
||||
vtkm::exec::internal::ArrayPortalTransform<ValueType,
|
||||
typename ArrayHandleType::PortalConstControl,
|
||||
typename ArrayHandleType::ReadPortalType,
|
||||
typename FunctorManager::FunctorType>;
|
||||
|
||||
// Note that this array is read only, so you really should only be getting the const
|
||||
@ -305,7 +307,7 @@ public:
|
||||
{
|
||||
VTKM_ASSERT(this->Valid);
|
||||
vtkm::cont::ScopedRuntimeDeviceTracker trackerScope(vtkm::cont::DeviceAdapterTagSerial{});
|
||||
return PortalConstType(this->Array.GetPortalConstControl(), this->Functor.PrepareForControl());
|
||||
return PortalConstType(this->Array.ReadPortal(), this->Functor.PrepareForControl());
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
@ -365,12 +367,12 @@ public:
|
||||
|
||||
using PortalType =
|
||||
vtkm::exec::internal::ArrayPortalTransform<ValueType,
|
||||
typename ArrayHandleType::PortalControl,
|
||||
typename ArrayHandleType::WritePortalType,
|
||||
typename FunctorManager::FunctorType,
|
||||
typename InverseFunctorManager::FunctorType>;
|
||||
using PortalConstType =
|
||||
vtkm::exec::internal::ArrayPortalTransform<ValueType,
|
||||
typename ArrayHandleType::PortalConstControl,
|
||||
typename ArrayHandleType::ReadPortalType,
|
||||
typename FunctorManager::FunctorType,
|
||||
typename InverseFunctorManager::FunctorType>;
|
||||
|
||||
@ -382,8 +384,8 @@ public:
|
||||
|
||||
VTKM_CONT
|
||||
Storage(const ArrayHandleType& array,
|
||||
const FunctorType& functor,
|
||||
const InverseFunctorType& inverseFunctor)
|
||||
const FunctorType& functor = FunctorType(),
|
||||
const InverseFunctorType& inverseFunctor = InverseFunctorType())
|
||||
: Array(array)
|
||||
, Functor(functor)
|
||||
, InverseFunctor(inverseFunctor)
|
||||
@ -396,7 +398,7 @@ public:
|
||||
{
|
||||
VTKM_ASSERT(this->Valid);
|
||||
vtkm::cont::ScopedRuntimeDeviceTracker trackerScope(vtkm::cont::DeviceAdapterTagSerial{});
|
||||
return PortalType(this->Array.GetPortalControl(),
|
||||
return PortalType(this->Array.WritePortal(),
|
||||
this->Functor.PrepareForControl(),
|
||||
this->InverseFunctor.PrepareForControl());
|
||||
}
|
||||
@ -406,7 +408,7 @@ public:
|
||||
{
|
||||
VTKM_ASSERT(this->Valid);
|
||||
vtkm::cont::ScopedRuntimeDeviceTracker trackerScope(vtkm::cont::DeviceAdapterTagSerial{});
|
||||
return PortalConstType(this->Array.GetPortalConstControl(),
|
||||
return PortalConstType(this->Array.ReadPortal(),
|
||||
this->Functor.PrepareForControl(),
|
||||
this->InverseFunctor.PrepareForControl());
|
||||
}
|
||||
@ -470,8 +472,12 @@ public:
|
||||
using PortalControl = typename StorageType::PortalType;
|
||||
using PortalConstControl = typename StorageType::PortalConstType;
|
||||
|
||||
//meant to be an invalid writeable execution portal
|
||||
using PortalExecution = typename StorageType::PortalType;
|
||||
// You can get the "writable" version of the portal, but you will not actually be
|
||||
// able to write to it.
|
||||
using PortalExecution = vtkm::exec::internal::ArrayPortalTransform<
|
||||
ValueType,
|
||||
typename ArrayHandleType::template ExecutionTypes<Device>::Portal,
|
||||
typename FunctorManager::FunctorType>;
|
||||
using PortalConstExecution = vtkm::exec::internal::ArrayPortalTransform<
|
||||
ValueType,
|
||||
typename ArrayHandleType::template ExecutionTypes<Device>::PortalConst,
|
||||
@ -488,21 +494,21 @@ public:
|
||||
vtkm::Id GetNumberOfValues() const { return this->Array.GetNumberOfValues(); }
|
||||
|
||||
VTKM_CONT
|
||||
PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData))
|
||||
PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData), vtkm::cont::Token& token)
|
||||
{
|
||||
return PortalConstExecution(this->Array.PrepareForInput(Device()),
|
||||
this->Functor.PrepareForExecution(Device()));
|
||||
return PortalConstExecution(this->Array.PrepareForInput(Device{}, token),
|
||||
this->Functor.PrepareForExecution(Device{}, token));
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
PortalExecution PrepareForInPlace(bool& vtkmNotUsed(updateData))
|
||||
PortalExecution PrepareForInPlace(bool& vtkmNotUsed(updateData), vtkm::cont::Token&)
|
||||
{
|
||||
throw vtkm::cont::ErrorBadType("ArrayHandleTransform read only. "
|
||||
"Cannot be used for in-place operations.");
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
PortalExecution PrepareForOutput(vtkm::Id vtkmNotUsed(numberOfValues))
|
||||
PortalExecution PrepareForOutput(vtkm::Id vtkmNotUsed(numberOfValues), vtkm::cont::Token&)
|
||||
{
|
||||
throw vtkm::cont::ErrorBadType("ArrayHandleTransform read only. Cannot be used as output.");
|
||||
}
|
||||
@ -573,27 +579,27 @@ public:
|
||||
vtkm::Id GetNumberOfValues() const { return this->Array.GetNumberOfValues(); }
|
||||
|
||||
VTKM_CONT
|
||||
PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData))
|
||||
PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData), vtkm::cont::Token& token)
|
||||
{
|
||||
return PortalConstExecution(this->Array.PrepareForInput(Device()),
|
||||
this->Functor.PrepareForExecution(Device()),
|
||||
this->InverseFunctor.PrepareForExecution(Device()));
|
||||
return PortalConstExecution(this->Array.PrepareForInput(Device{}, token),
|
||||
this->Functor.PrepareForExecution(Device{}, token),
|
||||
this->InverseFunctor.PrepareForExecution(Device{}, token));
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
PortalExecution PrepareForInPlace(bool& vtkmNotUsed(updateData))
|
||||
PortalExecution PrepareForInPlace(bool& vtkmNotUsed(updateData), vtkm::cont::Token& token)
|
||||
{
|
||||
return PortalExecution(this->Array.PrepareForInPlace(Device()),
|
||||
this->Functor.PrepareForExecution(Device()),
|
||||
this->InverseFunctor.PrepareForExecution(Device()));
|
||||
return PortalExecution(this->Array.PrepareForInPlace(Device{}, token),
|
||||
this->Functor.PrepareForExecution(Device{}, token),
|
||||
this->InverseFunctor.PrepareForExecution(Device{}, token));
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
PortalExecution PrepareForOutput(vtkm::Id numberOfValues)
|
||||
PortalExecution PrepareForOutput(vtkm::Id numberOfValues, vtkm::cont::Token& token)
|
||||
{
|
||||
return PortalExecution(this->Array.PrepareForOutput(numberOfValues, Device()),
|
||||
this->Functor.PrepareForExecution(Device()),
|
||||
this->InverseFunctor.PrepareForExecution(Device()));
|
||||
return PortalExecution(this->Array.PrepareForOutput(numberOfValues, Device{}, token),
|
||||
this->Functor.PrepareForExecution(Device{}, token),
|
||||
this->InverseFunctor.PrepareForExecution(Device{}, token));
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
@ -703,6 +709,13 @@ public:
|
||||
: Superclass(StorageType(handle, functor, inverseFunctor))
|
||||
{
|
||||
}
|
||||
|
||||
/// Implemented so that it is defined exclusively in the control environment.
|
||||
/// If there is a separate device for the execution environment (for example,
|
||||
/// with CUDA), then the automatically generated destructor could be
|
||||
/// created for all devices, and it would not be valid for all devices.
|
||||
///
|
||||
~ArrayHandleTransform() {}
|
||||
};
|
||||
|
||||
template <typename HandleType, typename FunctorType, typename InverseFunctorType>
|
||||
|
@ -19,22 +19,48 @@ namespace vtkm
|
||||
namespace cont
|
||||
{
|
||||
|
||||
struct VTKM_ALWAYS_EXPORT StorageTagUniformPoints
|
||||
{
|
||||
};
|
||||
|
||||
namespace internal
|
||||
{
|
||||
|
||||
using StorageTagUniformPointsSuperclass =
|
||||
vtkm::cont::StorageTagImplicit<vtkm::internal::ArrayPortalUniformPointCoordinates>;
|
||||
|
||||
template <>
|
||||
struct Storage<vtkm::Vec3f, vtkm::cont::StorageTagUniformPoints>
|
||||
: Storage<vtkm::Vec3f, StorageTagUniformPointsSuperclass>
|
||||
{
|
||||
using Superclass = Storage<vtkm::Vec3f, StorageTagUniformPointsSuperclass>;
|
||||
|
||||
using Superclass::Superclass;
|
||||
};
|
||||
|
||||
template <typename Device>
|
||||
struct ArrayTransfer<vtkm::Vec3f, vtkm::cont::StorageTagUniformPoints, Device>
|
||||
: ArrayTransfer<vtkm::Vec3f, StorageTagUniformPointsSuperclass, Device>
|
||||
{
|
||||
using Superclass = ArrayTransfer<vtkm::Vec3f, StorageTagUniformPointsSuperclass, Device>;
|
||||
|
||||
using Superclass::Superclass;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
/// ArrayHandleUniformPointCoordinates is a specialization of ArrayHandle. It
|
||||
/// contains the information necessary to compute the point coordinates in a
|
||||
/// uniform orthogonal grid (extent, origin, and spacing) and implicitly
|
||||
/// computes these coordinates in its array portal.
|
||||
///
|
||||
class VTKM_ALWAYS_EXPORT ArrayHandleUniformPointCoordinates
|
||||
: public vtkm::cont::ArrayHandle<
|
||||
vtkm::Vec3f,
|
||||
vtkm::cont::StorageTagImplicit<vtkm::internal::ArrayPortalUniformPointCoordinates>>
|
||||
: public vtkm::cont::ArrayHandle<vtkm::Vec3f, vtkm::cont::StorageTagUniformPoints>
|
||||
{
|
||||
public:
|
||||
VTKM_ARRAY_HANDLE_SUBCLASS_NT(
|
||||
ArrayHandleUniformPointCoordinates,
|
||||
(vtkm::cont::ArrayHandle<
|
||||
vtkm::Vec3f,
|
||||
vtkm::cont::StorageTagImplicit<vtkm::internal::ArrayPortalUniformPointCoordinates>>));
|
||||
(vtkm::cont::ArrayHandle<vtkm::Vec3f, vtkm::cont::StorageTagUniformPoints>));
|
||||
|
||||
private:
|
||||
using StorageType = vtkm::cont::internal::Storage<ValueType, StorageTag>;
|
||||
@ -48,6 +74,13 @@ public:
|
||||
vtkm::internal::ArrayPortalUniformPointCoordinates(dimensions, origin, spacing)))
|
||||
{
|
||||
}
|
||||
|
||||
/// Implemented so that it is defined exclusively in the control environment.
|
||||
/// If there is a separate device for the execution environment (for example,
|
||||
/// with CUDA), then the automatically generated destructor could be
|
||||
/// created for all devices, and it would not be valid for all devices.
|
||||
///
|
||||
~ArrayHandleUniformPointCoordinates() {}
|
||||
};
|
||||
}
|
||||
} // namespace vtkm::cont
|
||||
@ -67,9 +100,8 @@ struct SerializableTypeString<vtkm::cont::ArrayHandleUniformPointCoordinates>
|
||||
};
|
||||
|
||||
template <>
|
||||
struct SerializableTypeString<vtkm::cont::ArrayHandle<
|
||||
vtkm::Vec3f,
|
||||
vtkm::cont::StorageTagImplicit<vtkm::internal::ArrayPortalUniformPointCoordinates>>>
|
||||
struct SerializableTypeString<
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec3f, vtkm::cont::StorageTagUniformPoints>>
|
||||
: SerializableTypeString<vtkm::cont::ArrayHandleUniformPointCoordinates>
|
||||
{
|
||||
};
|
||||
@ -89,7 +121,7 @@ private:
|
||||
public:
|
||||
static VTKM_CONT void save(BinaryBuffer& bb, const BaseType& obj)
|
||||
{
|
||||
auto portal = obj.GetPortalConstControl();
|
||||
auto portal = obj.ReadPortal();
|
||||
vtkmdiy::save(bb, portal.GetDimensions());
|
||||
vtkmdiy::save(bb, portal.GetOrigin());
|
||||
vtkmdiy::save(bb, portal.GetSpacing());
|
||||
@ -109,9 +141,7 @@ public:
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Serialization<vtkm::cont::ArrayHandle<
|
||||
vtkm::Vec3f,
|
||||
vtkm::cont::StorageTagImplicit<vtkm::internal::ArrayPortalUniformPointCoordinates>>>
|
||||
struct Serialization<vtkm::cont::ArrayHandle<vtkm::Vec3f, vtkm::cont::StorageTagUniformPoints>>
|
||||
: Serialization<vtkm::cont::ArrayHandleUniformPointCoordinates>
|
||||
{
|
||||
};
|
||||
|
@ -11,6 +11,7 @@
|
||||
#define vtk_m_cont_ArrayHandleView_h
|
||||
|
||||
#include <vtkm/Assert.h>
|
||||
#include <vtkm/Deprecated.h>
|
||||
|
||||
#include <vtkm/cont/ArrayHandle.h>
|
||||
#include <vtkm/cont/ArrayPortal.h>
|
||||
@ -81,22 +82,60 @@ private:
|
||||
|
||||
} // namespace internal
|
||||
|
||||
template <typename ArrayHandleType>
|
||||
struct StorageTagView
|
||||
template <typename StorageTag>
|
||||
struct VTKM_ALWAYS_EXPORT StorageTagView
|
||||
{
|
||||
};
|
||||
|
||||
namespace internal
|
||||
{
|
||||
|
||||
template <typename ArrayHandleType>
|
||||
class Storage<typename ArrayHandleType::ValueType, StorageTagView<ArrayHandleType>>
|
||||
namespace detail
|
||||
{
|
||||
public:
|
||||
using ValueType = typename ArrayHandleType::ValueType;
|
||||
|
||||
using PortalType = ArrayPortalView<typename ArrayHandleType::PortalControl>;
|
||||
using PortalConstType = ArrayPortalView<typename ArrayHandleType::PortalConstControl>;
|
||||
template <typename T, typename ArrayOrStorage, bool IsArrayType>
|
||||
struct ViewTypeArgImpl;
|
||||
|
||||
template <typename T, typename Storage>
|
||||
struct ViewTypeArgImpl<T, Storage, false>
|
||||
{
|
||||
using StorageTag = Storage;
|
||||
using ArrayHandle = vtkm::cont::ArrayHandle<T, StorageTag>;
|
||||
};
|
||||
|
||||
template <typename T, typename Array>
|
||||
struct ViewTypeArgImpl<T, Array, true>
|
||||
{
|
||||
VTKM_STATIC_ASSERT_MSG((std::is_same<T, typename Array::ValueType>::value),
|
||||
"Used array with wrong type in ArrayHandleView.");
|
||||
using StorageTag VTKM_DEPRECATED(1.6,
|
||||
"Use storage tag instead of array handle in StorageTagView.") =
|
||||
typename Array::StorageTag;
|
||||
using ArrayHandle VTKM_DEPRECATED(1.6,
|
||||
"Use storage tag instead of array handle in StorageTagView.") =
|
||||
vtkm::cont::ArrayHandle<T, typename Array::StorageTag>;
|
||||
};
|
||||
|
||||
template <typename T, typename ArrayOrStorage>
|
||||
struct ViewTypeArg
|
||||
: ViewTypeArgImpl<T,
|
||||
ArrayOrStorage,
|
||||
vtkm::cont::internal::ArrayHandleCheck<ArrayOrStorage>::type::value>
|
||||
{
|
||||
};
|
||||
|
||||
} // detail
|
||||
|
||||
template <typename T, typename ST>
|
||||
class Storage<T, StorageTagView<ST>>
|
||||
{
|
||||
using ArrayHandleType = typename detail::ViewTypeArg<T, ST>::ArrayHandle;
|
||||
|
||||
public:
|
||||
using ValueType = T;
|
||||
|
||||
using PortalType = ArrayPortalView<typename ArrayHandleType::WritePortalType>;
|
||||
using PortalConstType = ArrayPortalView<typename ArrayHandleType::ReadPortalType>;
|
||||
|
||||
VTKM_CONT
|
||||
Storage()
|
||||
@ -119,14 +158,14 @@ public:
|
||||
PortalType GetPortal()
|
||||
{
|
||||
VTKM_ASSERT(this->Valid);
|
||||
return PortalType(this->Array.GetPortalControl(), this->StartIndex, this->NumValues);
|
||||
return PortalType(this->Array.WritePortal(), this->StartIndex, this->NumValues);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
PortalConstType GetPortalConst() const
|
||||
{
|
||||
VTKM_ASSERT(this->Valid);
|
||||
return PortalConstType(this->Array.GetPortalConstControl(), this->StartIndex, this->NumValues);
|
||||
return PortalConstType(this->Array.ReadPortal(), this->StartIndex, this->NumValues);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
@ -174,17 +213,15 @@ private:
|
||||
bool Valid;
|
||||
};
|
||||
|
||||
template <typename ArrayHandleType, typename Device>
|
||||
class ArrayTransfer<typename ArrayHandleType::ValueType, StorageTagView<ArrayHandleType>, Device>
|
||||
template <typename T, typename ST, typename Device>
|
||||
class ArrayTransfer<T, StorageTagView<ST>, Device>
|
||||
{
|
||||
public:
|
||||
using ValueType = typename ArrayHandleType::ValueType;
|
||||
|
||||
private:
|
||||
using StorageTag = StorageTagView<ArrayHandleType>;
|
||||
using StorageType = vtkm::cont::internal::Storage<ValueType, StorageTag>;
|
||||
using StorageType = vtkm::cont::internal::Storage<T, vtkm::cont::StorageTagView<ST>>;
|
||||
using ArrayHandleType = typename detail::ViewTypeArg<T, ST>::ArrayHandle;
|
||||
|
||||
public:
|
||||
using ValueType = T;
|
||||
using PortalControl = typename StorageType::PortalType;
|
||||
using PortalConstControl = typename StorageType::PortalConstType;
|
||||
|
||||
@ -205,21 +242,21 @@ public:
|
||||
vtkm::Id GetNumberOfValues() const { return this->NumValues; }
|
||||
|
||||
VTKM_CONT
|
||||
PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData))
|
||||
PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData), vtkm::cont::Token& token)
|
||||
{
|
||||
return PortalConstExecution(
|
||||
this->Array.PrepareForInput(Device()), this->StartIndex, this->NumValues);
|
||||
this->Array.PrepareForInput(Device(), token), this->StartIndex, this->NumValues);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
PortalExecution PrepareForInPlace(bool vtkmNotUsed(updateData))
|
||||
PortalExecution PrepareForInPlace(bool vtkmNotUsed(updateData), vtkm::cont::Token& token)
|
||||
{
|
||||
return PortalExecution(
|
||||
this->Array.PrepareForInPlace(Device()), this->StartIndex, this->NumValues);
|
||||
this->Array.PrepareForInPlace(Device(), token), this->StartIndex, this->NumValues);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
PortalExecution PrepareForOutput(vtkm::Id numberOfValues)
|
||||
PortalExecution PrepareForOutput(vtkm::Id numberOfValues, vtkm::cont::Token& token)
|
||||
{
|
||||
if (numberOfValues != this->GetNumberOfValues())
|
||||
{
|
||||
@ -240,9 +277,10 @@ public:
|
||||
"output of ArrayHandlePermutation.");
|
||||
}
|
||||
|
||||
return PortalExecution(this->Array.PrepareForOutput(this->Array.GetNumberOfValues(), Device()),
|
||||
this->StartIndex,
|
||||
this->NumValues);
|
||||
return PortalExecution(
|
||||
this->Array.PrepareForOutput(this->Array.GetNumberOfValues(), Device(), token),
|
||||
this->StartIndex,
|
||||
this->NumValues);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
@ -266,16 +304,18 @@ private:
|
||||
} // namespace internal
|
||||
|
||||
template <typename ArrayHandleType>
|
||||
class ArrayHandleView : public vtkm::cont::ArrayHandle<typename ArrayHandleType::ValueType,
|
||||
StorageTagView<ArrayHandleType>>
|
||||
class ArrayHandleView
|
||||
: public vtkm::cont::ArrayHandle<typename ArrayHandleType::ValueType,
|
||||
StorageTagView<typename ArrayHandleType::StorageTag>>
|
||||
{
|
||||
VTKM_IS_ARRAY_HANDLE(ArrayHandleType);
|
||||
|
||||
public:
|
||||
VTKM_ARRAY_HANDLE_SUBCLASS(ArrayHandleView,
|
||||
(ArrayHandleView<ArrayHandleType>),
|
||||
(vtkm::cont::ArrayHandle<typename ArrayHandleType::ValueType,
|
||||
StorageTagView<ArrayHandleType>>));
|
||||
VTKM_ARRAY_HANDLE_SUBCLASS(
|
||||
ArrayHandleView,
|
||||
(ArrayHandleView<ArrayHandleType>),
|
||||
(vtkm::cont::ArrayHandle<typename ArrayHandleType::ValueType,
|
||||
StorageTagView<typename ArrayHandleType::StorageTag>>));
|
||||
|
||||
private:
|
||||
using StorageType = vtkm::cont::internal::Storage<ValueType, StorageTag>;
|
||||
|
@ -39,7 +39,6 @@ public:
|
||||
using T = typename ValueType::FirstType;
|
||||
using U = typename ValueType::SecondType;
|
||||
|
||||
using IteratorType = ValueType_;
|
||||
using PortalTypeFirst = PortalTypeFirst_;
|
||||
using PortalTypeSecond = PortalTypeSecond_;
|
||||
|
||||
@ -106,14 +105,14 @@ namespace vtkm
|
||||
namespace cont
|
||||
{
|
||||
|
||||
namespace internal
|
||||
{
|
||||
|
||||
template <typename FirstHandleType, typename SecondHandleType>
|
||||
template <typename ST1, typename ST2>
|
||||
struct VTKM_ALWAYS_EXPORT StorageTagZip
|
||||
{
|
||||
};
|
||||
|
||||
namespace internal
|
||||
{
|
||||
|
||||
/// This helper struct defines the value type for a zip container containing
|
||||
/// the given two array handles.
|
||||
///
|
||||
@ -127,31 +126,31 @@ struct ArrayHandleZipTraits
|
||||
|
||||
/// The appropriately templated tag.
|
||||
///
|
||||
using Tag = StorageTagZip<FirstHandleType, SecondHandleType>;
|
||||
using Tag =
|
||||
StorageTagZip<typename FirstHandleType::StorageTag, typename SecondHandleType::StorageTag>;
|
||||
|
||||
/// The superclass for ArrayHandleZip.
|
||||
///
|
||||
using Superclass = vtkm::cont::ArrayHandle<ValueType, Tag>;
|
||||
};
|
||||
|
||||
template <typename FirstHandleType, typename SecondHandleType>
|
||||
class Storage<vtkm::Pair<typename FirstHandleType::ValueType, typename SecondHandleType::ValueType>,
|
||||
StorageTagZip<FirstHandleType, SecondHandleType>>
|
||||
template <typename T1, typename T2, typename ST1, typename ST2>
|
||||
class Storage<vtkm::Pair<T1, T2>, vtkm::cont::StorageTagZip<ST1, ST2>>
|
||||
{
|
||||
VTKM_IS_ARRAY_HANDLE(FirstHandleType);
|
||||
VTKM_IS_ARRAY_HANDLE(SecondHandleType);
|
||||
using FirstHandleType = vtkm::cont::ArrayHandle<T1, ST1>;
|
||||
using SecondHandleType = vtkm::cont::ArrayHandle<T2, ST2>;
|
||||
|
||||
public:
|
||||
using ValueType =
|
||||
vtkm::Pair<typename FirstHandleType::ValueType, typename SecondHandleType::ValueType>;
|
||||
using ValueType = vtkm::Pair<T1, T2>;
|
||||
|
||||
using PortalType = vtkm::exec::internal::ArrayPortalZip<ValueType,
|
||||
typename FirstHandleType::PortalControl,
|
||||
typename SecondHandleType::PortalControl>;
|
||||
using PortalType =
|
||||
vtkm::exec::internal::ArrayPortalZip<ValueType,
|
||||
typename FirstHandleType::WritePortalType,
|
||||
typename SecondHandleType::WritePortalType>;
|
||||
using PortalConstType =
|
||||
vtkm::exec::internal::ArrayPortalZip<ValueType,
|
||||
typename FirstHandleType::PortalConstControl,
|
||||
typename SecondHandleType::PortalConstControl>;
|
||||
typename FirstHandleType::ReadPortalType,
|
||||
typename SecondHandleType::ReadPortalType>;
|
||||
|
||||
VTKM_CONT
|
||||
Storage()
|
||||
@ -170,14 +169,13 @@ public:
|
||||
VTKM_CONT
|
||||
PortalType GetPortal()
|
||||
{
|
||||
return PortalType(this->FirstArray.GetPortalControl(), this->SecondArray.GetPortalControl());
|
||||
return PortalType(this->FirstArray.WritePortal(), this->SecondArray.WritePortal());
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
PortalConstType GetPortalConst() const
|
||||
{
|
||||
return PortalConstType(this->FirstArray.GetPortalConstControl(),
|
||||
this->SecondArray.GetPortalConstControl());
|
||||
return PortalConstType(this->FirstArray.ReadPortal(), this->SecondArray.ReadPortal());
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
@ -219,21 +217,18 @@ private:
|
||||
SecondHandleType SecondArray;
|
||||
};
|
||||
|
||||
template <typename FirstHandleType, typename SecondHandleType, typename Device>
|
||||
class ArrayTransfer<
|
||||
vtkm::Pair<typename FirstHandleType::ValueType, typename SecondHandleType::ValueType>,
|
||||
StorageTagZip<FirstHandleType, SecondHandleType>,
|
||||
Device>
|
||||
template <typename T1, typename T2, typename ST1, typename ST2, typename Device>
|
||||
class ArrayTransfer<vtkm::Pair<T1, T2>, vtkm::cont::StorageTagZip<ST1, ST2>, Device>
|
||||
{
|
||||
public:
|
||||
using ValueType =
|
||||
vtkm::Pair<typename FirstHandleType::ValueType, typename SecondHandleType::ValueType>;
|
||||
using StorageTag = vtkm::cont::StorageTagZip<ST1, ST2>;
|
||||
using StorageType = vtkm::cont::internal::Storage<vtkm::Pair<T1, T2>, StorageTag>;
|
||||
|
||||
private:
|
||||
using StorageTag = StorageTagZip<FirstHandleType, SecondHandleType>;
|
||||
using StorageType = vtkm::cont::internal::Storage<ValueType, StorageTag>;
|
||||
using FirstHandleType = vtkm::cont::ArrayHandle<T1, ST1>;
|
||||
using SecondHandleType = vtkm::cont::ArrayHandle<T2, ST2>;
|
||||
|
||||
public:
|
||||
using ValueType = vtkm::Pair<T1, T2>;
|
||||
|
||||
using PortalControl = typename StorageType::PortalType;
|
||||
using PortalConstControl = typename StorageType::PortalConstType;
|
||||
|
||||
@ -262,24 +257,24 @@ public:
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData))
|
||||
PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData), vtkm::cont::Token& token)
|
||||
{
|
||||
return PortalConstExecution(this->FirstArray.PrepareForInput(Device()),
|
||||
this->SecondArray.PrepareForInput(Device()));
|
||||
return PortalConstExecution(this->FirstArray.PrepareForInput(Device(), token),
|
||||
this->SecondArray.PrepareForInput(Device(), token));
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
PortalExecution PrepareForInPlace(bool vtkmNotUsed(updateData))
|
||||
PortalExecution PrepareForInPlace(bool vtkmNotUsed(updateData), vtkm::cont::Token& token)
|
||||
{
|
||||
return PortalExecution(this->FirstArray.PrepareForInPlace(Device()),
|
||||
this->SecondArray.PrepareForInPlace(Device()));
|
||||
return PortalExecution(this->FirstArray.PrepareForInPlace(Device(), token),
|
||||
this->SecondArray.PrepareForInPlace(Device(), token));
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
PortalExecution PrepareForOutput(vtkm::Id numberOfValues)
|
||||
PortalExecution PrepareForOutput(vtkm::Id numberOfValues, vtkm::cont::Token& token)
|
||||
{
|
||||
return PortalExecution(this->FirstArray.PrepareForOutput(numberOfValues, Device()),
|
||||
this->SecondArray.PrepareForOutput(numberOfValues, Device()));
|
||||
return PortalExecution(this->FirstArray.PrepareForOutput(numberOfValues, Device(), token),
|
||||
this->SecondArray.PrepareForOutput(numberOfValues, Device(), token));
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
@ -375,11 +370,11 @@ struct SerializableTypeString<vtkm::cont::ArrayHandleZip<AH1, AH2>>
|
||||
}
|
||||
};
|
||||
|
||||
template <typename AH1, typename AH2>
|
||||
template <typename T1, typename T2, typename ST1, typename ST2>
|
||||
struct SerializableTypeString<
|
||||
vtkm::cont::ArrayHandle<vtkm::Pair<typename AH1::ValueType, typename AH2::ValueType>,
|
||||
vtkm::cont::internal::StorageTagZip<AH1, AH2>>>
|
||||
: SerializableTypeString<vtkm::cont::ArrayHandleZip<AH1, AH2>>
|
||||
vtkm::cont::ArrayHandle<vtkm::Pair<T1, T2>, vtkm::cont::StorageTagZip<ST1, ST2>>>
|
||||
: SerializableTypeString<vtkm::cont::ArrayHandleZip<vtkm::cont::ArrayHandle<T1, ST1>,
|
||||
vtkm::cont::ArrayHandle<T2, ST2>>>
|
||||
{
|
||||
};
|
||||
}
|
||||
@ -415,11 +410,11 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template <typename AH1, typename AH2>
|
||||
template <typename T1, typename T2, typename ST1, typename ST2>
|
||||
struct Serialization<
|
||||
vtkm::cont::ArrayHandle<vtkm::Pair<typename AH1::ValueType, typename AH2::ValueType>,
|
||||
vtkm::cont::internal::StorageTagZip<AH1, AH2>>>
|
||||
: Serialization<vtkm::cont::ArrayHandleZip<AH1, AH2>>
|
||||
vtkm::cont::ArrayHandle<vtkm::Pair<T1, T2>, vtkm::cont::StorageTagZip<ST1, ST2>>>
|
||||
: Serialization<vtkm::cont::ArrayHandleZip<vtkm::cont::ArrayHandle<T1, ST1>,
|
||||
vtkm::cont::ArrayHandle<T2, ST2>>>
|
||||
{
|
||||
};
|
||||
|
||||
|
@ -51,6 +51,13 @@ namespace cont
|
||||
/// (e.g., ArrayHandleCast may be casting a read-only OR read-write array), the
|
||||
/// Set method may be conditionally removed using SFINAE.
|
||||
///
|
||||
/// The ArrayPortalToIterators utilities wrap ArrayPortals in STL-style
|
||||
/// iterators. If an ArrayPortal implementation wishes to provide a custom
|
||||
/// iterator type, it may define an IteratorType type alias along with the
|
||||
/// methods `IteratorType GetIteratorBegin()` and
|
||||
/// `IteratorType GetIteratorEnd()`. These are not required members, but if
|
||||
/// present, will allow additional optimizations for certain portals.
|
||||
///
|
||||
template <typename T>
|
||||
class ArrayPortal
|
||||
{
|
||||
|
@ -13,11 +13,42 @@
|
||||
#include <vtkm/cont/ArrayPortal.h>
|
||||
#include <vtkm/cont/internal/IteratorFromArrayPortal.h>
|
||||
|
||||
#include <vtkm/internal/ArrayPortalHelpers.h>
|
||||
|
||||
namespace vtkmstd
|
||||
{
|
||||
/// Implementation of std::void_t (C++17):
|
||||
/// Allows for specialization of class templates based on members of template
|
||||
/// parameters.
|
||||
#if defined(VTKM_GCC) && (__GNUC__ < 5)
|
||||
// Due to a defect in the wording (CWG 1558) unused parameters in alias templates
|
||||
// were not guaranteed to ensure SFINAE, and therefore would consider everything
|
||||
// to match the 'true' side. For VTK-m the only known compiler that implemented
|
||||
// this defect is GCC < 5.
|
||||
template <class... T>
|
||||
struct void_pack
|
||||
{
|
||||
using type = void;
|
||||
};
|
||||
template <class... T>
|
||||
using void_t = typename void_pack<T...>::type;
|
||||
#else
|
||||
template <typename...>
|
||||
using void_t = void;
|
||||
#endif
|
||||
|
||||
|
||||
} // end namespace vtkmstd
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace cont
|
||||
{
|
||||
|
||||
template <typename PortalType,
|
||||
typename CustomIterators = vtkm::internal::PortalSupportsIterators<PortalType>>
|
||||
class ArrayPortalToIterators;
|
||||
|
||||
/// \brief Convert an \c ArrayPortal to STL iterators.
|
||||
///
|
||||
/// \c ArrayPortalToIterators is a class that holds an \c ArrayPortal and
|
||||
@ -26,13 +57,12 @@ namespace cont
|
||||
/// STL iterators such as STL algorithms or Thrust operations.
|
||||
///
|
||||
/// The default template implementation constructs iterators that provide
|
||||
/// values through the \c ArrayPortal itself. This class can be specialized to
|
||||
/// provide iterators that more directly access the data. For example, \c
|
||||
/// ArrayPortalFromIterator has a specialization to return the original
|
||||
/// iterators.
|
||||
/// values through the \c ArrayPortal itself. However, if the \c ArrayPortal
|
||||
/// contains its own iterators (by defining \c GetIteratorBegin and
|
||||
/// \c GetIteratorEnd), then those iterators are used.
|
||||
///
|
||||
template <typename PortalType>
|
||||
class ArrayPortalToIterators
|
||||
class ArrayPortalToIterators<PortalType, std::false_type>
|
||||
{
|
||||
public:
|
||||
/// \c ArrayPortaltoIterators should be constructed with an instance of
|
||||
@ -40,11 +70,44 @@ public:
|
||||
///
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
VTKM_EXEC_CONT
|
||||
ArrayPortalToIterators(const PortalType& portal)
|
||||
explicit ArrayPortalToIterators(const PortalType& portal)
|
||||
: Portal(portal)
|
||||
{
|
||||
}
|
||||
|
||||
// These are the same as the default implementation, but explicitly created to prevent warnings
|
||||
// from the CUDA compiler where it tries to compile for the device when the underlying portal
|
||||
// only works for the host.
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
VTKM_EXEC_CONT
|
||||
ArrayPortalToIterators(const ArrayPortalToIterators& src)
|
||||
: Portal(src.Portal)
|
||||
{
|
||||
}
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
VTKM_EXEC_CONT
|
||||
ArrayPortalToIterators(ArrayPortalToIterators&& rhs)
|
||||
: Portal(std::move(rhs.Portal))
|
||||
{
|
||||
}
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
VTKM_EXEC_CONT
|
||||
~ArrayPortalToIterators() {}
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
VTKM_EXEC_CONT
|
||||
ArrayPortalToIterators& operator=(const ArrayPortalToIterators& src)
|
||||
{
|
||||
this->Portal = src.Portal;
|
||||
return *this;
|
||||
}
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
VTKM_EXEC_CONT
|
||||
ArrayPortalToIterators& operator=(ArrayPortalToIterators&& rhs)
|
||||
{
|
||||
this->Portal = std::move(rhs.Portal);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// The type of the iterator.
|
||||
///
|
||||
using IteratorType = vtkm::cont::internal::IteratorFromArrayPortal<PortalType>;
|
||||
@ -65,6 +128,71 @@ private:
|
||||
PortalType Portal;
|
||||
};
|
||||
|
||||
// Specialize for custom iterator types:
|
||||
template <typename PortalType>
|
||||
class ArrayPortalToIterators<PortalType, std::true_type>
|
||||
{
|
||||
public:
|
||||
using IteratorType = decltype(std::declval<PortalType>().GetIteratorBegin());
|
||||
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
VTKM_EXEC_CONT
|
||||
explicit ArrayPortalToIterators(const PortalType& portal)
|
||||
: Begin(portal.GetIteratorBegin())
|
||||
, End(portal.GetIteratorEnd())
|
||||
{
|
||||
}
|
||||
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
VTKM_EXEC_CONT
|
||||
IteratorType GetBegin() const { return this->Begin; }
|
||||
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
VTKM_EXEC_CONT
|
||||
IteratorType GetEnd() const { return this->End; }
|
||||
|
||||
// These are the same as the default implementation, but explicitly created to prevent warnings
|
||||
// from the CUDA compiler where it tries to compile for the device when the underlying portal
|
||||
// only works for the host.
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
VTKM_EXEC_CONT
|
||||
ArrayPortalToIterators(const ArrayPortalToIterators& src)
|
||||
: Begin(src.Begin)
|
||||
, End(src.End)
|
||||
{
|
||||
}
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
VTKM_EXEC_CONT
|
||||
ArrayPortalToIterators(ArrayPortalToIterators&& rhs)
|
||||
: Begin(std::move(rhs.Begin))
|
||||
, End(std::move(rhs.End))
|
||||
{
|
||||
}
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
VTKM_EXEC_CONT
|
||||
~ArrayPortalToIterators() {}
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
VTKM_EXEC_CONT
|
||||
ArrayPortalToIterators& operator=(const ArrayPortalToIterators& src)
|
||||
{
|
||||
this->Begin = src.Begin;
|
||||
this->End = src.End;
|
||||
return *this;
|
||||
}
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
VTKM_EXEC_CONT
|
||||
ArrayPortalToIterators& operator=(ArrayPortalToIterators&& rhs)
|
||||
{
|
||||
this->Begin = std::move(rhs.Begin);
|
||||
this->End = std::move(rhs.End);
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
IteratorType Begin;
|
||||
IteratorType End;
|
||||
};
|
||||
|
||||
/// Convenience function for converting an ArrayPortal to a begin iterator.
|
||||
///
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
|
@ -77,7 +77,7 @@ vtkm::cont::ArrayHandle<vtkm::Range> ArrayRangeCompute(
|
||||
vtkm::cont::ArrayHandleUniformPointCoordinates::StorageTag>& array,
|
||||
vtkm::cont::DeviceAdapterId)
|
||||
{
|
||||
vtkm::internal::ArrayPortalUniformPointCoordinates portal = array.GetPortalConstControl();
|
||||
vtkm::internal::ArrayPortalUniformPointCoordinates portal = array.ReadPortal();
|
||||
|
||||
// In this portal we know that the min value is the first entry and the
|
||||
// max value is the last entry.
|
||||
@ -86,7 +86,7 @@ vtkm::cont::ArrayHandle<vtkm::Range> ArrayRangeCompute(
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Range> rangeArray;
|
||||
rangeArray.Allocate(3);
|
||||
vtkm::cont::ArrayHandle<vtkm::Range>::PortalControl outPortal = rangeArray.GetPortalControl();
|
||||
vtkm::cont::ArrayHandle<vtkm::Range>::WritePortalType outPortal = rangeArray.WritePortal();
|
||||
outPortal.Set(0, vtkm::Range(minimum[0], maximum[0]));
|
||||
outPortal.Set(1, vtkm::Range(minimum[1], maximum[1]));
|
||||
outPortal.Set(2, vtkm::Range(minimum[2], maximum[2]));
|
||||
|
@ -117,11 +117,10 @@ VTKM_CONT_EXPORT VTKM_CONT vtkm::cont::ArrayHandle<vtkm::Range> ArrayRangeComput
|
||||
vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny());
|
||||
|
||||
// Implementation of cartesian products
|
||||
template <typename T, typename ArrayType1, typename ArrayType2, typename ArrayType3>
|
||||
template <typename T, typename ST1, typename ST2, typename ST3>
|
||||
VTKM_CONT inline vtkm::cont::ArrayHandle<vtkm::Range> ArrayRangeCompute(
|
||||
const vtkm::cont::ArrayHandle<
|
||||
T,
|
||||
vtkm::cont::internal::StorageTagCartesianProduct<ArrayType1, ArrayType2, ArrayType3>>& input,
|
||||
const vtkm::cont::ArrayHandle<vtkm::Vec<T, 3>,
|
||||
vtkm::cont::StorageTagCartesianProduct<ST1, ST2, ST3>>& input,
|
||||
vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny())
|
||||
{
|
||||
vtkm::cont::ArrayHandle<vtkm::Range> result;
|
||||
@ -130,20 +129,20 @@ VTKM_CONT inline vtkm::cont::ArrayHandle<vtkm::Range> ArrayRangeCompute(
|
||||
vtkm::cont::ArrayHandle<vtkm::Range> componentRangeArray;
|
||||
vtkm::Range componentRange;
|
||||
|
||||
ArrayType1 firstArray = input.GetStorage().GetFirstArray();
|
||||
vtkm::cont::ArrayHandle<T, ST1> firstArray = input.GetStorage().GetFirstArray();
|
||||
componentRangeArray = vtkm::cont::ArrayRangeCompute(firstArray, device);
|
||||
componentRange = componentRangeArray.GetPortalConstControl().Get(0);
|
||||
result.GetPortalControl().Set(0, componentRange);
|
||||
componentRange = componentRangeArray.ReadPortal().Get(0);
|
||||
result.WritePortal().Set(0, componentRange);
|
||||
|
||||
ArrayType2 secondArray = input.GetStorage().GetSecondArray();
|
||||
vtkm::cont::ArrayHandle<T, ST2> secondArray = input.GetStorage().GetSecondArray();
|
||||
componentRangeArray = vtkm::cont::ArrayRangeCompute(secondArray, device);
|
||||
componentRange = componentRangeArray.GetPortalConstControl().Get(0);
|
||||
result.GetPortalControl().Set(1, componentRange);
|
||||
componentRange = componentRangeArray.ReadPortal().Get(0);
|
||||
result.WritePortal().Set(1, componentRange);
|
||||
|
||||
ArrayType3 thirdArray = input.GetStorage().GetThirdArray();
|
||||
vtkm::cont::ArrayHandle<T, ST3> thirdArray = input.GetStorage().GetThirdArray();
|
||||
componentRangeArray = vtkm::cont::ArrayRangeCompute(thirdArray, device);
|
||||
componentRange = componentRangeArray.GetPortalConstControl().Get(0);
|
||||
result.GetPortalControl().Set(2, componentRange);
|
||||
componentRange = componentRangeArray.ReadPortal().Get(0);
|
||||
result.WritePortal().Set(2, componentRange);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ inline vtkm::cont::ArrayHandle<vtkm::Range> ArrayRangeComputeImpl(
|
||||
|
||||
if (input.GetNumberOfValues() < 1)
|
||||
{
|
||||
auto portal = range.GetPortalControl();
|
||||
auto portal = range.WritePortal();
|
||||
for (vtkm::IdComponent i = 0; i < VecTraits::NUM_COMPONENTS; ++i)
|
||||
{
|
||||
portal.Set(i, vtkm::Range());
|
||||
@ -79,7 +79,7 @@ inline vtkm::cont::ArrayHandle<vtkm::Range> ArrayRangeComputeImpl(
|
||||
}
|
||||
else
|
||||
{
|
||||
auto portal = range.GetPortalControl();
|
||||
auto portal = range.WritePortal();
|
||||
for (vtkm::IdComponent i = 0; i < VecTraits::NUM_COMPONENTS; ++i)
|
||||
{
|
||||
portal.Set(i,
|
||||
|
@ -49,6 +49,11 @@ AssignerPartitionedDataSet::AssignerPartitionedDataSet(vtkm::Id num_partitions)
|
||||
this->set_nblocks(static_cast<int>(this->IScanPartitionCounts.back()));
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
AssignerPartitionedDataSet::~AssignerPartitionedDataSet()
|
||||
{
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
void AssignerPartitionedDataSet::local_gids(int my_rank, std::vector<int>& gids) const
|
||||
{
|
||||
|
@ -58,6 +58,9 @@ public:
|
||||
VTKM_CONT
|
||||
AssignerPartitionedDataSet(vtkm::Id num_partitions);
|
||||
|
||||
VTKM_CONT
|
||||
virtual ~AssignerPartitionedDataSet();
|
||||
|
||||
///@{
|
||||
/// vtkmdiy::Assigner API implementation.
|
||||
VTKM_CONT
|
||||
|
@ -10,6 +10,7 @@
|
||||
#ifndef vtk_m_cont_AtomicArray_h
|
||||
#define vtk_m_cont_AtomicArray_h
|
||||
|
||||
#include <vtkm/List.h>
|
||||
#include <vtkm/ListTag.h>
|
||||
#include <vtkm/StaticAssert.h>
|
||||
#include <vtkm/cont/ArrayHandle.h>
|
||||
@ -24,8 +25,12 @@ namespace cont
|
||||
|
||||
/// \brief A type list containing types that can be used with an AtomicArray.
|
||||
///
|
||||
struct AtomicArrayTypeListTag
|
||||
: vtkm::ListTagBase<vtkm::UInt32, vtkm::Int32, vtkm::UInt64, vtkm::Int64>
|
||||
using AtomicArrayTypeList = vtkm::List<vtkm::UInt32, vtkm::Int32, vtkm::UInt64, vtkm::Int64>;
|
||||
|
||||
struct VTKM_DEPRECATED(1.6,
|
||||
"AtomicArrayTypeListTag replaced by AtomicArrayTypeList. Note that the "
|
||||
"new AtomicArrayTypeList cannot be subclassed.") AtomicArrayTypeListTag
|
||||
: vtkm::internal::ListAsListTag<AtomicArrayTypeList>
|
||||
{
|
||||
};
|
||||
|
||||
@ -48,7 +53,7 @@ struct AtomicArrayTypeListTag
|
||||
template <typename T>
|
||||
class AtomicArray : public vtkm::cont::ExecutionObjectBase
|
||||
{
|
||||
static constexpr bool ValueTypeIsValid = vtkm::ListContains<AtomicArrayTypeListTag, T>::value;
|
||||
static constexpr bool ValueTypeIsValid = vtkm::ListHas<AtomicArrayTypeList, T>::value;
|
||||
VTKM_STATIC_ASSERT_MSG(ValueTypeIsValid, "AtomicArray used with unsupported ValueType.");
|
||||
|
||||
|
||||
@ -67,9 +72,19 @@ public:
|
||||
}
|
||||
|
||||
template <typename Device>
|
||||
VTKM_CONT vtkm::exec::AtomicArrayExecutionObject<T, Device> PrepareForExecution(Device) const
|
||||
VTKM_CONT vtkm::exec::AtomicArrayExecutionObject<T, Device> PrepareForExecution(
|
||||
Device,
|
||||
vtkm::cont::Token& token) const
|
||||
{
|
||||
return vtkm::exec::AtomicArrayExecutionObject<T, Device>(this->Handle);
|
||||
return vtkm::exec::AtomicArrayExecutionObject<T, Device>(this->Handle, token);
|
||||
}
|
||||
|
||||
template <typename Device>
|
||||
VTKM_CONT VTKM_DEPRECATED(1.6, "PrepareForExecution now requires a vtkm::cont::Token object.")
|
||||
vtkm::exec::AtomicArrayExecutionObject<T, Device> PrepareForExecution(Device device) const
|
||||
{
|
||||
vtkm::cont::Token token;
|
||||
return this->PrepareForExecution(device, token);
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -17,7 +17,8 @@
|
||||
#include <vtkm/cont/ArrayHandle.h>
|
||||
#include <vtkm/cont/Logging.h>
|
||||
|
||||
#include <vtkm/ListTag.h>
|
||||
#include <vtkm/Deprecated.h>
|
||||
#include <vtkm/List.h>
|
||||
#include <vtkm/Types.h>
|
||||
|
||||
#include <cassert>
|
||||
@ -61,16 +62,16 @@ struct BitFieldTraits
|
||||
/// Require an unsigned integral type that is <= BlockSize bytes, and is
|
||||
/// is supported by the specified AtomicInterface.
|
||||
template <typename WordType, typename AtomicInterface>
|
||||
using IsValidWordTypeAtomic = std::integral_constant<
|
||||
bool,
|
||||
/* is unsigned */
|
||||
std::is_unsigned<WordType>::value &&
|
||||
/* doesn't exceed blocksize */
|
||||
sizeof(WordType) <= static_cast<size_t>(BlockSize) &&
|
||||
/* BlockSize is a multiple of WordType */
|
||||
static_cast<size_t>(BlockSize) % sizeof(WordType) == 0 &&
|
||||
/* Supported by atomic interface */
|
||||
vtkm::ListContains<typename AtomicInterface::WordTypes, WordType>::value>;
|
||||
using IsValidWordTypeAtomic =
|
||||
std::integral_constant<bool,
|
||||
/* is unsigned */
|
||||
std::is_unsigned<WordType>::value &&
|
||||
/* doesn't exceed blocksize */
|
||||
sizeof(WordType) <= static_cast<size_t>(BlockSize) &&
|
||||
/* BlockSize is a multiple of WordType */
|
||||
static_cast<size_t>(BlockSize) % sizeof(WordType) == 0 &&
|
||||
/* Supported by atomic interface */
|
||||
vtkm::ListHas<typename AtomicInterface::WordTypes, WordType>::value>;
|
||||
};
|
||||
|
||||
/// Identifies a bit in a BitField by Word and BitOffset. Note that these
|
||||
@ -500,10 +501,17 @@ public:
|
||||
using ArrayHandleType = ArrayHandle<WordTypeDefault, StorageTagBasic>;
|
||||
|
||||
/// The BitPortal used in the control environment.
|
||||
using PortalControl = detail::BitPortal<vtkm::cont::internal::AtomicInterfaceControl>;
|
||||
using WritePortalType = vtkm::cont::internal::ArrayPortalToken<
|
||||
detail::BitPortal<vtkm::cont::internal::AtomicInterfaceControl>>;
|
||||
|
||||
/// A read-only BitPortal used in the control environment.
|
||||
using PortalConstControl = detail::BitPortalConst<vtkm::cont::internal::AtomicInterfaceControl>;
|
||||
using ReadPortalType = vtkm::cont::internal::ArrayPortalToken<
|
||||
detail::BitPortalConst<vtkm::cont::internal::AtomicInterfaceControl>>;
|
||||
|
||||
using PortalControl VTKM_DEPRECATED(1.6, "Use BitField::WritePortalType instead.") =
|
||||
detail::BitPortal<vtkm::cont::internal::AtomicInterfaceControl>;
|
||||
using PortalConstControl VTKM_DEPRECATED(1.6, "Use ArrayBitField::ReadPortalType instead.") =
|
||||
detail::BitPortalConst<vtkm::cont::internal::AtomicInterfaceControl>;
|
||||
|
||||
template <typename Device>
|
||||
struct ExecutionTypes
|
||||
@ -624,20 +632,46 @@ public:
|
||||
VTKM_CONT
|
||||
DeviceAdapterId GetDeviceAdapterId() const { return this->Internals->Data.GetDeviceAdapterId(); }
|
||||
|
||||
/// Get a portal to the data that is usable from the control environment.
|
||||
VTKM_CONT
|
||||
PortalControl GetPortalControl()
|
||||
/// \brief Get a portal to the data that is usable from the control environment.
|
||||
///
|
||||
/// As long as this portal is in scope, no one else will be able to read or write the BitField.
|
||||
VTKM_CONT WritePortalType WritePortal() const
|
||||
{
|
||||
return PortalControl{ this->Internals->Data.GetPortalControl(), this->Internals->NumberOfBits };
|
||||
auto dataPortal = this->Internals->Data.WritePortal();
|
||||
return WritePortalType{ dataPortal.GetToken(), dataPortal, this->Internals->NumberOfBits };
|
||||
}
|
||||
|
||||
/// \brief Get a read-only portal to the data that is usable from the control environment.
|
||||
///
|
||||
/// As long as this portal is in scope, no one else will be able to write in the BitField.
|
||||
VTKM_CONT ReadPortalType ReadPortal() const
|
||||
{
|
||||
auto dataPortal = this->Internals->Data.ReadPortal();
|
||||
return ReadPortalType{ dataPortal.GetToken(), dataPortal, this->Internals->NumberOfBits };
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
VTKM_DEPRECATED(1.6,
|
||||
"Use BitField::WritePortal() instead. "
|
||||
"Note that the returned portal will lock the array while it is in scope.")
|
||||
detail::BitPortal<vtkm::cont::internal::AtomicInterfaceControl> GetPortalControl()
|
||||
{
|
||||
return detail::BitPortal<vtkm::cont::internal::AtomicInterfaceControl>{
|
||||
this->Internals->Data.WritePortal(), this->Internals->NumberOfBits
|
||||
};
|
||||
}
|
||||
|
||||
/// Get a read-only portal to the data that is usable from the control
|
||||
/// environment.
|
||||
VTKM_CONT
|
||||
PortalConstControl GetPortalConstControl() const
|
||||
VTKM_DEPRECATED(1.6,
|
||||
"Use BitField::ReadPortal() instead. "
|
||||
"Note that the returned portal will lock the array while it is in scope.")
|
||||
detail::BitPortalConst<vtkm::cont::internal::AtomicInterfaceControl> GetPortalConstControl() const
|
||||
{
|
||||
return PortalConstControl{ this->Internals->Data.GetPortalConstControl(),
|
||||
this->Internals->NumberOfBits };
|
||||
return detail::BitPortalConst<vtkm::cont::internal::AtomicInterfaceControl>{
|
||||
this->Internals->Data.ReadPortal(), this->Internals->NumberOfBits
|
||||
};
|
||||
}
|
||||
|
||||
/// Prepares this BitField to be used as an input to an operation in the
|
||||
@ -647,13 +681,23 @@ public:
|
||||
/// execution environment.
|
||||
template <typename DeviceAdapterTag>
|
||||
VTKM_CONT typename ExecutionTypes<DeviceAdapterTag>::PortalConst PrepareForInput(
|
||||
DeviceAdapterTag device) const
|
||||
DeviceAdapterTag device,
|
||||
vtkm::cont::Token& token) const
|
||||
{
|
||||
using PortalType = typename ExecutionTypes<DeviceAdapterTag>::PortalConst;
|
||||
return PortalType{ this->Internals->Data.PrepareForInput(device),
|
||||
return PortalType{ this->Internals->Data.PrepareForInput(device, token),
|
||||
this->Internals->NumberOfBits };
|
||||
}
|
||||
|
||||
template <typename DeviceAdapterTag>
|
||||
VTKM_CONT VTKM_DEPRECATED(1.6, "PrepareForInput now requires a vtkm::cont::Token object.")
|
||||
typename ExecutionTypes<DeviceAdapterTag>::PortalConst
|
||||
PrepareForInput(DeviceAdapterTag device) const
|
||||
{
|
||||
vtkm::cont::Token token;
|
||||
return this->PrepareForInput(device, token);
|
||||
}
|
||||
|
||||
/// Prepares (allocates) this BitField to be used as an output from an
|
||||
/// operation in the execution environment. The internal state of this class
|
||||
/// is set to have valid data in the execution BitField with the assumption
|
||||
@ -661,9 +705,8 @@ public:
|
||||
/// object are called). Returns a portal that can be used in code running in
|
||||
/// the execution environment.
|
||||
template <typename DeviceAdapterTag>
|
||||
VTKM_CONT typename ExecutionTypes<DeviceAdapterTag>::Portal PrepareForOutput(
|
||||
vtkm::Id numBits,
|
||||
DeviceAdapterTag device) const
|
||||
VTKM_CONT typename ExecutionTypes<DeviceAdapterTag>::Portal
|
||||
PrepareForOutput(vtkm::Id numBits, DeviceAdapterTag device, vtkm::cont::Token& token) const
|
||||
{
|
||||
using PortalType = typename ExecutionTypes<DeviceAdapterTag>::Portal;
|
||||
const vtkm::Id numWords = this->BitsToAllocatedStorageWords(numBits);
|
||||
@ -675,11 +718,20 @@ public:
|
||||
static_cast<vtkm::UInt64>(static_cast<size_t>(numWords) * sizeof(WordTypeDefault)))
|
||||
.c_str());
|
||||
|
||||
auto portal = this->Internals->Data.PrepareForOutput(numWords, device);
|
||||
auto portal = this->Internals->Data.PrepareForOutput(numWords, device, token);
|
||||
this->Internals->NumberOfBits = numBits;
|
||||
return PortalType{ portal, numBits };
|
||||
}
|
||||
|
||||
template <typename DeviceAdapterTag>
|
||||
VTKM_CONT VTKM_DEPRECATED(1.6, "PrepareForOutput now requires a vtkm::cont::Token object.")
|
||||
typename ExecutionTypes<DeviceAdapterTag>::Portal
|
||||
PrepareForOutput(vtkm::Id numBits, DeviceAdapterTag device) const
|
||||
{
|
||||
vtkm::cont::Token token;
|
||||
return this->PrepareForOutput(numBits, device, token);
|
||||
}
|
||||
|
||||
/// Prepares this BitField to be used in an in-place operation (both as input
|
||||
/// and output) in the execution environment. If necessary, copies data to
|
||||
/// the execution environment. Can throw an exception if this BitField does
|
||||
@ -687,13 +739,23 @@ public:
|
||||
/// running in the execution environment.
|
||||
template <typename DeviceAdapterTag>
|
||||
VTKM_CONT typename ExecutionTypes<DeviceAdapterTag>::Portal PrepareForInPlace(
|
||||
DeviceAdapterTag device) const
|
||||
DeviceAdapterTag device,
|
||||
vtkm::cont::Token& token) const
|
||||
{
|
||||
using PortalType = typename ExecutionTypes<DeviceAdapterTag>::Portal;
|
||||
return PortalType{ this->Internals->Data.PrepareForInPlace(device),
|
||||
return PortalType{ this->Internals->Data.PrepareForInPlace(device, token),
|
||||
this->Internals->NumberOfBits };
|
||||
}
|
||||
|
||||
template <typename DeviceAdapterTag>
|
||||
VTKM_CONT VTKM_DEPRECATED(1.6, "PrepareForInPlace now requires a vtkm::cont::Token object.")
|
||||
typename ExecutionTypes<DeviceAdapterTag>::Portal
|
||||
PrepareForInPlace(DeviceAdapterTag device) const
|
||||
{
|
||||
vtkm::cont::Token token;
|
||||
return this->PrepareForInPlace(device, token);
|
||||
}
|
||||
|
||||
private:
|
||||
/// Returns the number of words, padded out to respect BlockSize.
|
||||
VTKM_CONT
|
||||
|
@ -29,12 +29,12 @@ vtkm::Bounds MergeBoundsGlobal(const vtkm::Bounds& local)
|
||||
{
|
||||
vtkm::cont::ArrayHandle<vtkm::Range> ranges;
|
||||
ranges.Allocate(3);
|
||||
ranges.GetPortalControl().Set(0, local.X);
|
||||
ranges.GetPortalControl().Set(1, local.Y);
|
||||
ranges.GetPortalControl().Set(2, local.Z);
|
||||
ranges.WritePortal().Set(0, local.X);
|
||||
ranges.WritePortal().Set(1, local.Y);
|
||||
ranges.WritePortal().Set(2, local.Z);
|
||||
|
||||
ranges = vtkm::cont::detail::MergeRangesGlobal(ranges);
|
||||
auto portal = ranges.GetPortalConstControl();
|
||||
auto portal = ranges.ReadPortal();
|
||||
return vtkm::Bounds(portal.Get(0), portal.Get(1), portal.Get(2));
|
||||
}
|
||||
}
|
||||
|
@ -59,6 +59,7 @@ set(headers
|
||||
CellSet.h
|
||||
CellSetExplicit.h
|
||||
CellSetExtrude.h
|
||||
CellSetList.h
|
||||
CellSetListTag.h
|
||||
CellSetPermutation.h
|
||||
CellSetSingleType.h
|
||||
@ -73,6 +74,7 @@ set(headers
|
||||
DataSetFieldAdd.h
|
||||
DeviceAdapter.h
|
||||
DeviceAdapterAlgorithm.h
|
||||
DeviceAdapterList.h
|
||||
DeviceAdapterListTag.h
|
||||
DeviceAdapterTag.h
|
||||
DynamicCellSet.h
|
||||
@ -104,9 +106,11 @@ set(headers
|
||||
StorageBasic.h
|
||||
StorageExtrude.h
|
||||
StorageImplicit.h
|
||||
StorageList.h
|
||||
StorageListTag.h
|
||||
StorageVirtual.h
|
||||
Timer.h
|
||||
Token.h
|
||||
TryExecute.h
|
||||
SerializableTypeString.h
|
||||
VariantArrayHandle.h
|
||||
@ -145,6 +149,7 @@ set(sources
|
||||
Logging.cxx
|
||||
RuntimeDeviceTracker.cxx
|
||||
StorageBasic.cxx
|
||||
Token.cxx
|
||||
TryExecute.cxx
|
||||
)
|
||||
|
||||
@ -211,6 +216,7 @@ if(TARGET vtkm::openmp)
|
||||
endif()
|
||||
|
||||
target_link_libraries(vtkm_cont PUBLIC vtkm_compiler_flags ${backends})
|
||||
target_link_libraries(vtkm_cont PUBLIC Threads::Threads)
|
||||
target_link_libraries(vtkm_cont PUBLIC vtkm_taotuple vtkm_optionparser vtkm_diy vtkm_lcl)
|
||||
if(TARGET vtkm_loguru)
|
||||
target_link_libraries(vtkm_cont PRIVATE vtkm_loguru)
|
||||
|
@ -56,7 +56,16 @@ public:
|
||||
}
|
||||
|
||||
VTKM_CONT virtual const vtkm::exec::CellLocator* PrepareForExecution(
|
||||
vtkm::cont::DeviceAdapterId device) const = 0;
|
||||
vtkm::cont::DeviceAdapterId device,
|
||||
vtkm::cont::Token& token) const = 0;
|
||||
|
||||
VTKM_CONT
|
||||
VTKM_DEPRECATED(1.6, "PrepareForExecution now requires a vtkm::cont::Token object.")
|
||||
const vtkm::exec::CellLocator* PrepareForExecution(vtkm::cont::DeviceAdapterId device) const
|
||||
{
|
||||
vtkm::cont::Token token;
|
||||
return this->PrepareForExecution(device, token);
|
||||
}
|
||||
|
||||
protected:
|
||||
void SetModified() { this->Modified = true; }
|
||||
|
@ -266,13 +266,13 @@ void CellLocatorBoundingIntervalHierarchy::Build()
|
||||
IdArrayHandle discardKeys;
|
||||
IdArrayHandle segmentSizes;
|
||||
segmentSizes.Allocate(1);
|
||||
segmentSizes.GetPortalControl().Set(0, numCells);
|
||||
segmentSizes.WritePortal().Set(0, numCells);
|
||||
this->ProcessedCellIds.Allocate(numCells);
|
||||
vtkm::Id cellIdsOffset = 0;
|
||||
|
||||
IdArrayHandle parentIndices;
|
||||
parentIndices.Allocate(1);
|
||||
parentIndices.GetPortalControl().Set(0, -1);
|
||||
parentIndices.WritePortal().Set(0, -1);
|
||||
|
||||
while (!done)
|
||||
{
|
||||
@ -453,6 +453,7 @@ struct CellLocatorBIHPrepareForExecutionFunctor
|
||||
bool operator()(
|
||||
DeviceAdapter,
|
||||
const CellSetType& cellset,
|
||||
vtkm::cont::Token& token,
|
||||
vtkm::cont::VirtualObjectHandle<vtkm::exec::CellLocator>& bihExec,
|
||||
const vtkm::cont::ArrayHandle<vtkm::exec::CellLocatorBoundingIntervalHierarchyNode>& nodes,
|
||||
const vtkm::cont::ArrayHandle<vtkm::Id>& processedCellIds,
|
||||
@ -461,7 +462,7 @@ struct CellLocatorBIHPrepareForExecutionFunctor
|
||||
using ExecutionType =
|
||||
vtkm::exec::CellLocatorBoundingIntervalHierarchyExec<DeviceAdapter, CellSetType>;
|
||||
ExecutionType* execObject =
|
||||
new ExecutionType(nodes, processedCellIds, cellset, coords, DeviceAdapter());
|
||||
new ExecutionType(nodes, processedCellIds, cellset, coords, DeviceAdapter(), token);
|
||||
bihExec.Reset(execObject);
|
||||
return true;
|
||||
}
|
||||
@ -470,11 +471,17 @@ struct CellLocatorBIHPrepareForExecutionFunctor
|
||||
struct BIHCellSetCaster
|
||||
{
|
||||
template <typename CellSet, typename... Args>
|
||||
void operator()(CellSet&& cellset, vtkm::cont::DeviceAdapterId device, Args&&... args) const
|
||||
void operator()(CellSet&& cellset,
|
||||
vtkm::cont::DeviceAdapterId device,
|
||||
vtkm::cont::Token& token,
|
||||
Args&&... args) const
|
||||
{
|
||||
//We need to go though CastAndCall first
|
||||
const bool success = vtkm::cont::TryExecuteOnDevice(
|
||||
device, CellLocatorBIHPrepareForExecutionFunctor(), cellset, std::forward<Args>(args)...);
|
||||
const bool success = vtkm::cont::TryExecuteOnDevice(device,
|
||||
CellLocatorBIHPrepareForExecutionFunctor(),
|
||||
cellset,
|
||||
token,
|
||||
std::forward<Args>(args)...);
|
||||
if (!success)
|
||||
{
|
||||
throwFailedRuntimeDeviceTransfer("BoundingIntervalHierarchy", device);
|
||||
@ -485,15 +492,17 @@ struct BIHCellSetCaster
|
||||
|
||||
|
||||
const vtkm::exec::CellLocator* CellLocatorBoundingIntervalHierarchy::PrepareForExecution(
|
||||
vtkm::cont::DeviceAdapterId device) const
|
||||
vtkm::cont::DeviceAdapterId device,
|
||||
vtkm::cont::Token& token) const
|
||||
{
|
||||
this->GetCellSet().CastAndCall(BIHCellSetCaster{},
|
||||
device,
|
||||
token,
|
||||
this->ExecutionObjectHandle,
|
||||
this->Nodes,
|
||||
this->ProcessedCellIds,
|
||||
this->GetCoordinates().GetData());
|
||||
return this->ExecutionObjectHandle.PrepareForExecution(device);
|
||||
return this->ExecutionObjectHandle.PrepareForExecution(device, token);
|
||||
;
|
||||
}
|
||||
|
||||
|
@ -62,8 +62,8 @@ public:
|
||||
vtkm::Id GetMaxLeafSize() { return this->MaxLeafSize; }
|
||||
|
||||
VTKM_CONT
|
||||
const vtkm::exec::CellLocator* PrepareForExecution(
|
||||
vtkm::cont::DeviceAdapterId device) const override;
|
||||
const vtkm::exec::CellLocator* PrepareForExecution(vtkm::cont::DeviceAdapterId device,
|
||||
vtkm::cont::Token& token) const override;
|
||||
|
||||
protected:
|
||||
VTKM_CONT
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user