Viskores  1.0
internal/TransferToOpenGL.h
Go to the documentation of this file.
1 //============================================================================
2 // The contents of this file are covered by the Viskores license. See
3 // LICENSE.txt for details.
4 //
5 // By contributing to this file, all contributors agree to the Developer
6 // Certificate of Origin Version 1.1 (DCO 1.1) as stated in DCO.txt.
7 //============================================================================
8 
9 //============================================================================
10 // Copyright (c) Kitware, Inc.
11 // All rights reserved.
12 // See LICENSE.txt for details.
13 //
14 // This software is distributed WITHOUT ANY WARRANTY; without even
15 // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 // PURPOSE. See the above copyright notice for more information.
17 //============================================================================
18 #ifndef viskores_interop_internal_TransferToOpenGL_h
19 #define viskores_interop_internal_TransferToOpenGL_h
20 
22 #include <viskores/cont/Storage.h>
23 
27 
30 
31 namespace viskores
32 {
33 namespace interop
34 {
35 namespace internal
36 {
37 
44 class SMPTransferResource : public viskores::interop::internal::TransferResource
45 {
46 public:
47  template <typename T>
48  SMPTransferResource(T, viskores::Id numberOfValues)
49  : viskores::interop::internal::TransferResource()
50  , Size(0)
51  , TempStorage()
52  {
53  this->resize<T>(numberOfValues);
54  }
55 
56  ~SMPTransferResource() {}
57 
58  template <typename T>
59  void resize(viskores::Id numberOfValues)
60  {
61  if (this->Size != numberOfValues)
62  {
63  this->Size = numberOfValues;
64  T* storage = new T[static_cast<std::size_t>(this->Size)];
65  this->TempStorage.reset(reinterpret_cast<viskores::UInt8*>(storage));
66  }
67  }
68 
69  template <typename T>
71  {
72  VISKORES_ASSERT(this->Size > 0);
73  VISKORES_ASSERT(this->Size >= size);
74 
75  T* storage = reinterpret_cast<T*>(this->TempStorage.get());
76  //construct a handle that is a view onto the memory
78  }
79 
80  template <typename T>
81  T* as() const
82  {
83  VISKORES_ASSERT(this->Size > 0);
84  T* storage = reinterpret_cast<T*>(this->TempStorage.get());
85  return storage;
86  }
87 
88  viskores::Id Size;
89  std::unique_ptr<viskores::UInt8[]> TempStorage;
90 };
91 
92 namespace detail
93 {
94 
95 template <class ValueType, class StorageTag, class DeviceAdapterTag>
98  DeviceAdapterTag)
99 {
100  //Generic implementation that will work no matter what. We copy the data
101  //in the given handle to storage held by the buffer state.
102  const viskores::Id numberOfValues = handle.GetNumberOfValues();
103  const GLsizeiptr size =
104  static_cast<GLsizeiptr>(sizeof(ValueType)) * static_cast<GLsizeiptr>(numberOfValues);
105 
106  //grab the temporary storage from the buffer resource
107  viskores::interop::internal::SMPTransferResource* resource =
108  dynamic_cast<viskores::interop::internal::SMPTransferResource*>(state.GetResource());
109 
110  //Determine if we need to reallocate the buffer
111  state.SetSize(size);
112  const bool resize = state.ShouldRealloc(size);
113 
114  if (resize)
115  {
116  //Allocate the memory and set it as GL_DYNAMIC_DRAW draw
117  glBufferData(state.GetType(), size, 0, GL_DYNAMIC_DRAW);
118  state.SetCapacity(size);
119 
120  //If we have an existing resource reallocate it to fit our new size
121  if (resource)
122  {
123  resource->resize<ValueType>(numberOfValues);
124  }
125  }
126 
127  //if we don't have a valid resource make a new one. We do this after the
128  //resize check so we don't double allocate when resource == nullptr and
129  //resize == true
130  if (!resource)
131  {
132  resource = new viskores::interop::internal::SMPTransferResource(ValueType(), numberOfValues);
133  state.SetResource(resource);
134  }
135 
137  auto resourceHandle = resource->handle<ValueType>(numberOfValues);
138  Algorithm::Copy(handle, resourceHandle);
139 
140  //copy into opengl buffer
141  glBufferSubData(state.GetType(), 0, size, resource->as<ValueType>());
142 }
143 
144 template <class ValueType, class DeviceAdapterTag>
145 VISKORES_CONT void CopyFromHandle(
148  DeviceAdapterTag)
149 {
150  //Specialization given that we are use an C allocated array storage tag
151  //that allows us to directly hook into the data. We pull the data
152  //back to the control environment using PerpareForInput and give an iterator
153  //from the portal to OpenGL to upload to the rendering system
154  //This also works because we know that this class isn't used for cuda interop,
155  //instead we are specialized
156  const GLsizeiptr size = static_cast<GLsizeiptr>(sizeof(ValueType)) *
157  static_cast<GLsizeiptr>(handle.GetNumberOfValues());
158 
159  //Determine if we need to reallocate the buffer
160  state.SetSize(size);
161  const bool resize = state.ShouldRealloc(size);
162  if (resize)
163  {
164  //Allocate the memory and set it as GL_DYNAMIC_DRAW draw
165  glBufferData(state.GetType(), size, 0, GL_DYNAMIC_DRAW);
166 
167  state.SetCapacity(size);
168  }
169 
170  //Allocate the memory and set it as static draw and copy into opengl
171  viskores::cont::Token token;
172  auto portal = handle.PrepareForInput(DeviceAdapterTag{}, token);
173  const ValueType* memory = &(*viskores::cont::ArrayPortalToIteratorBegin(portal));
174  glBufferSubData(state.GetType(), 0, size, memory);
175 }
176 
177 } //namespace detail
178 
184 template <typename ValueType, class DeviceAdapterTag>
185 class TransferToOpenGL
186 {
187 public:
188  VISKORES_CONT explicit TransferToOpenGL(BufferState& state)
189  : State(state)
190  {
191  if (!this->State.HasType())
192  {
193  this->State.DeduceAndSetType(ValueType());
194  }
195  }
196 
197  template <typename StorageTag>
198  VISKORES_CONT void Transfer(
200  {
201  //make a buffer for the handle if the user has forgotten too
202  if (!glIsBuffer(*this->State.GetHandle()))
203  {
204  glGenBuffers(1, this->State.GetHandle());
205  }
206 
207  //bind the buffer to the given buffer type
208  glBindBuffer(this->State.GetType(), *this->State.GetHandle());
209 
210  //transfer the data.
211  //the primary concern that we have at this point is data locality and
212  //the type of storage. Our options include using DeviceAdapterAlgorithm::Copy
213  //and provide a temporary location for the values to reside before we give it
214  //to openGL this works for all storage types.
215  //
216  //Second option is to call PrepareForInput and get a PortalConst in the
217  //execution environment.
218  //if we are StorageTagBasic this would allow us the ability to grab
219  //the raw memory value and copy those, which we know are valid and remove
220  //a unneeded copy.
221  //
222  //The end result is that we have CopyFromHandle which does number two
223  //from StorageTagBasic, and does the DeviceAdapterAlgorithm::Copy for everything
224  //else
225  detail::CopyFromHandle(handle, this->State, DeviceAdapterTag());
226  }
227 
228 private:
230 };
231 }
232 }
233 } //namespace viskores::interop::internal
234 
235 //-----------------------------------------------------------------------------
236 // These includes are intentionally placed here after the declaration of the
237 // TransferToOpenGL class, so that people get the correct device adapter
239 #if VISKORES_DEVICE_ADAPTER == VISKORES_DEVICE_ADAPTER_CUDA
241 #endif
242 
243 #endif //viskores_interop_internal_TransferToOpenGL_h
viskores::interop::BufferState::SetSize
void SetSize(viskores::Int64 size)
Definition: BufferState.h:145
viskores::cont::DeviceAdapterAlgorithm
Struct containing device adapter algorithms.
Definition: DeviceAdapterAlgorithm.h:49
ArrayHandle.h
viskores::interop::BufferState::GetResource
viskores::interop::internal::TransferResource * GetResource()
Definition: BufferState.h:171
viskores::CopyFlag::Off
@ Off
viskores::interop::BufferState::GetType
GLenum GetType() const
return what OpenGL buffer type we are bound to
Definition: BufferState.h:118
viskores::cont::ArrayHandle::PrepareForInput
ReadPortalType PrepareForInput(viskores::cont::DeviceAdapterId device, viskores::cont::Token &token) const
Prepares this array to be used as an input to an operation in the execution environment.
Definition: ArrayHandle.h:615
DeviceAdapterTBB.h
OpenGLHeaders.h
Storage.h
viskores::cont::ArrayHandle< T, viskores::cont::StorageTagBasic >
DeviceAdapterAlgorithm.h
viskores::Id
viskores::Int64 Id
Base type to use to index arrays.
Definition: Types.h:235
VISKORES_CONT
#define VISKORES_CONT
Definition: ExportMacros.h:65
viskores
Groups connected points that have the same field value.
Definition: Atomic.h:27
viskores::cont::ArrayPortalToIteratorBegin
viskores::cont::ArrayPortalToIterators< PortalType >::IteratorType ArrayPortalToIteratorBegin(const PortalType &portal)
Convenience function for converting an ArrayPortal to a begin iterator.
Definition: ArrayPortalToIterators.h:189
viskores::interop::BufferState
Manages the state for transferring an ArrayHandle to opengl.
Definition: BufferState.h:64
DeviceAdapterSerial.h
viskores::cont::ArrayHandle::GetNumberOfValues
viskores::Id GetNumberOfValues() const
Returns the number of entries in the array.
Definition: ArrayHandle.h:482
viskores::interop::TransferToOpenGL
void TransferToOpenGL(const viskores::cont::ArrayHandle< ValueType, StorageTag > &handle, BufferState &state, DeviceAdapterTag)
Manages transferring an ArrayHandle to opengl .
Definition: TransferToOpenGL.h:49
VISKORES_ASSERT
#define VISKORES_ASSERT(condition)
Definition: Assert.h:51
viskores::interop::BufferState::SetCapacity
void SetCapacity(viskores::Int64 capacity)
Definition: BufferState.h:168
TransferToOpenGL.h
viskores::UInt8
uint8_t UInt8
Base type to use for 8-bit unsigned integer numbers.
Definition: Types.h:177
viskores::interop::BufferState::SetResource
void SetResource(viskores::interop::internal::TransferResource *resource)
Definition: BufferState.h:174
BufferState.h
viskores::interop::BufferState::ShouldRealloc
bool ShouldRealloc(viskores::Int64 desiredSize) const
Definition: BufferState.h:158
viskores::cont::make_ArrayHandle
viskores::cont::ArrayHandleBasic< T > make_ArrayHandle(const T *array, viskores::Id numberOfValues, viskores::CopyFlag copy)
A convenience function for creating an ArrayHandle from a standard C array.
Definition: ArrayHandleBasic.h:285
viskores::cont::Token
A token to hold the scope of an ArrayHandle or other object.
Definition: Token.h:43