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        
050package com.nativelibs4java.opencl;
051import com.nativelibs4java.util.Pair;
052
053import static com.nativelibs4java.opencl.CLException.error;
054import static com.nativelibs4java.opencl.CLException.failedForLackOfMemory;
055import static com.nativelibs4java.opencl.JavaCL.CL;
056import static com.nativelibs4java.opencl.library.OpenCLLibrary.*;
057import static com.nativelibs4java.opencl.library.IOpenCLLibrary.*;
058import com.nativelibs4java.opencl.library.IOpenCLLibrary.cl_event;
059import static com.nativelibs4java.util.ImageUtils.getImageIntPixels;
060import static com.nativelibs4java.util.NIOUtils.getSizeInBytes;
061
062import java.awt.Image;
063import java.io.IOException;
064import java.nio.Buffer;
065import java.nio.ByteBuffer;
066import java.nio.ByteOrder;
067import java.nio.CharBuffer;
068import java.nio.DoubleBuffer;
069import java.nio.FloatBuffer;
070import java.nio.IntBuffer;
071import java.nio.LongBuffer;
072import java.nio.ShortBuffer;
073import java.util.ArrayList;
074import java.util.concurrent.ConcurrentHashMap;
075import java.util.concurrent.atomic.AtomicReference;
076import java.util.List;
077import java.util.logging.*;
078
079import com.nativelibs4java.opencl.CLDevice.QueueProperties;
080import com.nativelibs4java.opencl.CLSampler.AddressingMode;
081import com.nativelibs4java.opencl.CLSampler.FilterMode;
082import com.nativelibs4java.opencl.ImageIOUtils.ImageInfo;
083import com.nativelibs4java.opencl.library.OpenGLContextUtils;
084import com.nativelibs4java.opencl.library.cl_image_format;
085import com.nativelibs4java.opencl.library.IOpenCLLibrary.cl_context;
086import com.nativelibs4java.opencl.library.IOpenCLLibrary.cl_device_id;
087import com.nativelibs4java.opencl.library.IOpenCLLibrary.cl_mem;
088import com.nativelibs4java.opencl.library.IOpenCLLibrary.cl_sampler;
089import com.nativelibs4java.util.EnumValue;
090import com.nativelibs4java.util.EnumValues;
091import com.nativelibs4java.util.NIOUtils;
092import org.bridj.*;
093import static org.bridj.Pointer.*;
094import static com.nativelibs4java.opencl.proxy.PointerUtils.*;
095import java.io.InputStream;
096import java.util.Arrays;
097import java.util.Map;
098
099
100/**
101 * OpenCL context.<br>
102 * An OpenCL context is created with one or more devices.<br>
103 * Contexts are used by the OpenCL runtime for managing objects such as command-queues, memory, program and kernel objects and for executing kernels on one or more devices specified in the context.
104 * @author Olivier Chafik
105 */
106public class CLContext extends CLAbstractEntity {
107
108
109
110
111
112
113
114
115        private final AtomicReference<ConcurrentHashMap<Object, Object>> propertiesMapRef =
116                new AtomicReference<ConcurrentHashMap<Object, Object>>();
117        
118        public Object getClientProperty(Object key) {
119                ConcurrentHashMap<Object, Object> propertiesMap = propertiesMapRef.get();
120                return propertiesMap == null ? null : propertiesMap.get(key);
121        }
122        public Object putClientProperty(Object key, Object value) {
123                ConcurrentHashMap<Object, Object> propertiesMap = propertiesMapRef.get();
124                if (propertiesMap == null) {
125                        propertiesMap = new ConcurrentHashMap<Object, Object>();
126                        if (!propertiesMapRef.compareAndSet(null, propertiesMap))
127                                propertiesMap = propertiesMapRef.get();
128                }
129                return propertiesMap.put(key, value);
130        }
131        
132        private volatile long maxMemAllocSize = -1;
133        
134        /**
135     * Max size of memory object allocation in bytes. The minimum value is max (1/4th of CL_DEVICE_GLOBAL_MEM_SIZE , 128*1024*1024)
136     */
137    public long getMaxMemAllocSize() {
138        if (maxMemAllocSize < 0) {
139                        long min = Long.MAX_VALUE;
140                        for (CLDevice device : getDevices()) {
141                                long m = device.getMaxMemAllocSize();
142                                if (m < min)
143                                        min = m;
144                        }
145                        maxMemAllocSize = min;
146                }
147        return maxMemAllocSize;
148    }
149    
150    volatile Boolean cacheBinaries;
151        
152        /**
153         * Change whether program binaries are automatically cached or not.<br>
154         * By default it is true, it can be set to false with the "javacl.cacheBinaries" Java property or the "JAVACL_CACHE_BINARIES" environment variable (when set to "0").<br>
155         * Each program can be set to be cached or not using {@link CLProgram#setCached(boolean) }.<br>
156         * Caching of binaries might be disabled by default on some platforms (ATI Stream, for instance).
157         */ 
158        public synchronized void setCacheBinaries(boolean cacheBinaries) {
159                this.cacheBinaries = cacheBinaries;
160        }
161        /**
162         * Says whether program binaries are automatically cached or not.<br>
163         * By default it is true, it can be set to false with the "javacl.cacheBinaries" Java property, the "JAVACL_CACHE_BINARIES" environment variable (when set to "0") or the {@link CLContext#setCacheBinaries(boolean) } method.<br>
164         * Each program can be set to be cached or not using {@link CLProgram#setCached(boolean) }.<br>
165         * Caching of binaries might be disabled by default on some platforms (ATI Stream, for instance).
166         */ 
167        public synchronized boolean getCacheBinaries() {
168                if (cacheBinaries == null) {
169                        String prop = System.getProperty("javacl.cacheBinaries"), env = System.getenv("JAVACL_CACHE_BINARIES");
170                        if ("true".equals(prop) || "1".equals(env))
171                                cacheBinaries = true;
172                        else if ("false".equals(prop) || "0".equals(env))
173                                cacheBinaries = false;
174                        else {
175                                cacheBinaries = !PlatformUtils.PlatformKind.AMDApp.equals(PlatformUtils.guessPlatformKind(getPlatform()));
176                        }
177                        //System.out.println("CACHE BINARIES = " + cacheBinaries);
178                }
179                return cacheBinaries;
180        }
181        
182                protected static CLInfoGetter infos = new CLInfoGetter() {
183                @Override
184                protected int getInfo(long entity, int infoTypeEnum, long size, Pointer out, Pointer<SizeT> sizeOut) {
185                        return CL.clGetContextInfo(entity, infoTypeEnum, size, getPeer(out), getPeer(sizeOut));
186                }
187        };
188        
189        CLPlatform platform;
190        protected Pointer<SizeT> deviceIds;
191
192        CLContext(CLPlatform platform, Pointer<SizeT> deviceIds, long context) {
193                super(context);
194                this.platform = platform;
195                this.deviceIds = deviceIds;
196                
197                if (getByteOrder() == null) {
198                        JavaCL.log(Level.WARNING, "The devices in this context have mismatching byte orders. This mandates the use of __attribute__((endian(host))) in kernel sources or *very* careful use of buffers to avoid facing endianness issues");   
199                }
200        }
201    
202        /**
203         * Creates a user event object. <br>
204         * User events allow applications to enqueue commands that wait on a user event to finish before the command is executed by the device.
205         * @since OpenCL 1.1
206         */
207        public CLUserEvent createUserEvent() {
208                platform.requireMinVersionValue("clCreateUserEvent", 1.1);
209                                ReusablePointers ptrs = ReusablePointers.get();
210                Pointer<Integer> pErr = ptrs.pErr;
211                long evt = CL.clCreateUserEvent(getEntity(), getPeer(pErr));
212                        error(pErr.getInt());
213                return (CLUserEvent)CLEvent.createEvent(null, evt, true);
214        }
215
216        /**
217         * Create an OpenCL queue on the first device of this context.<br>
218         * Equivalent to calling <code>getDevices()[0].createQueue(context)</code>
219         * @return new OpenCL queue
220         */
221        public CLQueue createDefaultQueue(QueueProperties... queueProperties) {
222                return new CLDevice(platform, deviceIds.getSizeT()).createQueue(this, queueProperties);
223        }
224
225        /**
226         * Create an out-of-order OpenCL queue on the first device of this context.<br>
227         * Equivalent to calling <code>getDevices()[0].createOutOfOrderQueue(context)</code>
228         * @return new out-of-order OpenCL queue
229         */
230        public CLQueue createDefaultOutOfOrderQueue() {
231                return new CLDevice(platform, deviceIds.getSizeT()).createOutOfOrderQueue(this);
232        }
233
234        
235    public String toString() {
236        StringBuilder b = new StringBuilder("CLContext(platform = ").append(getPlatform().getName()).append("; devices = ");
237        boolean first = true;
238        for (CLDevice d : getDevices()) {
239            if (first)
240                first = false;
241            else
242                b.append(", ");
243            b.append(d.getName());
244        }
245        b.append(")");
246        return b.toString();
247    }
248        public CLQueue createDefaultOutOfOrderQueueIfPossible() {
249                try {
250                        return createDefaultOutOfOrderQueue();
251                } catch (Throwable th) {//CLException.InvalidQueueProperties ex) {
252                        return createDefaultQueue();
253                }
254    }
255
256        /**
257         * Create an profiling-enabled OpenCL queue on the first device of this context.<br>
258         * Equivalent to calling <code>getDevices()[0].createProfilingQueue(context)</code>
259         * @return new profiling-enabled OpenCL queue
260         */
261        public CLQueue createDefaultProfilingQueue() {
262                return new CLDevice(platform, deviceIds.getSizeT()).createProfilingQueue(this);
263        }
264
265        /**
266  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clGetSupportedImageFormats.html">clGetSupportedImageFormats</a>.<br>
267        */
268        @SuppressWarnings("deprecation")
269        public CLImageFormat[] getSupportedImageFormats(CLBuffer.Flags flags, CLBuffer.ObjectType imageType) {
270                Pointer<Integer> pCount = allocateInt();
271                int memFlags = (int) flags.value();
272                int imTyp = (int) imageType.value();
273                CL.clGetSupportedImageFormats(getEntity(), memFlags, imTyp, 0, 0, getPeer(pCount));
274                //cl_image_format ft = new cl_image_format();
275                //int sz = ft.size();
276                int n = pCount.getInt();
277                if (n == 0) {
278                        n = 30; // There HAS to be at least one format. the spec even says even more, but in fact on Mac OS X / CPU there's only one...
279                }
280        Pointer<cl_image_format> formats = allocateArray(cl_image_format.class, n);
281                CL.clGetSupportedImageFormats(getEntity(), memFlags, imTyp, n, getPeer(formats), 0);
282                List<CLImageFormat> ret = new ArrayList<CLImageFormat>(n);
283        for (cl_image_format ft : formats) {
284            if (ft.image_channel_data_type() == 0 && ft.image_channel_order() == 0)
285                                break;
286
287                        ret.add(new CLImageFormat(ft));
288                }
289                return ret.toArray(new CLImageFormat[ret.size()]);
290        }
291
292        /**
293  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateSampler.html">clCreateSampler</a>.<br>
294        */
295        @SuppressWarnings("deprecation")
296        public CLSampler createSampler(boolean normalized_coords, AddressingMode addressing_mode, FilterMode filter_mode) {
297                                ReusablePointers ptrs = ReusablePointers.get();
298                Pointer<Integer> pErr = ptrs.pErr;
299                long sampler = CL.clCreateSampler(
300                        getEntity(), 
301                        normalized_coords ? CL_TRUE : CL_FALSE, 
302                        (int) addressing_mode.value(), 
303                        (int) filter_mode.value(), 
304                        getPeer(pErr)
305                );
306                        error(pErr.getInt());
307                return new CLSampler(sampler);
308        }
309
310        public int getDeviceCount() {
311                return infos.getOptionalFeatureInt(getEntity(), CL.CL_CONTEXT_NUM_DEVICES);
312        }
313        
314        /**
315         * Lists the devices of this context
316         * @return array of the devices that form this context
317         */
318        public synchronized CLDevice[] getDevices() {
319                if (deviceIds == null) {
320                        deviceIds = infos.getMemory(getEntity(), CL_CONTEXT_DEVICES).as(SizeT.class);
321                }
322        int n = (int)deviceIds.getValidElements();
323
324                CLDevice[] devices = new CLDevice[n];
325                for (int i = n; i-- != 0;) {
326                        devices[i] = new CLDevice(platform, deviceIds.getSizeTAtIndex(i));
327                }
328                return devices;
329        }
330
331        /**
332         * Create a program with all the C source code content provided as argument.
333         * @param srcs list of the content of source code for the program
334         * @return a program that needs to be built
335         */
336        public CLProgram createProgram(String... srcs) {
337        return createProgram(null, srcs);
338        }
339
340    public CLProgram createProgram(CLDevice[] devices, String... srcs) {
341        CLProgram program = new CLProgram(this, devices);
342        for (String src : srcs)
343            program.addSource(src);
344        return program;
345    }
346
347    /**
348     * Restore a program previously saved with {@link CLProgram#store(java.io.OutputStream) }
349     * @param in will be closed
350     * @return a CLProgram object representing the previously saved program
351     * @throws IOException
352     */
353    public CLProgram loadProgram(InputStream in) throws IOException {
354        Pair<Map<CLDevice, byte[]>, String> binaries = CLProgram.readBinaries(Arrays.asList(getDevices()), null, in);
355        return createProgram(binaries.getFirst(), binaries.getSecond());
356    }
357
358        public CLProgram createProgram(Map<CLDevice, byte[]> binaries, String source) {
359                return new CLProgram(this, binaries, source);
360        }
361
362        //cl_queue queue;
363        @Override
364        protected void clear() {
365                error(CL.clReleaseContext(getEntity()));
366        }
367
368
369
370    @Deprecated
371    public CLDevice guessCurrentGLDevice() {
372        long[] props = platform.getContextProps(CLPlatform.getGLContextProperties(getPlatform()));
373        Pointer<SizeT> propsRef = pointerToSizeTs(props);
374        
375        Pointer<SizeT> pCount = allocateSizeT();
376        Pointer<Pointer<?>> mem = allocatePointer();
377        if (Platform.isMacOSX())
378            error(CL.clGetGLContextInfoAPPLE(
379                getEntity(), 
380                getPeer(OpenGLContextUtils.CGLGetCurrentContext()),
381                CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR,
382                Pointer.SIZE, 
383                getPeer(mem), 
384                getPeer(pCount)));
385        else
386            error(CL.clGetGLContextInfoKHR(
387                getPeer(propsRef), 
388                CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR, 
389                Pointer.SIZE, 
390                getPeer(mem), 
391                getPeer(pCount)
392                        ));
393
394        if (pCount.getSizeT() != Pointer.SIZE)
395            throw new RuntimeException("Not a device : len = " + pCount.get().intValue());
396
397        Pointer p = mem.getPointer();
398        if (p.equals(Pointer.NULL))
399            return null;
400        return new CLDevice(null, getPeer(p));
401    }
402
403    private static <T extends CLMem> T markAsGL(T mem) {
404        mem.isGL = true;
405        return mem;
406    }
407
408    /**
409  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateFromGLBuffer.html">clCreateFromGLBuffer</a>.<br>
410     * Makes an OpenGL Vertex Buffer Object (VBO) visible to OpenCL as a buffer object.<br>
411     * Note that memory objects shared with OpenGL must be acquired / released before / after use from OpenCL.
412     * see {@link CLMem#acquireGLObject(com.nativelibs4java.opencl.CLQueue, com.nativelibs4java.opencl.CLEvent[]) }
413     * see {@link CLMem#releaseGLObject(com.nativelibs4java.opencl.CLQueue, com.nativelibs4java.opencl.CLEvent[]) } 
414         * @param usage flags
415     * @param openGLBufferObject Identifier of a VBO, as generated by glGenBuffers
416     */
417        @SuppressWarnings("deprecation")
418        public CLBuffer<Byte> createBufferFromGLBuffer(CLMem.Usage usage, int openGLBufferObject) {
419                                ReusablePointers ptrs = ReusablePointers.get();
420                Pointer<Integer> pErr = ptrs.pErr;
421                long mem;
422                int previousAttempts = 0;
423                do {
424                        mem = CL.clCreateFromGLBuffer(
425                                getEntity(), 
426                                usage.getIntFlags(), 
427                                openGLBufferObject, 
428                                getPeer(pErr)
429                        );
430                } while (failedForLackOfMemory(pErr.getInt(), previousAttempts++));
431        return markAsGL(new CLBuffer(this, -1, mem, null, PointerIO.getByteInstance()));
432        }
433
434    /**
435  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateFromGLRenderbuffer.html">clCreateFromGLRenderbuffer</a>.<br>
436     * Makes an OpenGL Render Buffer visible to OpenCL as a 2D image.<br>
437     * Note that memory objects shared with OpenGL must be acquired / released before / after use from OpenCL.
438     * see {@link CLMem#acquireGLObject(com.nativelibs4java.opencl.CLQueue, com.nativelibs4java.opencl.CLEvent[]) }
439     * see {@link CLMem#releaseGLObject(com.nativelibs4java.opencl.CLQueue, com.nativelibs4java.opencl.CLEvent[]) }
440     * @param openGLRenderBuffer Identifier of an OpenGL render buffer
441     */
442        @SuppressWarnings("deprecation")
443        public CLImage2D createImage2DFromGLRenderBuffer(CLMem.Usage usage, int openGLRenderBuffer) {
444                                ReusablePointers ptrs = ReusablePointers.get();
445                Pointer<Integer> pErr = ptrs.pErr;
446                long mem;
447                int previousAttempts = 0;
448                do {
449                        mem = CL.clCreateFromGLRenderbuffer(
450                                getEntity(), 
451                                usage.getIntFlags(), 
452                                openGLRenderBuffer, 
453                                getPeer(pErr)
454                        );
455                } while (failedForLackOfMemory(pErr.getInt(), previousAttempts++));
456                return markAsGL(new CLImage2D(this, mem, null));
457        }
458        
459        /**
460  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateFromGLTexture2D.html">clCreateFromGLTexture2D</a>.<br>
461         * Creates an OpenCL 2D image object from an OpenGL 2D texture object, or a single face of an OpenGL cubemap texture object.<br>
462         * Note that memory objects shared with OpenGL must be acquired / released before / after use from OpenCL.
463     * @param usage
464         * @param textureTarget Must be one of GL_TEXTURE_2D, GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, or GL_TEXTURE_RECTANGLE47. texture_target is used only to define the image type of texture. No reference to a bound GL texture object is made or implied by this parameter.
465         * @param mipLevel Mipmap level to be used (Implementations may return CL_INVALID_OPERATION for miplevel values &gt; 0)
466         * @param texture Name of a GL 2D, cubemap or rectangle texture object. The texture object must be a complete texture as per OpenGL rules on texture completeness. The texture format and dimensions defined by OpenGL for the specified miplevel of the texture will be used to create the 2D image object. Only GL texture objects with an internal format that maps to appropriate image channel order and data type specified in tables 5.4 and 5.5 may be used to create a 2D image object.
467         * @return valid OpenCL image object if the image object is created successfully
468         * @throws CLException.InvalidMipLevel if miplevel is less than the value of levelbase (for OpenGL implementations) or zero (for OpenGL ES implementations); or greater than the value of q (for both OpenGL and OpenGL ES). levelbase and q are defined for the texture in section 3.8.10 (Texture Completeness) of the OpenGL 2.1 specification and section 3.7.10 of the OpenGL ES 2.0, or if miplevel is greather than zero and the OpenGL implementation does not support creating from non-zero mipmap levels.
469         * @throws CLException.InvalidGLObject if texture is not a GL texture object whose type matches texture_target, if the specified miplevel of texture is not defined, or if the width or height of the specified miplevel is zero.
470         * @throws CLException.InvalidImageFormatDescriptor if the OpenGL texture internal format does not map to a supported OpenCL image format.
471         */
472        @SuppressWarnings("deprecation")
473        public CLImage2D createImage2DFromGLTexture2D(CLMem.Usage usage, GLTextureTarget textureTarget, int texture, int mipLevel) {
474                platform.requireMinVersionValue("clCreateFromGLTexture2D", 1.1, 1.2);
475                                ReusablePointers ptrs = ReusablePointers.get();
476                Pointer<Integer> pErr = ptrs.pErr;
477                long mem;
478                int previousAttempts = 0;
479                do {
480                        mem = CL.clCreateFromGLTexture2D(
481                                getEntity(), 
482                                usage.getIntFlags(), 
483                                (int)textureTarget.value(), 
484                                mipLevel, 
485                                texture, 
486                                getPeer(pErr)
487                        );
488                } while (failedForLackOfMemory(pErr.getInt(), previousAttempts++));
489                return markAsGL(new CLImage2D(this, mem, null));
490        }
491
492        private static final int 
493                GL_TEXTURE_2D = 0x0DE1,
494                GL_TEXTURE_3D = 0x806F,
495                GL_TEXTURE_CUBE_MAP_POSITIVE_X = 0x8515,
496                GL_TEXTURE_CUBE_MAP_NEGATIVE_X = 0x8516,
497                GL_TEXTURE_CUBE_MAP_POSITIVE_Y = 0x8517,
498                GL_TEXTURE_CUBE_MAP_NEGATIVE_Y = 0x8518,
499                GL_TEXTURE_CUBE_MAP_POSITIVE_Z = 0x8519,
500                GL_TEXTURE_CUBE_MAP_NEGATIVE_Z = 0x851A,
501                GL_TEXTURE_RECTANGLE = 0x84F5;
502
503        public CLPlatform getPlatform() {
504                return platform;
505        }
506                
507
508        public enum GLTextureTarget implements com.nativelibs4java.util.ValuedEnum {
509                
510                Texture2D(GL_TEXTURE_2D),
511                //Texture3D(GL_TEXTURE_3D),
512                CubeMapPositiveX(GL_TEXTURE_CUBE_MAP_POSITIVE_X),
513                CubeMapNegativeX(GL_TEXTURE_CUBE_MAP_NEGATIVE_X),
514                CubeMapPositiveY(GL_TEXTURE_CUBE_MAP_POSITIVE_Y),
515                CubeMapNegativeY(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y),
516                CubeMapPositiveZ(GL_TEXTURE_CUBE_MAP_POSITIVE_Z),
517                CubeMapNegativeZ(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z),
518                Rectangle(GL_TEXTURE_RECTANGLE);
519
520                GLTextureTarget(long value) { this.value = value; }
521                long value;
522                @Override
523                public long value() { return value; }
524                public static GLTextureTarget getEnum(int v) { return EnumValues.getEnum(v, GLTextureTarget.class); }
525        }
526        
527        /**
528  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateFromGLTexture3D.html">clCreateFromGLTexture3D</a>.<br>
529         * Creates an OpenCL 3D image object from an OpenGL 3D texture object<br>
530         * Note that memory objects shared with OpenGL must be acquired / released before / after use from OpenCL.
531         * @param usage
532         * @param mipLevel Mipmap level to be used (Implementations may return CL_INVALID_OPERATION for miplevel values &gt; 0)
533         * @param texture Name of a GL 3D texture object. The texture object must be a complete texture as per OpenGL rules on texture completeness. The texture format and dimensions defined by OpenGL for the specified miplevel of the texture will be used to create the 3D image object. Only GL texture objects with an internal format that maps to appropriate image channel order and data type specified in tables 5.4 and 5.5 can be used to create the 3D image object.
534         * @return valid OpenCL image object if the image object is created successfully
535         * @throws CLException.InvalidMipLevel if miplevel is less than the value of levelbase (for OpenGL implementations) or zero (for OpenGL ES implementations); or greater than the value of q (for both OpenGL and OpenGL ES). levelbase and q are defined for the texture in section 3.8.10 (Texture Completeness) of the OpenGL 2.1 specification and section 3.7.10 of the OpenGL ES 2.0, or if miplevel is greather than zero and the OpenGL implementation does not support creating from non-zero mipmap levels.
536         * @throws CLException.InvalidGLObject if texture is not a GL texture object whose type matches texture_target, if the specified miplevel of texture is not defined, or if the width or height of the specified miplevel is zero.
537         * @throws CLException.InvalidImageFormatDescriptor if the OpenGL texture internal format does not map to a supported OpenCL image format.
538         */
539        @SuppressWarnings("deprecation")
540        public CLImage3D createImage3DFromGLTexture3D(CLMem.Usage usage, int texture, int mipLevel) {
541                platform.requireMinVersionValue("clCreateFromGLTexture3D", 1.1, 1.2);
542                                ReusablePointers ptrs = ReusablePointers.get();
543                Pointer<Integer> pErr = ptrs.pErr;
544                long mem;
545                int previousAttempts = 0;
546                do {
547                        mem = CL.clCreateFromGLTexture3D(
548                                getEntity(), 
549                                usage.getIntFlags(), 
550                                GL_TEXTURE_3D, 
551                                mipLevel, 
552                                texture, 
553                                getPeer(pErr)
554                        );
555                } while (failedForLackOfMemory(pErr.getInt(), previousAttempts++));
556                return markAsGL(new CLImage3D(this, mem, null));
557        }
558        
559        /**
560         * Create an ARGB input 2D image with the content provided
561         * @param allowUnoptimizingDirectRead Some images expose their internal data for direct read, leading to performance increase during the creation of the OpenCL image. However, direct access to the image data disables some Java2D optimizations for this image, leading to degraded performance in subsequent uses with AWT/Swing.
562         */
563        public CLImage2D createImage2D(CLMem.Usage usage, Image image, boolean allowUnoptimizingDirectRead) {
564                int width = image.getWidth(null), height = image.getHeight(null);
565                ImageInfo info = ImageIOUtils.getImageInfo(image);
566        return createImage2D(
567                                usage,
568                                info.clImageFormat,
569                                width, height,
570                                0,
571                                info.dataGetter.getData(image, null, true, allowUnoptimizingDirectRead, getByteOrder()),
572                                true);
573        }
574
575        /**
576  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateImage2D.html">clCreateImage2D</a>.<br>
577     * @param usage Usage intended for the image.
578     * @param format Format of the image.
579     * @param width Image width
580     * @param height Image height
581     * @return A new image allocated on this context.
582   * @param rowPitch Row pitch.
583   * @param buffer Image data buffer.
584   * @param copy Whether to copy the input buffer.
585        */
586        @SuppressWarnings("deprecation")
587        public CLImage2D createImage2D(CLMem.Usage usage, CLImageFormat format, long width, long height, long rowPitch, Buffer buffer, boolean copy) {
588                platform.requireMinVersionValue("clCreateImage2D", 1.1, 1.2);
589                
590                long memFlags = usage.getIntFlags();
591                if (buffer != null) {
592                        memFlags |= copy ? CL_MEM_COPY_HOST_PTR : CL_MEM_USE_HOST_PTR;
593                }
594
595                                ReusablePointers ptrs = ReusablePointers.get();
596                Pointer<Integer> pErr = ptrs.pErr;
597                Pointer<cl_image_format> pImageFormat = getPointer(format.to_cl_image_format());
598                Pointer<?> pBuffer = buffer == null ? null : pointerToBuffer(buffer);
599                long mem;
600                int previousAttempts = 0;
601                do {
602                        mem = CL.clCreateImage2D(
603                                getEntity(),
604                                memFlags,
605                                getPeer(pImageFormat),
606                                width,
607                                height,
608                                rowPitch,
609                                getPeer(pBuffer),
610                                getPeer(pErr));
611                } while (failedForLackOfMemory(pErr.getInt(), previousAttempts++));
612                return new CLImage2D(this, mem, format);
613        }
614
615        /**
616  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateImage2D.html">clCreateImage2D</a>.<br>
617     * @param usage Usage intended for the image.
618     * @param format Format of the image.
619     * @param width Image width
620     * @param height Image height
621     * @return A new image allocated on this context.
622   * @param rowPitch Row pitch.
623  */
624  public CLImage2D createImage2D(CLMem.Usage usage, CLImageFormat format, long width, long height, long rowPitch) {
625                return createImage2D(usage, format, width, height, rowPitch, null, false);
626        }
627
628        /**
629  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateImage2D.html">clCreateImage2D</a>.<br>
630     * @param usage Usage intended for the image.
631     * @param format Format of the image.
632     * @param width Image width
633     * @param height Image height
634     * @return A new image allocated on this context.
635  */
636  public CLImage2D createImage2D(CLMem.Usage usage, CLImageFormat format, long width, long height) {
637                return createImage2D(usage, format, width, height, 0, null, false);
638        }
639
640        /**
641  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateImage3D.html">clCreateImage3D</a>.<br>
642     * @param usage Usage intended for the image.
643     * @param format Format of the image.
644     * @param width Image width
645     * @param height Image height
646     * @return A new image allocated on this context.
647     * @param depth Image depth
648   * @param rowPitch Row pitch.
649   * @param slicePitch Slice pitch.
650   * @param buffer Image data buffer.
651   * @param copy Whether to copy the input buffer.
652  */
653  @SuppressWarnings("deprecation")
654        public CLImage3D createImage3D(CLMem.Usage usage, CLImageFormat format, long width, long height, long depth, long rowPitch, long slicePitch, Buffer buffer, boolean copy) {
655                platform.requireMinVersionValue("clCreateImage3D", 1.1, 1.2);
656                long memFlags = usage.getIntFlags();
657                if (buffer != null) {
658                        memFlags |= copy ? CL_MEM_COPY_HOST_PTR : CL_MEM_USE_HOST_PTR;
659                }
660
661                                ReusablePointers ptrs = ReusablePointers.get();
662                Pointer<Integer> pErr = ptrs.pErr;
663                Pointer<cl_image_format> pImageFormat = getPointer(format.to_cl_image_format());
664                Pointer<?> pBuffer = buffer == null ? null : pointerToBuffer(buffer);
665                long mem;
666                int previousAttempts = 0;
667                do {
668                        mem = CL.clCreateImage3D(
669                                getEntity(),
670                                memFlags,
671                                getPeer(pImageFormat),
672                                width,
673                                height,
674                                depth,
675                                rowPitch,
676                                slicePitch,
677                                getPeer(pBuffer),
678                                getPeer(pErr));
679                } while (failedForLackOfMemory(pErr.getInt(), previousAttempts++));
680                return new CLImage3D(this, mem, format);
681        }
682
683        /**
684  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateImage3D.html">clCreateImage3D</a>.<br>
685     * @param usage Usage intended for the image.
686     * @param format Format of the image.
687     * @param width Image width
688     * @param height Image height
689     * @return A new image allocated on this context.
690     * @param depth Image depth
691   * @param rowPitch Row pitch.
692   * @param slicePitch Slice pitch.
693  */
694  public CLImage3D createImage3D(CLMem.Usage usage, CLImageFormat format, long width, long height, long depth, long rowPitch, long slicePitch) {
695                return createImage3D(usage, format, width, height, depth, rowPitch, slicePitch, null, false);
696        }
697
698        /**
699  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateImage3D.html">clCreateImage3D</a>.<br>
700     * @param usage Usage intended for the image.
701     * @param format Format of the image.
702     * @param width Image width
703     * @param height Image height
704     * @return A new image allocated on this context.
705     * @param depth Image depth
706  */
707  public CLImage3D createImage3D(CLMem.Usage usage, CLImageFormat format, long width, long height, long depth) {
708                return createImage3D(usage, format, width, height, depth, 0, 0, null, false);
709        }
710
711
712        /**
713  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateBuffer.html">clCreateBuffer</a>.<br>
714         * Create a <code>CLBuffer&lt;Integer&gt;</code> OpenCL buffer  with the provided initial values.<br>
715         * If copy is true (see <a href="http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/clCreateBuffer.html">CL_MEM_COPY_HOST_PTR</a>), then the buffer will be hosted in OpenCL and will have the best performance, but any change done to the OpenCL buffer won't be propagated to the original data pointer.<br>
716         * If copy is false (see <a href="http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/clCreateBuffer.html">CL_MEM_USE_HOST_PTR</a>), then the provided data pointer will be used for storage of the OpenCL buffer. OpenCL might still cache the data in the OpenCL land, so careful use of {@link CLBuffer#map(CLQueue, CLMem.MapFlags, CLEvent...) CLBuffer#map(CLQueue, MapFlags, CLEvent...)} is then necessary to ensure the data is properly synchronized with the buffer. 
717         * @param usage Usage intended for the pointer in OpenCL kernels : a pointer created with {@link CLMem.Usage#Input} cannot be written to in a kernel.
718         * @param data Pointer to the initial values, must have known bounds (see {@link Pointer#getValidElements()}).
719   * @param data Data buffer.
720   * @param copy Whether to copy the input data.
721   * @return A new buffer allocated on this context.
722         */
723        public CLBuffer<Integer> createIntBuffer(CLMem.Usage usage,  IntBuffer  data, boolean copy) {
724                return createBuffer(usage, Pointer.pointerToInts(data), copy);
725        }
726
727    /**
728  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateBuffer.html">clCreateBuffer</a>.<br>
729     * Create a <code>CLBuffer&lt;Integer&gt;</code> OpenCL buffer big enough to hold the valid  values of the provided data pointer.
730     * @param usage Usage intended for the pointer in OpenCL kernels : a pointer created with {@link CLMem.Usage#Input} cannot be written to in a kernel.
731     * @param data Host data to copy to the buffer
732     * @return A new buffer allocated on this context.
733   */
734        public CLBuffer<Integer> createIntBuffer(CLMem.Usage usage, Pointer<Integer> data) {
735                return createIntBuffer(usage, data, true);
736        }
737        /**
738  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateBuffer.html">clCreateBuffer</a>.<br>
739         * Create a <code>CLBuffer&lt;Integer&gt;</code> OpenCL buffer  with the provided initial values.<br>
740         * If copy is true (see <a href="http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/clCreateBuffer.html">CL_MEM_COPY_HOST_PTR</a>), then the buffer will be hosted in OpenCL and will have the best performance, but any change done to the OpenCL buffer won't be propagated to the original data pointer.<br>
741         * If copy is false (see <a href="http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/clCreateBuffer.html">CL_MEM_USE_HOST_PTR</a>), then the provided data pointer will be used for storage of the OpenCL buffer. OpenCL might still cache the data in the OpenCL land, so careful use of {@link CLBuffer#map(CLQueue, CLMem.MapFlags, CLEvent...) CLBuffer#map(CLQueue, MapFlags, CLEvent...)} is then necessary to ensure the data is properly synchronized with the buffer. 
742         * @param usage Usage intended for the pointer in OpenCL kernels : a pointer created with {@link CLMem.Usage#Input} cannot be written to in a kernel.
743         * @param data Pointer to the initial values, must have known bounds (see {@link Pointer#getValidElements()}).
744   * @param data Data buffer.
745   * @param copy Whether to copy the input data.
746   * @return A new buffer allocated on this context.
747         */
748        public CLBuffer<Integer> createIntBuffer(CLMem.Usage usage, Pointer<Integer> data, boolean copy) {
749                return createBuffer(usage, data, copy);
750        }
751        
752    /**
753  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateBuffer.html">clCreateBuffer</a>.<br>
754     * Create a <code>CLBuffer&lt;Integer&gt;</code> OpenCL buffer big enough to hold 'length' values of type int.
755     * @param usage Usage intended for the pointer in OpenCL kernels : a pointer created with {@link CLMem.Usage#Input} cannot be written to in a kernel.
756    
757   * @param elementCount Length of the buffer expressed in elements (for instance, a <code>CLBuffer&lt;Integer&gt;</code> of length 10 will actually contain 10 * 4 bytes, as ints are 4-bytes-long)
758   * @return A new buffer allocated on this context.
759   */
760        public CLBuffer<Integer> createIntBuffer(CLMem.Usage usage, long elementCount) {
761                return createBuffer(usage, Integer.class, elementCount);
762        }
763        
764
765        /**
766  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateBuffer.html">clCreateBuffer</a>.<br>
767         * Create a <code>CLBuffer&lt;Long&gt;</code> OpenCL buffer  with the provided initial values.<br>
768         * If copy is true (see <a href="http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/clCreateBuffer.html">CL_MEM_COPY_HOST_PTR</a>), then the buffer will be hosted in OpenCL and will have the best performance, but any change done to the OpenCL buffer won't be propagated to the original data pointer.<br>
769         * If copy is false (see <a href="http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/clCreateBuffer.html">CL_MEM_USE_HOST_PTR</a>), then the provided data pointer will be used for storage of the OpenCL buffer. OpenCL might still cache the data in the OpenCL land, so careful use of {@link CLBuffer#map(CLQueue, CLMem.MapFlags, CLEvent...) CLBuffer#map(CLQueue, MapFlags, CLEvent...)} is then necessary to ensure the data is properly synchronized with the buffer. 
770         * @param usage Usage intended for the pointer in OpenCL kernels : a pointer created with {@link CLMem.Usage#Input} cannot be written to in a kernel.
771         * @param data Pointer to the initial values, must have known bounds (see {@link Pointer#getValidElements()}).
772   * @param data Data buffer.
773   * @param copy Whether to copy the input data.
774   * @return A new buffer allocated on this context.
775         */
776        public CLBuffer<Long> createLongBuffer(CLMem.Usage usage,  LongBuffer  data, boolean copy) {
777                return createBuffer(usage, Pointer.pointerToLongs(data), copy);
778        }
779
780    /**
781  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateBuffer.html">clCreateBuffer</a>.<br>
782     * Create a <code>CLBuffer&lt;Long&gt;</code> OpenCL buffer big enough to hold the valid  values of the provided data pointer.
783     * @param usage Usage intended for the pointer in OpenCL kernels : a pointer created with {@link CLMem.Usage#Input} cannot be written to in a kernel.
784     * @param data Host data to copy to the buffer
785     * @return A new buffer allocated on this context.
786   */
787        public CLBuffer<Long> createLongBuffer(CLMem.Usage usage, Pointer<Long> data) {
788                return createLongBuffer(usage, data, true);
789        }
790        /**
791  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateBuffer.html">clCreateBuffer</a>.<br>
792         * Create a <code>CLBuffer&lt;Long&gt;</code> OpenCL buffer  with the provided initial values.<br>
793         * If copy is true (see <a href="http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/clCreateBuffer.html">CL_MEM_COPY_HOST_PTR</a>), then the buffer will be hosted in OpenCL and will have the best performance, but any change done to the OpenCL buffer won't be propagated to the original data pointer.<br>
794         * If copy is false (see <a href="http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/clCreateBuffer.html">CL_MEM_USE_HOST_PTR</a>), then the provided data pointer will be used for storage of the OpenCL buffer. OpenCL might still cache the data in the OpenCL land, so careful use of {@link CLBuffer#map(CLQueue, CLMem.MapFlags, CLEvent...) CLBuffer#map(CLQueue, MapFlags, CLEvent...)} is then necessary to ensure the data is properly synchronized with the buffer. 
795         * @param usage Usage intended for the pointer in OpenCL kernels : a pointer created with {@link CLMem.Usage#Input} cannot be written to in a kernel.
796         * @param data Pointer to the initial values, must have known bounds (see {@link Pointer#getValidElements()}).
797   * @param data Data buffer.
798   * @param copy Whether to copy the input data.
799   * @return A new buffer allocated on this context.
800         */
801        public CLBuffer<Long> createLongBuffer(CLMem.Usage usage, Pointer<Long> data, boolean copy) {
802                return createBuffer(usage, data, copy);
803        }
804        
805    /**
806  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateBuffer.html">clCreateBuffer</a>.<br>
807     * Create a <code>CLBuffer&lt;Long&gt;</code> OpenCL buffer big enough to hold 'length' values of type long.
808     * @param usage Usage intended for the pointer in OpenCL kernels : a pointer created with {@link CLMem.Usage#Input} cannot be written to in a kernel.
809    
810   * @param elementCount Length of the buffer expressed in elements (for instance, a <code>CLBuffer&lt;Long&gt;</code> of length 10 will actually contain 10 * 8 bytes, as longs are 8-bytes-long)
811   * @return A new buffer allocated on this context.
812   */
813        public CLBuffer<Long> createLongBuffer(CLMem.Usage usage, long elementCount) {
814                return createBuffer(usage, Long.class, elementCount);
815        }
816        
817
818        /**
819  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateBuffer.html">clCreateBuffer</a>.<br>
820         * Create a <code>CLBuffer&lt;Short&gt;</code> OpenCL buffer  with the provided initial values.<br>
821         * If copy is true (see <a href="http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/clCreateBuffer.html">CL_MEM_COPY_HOST_PTR</a>), then the buffer will be hosted in OpenCL and will have the best performance, but any change done to the OpenCL buffer won't be propagated to the original data pointer.<br>
822         * If copy is false (see <a href="http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/clCreateBuffer.html">CL_MEM_USE_HOST_PTR</a>), then the provided data pointer will be used for storage of the OpenCL buffer. OpenCL might still cache the data in the OpenCL land, so careful use of {@link CLBuffer#map(CLQueue, CLMem.MapFlags, CLEvent...) CLBuffer#map(CLQueue, MapFlags, CLEvent...)} is then necessary to ensure the data is properly synchronized with the buffer. 
823         * @param usage Usage intended for the pointer in OpenCL kernels : a pointer created with {@link CLMem.Usage#Input} cannot be written to in a kernel.
824         * @param data Pointer to the initial values, must have known bounds (see {@link Pointer#getValidElements()}).
825   * @param data Data buffer.
826   * @param copy Whether to copy the input data.
827   * @return A new buffer allocated on this context.
828         */
829        public CLBuffer<Short> createShortBuffer(CLMem.Usage usage,  ShortBuffer  data, boolean copy) {
830                return createBuffer(usage, Pointer.pointerToShorts(data), copy);
831        }
832
833    /**
834  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateBuffer.html">clCreateBuffer</a>.<br>
835     * Create a <code>CLBuffer&lt;Short&gt;</code> OpenCL buffer big enough to hold the valid  values of the provided data pointer.
836     * @param usage Usage intended for the pointer in OpenCL kernels : a pointer created with {@link CLMem.Usage#Input} cannot be written to in a kernel.
837     * @param data Host data to copy to the buffer
838     * @return A new buffer allocated on this context.
839   */
840        public CLBuffer<Short> createShortBuffer(CLMem.Usage usage, Pointer<Short> data) {
841                return createShortBuffer(usage, data, true);
842        }
843        /**
844  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateBuffer.html">clCreateBuffer</a>.<br>
845         * Create a <code>CLBuffer&lt;Short&gt;</code> OpenCL buffer  with the provided initial values.<br>
846         * If copy is true (see <a href="http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/clCreateBuffer.html">CL_MEM_COPY_HOST_PTR</a>), then the buffer will be hosted in OpenCL and will have the best performance, but any change done to the OpenCL buffer won't be propagated to the original data pointer.<br>
847         * If copy is false (see <a href="http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/clCreateBuffer.html">CL_MEM_USE_HOST_PTR</a>), then the provided data pointer will be used for storage of the OpenCL buffer. OpenCL might still cache the data in the OpenCL land, so careful use of {@link CLBuffer#map(CLQueue, CLMem.MapFlags, CLEvent...) CLBuffer#map(CLQueue, MapFlags, CLEvent...)} is then necessary to ensure the data is properly synchronized with the buffer. 
848         * @param usage Usage intended for the pointer in OpenCL kernels : a pointer created with {@link CLMem.Usage#Input} cannot be written to in a kernel.
849         * @param data Pointer to the initial values, must have known bounds (see {@link Pointer#getValidElements()}).
850   * @param data Data buffer.
851   * @param copy Whether to copy the input data.
852   * @return A new buffer allocated on this context.
853         */
854        public CLBuffer<Short> createShortBuffer(CLMem.Usage usage, Pointer<Short> data, boolean copy) {
855                return createBuffer(usage, data, copy);
856        }
857        
858    /**
859  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateBuffer.html">clCreateBuffer</a>.<br>
860     * Create a <code>CLBuffer&lt;Short&gt;</code> OpenCL buffer big enough to hold 'length' values of type short.
861     * @param usage Usage intended for the pointer in OpenCL kernels : a pointer created with {@link CLMem.Usage#Input} cannot be written to in a kernel.
862    
863   * @param elementCount Length of the buffer expressed in elements (for instance, a <code>CLBuffer&lt;Short&gt;</code> of length 10 will actually contain 10 * 2 bytes, as shorts are 2-bytes-long)
864   * @return A new buffer allocated on this context.
865   */
866        public CLBuffer<Short> createShortBuffer(CLMem.Usage usage, long elementCount) {
867                return createBuffer(usage, Short.class, elementCount);
868        }
869        
870
871        /**
872  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateBuffer.html">clCreateBuffer</a>.<br>
873         * Create a <code>CLBuffer&lt;Byte&gt;</code> OpenCL buffer  with the provided initial values.<br>
874         * If copy is true (see <a href="http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/clCreateBuffer.html">CL_MEM_COPY_HOST_PTR</a>), then the buffer will be hosted in OpenCL and will have the best performance, but any change done to the OpenCL buffer won't be propagated to the original data pointer.<br>
875         * If copy is false (see <a href="http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/clCreateBuffer.html">CL_MEM_USE_HOST_PTR</a>), then the provided data pointer will be used for storage of the OpenCL buffer. OpenCL might still cache the data in the OpenCL land, so careful use of {@link CLBuffer#map(CLQueue, CLMem.MapFlags, CLEvent...) CLBuffer#map(CLQueue, MapFlags, CLEvent...)} is then necessary to ensure the data is properly synchronized with the buffer. 
876         * @param usage Usage intended for the pointer in OpenCL kernels : a pointer created with {@link CLMem.Usage#Input} cannot be written to in a kernel.
877         * @param data Pointer to the initial values, must have known bounds (see {@link Pointer#getValidElements()}).
878   * @param data Data buffer.
879   * @param copy Whether to copy the input data.
880   * @return A new buffer allocated on this context.
881         */
882        public CLBuffer<Byte> createByteBuffer(CLMem.Usage usage,  Buffer  data, boolean copy) {
883                return createBuffer(usage, Pointer.pointerToBuffer(data).as(Byte.class), copy);
884        }
885
886    /**
887  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateBuffer.html">clCreateBuffer</a>.<br>
888     * Create a <code>CLBuffer&lt;Byte&gt;</code> OpenCL buffer big enough to hold the valid  values of the provided data pointer.
889     * @param usage Usage intended for the pointer in OpenCL kernels : a pointer created with {@link CLMem.Usage#Input} cannot be written to in a kernel.
890     * @param data Host data to copy to the buffer
891     * @return A new buffer allocated on this context.
892   */
893        public CLBuffer<Byte> createByteBuffer(CLMem.Usage usage, Pointer<Byte> data) {
894                return createByteBuffer(usage, data, true);
895        }
896        /**
897  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateBuffer.html">clCreateBuffer</a>.<br>
898         * Create a <code>CLBuffer&lt;Byte&gt;</code> OpenCL buffer  with the provided initial values.<br>
899         * If copy is true (see <a href="http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/clCreateBuffer.html">CL_MEM_COPY_HOST_PTR</a>), then the buffer will be hosted in OpenCL and will have the best performance, but any change done to the OpenCL buffer won't be propagated to the original data pointer.<br>
900         * If copy is false (see <a href="http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/clCreateBuffer.html">CL_MEM_USE_HOST_PTR</a>), then the provided data pointer will be used for storage of the OpenCL buffer. OpenCL might still cache the data in the OpenCL land, so careful use of {@link CLBuffer#map(CLQueue, CLMem.MapFlags, CLEvent...) CLBuffer#map(CLQueue, MapFlags, CLEvent...)} is then necessary to ensure the data is properly synchronized with the buffer. 
901         * @param usage Usage intended for the pointer in OpenCL kernels : a pointer created with {@link CLMem.Usage#Input} cannot be written to in a kernel.
902         * @param data Pointer to the initial values, must have known bounds (see {@link Pointer#getValidElements()}).
903   * @param data Data buffer.
904   * @param copy Whether to copy the input data.
905   * @return A new buffer allocated on this context.
906         */
907        public CLBuffer<Byte> createByteBuffer(CLMem.Usage usage, Pointer<Byte> data, boolean copy) {
908                return createBuffer(usage, data, copy);
909        }
910        
911    /**
912  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateBuffer.html">clCreateBuffer</a>.<br>
913     * Create a <code>CLBuffer&lt;Byte&gt;</code> OpenCL buffer big enough to hold 'length' values of type byte.
914     * @param usage Usage intended for the pointer in OpenCL kernels : a pointer created with {@link CLMem.Usage#Input} cannot be written to in a kernel.
915    
916   * @param elementCount Length of the buffer expressed in elements (for instance, a <code>CLBuffer&lt;Byte&gt;</code> of length 10 will actually contain 10 * 1 bytes, as bytes are 1-bytes-long)
917   * @return A new buffer allocated on this context.
918   */
919        public CLBuffer<Byte> createByteBuffer(CLMem.Usage usage, long elementCount) {
920                return createBuffer(usage, Byte.class, elementCount);
921        }
922        
923
924        /**
925  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateBuffer.html">clCreateBuffer</a>.<br>
926         * Create a <code>CLBuffer&lt;Character&gt;</code> OpenCL buffer  with the provided initial values.<br>
927         * If copy is true (see <a href="http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/clCreateBuffer.html">CL_MEM_COPY_HOST_PTR</a>), then the buffer will be hosted in OpenCL and will have the best performance, but any change done to the OpenCL buffer won't be propagated to the original data pointer.<br>
928         * If copy is false (see <a href="http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/clCreateBuffer.html">CL_MEM_USE_HOST_PTR</a>), then the provided data pointer will be used for storage of the OpenCL buffer. OpenCL might still cache the data in the OpenCL land, so careful use of {@link CLBuffer#map(CLQueue, CLMem.MapFlags, CLEvent...) CLBuffer#map(CLQueue, MapFlags, CLEvent...)} is then necessary to ensure the data is properly synchronized with the buffer. 
929         * @param usage Usage intended for the pointer in OpenCL kernels : a pointer created with {@link CLMem.Usage#Input} cannot be written to in a kernel.
930         * @param data Pointer to the initial values, must have known bounds (see {@link Pointer#getValidElements()}).
931   * @param data Data buffer.
932   * @param copy Whether to copy the input data.
933   * @return A new buffer allocated on this context.
934         */
935        public CLBuffer<Character> createCharBuffer(CLMem.Usage usage,  CharBuffer  data, boolean copy) {
936                return createBuffer(usage, Pointer.pointerToChars(data), copy);
937        }
938
939    /**
940  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateBuffer.html">clCreateBuffer</a>.<br>
941     * Create a <code>CLBuffer&lt;Character&gt;</code> OpenCL buffer big enough to hold the valid  values of the provided data pointer.
942     * @param usage Usage intended for the pointer in OpenCL kernels : a pointer created with {@link CLMem.Usage#Input} cannot be written to in a kernel.
943     * @param data Host data to copy to the buffer
944     * @return A new buffer allocated on this context.
945   */
946        public CLBuffer<Character> createCharBuffer(CLMem.Usage usage, Pointer<Character> data) {
947                return createCharBuffer(usage, data, true);
948        }
949        /**
950  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateBuffer.html">clCreateBuffer</a>.<br>
951         * Create a <code>CLBuffer&lt;Character&gt;</code> OpenCL buffer  with the provided initial values.<br>
952         * If copy is true (see <a href="http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/clCreateBuffer.html">CL_MEM_COPY_HOST_PTR</a>), then the buffer will be hosted in OpenCL and will have the best performance, but any change done to the OpenCL buffer won't be propagated to the original data pointer.<br>
953         * If copy is false (see <a href="http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/clCreateBuffer.html">CL_MEM_USE_HOST_PTR</a>), then the provided data pointer will be used for storage of the OpenCL buffer. OpenCL might still cache the data in the OpenCL land, so careful use of {@link CLBuffer#map(CLQueue, CLMem.MapFlags, CLEvent...) CLBuffer#map(CLQueue, MapFlags, CLEvent...)} is then necessary to ensure the data is properly synchronized with the buffer. 
954         * @param usage Usage intended for the pointer in OpenCL kernels : a pointer created with {@link CLMem.Usage#Input} cannot be written to in a kernel.
955         * @param data Pointer to the initial values, must have known bounds (see {@link Pointer#getValidElements()}).
956   * @param data Data buffer.
957   * @param copy Whether to copy the input data.
958   * @return A new buffer allocated on this context.
959         */
960        public CLBuffer<Character> createCharBuffer(CLMem.Usage usage, Pointer<Character> data, boolean copy) {
961                return createBuffer(usage, data, copy);
962        }
963        
964    /**
965  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateBuffer.html">clCreateBuffer</a>.<br>
966     * Create a <code>CLBuffer&lt;Character&gt;</code> OpenCL buffer big enough to hold 'length' values of type char.
967     * @param usage Usage intended for the pointer in OpenCL kernels : a pointer created with {@link CLMem.Usage#Input} cannot be written to in a kernel.
968    
969   * @param elementCount Length of the buffer expressed in elements (for instance, a <code>CLBuffer&lt;Character&gt;</code> of length 10 will actually contain 10 * 2 bytes, as chars are 2-bytes-long)
970   * @return A new buffer allocated on this context.
971   */
972        public CLBuffer<Character> createCharBuffer(CLMem.Usage usage, long elementCount) {
973                return createBuffer(usage, Character.class, elementCount);
974        }
975        
976
977        /**
978  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateBuffer.html">clCreateBuffer</a>.<br>
979         * Create a <code>CLBuffer&lt;Float&gt;</code> OpenCL buffer  with the provided initial values.<br>
980         * If copy is true (see <a href="http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/clCreateBuffer.html">CL_MEM_COPY_HOST_PTR</a>), then the buffer will be hosted in OpenCL and will have the best performance, but any change done to the OpenCL buffer won't be propagated to the original data pointer.<br>
981         * If copy is false (see <a href="http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/clCreateBuffer.html">CL_MEM_USE_HOST_PTR</a>), then the provided data pointer will be used for storage of the OpenCL buffer. OpenCL might still cache the data in the OpenCL land, so careful use of {@link CLBuffer#map(CLQueue, CLMem.MapFlags, CLEvent...) CLBuffer#map(CLQueue, MapFlags, CLEvent...)} is then necessary to ensure the data is properly synchronized with the buffer. 
982         * @param usage Usage intended for the pointer in OpenCL kernels : a pointer created with {@link CLMem.Usage#Input} cannot be written to in a kernel.
983         * @param data Pointer to the initial values, must have known bounds (see {@link Pointer#getValidElements()}).
984   * @param data Data buffer.
985   * @param copy Whether to copy the input data.
986   * @return A new buffer allocated on this context.
987         */
988        public CLBuffer<Float> createFloatBuffer(CLMem.Usage usage,  FloatBuffer  data, boolean copy) {
989                return createBuffer(usage, Pointer.pointerToFloats(data), copy);
990        }
991
992    /**
993  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateBuffer.html">clCreateBuffer</a>.<br>
994     * Create a <code>CLBuffer&lt;Float&gt;</code> OpenCL buffer big enough to hold the valid  values of the provided data pointer.
995     * @param usage Usage intended for the pointer in OpenCL kernels : a pointer created with {@link CLMem.Usage#Input} cannot be written to in a kernel.
996     * @param data Host data to copy to the buffer
997     * @return A new buffer allocated on this context.
998   */
999        public CLBuffer<Float> createFloatBuffer(CLMem.Usage usage, Pointer<Float> data) {
1000                return createFloatBuffer(usage, data, true);
1001        }
1002        /**
1003  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateBuffer.html">clCreateBuffer</a>.<br>
1004         * Create a <code>CLBuffer&lt;Float&gt;</code> OpenCL buffer  with the provided initial values.<br>
1005         * If copy is true (see <a href="http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/clCreateBuffer.html">CL_MEM_COPY_HOST_PTR</a>), then the buffer will be hosted in OpenCL and will have the best performance, but any change done to the OpenCL buffer won't be propagated to the original data pointer.<br>
1006         * If copy is false (see <a href="http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/clCreateBuffer.html">CL_MEM_USE_HOST_PTR</a>), then the provided data pointer will be used for storage of the OpenCL buffer. OpenCL might still cache the data in the OpenCL land, so careful use of {@link CLBuffer#map(CLQueue, CLMem.MapFlags, CLEvent...) CLBuffer#map(CLQueue, MapFlags, CLEvent...)} is then necessary to ensure the data is properly synchronized with the buffer. 
1007         * @param usage Usage intended for the pointer in OpenCL kernels : a pointer created with {@link CLMem.Usage#Input} cannot be written to in a kernel.
1008         * @param data Pointer to the initial values, must have known bounds (see {@link Pointer#getValidElements()}).
1009   * @param data Data buffer.
1010   * @param copy Whether to copy the input data.
1011   * @return A new buffer allocated on this context.
1012         */
1013        public CLBuffer<Float> createFloatBuffer(CLMem.Usage usage, Pointer<Float> data, boolean copy) {
1014                return createBuffer(usage, data, copy);
1015        }
1016        
1017    /**
1018  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateBuffer.html">clCreateBuffer</a>.<br>
1019     * Create a <code>CLBuffer&lt;Float&gt;</code> OpenCL buffer big enough to hold 'length' values of type float.
1020     * @param usage Usage intended for the pointer in OpenCL kernels : a pointer created with {@link CLMem.Usage#Input} cannot be written to in a kernel.
1021    
1022   * @param elementCount Length of the buffer expressed in elements (for instance, a <code>CLBuffer&lt;Float&gt;</code> of length 10 will actually contain 10 * 4 bytes, as floats are 4-bytes-long)
1023   * @return A new buffer allocated on this context.
1024   */
1025        public CLBuffer<Float> createFloatBuffer(CLMem.Usage usage, long elementCount) {
1026                return createBuffer(usage, Float.class, elementCount);
1027        }
1028        
1029
1030        /**
1031  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateBuffer.html">clCreateBuffer</a>.<br>
1032         * Create a <code>CLBuffer&lt;Double&gt;</code> OpenCL buffer  with the provided initial values.<br>
1033         * If copy is true (see <a href="http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/clCreateBuffer.html">CL_MEM_COPY_HOST_PTR</a>), then the buffer will be hosted in OpenCL and will have the best performance, but any change done to the OpenCL buffer won't be propagated to the original data pointer.<br>
1034         * If copy is false (see <a href="http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/clCreateBuffer.html">CL_MEM_USE_HOST_PTR</a>), then the provided data pointer will be used for storage of the OpenCL buffer. OpenCL might still cache the data in the OpenCL land, so careful use of {@link CLBuffer#map(CLQueue, CLMem.MapFlags, CLEvent...) CLBuffer#map(CLQueue, MapFlags, CLEvent...)} is then necessary to ensure the data is properly synchronized with the buffer. 
1035         * @param usage Usage intended for the pointer in OpenCL kernels : a pointer created with {@link CLMem.Usage#Input} cannot be written to in a kernel.
1036         * @param data Pointer to the initial values, must have known bounds (see {@link Pointer#getValidElements()}).
1037   * @param data Data buffer.
1038   * @param copy Whether to copy the input data.
1039   * @return A new buffer allocated on this context.
1040         */
1041        public CLBuffer<Double> createDoubleBuffer(CLMem.Usage usage,  DoubleBuffer  data, boolean copy) {
1042                return createBuffer(usage, Pointer.pointerToDoubles(data), copy);
1043        }
1044
1045    /**
1046  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateBuffer.html">clCreateBuffer</a>.<br>
1047     * Create a <code>CLBuffer&lt;Double&gt;</code> OpenCL buffer big enough to hold the valid  values of the provided data pointer.
1048     * @param usage Usage intended for the pointer in OpenCL kernels : a pointer created with {@link CLMem.Usage#Input} cannot be written to in a kernel.
1049     * @param data Host data to copy to the buffer
1050     * @return A new buffer allocated on this context.
1051   */
1052        public CLBuffer<Double> createDoubleBuffer(CLMem.Usage usage, Pointer<Double> data) {
1053                return createDoubleBuffer(usage, data, true);
1054        }
1055        /**
1056  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateBuffer.html">clCreateBuffer</a>.<br>
1057         * Create a <code>CLBuffer&lt;Double&gt;</code> OpenCL buffer  with the provided initial values.<br>
1058         * If copy is true (see <a href="http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/clCreateBuffer.html">CL_MEM_COPY_HOST_PTR</a>), then the buffer will be hosted in OpenCL and will have the best performance, but any change done to the OpenCL buffer won't be propagated to the original data pointer.<br>
1059         * If copy is false (see <a href="http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/clCreateBuffer.html">CL_MEM_USE_HOST_PTR</a>), then the provided data pointer will be used for storage of the OpenCL buffer. OpenCL might still cache the data in the OpenCL land, so careful use of {@link CLBuffer#map(CLQueue, CLMem.MapFlags, CLEvent...) CLBuffer#map(CLQueue, MapFlags, CLEvent...)} is then necessary to ensure the data is properly synchronized with the buffer. 
1060         * @param usage Usage intended for the pointer in OpenCL kernels : a pointer created with {@link CLMem.Usage#Input} cannot be written to in a kernel.
1061         * @param data Pointer to the initial values, must have known bounds (see {@link Pointer#getValidElements()}).
1062   * @param data Data buffer.
1063   * @param copy Whether to copy the input data.
1064   * @return A new buffer allocated on this context.
1065         */
1066        public CLBuffer<Double> createDoubleBuffer(CLMem.Usage usage, Pointer<Double> data, boolean copy) {
1067                return createBuffer(usage, data, copy);
1068        }
1069        
1070    /**
1071  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateBuffer.html">clCreateBuffer</a>.<br>
1072     * Create a <code>CLBuffer&lt;Double&gt;</code> OpenCL buffer big enough to hold 'length' values of type double.
1073     * @param usage Usage intended for the pointer in OpenCL kernels : a pointer created with {@link CLMem.Usage#Input} cannot be written to in a kernel.
1074    
1075   * @param elementCount Length of the buffer expressed in elements (for instance, a <code>CLBuffer&lt;Double&gt;</code> of length 10 will actually contain 10 * 8 bytes, as doubles are 8-bytes-long)
1076   * @return A new buffer allocated on this context.
1077   */
1078        public CLBuffer<Double> createDoubleBuffer(CLMem.Usage usage, long elementCount) {
1079                return createBuffer(usage, Double.class, elementCount);
1080        }
1081        
1082
1083        /**
1084  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateBuffer.html">clCreateBuffer</a>.<br>
1085         * Create an OpenCL buffer with the provided initial values, in copy mode (see <a href="http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/clCreateBuffer.html">CL_MEM_COPY_HOST_PTR</a>).
1086         * @param usage Usage intended for the pointer in OpenCL kernels : a pointer created with {@link CLMem.Usage#Input} cannot be written to in a kernel.
1087         * @param data Pointer to the initial values, must have known bounds (see {@link Pointer#getValidElements()})
1088         */
1089    public <T> CLBuffer<T> createBuffer(CLMem.Usage usage, Pointer<T> data) {
1090                return createBuffer(usage, data, true);
1091        }
1092        
1093        /**
1094  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateBuffer.html">clCreateBuffer</a>.<br>
1095         * Create a <code>CLBuffer&lt;N&gt;</code> OpenCL buffer  with the provided initial values.<br>
1096         * If copy is true (see <a href="http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/clCreateBuffer.html">CL_MEM_COPY_HOST_PTR</a>), then the buffer will be hosted in OpenCL and will have the best performance, but any change done to the OpenCL buffer won't be propagated to the original data pointer.<br>
1097         * If copy is false (see <a href="http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/clCreateBuffer.html">CL_MEM_USE_HOST_PTR</a>), then the provided data pointer will be used for storage of the OpenCL buffer. OpenCL might still cache the data in the OpenCL land, so careful use of {@link CLBuffer#map(CLQueue, CLMem.MapFlags, CLEvent...) CLBuffer#map(CLQueue, MapFlags, CLEvent...)} is then necessary to ensure the data is properly synchronized with the buffer. 
1098         * @param usage Usage intended for the pointer in OpenCL kernels : a pointer created with {@link CLMem.Usage#Input} cannot be written to in a kernel.
1099         * @param data Pointer to the initial values, must have known bounds (see {@link Pointer#getValidElements()}).
1100   * @param data Data buffer.
1101   * @param copy Whether to copy the input data.
1102   * @return A new buffer allocated on this context.
1103         */
1104    public <T> CLBuffer<T> createBuffer(CLMem.Usage usage, Pointer<T> data, boolean copy) {
1105        return createBuffer(data.getIO(), data, data.getValidBytes(), usage.getIntFlags() | (copy ? CL_MEM_COPY_HOST_PTR : CL_MEM_USE_HOST_PTR), copy);
1106        }
1107
1108    /**
1109  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateBuffer.html">clCreateBuffer</a>.<br>
1110     * Create a <code>CLBuffer&lt;N&gt;</code> OpenCL buffer big enough to hold 'length' values of type T.
1111     * @param usage Usage intended for the pointer in OpenCL kernels : a pointer created with {@link CLMem.Usage#Input} cannot be written to in a kernel.
1112   * @param elementClass Primitive type of the buffer. For instance a buffer of 'int' values can be created with elementClass being Integer.class or int.class indifferently. 
1113   * @param elementCount Length of the buffer expressed in elements 
1114   * @return A new buffer allocated on this context.
1115   */
1116    public <T> CLBuffer<T> createBuffer(CLMem.Usage usage, Class<T> elementClass, long elementCount) {
1117        PointerIO<T> io = PointerIO.getInstance(elementClass);
1118        if (io == null)
1119                throw new IllegalArgumentException("Unknown target type : " + elementClass.getName());
1120        return createBuffer(usage, io, elementCount);
1121        }
1122
1123        /**
1124  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateBuffer.html">clCreateBuffer</a>.<br>
1125         * Create an OpenCL buffer big enough to hold the provided amount of values of the specified type.
1126         * @param usage Usage intended for the pointer in OpenCL kernels : a pointer created with {@link CLMem.Usage#Input} cannot be written to in a kernel.
1127         * @param io Delegate responsible for reading and writing values.
1128         * @param elementCount Length of the buffer expressed in elements (for instance, a CLBuffer&lt;Integer&gt; of length 4 will actually contain 4 * 4 bytes, as ints are 4-bytes-long)
1129         * @deprecated Intended for advanced uses in conjunction with BridJ.
1130         */
1131    @Deprecated
1132    public <T> CLBuffer<T> createBuffer(CLMem.Usage usage, PointerIO<T> io, long elementCount) {
1133        return createBuffer(io, null, io.getTargetSize() * elementCount, usage.getIntFlags(), false);
1134        }
1135
1136        /**
1137  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateBuffer.html">clCreateBuffer</a>.<br>
1138        */
1139        @SuppressWarnings("deprecation")
1140        private <T> CLBuffer<T> createBuffer(PointerIO<T> io, Pointer<T> data, long byteCount, final int CLBufferFlags, final boolean retainBufferReference) {
1141        if (byteCount <= 0)
1142                        throw new IllegalArgumentException("Buffer size must be greater than zero (asked for size " + byteCount + ")");
1143                
1144                if (byteCount > getMaxMemAllocSize())
1145            throw new OutOfMemoryError("Requested size for buffer allocation is more than the maximum for this context : " + byteCount + " > " + getMaxMemAllocSize());
1146
1147        if (data != null) {
1148                        ByteOrder contextOrder = getByteOrder();
1149                        ByteOrder dataOrder = data.order();
1150                        if (contextOrder != null && !dataOrder.equals(contextOrder) && data.getTargetSize() > 1)
1151                                throw new IllegalArgumentException("Byte order of this context is " + contextOrder + ", but was given pointer to data with order " + dataOrder + ". Please create a pointer with correct byte order (Pointer.order(CLContext.getByteOrder())).");
1152                }
1153        
1154                                ReusablePointers ptrs = ReusablePointers.get();
1155                Pointer<Integer> pErr = ptrs.pErr;
1156                long mem;
1157                int previousAttempts = 0;
1158                do {
1159                        mem = CL.clCreateBuffer(
1160                                getEntity(),
1161                                CLBufferFlags,
1162                                byteCount,
1163                                getPeer(data),
1164                                getPeer(pErr));
1165                } while (failedForLackOfMemory(pErr.getInt(), previousAttempts++));
1166                return new CLBuffer<T>(this, byteCount, mem, retainBufferReference ? data : null, io);
1167        }
1168
1169    public ByteOrder getKernelsDefaultByteOrder() {
1170        if (kernelsDefaultByteOrder == null) {
1171                        ByteOrder order = null;
1172                        for (CLDevice device : getDevices()) {
1173                                ByteOrder devOrder = device.getKernelsDefaultByteOrder();
1174                                if (order != null && devOrder != order)
1175                                        return null;
1176                                order = devOrder;
1177                        }
1178                        kernelsDefaultByteOrder = order;
1179                }
1180        return kernelsDefaultByteOrder;
1181    }
1182
1183    private volatile ByteOrder byteOrder, kernelsDefaultByteOrder;
1184    
1185    /**
1186     * Get the endianness common to all devices of this context, or null if the devices have mismatching endiannesses.
1187     */
1188    public ByteOrder getByteOrder() {
1189        if (byteOrder == null) {
1190                        ByteOrder order = null;
1191                        for (CLDevice device : getDevices()) {
1192                                ByteOrder devOrder = device.getByteOrder();
1193                                if (order != null && devOrder != order)
1194                                        return null;
1195                                order = devOrder;
1196                        }
1197                        byteOrder = order;
1198                }
1199        return byteOrder;
1200    }
1201
1202    private volatile int addressBits = -2;
1203    
1204    /**
1205     * Return the number of bits used to represent a pointer on all of the context's devices, or -1 if not all devices use the same number of bits.<br>
1206     * Size of size_t type in OpenCL kernels can be obtained with getAddressBits() / 8.
1207     * @return -1 if the address bits of the context's devices do not match, common address bits otherwise
1208     */
1209    public int getAddressBits() {
1210        if (addressBits == -2) {
1211            synchronized (this) {
1212                if (addressBits == -2) {
1213                    for (CLDevice device : getDevices()) {
1214                        int bits = device.getAddressBits();
1215                        if (addressBits != -2 && bits != addressBits) {
1216                            addressBits = -1;
1217                            break;
1218                        }
1219                        addressBits = bits;
1220                    }
1221                }
1222            }
1223        }
1224        return addressBits;
1225    }
1226
1227    private volatile Boolean doubleSupported;
1228    
1229    /**
1230     * Whether all the devices in this context support any double-precision numbers (see {@link CLDevice#isDoubleSupported()}).
1231     */
1232    public boolean isDoubleSupported() {
1233        if (doubleSupported == null) {
1234                boolean supported = true;
1235                        for (CLDevice device : getDevices()) {
1236                                if (!device.isDoubleSupported()) {
1237                                        supported = false;
1238                                        break;
1239                                }
1240                        }
1241                        doubleSupported = supported;
1242                }
1243                return doubleSupported;
1244        }
1245        
1246        private volatile Boolean halfSupported;
1247    
1248    /**
1249     * Whether all the devices in this context support half-precision numbers (see {@link CLDevice#isHalfSupported()}).
1250     */
1251    public boolean isHalfSupported() {
1252                if (halfSupported == null) {
1253                boolean supported = true;
1254                        for (CLDevice device : getDevices()) {
1255                                if (!device.isHalfSupported()) {
1256                                        supported = false;
1257                                        break;
1258                                }
1259                        }
1260                        halfSupported = supported;
1261                }
1262                return halfSupported;
1263        }
1264        
1265        private volatile Boolean byteAddressableStoreSupported;
1266    
1267    public boolean isByteAddressableStoreSupported() {
1268        if (byteAddressableStoreSupported == null) {
1269                boolean supported = true;
1270                        for (CLDevice device : getDevices()) {
1271                                if (!device.isByteAddressableStoreSupported()) {
1272                                        supported = false;
1273                                        break;
1274                                }
1275                        }
1276                        byteAddressableStoreSupported = supported;
1277                }
1278                return byteAddressableStoreSupported;
1279        }
1280}