CudaTypes.h

Go to the documentation of this file.
00001 /******************************************************************************
00002 *       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 3      *
00003 *                (c) 2006-2008 MGH, INRIA, USTL, UJF, CNRS                    *
00004 *                                                                             *
00005 * This library is free software; you can redistribute it and/or modify it     *
00006 * under the terms of the GNU Lesser General Public License as published by    *
00007 * the Free Software Foundation; either version 2.1 of the License, or (at     *
00008 * your option) any later version.                                             *
00009 *                                                                             *
00010 * This library is distributed in the hope that it will be useful, but WITHOUT *
00011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
00012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
00013 * for more details.                                                           *
00014 *                                                                             *
00015 * You should have received a copy of the GNU Lesser General Public License    *
00016 * along with this library; if not, write to the Free Software Foundation,     *
00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
00018 *******************************************************************************
00019 *                               SOFA :: Modules                               *
00020 *                                                                             *
00021 * Authors: The SOFA Team and external contributors (see Authors.txt)          *
00022 *                                                                             *
00023 * Contact information: contact@sofa-framework.org                             *
00024 ******************************************************************************/
00025 #ifndef SOFA_GPU_CUDA_CUDATYPES_H
00026 #define SOFA_GPU_CUDA_CUDATYPES_H
00027 
00028 //#include "host_runtime.h" // CUDA
00029 #include "CudaCommon.h"
00030 #include "mycuda.h"
00031 #include <sofa/helper/system/gl.h>
00032 #include <sofa/defaulttype/Vec.h>
00033 #include <sofa/helper/vector.h>
00034 //#include <sofa/helper/BackTrace.h>
00035 #include <sofa/core/objectmodel/Base.h>
00036 #include <sofa/core/componentmodel/behavior/ForceField.h>
00037 #include <sofa/defaulttype/RigidTypes.h>
00038 #include <iostream>
00039 
00040 namespace sofa
00041 {
00042 
00043 namespace gpu
00044 {
00045 
00046 namespace cuda
00047 {
00048 
00049   
00050 template<class T>
00051 class CudaVector
00052 {
00053 public:
00054     typedef T      value_type;
00055     typedef size_t size_type;
00056 
00057 protected:
00058     size_type     vectorSize;     
00059     size_type     allocSize;      
00060     mutable void* devicePointer;  
00061     T*            hostPointer;    
00062     GLuint        bufferObject;   
00063     mutable bool  deviceIsValid;  
00064     mutable bool  hostIsValid;    
00065     mutable bool  bufferIsRegistered;  
00066 
00067 public:
00068 
00069     CudaVector()
00070     : vectorSize ( 0 ), allocSize ( 0 ), devicePointer ( NULL ), hostPointer ( NULL ), bufferObject ( 0 ), deviceIsValid ( true ), hostIsValid ( true ), bufferIsRegistered( false )
00071     {}
00072     CudaVector ( size_type n )
00073     : vectorSize ( 0 ), allocSize ( 0 ), devicePointer ( NULL ), hostPointer ( NULL ), bufferObject ( 0 ), deviceIsValid ( true ), hostIsValid ( true ), bufferIsRegistered( false )
00074     {
00075         resize ( n );
00076     }
00077     CudaVector ( const CudaVector<T>& v )
00078     : vectorSize ( 0 ), allocSize ( 0 ), devicePointer ( NULL ), hostPointer ( NULL ), bufferObject ( 0 ), deviceIsValid ( true ), hostIsValid ( true ), bufferIsRegistered( false )
00079     {
00080         *this = v;
00081     }
00082     void clear()
00083     {
00084         vectorSize = 0;
00085         deviceIsValid = true;
00086         hostIsValid = true;
00087     }
00088 
00089     void operator= ( const CudaVector<T>& v )
00090     {
00091     if (&v == this)
00092     {
00093         std::cerr << "ERROR: self-assignment of CudaVector< " << core::objectmodel::Base::decodeTypeName(typeid(T)) << ">"<<std::endl;
00094         return;
00095     }
00096     size_type newSize = v.size();
00097         clear();
00098         fastResize ( newSize );
00099         deviceIsValid = v.deviceIsValid;
00100         hostIsValid = v.hostIsValid;
00101         if ( vectorSize > 0 && deviceIsValid )
00102     {
00103         if (bufferObject)
00104         mapBuffer();
00105         if (v.bufferObject)
00106         v.mapBuffer();
00107         mycudaMemcpyDeviceToDevice ( devicePointer, v.devicePointer, vectorSize*sizeof ( T ) );
00108     }
00109         if ( vectorSize!=0 && hostIsValid )
00110             std::copy ( v.hostPointer, v.hostPointer+vectorSize, hostPointer );
00111     }
00112     ~CudaVector()
00113     {
00114         if ( hostPointer!=NULL )
00115             mycudaFreeHost ( hostPointer );
00116     if ( bufferObject )
00117     {
00118         unregisterBuffer();
00119         glDeleteBuffers( 1, &bufferObject);
00120     }
00121     else
00122     {
00123         if ( devicePointer!=NULL )
00124         mycudaFree ( devicePointer );
00125     }
00126     }
00127     size_type size() const
00128     {
00129         return vectorSize;
00130     }
00131     bool empty() const
00132     {
00133         return vectorSize==0;
00134     }
00135      void reserve (size_type s,size_type WARP_SIZE=BSIZE)
00136     {
00137         if ( s <= allocSize ) return;
00138         allocSize = ( s>2*allocSize ) ?s:2*allocSize;
00139         // always allocate multiples of BSIZE values
00140           allocSize = ( allocSize+WARP_SIZE-1 ) &-WARP_SIZE;
00141 
00142     if (bufferObject)
00143     {
00144         if (mycudaVerboseLevel>=LOG_INFO) std::cout << "CudaVector<"<<sofa::core::objectmodel::Base::className((T*)NULL)<<"> : GL reserve("<<s<<")"<<std::endl;
00145         hostRead(); // make sure the host copy is valid
00146         unregisterBuffer();
00147         glBindBuffer( GL_ARRAY_BUFFER, bufferObject);
00148         glBufferData( GL_ARRAY_BUFFER, allocSize*sizeof ( T ), 0, GL_DYNAMIC_DRAW);
00149         glBindBuffer( GL_ARRAY_BUFFER, 0);
00150         if ( vectorSize > 0 && deviceIsValid )
00151         deviceIsValid = false;
00152     }
00153     else
00154     {
00155         void* prevDevicePointer = devicePointer;
00156         if (mycudaVerboseLevel>=LOG_INFO) std::cout << "CudaVector<"<<sofa::core::objectmodel::Base::className((T*)NULL)<<"> : reserve("<<s<<")"<<std::endl;
00157         mycudaMalloc ( &devicePointer, allocSize*sizeof ( T ) );
00158         if ( vectorSize > 0 && deviceIsValid )
00159         mycudaMemcpyDeviceToDevice ( devicePointer, prevDevicePointer, vectorSize*sizeof ( T ) );
00160         if ( prevDevicePointer != NULL )
00161         mycudaFree ( prevDevicePointer );
00162     }
00163 
00164         T* prevHostPointer = hostPointer;
00165         void* newHostPointer = NULL;
00166         mycudaMallocHost ( &newHostPointer, allocSize*sizeof ( T ) );
00167         hostPointer = (T*)newHostPointer;
00168         if ( vectorSize!=0 && hostIsValid )
00169             std::copy ( prevHostPointer, prevHostPointer+vectorSize, hostPointer );
00170         if ( prevHostPointer != NULL )
00171             mycudaFreeHost ( prevHostPointer );
00172     }
00174      void fastResize ( size_type s,size_type WARP_SIZE=BSIZE)
00175     {
00176         if ( s == vectorSize ) return;
00177           reserve ( s,WARP_SIZE);
00178         vectorSize = s;
00179         if ( !vectorSize )
00180         {
00181             // special case when the vector is now empty -> host and device are valid
00182             deviceIsValid = true;
00183             hostIsValid = true;
00184         }
00185     }
00186      void resize ( size_type s,size_type WARP_SIZE=BSIZE)
00187     {
00188         if ( s == vectorSize ) return;
00189           reserve ( s,WARP_SIZE);
00190         if ( s > vectorSize )
00191         {
00192         copyToHost();
00193         memset(hostPointer+vectorSize,0,(s-vectorSize)*sizeof(T));
00194             // Call the constructor for the new elements
00195             for ( size_type i = vectorSize; i < s; i++ )
00196             {
00197                 ::new ( hostPointer+i ) T;
00198             }
00199             if ( deviceIsValid )
00200             {
00201                 if ( vectorSize == 0 )
00202                 {
00203                     // wait until the transfer is really necessary, as other modifications might follow
00204                     deviceIsValid = false;
00205                 }
00206                 else
00207                 {
00208             if (bufferObject)
00209             mapBuffer();
00210                     mycudaMemcpyHostToDevice ( ( ( T* ) devicePointer ) +vectorSize, hostPointer+vectorSize, ( s-vectorSize ) *sizeof ( T ) );
00211                 }
00212             }
00213         }
00214         else if (s < vectorSize)
00215         {
00216         copyToHost();
00217             // Call the destructor for the deleted elements
00218             for ( size_type i = s; i < vectorSize; i++ )
00219             {
00220                 hostPointer[i].~T();
00221             }
00222         }
00223         vectorSize = s;
00224         if ( !vectorSize )
00225         {
00226             // special case when the vector is now empty -> host and device are valid
00227             deviceIsValid = true;
00228             hostIsValid = true;
00229         }
00230     }
00231     void swap ( CudaVector<T>& v )
00232     {
00233 #define VSWAP(type, var) { type t = var; var = v.var; v.var = t; }
00234         VSWAP ( size_type, vectorSize );
00235         VSWAP ( size_type, allocSize );
00236         VSWAP ( void*    , devicePointer );
00237         VSWAP ( T*       , hostPointer );
00238     VSWAP ( GLuint   , bufferObject );
00239         VSWAP ( bool     , deviceIsValid );
00240         VSWAP ( bool     , hostIsValid );
00241         VSWAP ( bool     , bufferIsRegistered );
00242 #undef VSWAP
00243     }
00244     const void* deviceRead ( int i=0 ) const
00245     {
00246         copyToDevice();
00247         return ( ( const T* ) devicePointer ) +i;
00248     }
00249     void* deviceWrite ( int i=0 )
00250     {
00251         copyToDevice();
00252         hostIsValid = false;
00253         return ( ( T* ) devicePointer ) +i;
00254     }
00255     const T* hostRead ( int i=0 ) const
00256     {
00257         copyToHost();
00258         return hostPointer+i;
00259     }
00260     T* hostWrite ( int i=0 )
00261     {
00262         copyToHost();
00263         deviceIsValid = false;
00264         return hostPointer+i;
00265     }
00266     bool isHostValid() const
00267     {
00268         return hostIsValid;
00269     }
00270     bool isDeviceValid() const
00271     {
00272         return deviceIsValid;
00273     }
00274 
00276     GLuint bufferRead(bool create = false)
00277     {
00278     if (!bufferObject)
00279       {
00280         if (create)
00281         createBuffer();
00282         else
00283         return 0;
00284       }
00285     copyToDevice();
00286     return bufferObject;
00287     }
00288 
00290     GLuint bufferWrite(bool create = false)
00291     {
00292     if (!bufferObject)
00293       {
00294         if (create)
00295         createBuffer();
00296         else
00297         return 0;
00298       }
00299     copyToDevice();
00300     unmapBuffer();
00301     hostIsValid = false;
00302     return bufferObject;
00303     }
00304 
00305     void push_back ( const T& t )
00306     {
00307         size_type i = size();
00308         copyToHost();
00309         deviceIsValid = false;
00310         fastResize ( i+1 );
00311         ::new ( hostPointer+i ) T ( t );
00312     }
00313     void pop_back()
00314     {
00315         if ( !empty() )
00316             resize ( size()-1 );
00317     }
00318     const T& operator[] ( size_type i ) const
00319     {
00320         checkIndex ( i );
00321         return hostRead() [i];
00322     }
00323     T& operator[] ( size_type i )
00324     {
00325         checkIndex ( i );
00326         return hostWrite() [i];
00327     }
00328 
00329     const T& getCached ( size_type i ) const
00330     {
00331         checkIndex ( i );
00332         return hostPointer[i];
00333     }
00334 
00336     inline friend std::ostream& operator<< ( std::ostream& os, const CudaVector<T>& vec )
00337     {
00338         if ( vec.size() >0 )
00339         {
00340             for ( unsigned int i=0; i<vec.size()-1; ++i ) os<<vec[i]<<" ";
00341             os<<vec[vec.size()-1];
00342         }
00343         return os;
00344     }
00345 
00347     inline friend std::istream& operator>> ( std::istream& in, CudaVector<T>& vec )
00348     {
00349         T t;
00350         vec.clear();
00351         while ( in>>t )
00352         {
00353             vec.push_back ( t );
00354         }
00355         if ( in.rdstate() & std::ios_base::eofbit ) { in.clear(); }
00356         return in;
00357     }
00358 
00359 protected:
00360     void copyToHost() const
00361     {
00362         if ( hostIsValid ) return;
00363 //#ifndef NDEBUG
00364         if (mycudaVerboseLevel>=LOG_TRACE)
00365         {
00366             std::cout << "CUDA: GPU->CPU copy of "<<sofa::core::objectmodel::Base::decodeTypeName ( typeid ( *this ) ) <<": "<<vectorSize*sizeof ( T ) <<" B"<<std::endl;
00367             //sofa::helper::BackTrace::dump();
00368         }
00369 //#endif
00370     if (bufferObject)
00371         mapBuffer();
00372         mycudaMemcpyDeviceToHost ( hostPointer, devicePointer, vectorSize*sizeof ( T ) );
00373         hostIsValid = true;
00374     }
00375     void copyToDevice() const
00376     {
00377     if (bufferObject)
00378         mapBuffer();
00379         if ( deviceIsValid ) return;
00380 //#ifndef NDEBUG
00381         if (mycudaVerboseLevel>=LOG_TRACE) std::cout << "CUDA: CPU->GPU copy of "<<sofa::core::objectmodel::Base::decodeTypeName ( typeid ( *this ) ) <<": "<<vectorSize*sizeof ( T ) <<" B"<<std::endl;
00382 //#endif
00383         mycudaMemcpyHostToDevice ( devicePointer, hostPointer, vectorSize*sizeof ( T ) );
00384         deviceIsValid = true;
00385     }
00386 #ifdef NDEBUG
00387     void checkIndex ( size_type ) const
00388     {
00389     }
00390 #else
00391     void checkIndex ( size_type i ) const
00392     {
00393         assert ( i<this->size() );
00394     }
00395 #endif
00396     void registerBuffer() const
00397     {
00398     if (allocSize > 0 && !bufferIsRegistered)
00399     {
00400         mycudaGLRegisterBufferObject(bufferObject);
00401         bufferIsRegistered = true;
00402     }
00403     }
00404     void mapBuffer() const
00405     {
00406     registerBuffer();
00407     if (allocSize > 0 && devicePointer==NULL)
00408     {
00409         mycudaGLMapBufferObject(&devicePointer, bufferObject);
00410     }
00411     }
00412     void unmapBuffer() const
00413     {
00414     if (allocSize > 0 && devicePointer != NULL)
00415     {
00416         mycudaGLUnmapBufferObject(bufferObject);
00417         devicePointer = NULL;
00418     }
00419     }
00420     void unregisterBuffer() const
00421     {
00422     unmapBuffer();
00423     if (allocSize > 0 && bufferIsRegistered)
00424     {
00425         mycudaGLUnregisterBufferObject(bufferObject);
00426         bufferIsRegistered = false;
00427     }
00428     }
00429     void createBuffer()
00430     {
00431     if (bufferObject) return;
00432     glGenBuffers(1, &bufferObject);
00433     if (allocSize > 0)
00434     {
00435         glBindBuffer( GL_ARRAY_BUFFER, bufferObject);
00436         glBufferData( GL_ARRAY_BUFFER, allocSize*sizeof ( T ), 0, GL_DYNAMIC_DRAW);
00437         glBindBuffer( GL_ARRAY_BUFFER, 0);
00438         void* prevDevicePointer = devicePointer;
00439         devicePointer = NULL;
00440         if ( vectorSize > 0 && deviceIsValid )
00441         {
00442         mapBuffer();
00443         mycudaMemcpyDeviceToDevice ( devicePointer, prevDevicePointer, vectorSize*sizeof ( T ) );
00444         }
00445         if ( prevDevicePointer != NULL )
00446         mycudaFree ( prevDevicePointer );
00447     }
00448     }
00449 };
00450 
00451 template<class T>
00452 class CudaMatrix
00453 {
00454 public:
00455         typedef T      value_type;
00456         typedef size_t size_type;
00457 
00458 protected:
00459         size_type    sizeX;     
00460         size_type    sizeY;     
00461         size_type    pitch;     
00462         size_type    hostAllocSize;  
00463         size_type    deviceAllocSize;
00464         void*        devicePointer;  
00465         T*           hostPointer;    
00466         mutable bool deviceIsValid;  
00467         mutable bool hostIsValid;    
00468 public:
00469 
00470         CudaMatrix()
00471         : sizeX ( 0 ), sizeY( 0 ), pitch(0), hostAllocSize ( 0 ), deviceAllocSize ( 0 ), devicePointer ( NULL ), hostPointer ( NULL ), deviceIsValid ( true ), hostIsValid ( true )
00472         {}
00473         
00474         CudaMatrix(size_t x, size_t y )
00475         : sizeX ( 0 ), sizeY ( 0 ), pitch(0), hostAllocSize ( 0 ), deviceAllocSize ( 0 ), devicePointer ( NULL ), hostPointer ( NULL ), deviceIsValid ( true ), hostIsValid ( true )    {
00476                 resize (x,y,0);
00477         }
00478         
00479         CudaMatrix(const CudaMatrix<T>& v )
00480         : sizeX ( 0 ), sizeY ( 0 ), pitch(0), hostAllocSize ( 0 ), deviceAllocSize ( 0 ), devicePointer ( NULL ), hostPointer ( NULL ), deviceIsValid ( true ), hostIsValid ( true )    {
00481                 *this = v;
00482         }
00483         
00484         void clear() {
00485                 sizeY = 0;
00486                 sizeY = 0;
00487                 pitch = 0;
00488                 deviceIsValid = true;
00489                 hostIsValid = true;
00490         }
00491         
00492         ~CudaMatrix() {
00493                 if (hostPointer!=NULL) mycudaFreeHost(hostPointer);
00494                 if (devicePointer!=NULL) mycudaFree(devicePointer);
00495         }
00496         
00497         size_type getSizeX() const {
00498                 return sizeX;
00499         }
00500         
00501         size_type getSizeY() const {
00502                 return sizeY;
00503         }
00504         
00505         size_type getPitch() const {
00506                 return pitch;
00507         }
00508         bool empty() const {
00509                 return sizeX==0 || sizeY==0;
00510         }
00511         
00512         void fastResize(size_type x,size_type y,size_type WARP_SIZE=BSIZE) {
00513                 size_type s = x*y;
00514                 
00515                 if (s > hostAllocSize) {
00516                         hostAllocSize = ( s>2*hostAllocSize ) ? s : 2*hostAllocSize;
00517                         // always allocate multiples of BSIZE values
00518                                 hostAllocSize = ( hostAllocSize+WARP_SIZE-1 )/WARP_SIZE * WARP_SIZE;
00519                         T* prevHostPointer = hostPointer;
00520                         
00521                         if ( prevHostPointer != NULL ) mycudaFreeHost ( prevHostPointer );
00522                         void* newHostPointer = NULL;
00523                         mycudaMallocHost ( &newHostPointer, hostAllocSize*sizeof ( T ) );
00524                         hostPointer = (T*)newHostPointer;
00525                 }
00526                 
00527                 if (WARP_SIZE==0) pitch = x*sizeof(T);
00528                 else pitch = ((x+WARP_SIZE-1)/WARP_SIZE)*WARP_SIZE*sizeof(T);
00529                 int ypitch;
00530                 if (WARP_SIZE==0) ypitch = y;
00531                 else ypitch = ((y+WARP_SIZE-1)/WARP_SIZE)*WARP_SIZE;
00532                 if (ypitch*pitch > deviceAllocSize) {
00533                         void* prevDevicePointer = devicePointer;
00534                         if (prevDevicePointer != NULL ) mycudaFree ( prevDevicePointer );
00535                                 
00536                         mycudaMallocPitch(&devicePointer, &pitch, pitch, ypitch);
00537                         deviceAllocSize = ypitch*pitch;
00538                 }
00539                 
00540                 sizeX = x;
00541                 sizeY = y;
00542                 deviceIsValid = true;
00543                 hostIsValid = true;
00544         }
00545 
00546           void resize (size_type x,size_type y,size_t WARP_SIZE=BSIZE) {
00547               fastResize(x,y,WARP_SIZE);        
00548         }
00549 
00550         void swap ( CudaMatrix<T>& v ) {
00551 #define VSWAP(type, var) { type t = var; var = v.var; v.var = t; }
00552                 VSWAP ( size_type, sizeX );
00553                 VSWAP ( size_type, sizeY );
00554                 VSWAP ( size_type, pitch );
00555                 VSWAP ( size_type, hostAllocSize );
00556                 VSWAP ( size_type, deviceAllocSize );
00557                 VSWAP ( void*    , devicePointer );
00558                 VSWAP ( T*       , hostPointer );
00559                 VSWAP ( bool     , deviceIsValid );
00560                 VSWAP ( bool     , hostIsValid );
00561 #undef VSWAP
00562         }
00563         
00564         const void* deviceRead ( int x=0, int y=0 ) const {
00565                 copyToDevice();
00566                 return (const T*)(( ( const char* ) devicePointer ) +(y*pitch+x*sizeof(T)));
00567         }
00568         
00569         void* deviceWrite ( int x=0, int y=0 )  {
00570                 copyToDevice();
00571                 hostIsValid = false;
00572                 return (T*)(( ( const char* ) devicePointer ) +(y*pitch+x*sizeof(T)));
00573         }
00574         
00575         const T* hostRead ( int x=0, int y=0 ) const {
00576                 copyToHost();
00577                 return hostPointer+(y*sizeX+x);
00578         }
00579         
00580         T* hostWrite ( int x=0, int y=0 ) {
00581                 copyToHost();
00582                 deviceIsValid = false;
00583                 return hostPointer+(y*sizeX+x);
00584         }
00585         
00586         bool isHostValid() const {
00587                 return hostIsValid;
00588         }
00589         
00590         bool isDeviceValid() const  {
00591                 return deviceIsValid;
00592         }
00593 
00594         const T& operator() (size_type x,size_type y) const {
00595                 checkIndex (x,y);
00596                 return hostRead(x,y);
00597         }
00598         
00599         T& operator() (size_type x,size_type y) {
00600                 checkIndex (x,y);
00601                 return hostWrite(x,y);
00602         }                   
00603         
00604         const T* operator[] (size_type y) const {
00605                 checkIndex (0,y);
00606                 return hostRead(0,y);
00607         }
00608                         
00609         T* operator[] (size_type y) {
00610                 checkIndex (0,y);
00611                 return hostWrite(0,y);
00612         }
00613                         
00614         const T& getCached (size_type x,size_type y) const {
00615                 checkIndex (x,y);
00616                 return hostPointer[y*sizeX+x];
00617         }
00618         
00619 protected:
00620         void copyToHost() const
00621         {
00622                 if ( hostIsValid ) return;
00623 //#ifndef NDEBUG
00624                 if (mycudaVerboseLevel>=LOG_TRACE) std::cout << "CUDA: GPU->CPU copy of "<<sofa::core::objectmodel::Base::decodeTypeName ( typeid ( *this ) ) <<": "<<sizeX*sizeof(T) <<" B"<<std::endl;
00625 //#endif
00626                 mycudaMemcpyDeviceToHost2D ( hostPointer, sizeX*sizeof(T), devicePointer, pitch, sizeX*sizeof(T), sizeY);
00627                 hostIsValid = true;
00628         }
00629         void copyToDevice() const
00630         {
00631                 if ( deviceIsValid ) return;
00632 //#ifndef NDEBUG
00633                 if (mycudaVerboseLevel>=LOG_TRACE) std::cout << "CUDA: CPU->GPU copy of "<<sofa::core::objectmodel::Base::decodeTypeName ( typeid ( *this ) ) <<": "<<sizeX*sizeof(T) <<" B"<<std::endl;
00634 //#endif
00635                 mycudaMemcpyHostToDevice2D ( devicePointer, pitch, hostPointer, sizeX*sizeof(T),  sizeX*sizeof(T), sizeY);
00636                 deviceIsValid = true;
00637         }
00638 
00639 #ifdef NDEBUG
00640         void checkIndex ( size_type,size_type ) const
00641         {
00642         }
00643 #else
00644         void checkIndex ( size_type x,size_type y) const
00645         {
00646                 assert (x<this->sizeX);
00647                 assert (y<this->sizeY);
00648         }
00649 #endif
00650 
00651 };
00652 
00653 template<class TCoord, class TDeriv, class TReal = typename TCoord::value_type>
00654 class CudaVectorTypes
00655 {
00656 public:
00657         typedef TCoord Coord;
00658         typedef TDeriv Deriv;
00659         typedef TReal Real;
00660         typedef CudaVector<Coord> VecCoord;
00661         typedef CudaVector<Deriv> VecDeriv;
00662         typedef CudaVector<Real> VecReal;
00663 
00664         template <class T>
00665         class SparseData
00666         {
00667                 public:
00668                         SparseData ( unsigned int _index, const T& _data ) : index ( _index ), data ( _data ) {};
00669                         unsigned int index;
00670                         T data;
00671         };
00672 
00673         typedef SparseData<Coord> SparseCoord;
00674         typedef SparseData<Deriv> SparseDeriv;
00675 
00676         typedef CudaVector<SparseCoord> SparseVecCoord;
00677         typedef CudaVector<SparseDeriv> SparseVecDeriv;
00678 
00680         typedef    sofa::helper::vector<SparseVecDeriv> VecConst;
00681 
00682         template<class C, typename T>
00683         static void set( C& c, T x, T y, T z )
00684         {
00685                 if ( c.size() >0 )
00686                         c[0] = (Real) x;
00687                 if ( c.size() >1 )
00688                         c[1] = (Real) y;
00689                 if ( c.size() >2 )
00690                         c[2] = (Real) z;
00691         }
00692 
00693         template<class C, typename T>
00694         static void get( T& x, T& y, T& z, const C& c )
00695         {
00696                 x = ( c.size() >0 ) ? (T) c[0] : (T) 0.0;
00697                 y = ( c.size() >1 ) ? (T) c[1] : (T) 0.0;
00698                 z = ( c.size() >2 ) ? (T) c[2] : (T) 0.0;
00699         }
00700 
00701         template<class C, typename T>
00702         static void add( C& c, T x, T y, T z )
00703         {
00704                 if ( c.size() >0 )
00705                         c[0] += (Real) x;
00706                 if ( c.size() >1 )
00707                         c[1] += (Real) y;
00708                 if ( c.size() >2 )
00709                         c[2] += (Real) z;
00710         }
00711 
00712         template<class C>
00713         static C interpolate(const helper::vector< C > & ancestors, const helper::vector< Real > & coefs)
00714         {
00715             assert(ancestors.size() == coefs.size());
00716                 
00717             C coord;
00718             
00719             for (unsigned int i = 0; i < ancestors.size(); i++)
00720             {
00721                 coord += ancestors[i] * coefs[i];
00722             }
00723 
00724             return coord;
00725         }
00726 
00727         static const char* Name();
00728 };
00729 
00730 typedef sofa::defaulttype::Vec3f Vec3f;
00731 typedef sofa::defaulttype::Vec2f Vec2f;
00732 
00733 using defaulttype::Vec;
00734 using defaulttype::NoInit;
00735 using defaulttype::NOINIT;
00736 
00737 template<class Real>
00738 class Vec3r1 : public sofa::defaulttype::Vec<3,Real>
00739 {
00740 public:
00741     typedef sofa::defaulttype::Vec<3,Real> Inherit;
00742     typedef Real real;
00743     enum { N=3 };
00744     Vec3r1() : dummy(0.0f) {}
00745     template<class real2>
00746     Vec3r1(const Vec<N,real2>& v): Inherit(v), dummy(0.0f) {}
00747     Vec3r1(float x, float y, float z) : Inherit(x,y,z), dummy(0.0f) {}
00748 
00750     explicit Vec3r1(NoInit n) : Inherit(n), dummy(0.0f)
00751     {
00752     }
00753 
00754     // LINEAR ALGEBRA
00755 
00757     template<class real2>
00758     Vec3r1 operator*(real2 f) const
00759     {
00760         Vec3r1 r(NOINIT);
00761         for (int i=0;i<N;i++)
00762             r[i] = this->elems[i]*(real)f;
00763         return r;
00764     }
00765 
00767     template<class real2>
00768     void operator*=(real2 f)
00769     {
00770         for (int i=0;i<N;i++)
00771             this->elems[i]*=(real)f;
00772     }
00773 
00774     template<class real2>
00775     Vec3r1 operator/(real2 f) const
00776     {
00777         Vec3r1 r(NOINIT);
00778         for (int i=0;i<N;i++)
00779             r[i] = this->elems[i]/(real)f;
00780         return r;
00781     }
00782 
00784     template<class real2>
00785     void operator/=(real2 f)
00786     {
00787         for (int i=0;i<N;i++)
00788             this->elems[i]/=(real)f;
00789     }
00790 
00792     template<class real2>
00793     real operator*(const Vec<N,real2>& v) const
00794     {
00795         real r = (real)(this->elems[0]*v[0]);
00796         for (int i=1;i<N;i++)
00797             r += (real)(this->elems[i]*v[i]);
00798         return r;
00799     }
00800 
00802     real operator*(const Vec3r1& v) const
00803     {
00804         real r = (real)(this->elems[0]*v[0]);
00805         for (int i=1;i<N;i++)
00806             r += (real)(this->elems[i]*v[i]);
00807         return r;
00808     }
00809 
00811     template<class real2>
00812     Vec3r1 linearProduct(const Vec<N,real2>& v) const
00813     {
00814         Vec3r1 r(NOINIT);
00815         for (int i=0;i<N;i++)
00816             r[i]=this->elems[i]*(real)v[i];
00817         return r;
00818     }
00819 
00821     Vec3r1 linearProduct(const Vec3r1& v) const
00822     {
00823         Vec3r1 r(NOINIT);
00824         for (int i=0;i<N;i++)
00825             r[i]=this->elems[i]*(real)v[i];
00826         return r;
00827     }
00828 
00830     template<class real2>
00831     Vec3r1 operator+(const Vec<N,real2>& v) const
00832     {
00833         Vec3r1 r(NOINIT);
00834         for (int i=0;i<N;i++)
00835             r[i]=this->elems[i]+(real)v[i];
00836         return r;
00837     }
00838 
00840     Vec3r1 operator+(const Vec3r1& v) const
00841     {
00842         Vec3r1 r(NOINIT);
00843         for (int i=0;i<N;i++)
00844             r[i]=this->elems[i]+(real)v[i];
00845         return r;
00846     }
00847 
00849     template<class real2>
00850     void operator+=(const Vec<N,real2>& v)
00851     {
00852         for (int i=0;i<N;i++)
00853             this->elems[i]+=(real)v[i];
00854     }
00855 
00857     void operator+=(const Vec3r1& v)
00858     {
00859         for (int i=0;i<N;i++)
00860             this->elems[i]+=(real)v[i];
00861     }
00862 
00864     template<class real2>
00865     Vec3r1 operator-(const Vec<N,real2>& v) const
00866     {
00867         Vec3r1 r(NOINIT);
00868         for (int i=0;i<N;i++)
00869             r[i]=this->elems[i]-(real)v[i];
00870         return r;
00871     }
00872 
00874     Vec3r1 operator-(const Vec3r1& v) const
00875     {
00876         Vec3r1 r(NOINIT);
00877         for (int i=0;i<N;i++)
00878             r[i]=this->elems[i]-(real)v[i];
00879         return r;
00880     }
00881 
00883     template<class real2>
00884     void operator-=(const Vec<N,real2>& v)
00885     {
00886         for (int i=0;i<N;i++)
00887             this->elems[i]-=(real)v[i];
00888     }
00889 
00891     void operator-=(const Vec3r1& v)
00892     {
00893         for (int i=0;i<N;i++)
00894             this->elems[i]-=(real)v[i];
00895     }
00896 
00898     Vec3r1 operator-() const
00899     {
00900         Vec3r1 r(NOINIT);
00901         for (int i=0;i<N;i++)
00902             r[i]=-this->elems[i];
00903         return r;
00904     }
00905 
00906     Vec3r1 cross( const Vec3r1& b ) const
00907     {
00908         BOOST_STATIC_ASSERT(N == 3);
00909         return Vec3r1(
00910             (*this)[1]*b[2] - (*this)[2]*b[1],
00911             (*this)[2]*b[0] - (*this)[0]*b[2],
00912             (*this)[0]*b[1] - (*this)[1]*b[0]
00913         );
00914     }
00915 
00916 protected:
00917     float dummy;
00918 };
00919 
00920 typedef Vec3r1<float> Vec3f1;
00921 
00922 typedef CudaVectorTypes<Vec3f,Vec3f,float> CudaVec3fTypes;
00923 typedef CudaVec3fTypes CudaVec3Types;
00924 
00925 template<>
00926 inline const char* CudaVec3fTypes::Name()
00927 {
00928     return "CudaVec3f";
00929 }
00930 
00931 typedef CudaVectorTypes<Vec2f,Vec2f,float> CudaVec2fTypes;
00932 typedef CudaVec2fTypes CudaVec2Types;
00933 
00934 template<>
00935 inline const char* CudaVec2fTypes::Name()
00936 {
00937     return "CudaVec2f";
00938 }
00939 
00940 typedef CudaVectorTypes<Vec3f1,Vec3f1,float> CudaVec3f1Types;
00941 
00942 template<>
00943 inline const char* CudaVec3f1Types::Name()
00944 {
00945     return "CudaVec3f1";
00946 }
00947 
00948 template<int N, typename real>
00949 class CudaRigidTypes;
00950 
00951 template<typename real>
00952 class CudaRigidTypes<3, real>
00953 {
00954 public:
00955     typedef real Real;
00956     typedef sofa::defaulttype::RigidCoord<3,real> Coord;
00957     typedef sofa::defaulttype::RigidDeriv<3,real> Deriv;
00958     typedef typename Coord::Vec3 Vec3;
00959     typedef typename Coord::Quat Quat;
00960     typedef CudaVector<Coord> VecCoord;
00961     typedef CudaVector<Deriv> VecDeriv;
00962     typedef CudaVector<Real> VecReal;
00963 
00964     template <class T>
00965     class SparseData
00966     {
00967     public:
00968         SparseData ( unsigned int _index, const T& _data ) : index ( _index ), data ( _data ) {};
00969         unsigned int index;
00970         T data;
00971     };
00972 
00973     typedef SparseData<Coord> SparseCoord;
00974     typedef SparseData<Deriv> SparseDeriv;
00975 
00976     typedef CudaVector<SparseCoord> SparseVecCoord;
00977     typedef CudaVector<SparseDeriv> SparseVecDeriv;
00978 
00980     typedef    sofa::helper::vector<SparseVecDeriv> VecConst;
00981 
00982     template<typename T>
00983     static void set(Coord& r, T x, T y, T z)
00984     {
00985         Vec3& c = r.getCenter();
00986         if ( c.size() >0 )
00987             c[0] = (Real) x;
00988         if ( c.size() >1 )
00989             c[1] = (Real) y;
00990         if ( c.size() >2 )
00991             c[2] = (Real) z;
00992     }
00993 
00994     template<typename T>
00995     static void get(T& x, T& y, T& z, const Coord& r)
00996     {
00997         const Vec3& c = r.getCenter();
00998         x = ( c.size() >0 ) ? (T) c[0] : (T) 0.0;
00999         y = ( c.size() >1 ) ? (T) c[1] : (T) 0.0;
01000         z = ( c.size() >2 ) ? (T) c[2] : (T) 0.0;
01001     }
01002 
01003     template<typename T>
01004     static void add(Coord& r, T x, T y, T z)
01005     {
01006         Vec3& c = r.getCenter();
01007         if ( c.size() >0 )
01008             c[0] += (Real) x;
01009         if ( c.size() >1 )
01010             c[1] += (Real) y;
01011         if ( c.size() >2 )
01012             c[2] += (Real) z;
01013     }
01014 
01015     template<typename T>
01016     static void set(Deriv& r, T x, T y, T z)
01017     {
01018         Vec3& c = r.getVCenter();
01019         if ( c.size() >0 )
01020             c[0] = (Real) x;
01021         if ( c.size() >1 )
01022             c[1] = (Real) y;
01023         if ( c.size() >2 )
01024             c[2] = (Real) z;
01025     }
01026 
01027     template<typename T>
01028     static void get(T& x, T& y, T& z, const Deriv& r)
01029     {
01030         const Vec3& c = r.getVCenter();
01031         x = ( c.size() >0 ) ? (T) c[0] : (T) 0.0;
01032         y = ( c.size() >1 ) ? (T) c[1] : (T) 0.0;
01033         z = ( c.size() >2 ) ? (T) c[2] : (T) 0.0;
01034     }
01035 
01036     template<typename T>
01037     static void add(Deriv& r, T x, T y, T z)
01038     {
01039         Vec3& c = r.getVCenter();
01040         if ( c.size() >0 )
01041             c[0] += (Real) x;
01042         if ( c.size() >1 )
01043             c[1] += (Real) y;
01044         if ( c.size() >2 )
01045             c[2] += (Real) z;
01046     }
01047 
01048     static Coord interpolate(const helper::vector< Coord > & ancestors, const helper::vector< Real > & coefs)
01049     {
01050         assert(ancestors.size() == coefs.size());
01051             
01052         Coord c;
01053 
01054         for (unsigned int i = 0; i < ancestors.size(); i++)
01055         {
01056             // Position interpolation.
01057             c.getCenter() += ancestors[i].getCenter() * coefs[i];
01058 
01059             // Angle extraction from the orientation quaternion.
01060             helper::Quater<Real> q = ancestors[i].getOrientation();
01061             Real angle = acos(q[3]) * 2;
01062 
01063             // Axis extraction from the orientation quaternion.
01064             defaulttype::Vec<3,Real> v(q[0], q[1], q[2]);
01065             Real norm = v.norm();
01066             if (norm > 0.0005)
01067             {
01068                 v.normalize();
01069 
01070                 // The scale factor is applied to the angle
01071                 angle *= coefs[i];
01072 
01073                 // Corresponding quaternion is computed, then added to the interpolated point orientation.
01074                 q.axisToQuat(v, angle);
01075                 q.normalize();
01076 
01077                 c.getOrientation() += q;
01078             }           
01079         }
01080         
01081         c.getOrientation().normalize();
01082         
01083         return c;
01084     }
01085 
01086     static Deriv interpolate(const helper::vector< Deriv > & ancestors, const helper::vector< Real > & coefs)
01087     {
01088         assert(ancestors.size() == coefs.size());
01089             
01090         Deriv d;
01091         
01092         for (unsigned int i = 0; i < ancestors.size(); i++)
01093         {
01094             d += ancestors[i] * coefs[i];
01095         }
01096 
01097         return d;
01098     }
01099 
01100     static const char* Name();
01101 };
01102 
01103 typedef CudaRigidTypes<3,float> CudaRigid3fTypes;
01104 typedef CudaRigid3fTypes CudaRigid3Types;
01105 
01106 template<>
01107 inline const char* CudaRigid3fTypes::Name()
01108 {
01109     return "CudaRigid3f";
01110 }
01111 
01112 
01113 } // namespace cuda
01114 
01115 } // namespace gpu
01116 
01117 } // namespace sofa
01118 
01119 #endif

Generated on Sun Nov 23 04:04:17 2008 for Sofa by  doxygen 1.5.7.1