1 #ifndef B3_OPENCL_ARRAY_H
2 #define B3_OPENCL_ARRAY_H
4 #include "Bullet3Common/b3AlignedObjectArray.h"
5 #include "Bullet3OpenCL/Initialize/b3OpenCLInclude.h"
14 cl_context m_clContext;
15 cl_command_queue m_commandQueue;
19 bool m_allowGrowingCapacity;
23 if (m_clBuffer && m_ownsMemory)
25 clReleaseMemObject(m_clBuffer);
31 b3OpenCLArray<T>& operator=(const b3OpenCLArray<T>& src);
33 B3_FORCE_INLINE size_t allocSize(size_t size)
35 return (size ? size * 2 : 1);
39 b3OpenCLArray(cl_context ctx, cl_command_queue queue, size_t initialCapacity = 0, bool allowGrowingCapacity = true)
40 : m_size(0), m_capacity(0), m_clBuffer(0), m_clContext(ctx), m_commandQueue(queue), m_ownsMemory(true), m_allowGrowingCapacity(true)
44 reserve(initialCapacity);
46 m_allowGrowingCapacity = allowGrowingCapacity;
49 ///this is an error-prone method with no error checking, be careful!
50 void setFromOpenCLBuffer(cl_mem buffer, size_t sizeInElements)
54 m_allowGrowingCapacity = false;
56 m_size = sizeInElements;
57 m_capacity = sizeInElements;
60 // we could enable this assignment, but need to make sure to avoid accidental deep copies
61 // b3OpenCLArray<T>& operator=(const b3AlignedObjectArray<T>& src)
63 // copyFromArray(src);
67 cl_mem getBufferCL() const
72 virtual ~b3OpenCLArray()
79 B3_FORCE_INLINE bool push_back(const T& _Val, bool waitForCompletion = true)
85 result = reserve(allocSize(size()));
87 copyFromHostPointer(&_Val, 1, sz, waitForCompletion);
92 B3_FORCE_INLINE T forcedAt(size_t n) const
95 b3Assert(n < capacity());
97 copyToHostPointer(&elem, 1, n, true);
101 B3_FORCE_INLINE T at(size_t n) const
104 b3Assert(n < size());
106 copyToHostPointer(&elem, 1, n, true);
110 B3_FORCE_INLINE bool resize(size_t newsize, bool copyOldContents = true)
113 size_t curSize = size();
115 if (newsize < curSize)
117 //leave the OpenCL memory for now
121 if (newsize > size())
123 result = reserve(newsize, copyOldContents);
126 //leave new data uninitialized (init in debug mode?)
127 //for (size_t i=curSize;i<newsize;i++) ...
141 B3_FORCE_INLINE size_t size() const
146 B3_FORCE_INLINE size_t capacity() const
151 B3_FORCE_INLINE bool reserve(size_t _Count, bool copyOldContents = true)
154 // determine new minimum length of allocated storage
155 if (capacity() < _Count)
156 { // not enough room, reallocate
158 if (m_allowGrowingCapacity)
161 //create a new OpenCL buffer
162 size_t memSizeInBytes = sizeof(T) * _Count;
163 cl_mem buf = clCreateBuffer(m_clContext, CL_MEM_READ_WRITE, memSizeInBytes, NULL, &ciErrNum);
164 if (ciErrNum != CL_SUCCESS)
166 b3Error("OpenCL out-of-memory\n");
170 //#define B3_ALWAYS_INITIALIZE_OPENCL_BUFFERS
171 #ifdef B3_ALWAYS_INITIALIZE_OPENCL_BUFFERS
172 unsigned char* src = (unsigned char*)malloc(memSizeInBytes);
173 for (size_t i = 0; i < memSizeInBytes; i++)
175 ciErrNum = clEnqueueWriteBuffer(m_commandQueue, buf, CL_TRUE, 0, memSizeInBytes, src, 0, 0, 0);
176 b3Assert(ciErrNum == CL_SUCCESS);
177 clFinish(m_commandQueue);
179 #endif //B3_ALWAYS_INITIALIZE_OPENCL_BUFFERS
184 copyToCL(buf, size());
187 //deallocate the old buffer
205 void copyToCL(cl_mem destination, size_t numElements, size_t firstElem = 0, size_t dstOffsetInElems = 0) const
207 if (numElements <= 0)
210 b3Assert(m_clBuffer);
211 b3Assert(destination);
213 //likely some error, destination is same as source
214 b3Assert(m_clBuffer != destination);
216 b3Assert((firstElem + numElements) <= m_size);
220 b3Assert(numElements > 0);
221 b3Assert(numElements <= m_size);
223 size_t srcOffsetBytes = sizeof(T) * firstElem;
224 size_t dstOffsetInBytes = sizeof(T) * dstOffsetInElems;
226 status = clEnqueueCopyBuffer(m_commandQueue, m_clBuffer, destination,
227 srcOffsetBytes, dstOffsetInBytes, sizeof(T) * numElements, 0, 0, 0);
229 b3Assert(status == CL_SUCCESS);
232 void copyFromHost(const b3AlignedObjectArray<T>& srcArray, bool waitForCompletion = true)
234 size_t newSize = srcArray.size();
236 bool copyOldContents = false;
237 resize(newSize, copyOldContents);
239 copyFromHostPointer(&srcArray[0], newSize, 0, waitForCompletion);
242 void copyFromHostPointer(const T* src, size_t numElems, size_t destFirstElem = 0, bool waitForCompletion = true)
244 b3Assert(numElems + destFirstElem <= capacity());
246 if (numElems + destFirstElem)
249 size_t sizeInBytes = sizeof(T) * numElems;
250 status = clEnqueueWriteBuffer(m_commandQueue, m_clBuffer, 0, sizeof(T) * destFirstElem, sizeInBytes,
252 b3Assert(status == CL_SUCCESS);
253 if (waitForCompletion)
254 clFinish(m_commandQueue);
258 b3Error("copyFromHostPointer invalid range\n");
262 void copyToHost(b3AlignedObjectArray<T>& destArray, bool waitForCompletion = true) const
264 destArray.resize(this->size());
266 copyToHostPointer(&destArray[0], size(), 0, waitForCompletion);
269 void copyToHostPointer(T* destPtr, size_t numElem, size_t srcFirstElem = 0, bool waitForCompletion = true) const
271 b3Assert(numElem + srcFirstElem <= capacity());
273 if (numElem + srcFirstElem <= capacity())
276 status = clEnqueueReadBuffer(m_commandQueue, m_clBuffer, 0, sizeof(T) * srcFirstElem, sizeof(T) * numElem,
278 b3Assert(status == CL_SUCCESS);
280 if (waitForCompletion)
281 clFinish(m_commandQueue);
285 b3Error("copyToHostPointer invalid range\n");
289 void copyFromOpenCLArray(const b3OpenCLArray& src)
291 size_t newSize = src.size();
295 src.copyToCL(m_clBuffer, size());
300 #endif //B3_OPENCL_ARRAY_H