Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'extern/bullet2/BulletMultiThreaded/SpuCollisionTaskProcess.cpp')
-rw-r--r--extern/bullet2/BulletMultiThreaded/SpuCollisionTaskProcess.cpp318
1 files changed, 318 insertions, 0 deletions
diff --git a/extern/bullet2/BulletMultiThreaded/SpuCollisionTaskProcess.cpp b/extern/bullet2/BulletMultiThreaded/SpuCollisionTaskProcess.cpp
new file mode 100644
index 00000000000..86eda8697d0
--- /dev/null
+++ b/extern/bullet2/BulletMultiThreaded/SpuCollisionTaskProcess.cpp
@@ -0,0 +1,318 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+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.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+//#define DEBUG_SPU_TASK_SCHEDULING 1
+
+
+//class OptimizedBvhNode;
+
+#include "SpuCollisionTaskProcess.h"
+
+
+
+
+void SpuCollisionTaskProcess::setNumTasks(int maxNumTasks)
+{
+ if (int(m_maxNumOutstandingTasks) != maxNumTasks)
+ {
+ m_maxNumOutstandingTasks = maxNumTasks;
+ m_taskBusy.resize(m_maxNumOutstandingTasks);
+ m_spuGatherTaskDesc.resize(m_maxNumOutstandingTasks);
+
+ for (int i = 0; i < m_taskBusy.size(); i++)
+ {
+ m_taskBusy[i] = false;
+ }
+
+ ///re-allocate task memory buffers
+ if (m_workUnitTaskBuffers != 0)
+ {
+ btAlignedFree(m_workUnitTaskBuffers);
+ }
+
+ m_workUnitTaskBuffers = (unsigned char *)btAlignedAlloc(MIDPHASE_WORKUNIT_TASK_SIZE*m_maxNumOutstandingTasks, 128);
+ m_workUnitTaskBuffers = (unsigned char *)btAlignedAlloc(MIDPHASE_WORKUNIT_TASK_SIZE*6, 128);
+ }
+
+}
+
+
+
+SpuCollisionTaskProcess::SpuCollisionTaskProcess(class btThreadSupportInterface* threadInterface, unsigned int maxNumOutstandingTasks)
+:m_threadInterface(threadInterface),
+m_maxNumOutstandingTasks(0)
+{
+ m_workUnitTaskBuffers = (unsigned char *)0;
+ setNumTasks(maxNumOutstandingTasks);
+ m_numBusyTasks = 0;
+ m_currentTask = 0;
+ m_currentPage = 0;
+ m_currentPageEntry = 0;
+
+#ifdef DEBUG_SpuCollisionTaskProcess
+ m_initialized = false;
+#endif
+
+ m_threadInterface->startSPU();
+
+ //printf("sizeof vec_float4: %d\n", sizeof(vec_float4));
+ printf("sizeof SpuGatherAndProcessWorkUnitInput: %d\n", int(sizeof(SpuGatherAndProcessWorkUnitInput)));
+
+}
+
+SpuCollisionTaskProcess::~SpuCollisionTaskProcess()
+{
+
+ if (m_workUnitTaskBuffers != 0)
+ {
+ btAlignedFree(m_workUnitTaskBuffers);
+ m_workUnitTaskBuffers = 0;
+ }
+
+
+
+ m_threadInterface->stopSPU();
+
+}
+
+
+
+void SpuCollisionTaskProcess::initialize2(bool useEpa)
+{
+
+#ifdef DEBUG_SPU_TASK_SCHEDULING
+ printf("SpuCollisionTaskProcess::initialize()\n");
+#endif //DEBUG_SPU_TASK_SCHEDULING
+
+ for (int i = 0; i < int (m_maxNumOutstandingTasks); i++)
+ {
+ m_taskBusy[i] = false;
+ }
+ m_numBusyTasks = 0;
+ m_currentTask = 0;
+ m_currentPage = 0;
+ m_currentPageEntry = 0;
+ m_useEpa = useEpa;
+
+#ifdef DEBUG_SpuCollisionTaskProcess
+ m_initialized = true;
+ btAssert(MIDPHASE_NUM_WORKUNITS_PER_TASK*sizeof(SpuGatherAndProcessWorkUnitInput) <= MIDPHASE_WORKUNIT_TASK_SIZE);
+#endif
+}
+
+
+void SpuCollisionTaskProcess::issueTask2()
+{
+
+#ifdef DEBUG_SPU_TASK_SCHEDULING
+ printf("SpuCollisionTaskProcess::issueTask (m_currentTask= %d\n)", m_currentTask);
+#endif //DEBUG_SPU_TASK_SCHEDULING
+
+ m_taskBusy[m_currentTask] = true;
+ m_numBusyTasks++;
+
+
+ SpuGatherAndProcessPairsTaskDesc& taskDesc = m_spuGatherTaskDesc[m_currentTask];
+ taskDesc.m_useEpa = m_useEpa;
+
+ {
+ // send task description in event message
+ // no error checking here...
+ // but, currently, event queue can be no larger than NUM_WORKUNIT_TASKS.
+
+ taskDesc.m_inPairPtr = reinterpret_cast<uint64_t>(MIDPHASE_TASK_PTR(m_currentTask));
+
+ taskDesc.taskId = m_currentTask;
+ taskDesc.numPages = m_currentPage+1;
+ taskDesc.numOnLastPage = m_currentPageEntry;
+ }
+
+
+
+ m_threadInterface->sendRequest(CMD_GATHER_AND_PROCESS_PAIRLIST, (ppu_address_t) &taskDesc,m_currentTask);
+
+ // if all tasks busy, wait for spu event to clear the task.
+
+
+ if (m_numBusyTasks >= m_maxNumOutstandingTasks)
+ {
+ unsigned int taskId;
+ unsigned int outputSize;
+
+
+ for (int i=0;i<int (m_maxNumOutstandingTasks);i++)
+ {
+ if (m_taskBusy[i])
+ {
+ taskId = i;
+ break;
+ }
+ }
+
+ btAssert(taskId>=0);
+
+
+ m_threadInterface->waitForResponse(&taskId, &outputSize);
+
+// printf("issueTask taskId %d completed, numBusy=%d\n",taskId,m_numBusyTasks);
+
+ //printf("PPU: after issue, received event: %u %d\n", taskId, outputSize);
+
+ //postProcess(taskId, outputSize);
+
+ m_taskBusy[taskId] = false;
+
+ m_numBusyTasks--;
+ }
+
+}
+
+void SpuCollisionTaskProcess::addWorkToTask(void* pairArrayPtr,int startIndex,int endIndex)
+{
+#ifdef DEBUG_SPU_TASK_SCHEDULING
+ printf("#");
+#endif //DEBUG_SPU_TASK_SCHEDULING
+
+#ifdef DEBUG_SpuCollisionTaskProcess
+ btAssert(m_initialized);
+ btAssert(m_workUnitTaskBuffers);
+
+#endif
+
+ bool batch = true;
+
+ if (batch)
+ {
+ if (m_currentPageEntry == MIDPHASE_NUM_WORKUNITS_PER_PAGE)
+ {
+ if (m_currentPage == MIDPHASE_NUM_WORKUNIT_PAGES-1)
+ {
+ // task buffer is full, issue current task.
+ // if all task buffers busy, this waits until SPU is done.
+ issueTask2();
+
+ // find new task buffer
+ for (unsigned int i = 0; i < m_maxNumOutstandingTasks; i++)
+ {
+ if (!m_taskBusy[i])
+ {
+ m_currentTask = i;
+ //init the task data
+
+ break;
+ }
+ }
+
+ m_currentPage = 0;
+ }
+ else
+ {
+ m_currentPage++;
+ }
+
+ m_currentPageEntry = 0;
+ }
+ }
+
+ {
+
+
+
+ SpuGatherAndProcessWorkUnitInput &wuInput =
+ *(reinterpret_cast<SpuGatherAndProcessWorkUnitInput*>
+ (MIDPHASE_ENTRY_PTR(m_currentTask, m_currentPage, m_currentPageEntry)));
+
+ wuInput.m_pairArrayPtr = reinterpret_cast<uint64_t>(pairArrayPtr);
+ wuInput.m_startIndex = startIndex;
+ wuInput.m_endIndex = endIndex;
+
+
+
+ m_currentPageEntry++;
+
+ if (!batch)
+ {
+ issueTask2();
+
+ // find new task buffer
+ for (unsigned int i = 0; i < m_maxNumOutstandingTasks; i++)
+ {
+ if (!m_taskBusy[i])
+ {
+ m_currentTask = i;
+ //init the task data
+
+ break;
+ }
+ }
+
+ m_currentPage = 0;
+ m_currentPageEntry =0;
+ }
+ }
+}
+
+
+void
+SpuCollisionTaskProcess::flush2()
+{
+#ifdef DEBUG_SPU_TASK_SCHEDULING
+ printf("\nSpuCollisionTaskProcess::flush()\n");
+#endif //DEBUG_SPU_TASK_SCHEDULING
+
+ // if there's a partially filled task buffer, submit that task
+ if (m_currentPage > 0 || m_currentPageEntry > 0)
+ {
+ issueTask2();
+ }
+
+
+ // all tasks are issued, wait for all tasks to be complete
+ while(m_numBusyTasks > 0)
+ {
+ // Consolidating SPU code
+ unsigned int taskId=-1;
+ unsigned int outputSize;
+
+ for (int i=0;i<int (m_maxNumOutstandingTasks);i++)
+ {
+ if (m_taskBusy[i])
+ {
+ taskId = i;
+ break;
+ }
+ }
+
+ btAssert(taskId>=0);
+
+
+ {
+
+ // SPURS support.
+ m_threadInterface->waitForResponse(&taskId, &outputSize);
+ }
+// printf("flush2 taskId %d completed, numBusy =%d \n",taskId,m_numBusyTasks);
+ //printf("PPU: flushing, received event: %u %d\n", taskId, outputSize);
+
+ //postProcess(taskId, outputSize);
+
+ m_taskBusy[taskId] = false;
+
+ m_numBusyTasks--;
+ }
+
+
+}