* Adjustment: Update Bullet version to 3.24.

This commit is contained in:
Robert MacGregor 2022-06-27 10:01:08 -04:00
parent 35de012ee7
commit 4a3f31df2a
6148 changed files with 2112532 additions and 56873 deletions

View file

@ -0,0 +1,68 @@
#ifndef INIT_CL_H
#define INIT_CL_H
void initCL()
{
int preferredDeviceIndex = -1;
int preferredPlatformIndex = -1;
bool allowCpuOpenCL = false;
b3CommandLineArgs args(gArgc, gArgv);
args.GetCmdLineArgument("cl_device", preferredDeviceIndex);
args.GetCmdLineArgument("cl_platform", preferredPlatformIndex);
allowCpuOpenCL = args.CheckCmdLineFlag("allow_opencl_cpu");
void* glCtx = 0;
void* glDC = 0;
int ciErrNum = 0;
cl_device_type deviceType = CL_DEVICE_TYPE_GPU;
if (allowCpuOpenCL)
deviceType = CL_DEVICE_TYPE_ALL;
// if (useInterop)
// {
// m_data->m_clContext = b3OpenCLUtils::createContextFromType(deviceType, &ciErrNum, glCtx, glDC);
// } else
{
m_clContext = b3OpenCLUtils::createContextFromType(deviceType, &ciErrNum, 0, 0, preferredDeviceIndex, preferredPlatformIndex, &m_platformId);
ASSERT_FALSE(m_clContext == 0);
}
b3OpenCLPlatformInfo platformInfo;
b3OpenCLUtils::getPlatformInfo(m_platformId, &platformInfo);
b3Printf("OpenCL Platform Name %s\n", platformInfo.m_platformName);
b3Printf("OpenCL Platform Vendor %s\n", platformInfo.m_platformVendor);
b3Printf("OpenCL Platform Version %s\n", platformInfo.m_platformVersion);
ASSERT_EQ(ciErrNum, CL_SUCCESS);
int numDev = b3OpenCLUtils::getNumDevices(m_clContext);
EXPECT_GT(numDev, 0);
if (numDev > 0)
{
m_clDevice = b3OpenCLUtils::getDevice(m_clContext, 0);
ASSERT_FALSE(m_clDevice == 0);
m_clQueue = clCreateCommandQueue(m_clContext, m_clDevice, 0, &ciErrNum);
ASSERT_FALSE(m_clQueue == 0);
ASSERT_EQ(ciErrNum, CL_SUCCESS);
b3OpenCLDeviceInfo info;
b3OpenCLUtils::getDeviceInfo(m_clDevice, &info);
b3OpenCLUtils::printDeviceInfo(m_clDevice);
m_clDeviceName = info.m_deviceName;
}
}
void exitCL()
{
clReleaseCommandQueue(m_clQueue);
clReleaseContext(m_clContext);
}
#endif //INIT_CL_H

View file

@ -0,0 +1,157 @@
#include <gtest/gtest.h>
#include "Bullet3Common/b3Logging.h"
#include "Bullet3Common/b3CommandLineArgs.h"
#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
#include "Bullet3OpenCL/BroadphaseCollision/kernels/sapKernels.h"
#include "Bullet3OpenCL/BroadphaseCollision/kernels/gridBroadphaseKernels.h"
extern int gArgc;
extern char** gArgv;
namespace
{
struct CompileBullet3BroadphaseKernels : public ::testing::Test
{
cl_context m_clContext;
cl_device_id m_clDevice;
cl_command_queue m_clQueue;
char* m_clDeviceName;
cl_platform_id m_platformId;
CompileBullet3BroadphaseKernels()
: m_clDeviceName(0),
m_clContext(0),
m_clDevice(0),
m_clQueue(0),
m_platformId(0)
{
// You can do set-up work for each test here.
b3CommandLineArgs args(gArgc, gArgv);
int preferredDeviceIndex = -1;
int preferredPlatformIndex = -1;
bool allowCpuOpenCL = false;
initCL();
}
virtual ~CompileBullet3BroadphaseKernels()
{
// You can do clean-up work that doesn't throw exceptions here.
exitCL();
}
// If the constructor and destructor are not enough for setting up
// and cleaning up each test, you can define the following methods:
#include "initCL.h"
virtual void SetUp()
{
// Code here will be called immediately after the constructor (right
// before each test).
}
virtual void TearDown()
{
// Code here will be called immediately after each test (right
// before the destructor).
}
};
TEST_F(CompileBullet3BroadphaseKernels, sapKernels)
{
cl_int errNum = 0;
cl_program sapProg = b3OpenCLUtils::compileCLProgramFromString(m_clContext, m_clDevice, sapCL, &errNum, "", 0, true);
{
ASSERT_EQ(CL_SUCCESS, errNum);
cl_kernel copyAabbsKernel = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, sapCL, "copyAabbsKernel", &errNum, sapProg);
ASSERT_EQ(CL_SUCCESS, errNum);
ASSERT_FALSE(copyAabbsKernel == 0);
clReleaseKernel(copyAabbsKernel);
}
{
cl_kernel sap2Kernel = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, sapCL, "computePairsKernelTwoArrays", &errNum, sapProg);
ASSERT_EQ(CL_SUCCESS, errNum);
ASSERT_FALSE(sap2Kernel == 0);
clReleaseKernel(sap2Kernel);
}
{
cl_kernel sapKernelBruteForce = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, sapCL, "computePairsKernelBruteForce", &errNum, sapProg);
ASSERT_EQ(CL_SUCCESS, errNum);
ASSERT_FALSE(sapKernelBruteForce == 0);
clReleaseKernel(sapKernelBruteForce);
}
{
cl_kernel sapKernelOriginal = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, sapCL, "computePairsKernelOriginal", &errNum, sapProg);
ASSERT_EQ(CL_SUCCESS, errNum);
ASSERT_FALSE(sapKernelOriginal == 0);
clReleaseKernel(sapKernelOriginal);
}
{
cl_kernel sapKernelBarrier = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, sapCL, "computePairsKernelBarrier", &errNum, sapProg);
ASSERT_EQ(CL_SUCCESS, errNum);
ASSERT_FALSE(sapKernelBarrier == 0);
clReleaseKernel(sapKernelBarrier);
}
{
cl_kernel sapKernelLocalShared = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, sapCL, "computePairsKernelLocalSharedMemory", &errNum, sapProg);
ASSERT_EQ(CL_SUCCESS, errNum);
ASSERT_FALSE(sapKernelLocalShared == 0);
clReleaseKernel(sapKernelLocalShared);
}
{
cl_kernel prepareSumVarianceKernel = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, sapCL, "prepareSumVarianceKernel", &errNum, sapProg);
ASSERT_EQ(CL_SUCCESS, errNum);
ASSERT_FALSE(prepareSumVarianceKernel == 0);
clReleaseKernel(prepareSumVarianceKernel);
}
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, sapCL, "flipFloatKernel", &errNum, sapProg);
ASSERT_EQ(CL_SUCCESS, errNum);
ASSERT_FALSE(k == 0);
clReleaseKernel(k);
}
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, sapCL, "scatterKernel", &errNum, sapProg);
ASSERT_EQ(CL_SUCCESS, errNum);
ASSERT_FALSE(k == 0);
clReleaseKernel(k);
}
clReleaseProgram(sapProg);
};
TEST_F(CompileBullet3BroadphaseKernels, gridBroadphaseKernels)
{
cl_int errNum = 0;
cl_program gridProg = b3OpenCLUtils::compileCLProgramFromString(m_clContext, m_clDevice, gridBroadphaseCL, &errNum, "", 0, true);
ASSERT_EQ(CL_SUCCESS, errNum);
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, gridBroadphaseCL, "kCalcHashAABB", &errNum, gridProg);
ASSERT_EQ(CL_SUCCESS, errNum);
clReleaseKernel(k);
}
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, gridBroadphaseCL, "kClearCellStart", &errNum, gridProg);
ASSERT_EQ(CL_SUCCESS, errNum);
clReleaseKernel(k);
}
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, gridBroadphaseCL, "kFindCellStart", &errNum, gridProg);
ASSERT_EQ(CL_SUCCESS, errNum);
clReleaseKernel(k);
}
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, gridBroadphaseCL, "kFindOverlappingPairs", &errNum, gridProg);
ASSERT_EQ(CL_SUCCESS, errNum);
clReleaseKernel(k);
}
clReleaseProgram(gridProg);
}
}; // namespace

View file

@ -0,0 +1,102 @@
#include <gtest/gtest.h>
#include "Bullet3Common/b3Logging.h"
#include "Bullet3Common/b3CommandLineArgs.h"
#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
#include "Bullet3OpenCL/RigidBody/kernels/integrateKernel.h"
#include "Bullet3OpenCL/RigidBody/kernels/updateAabbsKernel.h"
extern int gArgc;
extern char** gArgv;
namespace
{
struct testCompileBullet3IntegrateUpdateAabbKernels : public ::testing::Test
{
cl_context m_clContext;
cl_device_id m_clDevice;
cl_command_queue m_clQueue;
char* m_clDeviceName;
cl_platform_id m_platformId;
testCompileBullet3IntegrateUpdateAabbKernels()
: m_clDeviceName(0),
m_clContext(0),
m_clDevice(0),
m_clQueue(0),
m_platformId(0)
{
// You can do set-up work for each test here.
b3CommandLineArgs args(gArgc, gArgv);
int preferredDeviceIndex = -1;
int preferredPlatformIndex = -1;
bool allowCpuOpenCL = false;
initCL();
}
virtual ~testCompileBullet3IntegrateUpdateAabbKernels()
{
// You can do clean-up work that doesn't throw exceptions here.
exitCL();
}
// If the constructor and destructor are not enough for setting up
// and cleaning up each test, you can define the following methods:
#include "initCL.h"
virtual void SetUp()
{
// Code here will be called immediately after the constructor (right
// before each test).
}
virtual void TearDown()
{
// Code here will be called immediately after each test (right
// before the destructor).
}
};
TEST_F(testCompileBullet3IntegrateUpdateAabbKernels, integrateKernelCL)
{
cl_int errNum = 0;
cl_program prog = b3OpenCLUtils::compileCLProgramFromString(m_clContext, m_clDevice, integrateKernelCL, &errNum, "", 0, true);
ASSERT_EQ(CL_SUCCESS, errNum);
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, integrateKernelCL, "integrateTransformsKernel", &errNum, prog);
ASSERT_EQ(CL_SUCCESS, errNum);
ASSERT_FALSE(k == 0);
clReleaseKernel(k);
}
clReleaseProgram(prog);
}
TEST_F(testCompileBullet3IntegrateUpdateAabbKernels, updateAabbsKernelCL)
{
cl_int errNum = 0;
cl_program prog = b3OpenCLUtils::compileCLProgramFromString(m_clContext, m_clDevice, updateAabbsKernelCL, &errNum, "", 0, true);
ASSERT_EQ(CL_SUCCESS, errNum);
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, updateAabbsKernelCL, "initializeGpuAabbsFull", &errNum, prog);
ASSERT_EQ(CL_SUCCESS, errNum);
ASSERT_FALSE(k == 0);
clReleaseKernel(k);
}
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, updateAabbsKernelCL, "clearOverlappingPairsKernel", &errNum, prog);
ASSERT_EQ(CL_SUCCESS, errNum);
ASSERT_FALSE(k == 0);
clReleaseKernel(k);
}
clReleaseProgram(prog);
}
}; // namespace

View file

