btSoftBodySolverBuffer_OpenCL.h

Go to the documentation of this file.
00001 /*
00002 Bullet Continuous Collision Detection and Physics Library
00003 Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
00004 
00005 This software is provided 'as-is', without any express or implied warranty.
00006 In no event will the authors be held liable for any damages arising from the use of this software.
00007 Permission is granted to anyone to use this software for any purpose, 
00008 including commercial applications, and to alter it and redistribute it freely, 
00009 subject to the following restrictions:
00010 
00011 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.
00012 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
00013 3. This notice may not be removed or altered from any source distribution.
00014 */
00015 
00016 #ifndef BT_SOFT_BODY_SOLVER_BUFFER_OPENCL_H
00017 #define BT_SOFT_BODY_SOLVER_BUFFER_OPENCL_H
00018 
00019 // OpenCL support
00020 
00021 #ifdef USE_MINICL
00022         #include "MiniCL/cl.h"
00023 #else //USE_MINICL
00024         #ifdef __APPLE__
00025                 #include <OpenCL/OpenCL.h>
00026         #else
00027                 #include <CL/cl.h>
00028         #endif //__APPLE__
00029 #endif//USE_MINICL
00030 
00031 #ifndef SAFE_RELEASE
00032 #define SAFE_RELEASE(p)      { if(p) { (p)->Release(); (p)=NULL; } }
00033 #endif
00034 
00035 template <typename ElementType> class btOpenCLBuffer
00036 {
00037 public:
00038 
00039         cl_command_queue        m_cqCommandQue;
00040         cl_context                      m_clContext;
00041         cl_mem                          m_buffer;
00042 
00043 
00044 
00045         btAlignedObjectArray< ElementType > * m_CPUBuffer;
00046         
00047         int  m_gpuSize;
00048         bool m_onGPU;
00049         bool m_readOnlyOnGPU;
00050         bool m_allocated;
00051 
00052 
00053         bool createBuffer( cl_mem* preexistingBuffer = 0)
00054         {
00055 
00056                 cl_int err;
00057                  
00058 
00059                 if( preexistingBuffer )
00060                 {
00061                         m_buffer = *preexistingBuffer;
00062                 } 
00063                 else {
00064 
00065                         cl_mem_flags flags= m_readOnlyOnGPU ? CL_MEM_READ_ONLY : CL_MEM_READ_WRITE;
00066 
00067                         size_t size = m_CPUBuffer->size() * sizeof(ElementType);
00068                         // At a minimum the buffer must exist
00069                         if( size == 0 )
00070                                 size = sizeof(ElementType);
00071                         m_buffer = clCreateBuffer(m_clContext, flags, size, 0, &err);
00072                         if( err != CL_SUCCESS )
00073                         {
00074                                 btAssert( "Buffer::Buffer(m_buffer)");
00075                         }
00076                 }
00077 
00078                 m_gpuSize = m_CPUBuffer->size();
00079 
00080                 return true;
00081         }
00082 
00083 public:
00084         btOpenCLBuffer( cl_command_queue        commandQue,cl_context ctx, btAlignedObjectArray< ElementType >* CPUBuffer, bool readOnly)
00085                 :m_cqCommandQue(commandQue),
00086                 m_clContext(ctx),
00087                 m_buffer(0),
00088                 m_CPUBuffer(CPUBuffer),
00089                 m_gpuSize(0),
00090                 m_onGPU(false),
00091                 m_readOnlyOnGPU(readOnly),
00092                 m_allocated(false)
00093         {
00094         }
00095 
00096         ~btOpenCLBuffer()
00097         {
00098                 clReleaseMemObject(m_buffer);
00099         }
00100 
00101 
00102         bool moveToGPU()
00103         {
00104 
00105 
00106                 cl_int err;
00107 
00108                 if( (m_CPUBuffer->size() != m_gpuSize) )
00109                 {
00110                         m_onGPU = false;
00111                 }
00112 
00113                 if( !m_allocated && m_CPUBuffer->size() == 0  )
00114                 {
00115                         // If it isn't on the GPU and yet there is no data on the CPU side this may cause a problem with some kernels.
00116                         // We should create *something* on the device side
00117                         if (!createBuffer()) {
00118                                 return false;
00119                         }
00120                         m_allocated = true;
00121                 }
00122 
00123                 if( !m_onGPU && m_CPUBuffer->size() > 0 )
00124                 {
00125                         if (!m_allocated || (m_CPUBuffer->size() != m_gpuSize)) {
00126                                 if (!createBuffer()) {
00127                                         return false;
00128                                 }
00129                                 m_allocated = true;
00130                         }
00131                         
00132                         size_t size = m_CPUBuffer->size() * sizeof(ElementType);
00133                         err = clEnqueueWriteBuffer(m_cqCommandQue,m_buffer,
00134                                 CL_FALSE,
00135                                 0,
00136                                 size, 
00137                                 &((*m_CPUBuffer)[0]),0,0,0);
00138                         if( err != CL_SUCCESS )
00139                         {
00140                                 btAssert( "CommandQueue::enqueueWriteBuffer(m_buffer)" );
00141                         }
00142 
00143                         m_onGPU = true;
00144                 }
00145 
00146                 return true;
00147 
00148         }
00149 
00150         bool moveFromGPU()
00151         {
00152 
00153                 cl_int err;
00154 
00155                 if (m_CPUBuffer->size() > 0) {
00156                         if (m_onGPU && !m_readOnlyOnGPU) {
00157                                 size_t size = m_CPUBuffer->size() * sizeof(ElementType);
00158                                 err = clEnqueueReadBuffer(m_cqCommandQue,
00159                                         m_buffer,
00160                                         CL_TRUE,
00161                                         0,
00162                                         size,
00163                                         &((*m_CPUBuffer)[0]),0,0,0);
00164 
00165                                 if( err != CL_SUCCESS )
00166                                 {
00167                                         btAssert( "CommandQueue::enqueueReadBuffer(m_buffer)" );
00168                                 }
00169 
00170                                 m_onGPU = false;
00171                         }
00172                 }
00173 
00174                 return true;
00175         }
00176 
00177         bool copyFromGPU()
00178         {
00179 
00180                 cl_int err;
00181                 size_t size = m_CPUBuffer->size() * sizeof(ElementType);
00182 
00183                 if (m_CPUBuffer->size() > 0) {
00184                         if (m_onGPU && !m_readOnlyOnGPU) {
00185                                 err = clEnqueueReadBuffer(m_cqCommandQue,
00186                                         m_buffer,
00187                                         CL_TRUE,
00188                                         0,size, 
00189                                         &((*m_CPUBuffer)[0]),0,0,0);
00190 
00191                                 if( err != CL_SUCCESS )
00192                                 {
00193                                         btAssert( "CommandQueue::enqueueReadBuffer(m_buffer)");
00194                                 }
00195 
00196                         }
00197                 }
00198 
00199                 return true;
00200         }
00201 
00202         virtual void changedOnCPU()
00203         {
00204                 m_onGPU = false;
00205         }
00206 }; // class btOpenCLBuffer
00207 
00208 
00209 #endif // #ifndef BT_SOFT_BODY_SOLVER_BUFFER_OPENCL_H