2015-08-26 16:30:15 +00:00
|
|
|
//============================================================================
|
|
|
|
// Copyright (c) Kitware, Inc.
|
|
|
|
// All rights reserved.
|
|
|
|
// See LICENSE.txt for details.
|
2019-04-15 23:24:21 +00:00
|
|
|
//
|
2015-08-26 16:30:15 +00:00
|
|
|
// 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.
|
|
|
|
//============================================================================
|
2016-04-13 19:52:15 +00:00
|
|
|
#ifndef vtk_m_interop_testing_TestingOpenGLInterop_h
|
|
|
|
#define vtk_m_interop_testing_TestingOpenGLInterop_h
|
2015-08-26 16:30:15 +00:00
|
|
|
|
|
|
|
#include <vtkm/cont/ArrayHandle.h>
|
|
|
|
#include <vtkm/cont/ArrayHandleConstant.h>
|
2022-01-31 15:58:38 +00:00
|
|
|
#include <vtkm/filter/vector_analysis/worklet/Magnitude.h>
|
2015-08-26 16:30:15 +00:00
|
|
|
#include <vtkm/worklet/DispatcherMapField.h>
|
|
|
|
|
2016-04-13 19:52:15 +00:00
|
|
|
#include <vtkm/interop/TransferToOpenGL.h>
|
2015-08-26 16:30:15 +00:00
|
|
|
|
|
|
|
#include <vtkm/cont/testing/Testing.h>
|
|
|
|
// #include <vtkm/cont/testing/TestingGridGenerator.h>
|
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
#include <iterator>
|
2018-08-02 16:15:04 +00:00
|
|
|
#include <random>
|
2015-08-26 16:30:15 +00:00
|
|
|
#include <vector>
|
|
|
|
|
2017-05-18 14:29:41 +00:00
|
|
|
namespace vtkm
|
|
|
|
{
|
|
|
|
namespace interop
|
|
|
|
{
|
|
|
|
namespace testing
|
|
|
|
{
|
2015-08-26 16:30:15 +00:00
|
|
|
|
|
|
|
/// This class has a single static member, Run, that tests the templated
|
|
|
|
/// DeviceAdapter for support for opengl interop.
|
|
|
|
///
|
2017-05-18 14:29:41 +00:00
|
|
|
template <class DeviceAdapterTag, class StorageTag = VTKM_DEFAULT_STORAGE_TAG>
|
2015-08-26 16:30:15 +00:00
|
|
|
struct TestingOpenGLInterop
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
//fill the array with a collection of values and return it wrapped in
|
|
|
|
//an vtkm array handle
|
2017-05-18 14:29:41 +00:00
|
|
|
template <typename T>
|
|
|
|
static vtkm::cont::ArrayHandle<T, StorageTag> FillArray(std::vector<T>& data, std::size_t length)
|
2015-08-26 16:30:15 +00:00
|
|
|
{
|
2018-02-22 13:29:13 +00:00
|
|
|
using iterator = typename std::vector<T>::iterator;
|
2015-08-26 16:30:15 +00:00
|
|
|
//make sure the data array is exactly the right length
|
|
|
|
data.clear();
|
|
|
|
data.resize(length);
|
|
|
|
vtkm::Id pos = 0;
|
2017-05-18 14:29:41 +00:00
|
|
|
for (iterator i = data.begin(); i != data.end(); ++i, ++pos)
|
|
|
|
{
|
|
|
|
*i = TestValue(pos, T());
|
|
|
|
}
|
2015-08-26 16:30:15 +00:00
|
|
|
|
2018-08-02 16:15:04 +00:00
|
|
|
std::random_device rng;
|
|
|
|
std::mt19937 urng(rng());
|
|
|
|
std::shuffle(data.begin(), data.end(), urng);
|
2015-08-26 16:30:15 +00:00
|
|
|
return vtkm::cont::make_ArrayHandle(data);
|
|
|
|
}
|
|
|
|
|
|
|
|
//Transfer the data in a vtkm ArrayHandle to open gl while making sure
|
|
|
|
//we don't throw any errors
|
2017-05-18 14:29:41 +00:00
|
|
|
template <typename ArrayHandleType>
|
|
|
|
static void SafelyTransferArray(ArrayHandleType array, GLuint& handle)
|
2015-08-26 16:30:15 +00:00
|
|
|
{
|
|
|
|
try
|
2017-05-18 14:29:41 +00:00
|
|
|
{
|
2016-04-13 19:52:15 +00:00
|
|
|
vtkm::interop::BufferState state(handle);
|
|
|
|
vtkm::interop::TransferToOpenGL(array, state, DeviceAdapterTag());
|
2017-05-18 14:29:41 +00:00
|
|
|
}
|
|
|
|
catch (vtkm::cont::ErrorBadAllocation& error)
|
|
|
|
{
|
2015-08-26 16:30:15 +00:00
|
|
|
std::cout << error.GetMessage() << std::endl;
|
2017-05-18 14:29:41 +00:00
|
|
|
VTKM_TEST_ASSERT(true == false,
|
|
|
|
"Got an unexpected Out Of Memory error transferring to openGL");
|
|
|
|
}
|
|
|
|
catch (vtkm::cont::ErrorBadValue& bvError)
|
|
|
|
{
|
2015-08-26 16:30:15 +00:00
|
|
|
std::cout << bvError.GetMessage() << std::endl;
|
2017-05-18 14:29:41 +00:00
|
|
|
VTKM_TEST_ASSERT(true == false, "Got an unexpected Bad Value error transferring to openGL");
|
|
|
|
}
|
2017-08-11 19:36:24 +00:00
|
|
|
|
|
|
|
// Test device adapter deduction:
|
|
|
|
try
|
|
|
|
{
|
|
|
|
vtkm::interop::BufferState state(handle);
|
|
|
|
vtkm::interop::TransferToOpenGL(array, state);
|
|
|
|
}
|
|
|
|
catch (vtkm::cont::ErrorBadAllocation& error)
|
|
|
|
{
|
|
|
|
std::cout << error.GetMessage() << std::endl;
|
|
|
|
VTKM_TEST_ASSERT(true == false,
|
|
|
|
"Got an unexpected Out Of Memory error transferring to openGL");
|
|
|
|
}
|
|
|
|
catch (vtkm::cont::ErrorBadValue& bvError)
|
|
|
|
{
|
|
|
|
std::cout << bvError.GetMessage() << std::endl;
|
|
|
|
VTKM_TEST_ASSERT(true == false, "Got an unexpected Bad Value error transferring to openGL");
|
|
|
|
}
|
2015-08-26 16:30:15 +00:00
|
|
|
}
|
|
|
|
|
2017-05-18 14:29:41 +00:00
|
|
|
template <typename ArrayHandleType>
|
|
|
|
static void SafelyTransferArray(ArrayHandleType array, GLuint& handle, GLenum type)
|
2015-08-26 16:30:15 +00:00
|
|
|
{
|
|
|
|
try
|
2017-05-18 14:29:41 +00:00
|
|
|
{
|
2016-04-13 19:52:15 +00:00
|
|
|
vtkm::interop::BufferState state(handle, type);
|
|
|
|
vtkm::interop::TransferToOpenGL(array, state, DeviceAdapterTag());
|
2017-05-18 14:29:41 +00:00
|
|
|
}
|
|
|
|
catch (vtkm::cont::ErrorBadAllocation& error)
|
|
|
|
{
|
2015-08-26 16:30:15 +00:00
|
|
|
std::cout << error.GetMessage() << std::endl;
|
2017-05-18 14:29:41 +00:00
|
|
|
VTKM_TEST_ASSERT(true == false,
|
|
|
|
"Got an unexpected Out Of Memory error transferring to openGL");
|
|
|
|
}
|
|
|
|
catch (vtkm::cont::ErrorBadValue& bvError)
|
|
|
|
{
|
2015-08-26 16:30:15 +00:00
|
|
|
std::cout << bvError.GetMessage() << std::endl;
|
2017-05-18 14:29:41 +00:00
|
|
|
VTKM_TEST_ASSERT(true == false, "Got an unexpected Bad Value error transferring to openGL");
|
|
|
|
}
|
2017-08-11 19:36:24 +00:00
|
|
|
|
|
|
|
// Test device adapter deduction
|
|
|
|
try
|
|
|
|
{
|
|
|
|
vtkm::interop::BufferState state(handle, type);
|
|
|
|
vtkm::interop::TransferToOpenGL(array, state);
|
|
|
|
}
|
|
|
|
catch (vtkm::cont::ErrorBadAllocation& error)
|
|
|
|
{
|
|
|
|
std::cout << error.GetMessage() << std::endl;
|
|
|
|
VTKM_TEST_ASSERT(true == false,
|
|
|
|
"Got an unexpected Out Of Memory error transferring to openGL");
|
|
|
|
}
|
|
|
|
catch (vtkm::cont::ErrorBadValue& bvError)
|
|
|
|
{
|
|
|
|
std::cout << bvError.GetMessage() << std::endl;
|
|
|
|
VTKM_TEST_ASSERT(true == false, "Got an unexpected Bad Value error transferring to openGL");
|
|
|
|
}
|
2015-08-26 16:30:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//bring the data back from openGL and into a std vector. Will bind the
|
|
|
|
//passed in handle to the default buffer type for the type T
|
2017-05-18 14:29:41 +00:00
|
|
|
template <typename T>
|
|
|
|
static std::vector<T> CopyGLBuffer(GLuint& handle, T t)
|
2015-08-26 16:30:15 +00:00
|
|
|
{
|
|
|
|
//get the type we used for this buffer.
|
2016-04-13 19:52:15 +00:00
|
|
|
GLenum type = vtkm::interop::internal::BufferTypePicker(t);
|
2015-08-26 16:30:15 +00:00
|
|
|
|
|
|
|
//bind the buffer to the guessed buffer type, this way
|
|
|
|
//we can call CopyGLBuffer no matter what it the active buffer
|
|
|
|
glBindBuffer(type, handle);
|
|
|
|
|
|
|
|
//get the size of the buffer
|
|
|
|
int bytesInBuffer = 0;
|
|
|
|
glGetBufferParameteriv(type, GL_BUFFER_SIZE, &bytesInBuffer);
|
2017-05-18 14:29:41 +00:00
|
|
|
const std::size_t size = (static_cast<std::size_t>(bytesInBuffer) / sizeof(T));
|
2015-08-26 16:30:15 +00:00
|
|
|
|
|
|
|
//get the buffer contents and place it into a vector
|
|
|
|
std::vector<T> data;
|
|
|
|
data.resize(size);
|
2017-05-18 14:29:41 +00:00
|
|
|
glGetBufferSubData(type, 0, bytesInBuffer, &data[0]);
|
2015-08-26 16:30:15 +00:00
|
|
|
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct TransferFunctor
|
|
|
|
{
|
|
|
|
template <typename T>
|
|
|
|
void operator()(const T t) const
|
|
|
|
{
|
|
|
|
const std::size_t Size = 10;
|
|
|
|
GLuint GLHandle;
|
|
|
|
//verify that T is able to be transfer to openGL.
|
|
|
|
//than pull down the results from the array buffer and verify
|
|
|
|
//that they match the handles contents
|
|
|
|
std::vector<T> tempData;
|
2017-05-18 14:29:41 +00:00
|
|
|
vtkm::cont::ArrayHandle<T, StorageTag> temp = FillArray(tempData, Size);
|
2015-08-26 16:30:15 +00:00
|
|
|
|
|
|
|
//verify that the signature that doesn't have type works
|
2017-05-18 14:29:41 +00:00
|
|
|
SafelyTransferArray(temp, GLHandle);
|
2015-08-26 16:30:15 +00:00
|
|
|
|
2017-05-18 14:29:41 +00:00
|
|
|
GLboolean is_buffer;
|
2015-08-26 16:30:15 +00:00
|
|
|
is_buffer = glIsBuffer(GLHandle);
|
2017-05-18 14:29:41 +00:00
|
|
|
VTKM_TEST_ASSERT(is_buffer == GL_TRUE, "OpenGL buffer not filled");
|
2015-08-26 16:30:15 +00:00
|
|
|
|
|
|
|
std::vector<T> returnedValues = CopyGLBuffer(GLHandle, t);
|
|
|
|
|
|
|
|
//verify the results match what is in the array handle
|
|
|
|
temp.SyncControlArray();
|
2018-02-12 18:09:43 +00:00
|
|
|
T* expectedValues = temp.GetStorage().GetArray();
|
2015-08-26 16:30:15 +00:00
|
|
|
|
2017-05-18 14:29:41 +00:00
|
|
|
for (std::size_t i = 0; i < Size; ++i)
|
|
|
|
{
|
|
|
|
VTKM_TEST_ASSERT(test_equal(*(expectedValues + i), returnedValues[i]),
|
|
|
|
"Array Handle failed to transfer properly");
|
|
|
|
}
|
2015-08-26 16:30:15 +00:00
|
|
|
|
|
|
|
temp.ReleaseResources();
|
2017-05-18 14:29:41 +00:00
|
|
|
temp = FillArray(tempData, Size * 2);
|
2016-04-13 19:52:15 +00:00
|
|
|
GLenum type = vtkm::interop::internal::BufferTypePicker(t);
|
2017-05-18 14:29:41 +00:00
|
|
|
SafelyTransferArray(temp, GLHandle, type);
|
2015-08-26 16:30:15 +00:00
|
|
|
is_buffer = glIsBuffer(GLHandle);
|
2017-05-18 14:29:41 +00:00
|
|
|
VTKM_TEST_ASSERT(is_buffer == GL_TRUE, "OpenGL buffer not filled");
|
2015-08-26 16:30:15 +00:00
|
|
|
returnedValues = CopyGLBuffer(GLHandle, t);
|
|
|
|
//verify the results match what is in the array handle
|
|
|
|
temp.SyncControlArray();
|
2018-02-12 18:09:43 +00:00
|
|
|
expectedValues = temp.GetStorage().GetArray();
|
2015-08-26 16:30:15 +00:00
|
|
|
|
2017-05-18 14:29:41 +00:00
|
|
|
for (std::size_t i = 0; i < Size * 2; ++i)
|
|
|
|
{
|
|
|
|
VTKM_TEST_ASSERT(test_equal(*(expectedValues + i), returnedValues[i]),
|
|
|
|
"Array Handle failed to transfer properly");
|
|
|
|
}
|
2015-08-26 16:30:15 +00:00
|
|
|
|
|
|
|
//verify this work for a constant value array handle
|
2017-05-18 14:29:41 +00:00
|
|
|
T constantValue = TestValue(2, T()); //verified by die roll
|
|
|
|
vtkm::cont::ArrayHandleConstant<T> constant(constantValue, static_cast<vtkm::Id>(Size));
|
|
|
|
SafelyTransferArray(constant, GLHandle);
|
2015-08-26 16:30:15 +00:00
|
|
|
is_buffer = glIsBuffer(GLHandle);
|
2017-05-18 14:29:41 +00:00
|
|
|
VTKM_TEST_ASSERT(is_buffer == GL_TRUE, "OpenGL buffer not filled");
|
2015-08-26 16:30:15 +00:00
|
|
|
returnedValues = CopyGLBuffer(GLHandle, constantValue);
|
2017-05-18 14:29:41 +00:00
|
|
|
for (std::size_t i = 0; i < Size; ++i)
|
|
|
|
{
|
|
|
|
VTKM_TEST_ASSERT(test_equal(returnedValues[i], constantValue),
|
|
|
|
"Constant value array failed to transfer properly");
|
|
|
|
}
|
2015-08-26 16:30:15 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// struct TransferGridFunctor
|
|
|
|
// {
|
|
|
|
// GLuint CoordGLHandle;
|
|
|
|
// GLuint MagnitudeGLHandle;
|
|
|
|
|
|
|
|
// template <typename GridType>
|
|
|
|
// void operator()(const GridType)
|
|
|
|
// {
|
|
|
|
// //verify we are able to be transfer both coordinates and indices to openGL.
|
|
|
|
// //than pull down the results from the array buffer and verify
|
|
|
|
// //that they match the handles contents
|
|
|
|
// vtkm::cont::testing::TestGrid<GridType,
|
|
|
|
// StorageTag,
|
|
|
|
// DeviceAdapterTag> grid(64);
|
|
|
|
|
|
|
|
// vtkm::cont::ArrayHandle<vtkm::FloatDefault,
|
|
|
|
// StorageTag,
|
|
|
|
// DeviceAdapterTag> magnitudeHandle;
|
|
|
|
|
|
|
|
// vtkm::cont::DispatcherMapField< vtkm::worklet::Magnitude,
|
|
|
|
// DeviceAdapterTag> dispatcher;
|
|
|
|
// dispatcher.Invoke(grid->GetPointCoordinates(), magnitudeHandle);
|
|
|
|
|
|
|
|
// //transfer to openGL 3 handles and catch any errors
|
|
|
|
// //
|
|
|
|
// SafelyTransferArray(grid->GetPointCoordinates(),this->CoordGLHandle);
|
|
|
|
// SafelyTransferArray(magnitudeHandle,this->MagnitudeGLHandle);
|
|
|
|
|
|
|
|
// //verify all 3 handles are actually handles
|
|
|
|
// bool is_buffer = glIsBuffer(this->CoordGLHandle);
|
2016-06-21 23:59:49 +00:00
|
|
|
// VTKM_TEST_ASSERT(is_buffer==GL_TRUE,
|
2015-08-26 16:30:15 +00:00
|
|
|
// "Coordinates OpenGL buffer not filled");
|
|
|
|
|
|
|
|
// is_buffer = glIsBuffer(this->MagnitudeGLHandle);
|
2016-06-21 23:59:49 +00:00
|
|
|
// VTKM_TEST_ASSERT(is_buffer==GL_TRUE,
|
2015-08-26 16:30:15 +00:00
|
|
|
// "Magnitude OpenGL buffer not filled");
|
|
|
|
|
|
|
|
// //now that everything is openGL we have one task left.
|
|
|
|
// //transfer everything back to the host and compare it to the
|
|
|
|
// //computed values.
|
|
|
|
// std::vector<vtkm::Vec<vtkm::FloatDefault,3>> GLReturnedCoords = CopyGLBuffer(
|
|
|
|
// this->CoordGLHandle, vtkm::Vec<vtkm::FloatDefault,3>());
|
|
|
|
// std::vector<vtkm::FloatDefault> GLReturneMags = CopyGLBuffer(
|
|
|
|
// this->MagnitudeGLHandle,vtkm::FloatDefault());
|
|
|
|
|
|
|
|
// for (vtkm::Id pointIndex = 0;
|
|
|
|
// pointIndex < grid->GetNumberOfPoints();
|
|
|
|
// pointIndex++)
|
|
|
|
// {
|
|
|
|
// vtkm::Vec<vtkm::FloatDefault,3> pointCoordinateExpected = grid.GetPointCoordinates(
|
|
|
|
// pointIndex);
|
|
|
|
// vtkm::Vec<vtkm::FloatDefault,3> pointCoordinatesReturned = GLReturnedCoords[pointIndex];
|
|
|
|
// VTKM_TEST_ASSERT(test_equal(pointCoordinateExpected,
|
|
|
|
// pointCoordinatesReturned),
|
|
|
|
// "Got bad coordinate from OpenGL buffer.");
|
|
|
|
|
|
|
|
// vtkm::FloatDefault magnitudeValue = GLReturneMags[pointIndex];
|
|
|
|
// vtkm::FloatDefault magnitudeExpected =
|
2018-05-14 18:25:46 +00:00
|
|
|
// sqrt(vtkm::Dot(pointCoordinateExpected, pointCoordinateExpected));
|
2015-08-26 16:30:15 +00:00
|
|
|
// VTKM_TEST_ASSERT(test_equal(magnitudeValue, magnitudeExpected),
|
|
|
|
// "Got bad magnitude from OpenGL buffer.");
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// };
|
|
|
|
|
|
|
|
public:
|
2019-01-01 22:19:02 +00:00
|
|
|
VTKM_CONT static int Run(int argc, char* argv[])
|
2017-05-18 14:29:41 +00:00
|
|
|
{
|
2016-10-06 15:24:08 +00:00
|
|
|
std::cout << "TestingOpenGLInterop Run() " << std::endl;
|
2017-05-18 14:29:41 +00:00
|
|
|
|
2015-08-26 16:30:15 +00:00
|
|
|
//verify that we can transfer basic arrays and constant value arrays to opengl
|
2019-01-01 22:19:02 +00:00
|
|
|
vtkm::testing::Testing::TryTypes(TransferFunctor(), argc, argv);
|
2015-08-26 16:30:15 +00:00
|
|
|
|
|
|
|
//verify that openGL interop works with all grid types in that we can
|
|
|
|
//transfer coordinates / verts and properties to openGL
|
|
|
|
// vtkm::cont::testing::GridTesting::TryAllGridTypes(
|
|
|
|
// TransferGridFunctor(),
|
|
|
|
// vtkm::testing::Testing::CellCheckAlwaysTrue(),
|
|
|
|
// StorageTag(),
|
|
|
|
// DeviceAdapterTag() );
|
|
|
|
|
|
|
|
return 0;
|
2017-05-18 14:29:41 +00:00
|
|
|
}
|
2015-08-26 16:30:15 +00:00
|
|
|
};
|
2017-05-18 14:29:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-08-26 16:30:15 +00:00
|
|
|
|
2016-04-13 19:52:15 +00:00
|
|
|
#endif //vtk_m_interop_testing_TestingOpenGLInterop_h
|