@ -0,0 +1,120 @@
#include <gtest/gtest.h>
#include "Bullet3Common/b3Logging.h"
#include "Bullet3Common/b3CommandLineArgs.h"
#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
#include "Bullet3OpenCL/RigidBody/kernels/solverUtils.h"
extern int gArgc;
extern char** gArgv;
namespace
{
struct CompileBullet3JacobiContactSolverKernels : public ::testing::Test
{
cl_context m_clContext;
cl_device_id m_clDevice;
cl_command_queue m_clQueue;
char* m_clDeviceName;
cl_platform_id m_platformId;
CompileBullet3JacobiContactSolverKernels()
: m_clDeviceName(0),
m_clContext(0),
m_clDevice(0),
m_clQueue(0),
m_platformId(0)
{
// You can do set-up work for each test here.
b3CommandLineArgs args(gArgc, gArgv);
int preferredDeviceIndex = -1;
int preferredPlatformIndex = -1;
bool allowCpuOpenCL = false;
initCL();
}
virtual ~CompileBullet3JacobiContactSolverKernels()
{
// You can do clean-up work that doesn't throw exceptions here.
exitCL();
}
// If the constructor and destructor are not enough for setting up
// and cleaning up each test, you can define the following methods:
#include "initCL.h"
virtual void SetUp()
{
// Code here will be called immediately after the constructor (right
// before each test).
}
virtual void TearDown()
{
// Code here will be called immediately after each test (right
// before the destructor).
}
};
TEST_F(CompileBullet3JacobiContactSolverKernels, jacobiContactKernels)
{
cl_int errNum = 0;
const char* additionalMacros = "";
cl_program solverUtilsProg = b3OpenCLUtils::compileCLProgramFromString(m_clContext, m_clDevice, solverUtilsCL, &errNum, additionalMacros, 0, true);
ASSERT_EQ(CL_SUCCESS, errNum);
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, solverUtilsCL, "CountBodiesKernel", &errNum, solverUtilsProg, additionalMacros);
ASSERT_EQ(CL_SUCCESS, errNum);
ASSERT_FALSE(k == 0);
clReleaseKernel(k);
}
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, solverUtilsCL, "ContactToConstraintSplitKernel", &errNum, solverUtilsProg, additionalMacros);
ASSERT_EQ(CL_SUCCESS, errNum);
ASSERT_FALSE(k == 0);
clReleaseKernel(k);
}
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, solverUtilsCL, "ClearVelocitiesKernel", &errNum, solverUtilsProg, additionalMacros);
ASSERT_EQ(CL_SUCCESS, errNum);
ASSERT_FALSE(k == 0);
clReleaseKernel(k);
}
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, solverUtilsCL, "AverageVelocitiesKernel", &errNum, solverUtilsProg, additionalMacros);
ASSERT_EQ(CL_SUCCESS, errNum);
ASSERT_FALSE(k == 0);
clReleaseKernel(k);
}
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, solverUtilsCL, "UpdateBodyVelocitiesKernel", &errNum, solverUtilsProg, additionalMacros);
ASSERT_EQ(CL_SUCCESS, errNum);
ASSERT_FALSE(k == 0);
clReleaseKernel(k);
}
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, solverUtilsCL, "SolveContactJacobiKernel", &errNum, solverUtilsProg, additionalMacros);
ASSERT_EQ(CL_SUCCESS, errNum);
ASSERT_FALSE(k == 0);
clReleaseKernel(k);
}
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, solverUtilsCL, "SolveFrictionJacobiKernel", &errNum, solverUtilsProg, additionalMacros);
ASSERT_EQ(CL_SUCCESS, errNum);
ASSERT_FALSE(k == 0);
clReleaseKernel(k);
}
clReleaseProgram(solverUtilsProg);
}
}; // namespace

View file

@ -0,0 +1,254 @@
#include <gtest/gtest.h>
#include "Bullet3Common/b3Logging.h"
#include "Bullet3Common/b3CommandLineArgs.h"
#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
#include "Bullet3OpenCL/NarrowphaseCollision/kernels/satKernels.h"
#include "Bullet3OpenCL/NarrowphaseCollision/kernels/mprKernels.h"
#include "Bullet3OpenCL/NarrowphaseCollision/kernels/satConcaveKernels.h"
#include "Bullet3OpenCL/NarrowphaseCollision/kernels/satClipHullContacts.h"
#include "Bullet3OpenCL/NarrowphaseCollision/kernels/bvhTraversal.h"
#include "Bullet3OpenCL/NarrowphaseCollision/kernels/primitiveContacts.h"
extern int gArgc;
extern char** gArgv;
namespace
{
struct CompileBullet3NarrowphaseKernels : public ::testing::Test
{
cl_context m_clContext;
cl_device_id m_clDevice;
cl_command_queue m_clQueue;
char* m_clDeviceName;
cl_platform_id m_platformId;
CompileBullet3NarrowphaseKernels()
: m_clDeviceName(0),
m_clContext(0),
m_clDevice(0),
m_clQueue(0),
m_platformId(0)
{
// You can do set-up work for each test here.
b3CommandLineArgs args(gArgc, gArgv);
int preferredDeviceIndex = -1;
int preferredPlatformIndex = -1;
bool allowCpuOpenCL = false;
initCL();
}
virtual ~CompileBullet3NarrowphaseKernels()
{
// You can do clean-up work that doesn't throw exceptions here.
exitCL();
}
// If the constructor and destructor are not enough for setting up
// and cleaning up each test, you can define the following methods:
#include "initCL.h"
virtual void SetUp()
{
// Code here will be called immediately after the constructor (right
// before each test).
}
virtual void TearDown()
{
// Code here will be called immediately after each test (right
// before the destructor).
}
};
TEST_F(CompileBullet3NarrowphaseKernels, satKernelsCL)
{
cl_int errNum = 0;
char flags[1024] = {0};
cl_program satProg = b3OpenCLUtils::compileCLProgramFromString(m_clContext, m_clDevice, satKernelsCL, &errNum, flags, 0, true);
ASSERT_EQ(CL_SUCCESS, errNum);
{
cl_kernel m_findSeparatingAxisKernel = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, satKernelsCL, "findSeparatingAxisKernel", &errNum, satProg);
ASSERT_EQ(CL_SUCCESS, errNum);
clReleaseKernel(m_findSeparatingAxisKernel);
}
{
cl_kernel m_findSeparatingAxisVertexFaceKernel = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, satKernelsCL, "findSeparatingAxisVertexFaceKernel", &errNum, satProg);
ASSERT_EQ(CL_SUCCESS, errNum);
clReleaseKernel(m_findSeparatingAxisVertexFaceKernel);
}
{
cl_kernel m_findSeparatingAxisEdgeEdgeKernel = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, satKernelsCL, "findSeparatingAxisEdgeEdgeKernel", &errNum, satProg);
ASSERT_EQ(CL_SUCCESS, errNum);
clReleaseKernel(m_findSeparatingAxisEdgeEdgeKernel);
}
{
cl_kernel m_findConcaveSeparatingAxisKernel = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, satKernelsCL, "findConcaveSeparatingAxisKernel", &errNum, satProg);
ASSERT_EQ(CL_SUCCESS, errNum);
clReleaseKernel(m_findConcaveSeparatingAxisKernel);
}
{
cl_kernel m_findCompoundPairsKernel = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, satKernelsCL, "findCompoundPairsKernel", &errNum, satProg);
ASSERT_EQ(CL_SUCCESS, errNum);
clReleaseKernel(m_findCompoundPairsKernel);
}
{
cl_kernel m_processCompoundPairsKernel = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, satKernelsCL, "processCompoundPairsKernel", &errNum, satProg);
ASSERT_EQ(CL_SUCCESS, errNum);
clReleaseKernel(m_processCompoundPairsKernel);
}
clReleaseProgram(satProg);
}
TEST_F(CompileBullet3NarrowphaseKernels, satConcaveKernelsCL)
{
cl_int errNum = 0;
char flags[1024] = {0};
cl_program satConcaveProg = b3OpenCLUtils::compileCLProgramFromString(m_clContext, m_clDevice, satConcaveKernelsCL, &errNum, flags, 0, true);
ASSERT_EQ(CL_SUCCESS, errNum);
{
cl_kernel m_findConcaveSeparatingAxisVertexFaceKernel = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, satConcaveKernelsCL, "findConcaveSeparatingAxisVertexFaceKernel", &errNum, satConcaveProg);
ASSERT_EQ(CL_SUCCESS, errNum);
clReleaseKernel(m_findConcaveSeparatingAxisVertexFaceKernel);
}
{
cl_kernel m_findConcaveSeparatingAxisEdgeEdgeKernel = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, satConcaveKernelsCL, "findConcaveSeparatingAxisEdgeEdgeKernel", &errNum, satConcaveProg);
ASSERT_EQ(CL_SUCCESS, errNum);
clReleaseKernel(m_findConcaveSeparatingAxisEdgeEdgeKernel);
}
clReleaseProgram(satConcaveProg);
}
TEST_F(CompileBullet3NarrowphaseKernels, satClipKernelsCL)
{
char flags[1024] = {0};
cl_int errNum = 0;
//#ifdef CL_PLATFORM_INTEL
// sprintf(flags,"-g -s \"%s\"","C:/develop/bullet3_experiments2/opencl/gpu_narrowphase/kernels/satClipHullContacts.cl");
//#endif
cl_program satClipContactsProg = b3OpenCLUtils::compileCLProgramFromString(m_clContext, m_clDevice, satClipKernelsCL, &errNum, flags, 0, true);
ASSERT_EQ(CL_SUCCESS, errNum);
{
cl_kernel m_clipHullHullKernel = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, satClipKernelsCL, "clipHullHullKernel", &errNum, satClipContactsProg);
ASSERT_EQ(CL_SUCCESS, errNum);
clReleaseKernel(m_clipHullHullKernel);
}
{
cl_kernel m_clipCompoundsHullHullKernel = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, satClipKernelsCL, "clipCompoundsHullHullKernel", &errNum, satClipContactsProg);
ASSERT_EQ(CL_SUCCESS, errNum);
clReleaseKernel(m_clipCompoundsHullHullKernel);
}
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, satClipKernelsCL, "findClippingFacesKernel", &errNum, satClipContactsProg);
ASSERT_EQ(CL_SUCCESS, errNum);
clReleaseKernel(k);
}
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, satClipKernelsCL, "clipFacesAndFindContactsKernel", &errNum, satClipContactsProg);
ASSERT_EQ(CL_SUCCESS, errNum);
clReleaseKernel(k);
}
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, satClipKernelsCL, "clipHullHullConcaveConvexKernel", &errNum, satClipContactsProg);
ASSERT_EQ(CL_SUCCESS, errNum);
clReleaseKernel(k);
}
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, satClipKernelsCL,
"newContactReductionKernel", &errNum, satClipContactsProg);
ASSERT_EQ(CL_SUCCESS, errNum);
clReleaseKernel(k);
}
clReleaseProgram(satClipContactsProg);
}
TEST_F(CompileBullet3NarrowphaseKernels, bvhTraversalKernels)
{
cl_int errNum = 0;
cl_program bvhTraversalProg = b3OpenCLUtils::compileCLProgramFromString(m_clContext, m_clDevice, bvhTraversalKernelCL, &errNum, "", 0, true);
ASSERT_EQ(CL_SUCCESS, errNum);
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, bvhTraversalKernelCL, "bvhTraversalKernel", &errNum, bvhTraversalProg, "");
ASSERT_EQ(CL_SUCCESS, errNum);
clReleaseKernel(k);
}
clReleaseProgram(bvhTraversalProg);
}
TEST_F(CompileBullet3NarrowphaseKernels, primitiveContactsKernelsCL)
{
cl_int errNum = 0;
cl_program primitiveContactsProg = b3OpenCLUtils::compileCLProgramFromString(m_clContext, m_clDevice, primitiveContactsKernelsCL, &errNum, "", 0, true);
ASSERT_EQ(CL_SUCCESS, errNum);
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, primitiveContactsKernelsCL, "primitiveContactsKernel", &errNum, primitiveContactsProg, "");
ASSERT_EQ(CL_SUCCESS, errNum);
clReleaseKernel(k);
}
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, primitiveContactsKernelsCL, "findConcaveSphereContactsKernel", &errNum, primitiveContactsProg);
ASSERT_EQ(CL_SUCCESS, errNum);
clReleaseKernel(k);
}
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, primitiveContactsKernelsCL, "processCompoundPairsPrimitivesKernel", &errNum, primitiveContactsProg, "");
ASSERT_EQ(CL_SUCCESS, errNum);
clReleaseKernel(k);
}
clReleaseProgram(primitiveContactsProg);
}
TEST_F(CompileBullet3NarrowphaseKernels, mprKernelsCL)
{
cl_int errNum = 0;
const char* srcConcave = satConcaveKernelsCL;
char flags[1024] = {0};
cl_program mprProg = b3OpenCLUtils::compileCLProgramFromString(m_clContext, m_clDevice, mprKernelsCL, &errNum, flags, 0, true);
ASSERT_EQ(CL_SUCCESS, errNum);
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, mprKernelsCL, "mprPenetrationKernel", &errNum, mprProg);
ASSERT_EQ(CL_SUCCESS, errNum);
clReleaseKernel(k);
}
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, mprKernelsCL, "findSeparatingAxisUnitSphereKernel", &errNum, mprProg);
ASSERT_EQ(CL_SUCCESS, errNum);
clReleaseKernel(k);
}
clReleaseProgram(mprProg);
}
}; // namespace

View file

