1 #ifndef __GPU__VBO_H__ 2 #define __GPU__VBO_H__ 3 4 5 6 7 #include "InstantiatedObject.h" 8 9 10 // Macro enabling to recover the offset, in bytes, of a field in a structure. 11 #ifdef OffsetOf 12 #undef OffsetOf 13 #endif 14 #define OffsetOf( STRUCT, FIELD ) ( (unsigned int) &((STRUCT*)NULL)->FIELD ) 15 16 17 namespace GPU 18 { 19 // Class used to stop recursive template inheritance of class VBO. 20 class DefaultVBO 21 { 22 public: Alloc()23 inline bool Alloc() { return true; } Destroy()24 inline bool Destroy() { return true; } Bind()25 inline void Bind() {} Unbind()26 inline void Unbind() {} Enable()27 inline void Enable() {} Disable()28 inline void Disable() {} 29 }; 30 31 32 // Class defining a VBO's component without a neutral behaviour. Necessary for recursive template inheritance 33 // with an arbitrary number of unordered parameters. 34 template <typename TStoreMode,typename T> 35 class DefaultVBOComponent : public T 36 { 37 public: Alloc()38 inline bool Alloc() { return T::Alloc(); } Destroy()39 inline bool Destroy() { return T::Destroy(); } Bind()40 inline void Bind() { T::Bind(); } Unbind()41 inline void Unbind() { T::Unbind(); } Enable()42 inline void Enable() { T::Enable(); } Disable()43 inline void Disable() { T::Disable(); } 44 }; 45 46 47 class InterlacedBuffers {}; 48 class DistinctBuffers {}; 49 50 51 52 53 template < typename TStoreMode, 54 template <typename,typename> class A = DefaultVBOComponent, 55 template <typename,typename> class B = DefaultVBOComponent, 56 template <typename,typename> class C = DefaultVBOComponent, 57 template <typename,typename> class D = DefaultVBOComponent, 58 template <typename,typename> class E = DefaultVBOComponent, 59 template <typename,typename> class F = DefaultVBOComponent, 60 template <typename,typename> class G = DefaultVBOComponent, 61 template <typename,typename> class H = DefaultVBOComponent > class VBO; 62 63 64 template < template <typename,typename> class A, 65 template <typename,typename> class B, 66 template <typename,typename> class C, 67 template <typename,typename> class D, 68 template <typename,typename> class E, 69 template <typename,typename> class F, 70 template <typename,typename> class G, 71 template <typename,typename> class H > 72 class VBO<InterlacedBuffers,A,B,C,D,E,F,G,H> : public H< InterlacedBuffers, 73 G< InterlacedBuffers, 74 F< InterlacedBuffers, 75 E< InterlacedBuffers, 76 D< InterlacedBuffers, 77 C< InterlacedBuffers, 78 B< InterlacedBuffers, 79 A< InterlacedBuffers,DefaultVBO >>>>>>>>, 80 public InstantiatedObject 81 { 82 private: 83 typedef H< InterlacedBuffers, 84 G< InterlacedBuffers, 85 F< InterlacedBuffers, 86 E< InterlacedBuffers, 87 D< InterlacedBuffers, 88 C< InterlacedBuffers, 89 B< InterlacedBuffers, 90 A< InterlacedBuffers,DefaultVBO >>>>>>>> Super; 91 92 GLuint m_DataVBOId; 93 94 protected: Allocate()95 inline bool Allocate() 96 { 97 glGenBuffersARB( 1, &m_DataVBOId ); 98 glBindBufferARB( GL_ARRAY_BUFFER_ARB, m_DataVBOId ); 99 glBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 ); 100 return m_DataVBOId!=0 && Super::Alloc(); 101 } Unallocate()102 inline bool Unallocate() 103 { 104 glDeleteBuffersARB( 1, &m_DataVBOId ); 105 m_DataVBOId = 0; 106 return Super::Destroy(); 107 } 108 109 public: VBO()110 inline VBO() : InstantiatedObject(), m_DataVBOId(0) {} ~VBO()111 inline ~VBO() { Release(); } 112 Create()113 inline bool Create() { return Instantiate(); } 114 template <typename T> Create(GLenum usage,T * buffer,GLsizei count)115 inline bool Create( GLenum usage, T *buffer, GLsizei count ) 116 { 117 return Instantiate() && LoadData( usage, buffer, count ); 118 } 119 120 template <typename T> LoadData(GLenum usage,T * buffer,GLsizei count)121 inline bool LoadData( GLenum usage, T *buffer, GLsizei count ) 122 { 123 if( m_DataVBOId ) 124 { 125 glBindBufferARB( GL_ARRAY_BUFFER_ARB, m_DataVBOId ); 126 glBufferDataARB( GL_ARRAY_BUFFER_ARB, count*sizeof(T), buffer, usage ); 127 glBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 ); 128 return true; 129 } 130 return false; 131 } 132 Bind()133 inline void Bind() 134 { 135 glPushClientAttrib( GL_CLIENT_VERTEX_ARRAY_BIT ); 136 if( m_DataVBOId ) 137 { 138 glBindBufferARB( GL_ARRAY_BUFFER_ARB, m_DataVBOId ); 139 Super::Bind(); 140 } 141 } Unbind()142 inline void Unbind() 143 { 144 Super::Unbind(); 145 glBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 ); 146 glPopClientAttrib(); 147 } 148 DrawArrays(GLenum mode,GLint first,GLsizei count)149 inline void DrawArrays( GLenum mode, GLint first, GLsizei count ) { glDrawArrays( mode, first, count ); } 150 }; 151 152 153 template < template <typename,typename> class A, 154 template <typename,typename> class B, 155 template <typename,typename> class C, 156 template <typename,typename> class D, 157 template <typename,typename> class E, 158 template <typename,typename> class F, 159 template <typename,typename> class G, 160 template <typename,typename> class H > 161 class VBO<DistinctBuffers,A,B,C,D,E,F,G,H> : public H< DistinctBuffers, 162 G< DistinctBuffers, 163 F< DistinctBuffers, 164 E< DistinctBuffers, 165 D< DistinctBuffers, 166 C< DistinctBuffers, 167 B< DistinctBuffers, 168 A< DistinctBuffers,DefaultVBO >>>>>>>>, 169 public InstantiatedObject 170 { 171 private: 172 typedef H< DistinctBuffers, 173 G< DistinctBuffers, 174 F< DistinctBuffers, 175 E< DistinctBuffers, 176 D< DistinctBuffers, 177 C< DistinctBuffers, 178 B< DistinctBuffers, 179 A< DistinctBuffers,DefaultVBO >>>>>>>> Super; 180 181 protected: Allocate()182 inline bool Allocate() { return Super::Alloc(); } Unallocate()183 inline bool Unallocate() { return Super::Destroy(); } 184 185 public: VBO()186 inline VBO() : InstantiatedObject() {} ~VBO()187 inline ~VBO() { Release(); } 188 Create()189 inline bool Create() { return Instantiate(); } 190 Bind()191 inline void Bind() 192 { 193 glPushClientAttrib( GL_CLIENT_VERTEX_ARRAY_BIT ); 194 Super::Bind(); 195 } Unbind()196 inline void Unbind() 197 { 198 Super::Unbind(); 199 glBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 ); 200 glPopClientAttrib(); 201 } 202 DrawArrays(GLenum mode,GLint first,GLsizei count)203 inline void DrawArrays( GLenum mode, GLint first, GLsizei count ) { glDrawArrays( mode, first, count ); } 204 }; 205 206 207 208 209 template <typename TStoreMode> class VBOComponentContainer; 210 211 212 template <> 213 class VBOComponentContainer<InterlacedBuffers> 214 { 215 static const GLuint ENABLE_MASK = 1 << (8*sizeof(GLuint) - 1); 216 static const GLuint STRIDE_MASK = ((GLuint)-1) ^ ENABLE_MASK; 217 218 private: 219 GLuint m_StrideEnable; 220 GLuint m_Offset; 221 222 public: VBOComponentContainer()223 inline VBOComponentContainer() : m_StrideEnable(0), m_Offset(0) {} 224 SetPointer(GLuint stride,GLuint offset)225 inline void SetPointer( GLuint stride, GLuint offset ) 226 { 227 m_StrideEnable = stride | (m_StrideEnable & ENABLE_MASK); 228 m_Offset = offset; 229 } Stride()230 inline GLuint Stride() const { return m_StrideEnable & STRIDE_MASK; } Offset()231 inline GLuint Offset() const { return m_Offset; } 232 Alloc()233 inline bool Alloc() { return true; } Destroy()234 inline bool Destroy() { return true; } Bind()235 inline void Bind() {} Unbind()236 inline void Unbind() {} 237 IsEnabled()238 inline bool IsEnabled() const { return (m_StrideEnable & ENABLE_MASK) == 0; } IsDisabled()239 inline bool IsDisabled() const { return !IsEnabled(); } Enable()240 inline void Enable() { m_StrideEnable &= STRIDE_MASK; } Disable()241 inline void Disable() { m_StrideEnable |= ENABLE_MASK; } 242 }; 243 244 245 template <> 246 class VBOComponentContainer<DistinctBuffers> : public VBOComponentContainer<InterlacedBuffers> 247 { 248 private: 249 GLuint m_DataVBOId; 250 251 public: VBOComponentContainer()252 inline VBOComponentContainer() : VBOComponentContainer<InterlacedBuffers>(), m_DataVBOId(0) {} 253 Alloc()254 inline bool Alloc() 255 { 256 glGenBuffersARB( 1, &m_DataVBOId ); 257 glBindBufferARB( GL_ARRAY_BUFFER_ARB, m_DataVBOId ); 258 glBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 ); 259 return m_DataVBOId!=0; 260 } Destroy()261 inline bool Destroy() 262 { 263 glDeleteBuffersARB( 1, &m_DataVBOId ); 264 m_DataVBOId = 0; 265 return true; 266 } Bind()267 inline void Bind() 268 { 269 if( m_DataVBOId ) 270 glBindBufferARB( GL_ARRAY_BUFFER_ARB, m_DataVBOId ); 271 } Unbind()272 inline void Unbind() {} 273 274 template <typename T> LoadData(GLenum usage,T * buffer,GLsizei count)275 inline bool LoadData( GLenum usage, T *buffer, GLsizei count ) 276 { 277 if( m_DataVBOId ) 278 { 279 glBindBufferARB( GL_ARRAY_BUFFER_ARB, m_DataVBOId ); 280 glBufferDataARB( GL_ARRAY_BUFFER_ARB, count*sizeof(T), buffer, usage ); 281 glBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 ); 282 return true; 283 } 284 return false; 285 } 286 }; 287 288 289 290 291 template <typename TStoreMode,int TSize,int TGLType,typename T> 292 class VertexVBOComponent : public T 293 { 294 public: 295 VBOComponentContainer<TStoreMode> Vertex; Alloc()296 inline bool Alloc() { return Vertex.Alloc() && T::Alloc(); } Destroy()297 inline bool Destroy() { return Vertex.Destroy() && T::Destroy(); } Bind()298 inline void Bind() 299 { 300 if( Vertex.IsEnabled() ) 301 { 302 Vertex.Bind(); 303 glEnableClientState( GL_VERTEX_ARRAY ); 304 glVertexPointer( TSize, TGLType, Vertex.Stride(), (const GLvoid*)(Vertex.Offset()) ); 305 } 306 T::Bind(); 307 } Unbind()308 inline void Unbind() { Vertex.Unbind(); T::Unbind(); } Enable()309 inline void Enable() { Vertex.Enable(); T::Enable(); } Disable()310 inline void Disable() { Vertex.Disable(); T::Disable(); } 311 }; 312 313 template <typename TStoreMode,typename T> class Vertex2s : public VertexVBOComponent<TStoreMode,2,GL_SHORT ,T> {}; 314 template <typename TStoreMode,typename T> class Vertex2i : public VertexVBOComponent<TStoreMode,2,GL_INT ,T> {}; 315 template <typename TStoreMode,typename T> class Vertex2f : public VertexVBOComponent<TStoreMode,2,GL_FLOAT ,T> {}; 316 template <typename TStoreMode,typename T> class Vertex2d : public VertexVBOComponent<TStoreMode,2,GL_DOUBLE,T> {}; 317 template <typename TStoreMode,typename T> class Vertex3s : public VertexVBOComponent<TStoreMode,3,GL_SHORT ,T> {}; 318 template <typename TStoreMode,typename T> class Vertex3i : public VertexVBOComponent<TStoreMode,3,GL_INT ,T> {}; 319 template <typename TStoreMode,typename T> class Vertex3f : public VertexVBOComponent<TStoreMode,3,GL_FLOAT ,T> {}; 320 template <typename TStoreMode,typename T> class Vertex3d : public VertexVBOComponent<TStoreMode,3,GL_DOUBLE,T> {}; 321 template <typename TStoreMode,typename T> class Vertex4s : public VertexVBOComponent<TStoreMode,4,GL_SHORT ,T> {}; 322 template <typename TStoreMode,typename T> class Vertex4i : public VertexVBOComponent<TStoreMode,4,GL_INT ,T> {}; 323 template <typename TStoreMode,typename T> class Vertex4f : public VertexVBOComponent<TStoreMode,4,GL_FLOAT ,T> {}; 324 template <typename TStoreMode,typename T> class Vertex4d : public VertexVBOComponent<TStoreMode,4,GL_DOUBLE,T> {}; 325 326 327 template <typename TStoreMode,int TGLType,typename T> 328 class NormalVBOComponent : public T 329 { 330 public: 331 VBOComponentContainer<TStoreMode> Normal; Alloc()332 inline bool Alloc() { return Normal.Alloc() && T::Alloc(); } Destroy()333 inline bool Destroy() { return Normal.Destroy() && T::Destroy(); } Bind()334 inline void Bind() 335 { 336 if( Normal.IsEnabled() ) 337 { 338 Normal.Bind(); 339 glEnableClientState( GL_NORMAL_ARRAY ); 340 glNormalPointer( TGLType, Normal.Stride(), (const GLvoid*)(Normal.Offset()) ); 341 } 342 T::Bind(); 343 } Unbind()344 inline void Unbind() { Normal.Unbind(); T::Unbind(); } Enable()345 inline void Enable() { Normal.Enable(); T::Enable(); } Disable()346 inline void Disable() { Normal.Disable(); T::Disable(); } 347 }; 348 349 template <typename TStoreMode,typename T> class Normal3b : public NormalVBOComponent<typename TStoreMode,GL_BYTE ,T> {}; 350 template <typename TStoreMode,typename T> class Normal3s : public NormalVBOComponent<typename TStoreMode,GL_SHORT ,T> {}; 351 template <typename TStoreMode,typename T> class Normal3i : public NormalVBOComponent<typename TStoreMode,GL_INT ,T> {}; 352 template <typename TStoreMode,typename T> class Normal3f : public NormalVBOComponent<typename TStoreMode,GL_FLOAT ,T> {}; 353 template <typename TStoreMode,typename T> class Normal3d : public NormalVBOComponent<typename TStoreMode,GL_DOUBLE,T> {}; 354 355 356 template <typename TStoreMode,int TSize,int TGLType,typename T> 357 class ColorVBOComponent : public T 358 { 359 public: 360 VBOComponentContainer<TStoreMode> Color; Alloc()361 inline bool Alloc() { return Color.Alloc() && T::Alloc(); } Destroy()362 inline bool Destroy() { return Color.Destroy() && T::Destroy(); } Bind()363 inline void Bind() 364 { 365 if( Color.IsEnabled() ) 366 { 367 Color.Bind(); 368 glEnableClientState( GL_COLOR_ARRAY ); 369 glColorPointer( TSize, TGLType, Color.Stride(), (const GLvoid*)(Color.Offset()) ); 370 } 371 T::Bind(); 372 } Unbind()373 inline void Unbind() { Color.Unbind(); T::Unbind(); } Enable()374 inline void Enable() { Color.Enable(); T::Enable(); } Disable()375 inline void Disable() { Color.Disable(); T::Disable(); } 376 }; 377 378 template <typename TStoreMode,typename T> class Color3b : public ColorVBOComponent<typename TStoreMode,3,GL_BYTE ,T> {}; 379 template <typename TStoreMode,typename T> class Color3ub : public ColorVBOComponent<typename TStoreMode,3,GL_UNSIGNED_BYTE ,T> {}; 380 template <typename TStoreMode,typename T> class Color3s : public ColorVBOComponent<typename TStoreMode,3,GL_SHORT ,T> {}; 381 template <typename TStoreMode,typename T> class Color3us : public ColorVBOComponent<typename TStoreMode,3,GL_UNSIGNED_SHORT,T> {}; 382 template <typename TStoreMode,typename T> class Color3i : public ColorVBOComponent<typename TStoreMode,3,GL_INT ,T> {}; 383 template <typename TStoreMode,typename T> class Color3ui : public ColorVBOComponent<typename TStoreMode,3,GL_UNSIGNED_INT ,T> {}; 384 template <typename TStoreMode,typename T> class Color3f : public ColorVBOComponent<typename TStoreMode,3,GL_FLOAT ,T> {}; 385 template <typename TStoreMode,typename T> class Color3d : public ColorVBOComponent<typename TStoreMode,3,GL_DOUBLE ,T> {}; 386 template <typename TStoreMode,typename T> class Color4b : public ColorVBOComponent<typename TStoreMode,4,GL_BYTE ,T> {}; 387 template <typename TStoreMode,typename T> class Color4ub : public ColorVBOComponent<typename TStoreMode,4,GL_UNSIGNED_BYTE ,T> {}; 388 template <typename TStoreMode,typename T> class Color4s : public ColorVBOComponent<typename TStoreMode,4,GL_SHORT ,T> {}; 389 template <typename TStoreMode,typename T> class Color4us : public ColorVBOComponent<typename TStoreMode,4,GL_UNSIGNED_SHORT,T> {}; 390 template <typename TStoreMode,typename T> class Color4i : public ColorVBOComponent<typename TStoreMode,4,GL_INT ,T> {}; 391 template <typename TStoreMode,typename T> class Color4ui : public ColorVBOComponent<typename TStoreMode,4,GL_UNSIGNED_INT ,T> {}; 392 template <typename TStoreMode,typename T> class Color4f : public ColorVBOComponent<typename TStoreMode,4,GL_FLOAT ,T> {}; 393 template <typename TStoreMode,typename T> class Color4d : public ColorVBOComponent<typename TStoreMode,4,GL_DOUBLE ,T> {}; 394 395 396 template <typename TStoreMode,int TSize,int TGLType,typename T> 397 class TexCoordVBOComponent : public T 398 { 399 public: 400 VBOComponentContainer<TStoreMode> TexCoord; Alloc()401 inline bool Alloc() { return TexCoord.Alloc() && T::Alloc(); } Destroy()402 inline bool Destroy() { return TexCoord.Destroy() && T::Destroy(); } Bind()403 inline void Bind() 404 { 405 if( TexCoord.IsEnabled() ) 406 { 407 TexCoord.Bind(); 408 glEnableClientState( GL_TEXTURE_COORD_ARRAY ); 409 glTexCoordPointer( TSize, TGLType, TexCoord.Stride(), (const GLvoid*)(TexCoord.Offset()) ); 410 } 411 T::Bind(); 412 } Unbind()413 inline void Unbind() { TexCoord.Unbind(); T::Unbind(); } Enable()414 inline void Enable() { TexCoord.Enable(); T::Enable(); } Disable()415 inline void Disable() { TexCoord.Disable(); T::Disable(); } 416 }; 417 418 template <typename TStoreMode,typename T> class TexCoord1s : public TexCoordVBOComponent<typename TStoreMode,1,GL_SHORT ,T> {}; 419 template <typename TStoreMode,typename T> class TexCoord1i : public TexCoordVBOComponent<typename TStoreMode,1,GL_INT ,T> {}; 420 template <typename TStoreMode,typename T> class TexCoord1f : public TexCoordVBOComponent<typename TStoreMode,1,GL_FLOAT ,T> {}; 421 template <typename TStoreMode,typename T> class TexCoord1d : public TexCoordVBOComponent<typename TStoreMode,1,GL_DOUBLE,T> {}; 422 template <typename TStoreMode,typename T> class TexCoord2s : public TexCoordVBOComponent<typename TStoreMode,2,GL_SHORT ,T> {}; 423 template <typename TStoreMode,typename T> class TexCoord2i : public TexCoordVBOComponent<typename TStoreMode,2,GL_INT ,T> {}; 424 template <typename TStoreMode,typename T> class TexCoord2f : public TexCoordVBOComponent<typename TStoreMode,2,GL_FLOAT ,T> {}; 425 template <typename TStoreMode,typename T> class TexCoord2d : public TexCoordVBOComponent<typename TStoreMode,2,GL_DOUBLE,T> {}; 426 template <typename TStoreMode,typename T> class TexCoord3s : public TexCoordVBOComponent<typename TStoreMode,3,GL_SHORT ,T> {}; 427 template <typename TStoreMode,typename T> class TexCoord3i : public TexCoordVBOComponent<typename TStoreMode,3,GL_INT ,T> {}; 428 template <typename TStoreMode,typename T> class TexCoord3f : public TexCoordVBOComponent<typename TStoreMode,3,GL_FLOAT ,T> {}; 429 template <typename TStoreMode,typename T> class TexCoord3d : public TexCoordVBOComponent<typename TStoreMode,3,GL_DOUBLE,T> {}; 430 template <typename TStoreMode,typename T> class TexCoord4s : public TexCoordVBOComponent<typename TStoreMode,4,GL_SHORT ,T> {}; 431 template <typename TStoreMode,typename T> class TexCoord4i : public TexCoordVBOComponent<typename TStoreMode,4,GL_INT ,T> {}; 432 template <typename TStoreMode,typename T> class TexCoord4f : public TexCoordVBOComponent<typename TStoreMode,4,GL_FLOAT ,T> {}; 433 template <typename TStoreMode,typename T> class TexCoord4d : public TexCoordVBOComponent<typename TStoreMode,4,GL_DOUBLE,T> {}; 434 435 436 template <typename TRealType,int TGLType,typename T> 437 class IndexVBOComponent : public T 438 { 439 private: 440 GLuint m_IndexVBOId; 441 442 public: Alloc()443 inline bool Alloc() 444 { 445 glGenBuffersARB( 1, &m_IndexVBOId ); 446 glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, m_IndexVBOId ); 447 glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, 0 ); 448 return m_IndexVBOId!=0 && T::Alloc(); 449 } Destroy()450 inline bool Destroy() 451 { 452 glDeleteBuffersARB( 1, &m_IndexVBOId ); 453 m_IndexVBOId = 0; 454 return T::Destroy(); 455 } 456 Bind()457 inline void Bind() 458 { 459 if( m_IndexVBOId ) 460 glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, m_IndexVBOId ); 461 T::Bind(); 462 } Unbind()463 inline void Unbind() 464 { 465 glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, 0 ); 466 T::Unbind(); 467 } 468 LoadIndices(GLenum usage,TRealType * buffer,GLsizei count)469 inline bool LoadIndices( GLenum usage, TRealType *buffer, GLsizei count ) 470 { 471 if( m_IndexVBOId ) 472 { 473 glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, m_IndexVBOId ); 474 glBufferDataARB( GL_ELEMENT_ARRAY_BUFFER_ARB, count*sizeof(TRealType), buffer, usage ); 475 glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, 0 ); 476 return true; 477 } 478 return false; 479 } 480 DrawElements(GLenum mode,GLint first,GLsizei count)481 inline void DrawElements( GLenum mode, GLint first, GLsizei count ) 482 { 483 glDrawElements( mode, count, TGLType, (const GLvoid*)(first*sizeof(TRealType)) ); 484 } 485 }; 486 487 template <typename TStoreMode,typename T> class Indexub : public IndexVBOComponent<GLubyte ,GL_UNSIGNED_BYTE ,T> {}; 488 template <typename TStoreMode,typename T> class Indexus : public IndexVBOComponent<GLushort,GL_UNSIGNED_SHORT,T> {}; 489 template <typename TStoreMode,typename T> class Indexui : public IndexVBOComponent<GLuint ,GL_UNSIGNED_INT ,T> {}; 490 }; // namespace GPU 491 492 493 494 495 #endif /*__GPU__VBO_H__*/ 496