/* 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. */ //Originally written by Takahiro Harada #include "Solver.h" ///useNewBatchingKernel is a rewritten kernel using just a single thread of the warp, for experiments bool useNewBatchingKernel = false; #define SOLVER_SETUP_KERNEL_PATH "opencl/gpu_rigidbody/kernels/solverSetup.cl" #define SOLVER_SETUP2_KERNEL_PATH "opencl/gpu_rigidbody/kernels/solverSetup2.cl" #define SOLVER_CONTACT_KERNEL_PATH "opencl/gpu_rigidbody/kernels/solveContact.cl" #define SOLVER_FRICTION_KERNEL_PATH "opencl/gpu_rigidbody/kernels/solveFriction.cl" #define BATCHING_PATH "opencl/gpu_rigidbody/kernels/batchingKernels.cl" #define BATCHING_NEW_PATH "opencl/gpu_rigidbody/kernels/batchingKernelsNew.cl" #include "../kernels/solverSetup.h" #include "../kernels/solverSetup2.h" #include "../kernels/solveContact.h" #include "../kernels/solveFriction.h" #include "../kernels/batchingKernels.h" #include "../kernels/batchingKernelsNew.h" #include "BulletCommon/btQuickprof.h" #include "../../parallel_primitives/host/btLauncherCL.h" #include "BulletCommon/btVector3.h" struct SolverDebugInfo { int m_valInt0; int m_valInt1; int m_valInt2; int m_valInt3; int m_valInt4; int m_valInt5; int m_valInt6; int m_valInt7; int m_valInt8; int m_valInt9; int m_valInt10; int m_valInt11; int m_valInt12; int m_valInt13; int m_valInt14; int m_valInt15; float m_val0; float m_val1; float m_val2; float m_val3; }; class SolverDeviceInl { public: struct ParallelSolveData { btOpenCLArray* m_numConstraints; btOpenCLArray* m_offsets; }; }; Solver::Solver(cl_context ctx, cl_device_id device, cl_command_queue queue, int pairCapacity) :m_nIterations(4), m_context(ctx), m_device(device), m_queue(queue) { m_sort32 = new btRadixSort32CL(ctx,device,queue); m_scan = new btPrefixScanCL(ctx,device,queue,N_SPLIT*N_SPLIT); m_search = new btBoundSearchCL(ctx,device,queue,N_SPLIT*N_SPLIT); const int sortSize = BTNEXTMULTIPLEOF( pairCapacity, 512 ); m_sortDataBuffer = new btOpenCLArray(ctx,queue,sortSize); m_contactBuffer2 = new btOpenCLArray(ctx,queue); m_numConstraints = new btOpenCLArray(ctx,queue,N_SPLIT*N_SPLIT ); m_numConstraints->resize(N_SPLIT*N_SPLIT); m_offsets = new btOpenCLArray( ctx,queue, N_SPLIT*N_SPLIT ); m_offsets->resize(N_SPLIT*N_SPLIT); const char* additionalMacros = ""; const char* srcFileNameForCaching=""; cl_int pErrNum; const char* batchKernelSource = batchingKernelsCL; const char* batchKernelNewSource = batchingKernelsNewCL; const char* solverSetupSource = solverSetupCL; const char* solverSetup2Source = solverSetup2CL; const char* solveContactSource = solveContactCL; const char* solveFrictionSource = solveFrictionCL; { cl_program solveContactProg= btOpenCLUtils::compileCLProgramFromString( ctx, device, solveContactSource, &pErrNum,additionalMacros, SOLVER_CONTACT_KERNEL_PATH); btAssert(solveContactProg); cl_program solveFrictionProg= btOpenCLUtils::compileCLProgramFromString( ctx, device, solveFrictionSource, &pErrNum,additionalMacros, SOLVER_FRICTION_KERNEL_PATH); btAssert(solveFrictionProg); cl_program solverSetup2Prog= btOpenCLUtils::compileCLProgramFromString( ctx, device, solverSetup2Source, &pErrNum,additionalMacros, SOLVER_SETUP2_KERNEL_PATH); btAssert(solverSetup2Prog); cl_program solverSetupProg= btOpenCLUtils::compileCLProgramFromString( ctx, device, solverSetupSource, &pErrNum,additionalMacros, SOLVER_SETUP_KERNEL_PATH); btAssert(solverSetupProg); m_solveFrictionKernel= btOpenCLUtils::compileCLKernelFromString( ctx, device, solveFrictionSource, "BatchSolveKernelFriction", &pErrNum, solveFrictionProg,additionalMacros ); btAssert(m_solveFrictionKernel); m_solveContactKernel= btOpenCLUtils::compileCLKernelFromString( ctx, device, solveContactSource, "BatchSolveKernelContact", &pErrNum, solveContactProg,additionalMacros ); btAssert(m_solveContactKernel); m_contactToConstraintKernel = btOpenCLUtils::compileCLKernelFromString( ctx, device, solverSetupSource, "ContactToConstraintKernel", &pErrNum, solverSetupProg,additionalMacros ); btAssert(m_contactToConstraintKernel); m_setSortDataKernel = btOpenCLUtils::compileCLKernelFromString( ctx, device, solverSetup2Source, "SetSortDataKernel", &pErrNum, solverSetup2Prog,additionalMacros ); btAssert(m_setSortDataKernel); m_reorderContactKernel = btOpenCLUtils::compileCLKernelFromString( ctx, device, solverSetup2Source, "ReorderContactKernel", &pErrNum, solverSetup2Prog,additionalMacros ); btAssert(m_reorderContactKernel); m_copyConstraintKernel = btOpenCLUtils::compileCLKernelFromString( ctx, device, solverSetup2Source, "CopyConstraintKernel", &pErrNum, solverSetup2Prog,additionalMacros ); btAssert(m_copyConstraintKernel); } { cl_program batchingProg = btOpenCLUtils::compileCLProgramFromString( ctx, device, batchKernelSource, &pErrNum,additionalMacros, BATCHING_PATH); btAssert(batchingProg); m_batchingKernel = btOpenCLUtils::compileCLKernelFromString( ctx, device, batchKernelSource, "CreateBatches", &pErrNum, batchingProg,additionalMacros ); btAssert(m_batchingKernel); } { cl_program batchingNewProg = btOpenCLUtils::compileCLProgramFromString( ctx, device, batchKernelNewSource, &pErrNum,additionalMacros, BATCHING_NEW_PATH); btAssert(batchingNewProg); m_batchingKernelNew = btOpenCLUtils::compileCLKernelFromString( ctx, device, batchKernelNewSource, "CreateBatchesNew", &pErrNum, batchingNewProg,additionalMacros ); //m_batchingKernelNew = btOpenCLUtils::compileCLKernelFromString( ctx, device, batchKernelNewSource, "CreateBatchesBruteForce", &pErrNum, batchingNewProg,additionalMacros ); btAssert(m_batchingKernelNew); } } Solver::~Solver() { delete m_sortDataBuffer; delete m_contactBuffer2; delete m_sort32; delete m_scan; delete m_search; clReleaseKernel(m_batchingKernel); clReleaseKernel(m_batchingKernelNew); clReleaseKernel( m_solveContactKernel); clReleaseKernel( m_solveFrictionKernel); clReleaseKernel( m_contactToConstraintKernel); clReleaseKernel( m_setSortDataKernel); clReleaseKernel( m_reorderContactKernel); clReleaseKernel( m_copyConstraintKernel); } /*void Solver::reorderConvertToConstraints( const btOpenCLArray* bodyBuf, const btOpenCLArray* shapeBuf, btOpenCLArray* contactsIn, btOpenCLArray* contactCOut, void* additionalData, int nContacts, const Solver::ConstraintCfg& cfg ) { if( m_contactBuffer ) { m_contactBuffer->resize(nContacts); } if( m_contactBuffer == 0 ) { BT_PROFILE("new m_contactBuffer;"); m_contactBuffer = new btOpenCLArray(m_context,m_queue,nContacts ); m_contactBuffer->resize(nContacts); } //DeviceUtils::Config dhCfg; //Device* deviceHost = DeviceUtils::allocate( TYPE_HOST, dhCfg ); if( cfg.m_enableParallelSolve ) { clFinish(m_queue); // contactsIn -> m_contactBuffer { BT_PROFILE("sortContacts"); sortContacts( bodyBuf, contactsIn, additionalData, nContacts, cfg ); clFinish(m_queue); } { BT_PROFILE("m_copyConstraintKernel"); btInt4 cdata; cdata.x = nContacts; btBufferInfoCL bInfo[] = { btBufferInfoCL( m_contactBuffer->getBufferCL() ), btBufferInfoCL( contactsIn->getBufferCL() ) }; // btLauncherCL launcher( m_queue, data->m_device->getKernel( PATH, "CopyConstraintKernel", "-I ..\\..\\ -Wf,--c++", 0 ) ); btLauncherCL launcher( m_queue, m_copyConstraintKernel ); launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(btBufferInfoCL) ); launcher.setConst( cdata ); launcher.launch1D( nContacts, 64 ); clFinish(m_queue); } { BT_PROFILE("batchContacts"); Solver::batchContacts( contactsIn, nContacts, m_numConstraints, m_offsets, cfg.m_staticIdx ); } } { BT_PROFILE("waitForCompletion (batchContacts)"); clFinish(m_queue); } //================ { BT_PROFILE("convertToConstraints"); Solver::convertToConstraints( bodyBuf, shapeBuf, contactsIn, contactCOut, additionalData, nContacts, cfg ); } { BT_PROFILE("convertToConstraints waitForCompletion"); clFinish(m_queue); } } */ static inline float calcRelVel(const btVector3& l0, const btVector3& l1, const btVector3& a0, const btVector3& a1, const btVector3& linVel0, const btVector3& angVel0, const btVector3& linVel1, const btVector3& angVel1) { return btDot(l0, linVel0) + btDot(a0, angVel0) + btDot(l1, linVel1) + btDot(a1, angVel1); } static inline void setLinearAndAngular(const btVector3& n, const btVector3& r0, const btVector3& r1, btVector3& linear, btVector3& angular0, btVector3& angular1) { linear = -n; angular0 = -btCross(r0, n); angular1 = btCross(r1, n); } template static __inline void solveContact(btGpuConstraint4& cs, const btVector3& posA, btVector3& linVelA, btVector3& angVelA, float invMassA, const btMatrix3x3& invInertiaA, const btVector3& posB, btVector3& linVelB, btVector3& angVelB, float invMassB, const btMatrix3x3& invInertiaB, float maxRambdaDt[4], float minRambdaDt[4]) { btVector3 dLinVelA; dLinVelA.setZero(); btVector3 dAngVelA; dAngVelA.setZero(); btVector3 dLinVelB; dLinVelB.setZero(); btVector3 dAngVelB; dAngVelB.setZero(); for(int ic=0; ic<4; ic++) { // dont necessary because this makes change to 0 if( cs.m_jacCoeffInv[ic] == 0.f ) continue; { btVector3 angular0, angular1, linear; btVector3 r0 = cs.m_worldPos[ic] - (btVector3&)posA; btVector3 r1 = cs.m_worldPos[ic] - (btVector3&)posB; setLinearAndAngular( (const btVector3 &)-cs.m_linear, (const btVector3 &)r0, (const btVector3 &)r1, linear, angular0, angular1 ); float rambdaDt = calcRelVel((const btVector3 &)cs.m_linear,(const btVector3 &) -cs.m_linear, angular0, angular1, linVelA, angVelA, linVelB, angVelB ) + cs.m_b[ic]; rambdaDt *= cs.m_jacCoeffInv[ic]; { float prevSum = cs.m_appliedRambdaDt[ic]; float updated = prevSum; updated += rambdaDt; updated = btMax( updated, minRambdaDt[ic] ); updated = btMin( updated, maxRambdaDt[ic] ); rambdaDt = updated - prevSum; cs.m_appliedRambdaDt[ic] = updated; } btVector3 linImp0 = invMassA*linear*rambdaDt; btVector3 linImp1 = invMassB*(-linear)*rambdaDt; btVector3 angImp0 = (invInertiaA* angular0)*rambdaDt; btVector3 angImp1 = (invInertiaB* angular1)*rambdaDt; #ifdef _WIN32 btAssert(_finite(linImp0.x())); btAssert(_finite(linImp1.x())); #endif if( JACOBI ) { dLinVelA += linImp0; dAngVelA += angImp0; dLinVelB += linImp1; dAngVelB += angImp1; } else { linVelA += linImp0; angVelA += angImp0; linVelB += linImp1; angVelB += angImp1; } } } if( JACOBI ) { linVelA += dLinVelA; angVelA += dAngVelA; linVelB += dLinVelB; angVelB += dAngVelB; } } static __inline void solveFriction(btGpuConstraint4& cs, const btVector3& posA, btVector3& linVelA, btVector3& angVelA, float invMassA, const btMatrix3x3& invInertiaA, const btVector3& posB, btVector3& linVelB, btVector3& angVelB, float invMassB, const btMatrix3x3& invInertiaB, float maxRambdaDt[4], float minRambdaDt[4]) { if( cs.m_fJacCoeffInv[0] == 0 && cs.m_fJacCoeffInv[0] == 0 ) return; const btVector3& center = (const btVector3&)cs.m_center; btVector3 n = -(const btVector3&)cs.m_linear; btVector3 tangent[2]; #if 1 btPlaneSpace1 (n, tangent[0],tangent[1]); #else btVector3 r = cs.m_worldPos[0]-center; tangent[0] = cross3( n, r ); tangent[1] = cross3( tangent[0], n ); tangent[0] = normalize3( tangent[0] ); tangent[1] = normalize3( tangent[1] ); #endif btVector3 angular0, angular1, linear; btVector3 r0 = center - posA; btVector3 r1 = center - posB; for(int i=0; i<2; i++) { setLinearAndAngular( tangent[i], r0, r1, linear, angular0, angular1 ); float rambdaDt = calcRelVel(linear, -linear, angular0, angular1, linVelA, angVelA, linVelB, angVelB ); rambdaDt *= cs.m_fJacCoeffInv[i]; { float prevSum = cs.m_fAppliedRambdaDt[i]; float updated = prevSum; updated += rambdaDt; updated = btMax( updated, minRambdaDt[i] ); updated = btMin( updated, maxRambdaDt[i] ); rambdaDt = updated - prevSum; cs.m_fAppliedRambdaDt[i] = updated; } btVector3 linImp0 = invMassA*linear*rambdaDt; btVector3 linImp1 = invMassB*(-linear)*rambdaDt; btVector3 angImp0 = (invInertiaA* angular0)*rambdaDt; btVector3 angImp1 = (invInertiaB* angular1)*rambdaDt; #ifdef _WIN32 btAssert(_finite(linImp0.x())); btAssert(_finite(linImp1.x())); #endif linVelA += linImp0; angVelA += angImp0; linVelB += linImp1; angVelB += angImp1; } { // angular damping for point constraint btVector3 ab = ( posB - posA ).normalized(); btVector3 ac = ( center - posA ).normalized(); if( btDot( ab, ac ) > 0.95f || (invMassA == 0.f || invMassB == 0.f)) { float angNA = btDot( n, angVelA ); float angNB = btDot( n, angVelB ); angVelA -= (angNA*0.1f)*n; angVelB -= (angNB*0.1f)*n; } } } struct SolveTask// : public ThreadPool::Task { SolveTask(btAlignedObjectArray& bodies, btAlignedObjectArray& shapes, btAlignedObjectArray& constraints, int start, int nConstraints) : m_bodies( bodies ), m_shapes( shapes ), m_constraints( constraints ), m_start( start ), m_nConstraints( nConstraints ), m_solveFriction( true ){} unsigned short int getType(){ return 0; } void run(int tIdx) { for(int ic=0; ic( m_constraints[i], (btVector3&)bodyA.m_pos, (btVector3&)bodyA.m_linVel, (btVector3&)bodyA.m_angVel, bodyA.m_invMass, (const btMatrix3x3 &)m_shapes[aIdx].m_invInertiaWorld, (btVector3&)bodyB.m_pos, (btVector3&)bodyB.m_linVel, (btVector3&)bodyB.m_angVel, bodyB.m_invMass, (const btMatrix3x3 &)m_shapes[bIdx].m_invInertiaWorld, maxRambdaDt, minRambdaDt ); } else { float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX}; float minRambdaDt[4] = {0.f,0.f,0.f,0.f}; float sum = 0; for(int j=0; j<4; j++) { sum +=m_constraints[i].m_appliedRambdaDt[j]; } frictionCoeff = 0.7f; for(int j=0; j<4; j++) { maxRambdaDt[j] = frictionCoeff*sum; minRambdaDt[j] = -maxRambdaDt[j]; } solveFriction( m_constraints[i], (btVector3&)bodyA.m_pos, (btVector3&)bodyA.m_linVel, (btVector3&)bodyA.m_angVel, bodyA.m_invMass,(const btMatrix3x3 &) m_shapes[aIdx].m_invInertiaWorld, (btVector3&)bodyB.m_pos, (btVector3&)bodyB.m_linVel, (btVector3&)bodyB.m_angVel, bodyB.m_invMass,(const btMatrix3x3 &) m_shapes[bIdx].m_invInertiaWorld, maxRambdaDt, minRambdaDt ); } } } btAlignedObjectArray& m_bodies; btAlignedObjectArray& m_shapes; btAlignedObjectArray& m_constraints; int m_start; int m_nConstraints; bool m_solveFriction; }; void Solver::solveContactConstraintHost( btOpenCLArray* bodyBuf, btOpenCLArray* shapeBuf, btOpenCLArray* constraint, void* additionalData, int n ,int maxNumBatches) { btAlignedObjectArray bodyNative; bodyBuf->copyToHost(bodyNative); btAlignedObjectArray shapeNative; shapeBuf->copyToHost(shapeNative); btAlignedObjectArray constraintNative; constraint->copyToHost(constraintNative); for(int iter=0; itercopyFromHost(bodyNative); shapeBuf->copyFromHost(shapeNative); constraint->copyFromHost(constraintNative); } void Solver::solveContactConstraint( const btOpenCLArray* bodyBuf, const btOpenCLArray* shapeBuf, btOpenCLArray* constraint, void* additionalData, int n ,int maxNumBatches) { btInt4 cdata = btMakeInt4( n, 0, 0, 0 ); { const int nn = N_SPLIT*N_SPLIT; cdata.x = 0; cdata.y = maxNumBatches;//250; int numWorkItems = 64*nn/N_BATCHES; #ifdef DEBUG_ME SolverDebugInfo* debugInfo = new SolverDebugInfo[numWorkItems]; adl::btOpenCLArray gpuDebugInfo(data->m_device,numWorkItems); #endif { BT_PROFILE("m_batchSolveKernel iterations"); for(int iter=0; itergetBufferCL() ), btBufferInfoCL( shapeBuf->getBufferCL() ), btBufferInfoCL( constraint->getBufferCL() ), btBufferInfoCL( m_numConstraints->getBufferCL() ), btBufferInfoCL( m_offsets->getBufferCL() ) #ifdef DEBUG_ME , btBufferInfoCL(&gpuDebugInfo) #endif }; launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(btBufferInfoCL) ); //launcher.setConst( cdata.x ); launcher.setConst( cdata.y ); launcher.setConst( cdata.z ); launcher.setConst( cdata.w ); launcher.launch1D( numWorkItems, 64 ); #else const char* fileName = "m_batchSolveKernel.bin"; FILE* f = fopen(fileName,"rb"); if (f) { int sizeInBytes=0; if (fseek(f, 0, SEEK_END) || (sizeInBytes = ftell(f)) == EOF || fseek(f, 0, SEEK_SET)) { printf("error, cannot get file size\n"); exit(0); } unsigned char* buf = (unsigned char*) malloc(sizeInBytes); fread(buf,sizeInBytes,1,f); int serializedBytes = launcher.deserializeArgs(buf, sizeInBytes,m_context); int num = *(int*)&buf[serializedBytes]; launcher.launch1D( num); //this clFinish is for testing on errors clFinish(m_queue); } #endif #ifdef DEBUG_ME clFinish(m_queue); gpuDebugInfo.read(debugInfo,numWorkItems); clFinish(m_queue); for (int i=0;i0) { printf("debugInfo[i].m_valInt2 = %d\n",i,debugInfo[i].m_valInt2); } if (debugInfo[i].m_valInt3>0) { printf("debugInfo[i].m_valInt3 = %d\n",i,debugInfo[i].m_valInt3); } } #endif //DEBUG_ME } } clFinish(m_queue); } cdata.x = 1; bool applyFriction=true; if (applyFriction) { BT_PROFILE("m_batchSolveKernel iterations2"); for(int iter=0; itergetBufferCL() ), btBufferInfoCL( shapeBuf->getBufferCL() ), btBufferInfoCL( constraint->getBufferCL() ), btBufferInfoCL( m_numConstraints->getBufferCL() ), btBufferInfoCL( m_offsets->getBufferCL() ) #ifdef DEBUG_ME ,btBufferInfoCL(&gpuDebugInfo) #endif //DEBUG_ME }; btLauncherCL launcher( m_queue, m_solveFrictionKernel ); launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(btBufferInfoCL) ); //launcher.setConst( cdata.x ); launcher.setConst( cdata.y ); launcher.setConst( cdata.z ); launcher.setConst( cdata.w ); launcher.launch1D( 64*nn/N_BATCHES, 64 ); } } clFinish(m_queue); } #ifdef DEBUG_ME delete[] debugInfo; #endif //DEBUG_ME } } void Solver::convertToConstraints( const btOpenCLArray* bodyBuf, const btOpenCLArray* shapeBuf, btOpenCLArray* contactsIn, btOpenCLArray* contactCOut, void* additionalData, int nContacts, const ConstraintCfg& cfg ) { btOpenCLArray* constraintNative =0; struct CB { int m_nContacts; float m_dt; float m_positionDrift; float m_positionConstraintCoeff; }; { BT_PROFILE("m_contactToConstraintKernel"); CB cdata; cdata.m_nContacts = nContacts; cdata.m_dt = cfg.m_dt; cdata.m_positionDrift = cfg.m_positionDrift; cdata.m_positionConstraintCoeff = cfg.m_positionConstraintCoeff; btBufferInfoCL bInfo[] = { btBufferInfoCL( contactsIn->getBufferCL() ), btBufferInfoCL( bodyBuf->getBufferCL() ), btBufferInfoCL( shapeBuf->getBufferCL()), btBufferInfoCL( contactCOut->getBufferCL() )}; btLauncherCL launcher( m_queue, m_contactToConstraintKernel ); launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(btBufferInfoCL) ); //launcher.setConst( cdata ); launcher.setConst(cdata.m_nContacts); launcher.setConst(cdata.m_dt); launcher.setConst(cdata.m_positionDrift); launcher.setConst(cdata.m_positionConstraintCoeff); launcher.launch1D( nContacts, 64 ); clFinish(m_queue); } contactCOut->resize(nContacts); } /* void Solver::sortContacts( const btOpenCLArray* bodyBuf, btOpenCLArray* contactsIn, void* additionalData, int nContacts, const Solver::ConstraintCfg& cfg ) { const int sortAlignment = 512; // todo. get this out of sort if( cfg.m_enableParallelSolve ) { int sortSize = NEXTMULTIPLEOF( nContacts, sortAlignment ); btOpenCLArray* countsNative = m_numConstraints;//BufferUtils::map( data->m_device, &countsHost ); btOpenCLArray* offsetsNative = m_offsets;//BufferUtils::map( data->m_device, &offsetsHost ); { // 2. set cell idx struct CB { int m_nContacts; int m_staticIdx; float m_scale; int m_nSplit; }; btAssert( sortSize%64 == 0 ); CB cdata; cdata.m_nContacts = nContacts; cdata.m_staticIdx = cfg.m_staticIdx; cdata.m_scale = 1.f/(N_OBJ_PER_SPLIT*cfg.m_averageExtent); cdata.m_nSplit = N_SPLIT; btBufferInfoCL bInfo[] = { btBufferInfoCL( contactsIn->getBufferCL() ), btBufferInfoCL( bodyBuf->getBufferCL() ), btBufferInfoCL( m_sortDataBuffer->getBufferCL() ) }; btLauncherCL launcher( m_queue, m_setSortDataKernel ); launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(btBufferInfoCL) ); launcher.setConst( cdata ); launcher.launch1D( sortSize, 64 ); } { // 3. sort by cell idx int n = N_SPLIT*N_SPLIT; int sortBit = 32; //if( n <= 0xffff ) sortBit = 16; //if( n <= 0xff ) sortBit = 8; m_sort32->execute(*m_sortDataBuffer,sortSize); } { // 4. find entries m_search->execute( *m_sortDataBuffer, nContacts, *countsNative, N_SPLIT*N_SPLIT, btBoundSearchCL::COUNT); m_scan->execute( *countsNative, *offsetsNative, N_SPLIT*N_SPLIT ); } { // 5. sort constraints by cellIdx // todo. preallocate this // btAssert( contactsIn->getType() == TYPE_HOST ); // btOpenCLArray* out = BufferUtils::map( data->m_device, contactsIn ); // copying contacts to this buffer { btInt4 cdata; cdata.x = nContacts; btBufferInfoCL bInfo[] = { btBufferInfoCL( contactsIn->getBufferCL() ), btBufferInfoCL( m_contactBuffer->getBufferCL() ), btBufferInfoCL( m_sortDataBuffer->getBufferCL() ) }; btLauncherCL launcher( m_queue, m_reorderContactKernel ); launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(btBufferInfoCL) ); launcher.setConst( cdata ); launcher.launch1D( nContacts, 64 ); } // BufferUtils::unmap( out, contactsIn, nContacts ); } } } */ void Solver::batchContacts( btOpenCLArray* contacts, int nContacts, btOpenCLArray* nNative, btOpenCLArray* offsetsNative, int staticIdx ) { int numWorkItems = 64*N_SPLIT*N_SPLIT; { BT_PROFILE("batch generation"); btInt4 cdata; cdata.x = nContacts; cdata.y = 0; cdata.z = staticIdx; #ifdef BATCH_DEBUG SolverDebugInfo* debugInfo = new SolverDebugInfo[numWorkItems]; adl::btOpenCLArray gpuDebugInfo(data->m_device,numWorkItems); memset(debugInfo,0,sizeof(SolverDebugInfo)*numWorkItems); gpuDebugInfo.write(debugInfo,numWorkItems); #endif btBufferInfoCL bInfo[] = { btBufferInfoCL( contacts->getBufferCL() ), btBufferInfoCL( m_contactBuffer2->getBufferCL()), btBufferInfoCL( nNative->getBufferCL() ), btBufferInfoCL( offsetsNative->getBufferCL() ), #ifdef BATCH_DEBUG , btBufferInfoCL(&gpuDebugInfo) #endif }; { BT_PROFILE("batchingKernel"); //btLauncherCL launcher( m_queue, m_batchingKernel); cl_kernel k = useNewBatchingKernel ? m_batchingKernelNew : m_batchingKernel; btLauncherCL launcher( m_queue, k); if (!useNewBatchingKernel ) { launcher.setBuffer( contacts->getBufferCL() ); } launcher.setBuffer( m_contactBuffer2->getBufferCL() ); launcher.setBuffer( nNative->getBufferCL()); launcher.setBuffer( offsetsNative->getBufferCL()); //launcher.setConst( cdata ); launcher.setConst(staticIdx); launcher.launch1D( numWorkItems, 64 ); clFinish(m_queue); } #ifdef BATCH_DEBUG aaaa btContact4* hostContacts = new btContact4[nContacts]; m_contactBuffer->read(hostContacts,nContacts); clFinish(m_queue); gpuDebugInfo.read(debugInfo,numWorkItems); clFinish(m_queue); for (int i=0;i0) { printf("catch\n"); } if (debugInfo[i].m_valInt2>0) { printf("catch22\n"); } if (debugInfo[i].m_valInt3>0) { printf("catch666\n"); } if (debugInfo[i].m_valInt4>0) { printf("catch777\n"); } } delete[] debugInfo; #endif //BATCH_DEBUG } // copy buffer to buffer //btAssert(m_contactBuffer->size()==nContacts); //contacts->copyFromOpenCLArray( *m_contactBuffer); //clFinish(m_queue);//needed? }