@ -0,0 +1,227 @@
#include <gtest/gtest.h>
#include "Bullet3Common/b3Logging.h"
#include "Bullet3Common/b3CommandLineArgs.h"
#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
#include "Bullet3OpenCL/RigidBody/kernels/solverSetup.h"
#include "Bullet3OpenCL/RigidBody/kernels/solverSetup2.h"
#include "Bullet3OpenCL/RigidBody/kernels/solveContact.h"
#include "Bullet3OpenCL/RigidBody/kernels/solveFriction.h"
#include "Bullet3OpenCL/RigidBody/kernels/batchingKernels.h"
#include "Bullet3OpenCL/RigidBody/kernels/batchingKernelsNew.h"
extern int gArgc;
extern char** gArgv;
namespace
{
struct CompileBullet3PgsContactSolverKernels : public ::testing::Test
{
cl_context m_clContext;
cl_device_id m_clDevice;
cl_command_queue m_clQueue;
char* m_clDeviceName;
cl_platform_id m_platformId;
CompileBullet3PgsContactSolverKernels()
: m_clDeviceName(0),
m_clContext(0),
m_clDevice(0),
m_clQueue(0),
m_platformId(0)
{
// You can do set-up work for each test here.
b3CommandLineArgs args(gArgc, gArgv);
int preferredDeviceIndex = -1;
int preferredPlatformIndex = -1;
bool allowCpuOpenCL = false;
initCL();
}
virtual ~CompileBullet3PgsContactSolverKernels()
{
// You can do clean-up work that doesn't throw exceptions here.
exitCL();
}
// If the constructor and destructor are not enough for setting up
// and cleaning up each test, you can define the following methods:
#include "initCL.h"
virtual void SetUp()
{
// Code here will be called immediately after the constructor (right
// before each test).
}
virtual void TearDown()
{
// Code here will be called immediately after each test (right
// before the destructor).
}
};
TEST_F(CompileBullet3PgsContactSolverKernels, solveFrictionCL)
{
const char* additionalMacros = "";
cl_int errNum = 0;
cl_program solveFrictionProg = b3OpenCLUtils::compileCLProgramFromString(m_clContext, m_clDevice, solveFrictionCL, &errNum, additionalMacros, 0, true);
ASSERT_EQ(CL_SUCCESS, errNum);
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, solveFrictionCL, "BatchSolveKernelFriction", &errNum, solveFrictionProg, additionalMacros);
ASSERT_EQ(CL_SUCCESS, errNum);
ASSERT_FALSE(k == 0);
clReleaseKernel(k);
}
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, solveFrictionCL, "solveSingleFrictionKernel", &errNum, solveFrictionProg, additionalMacros);
ASSERT_EQ(CL_SUCCESS, errNum);
ASSERT_FALSE(k == 0);
clReleaseKernel(k);
}
clReleaseProgram(solveFrictionProg);
}
TEST_F(CompileBullet3PgsContactSolverKernels, solverSetupCL)
{
const char* additionalMacros = "";
cl_int errNum = 0;
cl_program solverSetupProg = b3OpenCLUtils::compileCLProgramFromString(m_clContext, m_clDevice, solverSetupCL, &errNum, additionalMacros, 0, true);
ASSERT_EQ(CL_SUCCESS, errNum);
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, solverSetupCL, "ContactToConstraintKernel", &errNum, solverSetupProg, additionalMacros);
ASSERT_EQ(CL_SUCCESS, errNum);
ASSERT_FALSE(k == 0);
clReleaseKernel(k);
}
clReleaseProgram(solverSetupProg);
}
TEST_F(CompileBullet3PgsContactSolverKernels, solverSetup2CL)
{
const char* additionalMacros = "";
cl_int errNum = 0;
cl_program solverSetup2Prog = b3OpenCLUtils::compileCLProgramFromString(m_clContext, m_clDevice, solverSetup2CL, &errNum, additionalMacros, 0, true);
ASSERT_EQ(CL_SUCCESS, errNum);
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, solverSetup2CL, "SetSortDataKernel", &errNum, solverSetup2Prog, additionalMacros);
ASSERT_EQ(CL_SUCCESS, errNum);
ASSERT_FALSE(k == 0);
clReleaseKernel(k);
}
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, solverSetup2CL, "SetDeterminismSortDataBodyA", &errNum, solverSetup2Prog, additionalMacros);
ASSERT_EQ(CL_SUCCESS, errNum);
ASSERT_FALSE(k == 0);
clReleaseKernel(k);
}
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, solverSetup2CL, "SetDeterminismSortDataBodyB", &errNum, solverSetup2Prog, additionalMacros);
ASSERT_EQ(CL_SUCCESS, errNum);
ASSERT_FALSE(k == 0);
clReleaseKernel(k);
}
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, solverSetup2CL, "SetDeterminismSortDataChildShapeA", &errNum, solverSetup2Prog, additionalMacros);
ASSERT_EQ(CL_SUCCESS, errNum);
ASSERT_FALSE(k == 0);
clReleaseKernel(k);
}
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, solverSetup2CL, "SetDeterminismSortDataChildShapeB", &errNum, solverSetup2Prog, additionalMacros);
ASSERT_EQ(CL_SUCCESS, errNum);
ASSERT_FALSE(k == 0);
clReleaseKernel(k);
}
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, solverSetup2CL, "ReorderContactKernel", &errNum, solverSetup2Prog, additionalMacros);
ASSERT_EQ(CL_SUCCESS, errNum);
ASSERT_FALSE(k == 0);
clReleaseKernel(k);
}
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, solverSetup2CL, "CopyConstraintKernel", &errNum, solverSetup2Prog, additionalMacros);
ASSERT_EQ(CL_SUCCESS, errNum);
ASSERT_FALSE(k == 0);
clReleaseKernel(k);
}
clReleaseProgram(solverSetup2Prog);
}
TEST_F(CompileBullet3PgsContactSolverKernels, solveContactCL)
{
const char* additionalMacros = "";
cl_int errNum = 0;
cl_program solveContactProg = b3OpenCLUtils::compileCLProgramFromString(m_clContext, m_clDevice, solveContactCL, &errNum, additionalMacros, 0, true);
ASSERT_EQ(CL_SUCCESS, errNum);
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, solveContactCL, "BatchSolveKernelContact", &errNum, solveContactProg, additionalMacros);
ASSERT_EQ(CL_SUCCESS, errNum);
ASSERT_FALSE(k == 0);
clReleaseKernel(k);
}
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, solveContactCL, "solveSingleContactKernel", &errNum, solveContactProg, additionalMacros);
ASSERT_EQ(CL_SUCCESS, errNum);
ASSERT_FALSE(k == 0);
clReleaseKernel(k);
}
clReleaseProgram(solveContactProg);
}
TEST_F(CompileBullet3PgsContactSolverKernels, batchingKernelsCL)
{
const char* additionalMacros = "";
cl_int errNum = 0;
cl_program batchingProg = b3OpenCLUtils::compileCLProgramFromString(m_clContext, m_clDevice, batchingKernelsCL, &errNum, additionalMacros, 0, true);
ASSERT_EQ(CL_SUCCESS, errNum);
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, batchingKernelsCL, "CreateBatches", &errNum, batchingProg, additionalMacros);
ASSERT_EQ(CL_SUCCESS, errNum);
ASSERT_FALSE(k == 0);
clReleaseKernel(k);
}
clReleaseProgram(batchingProg);
}
TEST_F(CompileBullet3PgsContactSolverKernels, batchingKernelsNewCL)
{
const char* additionalMacros = "";
cl_int errNum = 0;
cl_program batchingNewProg = b3OpenCLUtils::compileCLProgramFromString(m_clContext, m_clDevice, batchingKernelsNewCL, &errNum, additionalMacros, 0, true);
ASSERT_EQ(CL_SUCCESS, errNum);
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, batchingKernelsNewCL, "CreateBatchesNew", &errNum, batchingNewProg, additionalMacros);
ASSERT_EQ(CL_SUCCESS, errNum);
ASSERT_FALSE(k == 0);
clReleaseKernel(k);
}
clReleaseProgram(batchingNewProg);
}
}; // namespace

View file

@ -0,0 +1,115 @@
#include <gtest/gtest.h>
#include "Bullet3Common/b3Logging.h"
#include "Bullet3Common/b3CommandLineArgs.h"
#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
#include "Bullet3OpenCL/RigidBody/kernels/jointSolver.h"
extern int gArgc;
extern char** gArgv;
namespace
{
struct testCompileBullet3PgsJointSolverKernels : public ::testing::Test
{
cl_context m_clContext;
cl_device_id m_clDevice;
cl_command_queue m_clQueue;
char* m_clDeviceName;
cl_platform_id m_platformId;
testCompileBullet3PgsJointSolverKernels()
: m_clDeviceName(0),
m_clContext(0),
m_clDevice(0),
m_clQueue(0),
m_platformId(0)
{
// You can do set-up work for each test here.
b3CommandLineArgs args(gArgc, gArgv);
int preferredDeviceIndex = -1;
int preferredPlatformIndex = -1;
bool allowCpuOpenCL = false;
initCL();
}
virtual ~testCompileBullet3PgsJointSolverKernels()
{
// You can do clean-up work that doesn't throw exceptions here.
exitCL();
}
// If the constructor and destructor are not enough for setting up
// and cleaning up each test, you can define the following methods:
#include "initCL.h"
virtual void SetUp()
{
// Code here will be called immediately after the constructor (right
// before each test).
}
virtual void TearDown()
{
// Code here will be called immediately after each test (right
// before the destructor).
}
};
TEST_F(testCompileBullet3PgsJointSolverKernels, solveConstraintRowsCL)
{
cl_int errNum = 0;
cl_program prog = b3OpenCLUtils::compileCLProgramFromString(m_clContext, m_clDevice, solveConstraintRowsCL, &errNum, "", 0, true);
ASSERT_EQ(CL_SUCCESS, errNum);
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, solveConstraintRowsCL, "solveJointConstraintRows", &errNum, prog);
ASSERT_EQ(CL_SUCCESS, errNum);
ASSERT_FALSE(k == 0);
clReleaseKernel(k);
}
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, solveConstraintRowsCL, "initSolverBodies", &errNum, prog);
ASSERT_EQ(CL_SUCCESS, errNum);
ASSERT_FALSE(k == 0);
clReleaseKernel(k);
}
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, solveConstraintRowsCL, "getInfo1Kernel", &errNum, prog);
ASSERT_EQ(CL_SUCCESS, errNum);
ASSERT_FALSE(k == 0);
clReleaseKernel(k);
}
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, solveConstraintRowsCL, "initBatchConstraintsKernel", &errNum, prog);
ASSERT_EQ(CL_SUCCESS, errNum);
ASSERT_FALSE(k == 0);
clReleaseKernel(k);
}
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, solveConstraintRowsCL, "getInfo2Kernel", &errNum, prog);
ASSERT_EQ(CL_SUCCESS, errNum);
ASSERT_FALSE(k == 0);
clReleaseKernel(k);
}
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, solveConstraintRowsCL, "writeBackVelocitiesKernel", &errNum, prog);
ASSERT_EQ(CL_SUCCESS, errNum);
ASSERT_FALSE(k == 0);
clReleaseKernel(k);
}
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, solveConstraintRowsCL, "breakViolatedConstraintsKernel", &errNum, prog);
ASSERT_EQ(CL_SUCCESS, errNum);
ASSERT_FALSE(k == 0);
clReleaseKernel(k);
}
clReleaseProgram(prog);
}
}; // namespace

View file

@ -0,0 +1,76 @@
#include <gtest/gtest.h>
#include "Bullet3Common/b3Logging.h"
#include "Bullet3Common/b3CommandLineArgs.h"
#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
#include "Bullet3OpenCL/Raycast/kernels/rayCastKernels.h"
extern int gArgc;
extern char** gArgv;
namespace
{
struct CompileBullet3RaycastKernels : public ::testing::Test
{
cl_context m_clContext;
cl_device_id m_clDevice;
cl_command_queue m_clQueue;
char* m_clDeviceName;
cl_platform_id m_platformId;
CompileBullet3RaycastKernels()
: m_clDeviceName(0),
m_clContext(0),
m_clDevice(0),
m_clQueue(0),
m_platformId(0)
{
// You can do set-up work for each test here.
b3CommandLineArgs args(gArgc, gArgv);
int preferredDeviceIndex = -1;
int preferredPlatformIndex = -1;
bool allowCpuOpenCL = false;
initCL();
}
virtual ~CompileBullet3RaycastKernels()
{
// You can do clean-up work that doesn't throw exceptions here.
exitCL();
}
// If the constructor and destructor are not enough for setting up
// and cleaning up each test, you can define the following methods:
#include "initCL.h"
virtual void SetUp()
{
// Code here will be called immediately after the constructor (right
// before each test).
}
virtual void TearDown()
{
// Code here will be called immediately after each test (right
// before the destructor).
}
};
TEST_F(CompileBullet3RaycastKernels, sapFastKernels)
{
cl_int errNum = 0;
cl_program prog = b3OpenCLUtils::compileCLProgramFromString(m_clContext, m_clDevice, rayCastKernelCL, &errNum, "", 0, true);
ASSERT_EQ(CL_SUCCESS, errNum);
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, rayCastKernelCL, "rayCastKernel", &errNum, prog);
ASSERT_EQ(CL_SUCCESS, errNum);
clReleaseKernel(k);
}
clReleaseProgram(prog);
}
}; // namespace

View file

