use relative path, to make it easier to include btBulletWorldImporter, #include "../BulletFileLoader/btBulletFile.h"

Create a separate library for MiniCL (a rudimentary OpenCL wrapper to run kernels on multi-core CPU using the default C++ compiler, using Win32 Threads or Posix)
tweak vectormath/vmInclude.h for PS3 platforms
fix warning in btKinematicCharacterController
This commit is contained in:
erwin.coumans
2010-07-21 21:33:40 +00:00
parent 442959d457
commit 7684c1b92d
14 changed files with 60 additions and 29 deletions

View File

@@ -65,16 +65,6 @@ ADD_LIBRARY(BulletMultiThreaded
btGpuUtilsSharedCode.h
btGpuUtilsSharedDefs.h
#MiniCL provides a small subset of OpenCL
MiniCL.cpp
MiniCLTaskScheduler.cpp
MiniCLTaskScheduler.h
MiniCLTask/MiniCLTask.cpp
MiniCLTask/MiniCLTask.h
../MiniCL/cl.h
../MiniCL/cl_gl.h
../MiniCL/cl_platform.h
../MiniCL/cl_MiniCL_Defs.h
)
#for now, only Direct 11 (Direct Compute)

View File

@@ -1,575 +0,0 @@
/*
Copyright (C) 2010 Sony Computer Entertainment Inc.
All rights reserved.
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.
*/
#include "MiniCL/cl.h"
#define __PHYSICS_COMMON_H__ 1
#ifdef _WIN32
#include "BulletMultiThreaded/Win32ThreadSupport.h"
#endif
#include "BulletMultiThreaded/SequentialThreadSupport.h"
#include "MiniCLTaskScheduler.h"
#include "MiniCLTask/MiniCLTask.h"
#include "LinearMath/btMinMax.h"
#include <stdio.h>
//#define DEBUG_MINICL_KERNELS 1
static char* spPlatformID = "MiniCL, SCEA";
CL_API_ENTRY cl_int CL_API_CALL clGetPlatformIDs(
cl_uint num_entries,
cl_platform_id * platforms,
cl_uint * num_platforms ) CL_API_SUFFIX__VERSION_1_0
{
if(platforms != NULL)
{
if(num_entries <= 0)
{
return CL_INVALID_VALUE;
}
*((char**)platforms) = spPlatformID;
}
if(num_platforms != NULL)
{
*num_platforms = 1;
}
return CL_SUCCESS;
}
CL_API_ENTRY cl_int CL_API_CALL clGetPlatformInfo(
cl_platform_id platform,
cl_platform_info param_name,
size_t param_value_size,
void * param_value,
size_t * param_value_size_ret) CL_API_SUFFIX__VERSION_1_0
{
char* pId = (char*)platform;
if(strcmp(pId, spPlatformID))
{
return CL_INVALID_PLATFORM;
}
switch(param_name)
{
case CL_PLATFORM_VENDOR :
if(param_value_size < (strlen(spPlatformID) + 1))
{
return CL_INVALID_VALUE;
}
strcpy((char*)param_value, spPlatformID);
if(param_value_size_ret != NULL)
{
*param_value_size_ret = strlen(spPlatformID) + 1;
}
break;
default :
return CL_INVALID_VALUE;
}
return CL_SUCCESS;
}
CL_API_ENTRY cl_int CL_API_CALL clGetDeviceInfo(
cl_device_id device ,
cl_device_info param_name ,
size_t param_value_size ,
void * param_value ,
size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0
{
switch (param_name)
{
case CL_DEVICE_NAME:
{
char deviceName[] = "CPU";
unsigned int nameLen = strlen(deviceName)+1;
btAssert(param_value_size>strlen(deviceName));
if (nameLen < param_value_size)
{
const char* cpuName = "CPU";
sprintf((char*)param_value,"%s",cpuName);
} else
{
printf("error: param_value_size should be at least %d, but it is %d\n",nameLen,param_value_size);
}
break;
}
case CL_DEVICE_TYPE:
{
if (param_value_size>=sizeof(cl_device_type))
{
cl_device_type* deviceType = (cl_device_type*)param_value;
*deviceType = CL_DEVICE_TYPE_CPU;
} else
{
printf("error: param_value_size should be at least %d\n",sizeof(cl_device_type));
}
break;
}
case CL_DEVICE_MAX_COMPUTE_UNITS:
{
if (param_value_size>=sizeof(cl_uint))
{
cl_uint* numUnits = (cl_uint*)param_value;
*numUnits= 4;
} else
{
printf("error: param_value_size should be at least %d\n",sizeof(cl_uint));
}
break;
}
case CL_DEVICE_MAX_WORK_ITEM_SIZES:
{
size_t workitem_size[3];
if (param_value_size>=sizeof(workitem_size))
{
size_t* workItemSize = (size_t*)param_value;
workItemSize[0] = 64;
workItemSize[1] = 24;
workItemSize[2] = 16;
} else
{
printf("error: param_value_size should be at least %d\n",sizeof(cl_uint));
}
break;
}
case CL_DEVICE_MAX_CLOCK_FREQUENCY:
{
cl_uint* clock_frequency = (cl_uint*)param_value;
*clock_frequency = 3*1024;
break;
}
default:
{
printf("error: unsupported param_name:%d\n",param_name);
}
}
return 0;
}
CL_API_ENTRY cl_int CL_API_CALL clReleaseMemObject(cl_mem /* memobj */) CL_API_SUFFIX__VERSION_1_0
{
return 0;
}
CL_API_ENTRY cl_int CL_API_CALL clReleaseCommandQueue(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0
{
return 0;
}
CL_API_ENTRY cl_int CL_API_CALL clReleaseProgram(cl_program /* program */) CL_API_SUFFIX__VERSION_1_0
{
return 0;
}
CL_API_ENTRY cl_int CL_API_CALL clReleaseKernel(cl_kernel /* kernel */) CL_API_SUFFIX__VERSION_1_0
{
return 0;
}
// Enqueued Commands APIs
CL_API_ENTRY cl_int CL_API_CALL clEnqueueReadBuffer(cl_command_queue command_queue ,
cl_mem buffer ,
cl_bool /* blocking_read */,
size_t offset ,
size_t cb ,
void * ptr ,
cl_uint /* num_events_in_wait_list */,
const cl_event * /* event_wait_list */,
cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0
{
MiniCLTaskScheduler* scheduler = (MiniCLTaskScheduler*) command_queue;
///wait for all work items to be completed
scheduler->flush();
memcpy(ptr,(char*)buffer + offset,cb);
return 0;
}
CL_API_ENTRY cl_int clGetProgramBuildInfo(cl_program /* program */,
cl_device_id /* device */,
cl_program_build_info /* param_name */,
size_t /* param_value_size */,
void * /* param_value */,
size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0
{
return 0;
}
// Program Object APIs
CL_API_ENTRY cl_program
clCreateProgramWithSource(cl_context context ,
cl_uint /* count */,
const char ** /* strings */,
const size_t * /* lengths */,
cl_int * errcode_ret ) CL_API_SUFFIX__VERSION_1_0
{
*errcode_ret = CL_SUCCESS;
return (cl_program)context;
}
CL_API_ENTRY cl_int CL_API_CALL clEnqueueWriteBuffer(cl_command_queue command_queue ,
cl_mem buffer ,
cl_bool /* blocking_read */,
size_t offset,
size_t cb ,
const void * ptr ,
cl_uint /* num_events_in_wait_list */,
const cl_event * /* event_wait_list */,
cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0
{
MiniCLTaskScheduler* scheduler = (MiniCLTaskScheduler*) command_queue;
///wait for all work items to be completed
scheduler->flush();
memcpy((char*)buffer + offset, ptr,cb);
return 0;
}
CL_API_ENTRY cl_int CL_API_CALL clFlush(cl_command_queue command_queue)
{
MiniCLTaskScheduler* scheduler = (MiniCLTaskScheduler*) command_queue;
///wait for all work items to be completed
scheduler->flush();
return 0;
}
CL_API_ENTRY cl_int CL_API_CALL clEnqueueNDRangeKernel(cl_command_queue /* command_queue */,
cl_kernel clKernel ,
cl_uint work_dim ,
const size_t * /* global_work_offset */,
const size_t * global_work_size ,
const size_t * /* local_work_size */,
cl_uint /* num_events_in_wait_list */,
const cl_event * /* event_wait_list */,
cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0
{
MiniCLKernel* kernel = (MiniCLKernel*) clKernel;
for (unsigned int ii=0;ii<work_dim;ii++)
{
int maxTask = kernel->m_scheduler->getMaxNumOutstandingTasks();
int numWorkItems = global_work_size[ii];
// //at minimum 64 work items per task
// int numWorkItemsPerTask = btMax(64,numWorkItems / maxTask);
int numWorkItemsPerTask = numWorkItems / maxTask;
if (!numWorkItemsPerTask) numWorkItemsPerTask = 1;
for (int t=0;t<numWorkItems;)
{
//Performance Hint: tweak this number during benchmarking
int endIndex = (t+numWorkItemsPerTask) < numWorkItems ? t+numWorkItemsPerTask : numWorkItems;
kernel->m_scheduler->issueTask(t, endIndex, kernel);
t = endIndex;
}
}
/*
void* bla = 0;
scheduler->issueTask(bla,2,3);
scheduler->flush();
*/
return 0;
}
#define LOCAL_BUF_SIZE 32768
static int sLocalMemBuf[LOCAL_BUF_SIZE * 4 + 16];
static int* spLocalBufCurr = NULL;
static int sLocalBufUsed = LOCAL_BUF_SIZE; // so it will be reset at the first call
static void* localBufMalloc(int size)
{
int size16 = (size + 15) >> 4; // in 16-byte units
if((sLocalBufUsed + size16) > LOCAL_BUF_SIZE)
{ // reset
spLocalBufCurr = sLocalMemBuf;
while((unsigned long)spLocalBufCurr & 0x0F) spLocalBufCurr++; // align to 16 bytes
sLocalBufUsed = 0;
}
void* ret = spLocalBufCurr;
spLocalBufCurr += size16 * 4;
sLocalBufUsed += size;
return ret;
}
CL_API_ENTRY cl_int CL_API_CALL clSetKernelArg(cl_kernel clKernel ,
cl_uint arg_index ,
size_t arg_size ,
const void * arg_value ) CL_API_SUFFIX__VERSION_1_0
{
MiniCLKernel* kernel = (MiniCLKernel* ) clKernel;
btAssert(arg_size <= MINICL_MAX_ARGLENGTH);
if (arg_index>MINI_CL_MAX_ARG)
{
printf("error: clSetKernelArg arg_index (%d) exceeds %d\n",arg_index,MINI_CL_MAX_ARG);
} else
{
if (arg_size>MINICL_MAX_ARGLENGTH)
//if (arg_size != MINICL_MAX_ARGLENGTH)
{
printf("error: clSetKernelArg argdata too large: %d (maximum is %d)\n",arg_size,MINICL_MAX_ARGLENGTH);
}
else
{
if(arg_value == NULL)
{ // this is only for __local memory qualifier
void* ptr = localBufMalloc(arg_size);
kernel->m_argData[arg_index] = ptr;
}
else
{
memcpy(&(kernel->m_argData[arg_index]), arg_value, arg_size);
}
kernel->m_argSizes[arg_index] = arg_size;
if(arg_index >= kernel->m_numArgs)
{
kernel->m_numArgs = arg_index + 1;
kernel->updateLauncher();
}
}
}
return 0;
}
// Kernel Object APIs
CL_API_ENTRY cl_kernel CL_API_CALL clCreateKernel(cl_program program ,
const char * kernel_name ,
cl_int * errcode_ret ) CL_API_SUFFIX__VERSION_1_0
{
MiniCLTaskScheduler* scheduler = (MiniCLTaskScheduler*) program;
MiniCLKernel* kernel = new MiniCLKernel();
int nameLen = strlen(kernel_name);
if(nameLen >= MINI_CL_MAX_KERNEL_NAME)
{
*errcode_ret = CL_INVALID_KERNEL_NAME;
return NULL;
}
strcpy(kernel->m_name, kernel_name);
kernel->m_numArgs = 0;
//kernel->m_kernelProgramCommandId = scheduler->findProgramCommandIdByName(kernel_name);
//if (kernel->m_kernelProgramCommandId>=0)
//{
// *errcode_ret = CL_SUCCESS;
//} else
//{
// *errcode_ret = CL_INVALID_KERNEL_NAME;
//}
kernel->m_scheduler = scheduler;
if(kernel->registerSelf() == NULL)
{
*errcode_ret = CL_INVALID_KERNEL_NAME;
return NULL;
}
else
{
*errcode_ret = CL_SUCCESS;
}
return (cl_kernel)kernel;
}
CL_API_ENTRY cl_int CL_API_CALL clBuildProgram(cl_program /* program */,
cl_uint /* num_devices */,
const cl_device_id * /* device_list */,
const char * /* options */,
void (*pfn_notify)(cl_program /* program */, void * /* user_data */),
void * /* user_data */) CL_API_SUFFIX__VERSION_1_0
{
return CL_SUCCESS;
}
CL_API_ENTRY cl_program CL_API_CALL clCreateProgramWithBinary(cl_context context ,
cl_uint /* num_devices */,
const cl_device_id * /* device_list */,
const size_t * /* lengths */,
const unsigned char ** /* binaries */,
cl_int * /* binary_status */,
cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0
{
return (cl_program)context;
}
// Memory Object APIs
CL_API_ENTRY cl_mem CL_API_CALL clCreateBuffer(cl_context /* context */,
cl_mem_flags flags ,
size_t size,
void * host_ptr ,
cl_int * errcode_ret ) CL_API_SUFFIX__VERSION_1_0
{
cl_mem buf = (cl_mem)malloc(size);
if ((flags&CL_MEM_COPY_HOST_PTR) && host_ptr)
{
memcpy(buf,host_ptr,size);
}
*errcode_ret = 0;
return buf;
}
// Command Queue APIs
CL_API_ENTRY cl_command_queue CL_API_CALL clCreateCommandQueue(cl_context context ,
cl_device_id /* device */,
cl_command_queue_properties /* properties */,
cl_int * errcode_ret ) CL_API_SUFFIX__VERSION_1_0
{
*errcode_ret = 0;
return (cl_command_queue) context;
}
extern CL_API_ENTRY cl_int CL_API_CALL clGetContextInfo(cl_context /* context */,
cl_context_info param_name ,
size_t param_value_size ,
void * param_value,
size_t * param_value_size_ret ) CL_API_SUFFIX__VERSION_1_0
{
switch (param_name)
{
case CL_CONTEXT_DEVICES:
{
if (!param_value_size)
{
*param_value_size_ret = 13;
} else
{
const char* testName = "MiniCL_Test.";
sprintf((char*)param_value,"%s",testName);
}
break;
};
default:
{
printf("unsupported\n");
}
}
return 0;
}
CL_API_ENTRY cl_context CL_API_CALL clCreateContextFromType(cl_context_properties * /* properties */,
cl_device_type /* device_type */,
void (*pfn_notify)(const char *, const void *, size_t, void *) /* pfn_notify */,
void * /* user_data */,
cl_int * errcode_ret ) CL_API_SUFFIX__VERSION_1_0
{
int maxNumOutstandingTasks = 4;
// int maxNumOutstandingTasks = 2;
// int maxNumOutstandingTasks = 1;
gMiniCLNumOutstandingTasks = maxNumOutstandingTasks;
const int maxNumOfThreadSupports = 8;
static int sUniqueThreadSupportIndex = 0;
static char* sUniqueThreadSupportName[maxNumOfThreadSupports] =
{
"MiniCL_0", "MiniCL_1", "MiniCL_2", "MiniCL_3", "MiniCL_4", "MiniCL_5", "MiniCL_6", "MiniCL_7"
};
#ifdef DEBUG_MINICL_KERNELS
SequentialThreadSupport::SequentialThreadConstructionInfo stc("MiniCL",processMiniCLTask,createMiniCLLocalStoreMemory);
SequentialThreadSupport* threadSupport = new SequentialThreadSupport(stc);
#else
#if _WIN32
btAssert(sUniqueThreadSupportIndex < maxNumOfThreadSupports);
Win32ThreadSupport* threadSupport = new Win32ThreadSupport(Win32ThreadSupport::Win32ThreadConstructionInfo(
// "MiniCL",
sUniqueThreadSupportName[sUniqueThreadSupportIndex++],
processMiniCLTask, //processCollisionTask,
createMiniCLLocalStoreMemory,//createCollisionLocalStoreMemory,
maxNumOutstandingTasks));
#else
///todo: add posix thread support for other platforms
SequentialThreadSupport::SequentialThreadConstructionInfo stc("MiniCL",processMiniCLTask,createMiniCLLocalStoreMemory);
SequentialThreadSupport* threadSupport = new SequentialThreadSupport(stc);
#endif
#endif //DEBUG_MINICL_KERNELS
MiniCLTaskScheduler* scheduler = new MiniCLTaskScheduler(threadSupport,maxNumOutstandingTasks);
*errcode_ret = 0;
return (cl_context)scheduler;
}
CL_API_ENTRY cl_int CL_API_CALL clReleaseContext(cl_context context ) CL_API_SUFFIX__VERSION_1_0
{
MiniCLTaskScheduler* scheduler = (MiniCLTaskScheduler*) context;
btThreadSupportInterface* threadSupport = scheduler->getThreadSupportInterface();
delete scheduler;
delete threadSupport;
return 0;
}
extern CL_API_ENTRY cl_int CL_API_CALL
clFinish(cl_command_queue command_queue ) CL_API_SUFFIX__VERSION_1_0
{
MiniCLTaskScheduler* scheduler = (MiniCLTaskScheduler*) command_queue;
///wait for all work items to be completed
scheduler->flush();
return CL_SUCCESS;
}
extern CL_API_ENTRY cl_int CL_API_CALL
clGetKernelWorkGroupInfo(cl_kernel kernel ,
cl_device_id /* device */,
cl_kernel_work_group_info wgi/* param_name */,
size_t sz /* param_value_size */,
void * ptr /* param_value */,
size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0
{
if((wgi == CL_KERNEL_WORK_GROUP_SIZE)
&&(sz == sizeof(size_t))
&&(ptr != NULL))
{
MiniCLKernel* miniCLKernel = (MiniCLKernel*)kernel;
MiniCLTaskScheduler* scheduler = miniCLKernel->m_scheduler;
*((size_t*)ptr) = scheduler->getMaxNumOutstandingTasks();
return CL_SUCCESS;
}
else
{
return CL_INVALID_VALUE;
}
}

View File

@@ -1,74 +0,0 @@
/*
Bullet Continuous Collision Detection and Physics Library, Copyright (c) 2007 Erwin Coumans
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.
*/
#include "MiniCLTask.h"
#include "BulletMultiThreaded/PlatformDefinitions.h"
#include "BulletMultiThreaded/SpuFakeDma.h"
#include "LinearMath/btMinMax.h"
#include "MiniCLTask.h"
#include "BulletMultiThreaded/MiniCLTaskScheduler.h"
#ifdef __SPU__
#include <spu_printf.h>
#else
#include <stdio.h>
#define spu_printf printf
#endif
int gMiniCLNumOutstandingTasks = 0;
struct MiniCLTask_LocalStoreMemory
{
};
//-- MAIN METHOD
void processMiniCLTask(void* userPtr, void* lsMemory)
{
// BT_PROFILE("processSampleTask");
MiniCLTask_LocalStoreMemory* localMemory = (MiniCLTask_LocalStoreMemory*)lsMemory;
MiniCLTaskDesc* taskDescPtr = (MiniCLTaskDesc*)userPtr;
MiniCLTaskDesc& taskDesc = *taskDescPtr;
for (unsigned int i=taskDesc.m_firstWorkUnit;i<taskDesc.m_lastWorkUnit;i++)
{
taskDesc.m_kernel->m_launcher(&taskDesc, i);
}
// printf("Compute Unit[%d] executed kernel %d work items [%d..%d)\n",taskDesc.m_taskId,taskDesc.m_kernelProgramId,taskDesc.m_firstWorkUnit,taskDesc.m_lastWorkUnit);
}
#if defined(__CELLOS_LV2__) || defined (LIBSPE2)
ATTRIBUTE_ALIGNED16(MiniCLTask_LocalStoreMemory gLocalStoreMemory);
void* createMiniCLLocalStoreMemory()
{
return &gLocalStoreMemory;
}
#else
void* createMiniCLLocalStoreMemory()
{
return new MiniCLTask_LocalStoreMemory;
};
#endif

View File

@@ -1,62 +0,0 @@
/*
Bullet Continuous Collision Detection and Physics Library, Copyright (c) 2007 Erwin Coumans
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 MINICL__TASK_H
#define MINICL__TASK_H
#include "BulletMultiThreaded/PlatformDefinitions.h"
#include "LinearMath/btScalar.h"
#include "LinearMath/btAlignedAllocator.h"
#define MINICL_MAX_ARGLENGTH (sizeof(void*))
#define MINI_CL_MAX_ARG 16
#define MINI_CL_MAX_KERNEL_NAME 256
struct MiniCLKernel;
ATTRIBUTE_ALIGNED16(struct) MiniCLTaskDesc
{
BT_DECLARE_ALIGNED_ALLOCATOR();
MiniCLTaskDesc()
{
for (int i=0;i<MINI_CL_MAX_ARG;i++)
{
m_argSizes[i]=0;
}
}
uint32_t m_taskId;
uint32_t m_firstWorkUnit;
uint32_t m_lastWorkUnit;
MiniCLKernel* m_kernel;
void* m_argData[MINI_CL_MAX_ARG];
int m_argSizes[MINI_CL_MAX_ARG];
};
extern "C" int gMiniCLNumOutstandingTasks;
void processMiniCLTask(void* userPtr, void* lsMemory);
void* createMiniCLLocalStoreMemory();
#endif //MINICL__TASK_H

View File

@@ -1,519 +0,0 @@
/*
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 __BT_SKIP_UINT64_H 1
#define USE_SAMPLE_PROCESS 1
#ifdef USE_SAMPLE_PROCESS
#include "MiniCLTaskScheduler.h"
#include <stdio.h>
#ifdef __SPU__
void SampleThreadFunc(void* userPtr,void* lsMemory)
{
//do nothing
printf("hello world\n");
}
void* SamplelsMemoryFunc()
{
//don't create local store memory, just return 0
return 0;
}
#else
#include "BulletMultiThreaded/btThreadSupportInterface.h"
//# include "SPUAssert.h"
#include <string.h>
#include "MiniCL/cl_platform.h"
extern "C" {
extern char SPU_SAMPLE_ELF_SYMBOL[];
}
MiniCLTaskScheduler::MiniCLTaskScheduler(btThreadSupportInterface* threadInterface, int maxNumOutstandingTasks)
:m_threadInterface(threadInterface),
m_maxNumOutstandingTasks(maxNumOutstandingTasks)
{
m_taskBusy.resize(m_maxNumOutstandingTasks);
m_spuSampleTaskDesc.resize(m_maxNumOutstandingTasks);
m_kernels.resize(0);
for (int i = 0; i < m_maxNumOutstandingTasks; i++)
{
m_taskBusy[i] = false;
}
m_numBusyTasks = 0;
m_currentTask = 0;
m_initialized = false;
m_threadInterface->startSPU();
}
MiniCLTaskScheduler::~MiniCLTaskScheduler()
{
m_threadInterface->stopSPU();
}
void MiniCLTaskScheduler::initialize()
{
#ifdef DEBUG_SPU_TASK_SCHEDULING
printf("MiniCLTaskScheduler::initialize()\n");
#endif //DEBUG_SPU_TASK_SCHEDULING
for (int i = 0; i < m_maxNumOutstandingTasks; i++)
{
m_taskBusy[i] = false;
}
m_numBusyTasks = 0;
m_currentTask = 0;
m_initialized = true;
}
void MiniCLTaskScheduler::issueTask(int firstWorkUnit, int lastWorkUnit, MiniCLKernel* kernel)
{
#ifdef DEBUG_SPU_TASK_SCHEDULING
printf("MiniCLTaskScheduler::issueTask (m_currentTask= %d\)n", m_currentTask);
#endif //DEBUG_SPU_TASK_SCHEDULING
m_taskBusy[m_currentTask] = true;
m_numBusyTasks++;
MiniCLTaskDesc& taskDesc = m_spuSampleTaskDesc[m_currentTask];
{
// send task description in event message
taskDesc.m_firstWorkUnit = firstWorkUnit;
taskDesc.m_lastWorkUnit = lastWorkUnit;
taskDesc.m_kernel = kernel;
//some bookkeeping to recognize finished tasks
taskDesc.m_taskId = m_currentTask;
// for (int i=0;i<MINI_CL_MAX_ARG;i++)
for (unsigned int i=0; i < kernel->m_numArgs; i++)
{
taskDesc.m_argSizes[i] = kernel->m_argSizes[i];
if (taskDesc.m_argSizes[i])
{
taskDesc.m_argData[i] = kernel->m_argData[i];
// memcpy(&taskDesc.m_argData[i],&argData[MINICL_MAX_ARGLENGTH*i],taskDesc.m_argSizes[i]);
}
}
}
m_threadInterface->sendRequest(1, (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<m_maxNumOutstandingTasks;i++)
{
if (m_taskBusy[i])
{
taskId = i;
break;
}
}
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--;
}
// find new task buffer
for (int i = 0; i < m_maxNumOutstandingTasks; i++)
{
if (!m_taskBusy[i])
{
m_currentTask = i;
break;
}
}
}
///Optional PPU-size post processing for each task
void MiniCLTaskScheduler::postProcess(int taskId, int outputSize)
{
}
void MiniCLTaskScheduler::flush()
{
#ifdef DEBUG_SPU_TASK_SCHEDULING
printf("\nSpuCollisionTaskProcess::flush()\n");
#endif //DEBUG_SPU_TASK_SCHEDULING
// all tasks are issued, wait for all tasks to be complete
while(m_numBusyTasks > 0)
{
// Consolidating SPU code
unsigned int taskId;
unsigned int outputSize;
for (int i=0;i<m_maxNumOutstandingTasks;i++)
{
if (m_taskBusy[i])
{
taskId = i;
break;
}
}
{
m_threadInterface->waitForResponse(&taskId, &outputSize);
}
//printf("PPU: flushing, received event: %u %d\n", taskId, outputSize);
postProcess(taskId, outputSize);
m_taskBusy[taskId] = false;
m_numBusyTasks--;
}
}
typedef void (*MiniCLKernelLauncher0)(int);
typedef void (*MiniCLKernelLauncher1)(void*, int);
typedef void (*MiniCLKernelLauncher2)(void*, void*, int);
typedef void (*MiniCLKernelLauncher3)(void*, void*, void*, int);
typedef void (*MiniCLKernelLauncher4)(void*, void*, void*, void*, int);
typedef void (*MiniCLKernelLauncher5)(void*, void*, void*, void*, void*, int);
typedef void (*MiniCLKernelLauncher6)(void*, void*, void*, void*, void*, void*, int);
typedef void (*MiniCLKernelLauncher7)(void*, void*, void*, void*, void*, void*, void*, int);
typedef void (*MiniCLKernelLauncher8)(void*, void*, void*, void*, void*, void*, void*, void*, int);
typedef void (*MiniCLKernelLauncher9)(void*, void*, void*, void*, void*, void*, void*, void*, void*, int);
typedef void (*MiniCLKernelLauncher10)(void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, int);
typedef void (*MiniCLKernelLauncher11)(void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, int);
typedef void (*MiniCLKernelLauncher12)(void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, int);
typedef void (*MiniCLKernelLauncher13)(void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, int);
typedef void (*MiniCLKernelLauncher14)(void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, int);
typedef void (*MiniCLKernelLauncher15)(void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, int);
typedef void (*MiniCLKernelLauncher16)(void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, int);
static void kernelLauncher0(MiniCLTaskDesc* taskDesc, int guid)
{
((MiniCLKernelLauncher0)(taskDesc->m_kernel->m_launcher))(guid);
}
static void kernelLauncher1(MiniCLTaskDesc* taskDesc, int guid)
{
((MiniCLKernelLauncher1)(taskDesc->m_kernel->m_pCode))( taskDesc->m_argData[0],
guid);
}
static void kernelLauncher2(MiniCLTaskDesc* taskDesc, int guid)
{
((MiniCLKernelLauncher2)(taskDesc->m_kernel->m_pCode))( taskDesc->m_argData[0],
taskDesc->m_argData[1],
guid);
}
static void kernelLauncher3(MiniCLTaskDesc* taskDesc, int guid)
{
((MiniCLKernelLauncher3)(taskDesc->m_kernel->m_pCode))( taskDesc->m_argData[0],
taskDesc->m_argData[1],
taskDesc->m_argData[2],
guid);
}
static void kernelLauncher4(MiniCLTaskDesc* taskDesc, int guid)
{
((MiniCLKernelLauncher4)(taskDesc->m_kernel->m_pCode))( taskDesc->m_argData[0],
taskDesc->m_argData[1],
taskDesc->m_argData[2],
taskDesc->m_argData[3],
guid);
}
static void kernelLauncher5(MiniCLTaskDesc* taskDesc, int guid)
{
((MiniCLKernelLauncher5)(taskDesc->m_kernel->m_pCode))( taskDesc->m_argData[0],
taskDesc->m_argData[1],
taskDesc->m_argData[2],
taskDesc->m_argData[3],
taskDesc->m_argData[4],
guid);
}
static void kernelLauncher6(MiniCLTaskDesc* taskDesc, int guid)
{
((MiniCLKernelLauncher6)(taskDesc->m_kernel->m_pCode))( taskDesc->m_argData[0],
taskDesc->m_argData[1],
taskDesc->m_argData[2],
taskDesc->m_argData[3],
taskDesc->m_argData[4],
taskDesc->m_argData[5],
guid);
}
static void kernelLauncher7(MiniCLTaskDesc* taskDesc, int guid)
{
((MiniCLKernelLauncher7)(taskDesc->m_kernel->m_pCode))( taskDesc->m_argData[0],
taskDesc->m_argData[1],
taskDesc->m_argData[2],
taskDesc->m_argData[3],
taskDesc->m_argData[4],
taskDesc->m_argData[5],
taskDesc->m_argData[6],
guid);
}
static void kernelLauncher8(MiniCLTaskDesc* taskDesc, int guid)
{
((MiniCLKernelLauncher8)(taskDesc->m_kernel->m_pCode))( taskDesc->m_argData[0],
taskDesc->m_argData[1],
taskDesc->m_argData[2],
taskDesc->m_argData[3],
taskDesc->m_argData[4],
taskDesc->m_argData[5],
taskDesc->m_argData[6],
taskDesc->m_argData[7],
guid);
}
static void kernelLauncher9(MiniCLTaskDesc* taskDesc, int guid)
{
((MiniCLKernelLauncher9)(taskDesc->m_kernel->m_pCode))( taskDesc->m_argData[0],
taskDesc->m_argData[1],
taskDesc->m_argData[2],
taskDesc->m_argData[3],
taskDesc->m_argData[4],
taskDesc->m_argData[5],
taskDesc->m_argData[6],
taskDesc->m_argData[7],
taskDesc->m_argData[8],
guid);
}
static void kernelLauncher10(MiniCLTaskDesc* taskDesc, int guid)
{
((MiniCLKernelLauncher10)(taskDesc->m_kernel->m_pCode))(taskDesc->m_argData[0],
taskDesc->m_argData[1],
taskDesc->m_argData[2],
taskDesc->m_argData[3],
taskDesc->m_argData[4],
taskDesc->m_argData[5],
taskDesc->m_argData[6],
taskDesc->m_argData[7],
taskDesc->m_argData[8],
taskDesc->m_argData[9],
guid);
}
static void kernelLauncher11(MiniCLTaskDesc* taskDesc, int guid)
{
((MiniCLKernelLauncher11)(taskDesc->m_kernel->m_pCode))(taskDesc->m_argData[0],
taskDesc->m_argData[1],
taskDesc->m_argData[2],
taskDesc->m_argData[3],
taskDesc->m_argData[4],
taskDesc->m_argData[5],
taskDesc->m_argData[6],
taskDesc->m_argData[7],
taskDesc->m_argData[8],
taskDesc->m_argData[9],
taskDesc->m_argData[10],
guid);
}
static void kernelLauncher12(MiniCLTaskDesc* taskDesc, int guid)
{
((MiniCLKernelLauncher12)(taskDesc->m_kernel->m_pCode))(taskDesc->m_argData[0],
taskDesc->m_argData[1],
taskDesc->m_argData[2],
taskDesc->m_argData[3],
taskDesc->m_argData[4],
taskDesc->m_argData[5],
taskDesc->m_argData[6],
taskDesc->m_argData[7],
taskDesc->m_argData[8],
taskDesc->m_argData[9],
taskDesc->m_argData[10],
taskDesc->m_argData[11],
guid);
}
static void kernelLauncher13(MiniCLTaskDesc* taskDesc, int guid)
{
((MiniCLKernelLauncher13)(taskDesc->m_kernel->m_pCode))(taskDesc->m_argData[0],
taskDesc->m_argData[1],
taskDesc->m_argData[2],
taskDesc->m_argData[3],
taskDesc->m_argData[4],
taskDesc->m_argData[5],
taskDesc->m_argData[6],
taskDesc->m_argData[7],
taskDesc->m_argData[8],
taskDesc->m_argData[9],
taskDesc->m_argData[10],
taskDesc->m_argData[11],
taskDesc->m_argData[12],
guid);
}
static void kernelLauncher14(MiniCLTaskDesc* taskDesc, int guid)
{
((MiniCLKernelLauncher14)(taskDesc->m_kernel->m_pCode))(taskDesc->m_argData[0],
taskDesc->m_argData[1],
taskDesc->m_argData[2],
taskDesc->m_argData[3],
taskDesc->m_argData[4],
taskDesc->m_argData[5],
taskDesc->m_argData[6],
taskDesc->m_argData[7],
taskDesc->m_argData[8],
taskDesc->m_argData[9],
taskDesc->m_argData[10],
taskDesc->m_argData[11],
taskDesc->m_argData[12],
taskDesc->m_argData[13],
guid);
}
static void kernelLauncher15(MiniCLTaskDesc* taskDesc, int guid)
{
((MiniCLKernelLauncher15)(taskDesc->m_kernel->m_pCode))(taskDesc->m_argData[0],
taskDesc->m_argData[1],
taskDesc->m_argData[2],
taskDesc->m_argData[3],
taskDesc->m_argData[4],
taskDesc->m_argData[5],
taskDesc->m_argData[6],
taskDesc->m_argData[7],
taskDesc->m_argData[8],
taskDesc->m_argData[9],
taskDesc->m_argData[10],
taskDesc->m_argData[11],
taskDesc->m_argData[12],
taskDesc->m_argData[13],
taskDesc->m_argData[14],
guid);
}
static void kernelLauncher16(MiniCLTaskDesc* taskDesc, int guid)
{
((MiniCLKernelLauncher16)(taskDesc->m_kernel->m_pCode))(taskDesc->m_argData[0],
taskDesc->m_argData[1],
taskDesc->m_argData[2],
taskDesc->m_argData[3],
taskDesc->m_argData[4],
taskDesc->m_argData[5],
taskDesc->m_argData[6],
taskDesc->m_argData[7],
taskDesc->m_argData[8],
taskDesc->m_argData[9],
taskDesc->m_argData[10],
taskDesc->m_argData[11],
taskDesc->m_argData[12],
taskDesc->m_argData[13],
taskDesc->m_argData[14],
taskDesc->m_argData[15],
guid);
}
static kernelLauncherCB spLauncherList[MINI_CL_MAX_ARG+1] =
{
kernelLauncher0,
kernelLauncher1,
kernelLauncher2,
kernelLauncher3,
kernelLauncher4,
kernelLauncher5,
kernelLauncher6,
kernelLauncher7,
kernelLauncher8,
kernelLauncher9,
kernelLauncher10,
kernelLauncher11,
kernelLauncher12,
kernelLauncher13,
kernelLauncher14,
kernelLauncher15,
kernelLauncher16
};
void MiniCLKernel::updateLauncher()
{
m_launcher = spLauncherList[m_numArgs];
}
struct MiniCLKernelDescEntry
{
void* pCode;
char* pName;
};
static MiniCLKernelDescEntry spKernelDesc[256];
static int sNumKernelDesc = 0;
MiniCLKernelDesc::MiniCLKernelDesc(void* pCode, char* pName)
{
for(int i = 0; i < sNumKernelDesc; i++)
{
if(!strcmp(pName, spKernelDesc[i].pName))
{ // already registered
btAssert(spKernelDesc[i].pCode == pCode);
return;
}
}
spKernelDesc[sNumKernelDesc].pCode = pCode;
spKernelDesc[sNumKernelDesc].pName = pName;
sNumKernelDesc++;
}
MiniCLKernel* MiniCLKernel::registerSelf()
{
m_scheduler->registerKernel(this);
for(int i = 0; i < sNumKernelDesc; i++)
{
if(!strcmp(m_name, spKernelDesc[i].pName))
{
m_pCode = spKernelDesc[i].pCode;
return this;
}
}
return NULL;
}
#endif
#endif //USE_SAMPLE_PROCESS

View File

@@ -1,194 +0,0 @@
/*
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 MINICL_TASK_SCHEDULER_H
#define MINICL_TASK_SCHEDULER_H
#include <assert.h>
#include "BulletMultiThreaded/PlatformDefinitions.h"
#include <stdlib.h>
#include "LinearMath/btAlignedObjectArray.h"
#include "MiniCLTask/MiniCLTask.h"
//just add your commands here, try to keep them globally unique for debugging purposes
#define CMD_SAMPLE_TASK_COMMAND 10
struct MiniCLKernel;
/// MiniCLTaskScheduler handles SPU processing of collision pairs.
/// When PPU issues a task, it will look for completed task buffers
/// PPU will do postprocessing, dependent on workunit output (not likely)
class MiniCLTaskScheduler
{
// track task buffers that are being used, and total busy tasks
btAlignedObjectArray<bool> m_taskBusy;
btAlignedObjectArray<MiniCLTaskDesc> m_spuSampleTaskDesc;
btAlignedObjectArray<const MiniCLKernel*> m_kernels;
int m_numBusyTasks;
// the current task and the current entry to insert a new work unit
int m_currentTask;
bool m_initialized;
void postProcess(int taskId, int outputSize);
class btThreadSupportInterface* m_threadInterface;
int m_maxNumOutstandingTasks;
public:
MiniCLTaskScheduler(btThreadSupportInterface* threadInterface, int maxNumOutstandingTasks);
~MiniCLTaskScheduler();
///call initialize in the beginning of the frame, before addCollisionPairToTask
void initialize();
void issueTask(int firstWorkUnit, int lastWorkUnit, MiniCLKernel* kernel);
///call flush to submit potential outstanding work to SPUs and wait for all involved SPUs to be finished
void flush();
class btThreadSupportInterface* getThreadSupportInterface()
{
return m_threadInterface;
}
int findProgramCommandIdByName(const char* programName) const;
int getMaxNumOutstandingTasks() const
{
return m_maxNumOutstandingTasks;
}
void registerKernel(MiniCLKernel* kernel)
{
m_kernels.push_back(kernel);
}
};
typedef void (*kernelLauncherCB)(MiniCLTaskDesc* taskDesc, int guid);
struct MiniCLKernel
{
MiniCLTaskScheduler* m_scheduler;
// int m_kernelProgramCommandId;
char m_name[MINI_CL_MAX_KERNEL_NAME];
unsigned int m_numArgs;
kernelLauncherCB m_launcher;
void* m_pCode;
void updateLauncher();
MiniCLKernel* registerSelf();
void* m_argData[MINI_CL_MAX_ARG];
int m_argSizes[MINI_CL_MAX_ARG];
};
#if defined(USE_LIBSPE2) && defined(__SPU__)
////////////////////MAIN/////////////////////////////
#include "../SpuLibspe2Support.h"
#include <spu_intrinsics.h>
#include <spu_mfcio.h>
#include <SpuFakeDma.h>
void * SamplelsMemoryFunc();
void SampleThreadFunc(void* userPtr,void* lsMemory);
//#define DEBUG_LIBSPE2_MAINLOOP
int main(unsigned long long speid, addr64 argp, addr64 envp)
{
printf("SPU is up \n");
ATTRIBUTE_ALIGNED128(btSpuStatus status);
ATTRIBUTE_ALIGNED16( SpuSampleTaskDesc taskDesc ) ;
unsigned int received_message = Spu_Mailbox_Event_Nothing;
bool shutdown = false;
cellDmaGet(&status, argp.ull, sizeof(btSpuStatus), DMA_TAG(3), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(3));
status.m_status = Spu_Status_Free;
status.m_lsMemory.p = SamplelsMemoryFunc();
cellDmaLargePut(&status, argp.ull, sizeof(btSpuStatus), DMA_TAG(3), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(3));
while (!shutdown)
{
received_message = spu_read_in_mbox();
switch(received_message)
{
case Spu_Mailbox_Event_Shutdown:
shutdown = true;
break;
case Spu_Mailbox_Event_Task:
// refresh the status
#ifdef DEBUG_LIBSPE2_MAINLOOP
printf("SPU recieved Task \n");
#endif //DEBUG_LIBSPE2_MAINLOOP
cellDmaGet(&status, argp.ull, sizeof(btSpuStatus), DMA_TAG(3), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(3));
btAssert(status.m_status==Spu_Status_Occupied);
cellDmaGet(&taskDesc, status.m_taskDesc.p, sizeof(SpuSampleTaskDesc), DMA_TAG(3), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(3));
SampleThreadFunc((void*)&taskDesc, reinterpret_cast<void*> (taskDesc.m_mainMemoryPtr) );
break;
case Spu_Mailbox_Event_Nothing:
default:
break;
}
// set to status free and wait for next task
status.m_status = Spu_Status_Free;
cellDmaLargePut(&status, argp.ull, sizeof(btSpuStatus), DMA_TAG(3), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(3));
}
return 0;
}
//////////////////////////////////////////////////////
#endif
#endif // MINICL_TASK_SCHEDULER_H