btSoftBodySolverOutputCLtoGL.cpp

Go to the documentation of this file.
00001 #include "btSoftBodySolverOutputCLtoGL.h"
00002 #include <stdio.h> //@todo: remove the debugging printf at some stage
00003 #include "btSoftBodySolver_OpenCL.h"
00004 #include "BulletSoftBody/btSoftBodySolverVertexBuffer.h"
00005 #include "btSoftBodySolverVertexBuffer_OpenGL.h"
00006 #include "BulletSoftBody/btSoftBody.h"
00007 
00009 #define MSTRINGIFY(A) #A
00010 static char* OutputToVertexArrayCLString =
00011 #include "OpenCLC10/OutputToVertexArray.cl"
00012 
00013         
00014 #define RELEASE_CL_KERNEL(kernelName) {if( kernelName ){ clReleaseKernel( kernelName ); kernelName = 0; }}
00015 
00016 static const size_t workGroupSize = 128;
00017 
00018 void btSoftBodySolverOutputCLtoGL::copySoftBodyToVertexBuffer( const btSoftBody * const softBody, btVertexBufferDescriptor *vertexBuffer )
00019 {
00020 
00021         btSoftBodySolver *solver = softBody->getSoftBodySolver();
00022         btAssert( solver->getSolverType() == btSoftBodySolver::CL_SOLVER || solver->getSolverType() == btSoftBodySolver::CL_SIMD_SOLVER );
00023         btOpenCLSoftBodySolver *dxSolver = static_cast< btOpenCLSoftBodySolver * >( solver );
00024         checkInitialized();
00025         btOpenCLAcceleratedSoftBodyInterface* currentCloth = dxSolver->findSoftBodyInterface( softBody );
00026         btSoftBodyVertexDataOpenCL &vertexData( dxSolver->m_vertexData );       
00027 
00028         const int firstVertex = currentCloth->getFirstVertex();
00029         const int lastVertex = firstVertex + currentCloth->getNumVertices();
00030 
00031         if( vertexBuffer->getBufferType() == btVertexBufferDescriptor::OPENGL_BUFFER ) {                
00032 
00033                 const btOpenGLInteropVertexBufferDescriptor *openGLVertexBuffer = static_cast< btOpenGLInteropVertexBufferDescriptor* >(vertexBuffer);                                          
00034                 cl_int ciErrNum = CL_SUCCESS;    
00035 
00036                 cl_mem clBuffer = openGLVertexBuffer->getBuffer();              
00037                 cl_kernel outputKernel = outputToVertexArrayWithNormalsKernel;
00038                 if( !vertexBuffer->hasNormals() )
00039                         outputKernel = outputToVertexArrayWithoutNormalsKernel;
00040 
00041                 ciErrNum = clEnqueueAcquireGLObjects(m_cqCommandQue, 1, &clBuffer, 0, 0, NULL);
00042                 if( ciErrNum != CL_SUCCESS )
00043                 {
00044                         btAssert( 0 &&  "clEnqueueAcquireGLObjects(copySoftBodyToVertexBuffer)");
00045                 }
00046 
00047                 int numVertices = currentCloth->getNumVertices();
00048 
00049                 ciErrNum = clSetKernelArg(outputKernel, 0, sizeof(int), &firstVertex );
00050                 ciErrNum = clSetKernelArg(outputKernel, 1, sizeof(int), &numVertices );
00051                 ciErrNum = clSetKernelArg(outputKernel, 2, sizeof(cl_mem), (void*)&clBuffer );
00052                 if( vertexBuffer->hasVertexPositions() )
00053                 {
00054                         int vertexOffset = vertexBuffer->getVertexOffset();
00055                         int vertexStride = vertexBuffer->getVertexStride();
00056                         ciErrNum = clSetKernelArg(outputKernel, 3, sizeof(int), &vertexOffset );
00057                         ciErrNum = clSetKernelArg(outputKernel, 4, sizeof(int), &vertexStride );
00058                         ciErrNum = clSetKernelArg(outputKernel, 5, sizeof(cl_mem), (void*)&vertexData.m_clVertexPosition.m_buffer );
00059 
00060                 }
00061                 if( vertexBuffer->hasNormals() )
00062                 {
00063                         int normalOffset = vertexBuffer->getNormalOffset();
00064                         int normalStride = vertexBuffer->getNormalStride();
00065                         ciErrNum = clSetKernelArg(outputKernel, 6, sizeof(int), &normalOffset );
00066                         ciErrNum = clSetKernelArg(outputKernel, 7, sizeof(int), &normalStride );
00067                         ciErrNum = clSetKernelArg(outputKernel, 8, sizeof(cl_mem), (void*)&vertexData.m_clVertexNormal.m_buffer );
00068 
00069                 }
00070                 size_t  numWorkItems = workGroupSize*((vertexData.getNumVertices() + (workGroupSize-1)) / workGroupSize);
00071                 ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue, outputKernel, 1, NULL, &numWorkItems, &workGroupSize,0 ,0 ,0);
00072                 if( ciErrNum != CL_SUCCESS ) 
00073                 {
00074                         btAssert( 0 &&  "enqueueNDRangeKernel(copySoftBodyToVertexBuffer)");
00075                 }
00076 
00077                 ciErrNum = clEnqueueReleaseGLObjects(m_cqCommandQue, 1, &clBuffer, 0, 0, 0);
00078                 if( ciErrNum != CL_SUCCESS )
00079                 {
00080                         btAssert( 0 &&  "clEnqueueReleaseGLObjects(copySoftBodyToVertexBuffer)");
00081                 }
00082         } else {
00083                 btAssert( "Undefined output for this solver output" == false );
00084         }
00085 
00086         // clFinish in here may not be the best thing. It's possible that we should have a waitForFrameComplete function.
00087         clFinish(m_cqCommandQue);
00088 
00089 } // btSoftBodySolverOutputCLtoGL::outputToVertexBuffers
00090 
00091 bool btSoftBodySolverOutputCLtoGL::buildShaders()
00092 {
00093         // Ensure current kernels are released first
00094         releaseKernels();
00095 
00096         bool returnVal = true;
00097 
00098         if( m_shadersInitialized )
00099                 return true;
00100         
00101         outputToVertexArrayWithNormalsKernel = clFunctions.compileCLKernelFromString( OutputToVertexArrayCLString, "OutputToVertexArrayWithNormalsKernel" ,"","OpenCLC10/OutputToVertexArray.cl");
00102         outputToVertexArrayWithoutNormalsKernel = clFunctions.compileCLKernelFromString( OutputToVertexArrayCLString, "OutputToVertexArrayWithoutNormalsKernel" ,"","OpenCLC10/OutputToVertexArray.cl");
00103 
00104 
00105         if( returnVal )
00106                 m_shadersInitialized = true;
00107 
00108         return returnVal;
00109 } // btSoftBodySolverOutputCLtoGL::buildShaders
00110 
00111 void btSoftBodySolverOutputCLtoGL::releaseKernels()
00112 {
00113         RELEASE_CL_KERNEL( outputToVertexArrayWithNormalsKernel );
00114         RELEASE_CL_KERNEL( outputToVertexArrayWithoutNormalsKernel );
00115 
00116         m_shadersInitialized = false;
00117 } // btSoftBodySolverOutputCLtoGL::releaseKernels
00118 
00119 bool btSoftBodySolverOutputCLtoGL::checkInitialized()
00120 {
00121         if( !m_shadersInitialized )
00122                 if( buildShaders() )
00123                         m_shadersInitialized = true;
00124 
00125         return m_shadersInitialized;
00126 }