Voxel
 All Classes Namespaces Files Functions Typedefs Enumerations Enumerator Macros Pages
synchronized_texture_heap_opencl.h
1 #pragma once
2 
3 #ifndef SYNCHRONIZED_TEXTURE_HEAP_OPENCL_H
4 #define SYNCHRONIZED_TEXTURE_HEAP_OPENCL_H
5 
6 
7 
8 
9 #include "settings.h"
10 
11 
12 
13 
14 #if ( SETTING_OPENCL != 0 )
15 
16 
17 
18 
19 #include "synchronized_texture_heap_base.h"
20 #include "synchronized_detail_octree.h"
21 #include "platform.h"
22 #include "color.h"
23 #include "vector.h"
24 #include "opencl.h"
25 
26 #include <unordered_set>
27 #include <memory>
28 #include <array>
29 
30 #include <CL/cl.h>
31 
32 
33 
34 
35 namespace Synchronized {
36 
37 
38 
39 
40 /*==============================================================================
41  TextureHeap< PLATFORM_OPENCL > specialization
42 ==============================================================================*/
43 
44 
45 template< int t_ColorFormat >
46 struct TextureHeap< t_ColorFormat, PLATFORM_OPENCL > {
47 
48  struct Pointer;
49 
50  typedef cl_mem OpenCLType;
51 
52 
53  inline TextureHeap( std::shared_ptr< OpenCL::State > const& pState, unsigned int const logSize );
54 
55 
56  inline Pointer Allocate( unsigned int const logSize );
57 
58 
59  inline void Synchronize();
60 
61 
62  inline OpenCLType OpenCLConvert() const;
63 
64 
65 private:
66 
67  struct Object {
68 
69  inline Object( TextureHeap* const pParent, Vector< unsigned int, 3 > const& coordinates, unsigned int const logSize );
70 
71  inline ~Object();
72 
73 
74  inline void OpenCLWrite( void* const destination, size_t const rowPitch, size_t const slicePitch ) const;
75 
76 
77  inline unsigned int References() const;
78 
79  inline void AddReference();
80  inline void ReleaseReference();
81 
82 
83  inline Vector< unsigned int, 3 > const& Coordinates() const;
84  inline unsigned int const LogSize() const;
85 
86  inline void Mark() const;
87 
88 
89  inline Color< t_ColorFormat > const* Get( size_t const index = 0 ) const;
90  inline void Set( size_t const index, Color< t_ColorFormat > const& value );
91 
92 
93  private:
94 
95  unsigned int m_refcount;
96 
97  TextureHeap* m_pParent;
98  Vector< unsigned int, 3 > m_coordinates;
99  unsigned int m_logSize;
100 
101  Color< t_ColorFormat >* m_array;
102  };
103 
104 
105 public:
106 
107  struct Pointer {
108 
109  typedef Color< t_ColorFormat > const element_type;
110  typedef cl_uint OpenCLType; // **NOTE: (x,y,z) coordinates are packed into (11,11,10)-bit segments
111 
112 
113  inline Pointer();
114  inline Pointer( Pointer const& other );
115 
116  inline ~Pointer();
117 
118 
119  inline void reset();
120  inline void swap( Pointer& other );
121 
122  inline unsigned int use_count() const;
123  inline bool unique() const;
124 
125 
126  inline Color< t_ColorFormat > const* get() const;
127 
128  inline void Assign( size_t const index, Color< t_ColorFormat > const& data ) const;
129 
130 
131  inline Pointer const& operator=( Pointer const& other );
132 
133 
134  inline operator bool() const;
135 
136  inline Color< t_ColorFormat > const* operator->() const;
137  inline Color< t_ColorFormat > const& operator*() const;
138 
139  inline Color< t_ColorFormat > const& operator[]( size_t const index ) const;
140 
141  inline bool operator==( Pointer const& other ) const;
142  inline bool operator!=( Pointer const& other ) const;
143 
144 
145  inline OpenCLType OpenCLConvert() const;
146 
147 
148  private:
149 
150  inline Pointer( Object* pointer );
151 
152 
153  Object* m_pointer;
154 
155 
156  friend struct TextureHeap< t_ColorFormat, PLATFORM_OPENCL >;
157  };
158 
159 
160 private:
161 
162  // sorts in Morton Z-order so that marked objects are listed in the same order as detail::Octree leaves
163  struct ObjectComparison {
164 
165  inline bool operator()( Object const* const pLeft, Object const* const pRight ) const;
166  };
167 
168 
169  inline void FreeObject( Object const* pObject );
170 
171  inline void MarkObject( Object const* pObject );
172 
173 
174  typedef std::unordered_set< Object const* > MarkedObjects;
175 
176 
177  std::shared_ptr< OpenCL::State > m_pState;
178  std::unique_ptr< _cl_mem, OpenCL::Deleter< _cl_mem > > m_image;
179 
180  detail::Octree m_freeTree;
181  MarkedObjects m_markedObjects;
182 };
183 
184 
185 
186 
187 /*==============================================================================
188  TextureHeap< PLATFORM_OPENCL >::Object methods
189 ==============================================================================*/
190 
191 
192 template< int t_ColorFormat >
193 TextureHeap< t_ColorFormat, PLATFORM_OPENCL >::Object::Object( TextureHeap* const pParent, Vector< unsigned int, 3 > const& coordinates, unsigned int const logSize ) :
194  m_refcount( 0 ),
195  m_pParent( pParent ),
196  m_coordinates( coordinates ),
197  m_logSize( logSize ),
198  m_array( new Color< t_ColorFormat >[ 1u << ( 3 * m_logSize ) ] )
199 {
200 }
201 
202 
203 template< int t_ColorFormat >
204 TextureHeap< t_ColorFormat, PLATFORM_OPENCL >::Object::~Object() {
205 
206  assert( m_refcount == 0 );
207  assert( m_pParent != NULL );
208  m_pParent->FreeObject( this );
209  delete[] m_array;
210 }
211 
212 
213 template< int t_ColorFormat >
214 void TextureHeap< t_ColorFormat, PLATFORM_OPENCL >::Object::OpenCLWrite( void* const destination, size_t const rowPitch, size_t const slicePitch ) const {
215 
216  typedef typename OpenCL::Converter< Color< t_ColorFormat > >::Type OpenCLType;
217 
218  Color< t_ColorFormat > const* kk = m_array;
219  uint8_t* iiDestination = reinterpret_cast< uint8_t* >( destination );
220  for ( unsigned int ii = 0; ii < ( 1u << m_logSize ); ++ii ) {
221 
222  uint8_t* jjDestination = iiDestination;
223  for ( unsigned int jj = 0; jj < ( 1u << m_logSize ); ++jj ) {
224 
225  OpenCLType* kkDestination = reinterpret_cast< OpenCLType* >( jjDestination );
226  OpenCLType* kkDestinationEnd = kkDestination + ( 1u << m_logSize );
227  for ( ; kkDestination != kkDestinationEnd; ++kkDestination, ++kk )
228  *kkDestination = OpenCL::Converter< Color< t_ColorFormat > >::Convert( *kk );
229  jjDestination += rowPitch;
230  }
231 
232  iiDestination += slicePitch;
233  }
234 }
235 
236 
237 template< int t_ColorFormat >
238 unsigned int TextureHeap< t_ColorFormat, PLATFORM_OPENCL >::Object::References() const {
239 
240  return m_refcount;
241 }
242 
243 
244 template< int t_ColorFormat >
245 void TextureHeap< t_ColorFormat, PLATFORM_OPENCL >::Object::AddReference() {
246 
247  ++m_refcount;
248 }
249 
250 
251 template< int t_ColorFormat >
252 void TextureHeap< t_ColorFormat, PLATFORM_OPENCL >::Object::ReleaseReference() {
253 
254  assert( m_refcount > 0 );
255  if ( --m_refcount == 0 )
256  delete this;
257 }
258 
259 
260 template< int t_ColorFormat >
261 Vector< unsigned int, 3 > const& TextureHeap< t_ColorFormat, PLATFORM_OPENCL >::Object::Coordinates() const {
262 
263  return m_coordinates;
264 }
265 
266 
267 template< int t_ColorFormat >
268 unsigned int const TextureHeap< t_ColorFormat, PLATFORM_OPENCL >::Object::LogSize() const {
269 
270  return m_logSize;
271 }
272 
273 
274 template< int t_ColorFormat >
275 void TextureHeap< t_ColorFormat, PLATFORM_OPENCL >::Object::Mark() const {
276 
277  assert( m_pParent != NULL );
278  m_pParent->MarkObject( this );
279 }
280 
281 
282 template< int t_ColorFormat >
283 Color< t_ColorFormat > const* TextureHeap< t_ColorFormat, PLATFORM_OPENCL >::Object::Get( size_t const index ) const {
284 
285  assert( index < ( 1u << ( 3 * m_logSize ) ) );
286  return( m_array + index );
287 }
288 
289 
290 template< int t_ColorFormat >
291 void TextureHeap< t_ColorFormat, PLATFORM_OPENCL >::Object::Set( size_t const index, Color< t_ColorFormat > const& data ) {
292 
293  assert( index < ( 1u << ( 3 * m_logSize ) ) );
294  m_array[ index ] = data;
295  Mark();
296 }
297 
298 
299 
300 
301 /*==============================================================================
302  TextureHeap< PLATFORM_OPENCL >::Pointer methods
303 ==============================================================================*/
304 
305 
306 template< int t_ColorFormat >
307 TextureHeap< t_ColorFormat, PLATFORM_OPENCL >::Pointer::Pointer() : m_pointer( NULL ) {
308 }
309 
310 
311 template< int t_ColorFormat >
312 TextureHeap< t_ColorFormat, PLATFORM_OPENCL >::Pointer::Pointer( Pointer const& other ) : m_pointer( other.m_pointer ) {
313 
314  if ( m_pointer != NULL )
315  m_pointer->AddReference();
316 }
317 
318 
319 template< int t_ColorFormat >
320 TextureHeap< t_ColorFormat, PLATFORM_OPENCL >::Pointer::~Pointer() {
321 
322  reset();
323 }
324 
325 
326 template< int t_ColorFormat >
327 void TextureHeap< t_ColorFormat, PLATFORM_OPENCL >::Pointer::reset() {
328 
329  if ( m_pointer != NULL ) {
330 
331  m_pointer->ReleaseReference();
332  m_pointer = NULL;
333  }
334 }
335 
336 
337 template< int t_ColorFormat >
338 void TextureHeap< t_ColorFormat, PLATFORM_OPENCL >::Pointer::swap( Pointer& other ) {
339 
340  std::swap( m_pointer, other.m_pointer );
341 }
342 
343 
344 template< int t_ColorFormat >
345 unsigned int TextureHeap< t_ColorFormat, PLATFORM_OPENCL >::Pointer::use_count() const {
346 
347  unsigned int result = 0;
348  if ( m_pointer != NULL )
349  result = m_pointer->References();
350  return result;
351 }
352 
353 
354 template< int t_ColorFormat >
355 bool TextureHeap< t_ColorFormat, PLATFORM_OPENCL >::Pointer::unique() const {
356 
357  return( use_count() == 1 );
358 }
359 
360 
361 template< int t_ColorFormat >
362 Color< t_ColorFormat > const* TextureHeap< t_ColorFormat, PLATFORM_OPENCL >::Pointer::get() const {
363 
364  return m_pointer->Get();
365 }
366 
367 
368 template< int t_ColorFormat >
369 void TextureHeap< t_ColorFormat, PLATFORM_OPENCL >::Pointer::Assign( size_t const index, Color< t_ColorFormat > const& data ) const {
370 
371  m_pointer->Set( index, data );
372 }
373 
374 
375 template< int t_ColorFormat >
376 typename TextureHeap< t_ColorFormat, PLATFORM_OPENCL >::Pointer const& TextureHeap< t_ColorFormat, PLATFORM_OPENCL >::Pointer::operator=( Pointer const& other ) {
377 
378  if ( m_pointer != other.m_pointer ) {
379 
380  reset();
381  m_pointer = other.m_pointer;
382  if ( m_pointer != NULL )
383  m_pointer->AddReference();
384  }
385 
386  return *this;
387 }
388 
389 
390 template< int t_ColorFormat >
391 TextureHeap< t_ColorFormat, PLATFORM_OPENCL >::Pointer::operator bool() const {
392 
393  return( m_pointer != NULL );
394 }
395 
396 
397 template< int t_ColorFormat >
398 Color< t_ColorFormat > const* TextureHeap< t_ColorFormat, PLATFORM_OPENCL >::Pointer::operator->() const {
399 
400  return m_pointer->Get();
401 }
402 
403 
404 template< int t_ColorFormat >
405 Color< t_ColorFormat > const& TextureHeap< t_ColorFormat, PLATFORM_OPENCL >::Pointer::operator*() const {
406 
407  return *m_pointer->Get();
408 }
409 
410 
411 template< int t_ColorFormat >
412 Color< t_ColorFormat > const& TextureHeap< t_ColorFormat, PLATFORM_OPENCL >::Pointer::operator[]( size_t const index ) const {
413 
414  return *m_pointer->Get( index );
415 }
416 
417 
418 template< int t_ColorFormat >
419 bool TextureHeap< t_ColorFormat, PLATFORM_OPENCL >::Pointer::operator==( Pointer const& other ) const {
420 
421  return( m_pointer == other.m_pointer );
422 }
423 
424 
425 template< int t_ColorFormat >
426 bool TextureHeap< t_ColorFormat, PLATFORM_OPENCL >::Pointer::operator!=( Pointer const& other ) const {
427 
428  return( m_pointer != other.m_pointer );
429 }
430 
431 
432 template< int t_ColorFormat >
433 TextureHeap< t_ColorFormat, PLATFORM_OPENCL >::Pointer::Pointer( Object* pointer ) : m_pointer( pointer ) {
434 
435  if ( m_pointer != NULL )
436  m_pointer->AddReference();
437 }
438 
439 
440 template< int t_ColorFormat >
441 typename TextureHeap< t_ColorFormat, PLATFORM_OPENCL >::Pointer::OpenCLType TextureHeap< t_ColorFormat, PLATFORM_OPENCL >::Pointer::OpenCLConvert() const {
442 
443  TextureHeap< t_ColorFormat, PLATFORM_OPENCL >::Pointer::OpenCLType result = OPENCL_NULL;
444  if ( m_pointer != NULL ) {
445 
446  Vector< unsigned int, 3 > coordinates = m_pointer->Coordinates();
447  assert( coordinates[ 0 ] < ( 1u << 11 ) ); // **NOTE: x-coordinate = 11 bits
448  assert( coordinates[ 1 ] < ( 1u << 11 ) ); // **NOTE: y-coordinate = 11 bits
449  assert( coordinates[ 2 ] < ( 1u << 10 ) ); // **NOTE: z-coordinate = 10 bits
450  result = ( ( ( coordinates[ 2 ] << 11 ) + coordinates[ 1 ] ) << 11 ) + coordinates[ 0 ];
451  }
452  return result;
453 }
454 
455 
456 
457 
458 /*==============================================================================
459  TextureHeap< PLATFORM_OPENCL >::ObjectComparison methods
460 ==============================================================================*/
461 
462 
463 template< int t_ColorFormat >
464 bool TextureHeap< t_ColorFormat, PLATFORM_OPENCL >::ObjectComparison::operator()( Object const* const pLeft, Object const* const pRight ) const {
465 
466  int comparison = 0;
467 
468  Vector< unsigned int, 3 > const& leftCoordinates = pLeft->Coordinates();
469  assert( leftCoordinates[ 0 ] < ( 1u << 11 ) ); // **NOTE: x-coordinate = 11 bits
470  assert( leftCoordinates[ 1 ] < ( 1u << 11 ) ); // **NOTE: y-coordinate = 11 bits
471  assert( leftCoordinates[ 2 ] < ( 1u << 10 ) ); // **NOTE: z-coordinate = 10 bits
472 
473  Vector< unsigned int, 3 > const& rightCoordinates = pRight->Coordinates();
474  assert( rightCoordinates[ 0 ] < ( 1u << 11 ) ); // **NOTE: x-coordinate = 11 bits
475  assert( rightCoordinates[ 1 ] < ( 1u << 11 ) ); // **NOTE: y-coordinate = 11 bits
476  assert( rightCoordinates[ 2 ] < ( 1u << 10 ) ); // **NOTE: z-coordinate = 10 bits
477 
478  for ( int ii = 10; ( comparison == 0 ) && ( ii >= 0 ); --ii ) { // **NOTE: all coordinates must be in the range [0,2^11)
479 
480  unsigned int const mask = ( 1u << ii );
481 
482  for ( int jj = 2; jj >= 0; --jj ) {
483 
484  unsigned int const left = ( leftCoordinates[ jj ] & mask );
485  unsigned int const right = ( rightCoordinates[ jj ] & mask );
486  if ( left < right ) {
487 
488  comparison = -1;
489  break; // **NOTE: break
490  }
491  else if ( left > right ) {
492 
493  comparison = 1;
494  break; // **NOTE: break
495  }
496  }
497  }
498 
499  return( comparison < 0 );
500 }
501 
502 
503 
504 
505 /*==============================================================================
506  TextureHeap< PLATFORM_OPENCL > methods
507 ==============================================================================*/
508 
509 
510 template< int t_ColorFormat >
511 TextureHeap< t_ColorFormat, PLATFORM_OPENCL >::TextureHeap( std::shared_ptr< OpenCL::State > const& pState, unsigned int const logSize ) : m_pState( pState ) {
512 
513  assert( logSize <= 10 ); // **NOTE: (x,y,z) coordinates are packed into (11,11,10)-bit segments
514 
515  Vector< size_t, 3 > const size = m_freeTree.Fill( logSize );
516 
517  cl_int result = CL_SUCCESS;
518  m_image.reset( clCreateImage3D( m_pState->Context(), CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR, &OpenCL::ImageFormat< t_ColorFormat >::format, size[ 0 ], size[ 1 ], size[ 2 ], 0, 0, NULL, &result ) );
519  if ( result != CL_SUCCESS )
520  THROW_OPENCL_EXCEPTION( "clCreateImage3D failed!", result );
521 }
522 
523 
524 template< int t_ColorFormat >
525 typename TextureHeap< t_ColorFormat, PLATFORM_OPENCL >::Pointer TextureHeap< t_ColorFormat, PLATFORM_OPENCL >::Allocate( unsigned int const logSize ) {
526 
527  Vector< unsigned int, 3 > coordinates = m_freeTree.Erase( logSize );
528  Object* pObject = new Object( this, coordinates, logSize );
529  MarkObject( pObject );
530  return Pointer( pObject );
531 }
532 
533 
534 template< int t_ColorFormat >
535 void TextureHeap< t_ColorFormat, PLATFORM_OPENCL >::Synchronize() {
536 
537  if ( ! m_markedObjects.empty() ) {
538 
539  typename MarkedObjects::size_type const size = m_markedObjects.size();
540  std::unique_ptr< Object const* > markedObjects( new Object const*[ size ] );
541  std::copy( m_markedObjects.begin(), m_markedObjects.end(), markedObjects.get() );
542  std::sort( markedObjects.get(), markedObjects.get() + size, ObjectComparison() );
543  Object const* const* const iiBegin = markedObjects.get();
544  Object const* const* const iiEnd = markedObjects.get() + size;
545 
546  detail::Octree markedTree( m_freeTree.Height() );
547  for ( Object const* const* ii = iiBegin; ii != iiEnd; ++ii )
548  markedTree.Insert( ( *ii )->Coordinates(), ( *ii )->LogSize() );
549 
550  typedef std::pair< Vector< unsigned int, 3 >, unsigned int > Leaf;
551  unsigned int const leaves = markedTree.CountLeaves();
552  std::unique_ptr< Leaf > markedLeaves( new Leaf[ leaves ] );
553  markedTree.Leaves( markedLeaves.get() );
554  Leaf const* const jjBegin = markedLeaves.get();
555  Leaf const* const jjEnd = markedLeaves.get() + leaves;
556 
557  Object const* const* ii = iiBegin;
558  Leaf const* jj = jjBegin;
559  for ( ; jj != jjEnd; ++jj ) {
560 
561  assert( ii != iiEnd );
562 
563  unsigned int const mask = ( 1u << jj->second ) - 1;
564 
565  size_t origin[ 3 ] = { jj->first[ 0 ], jj->first[ 1 ], jj->first[ 2 ] };
566  size_t region[ 3 ] = { ( 1u << jj->second ), ( 1u << jj->second ), ( 1u << jj->second ) };
567  size_t rowPitch = 0;
568  size_t slicePitch = 0;
569 
570  cl_int result = CL_SUCCESS;
571  void* const buffer = clEnqueueMapImage(
572  m_pState->Queue(),
573  m_image.get(),
574  CL_TRUE, // blocking
575  CL_MAP_WRITE,
576  origin,
577  region,
578  &rowPitch,
579  &slicePitch,
580  0,
581  NULL,
582  NULL,
583  &result
584  );
585  if ( result != CL_SUCCESS )
586  THROW_OPENCL_EXCEPTION( "clEnqueueMapImage failed!", result );
587 
588  Object const* const* iiNext = ii;
589  for ( ; iiNext != iiEnd; ++iiNext ) {
590 
591  Vector< unsigned int, 3 > const& coordinates = ( *iiNext )->Coordinates();
592  if (
593  ( ( coordinates[ 0 ] & ~mask ) != jj->first[ 0 ] ) ||
594  ( ( coordinates[ 1 ] & ~mask ) != jj->first[ 1 ] ) ||
595  ( ( coordinates[ 2 ] & ~mask ) != jj->first[ 2 ] )
596  )
597  {
598  break;
599  }
600  }
601  assert( ii != iiNext );
602 
603  for ( ; ii != iiNext; ++ii ) {
604 
605  Vector< unsigned int, 3 > const& coordinates = ( *ii )->Coordinates();
606  uint8_t* const destination = (
607  reinterpret_cast< uint8_t* >( buffer ) +
608  ( coordinates[ 2 ] & mask ) * slicePitch +
609  ( coordinates[ 1 ] & mask ) * rowPitch +
610  ( coordinates[ 0 ] & mask ) * sizeof( typename OpenCL::Converter< Color< t_ColorFormat > >::Type )
611  );
612  ( *ii )->OpenCLWrite( destination, rowPitch, slicePitch );
613  }
614 
615  clEnqueueUnmapMemObject(
616  m_pState->Queue(),
617  m_image.get(),
618  buffer,
619  0,
620  NULL,
621  NULL
622  );
623  }
624  assert( ii == iiEnd );
625 
626  m_markedObjects.clear();
627  }
628 }
629 
630 
631 template< int t_ColorFormat >
632 typename TextureHeap< t_ColorFormat, PLATFORM_OPENCL >::OpenCLType TextureHeap< t_ColorFormat, PLATFORM_OPENCL >::OpenCLConvert() const {
633 
634  return m_image.get();
635 }
636 
637 
638 template< int t_ColorFormat >
639 void TextureHeap< t_ColorFormat, PLATFORM_OPENCL >::FreeObject( Object const* pObject ) {
640 
641  m_markedObjects.erase( pObject );
642  m_freeTree.Insert( pObject->Coordinates(), pObject->LogSize() );
643 }
644 
645 
646 template< int t_ColorFormat >
647 void TextureHeap< t_ColorFormat, PLATFORM_OPENCL >::MarkObject( Object const* pObject ) {
648 
649  m_markedObjects.insert( pObject );
650 }
651 
652 
653 
654 
655 } // namespace Synchronized
656 
657 
658 
659 
660 #endif // SETTING_OPENCL
661 
662 
663 
664 
665 #endif // SYNCHRONIZED_TEXTURE_HEAP_OPENCL_H