@ -0,0 +1,432 @@
#include <gtest/gtest.h>
#include "Bullet3Common/b3Logging.h"
#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
#include "Bullet3Common/b3CommandLineArgs.h"
#include "Bullet3OpenCL/NarrowphaseCollision/kernels/satKernels.h"
#include "Bullet3OpenCL/NarrowphaseCollision/kernels/mprKernels.h"
#include "Bullet3OpenCL/NarrowphaseCollision/kernels/satConcaveKernels.h"
#include "Bullet3OpenCL/NarrowphaseCollision/kernels/satClipHullContacts.h"
#include "Bullet3OpenCL/NarrowphaseCollision/kernels/bvhTraversal.h"
#include "Bullet3OpenCL/NarrowphaseCollision/kernels/primitiveContacts.h"
#ifdef B3_USE_ZLIB
#include "minizip/unzip.h"
#endif
#include "Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h"
extern int gArgc;
extern char** gArgv;
namespace
{
struct ExecuteBullet3NarrowphaseKernels : public ::testing::Test
{
cl_context m_clContext;
cl_device_id m_clDevice;
cl_command_queue m_clQueue;
char* m_clDeviceName;
cl_platform_id m_platformId;
ExecuteBullet3NarrowphaseKernels()
: m_clDeviceName(0),
m_clContext(0),
m_clDevice(0),
m_clQueue(0),
m_platformId(0)
{
// You can do set-up work for each test here.
initCL();
}
virtual ~ExecuteBullet3NarrowphaseKernels()
{
// You can do clean-up work that doesn't throw exceptions here.
exitCL();
}
// If the constructor and destructor are not enough for setting up
// and cleaning up each test, you can define the following methods:
#include "initCL.h"
virtual void SetUp()
{
// Code here will be called immediately after the constructor (right
// before each test).
}
virtual void TearDown()
{
// Code here will be called immediately after each test (right
// before the destructor).
}
};
#if 0
TEST_F(ExecuteBullet3NarrowphaseKernels,satKernelsCL)
{
cl_int errNum=0;
char flags[1024]={0};
cl_program satProg = b3OpenCLUtils::compileCLProgramFromString(m_clContext,m_clDevice,satKernelsCL,&errNum,flags,0,true);
ASSERT_EQ(CL_SUCCESS,errNum);
{
cl_kernel m_findSeparatingAxisKernel = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice,satKernelsCL, "findSeparatingAxisKernel",&errNum,satProg );
ASSERT_EQ(CL_SUCCESS,errNum);
clReleaseKernel(m_findSeparatingAxisKernel );
}
{
cl_kernel m_findSeparatingAxisVertexFaceKernel = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice,satKernelsCL, "findSeparatingAxisVertexFaceKernel",&errNum,satProg );
ASSERT_EQ(CL_SUCCESS,errNum);
clReleaseKernel(m_findSeparatingAxisVertexFaceKernel);
}
{
cl_kernel m_findSeparatingAxisEdgeEdgeKernel = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice,satKernelsCL, "findSeparatingAxisEdgeEdgeKernel",&errNum,satProg );
ASSERT_EQ(CL_SUCCESS,errNum);
clReleaseKernel(m_findSeparatingAxisEdgeEdgeKernel);
}
{
cl_kernel m_findConcaveSeparatingAxisKernel = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice,satKernelsCL, "findConcaveSeparatingAxisKernel",&errNum,satProg );
ASSERT_EQ(CL_SUCCESS,errNum);
clReleaseKernel(m_findConcaveSeparatingAxisKernel );
}
{
cl_kernel m_findCompoundPairsKernel = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice,satKernelsCL, "findCompoundPairsKernel",&errNum,satProg );
ASSERT_EQ(CL_SUCCESS,errNum);
clReleaseKernel(m_findCompoundPairsKernel);
}
{
cl_kernel m_processCompoundPairsKernel = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice,satKernelsCL, "processCompoundPairsKernel",&errNum,satProg );
ASSERT_EQ(CL_SUCCESS,errNum);
clReleaseKernel(m_processCompoundPairsKernel);
}
clReleaseProgram(satProg);
}
TEST_F(ExecuteBullet3NarrowphaseKernels,satConcaveKernelsCL)
{
cl_int errNum=0;
char flags[1024]={0};
cl_program satConcaveProg = b3OpenCLUtils::compileCLProgramFromString(m_clContext,m_clDevice,satConcaveKernelsCL,&errNum,flags,0,true);
ASSERT_EQ(CL_SUCCESS,errNum);
{
cl_kernel m_findConcaveSeparatingAxisVertexFaceKernel = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice,satConcaveKernelsCL, "findConcaveSeparatingAxisVertexFaceKernel",&errNum,satConcaveProg );
ASSERT_EQ(CL_SUCCESS,errNum);
clReleaseKernel(m_findConcaveSeparatingAxisVertexFaceKernel);
}
{
cl_kernel m_findConcaveSeparatingAxisEdgeEdgeKernel = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice,satConcaveKernelsCL, "findConcaveSeparatingAxisEdgeEdgeKernel",&errNum,satConcaveProg );
ASSERT_EQ(CL_SUCCESS,errNum);
clReleaseKernel(m_findConcaveSeparatingAxisEdgeEdgeKernel);
}
clReleaseProgram(satConcaveProg);
}
TEST_F(ExecuteBullet3NarrowphaseKernels,satClipKernelsCL)
{
char flags[1024]={0};
cl_int errNum=0;
//#ifdef CL_PLATFORM_INTEL
// sprintf(flags,"-g -s \"%s\"","C:/develop/bullet3_experiments2/opencl/gpu_narrowphase/kernels/satClipHullContacts.cl");
//#endif
cl_program satClipContactsProg = b3OpenCLUtils::compileCLProgramFromString(m_clContext,m_clDevice,satClipKernelsCL,&errNum,flags,0,true);
ASSERT_EQ(CL_SUCCESS,errNum);
{
cl_kernel m_clipHullHullKernel = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice,satClipKernelsCL, "clipHullHullKernel",&errNum,satClipContactsProg);
ASSERT_EQ(CL_SUCCESS,errNum);
clReleaseKernel(m_clipHullHullKernel);
}
{
cl_kernel m_clipCompoundsHullHullKernel = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice,satClipKernelsCL, "clipCompoundsHullHullKernel",&errNum,satClipContactsProg);
ASSERT_EQ(CL_SUCCESS,errNum);
clReleaseKernel(m_clipCompoundsHullHullKernel);
}
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice,satClipKernelsCL, "findClippingFacesKernel",&errNum,satClipContactsProg);
ASSERT_EQ(CL_SUCCESS,errNum);
clReleaseKernel(k);
}
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice,satClipKernelsCL, "clipFacesAndFindContactsKernel",&errNum,satClipContactsProg);
ASSERT_EQ(CL_SUCCESS,errNum);
clReleaseKernel(k);
}
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice,satClipKernelsCL, "clipHullHullConcaveConvexKernel",&errNum,satClipContactsProg);
ASSERT_EQ(CL_SUCCESS,errNum);
clReleaseKernel(k);
}
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice,satClipKernelsCL,
"newContactReductionKernel",&errNum,satClipContactsProg);
ASSERT_EQ(CL_SUCCESS,errNum);
clReleaseKernel(k);
}
clReleaseProgram(satClipContactsProg);
}
TEST_F(ExecuteBullet3NarrowphaseKernels,bvhTraversalKernels)
{
cl_int errNum=0;
cl_program bvhTraversalProg = b3OpenCLUtils::compileCLProgramFromString(m_clContext,m_clDevice,bvhTraversalKernelCL,&errNum,"",0,true);
ASSERT_EQ(CL_SUCCESS,errNum);
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice,bvhTraversalKernelCL, "bvhTraversalKernel",&errNum,bvhTraversalProg,"");
ASSERT_EQ(CL_SUCCESS,errNum);
clReleaseKernel(k);
}
clReleaseProgram(bvhTraversalProg);
}
TEST_F(ExecuteBullet3NarrowphaseKernels,primitiveContactsKernelsCL)
{
cl_int errNum=0;
cl_program primitiveContactsProg = b3OpenCLUtils::compileCLProgramFromString(m_clContext,m_clDevice,primitiveContactsKernelsCL,&errNum,"",0,true);
ASSERT_EQ(CL_SUCCESS,errNum);
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice,primitiveContactsKernelsCL, "primitiveContactsKernel",&errNum,primitiveContactsProg,"");
ASSERT_EQ(CL_SUCCESS,errNum);
clReleaseKernel(k);
}
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice,primitiveContactsKernelsCL, "findConcaveSphereContactsKernel",&errNum,primitiveContactsProg );
ASSERT_EQ(CL_SUCCESS,errNum);
clReleaseKernel(k);
}
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice,primitiveContactsKernelsCL, "processCompoundPairsPrimitivesKernel",&errNum,primitiveContactsProg,"");
ASSERT_EQ(CL_SUCCESS,errNum);
clReleaseKernel(k);
}
clReleaseProgram(primitiveContactsProg);
}
#endif
unsigned char* openFile(const char* fileName, int* sizeInBytesPtr)
{
*sizeInBytesPtr = 0;
unsigned char* buffer = 0;
const char* prefix[] = {"./", "./data/", "../data/", "../../data/", "../../../data/", "../../../../data/"};
int numPrefixes = sizeof(prefix) / sizeof(const char*);
char relativeFileName[1024];
#ifdef B3_USE_ZLIB
{
FILE* f = 0;
int result = 0;
for (int i = 0; !f && i < numPrefixes; i++)
{
sprintf(relativeFileName, "%s%s", prefix[i], "unittest_data.zip");
f = fopen(relativeFileName, "rb");
}
if (f)
{
fclose(f);
unzFile zipfile = unzOpen(relativeFileName);
if (zipfile == NULL)
{
printf("%s: not found\n", relativeFileName);
}
// Get info about the zip file
unz_global_info global_info;
result = unzGetGlobalInfo(zipfile, &global_info);
if (result != UNZ_OK)
{
b3Printf("could not read file global info\n");
unzClose(zipfile);
}
else
{
result = unzLocateFile(zipfile, fileName, 0);
if (result == UNZ_OK)
{
unz_file_info info;
result = unzGetCurrentFileInfo(zipfile, &info, NULL, 0, NULL, 0, NULL, 0);
if (result != UNZ_OK)
{
b3Printf("unzGetCurrentFileInfo() != UNZ_OK (%d)\n", result);
}
else
{
result = unzOpenCurrentFile(zipfile);
if (result == UNZ_OK)
{
buffer = (unsigned char*)malloc(info.uncompressed_size);
result = unzReadCurrentFile(zipfile, buffer, info.uncompressed_size);
if (result < 0)
{
free(buffer);
buffer = 0;
}
else
{
*sizeInBytesPtr = info.uncompressed_size;
}
unzCloseCurrentFile(zipfile);
}
else
{
b3Printf("cannot open file %s!\n", fileName);
}
}
}
else
{
b3Printf("cannot find file %s\n", fileName);
}
unzClose(zipfile);
}
}
}
#endif //B3_USE_ZLIB
if (!buffer)
{
FILE* f = 0;
int result = 0;
for (int i = 0; !f && i < numPrefixes; i++)
{
sprintf(relativeFileName, "%s%s", prefix[i], fileName);
f = fopen(relativeFileName, "rb");
}
//first try from data.zip, otherwise directly load the file from disk
if (f)
{
int sizeInBytes = 0;
if (fseek(f, 0, SEEK_END) || (sizeInBytes = ftell(f)) == EOF || fseek(f, 0, SEEK_SET))
{
b3Printf("error, cannot get file size\n");
}
buffer = (unsigned char*)malloc(sizeInBytes);
int actualRead = fread(buffer, sizeInBytes, 1, f);
if (actualRead != 1)
{
free(buffer);
buffer = 0;
}
else
{
*sizeInBytesPtr = sizeInBytes;
}
fclose(f);
}
}
return buffer;
}
void testLauncher(const char* fileName2, b3LauncherCL& launcher, cl_context ctx)
{
int sizeInBytes = 0;
unsigned char* buf = openFile(fileName2, &sizeInBytes);
ASSERT_FALSE(buf == NULL);
if (buf)
{
int serializedBytes = launcher.deserializeArgs(buf, sizeInBytes, ctx);
int num = *(int*)&buf[serializedBytes];
launcher.launch1D(num);
free(buf);
//this clFinish is for testing on errors
}
}
TEST_F(ExecuteBullet3NarrowphaseKernels, mprKernelsCL)
{
cl_int errNum = 0;
const char* srcConcave = satConcaveKernelsCL;
char flags[1024] = {0};
cl_program mprProg = b3OpenCLUtils::compileCLProgramFromString(m_clContext, m_clDevice, mprKernelsCL, &errNum, flags, 0, true);
ASSERT_EQ(CL_SUCCESS, errNum);
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, mprKernelsCL, "mprPenetrationKernel", &errNum, mprProg);
ASSERT_EQ(CL_SUCCESS, errNum);
if (1)
{
const char* fileNames[] = {"mprPenetrationKernel60.bin", "mprPenetrationKernel61.bin", "mprPenetrationKernel70.bin", "mprPenetrationKernel128.bin"};
int results[] = {0, 1, 46, 98};
int numTests = sizeof(fileNames) / sizeof(const char*);
for (int i = 0; i < numTests; i++)
{
b3LauncherCL launcher(m_clQueue, k, fileNames[i]);
testLauncher(fileNames[i], launcher, m_clContext);
clFinish(m_clQueue);
ASSERT_EQ(launcher.getNumArguments(), 11);
b3KernelArgData data = launcher.getArgument(8);
ASSERT_TRUE(data.m_isBuffer);
b3OpenCLArray<int> totalContactsOut(this->m_clContext, this->m_clQueue);
totalContactsOut.setFromOpenCLBuffer(data.m_clBuffer, 1);
int numContacts = totalContactsOut.at(0);
ASSERT_EQ(results[i], numContacts);
}
//printf("numContacts = %d\n",numContacts);
//nContacts = m_totalContactsOut.at(0);
}
clReleaseKernel(k);
}
{
cl_kernel k = b3OpenCLUtils::compileCLKernelFromString(m_clContext, m_clDevice, mprKernelsCL, "findSeparatingAxisUnitSphereKernel", &errNum, mprProg);
ASSERT_EQ(CL_SUCCESS, errNum);
clReleaseKernel(k);
}
clReleaseProgram(mprProg);
}
}; // namespace

