b3GpuPgsConstraintSolver.cpp 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069
  1. /*
  2. Copyright (c) 2013 Advanced Micro Devices, Inc.
  3. This software is provided 'as-is', without any express or implied warranty.
  4. In no event will the authors be held liable for any damages arising from the use of this software.
  5. Permission is granted to anyone to use this software for any purpose,
  6. including commercial applications, and to alter it and redistribute it freely,
  7. subject to the following restrictions:
  8. 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.
  9. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
  10. 3. This notice may not be removed or altered from any source distribution.
  11. */
  12. //Originally written by Erwin Coumans
  13. bool useGpuInitSolverBodies = true;
  14. bool useGpuInfo1 = true;
  15. bool useGpuInfo2 = true;
  16. bool useGpuSolveJointConstraintRows = true;
  17. bool useGpuWriteBackVelocities = true;
  18. bool gpuBreakConstraints = true;
  19. #include "b3GpuPgsConstraintSolver.h"
  20. #include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
  21. #include "Bullet3Dynamics/ConstraintSolver/b3TypedConstraint.h"
  22. #include <new>
  23. #include "Bullet3Common/b3AlignedObjectArray.h"
  24. #include <string.h> //for memset
  25. #include "Bullet3Collision/NarrowPhaseCollision/b3Contact4.h"
  26. #include "Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h"
  27. #include "Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h"
  28. #include "Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.h"
  29. #include "Bullet3OpenCL/RigidBody/kernels/jointSolver.h" //solveConstraintRowsCL
  30. #include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
  31. #define B3_JOINT_SOLVER_PATH "src/Bullet3OpenCL/RigidBody/kernels/jointSolver.cl"
  32. struct b3GpuPgsJacobiSolverInternalData
  33. {
  34. cl_context m_context;
  35. cl_device_id m_device;
  36. cl_command_queue m_queue;
  37. b3PrefixScanCL* m_prefixScan;
  38. cl_kernel m_solveJointConstraintRowsKernels;
  39. cl_kernel m_initSolverBodiesKernel;
  40. cl_kernel m_getInfo1Kernel;
  41. cl_kernel m_initBatchConstraintsKernel;
  42. cl_kernel m_getInfo2Kernel;
  43. cl_kernel m_writeBackVelocitiesKernel;
  44. cl_kernel m_breakViolatedConstraintsKernel;
  45. b3OpenCLArray<unsigned int>* m_gpuConstraintRowOffsets;
  46. b3OpenCLArray<b3GpuSolverBody>* m_gpuSolverBodies;
  47. b3OpenCLArray<b3BatchConstraint>* m_gpuBatchConstraints;
  48. b3OpenCLArray<b3GpuSolverConstraint>* m_gpuConstraintRows;
  49. b3OpenCLArray<unsigned int>* m_gpuConstraintInfo1;
  50. // b3AlignedObjectArray<b3GpuSolverBody> m_cpuSolverBodies;
  51. b3AlignedObjectArray<b3BatchConstraint> m_cpuBatchConstraints;
  52. b3AlignedObjectArray<b3GpuSolverConstraint> m_cpuConstraintRows;
  53. b3AlignedObjectArray<unsigned int> m_cpuConstraintInfo1;
  54. b3AlignedObjectArray<unsigned int> m_cpuConstraintRowOffsets;
  55. b3AlignedObjectArray<b3RigidBodyData> m_cpuBodies;
  56. b3AlignedObjectArray<b3InertiaData> m_cpuInertias;
  57. b3AlignedObjectArray<b3GpuGenericConstraint> m_cpuConstraints;
  58. b3AlignedObjectArray<int> m_batchSizes;
  59. };
  60. /*
  61. static b3Transform getWorldTransform(b3RigidBodyData* rb)
  62. {
  63. b3Transform newTrans;
  64. newTrans.setOrigin(rb->m_pos);
  65. newTrans.setRotation(rb->m_quat);
  66. return newTrans;
  67. }
  68. static const b3Matrix3x3& getInvInertiaTensorWorld(b3InertiaData* inertia)
  69. {
  70. return inertia->m_invInertiaWorld;
  71. }
  72. */
  73. static const b3Vector3& getLinearVelocity(b3RigidBodyData* rb)
  74. {
  75. return rb->m_linVel;
  76. }
  77. static const b3Vector3& getAngularVelocity(b3RigidBodyData* rb)
  78. {
  79. return rb->m_angVel;
  80. }
  81. b3Vector3 getVelocityInLocalPoint(b3RigidBodyData* rb, const b3Vector3& rel_pos)
  82. {
  83. //we also calculate lin/ang velocity for kinematic objects
  84. return getLinearVelocity(rb) + getAngularVelocity(rb).cross(rel_pos);
  85. }
  86. b3GpuPgsConstraintSolver::b3GpuPgsConstraintSolver(cl_context ctx, cl_device_id device, cl_command_queue queue, bool usePgs)
  87. {
  88. m_usePgs = usePgs;
  89. m_gpuData = new b3GpuPgsJacobiSolverInternalData();
  90. m_gpuData->m_context = ctx;
  91. m_gpuData->m_device = device;
  92. m_gpuData->m_queue = queue;
  93. m_gpuData->m_prefixScan = new b3PrefixScanCL(ctx, device, queue);
  94. m_gpuData->m_gpuConstraintRowOffsets = new b3OpenCLArray<unsigned int>(m_gpuData->m_context, m_gpuData->m_queue);
  95. m_gpuData->m_gpuSolverBodies = new b3OpenCLArray<b3GpuSolverBody>(m_gpuData->m_context, m_gpuData->m_queue);
  96. m_gpuData->m_gpuBatchConstraints = new b3OpenCLArray<b3BatchConstraint>(m_gpuData->m_context, m_gpuData->m_queue);
  97. m_gpuData->m_gpuConstraintRows = new b3OpenCLArray<b3GpuSolverConstraint>(m_gpuData->m_context, m_gpuData->m_queue);
  98. m_gpuData->m_gpuConstraintInfo1 = new b3OpenCLArray<unsigned int>(m_gpuData->m_context, m_gpuData->m_queue);
  99. cl_int errNum = 0;
  100. {
  101. cl_program prog = b3OpenCLUtils::compileCLProgramFromString(m_gpuData->m_context, m_gpuData->m_device, solveConstraintRowsCL, &errNum, "", B3_JOINT_SOLVER_PATH);
  102. //cl_program prog = b3OpenCLUtils::compileCLProgramFromString(m_gpuData->m_context,m_gpuData->m_device,0,&errNum,"",B3_JOINT_SOLVER_PATH,true);
  103. b3Assert(errNum == CL_SUCCESS);
  104. m_gpuData->m_solveJointConstraintRowsKernels = b3OpenCLUtils::compileCLKernelFromString(m_gpuData->m_context, m_gpuData->m_device, solveConstraintRowsCL, "solveJointConstraintRows", &errNum, prog);
  105. b3Assert(errNum == CL_SUCCESS);
  106. m_gpuData->m_initSolverBodiesKernel = b3OpenCLUtils::compileCLKernelFromString(m_gpuData->m_context, m_gpuData->m_device, solveConstraintRowsCL, "initSolverBodies", &errNum, prog);
  107. b3Assert(errNum == CL_SUCCESS);
  108. m_gpuData->m_getInfo1Kernel = b3OpenCLUtils::compileCLKernelFromString(m_gpuData->m_context, m_gpuData->m_device, solveConstraintRowsCL, "getInfo1Kernel", &errNum, prog);
  109. b3Assert(errNum == CL_SUCCESS);
  110. m_gpuData->m_initBatchConstraintsKernel = b3OpenCLUtils::compileCLKernelFromString(m_gpuData->m_context, m_gpuData->m_device, solveConstraintRowsCL, "initBatchConstraintsKernel", &errNum, prog);
  111. b3Assert(errNum == CL_SUCCESS);
  112. m_gpuData->m_getInfo2Kernel = b3OpenCLUtils::compileCLKernelFromString(m_gpuData->m_context, m_gpuData->m_device, solveConstraintRowsCL, "getInfo2Kernel", &errNum, prog);
  113. b3Assert(errNum == CL_SUCCESS);
  114. m_gpuData->m_writeBackVelocitiesKernel = b3OpenCLUtils::compileCLKernelFromString(m_gpuData->m_context, m_gpuData->m_device, solveConstraintRowsCL, "writeBackVelocitiesKernel", &errNum, prog);
  115. b3Assert(errNum == CL_SUCCESS);
  116. m_gpuData->m_breakViolatedConstraintsKernel = b3OpenCLUtils::compileCLKernelFromString(m_gpuData->m_context, m_gpuData->m_device, solveConstraintRowsCL, "breakViolatedConstraintsKernel", &errNum, prog);
  117. b3Assert(errNum == CL_SUCCESS);
  118. clReleaseProgram(prog);
  119. }
  120. }
  121. b3GpuPgsConstraintSolver::~b3GpuPgsConstraintSolver()
  122. {
  123. clReleaseKernel(m_gpuData->m_solveJointConstraintRowsKernels);
  124. clReleaseKernel(m_gpuData->m_initSolverBodiesKernel);
  125. clReleaseKernel(m_gpuData->m_getInfo1Kernel);
  126. clReleaseKernel(m_gpuData->m_initBatchConstraintsKernel);
  127. clReleaseKernel(m_gpuData->m_getInfo2Kernel);
  128. clReleaseKernel(m_gpuData->m_writeBackVelocitiesKernel);
  129. clReleaseKernel(m_gpuData->m_breakViolatedConstraintsKernel);
  130. delete m_gpuData->m_prefixScan;
  131. delete m_gpuData->m_gpuConstraintRowOffsets;
  132. delete m_gpuData->m_gpuSolverBodies;
  133. delete m_gpuData->m_gpuBatchConstraints;
  134. delete m_gpuData->m_gpuConstraintRows;
  135. delete m_gpuData->m_gpuConstraintInfo1;
  136. delete m_gpuData;
  137. }
  138. struct b3BatchConstraint
  139. {
  140. int m_bodyAPtrAndSignBit;
  141. int m_bodyBPtrAndSignBit;
  142. int m_originalConstraintIndex;
  143. int m_batchId;
  144. };
  145. static b3AlignedObjectArray<b3BatchConstraint> batchConstraints;
  146. void b3GpuPgsConstraintSolver::recomputeBatches()
  147. {
  148. m_gpuData->m_batchSizes.clear();
  149. }
  150. b3Scalar b3GpuPgsConstraintSolver::solveGroupCacheFriendlySetup(b3OpenCLArray<b3RigidBodyData>* gpuBodies, b3OpenCLArray<b3InertiaData>* gpuInertias, int numBodies, b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints, int numConstraints, const b3ContactSolverInfo& infoGlobal)
  151. {
  152. B3_PROFILE("GPU solveGroupCacheFriendlySetup");
  153. batchConstraints.resize(numConstraints);
  154. m_gpuData->m_gpuBatchConstraints->resize(numConstraints);
  155. m_staticIdx = -1;
  156. m_maxOverrideNumSolverIterations = 0;
  157. /* m_gpuData->m_gpuBodies->resize(numBodies);
  158. m_gpuData->m_gpuBodies->copyFromHostPointer(bodies,numBodies);
  159. b3OpenCLArray<b3InertiaData> gpuInertias(m_gpuData->m_context,m_gpuData->m_queue);
  160. gpuInertias.resize(numBodies);
  161. gpuInertias.copyFromHostPointer(inertias,numBodies);
  162. */
  163. m_gpuData->m_gpuSolverBodies->resize(numBodies);
  164. m_tmpSolverBodyPool.resize(numBodies);
  165. {
  166. if (useGpuInitSolverBodies)
  167. {
  168. B3_PROFILE("m_initSolverBodiesKernel");
  169. b3LauncherCL launcher(m_gpuData->m_queue, m_gpuData->m_initSolverBodiesKernel, "m_initSolverBodiesKernel");
  170. launcher.setBuffer(m_gpuData->m_gpuSolverBodies->getBufferCL());
  171. launcher.setBuffer(gpuBodies->getBufferCL());
  172. launcher.setConst(numBodies);
  173. launcher.launch1D(numBodies);
  174. clFinish(m_gpuData->m_queue);
  175. // m_gpuData->m_gpuSolverBodies->copyToHost(m_tmpSolverBodyPool);
  176. }
  177. else
  178. {
  179. gpuBodies->copyToHost(m_gpuData->m_cpuBodies);
  180. for (int i = 0; i < numBodies; i++)
  181. {
  182. b3RigidBodyData& body = m_gpuData->m_cpuBodies[i];
  183. b3GpuSolverBody& solverBody = m_tmpSolverBodyPool[i];
  184. initSolverBody(i, &solverBody, &body);
  185. solverBody.m_originalBodyIndex = i;
  186. }
  187. m_gpuData->m_gpuSolverBodies->copyFromHost(m_tmpSolverBodyPool);
  188. }
  189. }
  190. // int totalBodies = 0;
  191. int totalNumRows = 0;
  192. //b3RigidBody* rb0=0,*rb1=0;
  193. //if (1)
  194. {
  195. {
  196. // int i;
  197. m_tmpConstraintSizesPool.resizeNoInitialize(numConstraints);
  198. // b3OpenCLArray<b3GpuGenericConstraint> gpuConstraints(m_gpuData->m_context,m_gpuData->m_queue);
  199. if (useGpuInfo1)
  200. {
  201. B3_PROFILE("info1 and init batchConstraint");
  202. m_gpuData->m_gpuConstraintInfo1->resize(numConstraints);
  203. if (1)
  204. {
  205. B3_PROFILE("getInfo1Kernel");
  206. b3LauncherCL launcher(m_gpuData->m_queue, m_gpuData->m_getInfo1Kernel, "m_getInfo1Kernel");
  207. launcher.setBuffer(m_gpuData->m_gpuConstraintInfo1->getBufferCL());
  208. launcher.setBuffer(gpuConstraints->getBufferCL());
  209. launcher.setConst(numConstraints);
  210. launcher.launch1D(numConstraints);
  211. clFinish(m_gpuData->m_queue);
  212. }
  213. if (m_gpuData->m_batchSizes.size() == 0)
  214. {
  215. B3_PROFILE("initBatchConstraintsKernel");
  216. m_gpuData->m_gpuConstraintRowOffsets->resize(numConstraints);
  217. unsigned int total = 0;
  218. m_gpuData->m_prefixScan->execute(*m_gpuData->m_gpuConstraintInfo1, *m_gpuData->m_gpuConstraintRowOffsets, numConstraints, &total);
  219. unsigned int lastElem = m_gpuData->m_gpuConstraintInfo1->at(numConstraints - 1);
  220. totalNumRows = total + lastElem;
  221. {
  222. B3_PROFILE("init batch constraints");
  223. b3LauncherCL launcher(m_gpuData->m_queue, m_gpuData->m_initBatchConstraintsKernel, "m_initBatchConstraintsKernel");
  224. launcher.setBuffer(m_gpuData->m_gpuConstraintInfo1->getBufferCL());
  225. launcher.setBuffer(m_gpuData->m_gpuConstraintRowOffsets->getBufferCL());
  226. launcher.setBuffer(m_gpuData->m_gpuBatchConstraints->getBufferCL());
  227. launcher.setBuffer(gpuConstraints->getBufferCL());
  228. launcher.setBuffer(gpuBodies->getBufferCL());
  229. launcher.setConst(numConstraints);
  230. launcher.launch1D(numConstraints);
  231. clFinish(m_gpuData->m_queue);
  232. }
  233. //assume the batching happens on CPU, so copy the data
  234. m_gpuData->m_gpuBatchConstraints->copyToHost(batchConstraints);
  235. }
  236. }
  237. else
  238. {
  239. totalNumRows = 0;
  240. gpuConstraints->copyToHost(m_gpuData->m_cpuConstraints);
  241. //calculate the total number of contraint rows
  242. for (int i = 0; i < numConstraints; i++)
  243. {
  244. unsigned int& info1 = m_tmpConstraintSizesPool[i];
  245. // unsigned int info1;
  246. if (m_gpuData->m_cpuConstraints[i].isEnabled())
  247. {
  248. m_gpuData->m_cpuConstraints[i].getInfo1(&info1, &m_gpuData->m_cpuBodies[0]);
  249. }
  250. else
  251. {
  252. info1 = 0;
  253. }
  254. totalNumRows += info1;
  255. }
  256. m_gpuData->m_gpuBatchConstraints->copyFromHost(batchConstraints);
  257. m_gpuData->m_gpuConstraintInfo1->copyFromHost(m_tmpConstraintSizesPool);
  258. }
  259. m_tmpSolverNonContactConstraintPool.resizeNoInitialize(totalNumRows);
  260. m_gpuData->m_gpuConstraintRows->resize(totalNumRows);
  261. // b3GpuConstraintArray verify;
  262. if (useGpuInfo2)
  263. {
  264. {
  265. B3_PROFILE("getInfo2Kernel");
  266. b3LauncherCL launcher(m_gpuData->m_queue, m_gpuData->m_getInfo2Kernel, "m_getInfo2Kernel");
  267. launcher.setBuffer(m_gpuData->m_gpuConstraintRows->getBufferCL());
  268. launcher.setBuffer(m_gpuData->m_gpuConstraintInfo1->getBufferCL());
  269. launcher.setBuffer(m_gpuData->m_gpuConstraintRowOffsets->getBufferCL());
  270. launcher.setBuffer(gpuConstraints->getBufferCL());
  271. launcher.setBuffer(m_gpuData->m_gpuBatchConstraints->getBufferCL());
  272. launcher.setBuffer(gpuBodies->getBufferCL());
  273. launcher.setBuffer(gpuInertias->getBufferCL());
  274. launcher.setBuffer(m_gpuData->m_gpuSolverBodies->getBufferCL());
  275. launcher.setConst(infoGlobal.m_timeStep);
  276. launcher.setConst(infoGlobal.m_erp);
  277. launcher.setConst(infoGlobal.m_globalCfm);
  278. launcher.setConst(infoGlobal.m_damping);
  279. launcher.setConst(infoGlobal.m_numIterations);
  280. launcher.setConst(numConstraints);
  281. launcher.launch1D(numConstraints);
  282. clFinish(m_gpuData->m_queue);
  283. if (m_gpuData->m_batchSizes.size() == 0)
  284. m_gpuData->m_gpuBatchConstraints->copyToHost(batchConstraints);
  285. //m_gpuData->m_gpuConstraintRows->copyToHost(verify);
  286. //m_gpuData->m_gpuConstraintRows->copyToHost(m_tmpSolverNonContactConstraintPool);
  287. }
  288. }
  289. else
  290. {
  291. gpuInertias->copyToHost(m_gpuData->m_cpuInertias);
  292. ///setup the b3SolverConstraints
  293. for (int i = 0; i < numConstraints; i++)
  294. {
  295. const int& info1 = m_tmpConstraintSizesPool[i];
  296. if (info1)
  297. {
  298. int constraintIndex = batchConstraints[i].m_originalConstraintIndex;
  299. int constraintRowOffset = m_gpuData->m_cpuConstraintRowOffsets[constraintIndex];
  300. b3GpuSolverConstraint* currentConstraintRow = &m_tmpSolverNonContactConstraintPool[constraintRowOffset];
  301. b3GpuGenericConstraint& constraint = m_gpuData->m_cpuConstraints[i];
  302. b3RigidBodyData& rbA = m_gpuData->m_cpuBodies[constraint.getRigidBodyA()];
  303. //b3RigidBody& rbA = constraint.getRigidBodyA();
  304. // b3RigidBody& rbB = constraint.getRigidBodyB();
  305. b3RigidBodyData& rbB = m_gpuData->m_cpuBodies[constraint.getRigidBodyB()];
  306. int solverBodyIdA = constraint.getRigidBodyA(); //getOrInitSolverBody(constraint.getRigidBodyA(),bodies,inertias);
  307. int solverBodyIdB = constraint.getRigidBodyB(); //getOrInitSolverBody(constraint.getRigidBodyB(),bodies,inertias);
  308. b3GpuSolverBody* bodyAPtr = &m_tmpSolverBodyPool[solverBodyIdA];
  309. b3GpuSolverBody* bodyBPtr = &m_tmpSolverBodyPool[solverBodyIdB];
  310. if (rbA.m_invMass)
  311. {
  312. batchConstraints[i].m_bodyAPtrAndSignBit = solverBodyIdA;
  313. }
  314. else
  315. {
  316. if (!solverBodyIdA)
  317. m_staticIdx = 0;
  318. batchConstraints[i].m_bodyAPtrAndSignBit = -solverBodyIdA;
  319. }
  320. if (rbB.m_invMass)
  321. {
  322. batchConstraints[i].m_bodyBPtrAndSignBit = solverBodyIdB;
  323. }
  324. else
  325. {
  326. if (!solverBodyIdB)
  327. m_staticIdx = 0;
  328. batchConstraints[i].m_bodyBPtrAndSignBit = -solverBodyIdB;
  329. }
  330. int overrideNumSolverIterations = 0; //constraint->getOverrideNumSolverIterations() > 0 ? constraint->getOverrideNumSolverIterations() : infoGlobal.m_numIterations;
  331. if (overrideNumSolverIterations > m_maxOverrideNumSolverIterations)
  332. m_maxOverrideNumSolverIterations = overrideNumSolverIterations;
  333. int j;
  334. for (j = 0; j < info1; j++)
  335. {
  336. memset(&currentConstraintRow[j], 0, sizeof(b3GpuSolverConstraint));
  337. currentConstraintRow[j].m_angularComponentA.setValue(0, 0, 0);
  338. currentConstraintRow[j].m_angularComponentB.setValue(0, 0, 0);
  339. currentConstraintRow[j].m_appliedImpulse = 0.f;
  340. currentConstraintRow[j].m_appliedPushImpulse = 0.f;
  341. currentConstraintRow[j].m_cfm = 0.f;
  342. currentConstraintRow[j].m_contactNormal.setValue(0, 0, 0);
  343. currentConstraintRow[j].m_friction = 0.f;
  344. currentConstraintRow[j].m_frictionIndex = 0;
  345. currentConstraintRow[j].m_jacDiagABInv = 0.f;
  346. currentConstraintRow[j].m_lowerLimit = 0.f;
  347. currentConstraintRow[j].m_upperLimit = 0.f;
  348. currentConstraintRow[j].m_originalContactPoint = 0;
  349. currentConstraintRow[j].m_overrideNumSolverIterations = 0;
  350. currentConstraintRow[j].m_relpos1CrossNormal.setValue(0, 0, 0);
  351. currentConstraintRow[j].m_relpos2CrossNormal.setValue(0, 0, 0);
  352. currentConstraintRow[j].m_rhs = 0.f;
  353. currentConstraintRow[j].m_rhsPenetration = 0.f;
  354. currentConstraintRow[j].m_solverBodyIdA = 0;
  355. currentConstraintRow[j].m_solverBodyIdB = 0;
  356. currentConstraintRow[j].m_lowerLimit = -B3_INFINITY;
  357. currentConstraintRow[j].m_upperLimit = B3_INFINITY;
  358. currentConstraintRow[j].m_appliedImpulse = 0.f;
  359. currentConstraintRow[j].m_appliedPushImpulse = 0.f;
  360. currentConstraintRow[j].m_solverBodyIdA = solverBodyIdA;
  361. currentConstraintRow[j].m_solverBodyIdB = solverBodyIdB;
  362. currentConstraintRow[j].m_overrideNumSolverIterations = overrideNumSolverIterations;
  363. }
  364. bodyAPtr->internalGetDeltaLinearVelocity().setValue(0.f, 0.f, 0.f);
  365. bodyAPtr->internalGetDeltaAngularVelocity().setValue(0.f, 0.f, 0.f);
  366. bodyAPtr->internalGetPushVelocity().setValue(0.f, 0.f, 0.f);
  367. bodyAPtr->internalGetTurnVelocity().setValue(0.f, 0.f, 0.f);
  368. bodyBPtr->internalGetDeltaLinearVelocity().setValue(0.f, 0.f, 0.f);
  369. bodyBPtr->internalGetDeltaAngularVelocity().setValue(0.f, 0.f, 0.f);
  370. bodyBPtr->internalGetPushVelocity().setValue(0.f, 0.f, 0.f);
  371. bodyBPtr->internalGetTurnVelocity().setValue(0.f, 0.f, 0.f);
  372. b3GpuConstraintInfo2 info2;
  373. info2.fps = 1.f / infoGlobal.m_timeStep;
  374. info2.erp = infoGlobal.m_erp;
  375. info2.m_J1linearAxis = currentConstraintRow->m_contactNormal;
  376. info2.m_J1angularAxis = currentConstraintRow->m_relpos1CrossNormal;
  377. info2.m_J2linearAxis = 0;
  378. info2.m_J2angularAxis = currentConstraintRow->m_relpos2CrossNormal;
  379. info2.rowskip = sizeof(b3GpuSolverConstraint) / sizeof(b3Scalar); //check this
  380. ///the size of b3GpuSolverConstraint needs be a multiple of b3Scalar
  381. b3Assert(info2.rowskip * sizeof(b3Scalar) == sizeof(b3GpuSolverConstraint));
  382. info2.m_constraintError = &currentConstraintRow->m_rhs;
  383. currentConstraintRow->m_cfm = infoGlobal.m_globalCfm;
  384. info2.m_damping = infoGlobal.m_damping;
  385. info2.cfm = &currentConstraintRow->m_cfm;
  386. info2.m_lowerLimit = &currentConstraintRow->m_lowerLimit;
  387. info2.m_upperLimit = &currentConstraintRow->m_upperLimit;
  388. info2.m_numIterations = infoGlobal.m_numIterations;
  389. m_gpuData->m_cpuConstraints[i].getInfo2(&info2, &m_gpuData->m_cpuBodies[0]);
  390. ///finalize the constraint setup
  391. for (j = 0; j < info1; j++)
  392. {
  393. b3GpuSolverConstraint& solverConstraint = currentConstraintRow[j];
  394. if (solverConstraint.m_upperLimit >= m_gpuData->m_cpuConstraints[i].getBreakingImpulseThreshold())
  395. {
  396. solverConstraint.m_upperLimit = m_gpuData->m_cpuConstraints[i].getBreakingImpulseThreshold();
  397. }
  398. if (solverConstraint.m_lowerLimit <= -m_gpuData->m_cpuConstraints[i].getBreakingImpulseThreshold())
  399. {
  400. solverConstraint.m_lowerLimit = -m_gpuData->m_cpuConstraints[i].getBreakingImpulseThreshold();
  401. }
  402. // solverConstraint.m_originalContactPoint = constraint;
  403. b3Matrix3x3& invInertiaWorldA = m_gpuData->m_cpuInertias[constraint.getRigidBodyA()].m_invInertiaWorld;
  404. {
  405. //b3Vector3 angularFactorA(1,1,1);
  406. const b3Vector3& ftorqueAxis1 = solverConstraint.m_relpos1CrossNormal;
  407. solverConstraint.m_angularComponentA = invInertiaWorldA * ftorqueAxis1; //*angularFactorA;
  408. }
  409. b3Matrix3x3& invInertiaWorldB = m_gpuData->m_cpuInertias[constraint.getRigidBodyB()].m_invInertiaWorld;
  410. {
  411. const b3Vector3& ftorqueAxis2 = solverConstraint.m_relpos2CrossNormal;
  412. solverConstraint.m_angularComponentB = invInertiaWorldB * ftorqueAxis2; //*constraint.getRigidBodyB().getAngularFactor();
  413. }
  414. {
  415. //it is ok to use solverConstraint.m_contactNormal instead of -solverConstraint.m_contactNormal
  416. //because it gets multiplied iMJlB
  417. b3Vector3 iMJlA = solverConstraint.m_contactNormal * rbA.m_invMass;
  418. b3Vector3 iMJaA = invInertiaWorldA * solverConstraint.m_relpos1CrossNormal;
  419. b3Vector3 iMJlB = solverConstraint.m_contactNormal * rbB.m_invMass; //sign of normal?
  420. b3Vector3 iMJaB = invInertiaWorldB * solverConstraint.m_relpos2CrossNormal;
  421. b3Scalar sum = iMJlA.dot(solverConstraint.m_contactNormal);
  422. sum += iMJaA.dot(solverConstraint.m_relpos1CrossNormal);
  423. sum += iMJlB.dot(solverConstraint.m_contactNormal);
  424. sum += iMJaB.dot(solverConstraint.m_relpos2CrossNormal);
  425. b3Scalar fsum = b3Fabs(sum);
  426. b3Assert(fsum > B3_EPSILON);
  427. solverConstraint.m_jacDiagABInv = fsum > B3_EPSILON ? b3Scalar(1.) / sum : 0.f;
  428. }
  429. ///fix rhs
  430. ///todo: add force/torque accelerators
  431. {
  432. b3Scalar rel_vel;
  433. b3Scalar vel1Dotn = solverConstraint.m_contactNormal.dot(rbA.m_linVel) + solverConstraint.m_relpos1CrossNormal.dot(rbA.m_angVel);
  434. b3Scalar vel2Dotn = -solverConstraint.m_contactNormal.dot(rbB.m_linVel) + solverConstraint.m_relpos2CrossNormal.dot(rbB.m_angVel);
  435. rel_vel = vel1Dotn + vel2Dotn;
  436. b3Scalar restitution = 0.f;
  437. b3Scalar positionalError = solverConstraint.m_rhs; //already filled in by getConstraintInfo2
  438. b3Scalar velocityError = restitution - rel_vel * info2.m_damping;
  439. b3Scalar penetrationImpulse = positionalError * solverConstraint.m_jacDiagABInv;
  440. b3Scalar velocityImpulse = velocityError * solverConstraint.m_jacDiagABInv;
  441. solverConstraint.m_rhs = penetrationImpulse + velocityImpulse;
  442. solverConstraint.m_appliedImpulse = 0.f;
  443. }
  444. }
  445. }
  446. }
  447. m_gpuData->m_gpuConstraintRows->copyFromHost(m_tmpSolverNonContactConstraintPool);
  448. m_gpuData->m_gpuConstraintInfo1->copyFromHost(m_tmpConstraintSizesPool);
  449. if (m_gpuData->m_batchSizes.size() == 0)
  450. m_gpuData->m_gpuBatchConstraints->copyFromHost(batchConstraints);
  451. else
  452. m_gpuData->m_gpuBatchConstraints->copyToHost(batchConstraints);
  453. m_gpuData->m_gpuSolverBodies->copyFromHost(m_tmpSolverBodyPool);
  454. } //end useGpuInfo2
  455. }
  456. #ifdef B3_SUPPORT_CONTACT_CONSTRAINTS
  457. {
  458. int i;
  459. for (i = 0; i < numManifolds; i++)
  460. {
  461. b3Contact4& manifold = manifoldPtr[i];
  462. convertContact(bodies, inertias, &manifold, infoGlobal);
  463. }
  464. }
  465. #endif //B3_SUPPORT_CONTACT_CONSTRAINTS
  466. }
  467. // b3ContactSolverInfo info = infoGlobal;
  468. // int numNonContactPool = m_tmpSolverNonContactConstraintPool.size();
  469. // int numConstraintPool = m_tmpSolverContactConstraintPool.size();
  470. // int numFrictionPool = m_tmpSolverContactFrictionConstraintPool.size();
  471. return 0.f;
  472. }
  473. ///a straight copy from GPU/OpenCL kernel, for debugging
  474. __inline void internalApplyImpulse(b3GpuSolverBody* body, const b3Vector3& linearComponent, const b3Vector3& angularComponent, float impulseMagnitude)
  475. {
  476. body->m_deltaLinearVelocity += linearComponent * impulseMagnitude * body->m_linearFactor;
  477. body->m_deltaAngularVelocity += angularComponent * (impulseMagnitude * body->m_angularFactor);
  478. }
  479. void resolveSingleConstraintRowGeneric2(b3GpuSolverBody* body1, b3GpuSolverBody* body2, b3GpuSolverConstraint* c)
  480. {
  481. float deltaImpulse = c->m_rhs - b3Scalar(c->m_appliedImpulse) * c->m_cfm;
  482. float deltaVel1Dotn = b3Dot(c->m_contactNormal, body1->m_deltaLinearVelocity) + b3Dot(c->m_relpos1CrossNormal, body1->m_deltaAngularVelocity);
  483. float deltaVel2Dotn = -b3Dot(c->m_contactNormal, body2->m_deltaLinearVelocity) + b3Dot(c->m_relpos2CrossNormal, body2->m_deltaAngularVelocity);
  484. deltaImpulse -= deltaVel1Dotn * c->m_jacDiagABInv;
  485. deltaImpulse -= deltaVel2Dotn * c->m_jacDiagABInv;
  486. float sum = b3Scalar(c->m_appliedImpulse) + deltaImpulse;
  487. if (sum < c->m_lowerLimit)
  488. {
  489. deltaImpulse = c->m_lowerLimit - b3Scalar(c->m_appliedImpulse);
  490. c->m_appliedImpulse = c->m_lowerLimit;
  491. }
  492. else if (sum > c->m_upperLimit)
  493. {
  494. deltaImpulse = c->m_upperLimit - b3Scalar(c->m_appliedImpulse);
  495. c->m_appliedImpulse = c->m_upperLimit;
  496. }
  497. else
  498. {
  499. c->m_appliedImpulse = sum;
  500. }
  501. internalApplyImpulse(body1, c->m_contactNormal * body1->m_invMass, c->m_angularComponentA, deltaImpulse);
  502. internalApplyImpulse(body2, -c->m_contactNormal * body2->m_invMass, c->m_angularComponentB, deltaImpulse);
  503. }
  504. void b3GpuPgsConstraintSolver::initSolverBody(int bodyIndex, b3GpuSolverBody* solverBody, b3RigidBodyData* rb)
  505. {
  506. solverBody->m_deltaLinearVelocity.setValue(0.f, 0.f, 0.f);
  507. solverBody->m_deltaAngularVelocity.setValue(0.f, 0.f, 0.f);
  508. solverBody->internalGetPushVelocity().setValue(0.f, 0.f, 0.f);
  509. solverBody->internalGetTurnVelocity().setValue(0.f, 0.f, 0.f);
  510. b3Assert(rb);
  511. // solverBody->m_worldTransform = getWorldTransform(rb);
  512. solverBody->internalSetInvMass(b3MakeVector3(rb->m_invMass, rb->m_invMass, rb->m_invMass));
  513. solverBody->m_originalBodyIndex = bodyIndex;
  514. solverBody->m_angularFactor = b3MakeVector3(1, 1, 1);
  515. solverBody->m_linearFactor = b3MakeVector3(1, 1, 1);
  516. solverBody->m_linearVelocity = getLinearVelocity(rb);
  517. solverBody->m_angularVelocity = getAngularVelocity(rb);
  518. }
  519. void b3GpuPgsConstraintSolver::averageVelocities()
  520. {
  521. }
  522. b3Scalar b3GpuPgsConstraintSolver::solveGroupCacheFriendlyIterations(b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints1, int numConstraints, const b3ContactSolverInfo& infoGlobal)
  523. {
  524. //only create the batches once.
  525. //@todo: incrementally update batches when constraints are added/activated and/or removed/deactivated
  526. B3_PROFILE("GpuSolveGroupCacheFriendlyIterations");
  527. bool createBatches = m_gpuData->m_batchSizes.size() == 0;
  528. {
  529. if (createBatches)
  530. {
  531. m_gpuData->m_batchSizes.resize(0);
  532. {
  533. m_gpuData->m_gpuBatchConstraints->copyToHost(batchConstraints);
  534. B3_PROFILE("batch joints");
  535. b3Assert(batchConstraints.size() == numConstraints);
  536. int simdWidth = numConstraints + 1;
  537. int numBodies = m_tmpSolverBodyPool.size();
  538. sortConstraintByBatch3(&batchConstraints[0], numConstraints, simdWidth, m_staticIdx, numBodies);
  539. m_gpuData->m_gpuBatchConstraints->copyFromHost(batchConstraints);
  540. }
  541. }
  542. else
  543. {
  544. /*b3AlignedObjectArray<b3BatchConstraint> cpuCheckBatches;
  545. m_gpuData->m_gpuBatchConstraints->copyToHost(cpuCheckBatches);
  546. b3Assert(cpuCheckBatches.size()==batchConstraints.size());
  547. printf(".\n");
  548. */
  549. //>copyFromHost(batchConstraints);
  550. }
  551. int maxIterations = infoGlobal.m_numIterations;
  552. bool useBatching = true;
  553. if (useBatching)
  554. {
  555. if (!useGpuSolveJointConstraintRows)
  556. {
  557. B3_PROFILE("copy to host");
  558. m_gpuData->m_gpuSolverBodies->copyToHost(m_tmpSolverBodyPool);
  559. m_gpuData->m_gpuBatchConstraints->copyToHost(batchConstraints);
  560. m_gpuData->m_gpuConstraintRows->copyToHost(m_tmpSolverNonContactConstraintPool);
  561. m_gpuData->m_gpuConstraintInfo1->copyToHost(m_gpuData->m_cpuConstraintInfo1);
  562. m_gpuData->m_gpuConstraintRowOffsets->copyToHost(m_gpuData->m_cpuConstraintRowOffsets);
  563. gpuConstraints1->copyToHost(m_gpuData->m_cpuConstraints);
  564. }
  565. for (int iteration = 0; iteration < maxIterations; iteration++)
  566. {
  567. int batchOffset = 0;
  568. int constraintOffset = 0;
  569. int numBatches = m_gpuData->m_batchSizes.size();
  570. for (int bb = 0; bb < numBatches; bb++)
  571. {
  572. int numConstraintsInBatch = m_gpuData->m_batchSizes[bb];
  573. if (useGpuSolveJointConstraintRows)
  574. {
  575. B3_PROFILE("solveJointConstraintRowsKernels");
  576. /*
  577. __kernel void solveJointConstraintRows(__global b3GpuSolverBody* solverBodies,
  578. __global b3BatchConstraint* batchConstraints,
  579. __global b3SolverConstraint* rows,
  580. __global unsigned int* numConstraintRowsInfo1,
  581. __global unsigned int* rowOffsets,
  582. __global b3GpuGenericConstraint* constraints,
  583. int batchOffset,
  584. int numConstraintsInBatch*/
  585. b3LauncherCL launcher(m_gpuData->m_queue, m_gpuData->m_solveJointConstraintRowsKernels, "m_solveJointConstraintRowsKernels");
  586. launcher.setBuffer(m_gpuData->m_gpuSolverBodies->getBufferCL());
  587. launcher.setBuffer(m_gpuData->m_gpuBatchConstraints->getBufferCL());
  588. launcher.setBuffer(m_gpuData->m_gpuConstraintRows->getBufferCL());
  589. launcher.setBuffer(m_gpuData->m_gpuConstraintInfo1->getBufferCL());
  590. launcher.setBuffer(m_gpuData->m_gpuConstraintRowOffsets->getBufferCL());
  591. launcher.setBuffer(gpuConstraints1->getBufferCL()); //to detect disabled constraints
  592. launcher.setConst(batchOffset);
  593. launcher.setConst(numConstraintsInBatch);
  594. launcher.launch1D(numConstraintsInBatch);
  595. }
  596. else //useGpu
  597. {
  598. for (int b = 0; b < numConstraintsInBatch; b++)
  599. {
  600. const b3BatchConstraint& c = batchConstraints[batchOffset + b];
  601. /*printf("-----------\n");
  602. printf("bb=%d\n",bb);
  603. printf("c.batchId = %d\n", c.m_batchId);
  604. */
  605. b3Assert(c.m_batchId == bb);
  606. b3GpuGenericConstraint* constraint = &m_gpuData->m_cpuConstraints[c.m_originalConstraintIndex];
  607. if (constraint->m_flags & B3_CONSTRAINT_FLAG_ENABLED)
  608. {
  609. int numConstraintRows = m_gpuData->m_cpuConstraintInfo1[c.m_originalConstraintIndex];
  610. int constraintOffset = m_gpuData->m_cpuConstraintRowOffsets[c.m_originalConstraintIndex];
  611. for (int jj = 0; jj < numConstraintRows; jj++)
  612. {
  613. //
  614. b3GpuSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[constraintOffset + jj];
  615. //resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[constraint.m_solverBodyIdA],m_tmpSolverBodyPool[constraint.m_solverBodyIdB],constraint);
  616. resolveSingleConstraintRowGeneric2(&m_tmpSolverBodyPool[constraint.m_solverBodyIdA], &m_tmpSolverBodyPool[constraint.m_solverBodyIdB], &constraint);
  617. }
  618. }
  619. }
  620. } //useGpu
  621. batchOffset += numConstraintsInBatch;
  622. constraintOffset += numConstraintsInBatch;
  623. }
  624. } //for (int iteration...
  625. if (!useGpuSolveJointConstraintRows)
  626. {
  627. {
  628. B3_PROFILE("copy from host");
  629. m_gpuData->m_gpuSolverBodies->copyFromHost(m_tmpSolverBodyPool);
  630. m_gpuData->m_gpuBatchConstraints->copyFromHost(batchConstraints);
  631. m_gpuData->m_gpuConstraintRows->copyFromHost(m_tmpSolverNonContactConstraintPool);
  632. }
  633. //B3_PROFILE("copy to host");
  634. //m_gpuData->m_gpuSolverBodies->copyToHost(m_tmpSolverBodyPool);
  635. }
  636. //int sz = sizeof(b3GpuSolverBody);
  637. //printf("cpu sizeof(b3GpuSolverBody)=%d\n",sz);
  638. }
  639. else
  640. {
  641. for (int iteration = 0; iteration < maxIterations; iteration++)
  642. {
  643. int numJoints = m_tmpSolverNonContactConstraintPool.size();
  644. for (int j = 0; j < numJoints; j++)
  645. {
  646. b3GpuSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[j];
  647. resolveSingleConstraintRowGeneric2(&m_tmpSolverBodyPool[constraint.m_solverBodyIdA], &m_tmpSolverBodyPool[constraint.m_solverBodyIdB], &constraint);
  648. }
  649. if (!m_usePgs)
  650. {
  651. averageVelocities();
  652. }
  653. }
  654. }
  655. }
  656. clFinish(m_gpuData->m_queue);
  657. return 0.f;
  658. }
  659. static b3AlignedObjectArray<int> bodyUsed;
  660. static b3AlignedObjectArray<int> curUsed;
  661. inline int b3GpuPgsConstraintSolver::sortConstraintByBatch3(b3BatchConstraint* cs, int numConstraints, int simdWidth, int staticIdx, int numBodies)
  662. {
  663. //int sz = sizeof(b3BatchConstraint);
  664. B3_PROFILE("sortConstraintByBatch3");
  665. static int maxSwaps = 0;
  666. int numSwaps = 0;
  667. curUsed.resize(2 * simdWidth);
  668. static int maxNumConstraints = 0;
  669. if (maxNumConstraints < numConstraints)
  670. {
  671. maxNumConstraints = numConstraints;
  672. //printf("maxNumConstraints = %d\n",maxNumConstraints );
  673. }
  674. int numUsedArray = numBodies / 32 + 1;
  675. bodyUsed.resize(numUsedArray);
  676. for (int q = 0; q < numUsedArray; q++)
  677. bodyUsed[q] = 0;
  678. int curBodyUsed = 0;
  679. int numIter = 0;
  680. #if defined(_DEBUG)
  681. for (int i = 0; i < numConstraints; i++)
  682. cs[i].m_batchId = -1;
  683. #endif
  684. int numValidConstraints = 0;
  685. // int unprocessedConstraintIndex = 0;
  686. int batchIdx = 0;
  687. {
  688. B3_PROFILE("cpu batch innerloop");
  689. while (numValidConstraints < numConstraints)
  690. {
  691. numIter++;
  692. int nCurrentBatch = 0;
  693. // clear flag
  694. for (int i = 0; i < curBodyUsed; i++)
  695. bodyUsed[curUsed[i] / 32] = 0;
  696. curBodyUsed = 0;
  697. for (int i = numValidConstraints; i < numConstraints; i++)
  698. {
  699. int idx = i;
  700. b3Assert(idx < numConstraints);
  701. // check if it can go
  702. int bodyAS = cs[idx].m_bodyAPtrAndSignBit;
  703. int bodyBS = cs[idx].m_bodyBPtrAndSignBit;
  704. int bodyA = abs(bodyAS);
  705. int bodyB = abs(bodyBS);
  706. bool aIsStatic = (bodyAS < 0) || bodyAS == staticIdx;
  707. bool bIsStatic = (bodyBS < 0) || bodyBS == staticIdx;
  708. int aUnavailable = 0;
  709. int bUnavailable = 0;
  710. if (!aIsStatic)
  711. {
  712. aUnavailable = bodyUsed[bodyA / 32] & (1 << (bodyA & 31));
  713. }
  714. if (!aUnavailable)
  715. if (!bIsStatic)
  716. {
  717. bUnavailable = bodyUsed[bodyB / 32] & (1 << (bodyB & 31));
  718. }
  719. if (aUnavailable == 0 && bUnavailable == 0) // ok
  720. {
  721. if (!aIsStatic)
  722. {
  723. bodyUsed[bodyA / 32] |= (1 << (bodyA & 31));
  724. curUsed[curBodyUsed++] = bodyA;
  725. }
  726. if (!bIsStatic)
  727. {
  728. bodyUsed[bodyB / 32] |= (1 << (bodyB & 31));
  729. curUsed[curBodyUsed++] = bodyB;
  730. }
  731. cs[idx].m_batchId = batchIdx;
  732. if (i != numValidConstraints)
  733. {
  734. b3Swap(cs[i], cs[numValidConstraints]);
  735. numSwaps++;
  736. }
  737. numValidConstraints++;
  738. {
  739. nCurrentBatch++;
  740. if (nCurrentBatch == simdWidth)
  741. {
  742. nCurrentBatch = 0;
  743. for (int i = 0; i < curBodyUsed; i++)
  744. bodyUsed[curUsed[i] / 32] = 0;
  745. curBodyUsed = 0;
  746. }
  747. }
  748. }
  749. }
  750. m_gpuData->m_batchSizes.push_back(nCurrentBatch);
  751. batchIdx++;
  752. }
  753. }
  754. #if defined(_DEBUG)
  755. // debugPrintf( "nBatches: %d\n", batchIdx );
  756. for (int i = 0; i < numConstraints; i++)
  757. {
  758. b3Assert(cs[i].m_batchId != -1);
  759. }
  760. #endif
  761. if (maxSwaps < numSwaps)
  762. {
  763. maxSwaps = numSwaps;
  764. //printf("maxSwaps = %d\n", maxSwaps);
  765. }
  766. return batchIdx;
  767. }
  768. /// b3PgsJacobiSolver Sequentially applies impulses
  769. b3Scalar b3GpuPgsConstraintSolver::solveGroup(b3OpenCLArray<b3RigidBodyData>* gpuBodies, b3OpenCLArray<b3InertiaData>* gpuInertias,
  770. int numBodies, b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints, int numConstraints, const b3ContactSolverInfo& infoGlobal)
  771. {
  772. B3_PROFILE("solveJoints");
  773. //you need to provide at least some bodies
  774. solveGroupCacheFriendlySetup(gpuBodies, gpuInertias, numBodies, gpuConstraints, numConstraints, infoGlobal);
  775. solveGroupCacheFriendlyIterations(gpuConstraints, numConstraints, infoGlobal);
  776. solveGroupCacheFriendlyFinish(gpuBodies, gpuInertias, numBodies, gpuConstraints, numConstraints, infoGlobal);
  777. return 0.f;
  778. }
  779. void b3GpuPgsConstraintSolver::solveJoints(int numBodies, b3OpenCLArray<b3RigidBodyData>* gpuBodies, b3OpenCLArray<b3InertiaData>* gpuInertias,
  780. int numConstraints, b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints)
  781. {
  782. b3ContactSolverInfo infoGlobal;
  783. infoGlobal.m_splitImpulse = false;
  784. infoGlobal.m_timeStep = 1.f / 60.f;
  785. infoGlobal.m_numIterations = 4; //4;
  786. // infoGlobal.m_solverMode|=B3_SOLVER_USE_2_FRICTION_DIRECTIONS|B3_SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS|B3_SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION;
  787. //infoGlobal.m_solverMode|=B3_SOLVER_USE_2_FRICTION_DIRECTIONS|B3_SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS;
  788. infoGlobal.m_solverMode |= B3_SOLVER_USE_2_FRICTION_DIRECTIONS;
  789. //if (infoGlobal.m_solverMode & B3_SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS)
  790. //if ((infoGlobal.m_solverMode & B3_SOLVER_USE_2_FRICTION_DIRECTIONS) && (infoGlobal.m_solverMode & B3_SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION))
  791. solveGroup(gpuBodies, gpuInertias, numBodies, gpuConstraints, numConstraints, infoGlobal);
  792. }
  793. //b3AlignedObjectArray<b3RigidBodyData> testBodies;
  794. b3Scalar b3GpuPgsConstraintSolver::solveGroupCacheFriendlyFinish(b3OpenCLArray<b3RigidBodyData>* gpuBodies, b3OpenCLArray<b3InertiaData>* gpuInertias, int numBodies, b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints, int numConstraints, const b3ContactSolverInfo& infoGlobal)
  795. {
  796. B3_PROFILE("solveGroupCacheFriendlyFinish");
  797. // int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
  798. // int i,j;
  799. {
  800. if (gpuBreakConstraints)
  801. {
  802. B3_PROFILE("breakViolatedConstraintsKernel");
  803. b3LauncherCL launcher(m_gpuData->m_queue, m_gpuData->m_breakViolatedConstraintsKernel, "m_breakViolatedConstraintsKernel");
  804. launcher.setBuffer(gpuConstraints->getBufferCL());
  805. launcher.setBuffer(m_gpuData->m_gpuConstraintInfo1->getBufferCL());
  806. launcher.setBuffer(m_gpuData->m_gpuConstraintRowOffsets->getBufferCL());
  807. launcher.setBuffer(m_gpuData->m_gpuConstraintRows->getBufferCL());
  808. launcher.setConst(numConstraints);
  809. launcher.launch1D(numConstraints);
  810. }
  811. else
  812. {
  813. gpuConstraints->copyToHost(m_gpuData->m_cpuConstraints);
  814. m_gpuData->m_gpuBatchConstraints->copyToHost(m_gpuData->m_cpuBatchConstraints);
  815. m_gpuData->m_gpuConstraintRows->copyToHost(m_gpuData->m_cpuConstraintRows);
  816. gpuConstraints->copyToHost(m_gpuData->m_cpuConstraints);
  817. m_gpuData->m_gpuConstraintInfo1->copyToHost(m_gpuData->m_cpuConstraintInfo1);
  818. m_gpuData->m_gpuConstraintRowOffsets->copyToHost(m_gpuData->m_cpuConstraintRowOffsets);
  819. for (int cid = 0; cid < numConstraints; cid++)
  820. {
  821. int originalConstraintIndex = batchConstraints[cid].m_originalConstraintIndex;
  822. int constraintRowOffset = m_gpuData->m_cpuConstraintRowOffsets[originalConstraintIndex];
  823. int numRows = m_gpuData->m_cpuConstraintInfo1[originalConstraintIndex];
  824. if (numRows)
  825. {
  826. // printf("cid=%d, breakingThreshold =%f\n",cid,breakingThreshold);
  827. for (int i = 0; i < numRows; i++)
  828. {
  829. int rowIndex = constraintRowOffset + i;
  830. int orgConstraintIndex = m_gpuData->m_cpuConstraintRows[rowIndex].m_originalConstraintIndex;
  831. float breakingThreshold = m_gpuData->m_cpuConstraints[orgConstraintIndex].m_breakingImpulseThreshold;
  832. // printf("rows[%d].m_appliedImpulse=%f\n",rowIndex,rows[rowIndex].m_appliedImpulse);
  833. if (b3Fabs(m_gpuData->m_cpuConstraintRows[rowIndex].m_appliedImpulse) >= breakingThreshold)
  834. {
  835. m_gpuData->m_cpuConstraints[orgConstraintIndex].m_flags = 0; //&= ~B3_CONSTRAINT_FLAG_ENABLED;
  836. }
  837. }
  838. }
  839. }
  840. gpuConstraints->copyFromHost(m_gpuData->m_cpuConstraints);
  841. }
  842. }
  843. {
  844. if (useGpuWriteBackVelocities)
  845. {
  846. B3_PROFILE("GPU write back velocities and transforms");
  847. b3LauncherCL launcher(m_gpuData->m_queue, m_gpuData->m_writeBackVelocitiesKernel, "m_writeBackVelocitiesKernel");
  848. launcher.setBuffer(gpuBodies->getBufferCL());
  849. launcher.setBuffer(m_gpuData->m_gpuSolverBodies->getBufferCL());
  850. launcher.setConst(numBodies);
  851. launcher.launch1D(numBodies);
  852. clFinish(m_gpuData->m_queue);
  853. // m_gpuData->m_gpuSolverBodies->copyToHost(m_tmpSolverBodyPool);
  854. // m_gpuData->m_gpuBodies->copyToHostPointer(bodies,numBodies);
  855. //m_gpuData->m_gpuBodies->copyToHost(testBodies);
  856. }
  857. else
  858. {
  859. B3_PROFILE("CPU write back velocities and transforms");
  860. m_gpuData->m_gpuSolverBodies->copyToHost(m_tmpSolverBodyPool);
  861. gpuBodies->copyToHost(m_gpuData->m_cpuBodies);
  862. for (int i = 0; i < m_tmpSolverBodyPool.size(); i++)
  863. {
  864. int bodyIndex = m_tmpSolverBodyPool[i].m_originalBodyIndex;
  865. //printf("bodyIndex=%d\n",bodyIndex);
  866. b3Assert(i == bodyIndex);
  867. b3RigidBodyData* body = &m_gpuData->m_cpuBodies[bodyIndex];
  868. if (body->m_invMass)
  869. {
  870. if (infoGlobal.m_splitImpulse)
  871. m_tmpSolverBodyPool[i].writebackVelocityAndTransform(infoGlobal.m_timeStep, infoGlobal.m_splitImpulseTurnErp);
  872. else
  873. m_tmpSolverBodyPool[i].writebackVelocity();
  874. if (m_usePgs)
  875. {
  876. body->m_linVel = m_tmpSolverBodyPool[i].m_linearVelocity;
  877. body->m_angVel = m_tmpSolverBodyPool[i].m_angularVelocity;
  878. }
  879. else
  880. {
  881. b3Assert(0);
  882. }
  883. /*
  884. if (infoGlobal.m_splitImpulse)
  885. {
  886. body->m_pos = m_tmpSolverBodyPool[i].m_worldTransform.getOrigin();
  887. b3Quaternion orn;
  888. orn = m_tmpSolverBodyPool[i].m_worldTransform.getRotation();
  889. body->m_quat = orn;
  890. }
  891. */
  892. }
  893. } //for
  894. gpuBodies->copyFromHost(m_gpuData->m_cpuBodies);
  895. }
  896. }
  897. clFinish(m_gpuData->m_queue);
  898. m_tmpSolverContactConstraintPool.resizeNoInitialize(0);
  899. m_tmpSolverNonContactConstraintPool.resizeNoInitialize(0);
  900. m_tmpSolverContactFrictionConstraintPool.resizeNoInitialize(0);
  901. m_tmpSolverContactRollingFrictionConstraintPool.resizeNoInitialize(0);
  902. m_tmpSolverBodyPool.resizeNoInitialize(0);
  903. return 0.f;
  904. }