Bullet Collision Detection & Physics Library
SpuCollisionTaskProcess.cpp
Go to the documentation of this file.
1 /*
2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com
4 
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:
10 
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.
14 */
15 
16 
17 //#define DEBUG_SPU_TASK_SCHEDULING 1
18 
19 
20 //class OptimizedBvhNode;
21 
23 
24 
25 
26 
28 {
29  if (int(m_maxNumOutstandingTasks) != maxNumTasks)
30  {
31  m_maxNumOutstandingTasks = maxNumTasks;
34 
35  for (int i = 0; i < m_taskBusy.size(); i++)
36  {
37  m_taskBusy[i] = false;
38  }
39 
41  if (m_workUnitTaskBuffers != 0)
42  {
44  }
45 
47  }
48 
49 }
50 
51 
52 
53 SpuCollisionTaskProcess::SpuCollisionTaskProcess(class btThreadSupportInterface* threadInterface, unsigned int maxNumOutstandingTasks)
54 :m_threadInterface(threadInterface),
55 m_maxNumOutstandingTasks(0)
56 {
57  m_workUnitTaskBuffers = (unsigned char *)0;
58  setNumTasks(maxNumOutstandingTasks);
59  m_numBusyTasks = 0;
60  m_currentTask = 0;
61  m_currentPage = 0;
63 
64 #ifdef DEBUG_SpuCollisionTaskProcess
65  m_initialized = false;
66 #endif
67 
69 
70  //printf("sizeof vec_float4: %d\n", sizeof(vec_float4));
71  printf("sizeof SpuGatherAndProcessWorkUnitInput: %d\n", int(sizeof(SpuGatherAndProcessWorkUnitInput)));
72 
73 }
74 
76 {
77 
78  if (m_workUnitTaskBuffers != 0)
79  {
82  }
83 
84 
85 
87 
88 }
89 
90 
91 
93 {
94 
95 #ifdef DEBUG_SPU_TASK_SCHEDULING
96  printf("SpuCollisionTaskProcess::initialize()\n");
97 #endif //DEBUG_SPU_TASK_SCHEDULING
98 
99  for (int i = 0; i < int (m_maxNumOutstandingTasks); i++)
100  {
101  m_taskBusy[i] = false;
102  }
103  m_numBusyTasks = 0;
104  m_currentTask = 0;
105  m_currentPage = 0;
106  m_currentPageEntry = 0;
107  m_useEpa = useEpa;
108 
109 #ifdef DEBUG_SpuCollisionTaskProcess
110  m_initialized = true;
112 #endif
113 }
114 
115 
117 {
118 
119 #ifdef DEBUG_SPU_TASK_SCHEDULING
120  printf("SpuCollisionTaskProcess::issueTask (m_currentTask= %d\n)", m_currentTask);
121 #endif //DEBUG_SPU_TASK_SCHEDULING
122 
123  m_taskBusy[m_currentTask] = true;
124  m_numBusyTasks++;
125 
126 
128  taskDesc.m_useEpa = m_useEpa;
129 
130  {
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.
134 
135  taskDesc.m_inPairPtr = reinterpret_cast<uint64_t>(MIDPHASE_TASK_PTR(m_currentTask));
136 
137  taskDesc.taskId = m_currentTask;
138  taskDesc.numPages = m_currentPage+1;
140  }
141 
142 
143 
145 
146  // if all tasks busy, wait for spu event to clear the task.
147 
148 
150  {
151  unsigned int taskId;
152  unsigned int outputSize;
153 
154 
155  for (int i=0;i<int (m_maxNumOutstandingTasks);i++)
156  {
157  if (m_taskBusy[i])
158  {
159  taskId = i;
160  break;
161  }
162  }
163 
164  btAssert(taskId>=0);
165 
166 
167  m_threadInterface->waitForResponse(&taskId, &outputSize);
168 
169 // printf("issueTask taskId %d completed, numBusy=%d\n",taskId,m_numBusyTasks);
170 
171  //printf("PPU: after issue, received event: %u %d\n", taskId, outputSize);
172 
173  //postProcess(taskId, outputSize);
174 
175  m_taskBusy[taskId] = false;
176 
177  m_numBusyTasks--;
178  }
179 
180 }
181 
182 void SpuCollisionTaskProcess::addWorkToTask(void* pairArrayPtr,int startIndex,int endIndex)
183 {
184 #ifdef DEBUG_SPU_TASK_SCHEDULING
185  printf("#");
186 #endif //DEBUG_SPU_TASK_SCHEDULING
187 
188 #ifdef DEBUG_SpuCollisionTaskProcess
191 
192 #endif
193 
194  bool batch = true;
195 
196  if (batch)
197  {
199  {
201  {
202  // task buffer is full, issue current task.
203  // if all task buffers busy, this waits until SPU is done.
204  issueTask2();
205 
206  // find new task buffer
207  for (unsigned int i = 0; i < m_maxNumOutstandingTasks; i++)
208  {
209  if (!m_taskBusy[i])
210  {
211  m_currentTask = i;
212  //init the task data
213 
214  break;
215  }
216  }
217 
218  m_currentPage = 0;
219  }
220  else
221  {
222  m_currentPage++;
223  }
224 
225  m_currentPageEntry = 0;
226  }
227  }
228 
229  {
230 
231 
232 
234  *(reinterpret_cast<SpuGatherAndProcessWorkUnitInput*>
236 
237  wuInput.m_pairArrayPtr = reinterpret_cast<uint64_t>(pairArrayPtr);
238  wuInput.m_startIndex = startIndex;
239  wuInput.m_endIndex = endIndex;
240 
241 
242 
244 
245  if (!batch)
246  {
247  issueTask2();
248 
249  // find new task buffer
250  for (unsigned int i = 0; i < m_maxNumOutstandingTasks; i++)
251  {
252  if (!m_taskBusy[i])
253  {
254  m_currentTask = i;
255  //init the task data
256 
257  break;
258  }
259  }
260 
261  m_currentPage = 0;
263  }
264  }
265 }
266 
267 
268 void
270 {
271 #ifdef DEBUG_SPU_TASK_SCHEDULING
272  printf("\nSpuCollisionTaskProcess::flush()\n");
273 #endif //DEBUG_SPU_TASK_SCHEDULING
274 
275  // if there's a partially filled task buffer, submit that task
276  if (m_currentPage > 0 || m_currentPageEntry > 0)
277  {
278  issueTask2();
279  }
280 
281 
282  // all tasks are issued, wait for all tasks to be complete
283  while(m_numBusyTasks > 0)
284  {
285  // Consolidating SPU code
286  unsigned int taskId=-1;
287  unsigned int outputSize;
288 
289  for (int i=0;i<int (m_maxNumOutstandingTasks);i++)
290  {
291  if (m_taskBusy[i])
292  {
293  taskId = i;
294  break;
295  }
296  }
297 
298  btAssert(taskId>=0);
299 
300 
301  {
302 
303  // SPURS support.
304  m_threadInterface->waitForResponse(&taskId, &outputSize);
305  }
306 // printf("flush2 taskId %d completed, numBusy =%d \n",taskId,m_numBusyTasks);
307  //printf("PPU: flushing, received event: %u %d\n", taskId, outputSize);
308 
309  //postProcess(taskId, outputSize);
310 
311  m_taskBusy[taskId] = false;
312 
313  m_numBusyTasks--;
314  }
315 
316 
317 }
#define MIDPHASE_TASK_PTR(task)
#define MIDPHASE_ENTRY_PTR(task, page, entry)
void setNumTasks(int maxNumTasks)
set the maximum number of SPU tasks allocated
unsigned long int uint64_t
virtual void sendRequest(uint32_t uiCommand, ppu_address_t uiArgument0, uint32_t uiArgument1)=0
send messages to SPUs
uint32_t ppu_address_t
Task Description for SPU collision detection.
#define btAssert(x)
Definition: btScalar.h:101
void initialize2(bool useEpa=false)
call initialize in the beginning of the frame, before addCollisionPairToTask
#define MIDPHASE_NUM_WORKUNITS_PER_TASK
void flush2()
call flush to submit potential outstanding work to SPUs and wait for all involved SPUs to be finished...
btAlignedObjectArray< bool > m_taskBusy
#define MIDPHASE_WORKUNIT_TASK_SIZE
virtual void startSPU()=0
non-blocking test if a task is completed.
SpuCollisionTaskProcess(btThreadSupportInterface *threadInterface, unsigned int maxNumOutstandingTasks)
#define MIDPHASE_NUM_WORKUNIT_PAGES
class btThreadSupportInterface * m_threadInterface
int size() const
return the number of elements in the array
void addWorkToTask(void *pairArrayPtr, int startIndex, int endIndex)
batch up additional work to a current task for SPU processing. When batch is full, it issues the task.
MidphaseWorkUnitInput stores individual primitive versus mesh collision detection input...
#define btAlignedFree(ptr)
virtual void stopSPU()=0
tell the task scheduler we are done with the SPU tasks
btAlignedObjectArray< SpuGatherAndProcessPairsTaskDesc > m_spuGatherTaskDesc
#define MIDPHASE_NUM_WORKUNITS_PER_PAGE
void resize(int newsize, const T &fillData=T())
#define btAlignedAlloc(size, alignment)
virtual void waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1)=0
check for messages from SPUs
#define CMD_GATHER_AND_PROCESS_PAIRLIST