|
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 00017 //#define DEBUG_SPU_TASK_SCHEDULING 1 00018 00019 00020 //class OptimizedBvhNode; 00021 00022 #include "SpuCollisionTaskProcess.h" 00023 00024 00025 00026 00027 void SpuCollisionTaskProcess::setNumTasks(int maxNumTasks) 00028 { 00029 if (int(m_maxNumOutstandingTasks) != maxNumTasks) 00030 { 00031 m_maxNumOutstandingTasks = maxNumTasks; 00032 m_taskBusy.resize(m_maxNumOutstandingTasks); 00033 m_spuGatherTaskDesc.resize(m_maxNumOutstandingTasks); 00034 00035 for (int i = 0; i < m_taskBusy.size(); i++) 00036 { 00037 m_taskBusy[i] = false; 00038 } 00039 00041 if (m_workUnitTaskBuffers != 0) 00042 { 00043 btAlignedFree(m_workUnitTaskBuffers); 00044 } 00045 00046 m_workUnitTaskBuffers = (unsigned char *)btAlignedAlloc(MIDPHASE_WORKUNIT_TASK_SIZE*m_maxNumOutstandingTasks, 128); 00047 } 00048 00049 } 00050 00051 00052 00053 SpuCollisionTaskProcess::SpuCollisionTaskProcess(class btThreadSupportInterface* threadInterface, unsigned int maxNumOutstandingTasks) 00054 :m_threadInterface(threadInterface), 00055 m_maxNumOutstandingTasks(0) 00056 { 00057 m_workUnitTaskBuffers = (unsigned char *)0; 00058 setNumTasks(maxNumOutstandingTasks); 00059 m_numBusyTasks = 0; 00060 m_currentTask = 0; 00061 m_currentPage = 0; 00062 m_currentPageEntry = 0; 00063 00064 #ifdef DEBUG_SpuCollisionTaskProcess 00065 m_initialized = false; 00066 #endif 00067 00068 m_threadInterface->startSPU(); 00069 00070 //printf("sizeof vec_float4: %d\n", sizeof(vec_float4)); 00071 printf("sizeof SpuGatherAndProcessWorkUnitInput: %d\n", int(sizeof(SpuGatherAndProcessWorkUnitInput))); 00072 00073 } 00074 00075 SpuCollisionTaskProcess::~SpuCollisionTaskProcess() 00076 { 00077 00078 if (m_workUnitTaskBuffers != 0) 00079 { 00080 btAlignedFree(m_workUnitTaskBuffers); 00081 m_workUnitTaskBuffers = 0; 00082 } 00083 00084 00085 00086 m_threadInterface->stopSPU(); 00087 00088 } 00089 00090 00091 00092 void SpuCollisionTaskProcess::initialize2(bool useEpa) 00093 { 00094 00095 #ifdef DEBUG_SPU_TASK_SCHEDULING 00096 printf("SpuCollisionTaskProcess::initialize()\n"); 00097 #endif //DEBUG_SPU_TASK_SCHEDULING 00098 00099 for (int i = 0; i < int (m_maxNumOutstandingTasks); i++) 00100 { 00101 m_taskBusy[i] = false; 00102 } 00103 m_numBusyTasks = 0; 00104 m_currentTask = 0; 00105 m_currentPage = 0; 00106 m_currentPageEntry = 0; 00107 m_useEpa = useEpa; 00108 00109 #ifdef DEBUG_SpuCollisionTaskProcess 00110 m_initialized = true; 00111 btAssert(MIDPHASE_NUM_WORKUNITS_PER_TASK*sizeof(SpuGatherAndProcessWorkUnitInput) <= MIDPHASE_WORKUNIT_TASK_SIZE); 00112 #endif 00113 } 00114 00115 00116 void SpuCollisionTaskProcess::issueTask2() 00117 { 00118 00119 #ifdef DEBUG_SPU_TASK_SCHEDULING 00120 printf("SpuCollisionTaskProcess::issueTask (m_currentTask= %d\n)", m_currentTask); 00121 #endif //DEBUG_SPU_TASK_SCHEDULING 00122 00123 m_taskBusy[m_currentTask] = true; 00124 m_numBusyTasks++; 00125 00126 00127 SpuGatherAndProcessPairsTaskDesc& taskDesc = m_spuGatherTaskDesc[m_currentTask]; 00128 taskDesc.m_useEpa = m_useEpa; 00129 00130 { 00131 // send task description in event message 00132 // no error checking here... 00133 // but, currently, event queue can be no larger than NUM_WORKUNIT_TASKS. 00134 00135 taskDesc.m_inPairPtr = reinterpret_cast<uint64_t>(MIDPHASE_TASK_PTR(m_currentTask)); 00136 00137 taskDesc.taskId = m_currentTask; 00138 taskDesc.numPages = m_currentPage+1; 00139 taskDesc.numOnLastPage = m_currentPageEntry; 00140 } 00141 00142 00143 00144 m_threadInterface->sendRequest(CMD_GATHER_AND_PROCESS_PAIRLIST, (ppu_address_t) &taskDesc,m_currentTask); 00145 00146 // if all tasks busy, wait for spu event to clear the task. 00147 00148 00149 if (m_numBusyTasks >= m_maxNumOutstandingTasks) 00150 { 00151 unsigned int taskId; 00152 unsigned int outputSize; 00153 00154 00155 for (int i=0;i<int (m_maxNumOutstandingTasks);i++) 00156 { 00157 if (m_taskBusy[i]) 00158 { 00159 taskId = i; 00160 break; 00161 } 00162 } 00163 00164 btAssert(taskId>=0); 00165 00166 00167 m_threadInterface->waitForResponse(&taskId, &outputSize); 00168 00169 // printf("issueTask taskId %d completed, numBusy=%d\n",taskId,m_numBusyTasks); 00170 00171 //printf("PPU: after issue, received event: %u %d\n", taskId, outputSize); 00172 00173 //postProcess(taskId, outputSize); 00174 00175 m_taskBusy[taskId] = false; 00176 00177 m_numBusyTasks--; 00178 } 00179 00180 } 00181 00182 void SpuCollisionTaskProcess::addWorkToTask(void* pairArrayPtr,int startIndex,int endIndex) 00183 { 00184 #ifdef DEBUG_SPU_TASK_SCHEDULING 00185 printf("#"); 00186 #endif //DEBUG_SPU_TASK_SCHEDULING 00187 00188 #ifdef DEBUG_SpuCollisionTaskProcess 00189 btAssert(m_initialized); 00190 btAssert(m_workUnitTaskBuffers); 00191 00192 #endif 00193 00194 bool batch = true; 00195 00196 if (batch) 00197 { 00198 if (m_currentPageEntry == MIDPHASE_NUM_WORKUNITS_PER_PAGE) 00199 { 00200 if (m_currentPage == MIDPHASE_NUM_WORKUNIT_PAGES-1) 00201 { 00202 // task buffer is full, issue current task. 00203 // if all task buffers busy, this waits until SPU is done. 00204 issueTask2(); 00205 00206 // find new task buffer 00207 for (unsigned int i = 0; i < m_maxNumOutstandingTasks; i++) 00208 { 00209 if (!m_taskBusy[i]) 00210 { 00211 m_currentTask = i; 00212 //init the task data 00213 00214 break; 00215 } 00216 } 00217 00218 m_currentPage = 0; 00219 } 00220 else 00221 { 00222 m_currentPage++; 00223 } 00224 00225 m_currentPageEntry = 0; 00226 } 00227 } 00228 00229 { 00230 00231 00232 00233 SpuGatherAndProcessWorkUnitInput &wuInput = 00234 *(reinterpret_cast<SpuGatherAndProcessWorkUnitInput*> 00235 (MIDPHASE_ENTRY_PTR(m_currentTask, m_currentPage, m_currentPageEntry))); 00236 00237 wuInput.m_pairArrayPtr = reinterpret_cast<uint64_t>(pairArrayPtr); 00238 wuInput.m_startIndex = startIndex; 00239 wuInput.m_endIndex = endIndex; 00240 00241 00242 00243 m_currentPageEntry++; 00244 00245 if (!batch) 00246 { 00247 issueTask2(); 00248 00249 // find new task buffer 00250 for (unsigned int i = 0; i < m_maxNumOutstandingTasks; i++) 00251 { 00252 if (!m_taskBusy[i]) 00253 { 00254 m_currentTask = i; 00255 //init the task data 00256 00257 break; 00258 } 00259 } 00260 00261 m_currentPage = 0; 00262 m_currentPageEntry =0; 00263 } 00264 } 00265 } 00266 00267 00268 void 00269 SpuCollisionTaskProcess::flush2() 00270 { 00271 #ifdef DEBUG_SPU_TASK_SCHEDULING 00272 printf("\nSpuCollisionTaskProcess::flush()\n"); 00273 #endif //DEBUG_SPU_TASK_SCHEDULING 00274 00275 // if there's a partially filled task buffer, submit that task 00276 if (m_currentPage > 0 || m_currentPageEntry > 0) 00277 { 00278 issueTask2(); 00279 } 00280 00281 00282 // all tasks are issued, wait for all tasks to be complete 00283 while(m_numBusyTasks > 0) 00284 { 00285 // Consolidating SPU code 00286 unsigned int taskId=-1; 00287 unsigned int outputSize; 00288 00289 for (int i=0;i<int (m_maxNumOutstandingTasks);i++) 00290 { 00291 if (m_taskBusy[i]) 00292 { 00293 taskId = i; 00294 break; 00295 } 00296 } 00297 00298 btAssert(taskId>=0); 00299 00300 00301 { 00302 00303 // SPURS support. 00304 m_threadInterface->waitForResponse(&taskId, &outputSize); 00305 } 00306 // printf("flush2 taskId %d completed, numBusy =%d \n",taskId,m_numBusyTasks); 00307 //printf("PPU: flushing, received event: %u %d\n", taskId, outputSize); 00308 00309 //postProcess(taskId, outputSize); 00310 00311 m_taskBusy[taskId] = false; 00312 00313 m_numBusyTasks--; 00314 } 00315 00316 00317 }