diff --git a/Extras/BulletMultiThreaded/PlatformDefinitions.h b/Extras/BulletMultiThreaded/PlatformDefinitions.h index dcbad3f35..c88ce2590 100644 --- a/Extras/BulletMultiThreaded/PlatformDefinitions.h +++ b/Extras/BulletMultiThreaded/PlatformDefinitions.h @@ -1,44 +1,72 @@ -#ifndef TYPE_DEFINITIONS_H -#define TYPE_DEFINITIONS_H - - - -///This file provides some platform/compiler checks for common definitions - -#ifdef WIN32 - #if defined(__MINGW32__) || defined(__CYGWIN__) || (defined (_MSC_VER) && _MSC_VER < 1300) - #else - #endif //__MINGW32__ - - typedef unsigned char uint8_t; - typedef unsigned long int uint64_t; - typedef unsigned int uint32_t; - typedef unsigned short uint16_t; - - #include - #define memalign(alignment, size) malloc(size); - -#include //memcpy - - #define USE_WIN32_THREADING 1 - -#else -#if defined (__CELLOS_LV2__) - ///Playstation 3 Cell SDK - #include -#else - //non-windows systems - - #define USE_PTHREADS 1 - - -#endif //__CELLOS_LV2__ - - #include - #include - #include //for memcpy - -#endif - - -#endif //TYPE_DEFINITIONS_H \ No newline at end of file +#ifndef TYPE_DEFINITIONS_H +#define TYPE_DEFINITIONS_H + + + +///This file provides some platform/compiler checks for common definitions + +#ifdef WIN32 + +typedef union +{ + unsigned int u; + void *p; +} addr64; + + #if defined(__MINGW32__) || defined(__CYGWIN__) || (defined (_MSC_VER) && _MSC_VER < 1300) + #else + #endif //__MINGW32__ + + typedef unsigned char uint8_t; + typedef unsigned long int uint64_t; + typedef unsigned int uint32_t; + typedef unsigned short uint16_t; + + #include + #define memalign(alignment, size) malloc(size); + +#include //memcpy + + #define USE_WIN32_THREADING 1 + + + #include + #define spu_printf printf + +#else + #include + #include + #include //for memcpy + +#if defined (__CELLOS_LV2__) + // Playstation 3 Cell SDK +#include + +#else + // posix system + +#define USE_PTHREADS + +#ifdef USE_LIBSPE2 +#include +#define spu_printf printf +#define DWORD unsigned int + + typedef union + { + unsigned long long ull; + unsigned int ui[2]; + void *p; + } addr64; + + +#endif // USE_LIBSPE2 + +#endif //__CELLOS_LV2__ + +#endif + + +#endif //TYPE_DEFINITIONS_H + + diff --git a/Extras/BulletMultiThreaded/SpuCollisionTaskProcess.cpp b/Extras/BulletMultiThreaded/SpuCollisionTaskProcess.cpp index 0a07aac6b..27640fbea 100644 --- a/Extras/BulletMultiThreaded/SpuCollisionTaskProcess.cpp +++ b/Extras/BulletMultiThreaded/SpuCollisionTaskProcess.cpp @@ -1,288 +1,273 @@ -/* -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 - -#include "btThreadSupportInterface.h" - -//#include "SPUAssert.h" -#include - -//class OptimizedBvhNode; - -#include "SpuCollisionTaskProcess.h" -#include "BulletCollision/CollisionDispatch/btCollisionObject.h" -#include "BulletCollision/CollisionShapes/btCollisionShape.h" -#include "BulletCollision/CollisionShapes/btConvexShape.h" -#include "SpuLibspe2Support.h" -#include "SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h" // for definitions processCollisionTask and createCollisionLocalStoreMemory - - -#include - - - - - - - -SpuCollisionTaskProcess::SpuCollisionTaskProcess(class btThreadSupportInterface* threadInterface, unsigned int maxNumOutstandingTasks) -:m_threadInterface(threadInterface), -m_maxNumOutstandingTasks(maxNumOutstandingTasks) -{ - m_workUnitTaskBuffers = (unsigned char *)0; - - m_taskBusy.resize(m_maxNumOutstandingTasks); - m_spuGatherTaskDesc.resize(m_maxNumOutstandingTasks); - - for (int i = 0; i < m_maxNumOutstandingTasks; i++) - { - m_taskBusy[i] = false; - } - 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", sizeof(SpuGatherAndProcessWorkUnitInput)); - -} - -SpuCollisionTaskProcess::~SpuCollisionTaskProcess() -{ - if (m_workUnitTaskBuffers != 0) - { - free(m_workUnitTaskBuffers); - m_workUnitTaskBuffers = 0; - } - - - - m_threadInterface->stopSPU(); - -} - - - -void -SpuCollisionTaskProcess::initialize2() -{ -#ifdef DEBUG_SPU_TASK_SCHEDULING - printf("SpuCollisionTaskProcess::initialize()\n"); -#endif //DEBUG_SPU_TASK_SCHEDULING - if (!m_workUnitTaskBuffers) - { - m_workUnitTaskBuffers = (unsigned char *)memalign(128, MIDPHASE_WORKUNIT_TASK_SIZE*m_maxNumOutstandingTasks); - } - - for (int i = 0; i < m_maxNumOutstandingTasks; i++) - { - m_taskBusy[i] = false; - } - m_numBusyTasks = 0; - m_currentTask = 0; - m_currentPage = 0; - m_currentPageEntry = 0; - -#ifdef DEBUG_SpuCollisionTaskProcess - m_initialized = true; - assert(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]; - { - // send task description in event message - // no error checking here... - // but, currently, event queue can be no larger than NUM_WORKUNIT_TASKS. - - taskDesc.inPtr = reinterpret_cast(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, (uint32_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; - - m_threadInterface->waitForResponse(&taskId, &outputSize); - - //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 - assert(m_initialized); - assert(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 - (MIDPHASE_ENTRY_PTR(m_currentTask, m_currentPage, m_currentPageEntry))); - - wuInput.m_pairArrayPtr = reinterpret_cast(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; - unsigned int outputSize; - - { - - // SPURS support. - m_threadInterface->waitForResponse(&taskId, &outputSize); - } - - //printf("PPU: flushing, received event: %u %d\n", taskId, outputSize); - - //postProcess(taskId, outputSize); - - m_taskBusy[taskId] = false; - - m_numBusyTasks--; - } - - -} +/* +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" + + + + + + +SpuCollisionTaskProcess::SpuCollisionTaskProcess(class btThreadSupportInterface* threadInterface, unsigned int maxNumOutstandingTasks) +:m_threadInterface(threadInterface), +m_maxNumOutstandingTasks(maxNumOutstandingTasks) +{ + m_workUnitTaskBuffers = (unsigned char *)0; + m_taskBusy.resize(m_maxNumOutstandingTasks); + m_spuGatherTaskDesc.resize(m_maxNumOutstandingTasks); + + for (int i = 0; i < m_maxNumOutstandingTasks; i++) + { + m_taskBusy[i] = false; + } + 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", sizeof(SpuGatherAndProcessWorkUnitInput)); + +} + +SpuCollisionTaskProcess::~SpuCollisionTaskProcess() +{ + + if (m_workUnitTaskBuffers != 0) + { + btAlignedFree(m_workUnitTaskBuffers); + m_workUnitTaskBuffers = 0; + } + + + + m_threadInterface->stopSPU(); + +} + + + +void SpuCollisionTaskProcess::initialize2() +{ + +#ifdef DEBUG_SPU_TASK_SCHEDULING + printf("SpuCollisionTaskProcess::initialize()\n"); +#endif //DEBUG_SPU_TASK_SCHEDULING + if (!m_workUnitTaskBuffers) + { + m_workUnitTaskBuffers = (unsigned char *)btAlignedAlloc(MIDPHASE_WORKUNIT_TASK_SIZE*m_maxNumOutstandingTasks, 128); + } + + for (int i = 0; i < m_maxNumOutstandingTasks; i++) + { + m_taskBusy[i] = false; + } + m_numBusyTasks = 0; + m_currentTask = 0; + m_currentPage = 0; + m_currentPageEntry = 0; + +#ifdef DEBUG_SpuCollisionTaskProcess + m_initialized = true; + assert(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]; + { + // send task description in event message + // no error checking here... + // but, currently, event queue can be no larger than NUM_WORKUNIT_TASKS. + + taskDesc.inPtr = reinterpret_cast(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, (uint32_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; + + m_threadInterface->waitForResponse(&taskId, &outputSize); + + //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 + assert(m_initialized); + assert(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 + (MIDPHASE_ENTRY_PTR(m_currentTask, m_currentPage, m_currentPageEntry))); + + wuInput.m_pairArrayPtr = reinterpret_cast(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; + unsigned int outputSize; + + { + + // SPURS support. + m_threadInterface->waitForResponse(&taskId, &outputSize); + } + + //printf("PPU: flushing, received event: %u %d\n", taskId, outputSize); + + //postProcess(taskId, outputSize); + + m_taskBusy[taskId] = false; + + m_numBusyTasks--; + } + + +} diff --git a/Extras/BulletMultiThreaded/SpuCollisionTaskProcess.h b/Extras/BulletMultiThreaded/SpuCollisionTaskProcess.h index 7d6ae7b6d..28eabc535 100644 --- a/Extras/BulletMultiThreaded/SpuCollisionTaskProcess.h +++ b/Extras/BulletMultiThreaded/SpuCollisionTaskProcess.h @@ -1,134 +1,152 @@ -/* -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. -*/ - -#ifndef SPU_COLLISION_TASK_PROCESS_H -#define SPU_COLLISION_TASK_PROCESS_H - -#include - -#include - -#include "PlatformDefinitions.h" -#include "LinearMath/btAlignedObjectArray.h" - -//#define DEBUG_SpuCollisionTaskProcess 1 - - -#define CMD_GATHER_AND_PROCESS_PAIRLIST 1 - -class btCollisionObject; -class btPersistentManifold; -class btDispatcher; - - -///Task Description for SPU collision detection -struct SpuGatherAndProcessPairsTaskDesc -{ - uint64_t inPtr;//m_pairArrayPtr; - //mutex variable - uint32_t m_someMutexVariableInMainMemory; - - uint64_t m_dispatcher; - - uint32_t numOnLastPage; - - uint16_t numPages; - uint16_t taskId; - -// struct CollisionTask_LocalStoreMemory* m_lsMemory; -} -#ifdef __CELLOS_LV2__ -__attribute__ ((aligned (16))) -#endif -; - - -///MidphaseWorkUnitInput stores individual primitive versus mesh collision detection input, to be processed by the SPU. -struct SpuGatherAndProcessWorkUnitInput -{ - uint64_t m_pairArrayPtr; - int m_startIndex; - int m_endIndex; -}; - - - - -/// SpuCollisionTaskProcess handles SPU processing of collision pairs. -/// Maintains a set of task buffers. -/// When the task is full, the task is issued for SPUs to process. Contact output goes into btPersistentManifold -/// associated with each task. -/// When PPU issues a task, it will look for completed task buffers -/// PPU will do postprocessing, dependent on workunit output (not likely) -class SpuCollisionTaskProcess -{ - - unsigned char *m_workUnitTaskBuffers; - - - // track task buffers that are being used, and total busy tasks - btAlignedObjectArray m_taskBusy; - btAlignedObjectArray m_spuGatherTaskDesc; - - class btThreadSupportInterface* m_threadInterface; - - unsigned int m_maxNumOutstandingTasks; - - unsigned int m_numBusyTasks; - - // the current task and the current entry to insert a new work unit - unsigned int m_currentTask; - unsigned int m_currentPage; - unsigned int m_currentPageEntry; - -#ifdef DEBUG_SpuCollisionTaskProcess - bool m_initialized; -#endif - void issueTask2(); - //void postProcess(unsigned int taskId, int outputSize); - -public: - SpuCollisionTaskProcess(btThreadSupportInterface* threadInterface, unsigned int maxNumOutstandingTasks); - - ~SpuCollisionTaskProcess(); - - ///call initialize in the beginning of the frame, before addCollisionPairToTask - void initialize2(); - - ///batch up additional work to a current task for SPU processing. When batch is full, it issues the task. - void addWorkToTask(void* pairArrayPtr,int startIndex,int endIndex); - - ///call flush to submit potential outstanding work to SPUs and wait for all involved SPUs to be finished - void flush2(); -}; - - - -#define MIDPHASE_TASK_PTR(task) (&m_workUnitTaskBuffers[0] + MIDPHASE_WORKUNIT_TASK_SIZE*task) -#define MIDPHASE_ENTRY_PTR(task,page,entry) (MIDPHASE_TASK_PTR(task) + MIDPHASE_WORKUNIT_PAGE_SIZE*page + sizeof(SpuGatherAndProcessWorkUnitInput)*entry) -#define MIDPHASE_OUTPUT_PTR(task) (&m_contactOutputBuffers[0] + MIDPHASE_MAX_CONTACT_BUFFER_SIZE*task) -#define MIDPHASE_TREENODES_PTR(task) (&m_complexShapeBuffers[0] + MIDPHASE_COMPLEX_SHAPE_BUFFER_SIZE*task) - - -#define MIDPHASE_WORKUNIT_PAGE_SIZE (16) - -#define MIDPHASE_NUM_WORKUNIT_PAGES 1 -#define MIDPHASE_WORKUNIT_TASK_SIZE (MIDPHASE_WORKUNIT_PAGE_SIZE*MIDPHASE_NUM_WORKUNIT_PAGES) -#define MIDPHASE_NUM_WORKUNITS_PER_PAGE (MIDPHASE_WORKUNIT_PAGE_SIZE / sizeof(SpuGatherAndProcessWorkUnitInput)) -#define MIDPHASE_NUM_WORKUNITS_PER_TASK (MIDPHASE_NUM_WORKUNITS_PER_PAGE*MIDPHASE_NUM_WORKUNIT_PAGES) - - -#endif // SPU_COLLISION_TASK_PROCESS_H - +/* +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. +*/ + +#ifndef SPU_COLLISION_TASK_PROCESS_H +#define SPU_COLLISION_TASK_PROCESS_H + +#include + +#include + +#include "PlatformDefinitions.h" +#include "LinearMath/btAlignedObjectArray.h" +#include "SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h" // for definitions processCollisionTask and createCollisionLocalStoreMemory + +#include "btThreadSupportInterface.h" + + +//#include "SPUAssert.h" +#include + + +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionShapes/btCollisionShape.h" +#include "BulletCollision/CollisionShapes/btConvexShape.h" + +#include + +#include + + +#define DEBUG_SpuCollisionTaskProcess 1 + + +#define CMD_GATHER_AND_PROCESS_PAIRLIST 1 + +class btCollisionObject; +class btPersistentManifold; +class btDispatcher; + + +/////Task Description for SPU collision detection +//struct SpuGatherAndProcessPairsTaskDesc +//{ +// uint64_t inPtr;//m_pairArrayPtr; +// //mutex variable +// uint32_t m_someMutexVariableInMainMemory; +// +// uint64_t m_dispatcher; +// +// uint32_t numOnLastPage; +// +// uint16_t numPages; +// uint16_t taskId; +// +// struct CollisionTask_LocalStoreMemory* m_lsMemory; +//} +// +//#if defined(__CELLOS_LV2__) || defined(USE_LIBSPE2) +//__attribute__ ((aligned (16))) +//#endif +//; + + +///MidphaseWorkUnitInput stores individual primitive versus mesh collision detection input, to be processed by the SPU. +struct SpuGatherAndProcessWorkUnitInput +{ + uint64_t m_pairArrayPtr; + int m_startIndex; + int m_endIndex; +}; + + + + +/// SpuCollisionTaskProcess handles SPU processing of collision pairs. +/// Maintains a set of task buffers. +/// When the task is full, the task is issued for SPUs to process. Contact output goes into btPersistentManifold +/// associated with each task. +/// When PPU issues a task, it will look for completed task buffers +/// PPU will do postprocessing, dependent on workunit output (not likely) +class SpuCollisionTaskProcess +{ + + unsigned char *m_workUnitTaskBuffers; + + + // track task buffers that are being used, and total busy tasks + btAlignedObjectArray m_taskBusy; + btAlignedObjectArray m_spuGatherTaskDesc; + + class btThreadSupportInterface* m_threadInterface; + + unsigned int m_maxNumOutstandingTasks; + + unsigned int m_numBusyTasks; + + // the current task and the current entry to insert a new work unit + unsigned int m_currentTask; + unsigned int m_currentPage; + unsigned int m_currentPageEntry; + +#ifdef DEBUG_SpuCollisionTaskProcess + bool m_initialized; +#endif + void issueTask2(); + //void postProcess(unsigned int taskId, int outputSize); + +public: + SpuCollisionTaskProcess(btThreadSupportInterface* threadInterface, unsigned int maxNumOutstandingTasks); + + ~SpuCollisionTaskProcess(); + + ///call initialize in the beginning of the frame, before addCollisionPairToTask + void initialize2(); + + ///batch up additional work to a current task for SPU processing. When batch is full, it issues the task. + void addWorkToTask(void* pairArrayPtr,int startIndex,int endIndex); + + ///call flush to submit potential outstanding work to SPUs and wait for all involved SPUs to be finished + void flush2(); +}; + + + +#define MIDPHASE_TASK_PTR(task) (&m_workUnitTaskBuffers[0] + MIDPHASE_WORKUNIT_TASK_SIZE*task) +#define MIDPHASE_ENTRY_PTR(task,page,entry) (MIDPHASE_TASK_PTR(task) + MIDPHASE_WORKUNIT_PAGE_SIZE*page + sizeof(SpuGatherAndProcessWorkUnitInput)*entry) +#define MIDPHASE_OUTPUT_PTR(task) (&m_contactOutputBuffers[0] + MIDPHASE_MAX_CONTACT_BUFFER_SIZE*task) +#define MIDPHASE_TREENODES_PTR(task) (&m_complexShapeBuffers[0] + MIDPHASE_COMPLEX_SHAPE_BUFFER_SIZE*task) + + +#define MIDPHASE_WORKUNIT_PAGE_SIZE (16) + +#define MIDPHASE_NUM_WORKUNIT_PAGES 1 +#define MIDPHASE_WORKUNIT_TASK_SIZE (MIDPHASE_WORKUNIT_PAGE_SIZE*MIDPHASE_NUM_WORKUNIT_PAGES) +#define MIDPHASE_NUM_WORKUNITS_PER_PAGE (MIDPHASE_WORKUNIT_PAGE_SIZE / sizeof(SpuGatherAndProcessWorkUnitInput)) +#define MIDPHASE_NUM_WORKUNITS_PER_TASK (MIDPHASE_NUM_WORKUNITS_PER_PAGE*MIDPHASE_NUM_WORKUNIT_PAGES) + + +#endif // SPU_COLLISION_TASK_PROCESS_H + diff --git a/Extras/BulletMultiThreaded/SpuContactManifoldCollisionAlgorithm.cpp b/Extras/BulletMultiThreaded/SpuContactManifoldCollisionAlgorithm.cpp index 0299301f9..a6232cf47 100644 --- a/Extras/BulletMultiThreaded/SpuContactManifoldCollisionAlgorithm.cpp +++ b/Extras/BulletMultiThreaded/SpuContactManifoldCollisionAlgorithm.cpp @@ -55,4 +55,4 @@ SpuContactManifoldCollisionAlgorithm::~SpuContactManifoldCollisionAlgorithm() { if (m_manifoldPtr) m_dispatcher->releaseManifold(m_manifoldPtr); -} \ No newline at end of file +}