2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the use of this software.
7 Permission is granted to anyone to use this software for any purpose,
8 including commercial applications, and to alter it and redistribute it freely,
9 subject to the following restrictions:
11 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.
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 3. This notice may not be removed or altered from any source distribution.
17 //#define DEBUG_SPU_TASK_SCHEDULING 1
20 //class OptimizedBvhNode;
22 #include "SpuCollisionTaskProcess.h"
27 void SpuCollisionTaskProcess::setNumTasks(int maxNumTasks)
29 if (int(m_maxNumOutstandingTasks) != maxNumTasks)
31 m_maxNumOutstandingTasks = maxNumTasks;
32 m_taskBusy.resize(m_maxNumOutstandingTasks);
33 m_spuGatherTaskDesc.resize(m_maxNumOutstandingTasks);
35 for (int i = 0; i < m_taskBusy.size(); i++)
37 m_taskBusy[i] = false;
40 ///re-allocate task memory buffers
41 if (m_workUnitTaskBuffers != 0)
43 btAlignedFree(m_workUnitTaskBuffers);
46 m_workUnitTaskBuffers = (unsigned char *)btAlignedAlloc(MIDPHASE_WORKUNIT_TASK_SIZE*m_maxNumOutstandingTasks, 128);
53 SpuCollisionTaskProcess::SpuCollisionTaskProcess(class btThreadSupportInterface* threadInterface, unsigned int maxNumOutstandingTasks)
54 :m_threadInterface(threadInterface),
55 m_maxNumOutstandingTasks(0)
57 m_workUnitTaskBuffers = (unsigned char *)0;
58 setNumTasks(maxNumOutstandingTasks);
62 m_currentPageEntry = 0;
64 #ifdef DEBUG_SpuCollisionTaskProcess
65 m_initialized = false;
68 m_threadInterface->startSPU();
70 //printf("sizeof vec_float4: %d\n", sizeof(vec_float4));
71 printf("sizeof SpuGatherAndProcessWorkUnitInput: %d\n", int(sizeof(SpuGatherAndProcessWorkUnitInput)));
75 SpuCollisionTaskProcess::~SpuCollisionTaskProcess()
78 if (m_workUnitTaskBuffers != 0)
80 btAlignedFree(m_workUnitTaskBuffers);
81 m_workUnitTaskBuffers = 0;
86 m_threadInterface->stopSPU();
92 void SpuCollisionTaskProcess::initialize2(bool useEpa)
95 #ifdef DEBUG_SPU_TASK_SCHEDULING
96 printf("SpuCollisionTaskProcess::initialize()\n");
97 #endif //DEBUG_SPU_TASK_SCHEDULING
99 for (int i = 0; i < int (m_maxNumOutstandingTasks); i++)
101 m_taskBusy[i] = false;
106 m_currentPageEntry = 0;
109 #ifdef DEBUG_SpuCollisionTaskProcess
110 m_initialized = true;
111 btAssert(MIDPHASE_NUM_WORKUNITS_PER_TASK*sizeof(SpuGatherAndProcessWorkUnitInput) <= MIDPHASE_WORKUNIT_TASK_SIZE);
116 void SpuCollisionTaskProcess::issueTask2()
119 #ifdef DEBUG_SPU_TASK_SCHEDULING
120 printf("SpuCollisionTaskProcess::issueTask (m_currentTask= %d\n)", m_currentTask);
121 #endif //DEBUG_SPU_TASK_SCHEDULING
123 m_taskBusy[m_currentTask] = true;
127 SpuGatherAndProcessPairsTaskDesc& taskDesc = m_spuGatherTaskDesc[m_currentTask];
128 taskDesc.m_useEpa = m_useEpa;
131 // send task description in event message
132 // no error checking here...
133 // but, currently, event queue can be no larger than NUM_WORKUNIT_TASKS.
135 taskDesc.m_inPairPtr = reinterpret_cast<uint64_t>(MIDPHASE_TASK_PTR(m_currentTask));
137 taskDesc.taskId = m_currentTask;
138 taskDesc.numPages = m_currentPage+1;
139 taskDesc.numOnLastPage = m_currentPageEntry;
144 m_threadInterface->sendRequest(CMD_GATHER_AND_PROCESS_PAIRLIST, (ppu_address_t) &taskDesc,m_currentTask);
146 // if all tasks busy, wait for spu event to clear the task.
149 if (m_numBusyTasks >= m_maxNumOutstandingTasks)
152 unsigned int outputSize;
155 for (int i=0;i<int (m_maxNumOutstandingTasks);i++)
167 m_threadInterface->waitForResponse(&taskId, &outputSize);
169 // printf("issueTask taskId %d completed, numBusy=%d\n",taskId,m_numBusyTasks);
171 //printf("PPU: after issue, received event: %u %d\n", taskId, outputSize);
173 //postProcess(taskId, outputSize);
175 m_taskBusy[taskId] = false;
182 void SpuCollisionTaskProcess::addWorkToTask(void* pairArrayPtr,int startIndex,int endIndex)
184 #ifdef DEBUG_SPU_TASK_SCHEDULING
186 #endif //DEBUG_SPU_TASK_SCHEDULING
188 #ifdef DEBUG_SpuCollisionTaskProcess
189 btAssert(m_initialized);
190 btAssert(m_workUnitTaskBuffers);
198 if (m_currentPageEntry == MIDPHASE_NUM_WORKUNITS_PER_PAGE)
200 if (m_currentPage == MIDPHASE_NUM_WORKUNIT_PAGES-1)
202 // task buffer is full, issue current task.
203 // if all task buffers busy, this waits until SPU is done.
206 // find new task buffer
207 for (unsigned int i = 0; i < m_maxNumOutstandingTasks; i++)
225 m_currentPageEntry = 0;
233 SpuGatherAndProcessWorkUnitInput &wuInput =
234 *(reinterpret_cast<SpuGatherAndProcessWorkUnitInput*>
235 (MIDPHASE_ENTRY_PTR(m_currentTask, m_currentPage, m_currentPageEntry)));
237 wuInput.m_pairArrayPtr = reinterpret_cast<uint64_t>(pairArrayPtr);
238 wuInput.m_startIndex = startIndex;
239 wuInput.m_endIndex = endIndex;
243 m_currentPageEntry++;
249 // find new task buffer
250 for (unsigned int i = 0; i < m_maxNumOutstandingTasks; i++)
262 m_currentPageEntry =0;
269 SpuCollisionTaskProcess::flush2()
271 #ifdef DEBUG_SPU_TASK_SCHEDULING
272 printf("\nSpuCollisionTaskProcess::flush()\n");
273 #endif //DEBUG_SPU_TASK_SCHEDULING
275 // if there's a partially filled task buffer, submit that task
276 if (m_currentPage > 0 || m_currentPageEntry > 0)
282 // all tasks are issued, wait for all tasks to be complete
283 while(m_numBusyTasks > 0)
285 // Consolidating SPU code
286 unsigned int taskId=-1;
287 unsigned int outputSize;
289 for (int i=0;i<int (m_maxNumOutstandingTasks);i++)
304 m_threadInterface->waitForResponse(&taskId, &outputSize);
306 // printf("flush2 taskId %d completed, numBusy =%d \n",taskId,m_numBusyTasks);
307 //printf("PPU: flushing, received event: %u %d\n", taskId, outputSize);
309 //postProcess(taskId, outputSize);
311 m_taskBusy[taskId] = false;