View file

@ -0,0 +1,167 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2011 Advanced Micro Devices, Inc. http://bulletphysics.org
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.
*/
///original author: Erwin Coumans
#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
#include "Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h"
#include <stdio.h>
cl_context g_cxMainContext;
cl_command_queue g_cqCommandQue;
#include "Bullet3Common/b3Logging.h"
void myerrorwarningprintf(const char* msg)
{
//OutputDebugStringA(msg);
//printf(msg);
}
void myprintf(const char* msg)
{
//OutputDebugStringA(msg);
printf(msg);
}
int main(int argc, char* argv[])
{
b3SetCustomPrintfFunc(myprintf);
b3SetCustomWarningMessageFunc(myerrorwarningprintf);
b3SetCustomErrorMessageFunc(myerrorwarningprintf);
b3Printf("test b3Printf\n");
b3Warning("test warning\n");
b3Error("test error\n");
int ciErrNum = 0;
cl_device_type deviceType = CL_DEVICE_TYPE_ALL;
const char* vendorSDK = b3OpenCLUtils::getSdkVendorName();
b3Printf("This program was compiled using the %s OpenCL SDK\n", vendorSDK);
int numPlatforms = b3OpenCLUtils::getNumPlatforms();
b3Printf("Num Platforms = %d\n", numPlatforms);
for (int i = 0; i < numPlatforms; i++)
{
cl_platform_id platform = b3OpenCLUtils::getPlatform(i);
b3OpenCLPlatformInfo platformInfo;
b3OpenCLUtils::getPlatformInfo(platform, &platformInfo);
b3Printf("--------------------------------\n");
b3Printf("Platform info for platform nr %d:\n", i);
b3Printf(" CL_PLATFORM_VENDOR: \t\t\t%s\n", platformInfo.m_platformVendor);
b3Printf(" CL_PLATFORM_NAME: \t\t\t%s\n", platformInfo.m_platformName);
b3Printf(" CL_PLATFORM_VERSION: \t\t\t%s\n", platformInfo.m_platformVersion);
g_cxMainContext = b3OpenCLUtils::createContextFromPlatform(platform, deviceType, &ciErrNum);
int numDevices = b3OpenCLUtils::getNumDevices(g_cxMainContext);
b3Printf("Num Devices = %d\n", numDevices);
for (int j = 0; j < numDevices; j++)
{
cl_device_id device = b3OpenCLUtils::getDevice(g_cxMainContext, j);
b3OpenCLDeviceInfo devInfo;
b3OpenCLUtils::getDeviceInfo(device, &devInfo);
b3OpenCLUtils::printDeviceInfo(device);
g_cqCommandQue = clCreateCommandQueue(g_cxMainContext, device, 0, &ciErrNum);
b3OpenCLArray<char> memTester(g_cxMainContext, g_cqCommandQue, 0, true);
int maxMem = 0;
bool result = true;
for (size_t i = 1; result; i++)
{
size_t numBytes = i * 1024 * 1024;
result = memTester.resize(numBytes, false);
if (result)
{
maxMem = numBytes;
}
else
{
break;
}
}
printf("allocated %d MB successfully\n", maxMem / (1024 * 1024));
clReleaseCommandQueue(g_cqCommandQue);
g_cqCommandQue = 0;
}
clReleaseContext(g_cxMainContext);
g_cxMainContext = 0;
}
///Easier method to initialize OpenCL using createContextFromType for a GPU
deviceType = CL_DEVICE_TYPE_GPU;
void* glCtx = 0;
void* glDC = 0;
b3Printf("Initialize OpenCL using b3OpenCLUtils::createContextFromType for CL_DEVICE_TYPE_GPU\n");
g_cxMainContext = b3OpenCLUtils::createContextFromType(deviceType, &ciErrNum, glCtx, glDC);
oclCHECKERROR(ciErrNum, CL_SUCCESS);
if (g_cxMainContext)
{
int numDev = b3OpenCLUtils::getNumDevices(g_cxMainContext);
for (int i = 0; i < numDev; i++)
{
cl_device_id device;
device = b3OpenCLUtils::getDevice(g_cxMainContext, i);
b3OpenCLDeviceInfo clInfo;
b3OpenCLUtils::getDeviceInfo(device, &clInfo);
b3OpenCLUtils::printDeviceInfo(device);
// create a command-queue
g_cqCommandQue = clCreateCommandQueue(g_cxMainContext, device, 0, &ciErrNum);
oclCHECKERROR(ciErrNum, CL_SUCCESS);
//normally you would create and execute kernels using this command queue
int maxMem = 0;
{
b3OpenCLArray<char> memTester(g_cxMainContext, g_cqCommandQue, 0, true);
bool result = true;
for (size_t i = 1; result; i++)
{
size_t numBytes = i * 1024 * 1024;
result = memTester.resize(numBytes, false);
if (result)
{
maxMem = numBytes;
}
else
{
break;
}
}
printf("allocated %d MB successfully\n", maxMem / (1024 * 1024));
}
clReleaseCommandQueue(g_cqCommandQue);
}
clReleaseContext(g_cxMainContext);
}
else
{
b3Printf("No OpenCL capable GPU found!");
}
b3Printf("press <Enter>\n");
getchar();
return 0;
}

View file

@ -0,0 +1,33 @@
function createProject(vendor)
hasCL = findOpenCL(vendor)
if (hasCL) then
project ("Test_OpenCL_intialize_" .. vendor)
initOpenCL(vendor)
language "C++"
kind "ConsoleApp"
includedirs {"../../../src"}
files {
"main.cpp",
"../../../src/Bullet3OpenCL/Initialize/b3OpenCLUtils.cpp",
"../../../src/Bullet3Common/b3AlignedAllocator.cpp",
"../../../src/Bullet3OpenCL/Initialize/b3OpenCLUtils.h",
"../../../src/Bullet3Common/b3Logging.cpp",
}
end
end
createProject("clew")
createProject("Apple")
createProject("AMD")
createProject("Intel")
createProject("NVIDIA")

View file

@ -0,0 +1,111 @@
#include <gtest/gtest.h>
#include "Bullet3Common/b3Logging.h"
#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
TEST(b3OpenCLUtils, getNumPlatforms)
{
int numPlatforms = b3OpenCLUtils::getNumPlatforms();
ASSERT_GT(numPlatforms, 0);
}
TEST(b3OpenCLUtils, getSdkVendorName)
{
const char* vendorSDK = b3OpenCLUtils::getSdkVendorName();
b3Printf("getSdkVendorName=%s\n", vendorSDK);
ASSERT_FALSE(vendorSDK == NULL);
}
TEST(b3OpenCLUtils, getPlatformInfo)
{
int numPlatforms = b3OpenCLUtils::getNumPlatforms();
ASSERT_GT(numPlatforms, 0);
b3Printf("Num Platforms = %d\n", numPlatforms);
for (int i = 0; i < numPlatforms; i++)
{
cl_platform_id platform = b3OpenCLUtils::getPlatform(i);
ASSERT_FALSE(platform == NULL);
b3OpenCLPlatformInfo platformInfo;
b3OpenCLUtils::getPlatformInfo(platform, &platformInfo);
ASSERT_FALSE(platformInfo.m_platformName == NULL);
ASSERT_FALSE(platformInfo.m_platformVendor == NULL);
ASSERT_FALSE(platformInfo.m_platformVersion == NULL);
}
}
TEST(b3OpenCLUtils, createContextFromPlatform)
{
int numPlatforms = b3OpenCLUtils::getNumPlatforms();
b3Printf("Num Platforms = %d\n", numPlatforms);
cl_device_type deviceType = CL_DEVICE_TYPE_ALL;
int ciErrNum = 0;
for (int i = 0; i < numPlatforms; i++)
{
cl_platform_id platform = b3OpenCLUtils::getPlatform(i);
b3OpenCLPlatformInfo platformInfo;
b3OpenCLUtils::getPlatformInfo(platform, &platformInfo);
b3Printf("--------------------------------\n");
b3Printf("Platform info for platform nr %d:\n", i);
b3Printf(" CL_PLATFORM_VENDOR: \t\t\t%s\n", platformInfo.m_platformVendor);
b3Printf(" CL_PLATFORM_NAME: \t\t\t%s\n", platformInfo.m_platformName);
b3Printf(" CL_PLATFORM_VERSION: \t\t\t%s\n", platformInfo.m_platformVersion);
cl_context ctx = b3OpenCLUtils::createContextFromPlatform(platform, deviceType, &ciErrNum);
ASSERT_FALSE(ctx == 0);
ASSERT_EQ(CL_SUCCESS, ciErrNum);
clReleaseContext(ctx);
}
}
TEST(b3OpenCLUtils, getDeviceAndQueue)
{
int numPlatforms = b3OpenCLUtils::getNumPlatforms();
b3Printf("Num Platforms = %d\n", numPlatforms);
cl_device_type deviceType = CL_DEVICE_TYPE_ALL;
int ciErrNum = 0;
for (int i = 0; i < numPlatforms; i++)
{
cl_platform_id platform = b3OpenCLUtils::getPlatform(i);
b3OpenCLPlatformInfo platformInfo;
b3OpenCLUtils::getPlatformInfo(platform, &platformInfo);
b3Printf("--------------------------------\n");
b3Printf("Platform info for platform nr %d:\n", i);
b3Printf(" CL_PLATFORM_VENDOR: \t\t\t%s\n", platformInfo.m_platformVendor);
b3Printf(" CL_PLATFORM_NAME: \t\t\t%s\n", platformInfo.m_platformName);
b3Printf(" CL_PLATFORM_VERSION: \t\t\t%s\n", platformInfo.m_platformVersion);
cl_context ctx = b3OpenCLUtils::createContextFromPlatform(platform, deviceType, &ciErrNum);
ASSERT_FALSE(ctx == 0);
ASSERT_EQ(CL_SUCCESS, ciErrNum);
int numDevices = b3OpenCLUtils::getNumDevices(ctx);
ASSERT_GT(numDevices, 0);
b3Printf("Num Devices = %d\n", numDevices);
for (int j = 0; j < numDevices; j++)
{
cl_device_id device = b3OpenCLUtils::getDevice(ctx, j);
b3OpenCLDeviceInfo devInfo;
b3OpenCLUtils::getDeviceInfo(device, &devInfo);
ASSERT_GT(devInfo.m_clockFrequency, 0);
ASSERT_GT(devInfo.m_addressBits, 0);
ASSERT_GT(devInfo.m_computeUnits, 0);
ASSERT_GT(devInfo.m_constantBufferSize, 0);
ASSERT_FALSE(devInfo.m_deviceName == NULL);
ASSERT_FALSE(devInfo.m_deviceVendor == NULL);
ASSERT_FALSE(devInfo.m_driverVersion == NULL);
ASSERT_GT(devInfo.m_globalMemSize, 0);
b3OpenCLUtils::printDeviceInfo(device);
cl_command_queue q = clCreateCommandQueue(ctx, device, 0, &ciErrNum);
ASSERT_FALSE(q == 0);
clReleaseCommandQueue(q);
q = 0;
}
clReleaseContext(ctx);
}
}

View file

