diff --git a/vtkm/cont/ArrayHandle.h b/vtkm/cont/ArrayHandle.h index 6b978dbca..eaf0c18c6 100644 --- a/vtkm/cont/ArrayHandle.h +++ b/vtkm/cont/ArrayHandle.h @@ -463,6 +463,17 @@ public: } } + /// 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() + : VTKM_DEVICE_ADAPTER_UNDEFINED; + } + struct VTKM_ALWAYS_EXPORT InternalStruct { StorageType ControlArray; diff --git a/vtkm/cont/internal/ArrayHandleBasicImpl.h b/vtkm/cont/internal/ArrayHandleBasicImpl.h index 054fc9527..1dbaeb385 100644 --- a/vtkm/cont/internal/ArrayHandleBasicImpl.h +++ b/vtkm/cont/internal/ArrayHandleBasicImpl.h @@ -194,6 +194,8 @@ public: template VTKM_CONT void PrepareForDevice(DeviceAdapterTag) const; + VTKM_CONT DeviceAdapterId GetDeviceAdapterId() const; + VTKM_CONT void SyncControlArray() const; VTKM_CONT void ReleaseResourcesExecutionInternal(); diff --git a/vtkm/cont/internal/ArrayHandleBasicImpl.hxx b/vtkm/cont/internal/ArrayHandleBasicImpl.hxx index 5008d5ab5..3c8acdb7e 100644 --- a/vtkm/cont/internal/ArrayHandleBasicImpl.hxx +++ b/vtkm/cont/internal/ArrayHandleBasicImpl.hxx @@ -435,6 +435,13 @@ void ArrayHandle::PrepareForDevice(DeviceAdapterTag) const new internal::ExecutionArrayInterfaceBasic(this->Internals->ControlArray); } +template +DeviceAdapterId ArrayHandle::GetDeviceAdapterId() const +{ + return this->Internals->ExecutionArrayValid ? this->Internals->ExecutionInterface->GetDeviceId() + : VTKM_DEVICE_ADAPTER_UNDEFINED; +} + template void ArrayHandle::SyncControlArray() const { diff --git a/vtkm/cont/internal/ArrayHandleExecutionManager.h b/vtkm/cont/internal/ArrayHandleExecutionManager.h index ff2af02c8..c4038fcb2 100644 --- a/vtkm/cont/internal/ArrayHandleExecutionManager.h +++ b/vtkm/cont/internal/ArrayHandleExecutionManager.h @@ -157,6 +157,9 @@ public: return this->IsDeviceAdapterImpl(vtkm::cont::DeviceAdapterTraits::GetId()); } + VTKM_CONT + DeviceAdapterId GetDeviceAdapterId() const { return this->GetDeviceAdapterIdImpl(); } + protected: virtual vtkm::Id GetNumberOfValuesImpl() const = 0; @@ -174,6 +177,8 @@ protected: virtual bool IsDeviceAdapterImpl(const vtkm::cont::DeviceAdapterId& id) const = 0; + virtual DeviceAdapterId GetDeviceAdapterIdImpl() const = 0; + private: template VTKM_CONT void VerifyDeviceAdapter(DeviceAdapter device) const @@ -261,6 +266,12 @@ protected: return id == vtkm::cont::DeviceAdapterTraits::GetId(); } + VTKM_CONT + DeviceAdapterId GetDeviceAdapterIdImpl() const + { + return vtkm::cont::DeviceAdapterTraits::GetId(); + } + private: ArrayTransferType Transfer; }; diff --git a/vtkm/interop/TransferToOpenGL.h b/vtkm/interop/TransferToOpenGL.h index 1dfb0d1cc..e0cd856ef 100644 --- a/vtkm/interop/TransferToOpenGL.h +++ b/vtkm/interop/TransferToOpenGL.h @@ -21,9 +21,15 @@ #define vtk_m_interop_TransferToOpenGL_h #include +#include +#include #include #include +#include +#include +#include + namespace vtkm { namespace interop @@ -50,6 +56,54 @@ VTKM_CONT void TransferToOpenGL(vtkm::cont::ArrayHandle h vtkm::interop::internal::TransferToOpenGL toGL(state); return toGL.Transfer(handle); } + +/// Dispatch overload for TransferToOpenGL that deduces the DeviceAdapter for +/// the given ArrayHandle. +/// +/// \overload +/// +template +VTKM_CONT void TransferToOpenGL(vtkm::cont::ArrayHandle handle, + BufferState& state) +{ + vtkm::cont::DeviceAdapterId devId = handle.GetDeviceAdapterId(); + switch (devId) + { + case VTKM_DEVICE_ADAPTER_SERIAL: + TransferToOpenGL(handle, state, vtkm::cont::DeviceAdapterTagSerial()); + break; + +#ifdef VTKM_ENABLE_TBB + case VTKM_DEVICE_ADAPTER_TBB: + TransferToOpenGL(handle, state, vtkm::cont::DeviceAdapterTagTBB()); + break; +#endif + +#ifdef VTKM_CUDA + case VTKM_DEVICE_ADAPTER_CUDA: + TransferToOpenGL(handle, state, vtkm::cont::DeviceAdapterTagCuda()); + break; +#endif + + default: +// Print warning on debug builds, then fallthrough to host case. +#ifndef NDEBUG + std::cerr << __FILE__ << ":" << __LINE__ << ": " + << "Unrecognized DeviceAdapterId encountered: " << devId << "\n"; +#endif // NDEBUG + + /* Fallthrough */ + case VTKM_DEVICE_ADAPTER_UNDEFINED: +// GetDeviceAdapterId returns UNDEFINED when memory is on the host. +// Try TBB if enabled and serial otherwise. +#ifdef VTKM_ENABLE_TBB + TransferToOpenGL(handle, state, vtkm::cont::DeviceAdapterTagTBB()); +#else + TransferToOpenGL(handle, state, vtkm::cont::DeviceAdapterTagSerial()); +#endif + break; + } +} } } diff --git a/vtkm/interop/testing/TestingOpenGLInterop.h b/vtkm/interop/testing/TestingOpenGLInterop.h index b79b29680..620ec6e48 100644 --- a/vtkm/interop/testing/TestingOpenGLInterop.h +++ b/vtkm/interop/testing/TestingOpenGLInterop.h @@ -88,6 +88,24 @@ private: std::cout << bvError.GetMessage() << std::endl; VTKM_TEST_ASSERT(true == false, "Got an unexpected Bad Value error transferring to openGL"); } + + // 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"); + } } template @@ -109,6 +127,24 @@ private: std::cout << bvError.GetMessage() << std::endl; VTKM_TEST_ASSERT(true == false, "Got an unexpected Bad Value error transferring to openGL"); } + + // 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"); + } } //bring the data back from openGL and into a std vector. Will bind the