Added libspe2 parallel Cell SPE support contribution by IBM Germany 'Extreme Blue' project:

Thanks to Benjamin Hoeferlin, Minh Cuong Tran,Martina Huellmann,Frederick Roth.
This commit is contained in:
ejcoumans
2007-09-26 23:37:25 +00:00
parent dae8b658da
commit 5ebab3e59b
4 changed files with 498 additions and 467 deletions

View File

@@ -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 <malloc.h>
#define memalign(alignment, size) malloc(size);
#include <string.h> //memcpy
#define USE_WIN32_THREADING 1
#else
#if defined (__CELLOS_LV2__)
///Playstation 3 Cell SDK
#include <spu_printf.h>
#else
//non-windows systems
#define USE_PTHREADS 1
#endif //__CELLOS_LV2__
#include <stdint.h>
#include <stdlib.h>
#include <string.h> //for memcpy
#endif
#endif //TYPE_DEFINITIONS_H
#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 <malloc.h>
#define memalign(alignment, size) malloc(size);
#include <string.h> //memcpy
#define USE_WIN32_THREADING 1
#include <stdio.h>
#define spu_printf printf
#else
#include <stdint.h>
#include <stdlib.h>
#include <string.h> //for memcpy
#if defined (__CELLOS_LV2__)
// Playstation 3 Cell SDK
#include <spu_printf.h>
#else
// posix system
#define USE_PTHREADS
#ifdef USE_LIBSPE2
#include <stdio.h>
#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

View File

@@ -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 <string.h>
//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 <stdio.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)
{
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<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, (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<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;
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<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, (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<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;
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--;
}
}

View File

@@ -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 <assert.h>
#include <LinearMath/btScalar.h>
#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<bool> m_taskBusy;
btAlignedObjectArray<SpuGatherAndProcessPairsTaskDesc> 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 <assert.h>
#include <LinearMath/btScalar.h>
#include "PlatformDefinitions.h"
#include "LinearMath/btAlignedObjectArray.h"
#include "SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h" // for definitions processCollisionTask and createCollisionLocalStoreMemory
#include "btThreadSupportInterface.h"
//#include "SPUAssert.h"
#include <string.h>
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/CollisionShapes/btCollisionShape.h"
#include "BulletCollision/CollisionShapes/btConvexShape.h"
#include <LinearMath/btAlignedAllocator.h>
#include <stdio.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;
//}
//
//#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<bool> m_taskBusy;
btAlignedObjectArray<SpuGatherAndProcessPairsTaskDesc> 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

View File

@@ -55,4 +55,4 @@ SpuContactManifoldCollisionAlgorithm::~SpuContactManifoldCollisionAlgorithm()
{
if (m_manifoldPtr)
m_dispatcher->releaseManifold(m_manifoldPtr);
}
}