@ -0,0 +1,201 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2011 Advanced Micro Devices, Inc. http://bulletphysics.org
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.
*/
///original author: Erwin Coumans
#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
#include "Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h"
#include "Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h"
#include <stdio.h>
#include <string.h>
#include "Bullet3Common/shared/b3Float4.h"
//typedef b3Vector3 b3Float4;
typedef struct b3Contact4Data b3Contact4Data_t;
struct b3Contact4Data
{
b3Float4 m_worldPos[4];
b3Float4 m_localPosA[4];
b3Float4 m_localPosB[4];
b3Float4 m_worldNormal; // w: m_nPoints
unsigned short m_restituitionCoeffCmp;
unsigned short m_frictionCoeffCmp;
int m_batchIdx;
int m_bodyAPtrAndSignBit; //x:m_bodyAPtr, y:m_bodyBPtr
int m_bodyBPtrAndSignBit;
int m_childIndexA;
int m_childIndexB;
int m_unused1;
int m_unused2;
};
#define MSTRINGIFY(A) #A
static const char* s_testKernelString = MSTRINGIFY(
struct MyTest {
int bla;
};
typedef float4 b3Float4;
typedef struct b3Contact4Data b3Contact4Data_t;
struct b3Contact4Data {
b3Float4 m_worldPos[4];
b3Float4 m_localPosA[4];
b3Float4 m_localPosB[4];
b3Float4 m_worldNormal; // w: m_nPoints
unsigned short m_restituitionCoeffCmp;
unsigned short m_frictionCoeffCmp;
int m_batchIdx;
int m_bodyAPtrAndSignBit; //x:m_bodyAPtr, y:m_bodyBPtr
int m_bodyBPtrAndSignBit;
int m_childIndexA;
int m_childIndexB;
int m_unused1;
int m_unused2;
};
inline int b3Contact4Data_getNumPoints(const struct b3Contact4Data* contact) {
return (int)contact->m_worldNormal.w;
};
inline void b3Contact4Data_setNumPoints(struct b3Contact4Data* contact, int numPoints) {
contact->m_worldNormal.w = (float)numPoints;
};
typedef volatile __global int* my_counter32_t;
__kernel void testKernel(__global int* testData, __global b3Contact4Data_t* contactData, my_counter32_t numElements) {
int id = get_local_id(0);
int sz = sizeof(b3Contact4Data_t);
testData[id] = sz;
__private b3Contact4Data_t tmp;
if (id == 0)
{
tmp = contactData[1];
contactData[1] = contactData[0];
contactData[0] = tmp;
}
}
);
#include "Bullet3Common/b3Logging.h"
void myprintf(const char* msg)
{
//OutputDebugStringA(msg);
printf("%s", msg);
}
int main(int argc, char* argv[])
{
b3SetCustomPrintfFunc(myprintf);
//b3SetCustomWarningMessageFunc(myprintf);
//b3SetCustomErrorMessageFunc(myprintf);
b3Printf("test b3Printf\n");
b3Warning("test warning\n");
b3Error("test error\n");
int ciErrNum = 0;
cl_device_type deviceType = CL_DEVICE_TYPE_GPU;
const char* vendorSDK = b3OpenCLUtils::getSdkVendorName();
b3Printf("This program was compiled using the %s OpenCL SDK\n", vendorSDK);
int numPlatforms = b3OpenCLUtils::getNumPlatforms();
b3Printf("Num Platforms = %d\n", numPlatforms);
for (int i = 0; i < numPlatforms; i++)
{
cl_platform_id platform = b3OpenCLUtils::getPlatform(i);
b3OpenCLPlatformInfo platformInfo;
b3OpenCLUtils::getPlatformInfo(platform, &platformInfo);
b3Printf("--------------------------------\n");
b3Printf("Platform info for platform nr %d:\n", i);
b3Printf(" CL_PLATFORM_VENDOR: \t\t\t%s\n", platformInfo.m_platformVendor);
b3Printf(" CL_PLATFORM_NAME: \t\t\t%s\n", platformInfo.m_platformName);
b3Printf(" CL_PLATFORM_VERSION: \t\t\t%s\n", platformInfo.m_platformVersion);
cl_context context = b3OpenCLUtils::createContextFromPlatform(platform, deviceType, &ciErrNum);
if (context)
{
int numDevices = b3OpenCLUtils::getNumDevices(context);
b3Printf("Num Devices = %d\n", numDevices);
for (int j = 0; j < numDevices; j++)
{
cl_device_id dev = b3OpenCLUtils::getDevice(context, j);
b3OpenCLDeviceInfo devInfo;
b3OpenCLUtils::getDeviceInfo(dev, &devInfo);
b3OpenCLUtils::printDeviceInfo(dev);
int errNum;
cl_command_queue queue = clCreateCommandQueue(context, dev, 0, &errNum);
cl_program pairBenchProg = 0;
cl_kernel testKernel = b3OpenCLUtils::compileCLKernelFromString(context, dev, s_testKernelString, "testKernel", &errNum, pairBenchProg);
if (testKernel)
{
printf("kernel compiled ok\n");
int numWorkItems = 64;
b3OpenCLArray<int> deviceElements(context, queue);
b3OpenCLArray<int> atomicCounter(context, queue);
b3OpenCLArray<b3Contact4Data> deviceContacts(context, queue);
b3AlignedObjectArray<b3Contact4Data> hostContacts;
b3Contact4Data tmp;
int sz = sizeof(b3Contact4Data);
memset(&tmp, 1, sz);
deviceContacts.push_back(tmp);
b3Contact4Data tmp2 = tmp;
memset(&tmp, 2, sz);
deviceContacts.push_back(tmp);
b3Contact4Data tmp3 = tmp;
atomicCounter.push_back(0);
deviceElements.resize(numWorkItems);
b3LauncherCL run(queue, testKernel, "testKernel");
run.setBuffer(deviceElements.getBufferCL());
run.setBuffer(deviceContacts.getBufferCL());
run.setBuffer(atomicCounter.getBufferCL());
run.launch1D(numWorkItems);
b3AlignedObjectArray<int> hostElements;
deviceElements.copyToHost(hostElements);
deviceContacts.copyToHost(hostContacts);
tmp2 = hostContacts[0];
tmp3 = hostContacts[1];
printf("...\n");
}
else
{
printf("kernel failed to compile\n");
}
}
}
clReleaseContext(context);
}
b3Printf("\npress <Enter>\n");
getchar();
return 0;
}

View file

@ -0,0 +1,34 @@
function createProject(vendor)
hasCL = findOpenCL(vendor)
if (hasCL) then
project ("Test_OpenCL_kernel_launch_" .. vendor)
initOpenCL(vendor)
language "C++"
kind "ConsoleApp"
includedirs {"../../../src"}
files {
"main.cpp",
"../../../src/Bullet3OpenCL/Initialize/b3OpenCLUtils.cpp",
"../../../src/Bullet3Common/b3AlignedAllocator.cpp",
"../../../src/Bullet3OpenCL/Initialize/b3OpenCLUtils.h",
"../../../src/Bullet3Common/b3Logging.cpp",
"../../../src/Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.cpp"
}
end
end
createProject("clew")
createProject("Apple")
createProject("AMD")
createProject("Intel")
createProject("NVIDIA")

View file

@ -0,0 +1,368 @@
/*
Copyright (c) 2012 Advanced Micro Devices, Inc.
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 <stdio.h>
#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
#include "Bullet3OpenCL/ParallelPrimitives/b3FillCL.h"
#include "Bullet3OpenCL/ParallelPrimitives/b3BoundSearchCL.h"
#include "Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.h"
#include "Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.h"
#include "Bullet3Common/b3CommandLineArgs.h"
#include "Bullet3Common/b3MinMax.h"
int g_nPassed = 0;
int g_nFailed = 0;
bool g_testFailed = 0;
#define TEST_INIT g_testFailed = 0;
#define TEST_ASSERT(x) \
if (!(x)) \
{ \
g_testFailed = 1; \
}
#define TEST_REPORT(testName) \
printf("[%s] %s\n", (g_testFailed) ? "X" : "O", testName); \
if (g_testFailed) \
g_nFailed++; \
else \
g_nPassed++;
#define NEXTMULTIPLEOF(num, alignment) (((num) / (alignment) + (((num) % (alignment) == 0) ? 0 : 1)) * (alignment))
cl_context g_context = 0;
cl_device_id g_device = 0;
cl_command_queue g_queue = 0;
const char* g_deviceName = 0;
void initCL(int preferredDeviceIndex, int preferredPlatformIndex)
{
//void* glCtx=0;
//void* glDC = 0;
int ciErrNum = 0;
//bound search and radix sort only work on GPU right now (assume 32 or 64 width workgroup without barriers)
cl_device_type deviceType = CL_DEVICE_TYPE_ALL;
g_context = b3OpenCLUtils::createContextFromType(deviceType, &ciErrNum, 0, 0, preferredDeviceIndex, preferredPlatformIndex);
oclCHECKERROR(ciErrNum, CL_SUCCESS);
int numDev = b3OpenCLUtils::getNumDevices(g_context);
if (numDev > 0)
{
b3OpenCLDeviceInfo info;
g_device = b3OpenCLUtils::getDevice(g_context, 0);
g_queue = clCreateCommandQueue(g_context, g_device, 0, &ciErrNum);
oclCHECKERROR(ciErrNum, CL_SUCCESS);
b3OpenCLUtils::printDeviceInfo(g_device);
b3OpenCLUtils::getDeviceInfo(g_device, &info);
g_deviceName = info.m_deviceName;
}
}
void exitCL()
{
clReleaseCommandQueue(g_queue);
clReleaseContext(g_context);
}
inline void fillIntTest()
{
TEST_INIT;
b3FillCL* fillCL = new b3FillCL(g_context, g_device, g_queue);
int maxSize = 1024 * 256;
b3OpenCLArray<int> intBuffer(g_context, g_queue, maxSize);
intBuffer.resize(maxSize);
#define NUM_TESTS 7
int dx = maxSize / NUM_TESTS;
for (int iter = 0; iter < NUM_TESTS; iter++)
{
int size = b3Min(11 + dx * iter, maxSize);
int value = 2;
int offset = 0;
fillCL->execute(intBuffer, value, size, offset);
b3AlignedObjectArray<int> hostBuf2;
hostBuf2.resize(size);
fillCL->executeHost(hostBuf2, value, size, offset);
b3AlignedObjectArray<int> hostBuf;
intBuffer.copyToHost(hostBuf);
for (int i = 0; i < size; i++)
{
TEST_ASSERT(hostBuf[i] == hostBuf2[i]);
TEST_ASSERT(hostBuf[i] == hostBuf2[i]);
}
}
delete fillCL;
TEST_REPORT("fillIntTest");
}
__inline void seedRandom(int seed)
{
srand(seed);
}
template <typename T>
__inline T getRandom(const T& minV, const T& maxV)
{
float r = (rand() % 10000) / 10000.f;
T range = maxV - minV;
return (T)(minV + r * range);
}
struct b3SortDataCompare
{
inline bool operator()(const b3SortData& first, const b3SortData& second) const
{
return (first.m_key < second.m_key) || (first.m_key == second.m_key && first.m_value < second.m_value);
}
};
void boundSearchTest()
{
TEST_INIT;
int maxSize = 1024 * 256;
int bucketSize = 256;
b3OpenCLArray<b3SortData> srcCL(g_context, g_queue, maxSize);
b3OpenCLArray<unsigned int> upperCL(g_context, g_queue, maxSize);
b3OpenCLArray<unsigned int> lowerCL(g_context, g_queue, maxSize);
b3AlignedObjectArray<b3SortData> srcHost;
b3AlignedObjectArray<unsigned int> upperHost;
b3AlignedObjectArray<unsigned int> lowerHost;
b3AlignedObjectArray<unsigned int> upperHostCompare;
b3AlignedObjectArray<unsigned int> lowerHostCompare;
b3BoundSearchCL* search = new b3BoundSearchCL(g_context, g_device, g_queue, maxSize);
int dx = maxSize / NUM_TESTS;
for (int iter = 0; iter < NUM_TESTS; iter++)
{
int size = b3Min(128 + dx * iter, maxSize);
upperHost.resize(bucketSize);
lowerHost.resize(bucketSize);
upperHostCompare.resize(bucketSize);
lowerHostCompare.resize(bucketSize);
srcHost.resize(size);
for (int i = 0; i < size; i++)
{
b3SortData v;
// v.m_key = i<2? 0 : 5;
v.m_key = getRandom(0, bucketSize);
v.m_value = i;
srcHost.at(i) = v;
}
srcHost.quickSort(b3SortDataCompare());
srcCL.copyFromHost(srcHost);
{
for (int i = 0; i < bucketSize; i++)
{
lowerHost[i] = -1;
lowerHostCompare[i] = -1;
upperHost[i] = -1;
upperHostCompare[i] = -1;
}
upperCL.copyFromHost(upperHost);
lowerCL.copyFromHost(lowerHost);
}
search->execute(srcCL, size, upperCL, bucketSize, b3BoundSearchCL::BOUND_UPPER);
search->execute(srcCL, size, lowerCL, bucketSize, b3BoundSearchCL::BOUND_LOWER);
search->executeHost(srcHost, size, upperHostCompare, bucketSize, b3BoundSearchCL::BOUND_UPPER);
search->executeHost(srcHost, size, lowerHostCompare, bucketSize, b3BoundSearchCL::BOUND_LOWER);
lowerCL.copyToHost(lowerHost);
upperCL.copyToHost(upperHost);
for (int i = 0; i < bucketSize; i++)
{
TEST_ASSERT(upperHostCompare[i] == upperHost[i]);
TEST_ASSERT(lowerHostCompare[i] == lowerHost[i]);
}
/*
for(int i=1; i<bucketSize; i++)
{
int lhi_1 = lowerHost[i-1];
int lhi = lowerHost[i];
for(int j=lhi_1; j<lhi; j++)
//for(int j=lowerHost[i-1]; j<lowerHost[i]; j++)
{
TEST_ASSERT( srcHost[j].m_key < i );
}
}
for(int i=0; i<bucketSize; i++)
{
int jMin = (i==0)?0:upperHost[i-1];
for(int j=jMin; j<upperHost[i]; j++)
{
TEST_ASSERT( srcHost[j].m_key <= i );
}
}
*/
for (int i = 0; i < bucketSize; i++)
{
int lhi = lowerHost[i];
int uhi = upperHost[i];
for (int j = lhi; j < uhi; j++)
{
if (srcHost[j].m_key != i)
{
printf("error %d != %d\n", srcHost[j].m_key, i);
}
TEST_ASSERT(srcHost[j].m_key == i);
}
}
}
delete search;
TEST_REPORT("boundSearchTest");
}
void prefixScanTest()
{
TEST_INIT;
int maxSize = 1024 * 256;
b3AlignedObjectArray<unsigned int> buf0Host;
b3AlignedObjectArray<unsigned int> buf1Host;
b3OpenCLArray<unsigned int> buf2CL(g_context, g_queue, maxSize);
b3OpenCLArray<unsigned int> buf3CL(g_context, g_queue, maxSize);
b3PrefixScanCL* scan = new b3PrefixScanCL(g_context, g_device, g_queue, maxSize);
int dx = maxSize / NUM_TESTS;
for (int iter = 0; iter < NUM_TESTS; iter++)
{
int size = b3Min(128 + dx * iter, maxSize);
buf0Host.resize(size);
buf1Host.resize(size);
for (int i = 0; i < size; i++)
buf0Host[i] = 1;
buf2CL.copyFromHost(buf0Host);
unsigned int sumHost, sumGPU;
scan->executeHost(buf0Host, buf1Host, size, &sumHost);
scan->execute(buf2CL, buf3CL, size, &sumGPU);
buf3CL.copyToHost(buf0Host);
TEST_ASSERT(sumHost == sumGPU);
for (int i = 0; i < size; i++)
TEST_ASSERT(buf1Host[i] == buf0Host[i]);
}
delete scan;
TEST_REPORT("scanTest");
}
bool radixSortTest()
{
TEST_INIT;
int maxSize = 1024 * 256;
b3AlignedObjectArray<b3SortData> buf0Host;
buf0Host.resize(maxSize);
b3AlignedObjectArray<b3SortData> buf1Host;
buf1Host.resize(maxSize);
b3OpenCLArray<b3SortData> buf2CL(g_context, g_queue, maxSize);
b3RadixSort32CL* sort = new b3RadixSort32CL(g_context, g_device, g_queue, maxSize);
int dx = maxSize / NUM_TESTS;
for (int iter = 0; iter < NUM_TESTS; iter++)
{
int size = b3Min(128 + dx * iter, maxSize - 512);
size = NEXTMULTIPLEOF(size, 512); //not necessary
buf0Host.resize(size);
for (int i = 0; i < size; i++)
{
b3SortData v;
v.m_key = getRandom(0, 0xff);
v.m_value = i;
buf0Host[i] = v;
}
buf2CL.copyFromHost(buf0Host);
sort->executeHost(buf0Host);
sort->execute(buf2CL);
buf2CL.copyToHost(buf1Host);
for (int i = 0; i < size; i++)
{
TEST_ASSERT(buf0Host[i].m_value == buf1Host[i].m_value && buf0Host[i].m_key == buf1Host[i].m_key);
}
}
delete sort;
TEST_REPORT("radixSort");
return g_testFailed;
}
int main(int argc, char** argv)
{
int preferredDeviceIndex = -1;
int preferredPlatformIndex = -1;
b3CommandLineArgs args(argc, argv);
args.GetCmdLineArgument("deviceId", preferredDeviceIndex);
args.GetCmdLineArgument("platformId", preferredPlatformIndex);
initCL(preferredDeviceIndex, preferredPlatformIndex);
fillIntTest();
boundSearchTest();
prefixScanTest();
radixSortTest();
exitCL();
printf("%d tests passed, %d tests failed\n", g_nPassed, g_nFailed);
printf("End, press <enter>\n");
getchar();
}

