|
Bullet Collision Detection & Physics Library
|
00001 /* 00002 Bullet Continuous Collision Detection and Physics Library 00003 Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com 00004 00005 This software is provided 'as-is', without any express or implied warranty. 00006 In no event will the authors be held liable for any damages arising from the use of this software. 00007 Permission is granted to anyone to use this software for any purpose, 00008 including commercial applications, and to alter it and redistribute it freely, 00009 subject to the following restrictions: 00010 00011 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 00012 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 00013 3. This notice may not be removed or altered from any source distribution. 00014 */ 00015 00016 #ifdef USE_LIBSPE2 00017 00018 #include "SpuLibspe2Support.h" 00019 00020 00021 00022 00023 //SpuLibspe2Support helps to initialize/shutdown libspe2, start/stop SPU tasks and communication 00025 SpuLibspe2Support::SpuLibspe2Support(spe_program_handle_t *speprog, int numThreads) 00026 { 00027 this->program = speprog; 00028 this->numThreads = ((numThreads <= spe_cpu_info_get(SPE_COUNT_PHYSICAL_SPES, -1)) ? numThreads : spe_cpu_info_get(SPE_COUNT_PHYSICAL_SPES, -1)); 00029 } 00030 00032 SpuLibspe2Support::~SpuLibspe2Support() 00033 { 00034 00035 stopSPU(); 00036 } 00037 00038 00039 00041 void SpuLibspe2Support::sendRequest(uint32_t uiCommand, uint32_t uiArgument0, uint32_t uiArgument1) 00042 { 00043 spe_context_ptr_t context; 00044 00045 switch (uiCommand) 00046 { 00047 case CMD_SAMPLE_TASK_COMMAND: 00048 { 00049 //get taskdescription 00050 SpuSampleTaskDesc* taskDesc = (SpuSampleTaskDesc*) uiArgument0; 00051 00052 btAssert(taskDesc->m_taskId<m_activeSpuStatus.size()); 00053 00054 //get status of SPU on which task should run 00055 btSpuStatus& spuStatus = m_activeSpuStatus[taskDesc->m_taskId]; 00056 00057 //set data for spuStatus 00058 spuStatus.m_commandId = uiCommand; 00059 spuStatus.m_status = Spu_Status_Occupied; //set SPU as "occupied" 00060 spuStatus.m_taskDesc.p = taskDesc; 00061 00062 //get context 00063 context = data[taskDesc->m_taskId].context; 00064 00065 00066 taskDesc->m_mainMemoryPtr = reinterpret_cast<uint64_t> (spuStatus.m_lsMemory.p); 00067 00068 00069 break; 00070 } 00071 case CMD_GATHER_AND_PROCESS_PAIRLIST: 00072 { 00073 //get taskdescription 00074 SpuGatherAndProcessPairsTaskDesc* taskDesc = (SpuGatherAndProcessPairsTaskDesc*) uiArgument0; 00075 00076 btAssert(taskDesc->taskId<m_activeSpuStatus.size()); 00077 00078 //get status of SPU on which task should run 00079 btSpuStatus& spuStatus = m_activeSpuStatus[taskDesc->taskId]; 00080 00081 //set data for spuStatus 00082 spuStatus.m_commandId = uiCommand; 00083 spuStatus.m_status = Spu_Status_Occupied; //set SPU as "occupied" 00084 spuStatus.m_taskDesc.p = taskDesc; 00085 00086 //get context 00087 context = data[taskDesc->taskId].context; 00088 00089 00090 taskDesc->m_lsMemory = (CollisionTask_LocalStoreMemory*)spuStatus.m_lsMemory.p; 00091 00092 break; 00093 } 00094 default: 00095 { 00097 btAssert(0); 00098 } 00099 00100 }; 00101 00102 00103 //write taskdescription in mailbox 00104 unsigned int event = Spu_Mailbox_Event_Task; 00105 spe_in_mbox_write(context, &event, 1, SPE_MBOX_ANY_NONBLOCKING); 00106 00107 } 00108 00110 void SpuLibspe2Support::waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1) 00111 { 00113 00115 00116 btAssert(m_activeSpuStatus.size()); 00117 00118 00119 int last = -1; 00120 00121 //find an active spu/thread 00122 while(last < 0) 00123 { 00124 for (int i=0;i<m_activeSpuStatus.size();i++) 00125 { 00126 if ( m_activeSpuStatus[i].m_status == Spu_Status_Free) 00127 { 00128 last = i; 00129 break; 00130 } 00131 } 00132 if(last < 0) 00133 sched_yield(); 00134 } 00135 00136 00137 00138 btSpuStatus& spuStatus = m_activeSpuStatus[last]; 00139 00141 btAssert(last>=0); 00142 00143 00144 00145 *puiArgument0 = spuStatus.m_taskId; 00146 *puiArgument1 = spuStatus.m_status; 00147 00148 00149 } 00150 00151 00152 void SpuLibspe2Support::startSPU() 00153 { 00154 this->internal_startSPU(); 00155 } 00156 00157 00158 00160 void SpuLibspe2Support::internal_startSPU() 00161 { 00162 m_activeSpuStatus.resize(numThreads); 00163 00164 00165 for (int i=0; i < numThreads; i++) 00166 { 00167 00168 if(data[i].context == NULL) 00169 { 00170 00171 /* Create context */ 00172 if ((data[i].context = spe_context_create(0, NULL)) == NULL) 00173 { 00174 perror ("Failed creating context"); 00175 exit(1); 00176 } 00177 00178 /* Load program into context */ 00179 if(spe_program_load(data[i].context, this->program)) 00180 { 00181 perror ("Failed loading program"); 00182 exit(1); 00183 } 00184 00185 m_activeSpuStatus[i].m_status = Spu_Status_Startup; 00186 m_activeSpuStatus[i].m_taskId = i; 00187 m_activeSpuStatus[i].m_commandId = 0; 00188 m_activeSpuStatus[i].m_lsMemory.p = NULL; 00189 00190 00191 data[i].entry = SPE_DEFAULT_ENTRY; 00192 data[i].flags = 0; 00193 data[i].argp.p = &m_activeSpuStatus[i]; 00194 data[i].envp.p = NULL; 00195 00196 /* Create thread for each SPE context */ 00197 if (pthread_create(&data[i].pthread, NULL, &ppu_pthread_function, &(data[i]) )) 00198 { 00199 perror ("Failed creating thread"); 00200 exit(1); 00201 } 00202 /* 00203 else 00204 { 00205 printf("started thread %d\n",i); 00206 }*/ 00207 } 00208 } 00209 00210 00211 for (int i=0; i < numThreads; i++) 00212 { 00213 if(data[i].context != NULL) 00214 { 00215 while( m_activeSpuStatus[i].m_status == Spu_Status_Startup) 00216 { 00217 // wait for spu to set up 00218 sched_yield(); 00219 } 00220 printf("Spu %d is ready\n", i); 00221 } 00222 } 00223 } 00224 00226 void SpuLibspe2Support::stopSPU() 00227 { 00228 // wait for all threads to finish 00229 int i; 00230 for ( i = 0; i < this->numThreads; i++ ) 00231 { 00232 00233 unsigned int event = Spu_Mailbox_Event_Shutdown; 00234 spe_context_ptr_t context = data[i].context; 00235 spe_in_mbox_write(context, &event, 1, SPE_MBOX_ALL_BLOCKING); 00236 pthread_join (data[i].pthread, NULL); 00237 00238 } 00239 // close SPE program 00240 spe_image_close(program); 00241 // destroy SPE contexts 00242 for ( i = 0; i < this->numThreads; i++ ) 00243 { 00244 if(data[i].context != NULL) 00245 { 00246 spe_context_destroy (data[i].context); 00247 } 00248 } 00249 00250 m_activeSpuStatus.clear(); 00251 00252 } 00253 00254 00255 00256 #endif //USE_LIBSPE2 00257