SpuCollisionTaskProcess.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. /*
  2. Bullet Continuous Collision Detection and Physics Library
  3. Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com
  4. This software is provided 'as-is', without any express or implied warranty.
  5. In no event will the authors be held liable for any damages arising from the use of this software.
  6. Permission is granted to anyone to use this software for any purpose,
  7. including commercial applications, and to alter it and redistribute it freely,
  8. subject to the following restrictions:
  9. 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.
  10. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
  11. 3. This notice may not be removed or altered from any source distribution.
  12. */
  13. //#define DEBUG_SPU_TASK_SCHEDULING 1
  14. //class OptimizedBvhNode;
  15. #include "SpuCollisionTaskProcess.h"
  16. void SpuCollisionTaskProcess::setNumTasks(int maxNumTasks)
  17. {
  18. if (int(m_maxNumOutstandingTasks) != maxNumTasks)
  19. {
  20. m_maxNumOutstandingTasks = maxNumTasks;
  21. m_taskBusy.resize(m_maxNumOutstandingTasks);
  22. m_spuGatherTaskDesc.resize(m_maxNumOutstandingTasks);
  23. for (int i = 0; i < m_taskBusy.size(); i++)
  24. {
  25. m_taskBusy[i] = false;
  26. }
  27. ///re-allocate task memory buffers
  28. if (m_workUnitTaskBuffers != 0)
  29. {
  30. btAlignedFree(m_workUnitTaskBuffers);
  31. }
  32. m_workUnitTaskBuffers = (unsigned char *)btAlignedAlloc(MIDPHASE_WORKUNIT_TASK_SIZE*m_maxNumOutstandingTasks, 128);
  33. }
  34. }
  35. SpuCollisionTaskProcess::SpuCollisionTaskProcess(class btThreadSupportInterface* threadInterface, unsigned int maxNumOutstandingTasks)
  36. :m_threadInterface(threadInterface),
  37. m_maxNumOutstandingTasks(0)
  38. {
  39. m_workUnitTaskBuffers = (unsigned char *)0;
  40. setNumTasks(maxNumOutstandingTasks);
  41. m_numBusyTasks = 0;
  42. m_currentTask = 0;
  43. m_currentPage = 0;
  44. m_currentPageEntry = 0;
  45. #ifdef DEBUG_SpuCollisionTaskProcess
  46. m_initialized = false;
  47. #endif
  48. m_threadInterface->startSPU();
  49. //printf("sizeof vec_float4: %d\n", sizeof(vec_float4));
  50. printf("sizeof SpuGatherAndProcessWorkUnitInput: %d\n", int(sizeof(SpuGatherAndProcessWorkUnitInput)));
  51. }
  52. SpuCollisionTaskProcess::~SpuCollisionTaskProcess()
  53. {
  54. if (m_workUnitTaskBuffers != 0)
  55. {
  56. btAlignedFree(m_workUnitTaskBuffers);
  57. m_workUnitTaskBuffers = 0;
  58. }
  59. m_threadInterface->stopSPU();
  60. }
  61. void SpuCollisionTaskProcess::initialize2(bool useEpa)
  62. {
  63. #ifdef DEBUG_SPU_TASK_SCHEDULING
  64. printf("SpuCollisionTaskProcess::initialize()\n");
  65. #endif //DEBUG_SPU_TASK_SCHEDULING
  66. for (int i = 0; i < int (m_maxNumOutstandingTasks); i++)
  67. {
  68. m_taskBusy[i] = false;
  69. }
  70. m_numBusyTasks = 0;
  71. m_currentTask = 0;
  72. m_currentPage = 0;
  73. m_currentPageEntry = 0;
  74. m_useEpa = useEpa;
  75. #ifdef DEBUG_SpuCollisionTaskProcess
  76. m_initialized = true;
  77. btAssert(MIDPHASE_NUM_WORKUNITS_PER_TASK*sizeof(SpuGatherAndProcessWorkUnitInput) <= MIDPHASE_WORKUNIT_TASK_SIZE);
  78. #endif
  79. }
  80. void SpuCollisionTaskProcess::issueTask2()
  81. {
  82. #ifdef DEBUG_SPU_TASK_SCHEDULING
  83. printf("SpuCollisionTaskProcess::issueTask (m_currentTask= %d\n)", m_currentTask);
  84. #endif //DEBUG_SPU_TASK_SCHEDULING
  85. m_taskBusy[m_currentTask] = true;
  86. m_numBusyTasks++;
  87. SpuGatherAndProcessPairsTaskDesc& taskDesc = m_spuGatherTaskDesc[m_currentTask];
  88. taskDesc.m_useEpa = m_useEpa;
  89. {
  90. // send task description in event message
  91. // no error checking here...
  92. // but, currently, event queue can be no larger than NUM_WORKUNIT_TASKS.
  93. taskDesc.m_inPairPtr = reinterpret_cast<uint64_t>(MIDPHASE_TASK_PTR(m_currentTask));
  94. taskDesc.taskId = m_currentTask;
  95. taskDesc.numPages = m_currentPage+1;
  96. taskDesc.numOnLastPage = m_currentPageEntry;
  97. }
  98. m_threadInterface->sendRequest(CMD_GATHER_AND_PROCESS_PAIRLIST, (ppu_address_t) &taskDesc,m_currentTask);
  99. // if all tasks busy, wait for spu event to clear the task.
  100. if (m_numBusyTasks >= m_maxNumOutstandingTasks)
  101. {
  102. unsigned int taskId;
  103. unsigned int outputSize;
  104. for (int i=0;i<int (m_maxNumOutstandingTasks);i++)
  105. {
  106. if (m_taskBusy[i])
  107. {
  108. taskId = i;
  109. break;
  110. }
  111. }
  112. btAssert(taskId>=0);
  113. m_threadInterface->waitForResponse(&taskId, &outputSize);
  114. // printf("issueTask taskId %d completed, numBusy=%d\n",taskId,m_numBusyTasks);
  115. //printf("PPU: after issue, received event: %u %d\n", taskId, outputSize);
  116. //postProcess(taskId, outputSize);
  117. m_taskBusy[taskId] = false;
  118. m_numBusyTasks--;
  119. }
  120. }
  121. void SpuCollisionTaskProcess::addWorkToTask(void* pairArrayPtr,int startIndex,int endIndex)
  122. {
  123. #ifdef DEBUG_SPU_TASK_SCHEDULING
  124. printf("#");
  125. #endif //DEBUG_SPU_TASK_SCHEDULING
  126. #ifdef DEBUG_SpuCollisionTaskProcess
  127. btAssert(m_initialized);
  128. btAssert(m_workUnitTaskBuffers);
  129. #endif
  130. bool batch = true;
  131. if (batch)
  132. {
  133. if (m_currentPageEntry == MIDPHASE_NUM_WORKUNITS_PER_PAGE)
  134. {
  135. if (m_currentPage == MIDPHASE_NUM_WORKUNIT_PAGES-1)
  136. {
  137. // task buffer is full, issue current task.
  138. // if all task buffers busy, this waits until SPU is done.
  139. issueTask2();
  140. // find new task buffer
  141. for (unsigned int i = 0; i < m_maxNumOutstandingTasks; i++)
  142. {
  143. if (!m_taskBusy[i])
  144. {
  145. m_currentTask = i;
  146. //init the task data
  147. break;
  148. }
  149. }
  150. m_currentPage = 0;
  151. }
  152. else
  153. {
  154. m_currentPage++;
  155. }
  156. m_currentPageEntry = 0;
  157. }
  158. }
  159. {
  160. SpuGatherAndProcessWorkUnitInput &wuInput =
  161. *(reinterpret_cast<SpuGatherAndProcessWorkUnitInput*>
  162. (MIDPHASE_ENTRY_PTR(m_currentTask, m_currentPage, m_currentPageEntry)));
  163. wuInput.m_pairArrayPtr = reinterpret_cast<uint64_t>(pairArrayPtr);
  164. wuInput.m_startIndex = startIndex;
  165. wuInput.m_endIndex = endIndex;
  166. m_currentPageEntry++;
  167. if (!batch)
  168. {
  169. issueTask2();
  170. // find new task buffer
  171. for (unsigned int i = 0; i < m_maxNumOutstandingTasks; i++)
  172. {
  173. if (!m_taskBusy[i])
  174. {
  175. m_currentTask = i;
  176. //init the task data
  177. break;
  178. }
  179. }
  180. m_currentPage = 0;
  181. m_currentPageEntry =0;
  182. }
  183. }
  184. }
  185. void
  186. SpuCollisionTaskProcess::flush2()
  187. {
  188. #ifdef DEBUG_SPU_TASK_SCHEDULING
  189. printf("\nSpuCollisionTaskProcess::flush()\n");
  190. #endif //DEBUG_SPU_TASK_SCHEDULING
  191. // if there's a partially filled task buffer, submit that task
  192. if (m_currentPage > 0 || m_currentPageEntry > 0)
  193. {
  194. issueTask2();
  195. }
  196. // all tasks are issued, wait for all tasks to be complete
  197. while(m_numBusyTasks > 0)
  198. {
  199. // Consolidating SPU code
  200. unsigned int taskId=-1;
  201. unsigned int outputSize;
  202. for (int i=0;i<int (m_maxNumOutstandingTasks);i++)
  203. {
  204. if (m_taskBusy[i])
  205. {
  206. taskId = i;
  207. break;
  208. }
  209. }
  210. btAssert(taskId>=0);
  211. {
  212. // SPURS support.
  213. m_threadInterface->waitForResponse(&taskId, &outputSize);
  214. }
  215. // printf("flush2 taskId %d completed, numBusy =%d \n",taskId,m_numBusyTasks);
  216. //printf("PPU: flushing, received event: %u %d\n", taskId, outputSize);
  217. //postProcess(taskId, outputSize);
  218. m_taskBusy[taskId] = false;
  219. m_numBusyTasks--;
  220. }
  221. }