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         _assemble(frameID, fd);
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::_assemble(const uint32_t frameID, const FrameData& fd)
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 mode = w->getMode();
00148         bool usePBO = (mode == WINDOW_CUDA_GL) ? true : false;
00149                         
00150         switch(mode) {
00151             case WINDOW_CUDA_GL:
00152             case WINDOW_CUDA:
00153             {
00154                 bool sysready = _controller.init(initData, fd.getPos(), usePBO);
00155                 EQASSERT( sysready );
00156                 break;
00157             }
00158             case WINDOW_GL:
00159                 EQINFO << "GL window - no CUDA controller initialisation!" << std::endl;
00160                 break;
00161             default:
00162                 EQWARN << "Unknown mode - no CUDA controller initialisation!" << std::endl;
00163                 break;
00164         }
00165         
00166         _initDataProxies(fd);
00167     }
00168             
00169     void Channel::_initDataProxies(const FrameData& frameData)
00170     {
00171         Config* config      = static_cast<Config*>(getConfig());
00172         
00173         for(unsigned int i=0, j=1; i< frameData.getNumDataProxies(); i++) {
00174             unsigned int id = frameData.getProxyID(i);
00175             
00176             if( (id != _dataProxy[0].getID())) {
00177                 _dataProxy[j].init(frameData.getPos(), frameData.getVel(), frameData.getCol());
00178                 
00179                 const bool mapped = config->mapObject( &_dataProxy[j++], id );
00180                 EQASSERT( mapped );
00181             }
00182         }           
00183     }
00184     
00185     void Channel::_syncDataProxies(const FrameData& frameData)
00186     {
00187         for(unsigned int i=1; i< frameData.getNumDataProxies(); i++) {          
00188             unsigned int pid = _dataProxy[i].getID();
00189             unsigned int version = frameData.getVersionForProxyID(pid);
00190 
00191             // ...and sync!
00192             _dataProxy[i].sync(version);
00193         }
00194     }
00195     
00196     void Channel::_sendEvent(ConfigEvent::Type type, unsigned int version, unsigned int pid, const eq::Range& range)
00197     {
00198         Config* config      = static_cast<Config*>(getConfig());
00199         const string& name  = getName();
00200         
00201         ConfigEvent event;
00202         
00203         if( name.empty( )) {    
00204             snprintf( event.data.user.data, 32, "%p", this );
00205         }
00206         else {
00207             snprintf( event.data.user.data, 32, "%s", name.c_str( ));
00208         }
00209         
00210         event.data.user.data[31] = '\0';
00211         
00212         event.data.type = type;
00213         event._version = version;
00214         event._range[0] = range.start;
00215         event._range[1] = range.end;
00216         event._proxyID = pid;
00217         
00218         config->sendEvent( event );
00219     }
00220 }
Generated on Sat Feb 6 12:59:43 2010 for Equalizer 0.9.1 by  doxygen 1.6.1