View file

@ -0,0 +1,46 @@
function createProject(vendor)
hasCL = findOpenCL(vendor)
if (hasCL) then
project ("Test_OpenCL_Primitives_" .. vendor)
initOpenCL(vendor)
language "C++"
kind "ConsoleApp"
includedirs {".","../../../src"}
files {
"main.cpp",
"../../../src/Bullet3OpenCL/Initialize/b3OpenCLInclude.h",
"../../../src/Bullet3OpenCL/Initialize/b3OpenCLUtils.cpp",
"../../../src/Bullet3OpenCL/Initialize/b3OpenCLUtils.h",
"../../../src/Bullet3OpenCL/ParallelPrimitives/b3FillCL.cpp",
"../../../src/Bullet3OpenCL/ParallelPrimitives/b3FillCL.h",
"../../../src/Bullet3OpenCL/ParallelPrimitives/b3BoundSearchCL.cpp",
"../../../src/Bullet3OpenCL/ParallelPrimitives/b3BoundSearchCL.h",
"../../../src/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.cpp",
"../../../src/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.h",
"../../../src/Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.cpp",
"../../../src/Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.h",
"../../../src/Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.cpp",
"../../../src/Bullet3Common/b3AlignedAllocator.cpp",
"../../../src/Bullet3Common/b3AlignedAllocator.h",
"../../../src/Bullet3Common/b3AlignedObjectArray.h",
"../../../src/Bullet3Common/b3Logging.cpp",
"../../../src/Bullet3Common/b3Logging.h",
}
end
end
createProject("clew")
createProject("AMD")
createProject("Intel")
createProject("NVIDIA")
createProject("Apple")

View file

