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;
051
052import com.nativelibs4java.util.EnumValue;
053import com.nativelibs4java.util.EnumValues;
054import com.nativelibs4java.opencl.library.OpenCLLibrary;
055import com.nativelibs4java.util.IOUtils;
056import com.nativelibs4java.util.NIOUtils;
057
058import static com.nativelibs4java.opencl.library.OpenCLLibrary.*;
059import static com.nativelibs4java.opencl.library.IOpenCLLibrary.*;
060import org.bridj.*;
061import static org.bridj.Pointer.*;
062
063import java.io.IOException;
064import java.nio.*;
065import static com.nativelibs4java.opencl.JavaCL.*;
066import static com.nativelibs4java.util.NIOUtils.*;
067import java.util.*;
068import static com.nativelibs4java.opencl.CLException.*;
069import com.nativelibs4java.util.ValuedEnum;
070import java.util.logging.Level;
071import java.util.logging.Logger;
072
073/**
074 * OpenCL device (CPU, GPU...).<br>
075 * Devices are retrieved from a CLPlatform through 
076 * {@link CLPlatform#listDevices(CLDevice.Type, boolean) },
077 * {@link CLPlatform#listAllDevices(boolean) },
078 * {@link CLPlatform#listCPUDevices(boolean) },
079 * {@link CLPlatform#listGPUDevices(boolean) }
080 */
081@SuppressWarnings("unused")
082public class CLDevice extends CLAbstractEntity {
083
084        protected static CLInfoGetter infos = new CLInfoGetter() {
085                @Override
086                protected int getInfo(long entity, int infoTypeEnum, long size, Pointer out, Pointer<SizeT> sizeOut) {
087                        return CL.clGetDeviceInfo(entity, infoTypeEnum, size, getPeer(out), getPeer(sizeOut));
088                }
089        };
090    
091    private volatile CLPlatform platform;
092    private volatile CLDevice parent;
093    private volatile boolean fetchedParent;
094    private final boolean needsRelease;
095
096    CLDevice(CLPlatform platform, long device) {
097                this(platform, null, device, false);
098    }
099    CLDevice(CLPlatform platform, CLDevice parent, long device, boolean needsRelease) {
100        super(device);
101        this.platform = platform;
102        this.needsRelease = needsRelease;
103        this.parent = parent;
104        this.fetchedParent = parent != null;
105    }
106    
107    public synchronized CLPlatform getPlatform() {
108        if (platform == null) {
109            Pointer pplat = infos.getPointer(getEntity(), CL_DEVICE_PLATFORM);
110            platform = new CLPlatform(getPeer(pplat));
111        }
112        return platform;
113    }
114
115        @Override
116        protected void clear() {
117                if (needsRelease)
118                        error(CL.clReleaseDevice(getEntity()));
119        }
120
121    public String createSignature() {
122        return getName() + "|" + getVendor() + "|" + getDriverVersion() + "|" + getProfile();
123    }
124    public static Map<String, List<CLDevice>> getDevicesBySignature(List<CLDevice> devices) {
125        Map<String, List<CLDevice>> ret = new HashMap<String, List<CLDevice>>();
126        for (CLDevice device : devices) {
127            String signature = device.createSignature();
128            List<CLDevice> list = ret.get(signature);
129            if (list == null)
130                ret.put(signature, list = new ArrayList<CLDevice>());
131            list.add(device);
132        }
133        return ret;
134    }
135
136    private volatile ByteOrder byteOrder;
137    public ByteOrder getByteOrder() {
138        if (byteOrder == null)
139                byteOrder = isEndianLittle() ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN;
140        return byteOrder;
141    }
142
143    private volatile ByteOrder kernelsDefaultByteOrder;
144    /**
145     * @deprecated Use {@link CLDevice#getByteOrder()}
146     */
147    @Deprecated
148    public synchronized ByteOrder getKernelsDefaultByteOrder() {
149        if (kernelsDefaultByteOrder == null) {
150                kernelsDefaultByteOrder = ByteOrderHack.guessByteOrderNeededForBuffers(this);
151        }
152        return kernelsDefaultByteOrder;
153    }
154
155    /** Bit values for CL_DEVICE_EXECUTION_CAPABILITIES */
156    public enum ExecutionCapability implements com.nativelibs4java.util.ValuedEnum {
157
158        Kernel(CL_EXEC_KERNEL),
159        NativeKernel(CL_EXEC_NATIVE_KERNEL);
160
161        ExecutionCapability(long value) { this.value = value; }
162        long value;
163        @Override
164        public long value() { return value; }
165        public static long getValue(EnumSet<ExecutionCapability> set) {
166            return EnumValues.getValue(set);
167        }
168
169        public static EnumSet<ExecutionCapability> getEnumSet(long v) {
170            return EnumValues.getEnumSet(v, ExecutionCapability.class);
171        }
172    }
173
174    /**
175     * Describes the execution capabilities of the device.<br>
176     * The mandated minimum capability is: Kernel.
177     */
178    @InfoName("CL_DEVICE_EXECUTION_CAPABILITIES")
179    public EnumSet<ExecutionCapability> getExecutionCapabilities() {
180        return ExecutionCapability.getEnumSet(infos.getIntOrLong(getEntity(), CL_DEVICE_EXECUTION_CAPABILITIES));
181    }
182
183    /** Bit values for CL_DEVICE_TYPE */
184    public enum Type implements com.nativelibs4java.util.ValuedEnum {
185
186        CPU(CL_DEVICE_TYPE_CPU),
187        GPU(CL_DEVICE_TYPE_GPU),
188        Accelerator(CL_DEVICE_TYPE_ACCELERATOR),
189        Default(CL_DEVICE_TYPE_DEFAULT),
190        All(CL_DEVICE_TYPE_ALL);
191
192        Type(long value) { this.value = value; }
193        long value;
194        @Override
195                public long value() { return value; }
196        
197        public static long getValue(EnumSet<Type> set) {
198            return EnumValues.getValue(set);
199        }
200
201        public static EnumSet<Type> getEnumSet(long v) {
202            return EnumValues.getEnumSet(v, Type.class);
203        }
204    }
205
206    /**
207     * The OpenCL device type.
208     */
209    @InfoName("CL_DEVICE_TYPE")
210    public EnumSet<Type> getType() {
211        return Type.getEnumSet(infos.getIntOrLong(getEntity(), CL_DEVICE_TYPE));
212    }
213
214    /**
215     * A unique device vendor identifier. <br>
216     * An example of a unique device identifier could be the PCIe ID.
217     */
218    @InfoName("CL_DEVICE_VENDOR_ID")
219    public int getVendorId() {
220        return infos.getInt(getEntity(), CL_DEVICE_VENDOR_ID);
221    }
222
223    /**
224     * The number of parallel compute cores on the OpenCL device. <br>
225     * The minimum value is 1.
226     */
227    @InfoName("CL_DEVICE_MAX_COMPUTE_UNITS")
228    public int getMaxComputeUnits() {
229        return infos.getInt(getEntity(), CL_DEVICE_MAX_COMPUTE_UNITS);
230    }
231
232    /**
233     * Maximum dimensions that specify the global and local work-item IDs used by the data parallel execution model. <br>
234     * (Refer to clEnqueueNDRangeKernel).
235     * <br>The minimum value is 3.
236     */
237    @InfoName("CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS")
238    public int getMaxWorkItemDimensions() {
239        return infos.getInt(getEntity(), CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS);
240    }
241
242    /**
243     * Maximum number of work-items that can be specified in each dimension of the work-group to clEnqueueNDRangeKernel.
244     */
245    @InfoName("CL_DEVICE_MAX_WORK_ITEM_SIZES")
246    public long[] getMaxWorkItemSizes() {
247        long sizes[] = infos.getNativeSizes(getEntity(), CL_DEVICE_MAX_WORK_ITEM_SIZES, getMaxWorkItemDimensions());
248        for (int i = 0, n = sizes.length; i < n; i++) {
249            long size = sizes[i];
250            if ((size & 0xffffffff00000000L) == 0xcccccccc00000000L)
251                sizes[i] = size & 0xffffffffL;
252        }
253        return sizes;
254    }
255
256    /**
257     * Maximum number of work-items in a work-group executing a kernel using the data parallel execution model.
258     * (Refer to clEnqueueNDRangeKernel). <br>
259     * The minimum value is 1.
260     */
261    @InfoName("CL_DEVICE_MAX_WORK_GROUP_SIZE")
262    public long getMaxWorkGroupSize() {
263        return infos.getIntOrLong(getEntity(), CL_DEVICE_MAX_WORK_GROUP_SIZE);
264    }
265
266    /**
267     * Maximum configured clock frequency of the device in MHz.
268     */
269    @InfoName("CL_DEVICE_MAX_CLOCK_FREQUENCY")
270    public int getMaxClockFrequency() {
271        return infos.getInt(getEntity(), CL_DEVICE_MAX_CLOCK_FREQUENCY);
272    }
273
274    /**
275     * The default compute device address space size specified as an unsigned integer value in bits. Currently supported values are 32 or 64 bits..<br>
276     * Size of size_t type in OpenCL kernels can be obtained with getAddressBits() / 8.
277     */
278    @InfoName("CL_DEVICE_ADDRESS_BITS")
279    public int getAddressBits() {
280        return infos.getInt(getEntity(), CL_DEVICE_ADDRESS_BITS);
281    }
282
283    /**
284     * Max size of memory object allocation in bytes. The minimum value is max (1/4th of CL_DEVICE_GLOBAL_MEM_SIZE , 128*1024*1024)
285     */
286    @InfoName("CL_DEVICE_MAX_MEM_ALLOC_SIZE")
287    public long getMaxMemAllocSize() {
288        return infos.getIntOrLong(getEntity(), CL_DEVICE_MAX_MEM_ALLOC_SIZE);
289    }
290
291    /**
292     * Is CL_TRUE if images are supported by the OpenCL device and CL_FALSE otherwise.
293     */
294    @InfoName("CL_DEVICE_IMAGE_SUPPORT")
295    public boolean hasImageSupport() {
296        return infos.getBool(getEntity(), CL_DEVICE_IMAGE_SUPPORT);
297    }
298
299    /**
300     * Max number of simultaneous image objects that can be read by a kernel. <br>
301     * The minimum value is 128 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE (@see hasImageSupport()).
302     */
303    @InfoName("CL_DEVICE_MAX_READ_IMAGE_ARGS")
304    public int getMaxReadImageArgs() {
305        return infos.getInt(getEntity(), CL_DEVICE_MAX_READ_IMAGE_ARGS);
306    }
307
308    /**
309     * Max number of simultaneous image objects that can be written to by a kernel. <br>
310     * The minimum value is 8 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE (@see hasImageSupport()).
311     */
312    @InfoName("CL_DEVICE_MAX_WRITE_IMAGE_ARGS")
313    public int getMaxWriteImageArgs() {
314        return infos.getInt(getEntity(), CL_DEVICE_MAX_WRITE_IMAGE_ARGS);
315    }
316
317    @Override
318    public String toString() {
319        return getName() + " (" + getPlatform().getName() + ")";
320    }
321
322    /**
323  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateCommandQueue.html">clCreateCommandQueue</a>.<br>
324     * Create an OpenCL execution queue on this device for the specified context.
325     * @param context context of the queue to create
326     * @return new OpenCL queue object
327     */
328    @SuppressWarnings("deprecation")
329    public CLQueue createQueue(CLContext context, QueueProperties... queueProperties) {
330                        ReusablePointers ptrs = ReusablePointers.get();
331                Pointer<Integer> pErr = ptrs.pErr;
332                long flags = 0;
333        for (QueueProperties prop : queueProperties)
334            flags |= prop.value();
335        long queue = CL.clCreateCommandQueue(context.getEntity(), getEntity(), flags, getPeer(pErr));
336                error(pErr.getInt());
337        return new CLQueue(context, queue, this);
338    }
339
340    /**
341  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateCommandQueue.html">clCreateCommandQueue</a>.<br>
342     */
343    @Deprecated
344    public CLQueue createQueue(EnumSet<QueueProperties> queueProperties, CLContext context) {
345                        ReusablePointers ptrs = ReusablePointers.get();
346                Pointer<Integer> pErr = ptrs.pErr;
347                long queue = CL.clCreateCommandQueue(context.getEntity(), getEntity(), QueueProperties.getValue(queueProperties), getPeer(pErr));
348                error(pErr.getInt());
349
350        return new CLQueue(context, queue, this);
351    }
352
353    public CLQueue createOutOfOrderQueue(CLContext context) {
354        return createQueue(EnumSet.of(QueueProperties.OutOfOrderExecModeEnable), context);
355    }
356
357    public CLQueue createProfilingQueue(CLContext context) {
358        return createQueue(EnumSet.of(QueueProperties.ProfilingEnable), context);
359    }
360
361    /**
362     * Max width of 2D image in pixels. <br>
363     * The minimum value is 8192 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.
364     */
365    @InfoName("CL_DEVICE_IMAGE2D_MAX_WIDTH")
366    public long getImage2DMaxWidth() {
367        return infos.getIntOrLong(getEntity(), CL_DEVICE_IMAGE2D_MAX_WIDTH);
368    }
369
370    /**
371     * Max height of 2D image in pixels. <br>
372     * The minimum value is 8192 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.
373     */
374    @InfoName("CL_DEVICE_IMAGE2D_MAX_HEIGHT")
375    public long getImage2DMaxHeight() {
376        return infos.getIntOrLong(getEntity(), CL_DEVICE_IMAGE2D_MAX_HEIGHT);
377    }
378
379    /**
380     * Max width of 3D image in pixels. <br>
381     * The minimum value is 2048 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.
382     */
383    @InfoName("CL_DEVICE_IMAGE3D_MAX_WIDTH")
384    public long getImage3DMaxWidth() {
385        return infos.getIntOrLong(getEntity(), CL_DEVICE_IMAGE3D_MAX_WIDTH);
386    }
387
388    /**
389     * Max height of 3D image in pixels. <br>
390     * The minimum value is 2048 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.
391     */
392    @InfoName("CL_DEVICE_IMAGE3D_MAX_HEIGHT")
393    public long getImage3DMaxHeight() {
394        return infos.getIntOrLong(getEntity(), CL_DEVICE_IMAGE3D_MAX_HEIGHT);
395    }
396
397    /**
398     * Max depth of 3D image in pixels. <br>
399     * The minimum value is 2048 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.
400     */
401    @InfoName("CL_DEVICE_IMAGE3D_MAX_DEPTH")
402    public long getImage3DMaxDepth() {
403        return infos.getIntOrLong(getEntity(), CL_DEVICE_IMAGE3D_MAX_DEPTH);
404    }
405
406    /**
407     * Maximum number of samplers that can be used in a kernel. <br>
408     * Refer to section 6.11.8 for a detailed description on samplers. <br>
409     * The minimum value is 16 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.
410     */
411    @InfoName("CL_DEVICE_MAX_SAMPLERS")
412    public int getMaxSamplers() {
413        return infos.getInt(getEntity(), CL_DEVICE_MAX_SAMPLERS);
414    }
415
416    /**
417     * Max size in bytes of the arguments that can be passed to a kernel. <br>
418     * The minimum value is 256.
419     */
420    @InfoName("CL_DEVICE_MAX_PARAMETER_SIZE")
421    public long getMaxParameterSize() {
422        return infos.getIntOrLong(getEntity(), CL_DEVICE_MAX_PARAMETER_SIZE);
423    }
424
425    /**
426     * Describes the alignment in bits of the base address of any allocated memory object.
427     */
428    @InfoName("CL_DEVICE_MEM_BASE_ADDR_ALIGN")
429    public int getMemBaseAddrAlign() {
430        return infos.getInt(getEntity(), CL_DEVICE_MEM_BASE_ADDR_ALIGN);
431    }
432
433    /**
434     * The smallest alignment in bytes which can be used for any data type.
435     */
436    @InfoName("CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE")
437    public int getMinDataTypeAlign() {
438        return infos.getInt(getEntity(), CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE);
439    }
440
441    /**
442     * Describes single precision floating- point capability of the device.<br>
443     * The mandated minimum floating-point capability is: RoundToNearest and InfNaN.
444     */
445    @InfoName("CL_DEVICE_SINGLE_FP_CONFIG")
446    public EnumSet<FpConfig> getSingleFPConfig() {
447        return FpConfig.getEnumSet(infos.getIntOrLong(getEntity(), CL_DEVICE_SINGLE_FP_CONFIG));
448    }
449
450    /** Values for CL_DEVICE_GLOBAL_MEM_CACHE_TYPE */
451    public enum GlobalMemCacheType implements com.nativelibs4java.util.ValuedEnum {
452
453        None(CL_NONE),
454        ReadOnlyCache(CL_READ_ONLY_CACHE),
455        ReadWriteCache(CL_READ_WRITE_CACHE);
456
457        GlobalMemCacheType(long value) { this.value = value; }
458        long value;
459        @Override
460                public long value() { return value; }
461        
462        public static GlobalMemCacheType getEnum(long v) {
463            return EnumValues.getEnum(v, GlobalMemCacheType.class);
464        }
465    }
466
467    /**
468     * Type of global memory cache supported.
469     */
470    @InfoName("CL_DEVICE_GLOBAL_MEM_CACHE_TYPE")
471    public GlobalMemCacheType getGlobalMemCacheType() {
472        return GlobalMemCacheType.getEnum(infos.getInt(getEntity(), CL_DEVICE_GLOBAL_MEM_CACHE_TYPE));
473    }
474
475    /**
476     * Size of global memory cache line in bytes.
477     */
478    @InfoName("CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE")
479    public int getGlobalMemCachelineSize() {
480        return infos.getInt(getEntity(), CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE);
481    }
482
483    /**
484     * Size of global memory cache in bytes.
485     */
486    @InfoName("CL_DEVICE_GLOBAL_MEM_CACHE_SIZE")
487    public long getGlobalMemCacheSize() {
488        return infos.getIntOrLong(getEntity(), CL_DEVICE_GLOBAL_MEM_CACHE_SIZE);
489    }
490
491    /**
492     * Size of global device memory in bytes.
493     */
494    @InfoName("CL_DEVICE_GLOBAL_MEM_SIZE")
495    public long getGlobalMemSize() {
496        return infos.getIntOrLong(getEntity(), CL_DEVICE_GLOBAL_MEM_SIZE);
497    }
498
499    /**
500     * Max size in bytes of a constant buffer allocation. <br>
501     * The minimum value is 64 KB.
502     */
503    @InfoName("CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE")
504    public long getMaxConstantBufferSize() {
505        return infos.getIntOrLong(getEntity(), CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE);
506    }
507
508    /**
509     * Max number of arguments declared with the __constant qualifier in a kernel. <br>
510     * The minimum value is 8.
511     */
512    @InfoName("CL_DEVICE_MAX_CONSTANT_ARGS")
513    public int getMaxConstantArgs() {
514        return infos.getInt(getEntity(), CL_DEVICE_MAX_CONSTANT_ARGS);
515    }
516
517    /** Values for CL_DEVICE_LOCAL_MEM_TYPE */
518    public enum LocalMemType implements com.nativelibs4java.util.ValuedEnum {
519
520        /** implying dedicated local memory storage such as SRAM */
521        Local(CL_LOCAL),
522        Global(CL_GLOBAL);
523
524        LocalMemType(long value) { this.value = value; }
525        long value;
526        @Override
527                public long value() { return value; }
528        
529        public static LocalMemType getEnum(long v) {
530            return EnumValues.getEnum(v, LocalMemType.class);
531        }
532    }
533
534    /**
535     * Type of local memory supported. <br>
536     */
537    @InfoName("CL_DEVICE_LOCAL_MEM_TYPE")
538    public LocalMemType getLocalMemType() {
539        return LocalMemType.getEnum(infos.getInt(getEntity(), CL_DEVICE_LOCAL_MEM_TYPE));
540    }
541
542    /**
543     * Size of local memory arena in bytes. <br>
544     * The minimum value is 16 KB.
545     */
546    @InfoName("CL_DEVICE_LOCAL_MEM_SIZE")
547    public long getLocalMemSize() {
548        return infos.getIntOrLong(getEntity(), CL_DEVICE_LOCAL_MEM_SIZE);
549    }
550
551    /**
552     * Is CL_TRUE if the device implements error correction for the memories, caches, registers etc. in the device. <br>
553     * Is CL_FALSE if the device does not implement error correction. <br>
554     * This can be a requirement for certain clients of OpenCL.
555     */
556    @InfoName("CL_DEVICE_ERROR_CORRECTION_SUPPORT")
557    public boolean hasErrorCorrectionSupport() {
558        return infos.getBool(getEntity(), CL_DEVICE_ERROR_CORRECTION_SUPPORT);
559    }
560
561    /**
562     * Maximum size of the internal buffer that holds the output of printf calls from a kernel.
563     * The minimum value for the FULL profile is 1 MB. 
564     */
565    @InfoName("CL_DEVICE_PRINTF_BUFFER_SIZE")
566    public long getPrintfBufferSize() {
567        return infos.getIntOrLong(getEntity(), CL_DEVICE_PRINTF_BUFFER_SIZE);
568    }
569
570    /**
571     * Is CL_TRUE if the device’s preference is for the user to be responsible for synchronization, when sharing memory objects between OpenCL and other APIs such as DirectX, CL_FALSE if the device / implementation has a performant path for performing synchronization of memory object shared between OpenCL and other APIs such as DirectX. 
572     */
573    @InfoName("CL_DEVICE_PREFERRED_INTEROP_USER_SYNC")
574    public boolean isPreferredInteropUserSync() {
575        return infos.getBool(getEntity(), CL_DEVICE_PREFERRED_INTEROP_USER_SYNC);
576    }
577    
578    @InfoName("Out of order queues support")
579    public boolean hasOutOfOrderQueueSupport() {
580                CLContext context = getPlatform().createContext(null, this);
581                CLQueue queue = null;
582                try {
583                        queue = createOutOfOrderQueue(context);
584                        return true;
585                } catch (CLException ex) {
586                        return false;
587                } finally {
588                        if (queue != null)
589                                queue.release();
590                        context.release();
591                }
592    }
593
594    /**
595     * Describes the resolution of device timer. <br>
596     * This is measured in nanoseconds. <br>
597     * Refer to section 5.9 for details.
598     */
599    @InfoName("CL_DEVICE_PROFILING_TIMER_RESOLUTION")
600    public long getProfilingTimerResolution() {
601        return infos.getIntOrLong(getEntity(), CL_DEVICE_PROFILING_TIMER_RESOLUTION);
602    }
603
604    /**
605     * Is CL_TRUE if the OpenCL device is a little endian device and CL_FALSE otherwise.
606     */
607    @InfoName("CL_DEVICE_ENDIAN_LITTLE")
608    public boolean isEndianLittle() {
609        return infos.getBool(getEntity(), CL_DEVICE_ENDIAN_LITTLE);
610    }
611
612    /**
613     * Is CL_TRUE if the device is available and CL_FALSE if the device is not available.
614     */
615    @InfoName("CL_DEVICE_AVAILABLE")
616    public boolean isAvailable() {
617        return infos.getBool(getEntity(), CL_DEVICE_AVAILABLE);
618    }
619
620    /**
621     * Is CL_FALSE if the implementation does not have a compiler available to compile the program source. <br>
622     * Is CL_TRUE if the compiler is available.<br>
623     * This can be CL_FALSE for the embededed platform profile only.
624     */
625    @InfoName("CL_DEVICE_COMPILER_AVAILABLE")
626    public boolean isCompilerAvailable() {
627        return infos.getBool(getEntity(), CL_DEVICE_COMPILER_AVAILABLE);
628    }
629
630    /**
631    Device name string.
632     */
633    @InfoName("CL_DEVICE_NAME")
634    public String getName() {
635        return infos.getString(getEntity(), CL_DEVICE_NAME);
636    }
637
638    /**
639     * OpenCL C version string. <br>
640     * Returns the highest OpenCL C version supported by the compiler for this device. <br>
641     * This version string has the following format:<br>
642     *  OpenCL&lt;space&gt;C&lt;space&gt;&lt;major_version.minor_version&gt;&lt;space&gt;&lt;vendor-specific information&gt;<br>
643     *  The major_version.minor_version value returned must be 1.1 if CL_DEVICE_VERSION is OpenCL 1.1.<br>
644     *  The major_version.minor_version value returned can be 1.0 or 1.1 if CL_DEVICE_VERSION is OpenCL 1.0. <br>
645     *  If OpenCL C 1.1 is returned, this implies that the language feature set defined in section 6 of the OpenCL 1.1 specification is supported by the OpenCL 1.0 device.
646     *  @since OpenCL 1.1
647     */
648    @InfoName("CL_DEVICE_OPENCL_C_VERSION")
649    public String getOpenCLCVersion() {
650        try {
651                return infos.getString(getEntity(), CL_DEVICE_OPENCL_C_VERSION);
652        } catch (Throwable th) {
653                // TODO throw if supposed to handle OpenCL 1.1
654                return "OpenCL C 1.0";
655        }
656    }
657    /**
658     * @deprecated Legacy typo, use getOpenCLCVersion() instead.
659     */
660    @Deprecated
661    public String getOpenCLVersion() {
662        return getOpenCLCVersion();
663    }
664
665    /**
666    Vendor name string.
667     */
668    @InfoName("CL_DEVICE_VENDOR")
669    public String getVendor() {
670        return infos.getString(getEntity(), CL_DEVICE_VENDOR);
671    }
672
673        /**
674         * Floating-point config of a device.
675         * The mandated minimum floating-point capability for devices that are not of type CL_DEVICE_TYPE_CUSTOM is:
676         * CL_FP_ROUND_TO_NEAREST | CL_FP_INF_NAN.
677         */
678        public enum FpConfig implements com.nativelibs4java.util.ValuedEnum {
679                /**
680                 * Denorms are supported.
681                 */
682                Denorm(CL_FP_DENORM),
683                /**
684                 * INF and quiet NaNs are supported.
685                 */
686                InfNan(CL_FP_INF_NAN),
687                /**
688                 * Round to nearest even rounding mode supported.
689                 */
690                RoundToNearest(CL_FP_ROUND_TO_NEAREST),
691                /**
692                 * Round to zero rounding mode supported.
693                 */
694                RoundToZero(CL_FP_ROUND_TO_ZERO),
695                /**
696                 * Round to positive and negative infinity rounding modes supported.
697                 */
698                RoundToInf(CL_FP_ROUND_TO_INF),
699                /**
700                 * IEEE754-2008 fused multiply- add is supported.
701                 */
702                FMA(CL_FP_FMA),
703                /**
704                 * Divide and sqrt are correctly rounded as defined by the IEEE754 specification.
705                 */
706                CorrectlyRoundedDivideSqrt(CL_FP_CORRECTLY_ROUNDED_DIVIDE_SQRT),
707                /**
708                 * Basic floating-point operations (such as addition, subtraction, multiplication).
709                 * are implemented in software.
710                 */
711                SoftFloat(CL_FP_SOFT_FLOAT);
712
713        FpConfig(long value) { this.value = value; }
714        long value;
715        @Override
716        public long value() { return value; }
717        public static long getValue(EnumSet<FpConfig> set) {
718            return EnumValues.getValue(set);
719        }
720
721        public static EnumSet<FpConfig> getEnumSet(long v) {
722            return EnumValues.getEnumSet(v, FpConfig.class);
723        }
724    }
725
726
727    /**
728    OpenCL software driver version string in the form major_number.minor_number.
729     */
730    @InfoName("CL_DRIVER_VERSION")
731    public String getDriverVersion() {
732        return infos.getString(getEntity(), CL_DRIVER_VERSION);
733    }
734
735        /** TODO */
736    @InfoName("CL_DEVICE_IMAGE_MAX_ARRAY_SIZE")
737    public long getImageMaxArraySize() {
738        return infos.getIntOrLong(getEntity(), CL_DEVICE_IMAGE_MAX_ARRAY_SIZE);
739    }
740
741        /** TODO */
742    @InfoName("CL_DEVICE_IMAGE_MAX_BUFFER_SIZE")
743    public long getImageMaxBufferSize() {
744        return infos.getIntOrLong(getEntity(), CL_DEVICE_IMAGE_MAX_BUFFER_SIZE);
745    }
746
747        /** TODO */
748    @InfoName("CL_DEVICE_DOUBLE_FP_CONFIG")
749    public EnumSet<FpConfig> getDoubleFpConfig() {
750        return isDoubleSupported() ? FpConfig.getEnumSet(infos.getIntOrLong(getEntity(), CL_DEVICE_DOUBLE_FP_CONFIG)) : EnumSet.noneOf(FpConfig.class);
751    }
752
753        /** TODO */
754    @InfoName("CL_DEVICE_HALF_FP_CONFIG")
755    public EnumSet<FpConfig> getHalfFpConfig() {
756        return isHalfSupported() ? FpConfig.getEnumSet(infos.getIntOrLong(getEntity(), CL_DEVICE_HALF_FP_CONFIG)) : EnumSet.noneOf(FpConfig.class);
757    }
758
759        /** TODO */
760    @InfoName("CL_DEVICE_LINKER_AVAILABLE")
761    public boolean isLinkerAvailable() {
762        return infos.getBool(getEntity(), CL_DEVICE_LINKER_AVAILABLE);
763    }
764
765        /** TODO */
766    @InfoName("CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF")
767    public long getNativeVectorWidthHalf() {
768        return infos.getIntOrLong(getEntity(), CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF);
769    }
770
771    /** Device partition types. */
772    public enum PartitionType implements com.nativelibs4java.util.ValuedEnum {
773        Equally(CL_DEVICE_PARTITION_EQUALLY),
774        ByCounts(CL_DEVICE_PARTITION_BY_COUNTS),
775        ByAffinityDomain(CL_DEVICE_PARTITION_BY_AFFINITY_DOMAIN);
776
777        PartitionType(long value) { this.value = value; }
778        long value;
779        @Override
780        public long value() { return value; }
781        public static long getValue(EnumSet<PartitionType> set) {
782            return EnumValues.getValue(set);
783        }
784
785        public static EnumSet<PartitionType> getEnumSet(long v) {
786            return EnumValues.getEnumSet(v, PartitionType.class);
787        }
788    }
789
790        /** TODO */
791    @InfoName("CL_DEVICE_PARTITION_PROPERTIES")
792    public EnumSet<PartitionType> getPartitionProperties() {
793        return PartitionType.getEnumSet(infos.getIntOrLong(getEntity(), CL_DEVICE_PARTITION_PROPERTIES));
794    }
795
796        /** TODO */
797    @InfoName("CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF")
798    public long getPreferredVectorWidthHalf() {
799        return infos.getIntOrLong(getEntity(), CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF);
800    }
801
802        /** TODO */
803    @InfoName("CL_DEVICE_REFERENCE_COUNT")
804    public long getReferenceCount() {
805        return infos.getIntOrLong(getEntity(), CL_DEVICE_REFERENCE_COUNT);
806    }
807
808    /**
809     * Affinity domain specified in {@link #createSubDevicesByAffinity(AffinityDomain)}, or null if the device is not a sub-device or wasn't split by affinity.
810     * This returns part of CL_DEVICE_PARTITION_TYPE.
811     */
812    public AffinityDomain getPartitionAffinityDomain() {
813        Pointer<?> memory = infos.getMemory(getEntity(), CL_DEVICE_PARTITION_TYPE);
814        long type = memory.getSizeT();
815        if (type != CL_DEVICE_PARTITION_BY_AFFINITY_DOMAIN) {
816                return null;
817        }
818        AffinityDomain affinityDomain = AffinityDomain.getEnum(memory.getSizeTAtIndex(1));
819        return affinityDomain;
820    }
821
822
823    /**
824     * Returns the cl_device_id of the parent device to which this sub-device belongs. If device is a root-level device, a NULL value is returned.
825         */
826    public synchronized CLDevice getParent() {
827        if (!fetchedParent) {
828            Pointer ptr = infos.getPointer(getEntity(), CL_DEVICE_PARENT_DEVICE);
829            if (ptr != null) {
830                parent = new CLDevice(platform, null, getPeer(ptr), false);
831            }
832            fetchedParent = true;
833        }
834        return parent;
835    }
836
837
838    /**
839     * OpenCL profile string. <br>
840     * Returns the profile name supported by the device. <br>
841     * The profile name returned can be one of the following strings:
842     * <ul>
843     * <li>FULL_PROFILE if the device supports the OpenCL specification (functionality defined as part of the core specification and does not require any extensions to be supported).</li>
844     * <li>EMBEDDED_PROFILE if the device supports the OpenCL embedded profile.</li>
845     * </ul>
846     */
847    @InfoName("CL_DEVICE_PROFILE")
848    public String getProfile() {
849        return infos.getString(getEntity(), CL_DEVICE_PROFILE);
850    }
851
852    /**
853     * Whether the device and the host have a unified memory subsystem.
854     * @since OpenCL 1.1
855     */
856    @InfoName("CL_DEVICE_HOST_UNIFIED_MEMORY")
857    public boolean isHostUnifiedMemory() {
858                platform.requireMinVersionValue("CL_DEVICE_HOST_UNIFIED_MEMORY", 1.1);
859                return infos.getBool(getEntity(), CL_DEVICE_HOST_UNIFIED_MEMORY);
860    }
861    
862    /**
863     * Preferred native vector width size for built-in scalar types that can be put into vectors. <br>
864     * The vector width is defined as the number of scalar elements that can be stored in the vector. <br>
865     * If the cl_khr_fp64 extension is not supported, CL_DEVICE_PREFERRED_VECTOR_WID TH_DOUBLE must return 0.
866     */
867    @InfoName("CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR")
868    public int getPreferredVectorWidthChar() {
869        return infos.getInt(getEntity(), CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR);
870    }
871
872    /**
873     * Preferred native vector width size for built-in scalar types that can be put into vectors. <br>
874     * The vector width is defined as the number of scalar elements that can be stored in the vector. <br>
875     * If the cl_khr_fp64 extension is not supported, CL_DEVICE_PREFERRED_VECTOR_WID TH_DOUBLE must return 0.
876     */
877    @InfoName("CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT")
878    public int getPreferredVectorWidthShort() {
879        return infos.getInt(getEntity(), CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT);
880    }
881
882    /**
883     * Preferred native vector width size for built-in scalar types that can be put into vectors. <br>
884     * The vector width is defined as the number of scalar elements that can be stored in the vector. <br>
885     * If the cl_khr_fp64 extension is not supported, CL_DEVICE_PREFERRED_VECTOR_WID TH_DOUBLE must return 0.
886     */
887    @InfoName("CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT")
888    public int getPreferredVectorWidthInt() {
889        return infos.getInt(getEntity(), CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT);
890    }
891
892    /**
893     * Preferred native vector width size for built-in scalar types that can be put into vectors. <br>
894     * The vector width is defined as the number of scalar elements that can be stored in the vector. <br>
895     * If the cl_khr_fp64 extension is not supported, CL_DEVICE_PREFERRED_VECTOR_WID TH_DOUBLE must return 0.
896     */
897    @InfoName("CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG")
898    public int getPreferredVectorWidthLong() {
899        return infos.getInt(getEntity(), CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG);
900    }
901
902    /**
903     * Preferred native vector width size for built-in scalar types that can be put into vectors. <br>
904     * The vector width is defined as the number of scalar elements that can be stored in the vector. <br>
905     * If the cl_khr_fp64 extension is not supported, CL_DEVICE_PREFERRED_VECTOR_WID TH_DOUBLE must return 0.
906     */
907    @InfoName("CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT")
908    public int getPreferredVectorWidthFloat() {
909        return infos.getInt(getEntity(), CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT);
910    }
911
912    /**
913     * Preferred native vector width size for built-in scalar types that can be put into vectors. <br>
914     * The vector width is defined as the number of scalar elements that can be stored in the vector. <br>
915     * If the cl_khr_fp64 extension is not supported, CL_DEVICE_PREFERRED_VECTOR_WID TH_DOUBLE must return 0.
916     */
917    @InfoName("CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE")
918    public int getPreferredVectorWidthDouble() {
919        return infos.getInt(getEntity(), CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE);
920    }
921    
922    /**
923     * Returns the native ISA vector width. <br>
924     * The vector width is defined as the number of scalar elements that can be stored in the vector. <br>
925     * If the cl_khr_fp64 extension is not supported, CL_DEVICE_NATIVE_VECTOR_WID TH_DOUBLE must return 0.
926     */
927    @InfoName("CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR")
928    public int getNativeVectorWidthChar() {
929        return infos.getOptionalFeatureInt(getEntity(), CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR);
930    }
931
932    /**
933     * Returns the native ISA vector width. <br>
934     * The vector width is defined as the number of scalar elements that can be stored in the vector. <br>
935     * If the cl_khr_fp64 extension is not supported, CL_DEVICE_NATIVE_VECTOR_WID TH_DOUBLE must return 0.
936     */
937    @InfoName("CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT")
938    public int getNativeVectorWidthShort() {
939        return infos.getOptionalFeatureInt(getEntity(), CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT);
940    }
941
942    /**
943     * Returns the native ISA vector width. <br>
944     * The vector width is defined as the number of scalar elements that can be stored in the vector. <br>
945     * If the cl_khr_fp64 extension is not supported, CL_DEVICE_NATIVE_VECTOR_WID TH_DOUBLE must return 0.
946     */
947    @InfoName("CL_DEVICE_NATIVE_VECTOR_WIDTH_INT")
948    public int getNativeVectorWidthInt() {
949        return infos.getOptionalFeatureInt(getEntity(), CL_DEVICE_NATIVE_VECTOR_WIDTH_INT);
950    }
951
952    /**
953     * Returns the native ISA vector width. <br>
954     * The vector width is defined as the number of scalar elements that can be stored in the vector. <br>
955     * If the cl_khr_fp64 extension is not supported, CL_DEVICE_NATIVE_VECTOR_WID TH_DOUBLE must return 0.
956     */
957    @InfoName("CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG")
958    public int getNativeVectorWidthLong() {
959        return infos.getOptionalFeatureInt(getEntity(), CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG);
960    }
961
962    /**
963     * Returns the native ISA vector width. <br>
964     * The vector width is defined as the number of scalar elements that can be stored in the vector. <br>
965     * If the cl_khr_fp64 extension is not supported, CL_DEVICE_NATIVE_VECTOR_WID TH_DOUBLE must return 0.
966     */
967    @InfoName("CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT")
968    public int getNativeVectorWidthFloat() {
969        return infos.getOptionalFeatureInt(getEntity(), CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT);
970    }
971
972    /**
973     * Returns the native ISA vector width. <br>
974     * The vector width is defined as the number of scalar elements that can be stored in the vector. <br>
975     * If the cl_khr_fp64 extension is not supported, CL_DEVICE_NATIVE_VECTOR_WID TH_DOUBLE must return 0.
976     */
977    @InfoName("CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE")
978    public int getNativeVectorWidthDouble() {
979        return infos.getOptionalFeatureInt(getEntity(), CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE);
980    }
981
982    /**
983     * OpenCL version string. <br>
984     * Returns the OpenCL version supported by the device.<br>
985     * This version string has the following format:
986     * <code>
987     * OpenCL&lt;space&gt;&lt;major_version.min or_version&gt;&lt;space&gt;&lt;vendor-specific information&gt;
988     * </code>
989     * The major_version.minor_version value returned will be 1.0.
990     */
991    @InfoName("CL_DEVICE_VERSION")
992    public String getVersion() {
993        return infos.getString(getEntity(), CL_DEVICE_VERSION);
994    }
995
996    /**
997     * List of extension names supported by the device.
998     * The list of extension names returned can be vendor supported extension names and one or more of the following Khronos approved extension names:
999     * - cl_khr_int64_base_atomics
1000     * - cl_khr_int64_extended_atomics
1001     * - cl_khr_fp16
1002     * - cl_khr_gl_sharing
1003     * - cl_khr_gl_event
1004     * - cl_khr_d3d10_sharing
1005     * - cl_khr_dx9_media_sharing
1006     * - cl_khr_d3d11_sharing
1007     *
1008     * The following approved Khronos extension names must be returned by all device that support OpenCL C 1.2:
1009     * - cl_khr_global_int32_base_atomics
1010     * - cl_khr_global_int32_extended_atomics
1011     * - cl_khr_local_int32_base_atomics
1012     * - cl_khr_local_int32_extended_atomics
1013     * - cl_khr_byte_addressable_store
1014     * - cl_khr_fp64 (for backward compatibility if double precision is supported)
1015         * Please refer to the OpenCL 1.2 Extension Specification for a detailed description of these extensions.
1016     */
1017    @InfoName("CL_DEVICE_EXTENSIONS")
1018    public String[] getExtensions() {
1019        if (extensions == null) {
1020            extensions = new LinkedHashSet<String>(Arrays.asList(infos.getString(getEntity(), CL_DEVICE_EXTENSIONS).split("\\s+")));
1021        }
1022        return extensions.toArray(new String[extensions.size()]);
1023    }
1024    private Set<String> extensions;
1025
1026    public boolean hasExtension(String name) {
1027        getExtensions();
1028        return extensions.contains(name.trim());
1029    }
1030
1031    /**
1032     * List of built-in kernels supported by the device.
1033     */
1034    @InfoName("CL_DEVICE_BUILT_IN_KERNELS")
1035    public String[] getBuiltInKernels() {
1036        if (buildInKernels == null) {
1037            buildInKernels = new LinkedHashSet<String>(Arrays.asList(infos.getString(getEntity(), CL_DEVICE_BUILT_IN_KERNELS).split(";")));
1038        }
1039        return buildInKernels.toArray(new String[buildInKernels.size()]);
1040    }
1041    private Set<String> buildInKernels;
1042
1043    /**
1044     * Whether this device support any double-precision number extension (<a href="http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/cl_khr_fp64.html">cl_khr_fp64</a> or <a href="http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/cl_amd_fp64.html">cl_amd_fp64</a>)
1045     */
1046    public boolean isDoubleSupported() {
1047        return isDoubleSupportedKHR() || isDoubleSupportedAMD();
1048    }
1049
1050    /**
1051     * Whether this device support the <a href="http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/cl_khr_fp64.html">cl_khr_fp64</a> double-precision number extension
1052     */
1053    public boolean isDoubleSupportedKHR() {
1054        return hasExtension("cl_khr_fp64");
1055    }
1056
1057    /**
1058     * Whether this device supports the <a href="http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/cl_amd_fp64.html">cl_amd_fp64</a> double-precision number extension
1059     */
1060    public boolean isDoubleSupportedAMD() {
1061        return hasExtension("cl_amd_fp64");
1062    }
1063
1064    /**
1065     * If this device supports the extension cl_amd_fp64 but not cl_khr_fp64, replace any OpenCL source code pragma of the style <code>#pragma OPENCL EXTENSION cl_khr_fp64 : enable</code> by <code>#pragma OPENCL EXTENSION cl_amd_fp64 : enable</code>.<br>
1066     * Also works the other way around (if the KHR extension is available but the source code refers to the AMD extension).<br>
1067     * This method is called automatically by CLProgram unless the javacl.adjustDoubleExtension property is set to false or the JAVACL_ADJUST_DOUBLE_EXTENSION is set to 0.
1068     */
1069    public String replaceDoubleExtensionByExtensionActuallyAvailable(String kernelSource) {
1070        boolean hasKHR = isDoubleSupportedKHR(), hasAMD = isDoubleSupportedAMD();
1071        if (hasAMD && !hasKHR)
1072                        kernelSource = kernelSource.replaceAll("#pragma\\s+OPENCL\\s+EXTENSION\\s+cl_khr_fp64\\s*:\\s*enable", "#pragma OPENCL EXTENSION cl_amd_fp64 : enable");
1073                else if (!hasAMD && hasKHR)
1074                        kernelSource = kernelSource.replaceAll("#pragma\\s+OPENCL\\s+EXTENSION\\s+cl_amd_fp64\\s*:\\s*enable", "#pragma OPENCL EXTENSION cl_khr_fp64 : enable");
1075                return kernelSource;
1076    }
1077    
1078    /**
1079     * Whether this device supports the <a href="http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/cl_khr_fp16.html">cl_khr_fp16 extension</a>.
1080     */
1081    public boolean isHalfSupported() {
1082        return hasExtension("cl_khr_fp16");
1083    }
1084
1085    /**
1086     * Whether this device supports the <a href="http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/cl_khr_byte_addressable_store.html">cl_khr_byte_addressable_store extension</a>.
1087     */
1088    public boolean isByteAddressableStoreSupported() {
1089        return hasExtension("cl_khr_byte_addressable_store");
1090    }
1091
1092    /**
1093     * Whether this device supports any OpenGL sharing extension (<a href="http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/cl_khr_gl_sharing.html">cl_khr_gl_sharing</a> or <a href="http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/cl_APPLE_gl_sharing.html">cl_APPLE_gl_sharing</a>)
1094     */
1095    public boolean isGLSharingSupported() {
1096        return hasExtension("cl_khr_gl_sharing") || hasExtension("cl_APPLE_gl_sharing");
1097    }
1098        /**
1099     * Whether this device supports the <a href="http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/cl_khr_global_int32_base_atomics.html">cl_khr_global_int32_base_atomics extension</a>.
1100     */
1101    public boolean isGlobalInt32BaseAtomicsSupported() {
1102        return hasExtension("cl_khr_global_int32_base_atomics");
1103    }
1104    /**
1105     * Whether this device supports the <a href="http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/cl_khr_global_int32_extended_atomics.html">cl_khr_global_int32_extended_atomics extension</a>.
1106     */
1107    public boolean isGlobalInt32ExtendedAtomicsSupported() {
1108        return hasExtension("cl_khr_global_int32_extended_atomics");
1109    }
1110    /**
1111     * Whether this device supports the <a href="http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/cl_khr_local_int32_base_atomics.html">cl_khr_local_int32_base_atomics extension</a>.
1112     */
1113    public boolean isLocalInt32BaseAtomicsSupported() {
1114        return hasExtension("cl_khr_local_int32_base_atomics");
1115    }
1116    /**
1117     * Whether this device supports the <a href="http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/cl_khr_local_int32_extended_atomics.html">cl_khr_local_int32_extended_atomics extension</a>.
1118     */
1119    public boolean isLocalInt32ExtendedAtomicsSupported() {
1120        return hasExtension("cl_khr_local_int32_extended_atomics");
1121    }
1122
1123    /** Bit values for CL_DEVICE_QUEUE_PROPERTIES */
1124    public static enum QueueProperties implements com.nativelibs4java.util.ValuedEnum {
1125
1126        OutOfOrderExecModeEnable(CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE),
1127        ProfilingEnable(CL_QUEUE_PROFILING_ENABLE);
1128
1129        QueueProperties(long value) { this.value = value; }
1130        long value;
1131        @Override
1132                public long value() { return value; }
1133        
1134        public static long getValue(EnumSet<QueueProperties> set) {
1135            return EnumValues.getValue(set);
1136        }
1137
1138        public static EnumSet<QueueProperties> getEnumSet(long v) {
1139            return EnumValues.getEnumSet(v, QueueProperties.class);
1140        }
1141    }
1142
1143    /**
1144     * Describes the command-queue properties supported by the device.<br>
1145     * These properties are described in table 5.1.<br>
1146     * The mandated minimum capability is: ProfilingEnable.
1147     */
1148    @InfoName("CL_DEVICE_QUEUE_PROPERTIES")
1149    public EnumSet<QueueProperties> getQueueProperties() {
1150        return QueueProperties.getEnumSet(infos.getIntOrLong(getEntity(), CL_DEVICE_QUEUE_PROPERTIES));
1151    }
1152
1153    /** Enums values for cl_device_affinity_domain */
1154    public enum AffinityDomain implements com.nativelibs4java.util.ValuedEnum {
1155        /** Split the device into sub-devices comprised of compute units that share a NUMA node. */
1156        NUMA(CL_DEVICE_AFFINITY_DOMAIN_NUMA),
1157        /** Split the device into sub-devices comprised of compute units that share a level 4 data cache. */
1158                L4Cache(CL_DEVICE_AFFINITY_DOMAIN_L4_CACHE),
1159                /** Split the device into sub-devices comprised of compute units that share a level 3 data cache. */
1160                L3Cache(CL_DEVICE_AFFINITY_DOMAIN_L3_CACHE),
1161                /** Split the device into sub-devices comprised of compute units that share a level 2 data cache. */
1162                L2Cache(CL_DEVICE_AFFINITY_DOMAIN_L2_CACHE),
1163                /** Split the device into sub-devices comprised of compute units that share a level 1 data cache. */
1164                L1Cache(CL_DEVICE_AFFINITY_DOMAIN_L1_CACHE),
1165                /**
1166                 * Split the device along the next partitionable affinity domain. The implementation shall finde 
1167                 * first level along which the device or sub-device may be further subdivided in the order NUMA, 
1168                 * L4, L3, L2, L1, and partition the device into sub-devices comprised of compute units that share 
1169                 * memory subsystems at this level.
1170                 */
1171                NextPartitionable(CL_DEVICE_AFFINITY_DOMAIN_NEXT_PARTITIONABLE);
1172
1173        AffinityDomain(long value) { this.value = value; }
1174        long value;
1175        @Override
1176        public long value() { return value; }
1177        
1178        public static AffinityDomain getEnum(long v) {
1179            return EnumValues.getEnum(v, AffinityDomain.class);
1180        }
1181    }
1182
1183    /**
1184     * Creates an array of sub-devices that each reference a non-intersecting set of compute units within this device.
1185     * Split the aggregate device into as many smaller aggregate devices as can be created, each containing n compute units. The value n is passed as the value accompanying this property. If n does not divide evenly into CL_DEVICE_PARTITION_MAX_COMPUTE_UNITS, then the remaining compute units are not used.
1186  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateSubDevices.html">clCreateSubDevices</a>.<br>
1187         * @param computeUnitsForEverySubDevice Count of compute units for every subdevice.
1188     */
1189    public CLDevice[] createSubDevicesEqually(int computeUnitsForEverySubDevice) {
1190                return createSubDevices(pointerToSizeTs(
1191                        CL_DEVICE_PARTITION_EQUALLY, computeUnitsForEverySubDevice, 0, 0
1192                ));
1193        }
1194
1195    /**
1196     * Creates an array of sub-devices that each reference a non-intersecting set of compute units within this device.
1197     * For each nonzero count m in the list, a sub-device is created with m compute units in it.
1198         * The number of non-zero count entries in the list may not exceed CL_DEVICE_PARTITION_MAX_SUB_DEVICES.
1199         * The total number of compute units specified may not exceed CL_DEVICE_PARTITION_MAX_COMPUTE_UNITS.
1200  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateSubDevices.html">clCreateSubDevices</a>.<br>
1201         * @param computeUnitsForEachSubDevice List of counts of compute units for each subdevice.
1202     */
1203    public CLDevice[] createSubDevicesByCounts(long... computeUnitsForEachSubDevice) {
1204        Pointer<SizeT> pProperties = allocateSizeTs(1 + computeUnitsForEachSubDevice.length + 1 + 1);
1205        int i = 0;
1206        pProperties.setSizeTAtIndex(i++, CL_DEVICE_PARTITION_BY_COUNTS);
1207        for (long count : computeUnitsForEachSubDevice) {
1208                pProperties.setSizeTAtIndex(i++, count);
1209        }
1210                pProperties.setSizeTAtIndex(i++, CL_DEVICE_PARTITION_BY_COUNTS_LIST_END);
1211                return createSubDevices(pProperties);
1212        }
1213
1214    /**
1215     * Creates an array of sub-devices that each reference a non-intersecting set of compute units within this device.
1216     * Split the device into smaller aggregate devices containing one or more compute units that all share part of a cache hierarchy.
1217     * The user may determine what happened by calling clGetDeviceInfo (CL_DEVICE_PARTITION_TYPE) on the sub-devices.
1218  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateSubDevices.html">clCreateSubDevices</a>.<br>
1219     * @param affinityDomain Affinity domain along which devices should be split.
1220     */
1221    public CLDevice[] createSubDevicesByAffinity(AffinityDomain affinityDomain) {
1222                return createSubDevices(pointerToSizeTs(
1223                        CL_DEVICE_PARTITION_BY_AFFINITY_DOMAIN, affinityDomain.value(), 0, 0
1224                ));
1225        }
1226
1227    /**
1228     * Creates an array of sub-devices that each reference a non-intersecting set of compute units within this device.
1229  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateSubDevices.html">clCreateSubDevices</a>.<br>
1230         * @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.  
1231     * @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}.
1232     */
1233    CLDevice[] createSubDevices(Pointer<SizeT> pProperties) {
1234                platform.requireMinVersionValue("clCreateSubDevices", 1.2);
1235
1236                ReusablePointers ptrs = ReusablePointers.get();
1237        Pointer<Integer> pNum = ptrs.int1;
1238        error(CL.clCreateSubDevices(getEntity(), getPeer(pProperties), 0, 0, getPeer(pNum)));
1239        int num = pNum.getInt();
1240
1241        Pointer<SizeT> pDevices = allocateSizeTs(num);
1242        error(CL.clCreateSubDevices(getEntity(), getPeer(pProperties), num, getPeer(pDevices), 0));
1243        CLDevice[] devices = new CLDevice[(int) num];
1244        for (int i = 0; i < num; i++) {
1245                devices[i] = new CLDevice(platform, this, pDevices.getSizeTAtIndex(i), true);
1246        }
1247        pDevices.release();
1248        return devices;
1249    }
1250
1251    /**
1252  * Calls <a href="http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clEnqueueMigrateMemObjects.html">clEnqueueMigrateMemObjects</a>.<br>
1253     * @param queue
1254         * @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.  
1255     * @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}.
1256     */
1257    /*
1258    public CLEvent enqueueMigrateMemObjects(CLQueue queue, CLEvent... eventsToWaitFor) {
1259                context.getPlatform().requireMinVersionValue("clEnqueueMigrateMemObjects", 1.2);
1260                        ReusablePointers ptrs = ReusablePointers.get();
1261                int[] eventsInCount = ptrs.int1Array;
1262        Pointer<cl_event> eventsIn = 
1263                CLAbstractEntity.copyNonNullEntities(eventsToWaitFor, eventsInCount, ptrs.events_in);
1264                Pointer<cl_event> eventOut = 
1265                eventsToWaitFor == null || CLEvent.containsFireAndForget(eventsToWaitFor) 
1266                ? null 
1267                : ptrs.event_out;
1268        error(CL.clEnqueueMigrateMemObjects(queue.getEntity(), getEntity(),   eventsInCount[0], getPeer(eventsIn) ,  getPeer(eventOut)  ));
1269         return  CLEvent.createEventFromPointer(queue, eventOut) ;     }
1270    */
1271}