Equalizer  1.2.1
controller.cpp
00001 
00002 /*
00003  * Copyright (c) 2009, Philippe Robert <philippe.robert@gmail.com> 
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  * - Redistributions of source code must retain the above copyright notice, this
00009  *   list of conditions and the following disclaimer.
00010  * - Redistributions in binary form must reproduce the above copyright notice,
00011  *   this list of conditions and the following disclaimer in the documentation
00012  *   and/or other materials provided with the distribution.
00013  * - Neither the name of Eyescale Software GmbH nor the names of its
00014  *   contributors may be used to endorse or promote products derived from this
00015  *   software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027  * POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 
00030 #include "controller.h"
00031 #include "initData.h"
00032 #include "nbody.h"
00033 
00034 #include <eq/client/gl.h>
00035 
00036 #include <cuda.h>
00037 #include <cuda_gl_interop.h>
00038 
00039 namespace eqNbody
00040 {
00041 Controller::Controller( const GLEWContext* const glewContext ) 
00042     : _renderer( glewContext )
00043     , _glewContext( glewContext )
00044     , _numBodies( 0 )
00045     , _p( 0 )
00046     , _q( 0 )
00047     , _usePBO( true )
00048 {
00049    _dPos[0] = _dPos[1] = 0;
00050    _dVel[0] = _dVel[1] = 0;
00051     _currentRead = 0;
00052     _currentWrite = 1;
00053 }
00054 
00055 bool Controller::init( const InitData& initData, float* hPos, bool usePBO )
00056 {        
00057     _numBodies = initData.getNumBodies();
00058     _p         = initData.getP();
00059     _q         = initData.getQ();
00060     _damping   = initData.getDamping();
00061     _usePBO    = usePBO;
00062     _pointSize = 1.0f;
00063 
00064     // Setup p and q properly
00065     if( _q * _p > 256 )
00066         _p = 256 / _q;
00067 
00068     if ( _q == 1 && _numBodies < _p )
00069         _p = _numBodies;
00070 
00071     if( usePBO )
00072     {
00073         // create the position pixel buffer objects for rendering
00074         // we will actually compute directly from this memory in CUDA too
00075         glGenBuffers(2, (GLuint*)_pbo);   
00076         for (int i = 0; i < 2; ++i)
00077         {
00078             glBindBuffer( GL_ARRAY_BUFFER, _pbo[i] );
00079             glBufferData( GL_ARRAY_BUFFER, 4 * sizeof(float) * _numBodies, 
00080                           hPos, GL_DYNAMIC_DRAW);
00081             
00082             int size = 0;
00083             glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, (GLint*)&size); 
00084             if ((unsigned)size != 4 * (sizeof(float) * _numBodies)) {
00085                 EQERROR << "WARNING: Pixel Buffer Object allocation failed" 
00086                         << std::endl;
00087             }
00088 
00089             glBindBuffer(GL_ARRAY_BUFFER, 0);
00090             registerGLBufferObject(_pbo[i]);
00091         }
00092     }
00093     else
00094     {
00095         allocateNBodyArrays(_dPos, _numBodies * sizeof( float) * 4);
00096     }
00097     
00098     allocateNBodyArrays(_dVel, _numBodies * sizeof( float) * 4);
00099     setSoftening(0.00125f);
00100     _renderer.init();
00101 
00102     return true;
00103 }
00104 bool Controller::exit()
00105 {
00106     deleteNBodyArrays(_dVel);
00107     
00108     if (_usePBO)
00109     {
00110         unregisterGLBufferObject(_pbo[0]);
00111         unregisterGLBufferObject(_pbo[1]);
00112         glDeleteBuffers(2, (const GLuint*)_pbo);
00113     }
00114     else
00115     {
00116         deleteNBodyArrays(_dPos);
00117     }
00118     
00119     return true;
00120 }
00121                     
00122 void Controller::compute(const float timeStep, const eq::Range& range)
00123 {
00124     int offset    = range.start * _numBodies;
00125     int length    = ((range.end - range.start) * _numBodies) / _p;
00126         
00127     integrateNbodySystem(_dPos[_currentWrite], _dVel[_currentWrite], 
00128                          _dPos[_currentRead], _dVel[_currentRead],
00129                          _pbo[_currentWrite], _pbo[_currentRead],
00130                          timeStep, _damping, _numBodies, offset, length,
00131                          _p, _q, (_usePBO ? 1 : 0));
00132 }
00133 
00134 void Controller::draw(float* pos, float* col)
00135 {
00136     glMatrixMode(GL_MODELVIEW);
00137     glLoadIdentity();
00138     glTranslatef( 0.0f, 0.0f, -50.0f );
00139     
00140     if(_usePBO) {
00141         _renderer.setPBO(_pbo[_currentRead], _numBodies);
00142     }
00143     else {
00144         _renderer.setPositions(pos, _numBodies);
00145         _renderer.setPBO(0, _numBodies);
00146     }
00147     
00148     _renderer.setColors(col, _numBodies); // do this only on init
00149     _renderer.setSpriteSize(_pointSize);
00150     _renderer.draw(PARTICLE_SPRITES_COLOR);
00151 
00152     std::swap(_currentRead, _currentWrite);
00153 }
00154 
00155 void Controller::setSoftening(float softening)
00156 {
00157     setDeviceSoftening(softening);
00158 }
00159     
00160 void Controller::getArray(BodyArray array, SharedDataProxy& proxy)
00161 {
00162     float* ddata = 0;
00163     float* hdata = 0;
00164     unsigned int pbo = 0;
00165     
00166     const unsigned int offset = proxy.getOffset();
00167 
00168     switch (array)
00169     {
00170         default:
00171         case BODYSYSTEM_POSITION:
00172             hdata = proxy.getPosition();
00173             ddata = _dPos[ _currentRead ];
00174             if (_usePBO) {
00175                 pbo = _pbo[ _currentRead ];
00176             }
00177             break;
00178 
00179         case BODYSYSTEM_VELOCITY:
00180             hdata = proxy.getVelocity();
00181             ddata = _dVel[ _currentRead ];
00182             break;
00183     }
00184 
00185     copyArrayFromDevice( hdata + offset, ddata + offset, pbo, 
00186                          proxy.getNumBytes());
00187     proxy.markDirty();
00188 }
00189 
00190 void Controller::setArray( BodyArray array, const float* pos, 
00191                            unsigned int numBytes )
00192 {        
00193     switch (array)
00194     {
00195         default:
00196         case BODYSYSTEM_POSITION:
00197         {
00198             if ( !_usePBO )
00199             {
00200                 copyArrayToDevice( _dPos[ _currentRead ], pos, numBytes );
00201                 return;
00202             }
00203 
00204             unregisterGLBufferObject( _pbo[ _currentRead ] );
00205             glBindBuffer(GL_ARRAY_BUFFER, _pbo[_currentRead]);
00206             glBufferData(GL_ARRAY_BUFFER, numBytes, pos, GL_DYNAMIC_DRAW);
00207             
00208             int size = 0;
00209             glGetBufferParameteriv( GL_ARRAY_BUFFER, GL_BUFFER_SIZE, 
00210                                     ( GLint* )&size ); 
00211             if ((unsigned)size != numBytes) 
00212             {
00213                 EQERROR << " WARNING : Pixel Buffer Object download failed."  
00214                         <<  " Size " << size << " does not match numBytes " 
00215                         << numBytes << std::endl;
00216             }
00217             glBindBuffer(GL_ARRAY_BUFFER, 0);
00218             registerGLBufferObject( _pbo[ _currentRead ] );
00219             break;
00220         }
00221         
00222         case BODYSYSTEM_VELOCITY:
00223             copyArrayToDevice( _dVel[ _currentRead ], pos, numBytes );
00224             break;
00225     }       
00226 }
00227 
00228 }
Generated on Fri Jun 8 2012 15:44:30 for Equalizer 1.2.1 by  doxygen 1.8.0