@ -0,0 +1,707 @@
/******************************************************************************
* Copyright 2010 Duane Merrill
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may ob3ain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*
*
*
* AUTHORS' REQUEST:
*
* If you use|reference|benchmark this code, please cite our Technical
* Report (http://www.cs.virginia.edu/~dgm4d/papers/RadixSortTR.pdf):
*
* @TechReport{ Merrill:Sorting:2010,
* author = "Duane Merrill and Andrew Grimshaw",
* title = "Revisiting Sorting for GPGPU Stream Architectures",
* year = "2010",
* institution = "University of Virginia, Department of Computer Science",
* address = "Charlottesville, VA, USA",
* number = "CS2010-03"
* }
*
* For more information, see our Google Code project site:
* http://code.google.com/p/back40computing/
*
* Thanks!
******************************************************************************/
/******************************************************************************
* Simple test driver program for *large-problem* radix sorting.
*
* Useful for demonstrating how to integrate radix sorting into
* your application
******************************************************************************/
/******************************************************************************
* Converted from CUDA to OpenCL/DirectCompute by Erwin Coumans
******************************************************************************/
#ifdef _WIN32
#pragma warning(disable : 4996)
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <float.h>
#include <algorithm>
#include <string>
//#include <iostream>
#include <sstream>
/**********************
*
*/
#include "Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.h"
#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
#include "../btgui/Bullet3AppSupport/b3Clock.h"
cl_context g_cxMainContext;
cl_device_id g_device;
cl_command_queue g_cqCommandQueue;
/***********************
*
*/
bool g_verbose;
///Preferred OpenCL device/platform. When < 0 then no preference is used.
///Note that b3OpenCLUtils might still use the preference of using a platform vendor that matches the SDK vendor used to build the application.
///Preferred device/platform take priority over this platform-vendor match
int gPreferredDeviceId = -1;
int gPreferredPlatformId = -1;
/******************************************************************************
* Routines
******************************************************************************/
/**
* Keys-only sorting. Uses the GPU to sort the specified vector of elements for the given
* number of iterations, displaying runtime information.
*
* @param[in] num_elements
* Size in elements of the vector to sort
* @param[in] h_keys
* Vector of keys to sort
* @param[in] iterations
* Number of times to invoke the GPU sorting primitive
* @param[in] cfg
* Config
*/
template <typename K>
void TimedSort(
unsigned int num_elements,
K *h_keys,
unsigned int iterations)
{
printf("Keys only, %d iterations, %d elements\n", iterations, num_elements);
int max_elements = num_elements;
b3AlignedObjectArray<unsigned int> hostData;
hostData.resize(num_elements);
for (int i = 0; i < num_elements; i++)
{
hostData[i] = h_keys[i];
}
b3RadixSort32CL sorter(g_cxMainContext, g_device, g_cqCommandQueue);
b3OpenCLArray<unsigned int> gpuData(g_cxMainContext, g_cqCommandQueue);
gpuData.copyFromHost(hostData);
//sorter.executeHost(gpuData);
sorter.execute(gpuData);
b3AlignedObjectArray<unsigned int> hostDataSorted;
gpuData.copyToHost(hostDataSorted);
clFinish(g_cqCommandQueue);
{
//printf("Key-values, %d iterations, %d elements", iterations, num_elements);
// Create sorting enactor
// Perform the timed number of sorting iterations
double elapsed = 0;
float duration = 0;
b3Clock watch;
//warm-start
gpuData.copyFromHost(hostData);
clFinish(g_cqCommandQueue);
sorter.execute(gpuData);
watch.reset();
for (int i = 0; i < iterations; i++)
{
// Move a fresh copy of the problem into device storage
gpuData.copyFromHost(hostData);
clFinish(g_cqCommandQueue);
// Start GPU timing record
double startMs = watch.getTimeMicroseconds() / 1e3;
// Call the sorting API routine
sorter.execute(gpuData);
clFinish(g_cqCommandQueue);
double stopMs = watch.getTimeMicroseconds() / 1e3;
duration = stopMs - startMs;
// End GPU timing record
elapsed += (double)duration;
printf("duration = %f\n", duration);
}
// Display timing information
double avg_runtime = elapsed / iterations;
// double throughput = ((double) num_elements) / avg_runtime / 1000.0 / 1000.0;
// printf(", %f GPU ms, %f x10^9 elts/sec\n", avg_runtime, throughput);
double throughput = ((double)num_elements) / avg_runtime / 1000.0;
printf(", %f GPU ms, %f x10^6 elts/sec\n", avg_runtime, throughput);
gpuData.copyToHost(hostData);
for (int i = 0; i < num_elements; i++)
{
h_keys[i] = hostData[i];
}
}
}
/**
* Key-value sorting. Uses the GPU to sort the specified vector of elements for the given
* number of iterations, displaying runtime information.
*
* @param[in] num_elements
* Size in elements of the vector to sort
* @param[in] h_keys
* Vector of keys to sort
* @param[in,out] h_values
* Vector of values to sort
* @param[in] iterations
* Number of times to invoke the GPU sorting primitive
* @param[in] cfg
* Config
*/
template <typename K, typename V>
void TimedSort(
unsigned int num_elements,
K *h_keys,
V *h_values,
unsigned int iterations)
{
printf("Key-values, %d iterations, %d elements\n", iterations, num_elements);
int max_elements = num_elements;
b3AlignedObjectArray<b3SortData> hostData;
hostData.resize(num_elements);
for (int i = 0; i < num_elements; i++)
{
hostData[i].m_key = h_keys[i];
hostData[i].m_value = h_values[i];
}
b3RadixSort32CL sorter(g_cxMainContext, g_device, g_cqCommandQueue);
b3OpenCLArray<b3SortData> gpuData(g_cxMainContext, g_cqCommandQueue);
gpuData.copyFromHost(hostData);
//sorter.executeHost(gpuData);
sorter.execute(gpuData);
b3AlignedObjectArray<b3SortData> hostDataSorted;
gpuData.copyToHost(hostDataSorted);
#if 0
for (int i=0;i<num_elements;i++)
{
printf("hostData[%d].m_key = %d\n",i, hostDataSorted[i].m_key);
printf("hostData[%d].m_value = %d\n",i,hostDataSorted[i].m_value);
}
#endif
clFinish(g_cqCommandQueue);
{
//printf("Key-values, %d iterations, %d elements", iterations, num_elements);
// Create sorting enactor
// Perform the timed number of sorting iterations
double elapsed = 0;
float duration = 0;
b3Clock watch;
//warm-start
gpuData.copyFromHost(hostData);
sorter.execute(gpuData);
clFinish(g_cqCommandQueue);
watch.reset();
for (int i = 0; i < iterations; i++)
{
// Move a fresh copy of the problem into device storage
gpuData.copyFromHost(hostData);
clFinish(g_cqCommandQueue);
// Start GPU timing record
double startMs = watch.getTimeMicroseconds() / 1e3;
// Call the sorting API routine
sorter.execute(gpuData);
clFinish(g_cqCommandQueue);
double stopMs = watch.getTimeMicroseconds() / 1e3;
duration = stopMs - startMs;
// End GPU timing record
elapsed += (double)duration;
printf("duration = %f\n", duration);
}
// Display timing information
double avg_runtime = elapsed / iterations;
// double throughput = ((double) num_elements) / avg_runtime / 1000.0 / 1000.0;
// printf(", %f GPU ms, %f x10^9 elts/sec\n", avg_runtime, throughput);
double throughput = ((double)num_elements) / avg_runtime / 1000.0;
printf(", %f GPU ms, %f x10^6 elts/sec\n", avg_runtime, throughput);
gpuData.copyToHost(hostData);
for (int i = 0; i < num_elements; i++)
{
h_keys[i] = hostData[i].m_key;
h_values[i] = hostData[i].m_value;
}
}
}
/**
* Generates random 32-bit keys.
*
* We always take the second-order byte from rand() because the higher-order
* bits returned by rand() are commonly considered more uniformly distributed
* than the lower-order bits.
*
* We can decrease the entropy level of keys by adopting the technique
* of Thearling and Smith in which keys are computed from the bitwise AND of
* multiple random samples:
*
* entropy_reduction | Effectively-unique bits per key
* -----------------------------------------------------
* -1 | 0
* 0 | 32
* 1 | 25.95
* 2 | 17.41
* 3 | 10.78
* 4 | 6.42
* ... | ...
*
*/
template <typename K>
void RandomBits(K &key, int entropy_reduction = 0, int lower_key_bits = sizeof(K) * 8)
{
const unsigned int NUM_UCHARS = (sizeof(K) + sizeof(unsigned char) - 1) / sizeof(unsigned char);
unsigned char key_bits[NUM_UCHARS];
do
{
for (int j = 0; j < NUM_UCHARS; j++)
{
unsigned char quarterword = 0xff;
for (int i = 0; i <= entropy_reduction; i++)
{
quarterword &= (rand() >> 7);
}
key_bits[j] = quarterword;
}
if (lower_key_bits < sizeof(K) * 8)
{
unsigned long long base = 0;
memcpy(&base, key_bits, sizeof(K));
base &= (1 << lower_key_bits) - 1;
memcpy(key_bits, &base, sizeof(K));
}
memcpy(&key, key_bits, sizeof(K));
} while (key != key); // avoids NaNs when generating random floating point numbers
}
/******************************************************************************
* Templated routines for printing keys/values to the console
******************************************************************************/
template <typename T>
void PrintValue(T val)
{
printf("%d", val);
}
template <>
void PrintValue<float>(float val)
{
printf("%f", val);
}
template <>
void PrintValue<double>(double val)
{
printf("%f", val);
}
template <>
void PrintValue<unsigned char>(unsigned char val)
{
printf("%u", val);
}
template <>
void PrintValue<unsigned short>(unsigned short val)
{
printf("%u", val);
}
template <>
void PrintValue<unsigned int>(unsigned int val)
{
printf("%u", val);
}
template <>
void PrintValue<long>(long val)
{
printf("%ld", val);
}
template <>
void PrintValue<unsigned long>(unsigned long val)
{
printf("%lu", val);
}
template <>
void PrintValue<long long>(long long val)
{
printf("%lld", val);
}
template <>
void PrintValue<unsigned long long>(unsigned long long val)
{
printf("%llu", val);
}
/**
* Compares the equivalence of two arrays
*/
template <typename T, typename SizeT>
int CompareResults(T *computed, T *reference, SizeT len, bool verbose = true)
{
printf("\n");
for (SizeT i = 0; i < len; i++)
{
if (computed[i] != reference[i])
{
printf("INCORRECT: [%lu]: ", (unsigned long)i);
PrintValue<T>(computed[i]);
printf(" != ");
PrintValue<T>(reference[i]);
if (verbose)
{
printf("\nresult[...");
for (size_t j = (i >= 5) ? i - 5 : 0; (j < i + 5) && (j < len); j++)
{
PrintValue<T>(computed[j]);
printf(", ");
}
printf("...]");
printf("\nreference[...");
for (size_t j = (i >= 5) ? i - 5 : 0; (j < i + 5) && (j < len); j++)
{
PrintValue<T>(reference[j]);
printf(", ");
}
printf("...]");
}
return 1;
}
}
printf("CORRECT\n");
return 0;
}
/**
* Creates an example sorting problem whose keys is a vector of the specified
* number of K elements, values of V elements, and then dispatches the problem
* to the GPU for the given number of iterations, displaying runtime information.
*
* @param[in] iterations
* Number of times to invoke the GPU sorting primitive
* @param[in] num_elements
* Size in elements of the vector to sort
* @param[in] cfg
* Config
*/
template <typename K, typename V>
void TestSort(
unsigned int iterations,
int num_elements,
bool keys_only)
{
// Allocate the sorting problem on the host and fill the keys with random bytes
K *h_keys = NULL;
K *h_reference_keys = NULL;
V *h_values = NULL;
h_keys = (K *)malloc(num_elements * sizeof(K));
h_reference_keys = (K *)malloc(num_elements * sizeof(K));
if (!keys_only) h_values = (V *)malloc(num_elements * sizeof(V));
// Use random bits
for (unsigned int i = 0; i < num_elements; ++i)
{
RandomBits<K>(h_keys[i], 0);
//h_keys[i] = num_elements-i;
//h_keys[i] = 0xffffffffu-i;
if (!keys_only)
h_values[i] = h_keys[i]; //0xffffffffu-i;
h_reference_keys[i] = h_keys[i];
}
// Run the timing test
if (keys_only)
{
TimedSort<K>(num_elements, h_keys, iterations);
}
else
{
TimedSort<K, V>(num_elements, h_keys, h_values, iterations);
}
// cudaThreadSynchronize();
// Display sorted key data
if (g_verbose)
{
printf("\n\nKeys:\n");
for (int i = 0; i < num_elements; i++)
{
PrintValue<K>(h_keys[i]);
printf(", ");
}
printf("\n\n");
}
// Verify solution
std::sort(h_reference_keys, h_reference_keys + num_elements);
CompareResults<K>(h_keys, h_reference_keys, num_elements, true);
printf("\n");
fflush(stdout);
// Free our allocated host memory
if (h_keys != NULL) free(h_keys);
if (h_values != NULL) free(h_values);
}
/**
* Displays the commandline usage for this tool
*/
void Usage()
{
printf("\ntest_large_problem_sorting [--device=<device index>] [--v] [--i=<num-iterations>] [--n=<num-elements>] [--key-values] [--deviceId=<int>] [--platformId=<int>]\n");
printf("\n");
printf("\t--v\tDisplays sorted results to the console.\n");
printf("\n");
printf("\t--i\tPerforms the sorting operation <num-iterations> times\n");
printf("\t\t\ton the device. Re-copies original input each time. Default = 1\n");
printf("\n");
printf("\t--n\tThe number of elements to comprise the sample problem\n");
printf("\t\t\tDefault = 512\n");
printf("\n");
printf("\t--key-values\tSpecifies that keys are accommodated by value pairings\n");
printf("\n");
}
/******************************************************************************
* Command-line parsing
******************************************************************************/
#include <map>
#include <algorithm>
#include <string>
class b3CommandLineArgs
{
protected:
std::map<std::string, std::string> pairs;
public:
// Constructor
b3CommandLineArgs(int argc, char **argv)
{
using namespace std;
for (int i = 1; i < argc; i++)
{
string arg = argv[i];
if ((arg[0] != '-') || (arg[1] != '-'))
{
continue;
}
string::size_type pos;
string key, val;
if ((pos = arg.find('=')) == string::npos)
{
key = string(arg, 2, arg.length() - 2);
val = "";
}
else
{
key = string(arg, 2, pos - 2);
val = string(arg, pos + 1, arg.length() - 1);
}
pairs[key] = val;
}
}
bool CheckCmdLineFlag(const char *arg_name)
{
using namespace std;
map<string, string>::iterator itr;
if ((itr = pairs.find(arg_name)) != pairs.end())
{
return true;
}
return false;
}
template <typename T>
void GetCmdLineArgument(const char *arg_name, T &val);
int ParsedArgc()
{
return pairs.size();
}
};
template <typename T>
void b3CommandLineArgs::GetCmdLineArgument(const char *arg_name, T &val)
{
using namespace std;
map<string, string>::iterator itr;
if ((itr = pairs.find(arg_name)) != pairs.end())
{
istringstream strstream(itr->second);
strstream >> val;
}
}
template <>
void b3CommandLineArgs::GetCmdLineArgument<char *>(const char *arg_name, char *&val)
{
using namespace std;
map<string, string>::iterator itr;
if ((itr = pairs.find(arg_name)) != pairs.end())
{
string s = itr->second;
val = (char *)malloc(sizeof(char) * (s.length() + 1));
strcpy(val, s.c_str());
}
else
{
val = NULL;
}
}
/******************************************************************************
* Main
******************************************************************************/
extern bool gDebugSkipLoadingBinary;
void myprintf(const char *msg)
{
(void *)msg;
}
int main(int argc, char **argv)
{
//gDebugSkipLoadingBinary = true;
// b3SetCustomPrintfFunc(myprintf);
cl_int ciErrNum;
b3CommandLineArgs args(argc, argv);
args.GetCmdLineArgument("deviceId", gPreferredDeviceId);
args.GetCmdLineArgument("platformId", gPreferredPlatformId);
b3Printf("Initialize OpenCL using b3OpenCLUtils_createContextFromType\n");
cl_platform_id platformId;
// g_cxMainContext = b3OpenCLUtils_createContextFromType(CL_DEVICE_TYPE_ALL, &ciErrNum, 0, 0,gPreferredDeviceId,gPreferredPlatformId,&platformId);
g_cxMainContext = b3OpenCLUtils_createContextFromType(CL_DEVICE_TYPE_GPU, &ciErrNum, 0, 0, gPreferredDeviceId, gPreferredPlatformId, &platformId);
//g_cxMainContext = b3OpenCLUtils_createContextFromType(CL_DEVICE_TYPE_CPU, &ciErrNum, 0, 0,gPreferredDeviceId,gPreferredPlatformId,&platformId);
oclCHECKERROR(ciErrNum, CL_SUCCESS);
int numDev = b3OpenCLUtils_getNumDevices(g_cxMainContext);
if (!numDev)
{
b3Error("error: no OpenCL devices\n");
exit(0);
}
int devId = 0;
g_device = b3OpenCLUtils_getDevice(g_cxMainContext, devId);
b3OpenCLUtils_printDeviceInfo(g_device);
// create a command-queue
g_cqCommandQueue = clCreateCommandQueue(g_cxMainContext, g_device, 0, &ciErrNum);
oclCHECKERROR(ciErrNum, CL_SUCCESS);
//srand(time(NULL));
srand(0); // presently deterministic
unsigned int num_elements = 8 * 1024 * 1024; //4*1024*1024;//4*1024*1024;//257;//8*524288;//2048;//512;//524288;
unsigned int iterations = 10;
bool keys_only = true;
//
// Check command line arguments
//
if (args.CheckCmdLineFlag("help"))
{
Usage();
return 0;
}
args.GetCmdLineArgument("i", iterations);
args.GetCmdLineArgument("n", num_elements);
keys_only = !args.CheckCmdLineFlag("key-values");
g_verbose = args.CheckCmdLineFlag("v");
TestSort<unsigned int, unsigned int>(
iterations,
num_elements,
keys_only);
}

View file

@ -0,0 +1,47 @@
function createProject(vendor)
hasCL = findOpenCL(vendor)
if (hasCL) then
project ("Test_OpenCL_RadixSortBenchmark_" .. vendor)
initOpenCL(vendor)
language "C++"
kind "ConsoleApp"
includedirs {"..","../../../src"}
-- links {
-- ("OpenCL_lib_parallel_primitives_host_" .. vendor)
-- }
files {
"main.cpp",
"../../../src/Bullet3OpenCL/Initialize/b3OpenCLUtils.cpp",
"../../../src/Bullet3OpenCL/Initialize/b3OpenCLUtils.h",
"../../../src/Bullet3OpenCL/ParallelPrimitives/b3FillCL.cpp",
"../../../src/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.cpp",
"../../../src/Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.cpp",
"../../../src/Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.cpp",
"../../../src/Bullet3Common/b3AlignedAllocator.cpp",
"../../../src/Bullet3Common/b3AlignedAllocator.h",
"../../../src/Bullet3Common/b3AlignedObjectArray.h",
"../../../src/Bullet3Common/b3Logging.cpp",
"../../../src/Bullet3Common/b3Logging.h",
"../../../btgui/Bullet3AppSupport/b3Quickprof.cpp",
"../../../btgui/Bullet3AppSupport/b3Quickprof.h",
"../../../btgui/Bullet3AppSupport/b3Clock.cpp",
"../../../btgui/Bullet3AppSupport/b3Clock.h",
}
end
end
createProject("clew")
createProject("AMD")
createProject("Intel")
createProject("NVIDIA")
createProject("Apple")