//============================================================================ // Copyright (c) Kitware, Inc. // All rights reserved. // See LICENSE.txt for details. // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notice for more information. //============================================================================ #include #include #include #include #include namespace { constexpr vtkm::Id ARRAY_SIZE = 10; using ScalarTypesToTest = vtkm::List; using VectorTypesToTest = vtkm::List; struct PassThrough : public vtkm::worklet::WorkletMapField { using ControlSignature = void(FieldIn, FieldOut); using ExecutionSignature = void(_1, _2); template VTKM_EXEC void operator()(const InValue& inValue, OutValue& outValue) const { outValue = inValue; } }; struct TestArrayPortalSOA { template VTKM_CONT void operator()(ComponentType) const { constexpr vtkm::IdComponent NUM_COMPONENTS = 4; using ValueType = vtkm::Vec; using ComponentArrayType = vtkm::cont::ArrayHandle; using SOAPortalType = vtkm::internal::ArrayPortalSOA; std::cout << "Test SOA portal reflects data in component portals." << std::endl; SOAPortalType soaPortalIn(ARRAY_SIZE); std::array, NUM_COMPONENTS> implArrays; for (vtkm::IdComponent componentIndex = 0; componentIndex < NUM_COMPONENTS; ++componentIndex) { vtkm::cont::ArrayHandle array; array.Allocate(ARRAY_SIZE); auto portal = array.WritePortal(); for (vtkm::IdComponent valueIndex = 0; valueIndex < ARRAY_SIZE; ++valueIndex) { portal.Set(valueIndex, TestValue(valueIndex, ValueType{})[componentIndex]); } soaPortalIn.SetPortal(componentIndex, portal); implArrays[static_cast(componentIndex)] = array; } VTKM_TEST_ASSERT(soaPortalIn.GetNumberOfValues() == ARRAY_SIZE); CheckPortal(soaPortalIn); std::cout << "Test data set in SOA portal gets set in component portals." << std::endl; { SOAPortalType soaPortalOut(ARRAY_SIZE); for (vtkm::IdComponent componentIndex = 0; componentIndex < NUM_COMPONENTS; ++componentIndex) { vtkm::cont::ArrayHandle array; array.Allocate(ARRAY_SIZE); auto portal = array.WritePortal(); soaPortalOut.SetPortal(componentIndex, portal); implArrays[static_cast(componentIndex)] = array; } SetPortal(soaPortalOut); } for (vtkm::IdComponent componentIndex = 0; componentIndex < NUM_COMPONENTS; ++componentIndex) { auto portal = implArrays[static_cast(componentIndex)].ReadPortal(); for (vtkm::Id valueIndex = 0; valueIndex < ARRAY_SIZE; ++valueIndex) { ComponentType x = TestValue(valueIndex, ValueType{})[componentIndex]; VTKM_TEST_ASSERT(test_equal(x, portal.Get(valueIndex))); } } } }; struct TestSOAAsInput { template VTKM_CONT void operator()(const ValueType vtkmNotUsed(v)) const { using VTraits = vtkm::VecTraits; using ComponentType = typename VTraits::ComponentType; constexpr vtkm::IdComponent NUM_COMPONENTS = VTraits::NUM_COMPONENTS; { vtkm::cont::ArrayHandleSOA soaArray; for (vtkm::IdComponent componentIndex = 0; componentIndex < NUM_COMPONENTS; ++componentIndex) { vtkm::cont::ArrayHandle componentArray; componentArray.Allocate(ARRAY_SIZE); auto componentPortal = componentArray.WritePortal(); for (vtkm::Id valueIndex = 0; valueIndex < ARRAY_SIZE; ++valueIndex) { componentPortal.Set( valueIndex, VTraits::GetComponent(TestValue(valueIndex, ValueType{}), componentIndex)); } soaArray.SetArray(componentIndex, componentArray); } VTKM_TEST_ASSERT(soaArray.GetNumberOfValues() == ARRAY_SIZE); VTKM_TEST_ASSERT(soaArray.ReadPortal().GetNumberOfValues() == ARRAY_SIZE); CheckPortal(soaArray.ReadPortal()); vtkm::cont::ArrayHandle basicArray; vtkm::cont::ArrayCopyDevice(soaArray, basicArray); VTKM_TEST_ASSERT(basicArray.GetNumberOfValues() == ARRAY_SIZE); CheckPortal(basicArray.ReadPortal()); } { // Check constructors using Vec3 = vtkm::Vec; std::vector vector0; std::vector vector1; std::vector vector2; for (vtkm::Id valueIndex = 0; valueIndex < ARRAY_SIZE; ++valueIndex) { Vec3 value = TestValue(valueIndex, Vec3{}); vector0.push_back(value[0]); vector1.push_back(value[1]); vector2.push_back(value[2]); } { vtkm::cont::ArrayHandleSOA soaArray = vtkm::cont::make_ArrayHandleSOA({ vector0, vector1, vector2 }); VTKM_TEST_ASSERT(soaArray.GetNumberOfValues() == ARRAY_SIZE); CheckPortal(soaArray.ReadPortal()); } { vtkm::cont::ArrayHandleSOA soaArray = vtkm::cont::make_ArrayHandleSOA(vtkm::CopyFlag::Off, vector0, vector1, vector2); VTKM_TEST_ASSERT(soaArray.GetNumberOfValues() == ARRAY_SIZE); CheckPortal(soaArray.ReadPortal()); // Make sure calling ReleaseResources does not result in error. soaArray.ReleaseResources(); } { vtkm::cont::ArrayHandleSOA soaArray = vtkm::cont::make_ArrayHandleSOA( { vector0.data(), vector1.data(), vector2.data() }, ARRAY_SIZE, vtkm::CopyFlag::Off); VTKM_TEST_ASSERT(soaArray.GetNumberOfValues() == ARRAY_SIZE); CheckPortal(soaArray.ReadPortal()); } { vtkm::cont::ArrayHandleSOA soaArray = vtkm::cont::make_ArrayHandleSOA( ARRAY_SIZE, vtkm::CopyFlag::Off, vector0.data(), vector1.data(), vector2.data()); VTKM_TEST_ASSERT(soaArray.GetNumberOfValues() == ARRAY_SIZE); CheckPortal(soaArray.ReadPortal()); } } } }; struct TestSOAAsOutput { template VTKM_CONT void operator()(const ValueType vtkmNotUsed(v)) const { using VTraits = vtkm::VecTraits; using ComponentType = typename VTraits::ComponentType; constexpr vtkm::IdComponent NUM_COMPONENTS = VTraits::NUM_COMPONENTS; vtkm::cont::ArrayHandle basicArray; basicArray.Allocate(ARRAY_SIZE); SetPortal(basicArray.WritePortal()); vtkm::cont::ArrayHandleSOA soaArray; vtkm::cont::Invoker{}(PassThrough{}, basicArray, soaArray); VTKM_TEST_ASSERT(soaArray.GetNumberOfValues() == ARRAY_SIZE); for (vtkm::IdComponent componentIndex = 0; componentIndex < NUM_COMPONENTS; ++componentIndex) { vtkm::cont::ArrayHandle componentArray = soaArray.GetArray(componentIndex); auto componentPortal = componentArray.ReadPortal(); for (vtkm::Id valueIndex = 0; valueIndex < ARRAY_SIZE; ++valueIndex) { ComponentType expected = VTraits::GetComponent(TestValue(valueIndex, ValueType{}), componentIndex); ComponentType got = componentPortal.Get(valueIndex); VTKM_TEST_ASSERT(test_equal(expected, got)); } } } }; static void Run() { std::cout << "-------------------------------------------" << std::endl; std::cout << "Testing ArrayPortalSOA" << std::endl; vtkm::testing::Testing::TryTypes(TestArrayPortalSOA(), ScalarTypesToTest()); std::cout << "-------------------------------------------" << std::endl; std::cout << "Testing ArrayHandleSOA as Input" << std::endl; vtkm::testing::Testing::TryTypes(TestSOAAsInput(), VectorTypesToTest()); std::cout << "-------------------------------------------" << std::endl; std::cout << "Testing ArrayHandleSOA as Output" << std::endl; vtkm::testing::Testing::TryTypes(TestSOAAsOutput(), VectorTypesToTest()); } } // anonymous namespace int UnitTestArrayHandleSOA(int argc, char* argv[]) { return vtkm::cont::testing::Testing::Run(Run, argc, argv); }