#ifndef B3_OPENCL_ARRAY_H #define B3_OPENCL_ARRAY_H #include "Bullet3Common/b3AlignedObjectArray.h" #include "Bullet3OpenCL/Initialize/b3OpenCLInclude.h" template class b3OpenCLArray { size_t m_size; size_t m_capacity; cl_mem m_clBuffer; cl_context m_clContext; cl_command_queue m_commandQueue; bool m_ownsMemory; bool m_allowGrowingCapacity; void deallocate() { if (m_clBuffer && m_ownsMemory) { clReleaseMemObject(m_clBuffer); } m_clBuffer = 0; m_capacity=0; } b3OpenCLArray& operator=(const b3OpenCLArray& src); B3_FORCE_INLINE size_t allocSize(size_t size) { return (size ? size*2 : 1); } public: b3OpenCLArray(cl_context ctx, cl_command_queue queue, size_t initialCapacity=0, bool allowGrowingCapacity=true) :m_size(0), m_capacity(0),m_clBuffer(0), m_clContext(ctx),m_commandQueue(queue), m_ownsMemory(true),m_allowGrowingCapacity(true) { if (initialCapacity) { reserve(initialCapacity); } m_allowGrowingCapacity = allowGrowingCapacity; } ///this is an error-prone method with no error checking, be careful! void setFromOpenCLBuffer(cl_mem buffer, size_t sizeInElements) { deallocate(); m_ownsMemory = false; m_allowGrowingCapacity = false; m_clBuffer = buffer; m_size = sizeInElements; m_capacity = sizeInElements; } // we could enable this assignment, but need to make sure to avoid accidental deep copies // b3OpenCLArray& operator=(const b3AlignedObjectArray& src) // { // copyFromArray(src); // return *this; // } cl_mem getBufferCL() const { return m_clBuffer; } virtual ~b3OpenCLArray() { deallocate(); m_size=0; m_capacity=0; } B3_FORCE_INLINE bool push_back(const T& _Val,bool waitForCompletion=true) { bool result = true; size_t sz = size(); if( sz == capacity() ) { result = reserve( allocSize(size()) ); } copyFromHostPointer(&_Val, 1, sz, waitForCompletion); m_size++; return result; } B3_FORCE_INLINE T forcedAt(size_t n) const { b3Assert(n>=0); b3Assert(n=0); b3Assert(n size()) { result = reserve(newsize,copyOldContents); } //leave new data uninitialized (init in debug mode?) //for (size_t i=curSize;i0); b3Assert(numElements<=m_size); size_t srcOffsetBytes = sizeof(T)*firstElem; size_t dstOffsetInBytes = sizeof(T)*dstOffsetInElems; status = clEnqueueCopyBuffer( m_commandQueue, m_clBuffer, destination, srcOffsetBytes, dstOffsetInBytes, sizeof(T)*numElements, 0, 0, 0 ); b3Assert( status == CL_SUCCESS ); } void copyFromHost(const b3AlignedObjectArray& srcArray, bool waitForCompletion=true) { size_t newSize = srcArray.size(); bool copyOldContents = false; resize (newSize,copyOldContents); if (newSize) copyFromHostPointer(&srcArray[0],newSize,0,waitForCompletion); } void copyFromHostPointer(const T* src, size_t numElems, size_t destFirstElem= 0, bool waitForCompletion=true) { b3Assert(numElems+destFirstElem <= capacity()); if (numElems+destFirstElem) { cl_int status = 0; size_t sizeInBytes=sizeof(T)*numElems; status = clEnqueueWriteBuffer( m_commandQueue, m_clBuffer, 0, sizeof(T)*destFirstElem, sizeInBytes, src, 0,0,0 ); b3Assert(status == CL_SUCCESS ); if (waitForCompletion) clFinish(m_commandQueue); } else { b3Error("copyFromHostPointer invalid range\n"); } } void copyToHost(b3AlignedObjectArray& destArray, bool waitForCompletion=true) const { destArray.resize(this->size()); if (size()) copyToHostPointer(&destArray[0], size(),0,waitForCompletion); } void copyToHostPointer(T* destPtr, size_t numElem, size_t srcFirstElem=0, bool waitForCompletion=true) const { b3Assert(numElem+srcFirstElem <= capacity()); if(numElem+srcFirstElem <= capacity()) { cl_int status = 0; status = clEnqueueReadBuffer( m_commandQueue, m_clBuffer, 0, sizeof(T)*srcFirstElem, sizeof(T)*numElem, destPtr, 0,0,0 ); b3Assert( status==CL_SUCCESS ); if (waitForCompletion) clFinish(m_commandQueue); } else { b3Error("copyToHostPointer invalid range\n"); } } void copyFromOpenCLArray(const b3OpenCLArray& src) { size_t newSize = src.size(); resize(newSize); if (size()) { src.copyToCL(m_clBuffer,size()); } } }; #endif //B3_OPENCL_ARRAY_H