Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/physics/src/bullet/BulletMultiThreaded/SpuCollisionTaskProcess.cpp @ 1967

Last change on this file since 1967 was 1966, checked in by rgrieder, 16 years ago

Let's go for multithreaded physics!

  • Property svn:eol-style set to native
File size: 6.6 KB
Line 
1/*
2Bullet Continuous Collision Detection and Physics Library
3Copyright (c) 2003-2007 Erwin Coumans  http://bulletphysics.com
4
5This software is provided 'as-is', without any express or implied warranty.
6In no event will the authors be held liable for any damages arising from the use of this software.
7Permission is granted to anyone to use this software for any purpose,
8including commercial applications, and to alter it and redistribute it freely,
9subject to the following restrictions:
10
111. 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.
122. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
133. 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
22#include "SpuCollisionTaskProcess.h"
23
24
25
26
27
28
29SpuCollisionTaskProcess::SpuCollisionTaskProcess(class  btThreadSupportInterface*       threadInterface, unsigned int   maxNumOutstandingTasks)
30:m_threadInterface(threadInterface),
31m_maxNumOutstandingTasks(maxNumOutstandingTasks)
32{
33        m_workUnitTaskBuffers = (unsigned char *)0;
34        m_taskBusy.resize(m_maxNumOutstandingTasks);
35        m_spuGatherTaskDesc.resize(m_maxNumOutstandingTasks);
36
37        for (int i = 0; i < m_maxNumOutstandingTasks; i++)
38        {
39                m_taskBusy[i] = false;
40        }
41        m_numBusyTasks = 0;
42        m_currentTask = 0;
43        m_currentPage = 0;
44        m_currentPageEntry = 0;
45
46#ifdef DEBUG_SpuCollisionTaskProcess
47        m_initialized = false;
48#endif
49
50        m_threadInterface->startSPU();
51
52        //printf("sizeof vec_float4: %d\n", sizeof(vec_float4));
53        printf("sizeof SpuGatherAndProcessWorkUnitInput: %d\n", sizeof(SpuGatherAndProcessWorkUnitInput));
54
55}
56
57SpuCollisionTaskProcess::~SpuCollisionTaskProcess()
58{
59       
60        if (m_workUnitTaskBuffers != 0)
61        {
62                btAlignedFree(m_workUnitTaskBuffers);
63                m_workUnitTaskBuffers = 0;
64        }
65       
66
67
68        m_threadInterface->stopSPU();
69       
70}
71
72
73
74void SpuCollisionTaskProcess::initialize2(bool useEpa)
75{
76
77#ifdef DEBUG_SPU_TASK_SCHEDULING
78        printf("SpuCollisionTaskProcess::initialize()\n");
79#endif //DEBUG_SPU_TASK_SCHEDULING
80        if (!m_workUnitTaskBuffers)
81        {
82                m_workUnitTaskBuffers = (unsigned char *)btAlignedAlloc(MIDPHASE_WORKUNIT_TASK_SIZE*m_maxNumOutstandingTasks, 128);
83        }
84
85       
86        for (int i = 0; i < m_maxNumOutstandingTasks; i++)
87        {
88                m_taskBusy[i] = false;
89        }
90        m_numBusyTasks = 0;
91        m_currentTask = 0;
92        m_currentPage = 0;
93        m_currentPageEntry = 0;
94        m_useEpa = useEpa;
95
96#ifdef DEBUG_SpuCollisionTaskProcess
97        m_initialized = true;
98        assert(MIDPHASE_NUM_WORKUNITS_PER_TASK*sizeof(SpuGatherAndProcessWorkUnitInput) <= MIDPHASE_WORKUNIT_TASK_SIZE);
99#endif
100}
101
102
103void SpuCollisionTaskProcess::issueTask2()
104{
105
106#ifdef DEBUG_SPU_TASK_SCHEDULING
107        printf("SpuCollisionTaskProcess::issueTask (m_currentTask= %d\n)", m_currentTask);
108#endif //DEBUG_SPU_TASK_SCHEDULING
109
110        m_taskBusy[m_currentTask] = true;
111        m_numBusyTasks++;
112
113
114        SpuGatherAndProcessPairsTaskDesc& taskDesc = m_spuGatherTaskDesc[m_currentTask];
115        taskDesc.m_useEpa = m_useEpa;
116
117        {
118                // send task description in event message
119                // no error checking here...
120                // but, currently, event queue can be no larger than NUM_WORKUNIT_TASKS.
121       
122                taskDesc.inPtr = reinterpret_cast<uint64_t>(MIDPHASE_TASK_PTR(m_currentTask));
123       
124                taskDesc.taskId = m_currentTask;
125                taskDesc.numPages = m_currentPage+1;
126                taskDesc.numOnLastPage = m_currentPageEntry;
127        }
128
129
130
131        m_threadInterface->sendRequest(CMD_GATHER_AND_PROCESS_PAIRLIST, (uint32_t) &taskDesc,m_currentTask);
132
133        // if all tasks busy, wait for spu event to clear the task.
134       
135
136        if (m_numBusyTasks >= m_maxNumOutstandingTasks)
137        {
138                unsigned int taskId;
139                unsigned int outputSize;
140
141               
142                for (int i=0;i<m_maxNumOutstandingTasks;i++)
143                  {
144                          if (m_taskBusy[i])
145                          {
146                                  taskId = i;
147                                  break;
148                          }
149                  }
150
151          btAssert(taskId>=0);
152
153         
154                m_threadInterface->waitForResponse(&taskId, &outputSize);
155
156//              printf("issueTask taskId %d completed, numBusy=%d\n",taskId,m_numBusyTasks);
157
158                //printf("PPU: after issue, received event: %u %d\n", taskId, outputSize);
159
160                //postProcess(taskId, outputSize);
161
162                m_taskBusy[taskId] = false;
163
164                m_numBusyTasks--;
165        }
166       
167}
168
169void SpuCollisionTaskProcess::addWorkToTask(void* pairArrayPtr,int startIndex,int endIndex)
170{
171#ifdef DEBUG_SPU_TASK_SCHEDULING
172        printf("#");
173#endif //DEBUG_SPU_TASK_SCHEDULING
174       
175#ifdef DEBUG_SpuCollisionTaskProcess
176        assert(m_initialized);
177        assert(m_workUnitTaskBuffers);
178
179#endif
180
181        bool batch = true;
182
183        if (batch)
184        {
185                if (m_currentPageEntry == MIDPHASE_NUM_WORKUNITS_PER_PAGE)
186                {
187                        if (m_currentPage == MIDPHASE_NUM_WORKUNIT_PAGES-1)
188                        {
189                                // task buffer is full, issue current task.
190                                // if all task buffers busy, this waits until SPU is done.
191                                issueTask2();
192
193                                // find new task buffer
194                                for (unsigned int i = 0; i < m_maxNumOutstandingTasks; i++)
195                                {
196                                        if (!m_taskBusy[i])
197                                        {
198                                                m_currentTask = i;
199                                                //init the task data
200
201                                                break;
202                                        }
203                                }
204
205                                m_currentPage = 0;
206                        }
207                        else
208                        {
209                                m_currentPage++;
210                        }
211
212                        m_currentPageEntry = 0;
213                }
214        }
215
216        {
217
218
219
220                SpuGatherAndProcessWorkUnitInput &wuInput = 
221                        *(reinterpret_cast<SpuGatherAndProcessWorkUnitInput*>
222                        (MIDPHASE_ENTRY_PTR(m_currentTask, m_currentPage, m_currentPageEntry)));
223               
224                wuInput.m_pairArrayPtr = reinterpret_cast<uint64_t>(pairArrayPtr);
225                wuInput.m_startIndex = startIndex;
226                wuInput.m_endIndex = endIndex;
227
228               
229       
230                m_currentPageEntry++;
231
232                if (!batch)
233                {
234                        issueTask2();
235
236                        // find new task buffer
237                        for (unsigned int i = 0; i < m_maxNumOutstandingTasks; i++)
238                        {
239                                if (!m_taskBusy[i])
240                                {
241                                        m_currentTask = i;
242                                        //init the task data
243
244                                        break;
245                                }
246                        }
247
248                        m_currentPage = 0;
249                        m_currentPageEntry =0;
250                }
251        }
252}
253
254
255void 
256SpuCollisionTaskProcess::flush2()
257{
258#ifdef DEBUG_SPU_TASK_SCHEDULING
259        printf("\nSpuCollisionTaskProcess::flush()\n");
260#endif //DEBUG_SPU_TASK_SCHEDULING
261       
262        // if there's a partially filled task buffer, submit that task
263        if (m_currentPage > 0 || m_currentPageEntry > 0)
264        {
265                issueTask2();
266        }
267
268
269        // all tasks are issued, wait for all tasks to be complete
270        while(m_numBusyTasks > 0)
271        {
272          // Consolidating SPU code
273          unsigned int taskId=-1;
274          unsigned int outputSize;
275         
276          for (int i=0;i<m_maxNumOutstandingTasks;i++)
277          {
278                  if (m_taskBusy[i])
279                  {
280                          taskId = i;
281                          break;
282                  }
283          }
284
285          btAssert(taskId>=0);
286
287       
288          {
289                       
290                // SPURS support.
291                  m_threadInterface->waitForResponse(&taskId, &outputSize);
292          }
293//               printf("flush2 taskId %d completed, numBusy =%d \n",taskId,m_numBusyTasks);
294                //printf("PPU: flushing, received event: %u %d\n", taskId, outputSize);
295
296                //postProcess(taskId, outputSize);
297
298                m_taskBusy[taskId] = false;
299
300                m_numBusyTasks--;
301        }
302
303
304}
Note: See TracBrowser for help on using the repository browser.