examples/eqNBody/channel.cpp

00001 /*
00002  * Copyright (c) 2009, Philippe Robert <probert@eyescale.ch> 
00003  *
00004  * This library is free software; you can redistribute it and/or modify it under
00005  * the terms of the GNU Lesser General Public License version 2.1 as published
00006  * by the Free Software Foundation.
00007  *  
00008  * This library is distributed in the hope that it will be useful, but WITHOUT
00009  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00010  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
00011  * details.
00012  * 
00013  * You should have received a copy of the GNU Lesser General Public License
00014  * along with this library; if not, write to the Free Software Foundation, Inc.,
00015  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00016  */
00017 
00018 #include "channel.h"
00019 
00020 #include "client.h"
00021 #include "frameData.h"
00022 #include "initData.h"
00023 #include "config.h"
00024 #include "pipe.h"
00025 #include "window.h"
00026 
00027 using namespace eq::base;
00028 using namespace std;
00029 
00030 namespace eqNbody
00031 {
00032     void Channel::frameClear( const uint32_t frameID )
00033     {
00034         EQ_GL_CALL( applyBuffer( ));
00035         EQ_GL_CALL( applyViewport( ));
00036         
00037         glClearColor( 0.f, 0.f, 0.f, 1.0f );
00038         EQ_GL_CALL( glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ));
00039     }
00040     
00041     void Channel::frameDraw( const uint32_t frameID )
00042     {                       
00043         const Pipe* pipe = static_cast<const Pipe*>( getPipe( ));
00044         const FrameData& fd = pipe->getFrameData();
00045 
00046         // 1st, initialise the local proxy object
00047         static bool isInitialised1 = false;
00048         if(isInitialised1 == false) {
00049             _initLocalProxy();
00050             isInitialised1 = true;
00051             return;
00052         }
00053 
00054         // 2nd, initialise the CUDA part
00055         static bool isInitialised2 = false;
00056         if(isInitialised2 == false) {
00057             _initCUDAController();
00058             isInitialised2 = true;
00059         }
00060         
00061         _compute(frameID, fd);
00062         _draw(frameID, fd);
00063         _update();
00064     }   
00065 
00066     void Channel::_compute(const uint32_t frameID, const FrameData& fd)
00067     {
00068         const eq::Range& range = getRange();
00069 
00070         // Sync all remote data, if needed. 
00071         // In this example there will always be new data to be synchronized.
00072         _syncDataProxies(fd);
00073         
00074         // Upload the current data from the host to the GPU
00075         _controller.setArray(BODYSYSTEM_POSITION, fd);
00076         _controller.setArray(BODYSYSTEM_VELOCITY, fd);
00077         
00078         // Compute the next step in the simulation
00079         _controller.compute(frameID, fd, range);                
00080     }
00081 
00082     void Channel::_draw(const uint32_t frameID, const FrameData& fd)
00083     {
00084         // Setup OpenGL state and draw
00085         eq::Channel::frameDraw( frameID );
00086         
00087         glMatrixMode(GL_MODELVIEW);
00088         glLoadIdentity();
00089         
00090         glTranslatef( 0.0f, 0.0f, -50.0f );
00091         
00092         _controller.draw(fd);
00093         
00094 #ifndef NDEBUG
00095         outlineViewport();
00096 #endif
00097     }
00098 
00099     void Channel::_update()
00100     {
00101         const eq::Range& range = getRange();
00102 
00103         // Transfer the modified data from the device to the host.
00104         // In this example there will always be new data!
00105         _controller.getArray(BODYSYSTEM_POSITION, _dataProxy[0]);
00106         _controller.getArray(BODYSYSTEM_VELOCITY, _dataProxy[0]);           
00107         
00108         // Commit the local changes
00109         uint32_t version = _dataProxy[0].commit();
00110 
00111         // Tell the others what version to sync
00112         _sendEvent(ConfigEvent::PROXY_CHANGED, version, _dataProxy[0].getID(), range);
00113     }
00114     
00115     void Channel::_initLocalProxy()
00116     {       
00117         Config* config      = static_cast<Config*>(getConfig());
00118         const Pipe* pipe    = static_cast<Pipe*>( getPipe( ));
00119         const FrameData& fd = pipe->getFrameData();
00120         
00121         const eq::Range& range = getRange();
00122         
00123         // Initialise the local proxy
00124         unsigned int offset = range.start * fd.getNumBodies() * 4;
00125         unsigned int numBytes = (range.end - range.start) * fd.getNumBytes(); 
00126         
00127         // Register the proxy object
00128         config->registerObject( &_dataProxy[0] );
00129 
00130         // Init the local data proxy
00131         _dataProxy[0].init(offset, numBytes, fd.getPos(), fd.getVel(), fd.getCol());        
00132         uint32_t version = _dataProxy[0].commit(); 
00133         
00134         // Let the app know which range is covered by this proxy
00135         _sendEvent(ConfigEvent::DATA_CHANGED, version, _dataProxy[0].getID(), range);
00136     }
00137     
00138     void Channel::_initCUDAController()
00139     {
00140         Config* config      = static_cast<Config*>(getConfig());
00141         const Pipe* pipe    = static_cast<Pipe*>( getPipe( ));
00142         const FrameData& fd = pipe->getFrameData();
00143         
00144         Window *w = static_cast<eqNbody::Window*>(getWindow());         
00145         const InitData& initData = config->getInitData();       
00146         
00147         unsigned int devID = w->getDeviceID();
00148         unsigned int mode = w->getMode();
00149         
00150         bool sysready   = false;
00151         bool usePBO     = (mode == WINDOW_CUDA_GL) ? true : false;
00152         bool useGL      = (mode == WINDOW_CUDA_GL) ? true : false;
00153                 
00154         switch(mode) {
00155             case WINDOW_CUDA_GL:
00156                 EQINFO << "*** Channel::_initCUDAController WINDOW_CUDA_GL usePBO= " << usePBO << ", useGL= " << useGL << std::endl;
00157                 sysready = _controller.init(devID, initData, fd.getPos(), usePBO, useGL);
00158                 EQASSERT( sysready );
00159                 break;
00160             case WINDOW_CUDA:
00161                 EQINFO << "*** Channel::_initCUDAController WINDOW_CUDA usePBO= " << usePBO << ", useGL= " << useGL << std::endl;
00162                 sysready = _controller.init(devID, initData, fd.getPos(), usePBO, useGL);
00163                 EQASSERT( sysready );
00164                 break;
00165             case WINDOW_GL:
00166                 EQINFO << "GL window - no CUDA controller initialisation!" << std::endl;
00167                 sysready = true;
00168                 break;
00169             default:
00170                 EQWARN << "Unknown mode - no CUDA controller initialisation!" << std::endl;
00171                 break;
00172         }
00173         
00174         _initDataProxies(fd);
00175     }
00176             
00177     void Channel::_initDataProxies(const FrameData& frameData)
00178     {
00179         Config* config      = static_cast<Config*>(getConfig());
00180         
00181         for(unsigned int i=0, j=1; i< frameData.getNumDataProxies(); i++) {
00182             unsigned int id = frameData.getProxyID(i);
00183             
00184             if( (id != _dataProxy[0].getID())) {
00185                 _dataProxy[j].init(frameData.getPos(), frameData.getVel(), frameData.getCol());
00186                 
00187                 const bool mapped = config->mapObject( &_dataProxy[j++], id );
00188                 EQASSERT( mapped );
00189             }
00190         }           
00191     }
00192     
00193     void Channel::_syncDataProxies(const FrameData& frameData)
00194     {
00195         for(unsigned int i=1; i< frameData.getNumDataProxies(); i++) {          
00196             unsigned int pid = _dataProxy[i].getID();
00197             unsigned int version = frameData.getVersionForProxyID(pid);
00198                         
00199             EQINFO << "SYNC ID= " << pid << std::endl;
00200             
00201             // ...and sync!
00202             _dataProxy[i].sync(version);
00203         }
00204     }
00205     
00206     void Channel::_sendEvent(ConfigEvent::Type type, unsigned int version, unsigned int pid, const eq::Range& range)
00207     {
00208         Config* config      = static_cast<Config*>(getConfig());
00209         const string& name  = getName();
00210         
00211         ConfigEvent event;
00212         
00213         if( name.empty( )) {    
00214             snprintf( event.data.user.data, 32, "%p", this );
00215         }
00216         else {
00217             snprintf( event.data.user.data, 32, "%s", name.c_str( ));
00218         }
00219         
00220         event.data.user.data[31] = '\0';
00221         
00222         event.data.type = type;
00223         event._version = version;
00224         event._range[0] = range.start;
00225         event._range[1] = range.end;
00226         event._proxyID = pid;
00227         
00228         config->sendEvent( event );
00229     }
00230 }
Generated on Mon Aug 10 18:58:31 2009 for Equalizer 0.9 by  doxygen 1.5.8