Equalizer 1.0
|
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 <GL/glew.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 }