310 lines
7.2 KiB
C++
310 lines
7.2 KiB
C++
/*
|
|
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 __CELLOS_LV2__ 1
|
|
|
|
//#define DEBUG_SPU_TASK_SCHEDULING 1
|
|
|
|
#include "SpuLibspe2Support.h"
|
|
#include "Win32ThreadSupport.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>
|
|
|
|
|
|
//#ifdef __CELLOS_LV2__???
|
|
#ifdef USE_WIN32_THREADING
|
|
Win32ThreadSupport gMidphaseSPU(Win32ThreadSupport::Win32ThreadConstructionInfo("collision",
|
|
processCollisionTask,
|
|
createCollisionLocalStoreMemory,
|
|
MIDPHASE_NUM_WORKUNIT_TASKS));
|
|
#elif defined(USE_LIBSPE2)
|
|
SpuLibspe2Support gMidphaseSPU(SPU_ELF_COLLISION_DETECTION,MIDPHASE_NUM_WORKUNIT_TASKS);
|
|
#endif
|
|
|
|
#ifdef __CELLOS_LV2__
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
SpuGatherAndProcessPairsTaskDesc g_spuGatherTaskDesc[MIDPHASE_NUM_WORKUNIT_TASKS];
|
|
|
|
|
|
|
|
|
|
SpuCollisionTaskProcess::SpuCollisionTaskProcess()
|
|
{
|
|
m_workUnitTaskBuffers = (unsigned char *)0;
|
|
|
|
|
|
for (int i = 0; i < MIDPHASE_NUM_WORKUNIT_TASKS; i++)
|
|
{
|
|
m_taskBusy[i] = false;
|
|
}
|
|
m_numBusyTasks = 0;
|
|
m_currentTask = 0;
|
|
m_currentPage = 0;
|
|
m_currentPageEntry = 0;
|
|
|
|
#ifdef DEBUG_SpuCollisionTaskProcess
|
|
m_initialized = false;
|
|
#endif
|
|
|
|
#ifdef __CELLOS_LV2__
|
|
// adding SPURS support.
|
|
gMidphaseSPU.startSPU();
|
|
|
|
#endif
|
|
|
|
//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;
|
|
}
|
|
|
|
#ifdef __CELLOS_LV2__
|
|
|
|
// Consolidating SPU code
|
|
gMidphaseSPU.stopSPU();
|
|
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
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*MIDPHASE_NUM_WORKUNIT_TASKS);
|
|
}
|
|
|
|
for (int i = 0; i < MIDPHASE_NUM_WORKUNIT_TASKS; 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 = g_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;
|
|
}
|
|
|
|
|
|
|
|
gMidphaseSPU.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 >= MIDPHASE_NUM_WORKUNIT_TASKS)
|
|
{
|
|
unsigned int taskId;
|
|
unsigned int outputSize;
|
|
|
|
gMidphaseSPU.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 < MIDPHASE_NUM_WORKUNIT_TASKS; 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 < MIDPHASE_NUM_WORKUNIT_TASKS; 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.
|
|
gMidphaseSPU.waitForResponse(&taskId, &outputSize);
|
|
}
|
|
|
|
//printf("PPU: flushing, received event: %u %d\n", taskId, outputSize);
|
|
|
|
//postProcess(taskId, outputSize);
|
|
|
|
m_taskBusy[taskId] = false;
|
|
|
|
m_numBusyTasks--;
|
|
}
|
|
|
|
|
|
}
|