001/* 002 * JavaCL - Java API and utilities for OpenCL 003 * http://javacl.googlecode.com/ 004 * 005 * Copyright (c) 2009-2013, Olivier Chafik (http://ochafik.com/) 006 * All rights reserved. 007 * 008 * Redistribution and use in source and binary forms, with or without 009 * modification, are permitted provided that the following conditions are met: 010 * 011 * * Redistributions of source code must retain the above copyright 012 * notice, this list of conditions and the following disclaimer. 013 * * Redistributions in binary form must reproduce the above copyright 014 * notice, this list of conditions and the following disclaimer in the 015 * documentation and/or other materials provided with the distribution. 016 * * Neither the name of Olivier Chafik nor the 017 * names of its contributors may be used to endorse or promote products 018 * derived from this software without specific prior written permission. 019 * 020 * THIS SOFTWARE IS PROVIDED BY OLIVIER CHAFIK AND CONTRIBUTORS ``AS IS'' AND ANY 021 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 022 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 023 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY 024 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 025 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 026 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 027 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 028 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 029 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 030 */ 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052package com.nativelibs4java.opencl; 053import com.nativelibs4java.util.Pair; 054import static com.nativelibs4java.opencl.CLException.error; 055import static com.nativelibs4java.opencl.JavaCL.*; 056import static com.nativelibs4java.opencl.library.OpenCLLibrary.*; 057import static com.nativelibs4java.opencl.library.IOpenCLLibrary.*; 058import static com.nativelibs4java.util.NIOUtils.directBytes; 059import static com.nativelibs4java.util.NIOUtils.directCopy; 060 061import java.nio.ByteBuffer; 062 063import com.nativelibs4java.opencl.library.cl_buffer_region; 064import com.nativelibs4java.opencl.library.IOpenCLLibrary.cl_event; 065import com.nativelibs4java.opencl.library.IOpenCLLibrary.cl_mem; 066import org.bridj.*; 067import java.nio.ByteOrder; 068import java.nio.Buffer; 069import com.nativelibs4java.util.NIOUtils; 070import org.bridj.util.Utils; 071import static org.bridj.Pointer.*; 072import static com.nativelibs4java.opencl.proxy.PointerUtils.*; 073 074 075/** 076 * OpenCL Memory Buffer Object.<br> 077 * A buffer object stores a one-dimensional collection of elements.<br> 078 * Elements of a buffer object can be a scalar data type (such as an int, float), vector data type, or a user-defined structure.<br> 079 * @see CLContext 080 * @author Olivier Chafik 081 */ 082public class CLBuffer<T> extends CLMem { 083 final Object owner; 084 final PointerIO<T> io; 085 086 CLBuffer(CLContext context, long byteCount, long entityPeer, Object owner, PointerIO<T> io) { 087 super(context, byteCount, entityPeer); 088 this.owner = owner; 089 this.io = io; 090 } 091 092 public Class<T> getElementClass() { 093 return Utils.getClass(io.getTargetType()); 094 } 095 public int getElementSize() { 096 return (int)io.getTargetSize(); 097 } 098 public long getElementCount() { 099 return getByteCount() / getElementSize(); 100 } 101 /** 102 * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clEnqueueMapBuffer.html">clEnqueueMapBuffer</a>.<br> 103 * @param queue Execution queue for this operation. 104 * @param flags Map flags. 105 * @param eventsToWaitFor Events that need to complete before this particular command can be executed. Special value {@link CLEvent#FIRE_AND_FORGET} can be used to avoid returning a CLEvent. 106 * @return Event object that identifies this command and can be used to query or queue a wait for the command to complete, or null if eventsToWaitFor contains {@link CLEvent#FIRE_AND_FORGET}. 107 */ 108 public Pointer<T> map(CLQueue queue, MapFlags flags, CLEvent... eventsToWaitFor) throws CLException.MapFailure { 109 return map(queue, flags, 0, getElementCount(), true, eventsToWaitFor).getFirst(); 110 } 111 /** 112 * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clEnqueueMapBuffer.html">clEnqueueMapBuffer</a>.<br> 113 * @param queue Execution queue for this operation. 114 * @param flags Map flags. 115 * @param offset offset in the {@link CLBuffer} 116 * @param length length to write (in bytes) 117 * @param eventsToWaitFor Events that need to complete before this particular command can be executed. Special value {@link CLEvent#FIRE_AND_FORGET} can be used to avoid returning a CLEvent. 118 * @return Event object that identifies this command and can be used to query or queue a wait for the command to complete, or null if eventsToWaitFor contains {@link CLEvent#FIRE_AND_FORGET}. 119 */ 120 public Pointer<T> map(CLQueue queue, MapFlags flags, long offset, long length, CLEvent... eventsToWaitFor) throws CLException.MapFailure { 121 return map(queue, flags, offset, length, true, eventsToWaitFor).getFirst(); 122 } 123 124 /** 125 * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clEnqueueMapBuffer.html">clEnqueueMapBuffer</a>.<br> 126 * @param queue Execution queue for this operation. 127 * @param flags Map flags. 128 * @param eventsToWaitFor Events that need to complete before this particular command can be executed. Special value {@link CLEvent#FIRE_AND_FORGET} can be used to avoid returning a CLEvent. 129 * @return Event object that identifies this command and can be used to query or queue a wait for the command to complete, or null if eventsToWaitFor contains {@link CLEvent#FIRE_AND_FORGET}. 130 */ 131 public Pair<Pointer<T>, CLEvent> mapLater(CLQueue queue, MapFlags flags, CLEvent... eventsToWaitFor) throws CLException.MapFailure { 132 return map(queue, flags, 0, getElementCount(), false, eventsToWaitFor); 133 } 134 /** 135 * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clEnqueueMapBuffer.html">clEnqueueMapBuffer</a>.<br> 136 * @param queue Execution queue for this operation. 137 * @param flags Map flags. 138 * @param offset offset in the {@link CLBuffer} 139 * @param length length to write (in bytes) 140 * @param eventsToWaitFor Events that need to complete before this particular command can be executed. Special value {@link CLEvent#FIRE_AND_FORGET} can be used to avoid returning a CLEvent. 141 * @return Event object that identifies this command and can be used to query or queue a wait for the command to complete, or null if eventsToWaitFor contains {@link CLEvent#FIRE_AND_FORGET}. 142 */ 143 public Pair<Pointer<T>, CLEvent> mapLater(CLQueue queue, MapFlags flags, long offset, long length, CLEvent... eventsToWaitFor) throws CLException.MapFailure { 144 return map(queue, flags, offset, length, false, eventsToWaitFor); 145 } 146 147 /** 148 * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clEnqueueFillBuffer.html">clEnqueueFillBuffer</a>.<br> 149 * @param queue Execution queue for this operation. 150 * @param pattern Data pattern to fill the buffer with. 151 * @param eventsToWaitFor Events that need to complete before this particular command can be executed. Special value {@link CLEvent#FIRE_AND_FORGET} can be used to avoid returning a CLEvent. 152 * @return Event object that identifies this command and can be used to query or queue a wait for the command to complete, or null if eventsToWaitFor contains {@link CLEvent#FIRE_AND_FORGET}. 153 */ 154 public CLEvent fillBuffer(CLQueue queue, Pointer<T> pattern, CLEvent... eventsToWaitFor) { 155 return fillBuffer(queue, pattern, pattern.getValidElements(), 0, getElementCount(), eventsToWaitFor); 156 } 157 158 /** 159 * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clEnqueueFillBuffer.html">clEnqueueFillBuffer</a>.<br> 160 * @param pattern Data pattern to fill the buffer with. 161 * @param patternLength Length in elements (not in bytes) of the pattern to use. 162 * @param offset Offset in elements where to start filling the pattern. 163 * @param length Length in elements of the fill (must be a multiple of patternLength). 164 * @param eventsToWaitFor Events that need to complete before this particular command can be executed. Special value {@link CLEvent#FIRE_AND_FORGET} can be used to avoid returning a CLEvent. 165 * @return Event object that identifies this command and can be used to query or queue a wait for the command to complete, or null if eventsToWaitFor contains {@link CLEvent#FIRE_AND_FORGET}. 166 */ 167 public CLEvent fillBuffer(CLQueue queue, Pointer<T> pattern, long patternLength, long offset, long length, CLEvent... eventsToWaitFor) { 168 context.getPlatform().requireMinVersionValue("clEnqueueFillBuffer", 1.2); 169 checkBounds(offset, length); 170 check(pattern != null, "Null pattern!"); 171 long validPatternElements = pattern.getValidElements(); 172 check(validPatternElements < 0 || patternLength <= validPatternElements, 173 "Pattern length exceeds the valid pattern elements count (%d > %d)", 174 patternLength, validPatternElements); 175 check(length % patternLength == 0, "Fill length must be a multiple of pattern length"); 176 177 ReusablePointers ptrs = ReusablePointers.get(); 178 int[] eventsInCount = ptrs.int1Array; 179 Pointer<cl_event> eventsIn = 180 CLAbstractEntity.copyNonNullEntities(eventsToWaitFor, eventsInCount, ptrs.events_in); 181 Pointer<cl_event> eventOut = 182 eventsToWaitFor == null || CLEvent.containsFireAndForget(eventsToWaitFor) 183 ? null 184 : ptrs.event_out; 185 error(CL.clEnqueueFillBuffer( 186 queue.getEntity(), 187 getEntity(), 188 getPeer(pattern), 189 patternLength * getElementSize(), 190 offset * getElementSize(), 191 length * getElementSize(), 192 eventsInCount[0], getPeer(eventsIn) , getPeer(eventOut) )); 193 return CLEvent.createEventFromPointer(queue, eventOut) ; } 194 195 /** 196 * Returns a pointer to native memory large enough for this buffer's data, and with a compatible byte ordering. 197 */ 198 public Pointer<T> allocateCompatibleMemory(CLDevice device) { 199 return allocateArray(io, getElementCount()).order(device.getKernelsDefaultByteOrder()); 200 } 201 202 public PointerIO<T> getIO() { 203 return io; 204 } 205 206 /** 207 * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clEnqueueReadBuffer.html">clEnqueueReadBuffer</a>.<br> 208 */ 209 public Pointer<T> read(CLQueue queue, CLEvent... eventsToWaitFor) { 210 Pointer<T> out = allocateCompatibleMemory(queue.getDevice()); 211 read(queue, out, true, eventsToWaitFor); 212 return out; 213 } 214 /** 215 * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clEnqueueReadBuffer.html">clEnqueueReadBuffer</a>.<br> 216 */ 217 public Pointer<T> read(CLQueue queue, long offset, long length, CLEvent... eventsToWaitFor) { 218 Pointer<T> out = allocateCompatibleMemory(queue.getDevice()); 219 read(queue, offset, length, out, true, eventsToWaitFor); 220 return out; 221 } 222 223 protected void checkBounds(long offset, long length) { 224 if (offset + length * getElementSize() > getByteCount()) 225 throw new IndexOutOfBoundsException("Trying to map a region of memory object outside allocated range"); 226 } 227 228 /** 229 * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateSubBuffer.html">clCreateSubBuffer</a>.<br> 230 * Can be used to create a new buffer object (referred to as a sub-buffer object) from an existing buffer object. 231 * @param usage is used to specify allocation and usage information about the image memory object being created and is described in table 5.3 of the OpenCL spec. 232 * @param offset 233 * @param length length in bytes 234 * @since OpenCL 1.1 235 * @return sub-buffer that is a "window" of this buffer starting at the provided offset, with the provided length 236 */ 237 public CLBuffer<T> createSubBuffer(Usage usage, long offset, long length) { 238 context.getPlatform().requireMinVersionValue("clCreateSubBuffer", 1.1); 239 int s = getElementSize(); 240 cl_buffer_region region = new cl_buffer_region().origin(s * offset).size(s * length); 241 ReusablePointers ptrs = ReusablePointers.get(); 242 Pointer<Integer> pErr = ptrs.pErr; 243 long mem = CL.clCreateSubBuffer(getEntity(), usage.getIntFlags(), CL_BUFFER_CREATE_TYPE_REGION, getPeer(getPointer(region)), getPeer(pErr)); 244 error(pErr.getInt()); 245 return mem == 0 ? null : new CLBuffer<T>(context, length * s, mem, null, io); 246 } 247 248 /** 249 * enqueues a command to copy a buffer object identified by src_buffer to another buffer object identified by destination. 250 * @param destination destination buffer object 251 * @param eventsToWaitFor Events that need to complete before this particular command can be executed. Special value {@link CLEvent#FIRE_AND_FORGET} can be used to avoid returning a CLEvent. 252 * @return Event object that identifies this command and can be used to query or queue a wait for the command to complete, or null if eventsToWaitFor contains {@link CLEvent#FIRE_AND_FORGET}. 253 */ 254 public CLEvent copyTo(CLQueue queue, CLMem destination, CLEvent... eventsToWaitFor) { 255 return copyTo(queue, 0, getElementCount(), destination, 0, eventsToWaitFor); 256 } 257 258 /** 259 * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clEnqueueCopyBuffer.html">clEnqueueCopyBuffer</a>.<br> 260 * enqueues a command to copy a buffer object identified by src_buffer to another buffer object identified by destination. 261 * @param queue Execution queue for this operation. 262 * @param srcOffset 263 * @param length length in bytes 264 * @param destination destination buffer object 265 * @param destOffset 266 * @param eventsToWaitFor Events that need to complete before this particular command can be executed. Special value {@link CLEvent#FIRE_AND_FORGET} can be used to avoid returning a CLEvent. 267 * @return Event object that identifies this command and can be used to query or queue a wait for the command to complete, or null if eventsToWaitFor contains {@link CLEvent#FIRE_AND_FORGET}. 268 */ 269 public CLEvent copyTo(CLQueue queue, long srcOffset, long length, CLMem destination, long destOffset, CLEvent... eventsToWaitFor) { 270 long 271 byteCount = getByteCount(), 272 destByteCount = destination.getByteCount(), 273 eltSize = getElementSize(), 274 actualSrcOffset = srcOffset * eltSize, 275 actualDestOffset = destOffset * eltSize, 276 actualLength = length * eltSize; 277 278 if ( actualSrcOffset < 0 || 279 actualSrcOffset >= byteCount || 280 actualSrcOffset + actualLength > byteCount || 281 actualDestOffset < 0 || 282 actualDestOffset >= destByteCount || 283 actualDestOffset + actualLength > destByteCount 284 ) 285 throw new IndexOutOfBoundsException("Invalid copy parameters : srcOffset = " + srcOffset + ", destOffset = " + destOffset + ", length = " + length + " (element size = " + eltSize + ", source byte count = " + byteCount + ", destination byte count = " + destByteCount + ")"); 286 287 ReusablePointers ptrs = ReusablePointers.get(); 288 int[] eventsInCount = ptrs.int1Array; 289 Pointer<cl_event> eventsIn = 290 CLAbstractEntity.copyNonNullEntities(eventsToWaitFor, eventsInCount, ptrs.events_in); 291 Pointer<cl_event> eventOut = 292 eventsToWaitFor == null || CLEvent.containsFireAndForget(eventsToWaitFor) 293 ? null 294 : ptrs.event_out; 295 error(CL.clEnqueueCopyBuffer( 296 queue.getEntity(), 297 getEntity(), 298 destination.getEntity(), 299 actualSrcOffset, 300 actualDestOffset, 301 actualLength, 302 eventsInCount[0], getPeer(eventsIn) , getPeer(eventOut) )); 303 return CLEvent.createEventFromPointer(queue, eventOut) ; } 304 305 /** 306 * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clEnqueueMapBuffer.html">clEnqueueMapBuffer</a>.<br> 307 */ 308 protected Pair<Pointer<T>, CLEvent> map(CLQueue queue, MapFlags flags, long offset, long length, boolean blocking, CLEvent... eventsToWaitFor) { 309 if (flags == MapFlags.WriteInvalidateRegion) { 310 context.getPlatform().requireMinVersionValue("CL_MAP_WRITE_INVALIDATE_REGION", 1.2); 311 } 312 checkBounds(offset, length); 313 ReusablePointers ptrs = ReusablePointers.get(); 314 int[] eventsInCount = ptrs.int1Array; 315 Pointer<cl_event> eventsIn = 316 CLAbstractEntity.copyNonNullEntities(eventsToWaitFor, eventsInCount, ptrs.events_in); 317 Pointer<cl_event> eventOut = 318 blocking || eventsToWaitFor == null || CLEvent.containsFireAndForget(eventsToWaitFor) 319 ? null 320 : ptrs.event_out; 321 Pointer<Integer> pErr = ptrs.pErr; 322 long mappedPeer = CL.clEnqueueMapBuffer( 323 queue.getEntity(), 324 getEntity(), 325 blocking ? CL_TRUE : CL_FALSE, 326 flags.value(), 327 offset * getElementSize(), 328 length * getElementSize(), 329 eventsInCount[0], getPeer(eventsIn) , getPeer(eventOut) , 330 getPeer(pErr) 331 ); 332 error(pErr.getInt()); 333 if (mappedPeer == 0) 334 return null; 335 return new Pair<Pointer<T>, CLEvent>( 336 pointerToAddress(mappedPeer, io).validElements(length).order(queue.getDevice().getKernelsDefaultByteOrder()), 337 CLEvent.createEventFromPointer(queue, eventOut) ); 338 } 339 340 /** 341 * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clEnqueueUnmapMemObject.html">clEnqueueUnmapMemObject</a>.<br> 342 * @param queue Execution queue for this operation. 343 * @param buffer 344 * @param eventsToWaitFor Events that need to complete before this particular command can be executed. Special value {@link CLEvent#FIRE_AND_FORGET} can be used to avoid returning a CLEvent. 345 * @return Event object that identifies this command and can be used to query or queue a wait for the command to complete, or null if eventsToWaitFor contains {@link CLEvent#FIRE_AND_FORGET}. 346 */ 347 public CLEvent unmap(CLQueue queue, Pointer<T> buffer, CLEvent... eventsToWaitFor) { 348 ReusablePointers ptrs = ReusablePointers.get(); 349 int[] eventsInCount = ptrs.int1Array; 350 Pointer<cl_event> eventsIn = 351 CLAbstractEntity.copyNonNullEntities(eventsToWaitFor, eventsInCount, ptrs.events_in); 352 Pointer<cl_event> eventOut = 353 eventsToWaitFor == null || CLEvent.containsFireAndForget(eventsToWaitFor) 354 ? null 355 : ptrs.event_out; 356; 357 error(CL.clEnqueueUnmapMemObject(queue.getEntity(), getEntity(), getPeer(buffer), eventsInCount[0], getPeer(eventsIn) , getPeer(eventOut) )); 358 return CLEvent.createEventFromPointer(queue, eventOut) ; } 359 360 /** 361 * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clEnqueueReadBuffer.html">clEnqueueReadBuffer</a>.<br> 362 * @deprecated use {@link CLBuffer#read(CLQueue, Pointer, boolean, CLEvent[])} instead 363 * @param queue Execution queue for this operation. 364 * @param out output buffer 365 * @param blocking whether the operation should be blocking (and return null), or non-blocking (and return a completion event) 366 * @param eventsToWaitFor Events that need to complete before this particular command can be executed. Special value {@link CLEvent#FIRE_AND_FORGET} can be used to avoid returning a CLEvent. 367 * @return Event object that identifies this command and can be used to query or queue a wait for the command to complete, or null if eventsToWaitFor contains {@link CLEvent#FIRE_AND_FORGET}. 368 */ 369 @Deprecated 370 public CLEvent read(CLQueue queue, Buffer out, boolean blocking, CLEvent... eventsToWaitFor) { 371 return read(queue, 0, -1, out, blocking, eventsToWaitFor); 372 } 373 374 /** 375 * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clEnqueueReadBuffer.html">clEnqueueReadBuffer</a>.<br> 376 * @param queue Execution queue for this operation. 377 * @param out output buffer 378 * @param blocking whether the operation should be blocking (and return null), or non-blocking (and return a completion event) 379 * @param eventsToWaitFor Events that need to complete before this particular command can be executed. Special value {@link CLEvent#FIRE_AND_FORGET} can be used to avoid returning a CLEvent. 380 * @return Event object that identifies this command and can be used to query or queue a wait for the command to complete, or null if eventsToWaitFor contains {@link CLEvent#FIRE_AND_FORGET}. 381 */ 382 public CLEvent read(CLQueue queue, Pointer<T> out, boolean blocking, CLEvent... eventsToWaitFor) { 383 return read(queue, 0, -1, out, blocking, eventsToWaitFor); 384 } 385 386 /** 387 * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clEnqueueReadBuffer.html">clEnqueueReadBuffer</a>.<br> 388 * @deprecated use {@link CLBuffer#read(CLQueue, long, long, Pointer, boolean, CLEvent[])} instead 389 * @param queue Execution queue for this operation. 390 * @param offset offset in the {@link CLBuffer} 391 * @param length length to write (in bytes) 392 * @param out output buffer 393 * @param blocking whether the operation should be blocking (and return null), or non-blocking (and return a completion event) 394 * @param eventsToWaitFor Events that need to complete before this particular command can be executed. Special value {@link CLEvent#FIRE_AND_FORGET} can be used to avoid returning a CLEvent. 395 * @return Event object that identifies this command and can be used to query or queue a wait for the command to complete, or null if eventsToWaitFor contains {@link CLEvent#FIRE_AND_FORGET}. 396 */ 397 @Deprecated 398 public CLEvent read(CLQueue queue, long offset, long length, Buffer out, boolean blocking, CLEvent... eventsToWaitFor) { 399 if (out == null) 400 throw new IllegalArgumentException("Null output buffer !"); 401 402 if (out.isReadOnly()) 403 throw new IllegalArgumentException("Output buffer for read operation is read-only !"); 404 boolean indirect = !out.isDirect(); 405 Pointer<T> ptr = null; 406 if (indirect) { 407 ptr = allocateArray(io, length).order(queue.getDevice().getKernelsDefaultByteOrder()); 408 blocking = true; 409 } else { 410 ptr = (Pointer)pointerToBuffer(out); 411 } 412 CLEvent ret = read(queue, offset, length, ptr, blocking, eventsToWaitFor); 413 if (indirect) 414 NIOUtils.put(ptr.getBuffer(), out); 415 416 return ret; 417 } 418 419 /** 420 * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clEnqueueReadBuffer.html">clEnqueueReadBuffer</a>.<br> 421 * @param queue Execution queue for this operation. 422 * @param offset offset in the {@link CLBuffer} 423 * @param length length to write (in bytes) 424 * @param out output buffer 425 * @param blocking whether the operation should be blocking (and return null), or non-blocking (and return a completion event) 426 * @param eventsToWaitFor Events that need to complete before this particular command can be executed. Special value {@link CLEvent#FIRE_AND_FORGET} can be used to avoid returning a CLEvent. 427 * @return Event object that identifies this command and can be used to query or queue a wait for the command to complete, or null if eventsToWaitFor contains {@link CLEvent#FIRE_AND_FORGET}. 428 */ 429 public CLEvent read(CLQueue queue, long offset, long length, Pointer<T> out, boolean blocking, CLEvent... eventsToWaitFor) { 430 if (out == null) 431 throw new IllegalArgumentException("Null output pointer !"); 432 433 if (length < 0) { 434 if (isGL) { 435 length = out.getValidElements(); 436 } 437 if (length < 0) { 438 length = getElementCount(); 439 long s = out.getValidElements(); 440 if (length > s && s >= 0) 441 length = s; 442 } 443 } 444 445 ReusablePointers ptrs = ReusablePointers.get(); 446 int[] eventsInCount = ptrs.int1Array; 447 Pointer<cl_event> eventsIn = 448 CLAbstractEntity.copyNonNullEntities(eventsToWaitFor, eventsInCount, ptrs.events_in); 449 Pointer<cl_event> eventOut = 450 blocking || eventsToWaitFor == null || CLEvent.containsFireAndForget(eventsToWaitFor) 451 ? null 452 : ptrs.event_out; 453 error(CL.clEnqueueReadBuffer( 454 queue.getEntity(), 455 getEntity(), 456 blocking ? CL_TRUE : 0, 457 offset * getElementSize(), 458 length * getElementSize(), 459 getPeer(out), 460 eventsInCount[0], getPeer(eventsIn) , getPeer(eventOut) )); 461 return CLEvent.createEventFromPointer(queue, eventOut) ; } 462 463 /** 464 * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clEnqueueWriteBuffer.html">clEnqueueWriteBuffer</a>.<br> 465 * @deprecated use {@link CLBuffer#write(CLQueue, Pointer, boolean, CLEvent[])} instead 466 * @param queue Execution queue for this operation. 467 * @param in input buffer 468 * @param blocking whether the operation should be blocking (and return null), or non-blocking (and return a completion event) 469 * @param eventsToWaitFor Events that need to complete before this particular command can be executed. Special value {@link CLEvent#FIRE_AND_FORGET} can be used to avoid returning a CLEvent. 470 * @return Event object that identifies this command and can be used to query or queue a wait for the command to complete, or null if eventsToWaitFor contains {@link CLEvent#FIRE_AND_FORGET}. 471 */ 472 @Deprecated 473 public CLEvent write(CLQueue queue, Buffer in, boolean blocking, CLEvent... eventsToWaitFor) { 474 return write(queue, 0, -1, in, blocking, eventsToWaitFor); 475 } 476 477 /** 478 * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clEnqueueWriteBuffer.html">clEnqueueWriteBuffer</a>.<br> 479 * @param queue Execution queue for this operation. 480 * @param in input buffer 481 * @param blocking whether the operation should be blocking (and return null), or non-blocking (and return a completion event) 482 * @param eventsToWaitFor Events that need to complete before this particular command can be executed. Special value {@link CLEvent#FIRE_AND_FORGET} can be used to avoid returning a CLEvent. 483 * @return Event object that identifies this command and can be used to query or queue a wait for the command to complete, or null if eventsToWaitFor contains {@link CLEvent#FIRE_AND_FORGET}. 484 */ 485 public CLEvent write(CLQueue queue, Pointer<T> in, boolean blocking, CLEvent... eventsToWaitFor) { 486 return write(queue, 0, -1, in, blocking, eventsToWaitFor); 487 } 488 489 /** 490 * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clEnqueueWriteBuffer.html">clEnqueueWriteBuffer</a>.<br> 491 * @deprecated use {@link CLBuffer#write(CLQueue, long, long, Pointer, boolean, CLEvent[])} instead 492 * @param queue Execution queue for this operation. 493 * @param offset offset in the {@link CLBuffer} 494 * @param length length to write (in bytes) 495 * @param in input buffer 496 * @param blocking whether the operation should be blocking (and return null), or non-blocking (and return a completion event) 497 * @param eventsToWaitFor Events that need to complete before this particular command can be executed. Special value {@link CLEvent#FIRE_AND_FORGET} can be used to avoid returning a CLEvent. 498 * @return Event object that identifies this command and can be used to query or queue a wait for the command to complete, or null if eventsToWaitFor contains {@link CLEvent#FIRE_AND_FORGET}. 499 */ 500 @Deprecated 501 public CLEvent write(CLQueue queue, long offset, long length, Buffer in, boolean blocking, CLEvent... eventsToWaitFor) { 502 if (in == null) 503 throw new IllegalArgumentException("Null input buffer !"); 504 505 boolean indirect = !in.isDirect(); 506 Pointer<T> ptr = null; 507 if (indirect) { 508 ptr = allocateArray(io, length).order(queue.getDevice().getKernelsDefaultByteOrder()); 509 ptr.setValues(in); 510 blocking = true; 511 } else { 512 ptr = (Pointer)pointerToBuffer(in); 513 } 514 return write(queue, offset, length, ptr, blocking, eventsToWaitFor); 515 } 516 517 /** 518 * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clEnqueueWriteBuffer.html">clEnqueueWriteBuffer</a>.<br> 519 * @param queue Execution queue for this operation. 520 * @param offset offset in the {@link CLBuffer} 521 * @param length length to write (in bytes) 522 * @param in input buffer 523 * @param blocking whether the operation should be blocking (and return null), or non-blocking (and return a completion event) 524 * @param eventsToWaitFor Events that need to complete before this particular command can be executed. Special value {@link CLEvent#FIRE_AND_FORGET} can be used to avoid returning a CLEvent. 525 * @return Event object that identifies this command and can be used to query or queue a wait for the command to complete, or null if eventsToWaitFor contains {@link CLEvent#FIRE_AND_FORGET}. 526 */ 527 public CLEvent write(CLQueue queue, long offset, long length, Pointer<T> in, boolean blocking, CLEvent... eventsToWaitFor) { 528 if (length == 0) 529 return null; 530 531 if (in == null) 532 throw new IllegalArgumentException("Null input pointer !"); 533 534 if (length < 0) { 535 if (isGL) 536 length = in.getValidElements(); 537 if (length < 0) { 538 length = getElementCount(); 539 long s = in.getValidElements(); 540 if (length > s && s >= 0) 541 length = s; 542 } 543 } 544 545 ReusablePointers ptrs = ReusablePointers.get(); 546 int[] eventsInCount = ptrs.int1Array; 547 Pointer<cl_event> eventsIn = 548 CLAbstractEntity.copyNonNullEntities(eventsToWaitFor, eventsInCount, ptrs.events_in); 549 Pointer<cl_event> eventOut = 550 blocking || eventsToWaitFor == null || CLEvent.containsFireAndForget(eventsToWaitFor) 551 ? null 552 : ptrs.event_out; 553 error(CL.clEnqueueWriteBuffer( 554 queue.getEntity(), 555 getEntity(), 556 blocking ? CL_TRUE : CL_FALSE, 557 offset * getElementSize(), 558 length * getElementSize(), 559 getPeer(in), 560 eventsInCount[0], getPeer(eventsIn) , getPeer(eventOut) )); 561 return CLEvent.createEventFromPointer(queue, eventOut) ; } 562 563 /** 564 * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clEnqueueWriteBuffer.html">clEnqueueWriteBuffer</a>.<br> 565 * @param queue Execution queue for this operation. 566 * @param offset offset in the {@link CLBuffer} 567 * @param length length to write (in bytes) 568 * @param in input buffer 569 * @param blocking whether the operation should be blocking (and return null), or non-blocking (and return a completion event) 570 * @param eventsToWaitFor Events that need to complete before this particular command can be executed. Special value {@link CLEvent#FIRE_AND_FORGET} can be used to avoid returning a CLEvent. 571 * @return Event object that identifies this command and can be used to query or queue a wait for the command to complete, or null if eventsToWaitFor contains {@link CLEvent#FIRE_AND_FORGET}. 572 */ 573 public CLEvent writeBytes(CLQueue queue, long offset, long length, ByteBuffer in, boolean blocking, CLEvent... eventsToWaitFor) { 574 return writeBytes(queue, offset, length, pointerToBuffer(in), blocking, eventsToWaitFor); 575 } 576 /** 577 * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clEnqueueWriteBuffer.html">clEnqueueWriteBuffer</a>.<br> 578 * @param queue Execution queue for this operation. 579 * @param offset offset in the {@link CLBuffer} 580 * @param length length to write (in bytes) 581 * @param in input buffer 582 * @param blocking whether the operation should be blocking (and return null), or non-blocking (and return a completion event) 583 * @param eventsToWaitFor Events that need to complete before this particular command can be executed. Special value {@link CLEvent#FIRE_AND_FORGET} can be used to avoid returning a CLEvent. 584 * @return Event object that identifies this command and can be used to query or queue a wait for the command to complete, or null if eventsToWaitFor contains {@link CLEvent#FIRE_AND_FORGET}. 585 */ 586 public CLEvent writeBytes(CLQueue queue, long offset, long length, Pointer<?> in, boolean blocking, CLEvent... eventsToWaitFor) { 587 if (in == null) 588 throw new IllegalArgumentException("Null input pointer !"); 589 590 ReusablePointers ptrs = ReusablePointers.get(); 591 int[] eventsInCount = ptrs.int1Array; 592 Pointer<cl_event> eventsIn = 593 CLAbstractEntity.copyNonNullEntities(eventsToWaitFor, eventsInCount, ptrs.events_in); 594 Pointer<cl_event> eventOut = 595 blocking || eventsToWaitFor == null || CLEvent.containsFireAndForget(eventsToWaitFor) 596 ? null 597 : ptrs.event_out; 598 error(CL.clEnqueueWriteBuffer( 599 queue.getEntity(), 600 getEntity(), 601 blocking ? CL_TRUE : 0, 602 offset, 603 length, 604 getPeer(in), 605 eventsInCount[0], getPeer(eventsIn) , getPeer(eventOut) )); 606 return CLEvent.createEventFromPointer(queue, eventOut) ; } 607 608 private <T extends CLMem> T copyGLMark(T mem) { 609 mem.isGL = this.isGL; 610 return mem; 611 } 612 613 public CLBuffer<T> emptyClone(CLMem.Usage usage) { 614 return (CLBuffer)getContext().createBuffer(usage, io, getElementCount()); 615 } 616 617 618 public CLBuffer<Integer> asCLIntBuffer() { 619 return as(Integer.class); 620 } 621 622 623 public CLBuffer<Long> asCLLongBuffer() { 624 return as(Long.class); 625 } 626 627 628 public CLBuffer<Short> asCLShortBuffer() { 629 return as(Short.class); 630 } 631 632 633 public CLBuffer<Byte> asCLByteBuffer() { 634 return as(Byte.class); 635 } 636 637 638 public CLBuffer<Character> asCLCharBuffer() { 639 return as(Character.class); 640 } 641 642 643 public CLBuffer<Float> asCLFloatBuffer() { 644 return as(Float.class); 645 } 646 647 648 public CLBuffer<Double> asCLDoubleBuffer() { 649 return as(Double.class); 650 } 651 652 653 public <T> CLBuffer<T> as(Class<T> newTargetType) { 654 long mem = getEntity(); 655 assert mem != 0; 656 error(CL.clRetainMemObject(mem)); 657 PointerIO<T> newIO = PointerIO.getInstance(newTargetType); 658 return copyGLMark(new CLBuffer<T>(context, getByteCount(), mem, owner, newIO)); 659 } 660 661 /** 662 * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clEnqueueCopyBuffer.html">clEnqueueCopyBuffer</a>.<br> 663 * @param queue Execution queue for this operation. 664 * @param destination destination buffer object 665 * @param eventsToWaitFor Events that need to complete before this particular command can be executed. Special value {@link CLEvent#FIRE_AND_FORGET} can be used to avoid returning a CLEvent. 666 * @return Event object that identifies this command and can be used to query or queue a wait for the command to complete, or null if eventsToWaitFor contains {@link CLEvent#FIRE_AND_FORGET}. 667 */ 668 public CLEvent copyTo(CLQueue queue, CLBuffer destination, CLEvent... eventsToWaitFor) { 669 return copyBytesTo(queue, destination, 0, 0, getByteCount(), eventsToWaitFor); 670 } 671 672 /** 673 * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clEnqueueCopyBuffer.html">clEnqueueCopyBuffer</a>.<br> 674 * @param queue Execution queue for this operation. 675 * @param destination destination buffer object 676 * @param sourceByteOffset byte offset in the source 677 * @param destinationByteOffset byte offset in the destination 678 * @param byteCount number of bytes to copy 679 * @param eventsToWaitFor Events that need to complete before this particular command can be executed. Special value {@link CLEvent#FIRE_AND_FORGET} can be used to avoid returning a CLEvent. 680 * @return Event object that identifies this command and can be used to query or queue a wait for the command to complete, or null if eventsToWaitFor contains {@link CLEvent#FIRE_AND_FORGET}. 681 */ 682 public CLEvent copyBytesTo(CLQueue queue, CLBuffer destination, long sourceByteOffset, long destinationByteOffset, long byteCount, CLEvent... eventsToWaitFor) { 683 ReusablePointers ptrs = ReusablePointers.get(); 684 int[] eventsInCount = ptrs.int1Array; 685 Pointer<cl_event> eventsIn = 686 CLAbstractEntity.copyNonNullEntities(eventsToWaitFor, eventsInCount, ptrs.events_in); 687 Pointer<cl_event> eventOut = 688 eventsToWaitFor == null || CLEvent.containsFireAndForget(eventsToWaitFor) 689 ? null 690 : ptrs.event_out; 691 error(CL.clEnqueueCopyBuffer( 692 queue.getEntity(), 693 getEntity(), 694 destination.getEntity(), 695 sourceByteOffset, 696 destinationByteOffset, 697 byteCount, 698 eventsInCount[0], getPeer(eventsIn) , getPeer(eventOut) )); 699 return CLEvent.createEventFromPointer(queue, eventOut) ; } 700 701 /** 702 * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clEnqueueCopyBuffer.html">clEnqueueCopyBuffer</a>.<br> 703 * @param queue Execution queue for this operation. 704 * @param destination destination buffer object 705 * @param sourceElementOffset element offset in the source 706 * @param destinationElementOffset element offset in the destination 707 * @param elementCount number of elements to copy 708 * @param eventsToWaitFor Events that need to complete before this particular command can be executed. Special value {@link CLEvent#FIRE_AND_FORGET} can be used to avoid returning a CLEvent. 709 * @return Event object that identifies this command and can be used to query or queue a wait for the command to complete, or null if eventsToWaitFor contains {@link CLEvent#FIRE_AND_FORGET}. 710 */ 711 public CLEvent copyElementsTo(CLQueue queue, CLBuffer destination, long sourceElementOffset, long destinationElementOffset, long elementCount, CLEvent... eventsToWaitFor) { 712 return copyBytesTo(queue, destination, 713 sourceElementOffset * getElementSize(), 714 destinationElementOffset * getElementSize(), 715 elementCount * getElementSize(), 716 eventsToWaitFor); 717 } 718 719}