Publishing R3
[platform/upstream/dldt.git] / inference-engine / thirdparty / clDNN / common / khronos_ocl_clhpp / cl2.hpp
1 /*******************************************************************************
2  * Copyright (c) 2008-2015 The Khronos Group Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and/or associated documentation files (the
6  * "Materials"), to deal in the Materials without restriction, including
7  * without limitation the rights to use, copy, modify, merge, publish,
8  * distribute, sublicense, and/or sell copies of the Materials, and to
9  * permit persons to whom the Materials are furnished to do so, subject to
10  * the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included
13  * in all copies or substantial portions of the Materials.
14  *
15  * MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
16  * KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
17  * SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
18  *    https://www.khronos.org/registry/
19  *
20  * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
24  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26  * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
27  ******************************************************************************/
28
29 /*! \file
30  *
31  *   \brief C++ bindings for OpenCL 1.0 (rev 48), OpenCL 1.1 (rev 33), 
32  *       OpenCL 1.2 (rev 15) and OpenCL 2.0 (rev 29)
33  *   \author Lee Howes and Bruce Merry
34  *   
35  *   Derived from the OpenCL 1.x C++ bindings written by 
36  *   Benedict R. Gaster, Laurent Morichetti and Lee Howes
37  *   With additions and fixes from:
38  *       Brian Cole, March 3rd 2010 and April 2012
39  *       Matt Gruenke, April 2012.
40  *       Bruce Merry, February 2013.
41  *       Tom Deakin and Simon McIntosh-Smith, July 2013
42  *       James Price, June-November 2015
43  *
44  *   \version 2.0.9
45  *   \date 2015-12-07
46  *
47  *   Optional extension support
48  *
49  *         cl_ext_device_fission
50  *         #define CL_HPP_USE_CL_DEVICE_FISSION
51  *         cl_khr_d3d10_sharing
52  *         #define CL_HPP_USE_DX_INTEROP
53  *         cl_khr_sub_groups
54  *         #define CL_HPP_USE_CL_SUB_GROUPS_KHR
55  */
56
57 /*! \mainpage
58  * \section intro Introduction
59  * For many large applications C++ is the language of choice and so it seems
60  * reasonable to define C++ bindings for OpenCL.
61  *
62  * The interface is contained with a single C++ header file \em cl2.hpp and all
63  * definitions are contained within the namespace \em cl. There is no additional
64  * requirement to include \em cl.h and to use either the C++ or original C
65  * bindings; it is enough to simply include \em cl2.hpp.
66  *
67  * The bindings themselves are lightweight and correspond closely to the
68  * underlying C API. Using the C++ bindings introduces no additional execution
69  * overhead.
70  *
71  * There are numerous compatibility, portability and memory management
72  * fixes in the new header as well as additional OpenCL 2.0 features.
73  * As a result the header is not directly backward compatible and for this
74  * reason we release it as cl2.hpp rather than a new version of cl.hpp.
75  * 
76  *
77  * \section compatibility Compatibility
78  * Due to the evolution of the underlying OpenCL API the 2.0 C++ bindings
79  * include an updated approach to defining supported feature versions
80  * and the range of valid underlying OpenCL runtime versions supported.
81  *
82  * The combination of preprocessor macros CL_HPP_TARGET_OPENCL_VERSION and 
83  * CL_HPP_MINIMUM_OPENCL_VERSION control this range. These are three digit
84  * decimal values representing OpenCL runime versions. The default for 
85  * the target is 200, representing OpenCL 2.0 and the minimum is also 
86  * defined as 200. These settings would use 2.0 API calls only.
87  * If backward compatibility with a 1.2 runtime is required, the minimum
88  * version may be set to 120.
89  *
90  * Note that this is a compile-time setting, and so affects linking against
91  * a particular SDK version rather than the versioning of the loaded runtime.
92  *
93  * The earlier versions of the header included basic vector and string 
94  * classes based loosely on STL versions. These were difficult to 
95  * maintain and very rarely used. For the 2.0 header we now assume
96  * the presence of the standard library unless requested otherwise.
97  * We use std::array, std::vector, std::shared_ptr and std::string 
98  * throughout to safely manage memory and reduce the chance of a 
99  * recurrance of earlier memory management bugs.
100  *
101  * These classes are used through typedefs in the cl namespace: 
102  * cl::array, cl::vector, cl::pointer and cl::string.
103  * In addition cl::allocate_pointer forwards to std::allocate_shared
104  * by default.
105  * In all cases these standard library classes can be replaced with 
106  * custom interface-compatible versions using the CL_HPP_NO_STD_ARRAY, 
107  * CL_HPP_NO_STD_VECTOR, CL_HPP_NO_STD_UNIQUE_PTR and 
108  * CL_HPP_NO_STD_STRING macros.
109  *
110  * The OpenCL 1.x versions of the C++ bindings included a size_t wrapper
111  * class to interface with kernel enqueue. This caused unpleasant interactions
112  * with the standard size_t declaration and led to namespacing bugs.
113  * In the 2.0 version we have replaced this with a std::array-based interface.
114  * However, the old behaviour can be regained for backward compatibility
115  * using the CL_HPP_ENABLE_SIZE_T_COMPATIBILITY macro.
116  *
117  * Finally, the program construction interface used a clumsy vector-of-pairs
118  * design in the earlier versions. We have replaced that with a cleaner 
119  * vector-of-vectors and vector-of-strings design. However, for backward 
120  * compatibility old behaviour can be regained with the
121  * CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY macro.
122  * 
123  * In OpenCL 2.0 OpenCL C is not entirely backward compatibility with 
124  * earlier versions. As a result a flag must be passed to the OpenCL C
125  * compiled to request OpenCL 2.0 compilation of kernels with 1.2 as
126  * the default in the absence of the flag.
127  * In some cases the C++ bindings automatically compile code for ease.
128  * For those cases the compilation defaults to OpenCL C 2.0.
129  * If this is not wanted, the CL_HPP_CL_1_2_DEFAULT_BUILD macro may
130  * be specified to assume 1.2 compilation.
131  * If more fine-grained decisions on a per-kernel bases are required
132  * then explicit build operations that take the flag should be used.
133  *
134  *
135  * \section parameterization Parameters
136  * This header may be parameterized by a set of preprocessor macros.
137  * CL_HPP_TARGET_OPENCL_VERSION
138  *  - Defines the target OpenCL runtime version to build the header against.
139  *    Defaults to 200, representing OpenCL 2.0.
140  * CL_HPP_NO_STD_STRING
141  *  - Do not use the standard library string class.
142  *    cl::string is not defined and may be defined by the user before 
143  *    cl2.hpp is included.
144  * CL_HPP_NO_STD_VECTOR
145  *  - Do not use the standard library vector class.
146  *    cl::vector is not defined and may be defined by the user before
147  *    cl2.hpp is included. 
148  * CL_HPP_NO_STD_ARRAY
149  *  - Do not use the standard library array class.
150  *    cl::array is not defined and may be defined by the user before
151  *    cl2.hpp is included.
152  * CL_HPP_NO_STD_UNIQUE_PTR
153  *  - Do not use the standard library unique_ptr class.
154  *    cl::pointer and the cl::allocate_pointer function are not defined 
155  *    and may be defined by the user before cl2.hpp is included.
156  * CL_HPP_ENABLE_DEVICE_FISSION 
157  *  - Enables device fission for OpenCL 1.2 platforms
158  * CL_HPP_ENABLE_EXCEPTIONS
159  *  - Enable exceptions for use in the C++ bindings header.
160  *    This is the preferred error handling mechanism but is not required.
161  * CL_HPP_ENABLE_SIZE_T_COMPATIBILITY
162  *  - Backward compatibility option to support cl.hpp-style size_t class.
163  *    Replaces the updated std::array derived version and removal of size_t
164  *    from the namespace. Note that in this case the new size_t class
165  *    is placed in the cl::compatibility namespace and thus requires
166  *    an additional using declaration for direct backward compatibility.
167  * CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY 
168  *  - Enable older vector of pairs interface for construction of programs.
169  * CL_HPP_CL_1_2_DEFAULT_BUILD
170  *  - Default to OpenCL C 1.2 compilation rather than OpenCL C 2.0
171  *  - applies to use of cl::Program construction and other program build variants.
172  *
173  *
174  * \section example Example
175  *
176  * The following example shows a general use case for the C++
177  * bindings, including support for the optional exception feature and
178  * also the supplied vector and string classes, see following sections for
179  * decriptions of these features.
180  * 
181  * \code
182     #define CL_HPP_ENABLE_EXCEPTIONS
183     #define CL_HPP_TARGET_OPENCL_VERSION 200
184    
185     #include <CL/cl2.hpp>
186     #include <iostream>
187     #include <vector>
188     #include <memory>
189     #include <algorithm>
190   
191     const int numElements = 32;
192   
193     int main(void)
194     {
195         // Filter for a 2.0 platform and set it as the default
196         std::vector<cl::Platform> platforms;
197         cl::Platform::get(&platforms);
198         cl::Platform plat;
199         for (auto &p : platforms) {
200             std::string platver = p.getInfo<CL_PLATFORM_VERSION>();
201             if (platver.find("OpenCL 2.") != std::string::npos) {
202                 plat = p;
203             }
204         }
205         if (plat() == 0)  {
206             std::cout << "No OpenCL 2.0 platform found.";
207             return -1;
208         }
209
210         cl::Platform newP = cl::Platform::setDefault(plat);
211         if (newP != plat) {
212             std::cout << "Error setting default platform.";
213             return -1;
214         }
215     
216         std::string kernel1{
217             "global int globalA;"
218             "kernel void updateGlobal(){"
219             "  globalA = 75;"
220             "}"};
221         std::string kernel2{
222             "typedef struct { global int *bar; } Foo; kernel void vectorAdd(global const Foo* aNum, global const int *inputA, global const int *inputB, global int *output, int val, write_only pipe int outPipe, queue_t childQueue){"
223             "  output[get_global_id(0)] = inputA[get_global_id(0)] + inputB[get_global_id(0)] + val + *(aNum->bar);"
224             "  write_pipe(outPipe, &val);"
225             "  queue_t default_queue = get_default_queue(); "
226             "  ndrange_t ndrange = ndrange_1D(get_global_size(0)/2, get_global_size(0)/2); "
227             // Have a child kernel write into third quarter of output
228             "  enqueue_kernel(default_queue, CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, "
229             "    ^{"
230             "      output[get_global_size(0)*2 + get_global_id(0)] = inputA[get_global_size(0)*2+get_global_id(0)] + inputB[get_global_size(0)*2+get_global_id(0)] + globalA;"
231             "    });"
232             // Have a child kernel write into last quarter of output
233             "  enqueue_kernel(childQueue, CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, "
234             "    ^{"
235             "      output[get_global_size(0)*3 + get_global_id(0)] = inputA[get_global_size(0)*3 + get_global_id(0)] + inputB[get_global_size(0)*3 + get_global_id(0)] + globalA + 2;"
236             "    });"
237             "}" };
238
239         // New simpler string interface style
240         std::vector<std::string> programStrings {kernel1, kernel2};
241
242         cl::Program vectorAddProgram(
243             programStrings);
244         try {
245             vectorAddProgram.build("-cl-std=CL2.0");
246         }
247         catch (...) {
248             // Print build info for all devices
249             cl_int buildErr = CL_SUCCESS;
250             auto buildInfo = vectorAddProgram.getBuildInfo<CL_PROGRAM_BUILD_LOG>(&buildErr);
251             for (auto &pair : buildInfo) {
252                 std::cerr << pair.second << std::endl << std::endl;
253             }
254         
255             return 1;
256         }
257
258         typedef struct { int *bar; } Foo;
259
260         // Get and run kernel that initializes the program-scope global
261         // A test for kernels that take no arguments
262         auto program2Kernel =
263             cl::KernelFunctor<>(vectorAddProgram, "updateGlobal");
264         program2Kernel(
265             cl::EnqueueArgs(
266             cl::NDRange(1)));
267     
268         //////////////////
269         // SVM allocations
270     
271         cl::pointer<int> anSVMInt = cl::allocate_svm<int, cl::SVMTraitCoarse<>>();
272         *anSVMInt = 5;
273         cl::SVMAllocator<int, cl::SVMTraitCoarse<cl::SVMTraitReadOnly<>>> svmAllocReadOnly;
274         auto fooPointer = cl::allocate_pointer<Foo>(svmAllocReadOnly);
275         fooPointer->bar = anSVMInt.get();
276         cl::SVMAllocator<int, cl::SVMTraitCoarse<>> svmAlloc;
277         std::vector<int, cl::SVMAllocator<int, cl::SVMTraitCoarse<>>> inputA(numElements, 1, svmAlloc);    
278         cl::coarse_svm_vector<int> inputB(numElements, 2, svmAlloc);
279
280         //
281         //////////////
282
283         // Traditional cl_mem allocations
284         std::vector<int> output(numElements, 0xdeadbeef);
285         cl::Buffer outputBuffer(begin(output), end(output), false);
286         cl::Pipe aPipe(sizeof(cl_int), numElements / 2);
287     
288         // Default command queue, also passed in as a parameter
289         cl::DeviceCommandQueue defaultDeviceQueue = cl::DeviceCommandQueue::makeDefault(
290             cl::Context::getDefault(), cl::Device::getDefault());
291
292         auto vectorAddKernel =
293             cl::KernelFunctor<
294                 decltype(fooPointer)&,
295                 int*,
296                 cl::coarse_svm_vector<int>&,
297                 cl::Buffer,
298                 int,
299                 cl::Pipe&,
300                 cl::DeviceCommandQueue
301                 >(vectorAddProgram, "vectorAdd");
302
303         // Ensure that the additional SVM pointer is available to the kernel
304         // This one was not passed as a parameter
305         vectorAddKernel.setSVMPointers(anSVMInt);
306
307         // Hand control of coarse allocations to runtime
308         cl::enqueueUnmapSVM(anSVMInt);
309         cl::enqueueUnmapSVM(fooPointer);
310         cl::unmapSVM(inputB);
311         cl::unmapSVM(output2);
312
313             cl_int error;
314             vectorAddKernel(
315             cl::EnqueueArgs(
316                 cl::NDRange(numElements/2),
317                 cl::NDRange(numElements/2)),
318             fooPointer,
319             inputA.data(),
320             inputB,
321             outputBuffer,
322             3,
323             aPipe,
324             defaultDeviceQueue,
325                     error
326             );
327
328         cl::copy(outputBuffer, begin(output), end(output));
329         // Grab the SVM output vector using a map
330         cl::mapSVM(output2);
331
332         cl::Device d = cl::Device::getDefault();
333
334         std::cout << "Output:\n";
335         for (int i = 1; i < numElements; ++i) {
336             std::cout << "\t" << output[i] << "\n";
337         }
338         std::cout << "\n\n";
339
340         return 0;
341     }
342  * 
343  * \endcode
344  *
345  */
346 #ifndef CL_HPP_
347 #define CL_HPP_
348
349 /* Handle deprecated preprocessor definitions. In each case, we only check for
350  * the old name if the new name is not defined, so that user code can define
351  * both and hence work with either version of the bindings.
352  */
353 #if !defined(CL_HPP_USE_DX_INTEROP) && defined(USE_DX_INTEROP)
354 # pragma message("cl2.hpp: USE_DX_INTEROP is deprecated. Define CL_HPP_USE_DX_INTEROP instead")
355 # define CL_HPP_USE_DX_INTEROP
356 #endif
357 #if !defined(CL_HPP_USE_CL_DEVICE_FISSION) && defined(USE_CL_DEVICE_FISSION)
358 # pragma message("cl2.hpp: USE_CL_DEVICE_FISSION is deprecated. Define CL_HPP_USE_CL_DEVICE_FISSION instead")
359 # define CL_HPP_USE_CL_DEVICE_FISSION
360 #endif
361 #if !defined(CL_HPP_ENABLE_EXCEPTIONS) && defined(__CL_ENABLE_EXCEPTIONS)
362 # pragma message("cl2.hpp: __CL_ENABLE_EXCEPTIONS is deprecated. Define CL_HPP_ENABLE_EXCEPTIONS instead")
363 # define CL_HPP_ENABLE_EXCEPTIONS
364 #endif
365 #if !defined(CL_HPP_NO_STD_VECTOR) && defined(__NO_STD_VECTOR)
366 # pragma message("cl2.hpp: __NO_STD_VECTOR is deprecated. Define CL_HPP_NO_STD_VECTOR instead")
367 # define CL_HPP_NO_STD_VECTOR
368 #endif
369 #if !defined(CL_HPP_NO_STD_STRING) && defined(__NO_STD_STRING)
370 # pragma message("cl2.hpp: __NO_STD_STRING is deprecated. Define CL_HPP_NO_STD_STRING instead")
371 # define CL_HPP_NO_STD_STRING
372 #endif
373 #if defined(VECTOR_CLASS)
374 # pragma message("cl2.hpp: VECTOR_CLASS is deprecated. Alias cl::vector instead")
375 #endif
376 #if defined(STRING_CLASS)
377 # pragma message("cl2.hpp: STRING_CLASS is deprecated. Alias cl::string instead.")
378 #endif
379 #if !defined(CL_HPP_USER_OVERRIDE_ERROR_STRINGS) && defined(__CL_USER_OVERRIDE_ERROR_STRINGS)
380 # pragma message("cl2.hpp: __CL_USER_OVERRIDE_ERROR_STRINGS is deprecated. Define CL_HPP_USER_OVERRIDE_ERROR_STRINGS instead")
381 # define CL_HPP_USER_OVERRIDE_ERROR_STRINGS
382 #endif
383
384 /* Warn about features that are no longer supported
385  */
386 #if defined(__USE_DEV_VECTOR)
387 # pragma message("cl2.hpp: __USE_DEV_VECTOR is no longer supported. Expect compilation errors")
388 #endif
389 #if defined(__USE_DEV_STRING)
390 # pragma message("cl2.hpp: __USE_DEV_STRING is no longer supported. Expect compilation errors")
391 #endif
392
393 /* Detect which version to target */
394 #if !defined(CL_HPP_TARGET_OPENCL_VERSION)
395 # pragma message("cl2.hpp: CL_HPP_TARGET_OPENCL_VERSION is not defined. It will default to 200 (OpenCL 2.0)")
396 # define CL_HPP_TARGET_OPENCL_VERSION 200
397 #endif
398 #if CL_HPP_TARGET_OPENCL_VERSION != 100 && CL_HPP_TARGET_OPENCL_VERSION != 110 && CL_HPP_TARGET_OPENCL_VERSION != 120 && CL_HPP_TARGET_OPENCL_VERSION != 200
399 # pragma message("cl2.hpp: CL_HPP_TARGET_OPENCL_VERSION is not a valid value (100, 110, 120 or 200). It will be set to 200")
400 # undef CL_HPP_TARGET_OPENCL_VERSION
401 # define CL_HPP_TARGET_OPENCL_VERSION 200
402 #endif
403
404 #if !defined(CL_HPP_MINIMUM_OPENCL_VERSION)
405 # define CL_HPP_MINIMUM_OPENCL_VERSION 200
406 #endif
407 #if CL_HPP_MINIMUM_OPENCL_VERSION != 100 && CL_HPP_MINIMUM_OPENCL_VERSION != 110 && CL_HPP_MINIMUM_OPENCL_VERSION != 120 && CL_HPP_MINIMUM_OPENCL_VERSION != 200
408 # pragma message("cl2.hpp: CL_HPP_MINIMUM_OPENCL_VERSION is not a valid value (100, 110, 120 or 200). It will be set to 100")
409 # undef CL_HPP_MINIMUM_OPENCL_VERSION
410 # define CL_HPP_MINIMUM_OPENCL_VERSION 100
411 #endif
412 #if CL_HPP_MINIMUM_OPENCL_VERSION > CL_HPP_TARGET_OPENCL_VERSION
413 # error "CL_HPP_MINIMUM_OPENCL_VERSION must not be greater than CL_HPP_TARGET_OPENCL_VERSION"
414 #endif
415
416 #if CL_HPP_MINIMUM_OPENCL_VERSION <= 100 && !defined(CL_USE_DEPRECATED_OPENCL_1_0_APIS)
417 # define CL_USE_DEPRECATED_OPENCL_1_0_APIS
418 #endif
419 #if CL_HPP_MINIMUM_OPENCL_VERSION <= 110 && !defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS)
420 # define CL_USE_DEPRECATED_OPENCL_1_1_APIS
421 #endif
422 #if CL_HPP_MINIMUM_OPENCL_VERSION <= 120 && !defined(CL_USE_DEPRECATED_OPENCL_1_2_APIS)
423 # define CL_USE_DEPRECATED_OPENCL_1_2_APIS
424 #endif
425 #if CL_HPP_MINIMUM_OPENCL_VERSION <= 200 && !defined(CL_USE_DEPRECATED_OPENCL_2_0_APIS)
426 # define CL_USE_DEPRECATED_OPENCL_2_0_APIS
427 #endif
428
429 #ifdef _WIN32
430
431 #include <malloc.h>
432
433 #if defined(CL_HPP_USE_DX_INTEROP)
434 #include <CL/cl_d3d10.h>
435 #include <CL/cl_dx9_media_sharing.h>
436 #endif
437 #endif // _WIN32
438
439 #if defined(_MSC_VER)
440 #include <intrin.h>
441 #endif // _MSC_VER 
442  
443  // Check for a valid C++ version
444
445 // Need to do both tests here because for some reason __cplusplus is not 
446 // updated in visual studio
447 #if (!defined(_MSC_VER) && __cplusplus < 201103L) || (defined(_MSC_VER) && _MSC_VER < 1700)
448 #error Visual studio 2013 or another C++11-supporting compiler required
449 #endif
450
451 // 
452 #if defined(CL_HPP_USE_CL_DEVICE_FISSION) || defined(CL_HPP_USE_CL_SUB_GROUPS_KHR)
453 #include <CL/cl_ext.h>
454 #endif
455
456 #if defined(__APPLE__) || defined(__MACOSX)
457 #include <OpenCL/opencl.h>
458 #else
459 #include <CL/opencl.h>
460 #endif // !__APPLE__
461
462 #if (__cplusplus >= 201103L)
463 #define CL_HPP_NOEXCEPT_ noexcept
464 #else
465 #define CL_HPP_NOEXCEPT_
466 #endif
467
468 #if defined(_MSC_VER)
469 # define CL_HPP_DEFINE_STATIC_MEMBER_ __declspec(selectany)
470 #else
471 # define CL_HPP_DEFINE_STATIC_MEMBER_ __attribute__((weak))
472 #endif // !_MSC_VER
473
474 // Define deprecated prefixes and suffixes to ensure compilation
475 // in case they are not pre-defined
476 #if !defined(CL_EXT_PREFIX__VERSION_1_1_DEPRECATED)
477 #define CL_EXT_PREFIX__VERSION_1_1_DEPRECATED  
478 #endif // #if !defined(CL_EXT_PREFIX__VERSION_1_1_DEPRECATED)
479 #if !defined(CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED)
480 #define CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED
481 #endif // #if !defined(CL_EXT_PREFIX__VERSION_1_1_DEPRECATED)
482
483 #if !defined(CL_EXT_PREFIX__VERSION_1_2_DEPRECATED)
484 #define CL_EXT_PREFIX__VERSION_1_2_DEPRECATED  
485 #endif // #if !defined(CL_EXT_PREFIX__VERSION_1_2_DEPRECATED)
486 #if !defined(CL_EXT_SUFFIX__VERSION_1_2_DEPRECATED)
487 #define CL_EXT_SUFFIX__VERSION_1_2_DEPRECATED
488 #endif // #if !defined(CL_EXT_PREFIX__VERSION_1_2_DEPRECATED)
489
490 #if !defined(CL_CALLBACK)
491 #define CL_CALLBACK
492 #endif //CL_CALLBACK
493
494 #include <utility>
495 #include <limits>
496 #include <iterator>
497 #include <mutex>
498 #include <cstring>
499 #include <functional>
500
501
502 // Define a size_type to represent a correctly resolved size_t
503 #if defined(CL_HPP_ENABLE_SIZE_T_COMPATIBILITY)
504 namespace cl {
505     using size_type = ::size_t;
506 } // namespace cl
507 #else // #if defined(CL_HPP_ENABLE_SIZE_T_COMPATIBILITY)
508 namespace cl {
509     using size_type = size_t;
510 } // namespace cl
511 #endif // #if defined(CL_HPP_ENABLE_SIZE_T_COMPATIBILITY)
512
513
514 #if defined(CL_HPP_ENABLE_EXCEPTIONS)
515 #include <exception>
516 #endif // #if defined(CL_HPP_ENABLE_EXCEPTIONS)
517
518 #if !defined(CL_HPP_NO_STD_VECTOR)
519 #include <vector>
520 namespace cl {
521     template < class T, class Alloc = std::allocator<T> >
522     using vector = std::vector<T, Alloc>;
523 } // namespace cl
524 #endif // #if !defined(CL_HPP_NO_STD_VECTOR)
525
526 #if !defined(CL_HPP_NO_STD_STRING)
527 #include <string>
528 namespace cl {
529     using string = std::string;
530 } // namespace cl
531 #endif // #if !defined(CL_HPP_NO_STD_STRING)
532
533 #if CL_HPP_TARGET_OPENCL_VERSION >= 200
534
535 #if !defined(CL_HPP_NO_STD_UNIQUE_PTR)
536 #include <memory>
537 namespace cl {
538     // Replace unique_ptr and allocate_pointer for internal use
539     // to allow user to replace them
540     template<class T, class D>
541     using pointer = std::unique_ptr<T, D>;
542 } // namespace cl
543 #endif 
544 #endif // #if CL_HPP_TARGET_OPENCL_VERSION >= 200
545 #if !defined(CL_HPP_NO_STD_ARRAY)
546 #include <array>
547 namespace cl {
548     template < class T, size_type N >
549     using array = std::array<T, N>;
550 } // namespace cl
551 #endif // #if !defined(CL_HPP_NO_STD_ARRAY)
552
553 // Define size_type appropriately to allow backward-compatibility
554 // use of the old size_t interface class
555 #if defined(CL_HPP_ENABLE_SIZE_T_COMPATIBILITY)
556 namespace cl {
557     namespace compatibility {
558         /*! \brief class used to interface between C++ and
559         *  OpenCL C calls that require arrays of size_t values, whose
560         *  size is known statically.
561         */
562         template <int N>
563         class size_t
564         {
565         private:
566             size_type data_[N];
567
568         public:
569             //! \brief Initialize size_t to all 0s
570             size_t()
571             {
572                 for (int i = 0; i < N; ++i) {
573                     data_[i] = 0;
574                 }
575             }
576
577             size_t(const array<size_type, N> &rhs)
578             {
579                 for (int i = 0; i < N; ++i) {
580                     data_[i] = rhs[i];
581                 }
582             }
583
584             size_type& operator[](int index)
585             {
586                 return data_[index];
587             }
588
589             const size_type& operator[](int index) const
590             {
591                 return data_[index];
592             }
593
594             //! \brief Conversion operator to T*.
595             operator size_type* ()             { return data_; }
596
597             //! \brief Conversion operator to const T*.
598             operator const size_type* () const { return data_; }
599
600             operator array<size_type, N>() const
601             {
602                 array<size_type, N> ret;
603
604                 for (int i = 0; i < N; ++i) {
605                     ret[i] = data_[i];
606                 }
607                 return ret;
608             }
609         };
610     } // namespace compatibility
611
612     template<int N>
613     using size_t = compatibility::size_t<N>;
614 } // namespace cl
615 #endif // #if defined(CL_HPP_ENABLE_SIZE_T_COMPATIBILITY)
616
617 // Helper alias to avoid confusing the macros
618 namespace cl {
619     namespace detail {
620         using size_t_array = array<size_type, 3>;
621     } // namespace detail
622 } // namespace cl
623
624
625 /*! \namespace cl
626  *
627  * \brief The OpenCL C++ bindings are defined within this namespace.
628  *
629  */
630 namespace cl {
631     class Memory;
632
633 #define CL_HPP_INIT_CL_EXT_FCN_PTR_(name) \
634     if (!pfn_##name) {    \
635     pfn_##name = (PFN_##name) \
636     clGetExtensionFunctionAddress(#name); \
637     if (!pfn_##name) {    \
638     } \
639     }
640
641 #define CL_HPP_INIT_CL_EXT_FCN_PTR_PLATFORM_(platform, name) \
642     if (!pfn_##name) {    \
643     pfn_##name = (PFN_##name) \
644     clGetExtensionFunctionAddressForPlatform(platform, #name); \
645     if (!pfn_##name) {    \
646     } \
647     }
648
649     class Program;
650     class Device;
651     class Context;
652     class CommandQueue;
653     class DeviceCommandQueue;
654     class Memory;
655     class Buffer;
656     class Pipe;
657
658 #if defined(CL_HPP_ENABLE_EXCEPTIONS)
659     /*! \brief Exception class 
660      * 
661      *  This may be thrown by API functions when CL_HPP_ENABLE_EXCEPTIONS is defined.
662      */
663     class Error : public std::exception
664     {
665     private:
666         cl_int err_;
667         const char * errStr_;
668     public:
669         /*! \brief Create a new CL error exception for a given error code
670          *  and corresponding message.
671          * 
672          *  \param err error code value.
673          *
674          *  \param errStr a descriptive string that must remain in scope until
675          *                handling of the exception has concluded.  If set, it
676          *                will be returned by what().
677          */
678         Error(cl_int err, const char * errStr = NULL) : err_(err), errStr_(errStr)
679         {}
680
681         ~Error() throw() {}
682
683         /*! \brief Get error string associated with exception
684          *
685          * \return A memory pointer to the error message string.
686          */
687         virtual const char * what() const throw ()
688         {
689             if (errStr_ == NULL) {
690                 return "empty";
691             }
692             else {
693                 return errStr_;
694             }
695         }
696
697         /*! \brief Get error code associated with exception
698          *
699          *  \return The error code.
700          */
701         cl_int err(void) const { return err_; }
702     };
703 #define CL_HPP_ERR_STR_(x) #x
704 #else
705 #define CL_HPP_ERR_STR_(x) NULL
706 #endif // CL_HPP_ENABLE_EXCEPTIONS
707
708
709 namespace detail
710 {
711 #if defined(CL_HPP_ENABLE_EXCEPTIONS)
712 static inline cl_int errHandler (
713     cl_int err,
714     const char * errStr = NULL)
715 {
716     if (err != CL_SUCCESS) {
717         throw Error(err, errStr);
718     }
719     return err;
720 }
721 #else
722 static inline cl_int errHandler (cl_int err, const char * errStr = NULL)
723 {
724     (void) errStr; // suppress unused variable warning
725     return err;
726 }
727 #endif // CL_HPP_ENABLE_EXCEPTIONS
728 }
729
730
731
732 //! \cond DOXYGEN_DETAIL
733 #if !defined(CL_HPP_USER_OVERRIDE_ERROR_STRINGS)
734 #define __GET_DEVICE_INFO_ERR               CL_HPP_ERR_STR_(clGetDeviceInfo)
735 #define __GET_PLATFORM_INFO_ERR             CL_HPP_ERR_STR_(clGetPlatformInfo)
736 #define __GET_DEVICE_IDS_ERR                CL_HPP_ERR_STR_(clGetDeviceIDs)
737 #define __GET_PLATFORM_IDS_ERR              CL_HPP_ERR_STR_(clGetPlatformIDs)
738 #define __GET_CONTEXT_INFO_ERR              CL_HPP_ERR_STR_(clGetContextInfo)
739 #define __GET_EVENT_INFO_ERR                CL_HPP_ERR_STR_(clGetEventInfo)
740 #define __GET_EVENT_PROFILE_INFO_ERR        CL_HPP_ERR_STR_(clGetEventProfileInfo)
741 #define __GET_MEM_OBJECT_INFO_ERR           CL_HPP_ERR_STR_(clGetMemObjectInfo)
742 #define __GET_IMAGE_INFO_ERR                CL_HPP_ERR_STR_(clGetImageInfo)
743 #define __GET_SAMPLER_INFO_ERR              CL_HPP_ERR_STR_(clGetSamplerInfo)
744 #define __GET_KERNEL_INFO_ERR               CL_HPP_ERR_STR_(clGetKernelInfo)
745 #if CL_HPP_TARGET_OPENCL_VERSION >= 120
746 #define __GET_KERNEL_ARG_INFO_ERR           CL_HPP_ERR_STR_(clGetKernelArgInfo)
747 #endif // CL_HPP_TARGET_OPENCL_VERSION >= 120
748 #define __GET_KERNEL_WORK_GROUP_INFO_ERR    CL_HPP_ERR_STR_(clGetKernelWorkGroupInfo)
749 #define __GET_PROGRAM_INFO_ERR              CL_HPP_ERR_STR_(clGetProgramInfo)
750 #define __GET_PROGRAM_BUILD_INFO_ERR        CL_HPP_ERR_STR_(clGetProgramBuildInfo)
751 #define __GET_COMMAND_QUEUE_INFO_ERR        CL_HPP_ERR_STR_(clGetCommandQueueInfo)
752
753 #define __CREATE_CONTEXT_ERR                CL_HPP_ERR_STR_(clCreateContext)
754 #define __CREATE_CONTEXT_FROM_TYPE_ERR      CL_HPP_ERR_STR_(clCreateContextFromType)
755 #define __GET_SUPPORTED_IMAGE_FORMATS_ERR   CL_HPP_ERR_STR_(clGetSupportedImageFormats)
756
757 #define __CREATE_BUFFER_ERR                 CL_HPP_ERR_STR_(clCreateBuffer)
758 #define __COPY_ERR                          CL_HPP_ERR_STR_(cl::copy)
759 #define __CREATE_SUBBUFFER_ERR              CL_HPP_ERR_STR_(clCreateSubBuffer)
760 #define __CREATE_GL_BUFFER_ERR              CL_HPP_ERR_STR_(clCreateFromGLBuffer)
761 #define __CREATE_GL_RENDER_BUFFER_ERR       CL_HPP_ERR_STR_(clCreateFromGLBuffer)
762 #define __GET_GL_OBJECT_INFO_ERR            CL_HPP_ERR_STR_(clGetGLObjectInfo)
763 #if CL_HPP_TARGET_OPENCL_VERSION >= 120
764 #define __CREATE_IMAGE_ERR                  CL_HPP_ERR_STR_(clCreateImage)
765 #define __CREATE_GL_TEXTURE_ERR             CL_HPP_ERR_STR_(clCreateFromGLTexture)
766 #define __IMAGE_DIMENSION_ERR               CL_HPP_ERR_STR_(Incorrect image dimensions)
767 #endif // CL_HPP_TARGET_OPENCL_VERSION >= 120
768 #define __SET_MEM_OBJECT_DESTRUCTOR_CALLBACK_ERR CL_HPP_ERR_STR_(clSetMemObjectDestructorCallback)
769
770 #define __CREATE_USER_EVENT_ERR             CL_HPP_ERR_STR_(clCreateUserEvent)
771 #define __SET_USER_EVENT_STATUS_ERR         CL_HPP_ERR_STR_(clSetUserEventStatus)
772 #define __SET_EVENT_CALLBACK_ERR            CL_HPP_ERR_STR_(clSetEventCallback)
773 #define __WAIT_FOR_EVENTS_ERR               CL_HPP_ERR_STR_(clWaitForEvents)
774
775 #define __CREATE_KERNEL_ERR                 CL_HPP_ERR_STR_(clCreateKernel)
776 #define __SET_KERNEL_ARGS_ERR               CL_HPP_ERR_STR_(clSetKernelArg)
777 #define __CREATE_PROGRAM_WITH_SOURCE_ERR    CL_HPP_ERR_STR_(clCreateProgramWithSource)
778 #define __CREATE_PROGRAM_WITH_BINARY_ERR    CL_HPP_ERR_STR_(clCreateProgramWithBinary)
779 #if CL_HPP_TARGET_OPENCL_VERSION >= 120
780 #define __CREATE_PROGRAM_WITH_BUILT_IN_KERNELS_ERR    CL_HPP_ERR_STR_(clCreateProgramWithBuiltInKernels)
781 #endif // CL_HPP_TARGET_OPENCL_VERSION >= 120
782 #define __BUILD_PROGRAM_ERR                 CL_HPP_ERR_STR_(clBuildProgram)
783 #if CL_HPP_TARGET_OPENCL_VERSION >= 120
784 #define __COMPILE_PROGRAM_ERR               CL_HPP_ERR_STR_(clCompileProgram)
785 #define __LINK_PROGRAM_ERR                  CL_HPP_ERR_STR_(clLinkProgram)
786 #endif // CL_HPP_TARGET_OPENCL_VERSION >= 120
787 #define __CREATE_KERNELS_IN_PROGRAM_ERR     CL_HPP_ERR_STR_(clCreateKernelsInProgram)
788
789 #if CL_HPP_TARGET_OPENCL_VERSION >= 200
790 #define __CREATE_COMMAND_QUEUE_WITH_PROPERTIES_ERR          CL_HPP_ERR_STR_(clCreateCommandQueueWithProperties)
791 #define __CREATE_SAMPLER_WITH_PROPERTIES_ERR                CL_HPP_ERR_STR_(clCreateSamplerWithProperties)
792 #endif // CL_HPP_TARGET_OPENCL_VERSION >= 200
793 #define __SET_COMMAND_QUEUE_PROPERTY_ERR    CL_HPP_ERR_STR_(clSetCommandQueueProperty)
794 #define __ENQUEUE_READ_BUFFER_ERR           CL_HPP_ERR_STR_(clEnqueueReadBuffer)
795 #define __ENQUEUE_READ_BUFFER_RECT_ERR      CL_HPP_ERR_STR_(clEnqueueReadBufferRect)
796 #define __ENQUEUE_WRITE_BUFFER_ERR          CL_HPP_ERR_STR_(clEnqueueWriteBuffer)
797 #define __ENQUEUE_WRITE_BUFFER_RECT_ERR     CL_HPP_ERR_STR_(clEnqueueWriteBufferRect)
798 #define __ENQEUE_COPY_BUFFER_ERR            CL_HPP_ERR_STR_(clEnqueueCopyBuffer)
799 #define __ENQEUE_COPY_BUFFER_RECT_ERR       CL_HPP_ERR_STR_(clEnqueueCopyBufferRect)
800 #define __ENQUEUE_FILL_BUFFER_ERR           CL_HPP_ERR_STR_(clEnqueueFillBuffer)
801 #define __ENQUEUE_READ_IMAGE_ERR            CL_HPP_ERR_STR_(clEnqueueReadImage)
802 #define __ENQUEUE_WRITE_IMAGE_ERR           CL_HPP_ERR_STR_(clEnqueueWriteImage)
803 #define __ENQUEUE_COPY_IMAGE_ERR            CL_HPP_ERR_STR_(clEnqueueCopyImage)
804 #define __ENQUEUE_FILL_IMAGE_ERR            CL_HPP_ERR_STR_(clEnqueueFillImage)
805 #define __ENQUEUE_COPY_IMAGE_TO_BUFFER_ERR  CL_HPP_ERR_STR_(clEnqueueCopyImageToBuffer)
806 #define __ENQUEUE_COPY_BUFFER_TO_IMAGE_ERR  CL_HPP_ERR_STR_(clEnqueueCopyBufferToImage)
807 #define __ENQUEUE_MAP_BUFFER_ERR            CL_HPP_ERR_STR_(clEnqueueMapBuffer)
808 #define __ENQUEUE_MAP_IMAGE_ERR             CL_HPP_ERR_STR_(clEnqueueMapImage)
809 #define __ENQUEUE_UNMAP_MEM_OBJECT_ERR      CL_HPP_ERR_STR_(clEnqueueUnMapMemObject)
810 #define __ENQUEUE_NDRANGE_KERNEL_ERR        CL_HPP_ERR_STR_(clEnqueueNDRangeKernel)
811 #define __ENQUEUE_NATIVE_KERNEL             CL_HPP_ERR_STR_(clEnqueueNativeKernel)
812 #if CL_HPP_TARGET_OPENCL_VERSION >= 120
813 #define __ENQUEUE_MIGRATE_MEM_OBJECTS_ERR   CL_HPP_ERR_STR_(clEnqueueMigrateMemObjects)
814 #endif // CL_HPP_TARGET_OPENCL_VERSION >= 120
815
816 #define __ENQUEUE_ACQUIRE_GL_ERR            CL_HPP_ERR_STR_(clEnqueueAcquireGLObjects)
817 #define __ENQUEUE_RELEASE_GL_ERR            CL_HPP_ERR_STR_(clEnqueueReleaseGLObjects)
818
819 #define __CREATE_PIPE_ERR             CL_HPP_ERR_STR_(clCreatePipe)
820 #define __GET_PIPE_INFO_ERR           CL_HPP_ERR_STR_(clGetPipeInfo)
821
822
823 #define __RETAIN_ERR                        CL_HPP_ERR_STR_(Retain Object)
824 #define __RELEASE_ERR                       CL_HPP_ERR_STR_(Release Object)
825 #define __FLUSH_ERR                         CL_HPP_ERR_STR_(clFlush)
826 #define __FINISH_ERR                        CL_HPP_ERR_STR_(clFinish)
827 #define __VECTOR_CAPACITY_ERR               CL_HPP_ERR_STR_(Vector capacity error)
828
829 /**
830  * CL 1.2 version that uses device fission.
831  */
832 #if CL_HPP_TARGET_OPENCL_VERSION >= 120
833 #define __CREATE_SUB_DEVICES_ERR            CL_HPP_ERR_STR_(clCreateSubDevices)
834 #else
835 #define __CREATE_SUB_DEVICES_ERR            CL_HPP_ERR_STR_(clCreateSubDevicesEXT)
836 #endif // CL_HPP_TARGET_OPENCL_VERSION >= 120
837
838 /**
839  * Deprecated APIs for 1.2
840  */
841 #if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS)
842 #define __ENQUEUE_MARKER_ERR                CL_HPP_ERR_STR_(clEnqueueMarker)
843 #define __ENQUEUE_WAIT_FOR_EVENTS_ERR       CL_HPP_ERR_STR_(clEnqueueWaitForEvents)
844 #define __ENQUEUE_BARRIER_ERR               CL_HPP_ERR_STR_(clEnqueueBarrier)
845 #define __UNLOAD_COMPILER_ERR               CL_HPP_ERR_STR_(clUnloadCompiler)
846 #define __CREATE_GL_TEXTURE_2D_ERR          CL_HPP_ERR_STR_(clCreateFromGLTexture2D)
847 #define __CREATE_GL_TEXTURE_3D_ERR          CL_HPP_ERR_STR_(clCreateFromGLTexture3D)
848 #define __CREATE_IMAGE2D_ERR                CL_HPP_ERR_STR_(clCreateImage2D)
849 #define __CREATE_IMAGE3D_ERR                CL_HPP_ERR_STR_(clCreateImage3D)
850 #endif // #if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS)
851
852 /**
853  * Deprecated APIs for 2.0
854  */
855 #if defined(CL_USE_DEPRECATED_OPENCL_1_2_APIS)
856 #define __CREATE_COMMAND_QUEUE_ERR          CL_HPP_ERR_STR_(clCreateCommandQueue)
857 #define __ENQUEUE_TASK_ERR                  CL_HPP_ERR_STR_(clEnqueueTask)
858 #define __CREATE_SAMPLER_ERR                CL_HPP_ERR_STR_(clCreateSampler)
859 #endif // #if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS)
860
861 /**
862  * CL 1.2 marker and barrier commands
863  */
864 #if CL_HPP_TARGET_OPENCL_VERSION >= 120
865 #define __ENQUEUE_MARKER_WAIT_LIST_ERR                CL_HPP_ERR_STR_(clEnqueueMarkerWithWaitList)
866 #define __ENQUEUE_BARRIER_WAIT_LIST_ERR               CL_HPP_ERR_STR_(clEnqueueBarrierWithWaitList)
867 #endif // CL_HPP_TARGET_OPENCL_VERSION >= 120
868
869 #endif // CL_HPP_USER_OVERRIDE_ERROR_STRINGS
870 //! \endcond
871
872
873 namespace detail {
874
875 // Generic getInfoHelper. The final parameter is used to guide overload
876 // resolution: the actual parameter passed is an int, which makes this
877 // a worse conversion sequence than a specialization that declares the
878 // parameter as an int.
879 template<typename Functor, typename T>
880 inline cl_int getInfoHelper(Functor f, cl_uint name, T* param, long)
881 {
882     return f(name, sizeof(T), param, NULL);
883 }
884
885 // Specialized for getInfo<CL_PROGRAM_BINARIES>
886 // Assumes that the output vector was correctly resized on the way in
887 template <typename Func>
888 inline cl_int getInfoHelper(Func f, cl_uint name, vector<vector<unsigned char>>* param, int)
889 {
890     if (name != CL_PROGRAM_BINARIES) {
891         return CL_INVALID_VALUE;
892     }
893     if (param) {
894         // Create array of pointers, calculate total size and pass pointer array in
895         size_type numBinaries = param->size();
896         vector<unsigned char*> binariesPointers(numBinaries);
897
898         size_type totalSize = 0;
899         for (size_type i = 0; i < numBinaries; ++i)
900         {
901             binariesPointers[i] = (*param)[i].data();
902             totalSize += (*param)[i].size();
903         }
904
905         cl_int err = f(name, totalSize, binariesPointers.data(), NULL);
906
907         if (err != CL_SUCCESS) {
908             return err;
909         }
910     }
911
912
913     return CL_SUCCESS;
914 }
915
916 // Specialized getInfoHelper for vector params
917 template <typename Func, typename T>
918 inline cl_int getInfoHelper(Func f, cl_uint name, vector<T>* param, long)
919 {
920     size_type required;
921     cl_int err = f(name, 0, NULL, &required);
922     if (err != CL_SUCCESS) {
923         return err;
924     }
925     const size_type elements = required / sizeof(T);
926
927     // Temporary to avoid changing param on an error
928     vector<T> localData(elements);
929     err = f(name, required, localData.data(), NULL);
930     if (err != CL_SUCCESS) {
931         return err;
932     }
933     if (param) {
934         *param = std::move(localData);
935     }
936
937     return CL_SUCCESS;
938 }
939
940 /* Specialization for reference-counted types. This depends on the
941  * existence of Wrapper<T>::cl_type, and none of the other types having the
942  * cl_type member. Note that simplify specifying the parameter as Wrapper<T>
943  * does not work, because when using a derived type (e.g. Context) the generic
944  * template will provide a better match.
945  */
946 template <typename Func, typename T>
947 inline cl_int getInfoHelper(
948     Func f, cl_uint name, vector<T>* param, int, typename T::cl_type = 0)
949 {
950     size_type required;
951     cl_int err = f(name, 0, NULL, &required);
952     if (err != CL_SUCCESS) {
953         return err;
954     }
955
956     const size_type elements = required / sizeof(typename T::cl_type);
957
958     vector<typename T::cl_type> value(elements);
959     err = f(name, required, value.data(), NULL);
960     if (err != CL_SUCCESS) {
961         return err;
962     }
963
964     if (param) {
965         // Assign to convert CL type to T for each element
966         param->resize(elements);
967
968         // Assign to param, constructing with retain behaviour
969         // to correctly capture each underlying CL object
970         for (size_type i = 0; i < elements; i++) {
971             (*param)[i] = T(value[i], true);
972         }
973     }
974     return CL_SUCCESS;
975 }
976
977 // Specialized GetInfoHelper for string params
978 template <typename Func>
979 inline cl_int getInfoHelper(Func f, cl_uint name, string* param, long)
980 {
981     size_type required;
982     cl_int err = f(name, 0, NULL, &required);
983     if (err != CL_SUCCESS) {
984         return err;
985     }
986
987     // std::string has a constant data member
988     // a char vector does not
989     if (required > 0) {
990         vector<char> value(required);
991         err = f(name, required, value.data(), NULL);
992         if (err != CL_SUCCESS) {
993             return err;
994         }
995         if (param) {
996             param->assign(begin(value), prev(end(value)));
997         }
998     }
999     else if (param) {
1000         param->assign("");
1001     }
1002     return CL_SUCCESS;
1003 }
1004
1005 // Specialized GetInfoHelper for clsize_t params
1006 template <typename Func, size_type N>
1007 inline cl_int getInfoHelper(Func f, cl_uint name, array<size_type, N>* param, long)
1008 {
1009     size_type required;
1010     cl_int err = f(name, 0, NULL, &required);
1011     if (err != CL_SUCCESS) {
1012         return err;
1013     }
1014
1015     size_type elements = required / sizeof(size_type);
1016     vector<size_type> value(elements, 0);
1017
1018     err = f(name, required, value.data(), NULL);
1019     if (err != CL_SUCCESS) {
1020         return err;
1021     }
1022     
1023     // Bound the copy with N to prevent overruns
1024     // if passed N > than the amount copied
1025     if (elements > N) {
1026         elements = N;
1027     }
1028     for (size_type i = 0; i < elements; ++i) {
1029         (*param)[i] = value[i];
1030     }
1031
1032     return CL_SUCCESS;
1033 }
1034
1035 template<typename T> struct ReferenceHandler;
1036
1037 /* Specialization for reference-counted types. This depends on the
1038  * existence of Wrapper<T>::cl_type, and none of the other types having the
1039  * cl_type member. Note that simplify specifying the parameter as Wrapper<T>
1040  * does not work, because when using a derived type (e.g. Context) the generic
1041  * template will provide a better match.
1042  */
1043 template<typename Func, typename T>
1044 inline cl_int getInfoHelper(Func f, cl_uint name, T* param, int, typename T::cl_type = 0)
1045 {
1046     typename T::cl_type value;
1047     cl_int err = f(name, sizeof(value), &value, NULL);
1048     if (err != CL_SUCCESS) {
1049         return err;
1050     }
1051     *param = value;
1052     if (value != NULL)
1053     {
1054         err = param->retain();
1055         if (err != CL_SUCCESS) {
1056             return err;
1057         }
1058     }
1059     return CL_SUCCESS;
1060 }
1061
1062 #define CL_HPP_PARAM_NAME_INFO_1_0_(F) \
1063     F(cl_platform_info, CL_PLATFORM_PROFILE, string) \
1064     F(cl_platform_info, CL_PLATFORM_VERSION, string) \
1065     F(cl_platform_info, CL_PLATFORM_NAME, string) \
1066     F(cl_platform_info, CL_PLATFORM_VENDOR, string) \
1067     F(cl_platform_info, CL_PLATFORM_EXTENSIONS, string) \
1068     \
1069     F(cl_device_info, CL_DEVICE_TYPE, cl_device_type) \
1070     F(cl_device_info, CL_DEVICE_VENDOR_ID, cl_uint) \
1071     F(cl_device_info, CL_DEVICE_MAX_COMPUTE_UNITS, cl_uint) \
1072     F(cl_device_info, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, cl_uint) \
1073     F(cl_device_info, CL_DEVICE_MAX_WORK_GROUP_SIZE, size_type) \
1074     F(cl_device_info, CL_DEVICE_MAX_WORK_ITEM_SIZES, cl::vector<size_type>) \
1075     F(cl_device_info, CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR, cl_uint) \
1076     F(cl_device_info, CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT, cl_uint) \
1077     F(cl_device_info, CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT, cl_uint) \
1078     F(cl_device_info, CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG, cl_uint) \
1079     F(cl_device_info, CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT, cl_uint) \
1080     F(cl_device_info, CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE, cl_uint) \
1081     F(cl_device_info, CL_DEVICE_MAX_CLOCK_FREQUENCY, cl_uint) \
1082     F(cl_device_info, CL_DEVICE_ADDRESS_BITS, cl_uint) \
1083     F(cl_device_info, CL_DEVICE_MAX_READ_IMAGE_ARGS, cl_uint) \
1084     F(cl_device_info, CL_DEVICE_MAX_WRITE_IMAGE_ARGS, cl_uint) \
1085     F(cl_device_info, CL_DEVICE_MAX_MEM_ALLOC_SIZE, cl_ulong) \
1086     F(cl_device_info, CL_DEVICE_IMAGE2D_MAX_WIDTH, size_type) \
1087     F(cl_device_info, CL_DEVICE_IMAGE2D_MAX_HEIGHT, size_type) \
1088     F(cl_device_info, CL_DEVICE_IMAGE3D_MAX_WIDTH, size_type) \
1089     F(cl_device_info, CL_DEVICE_IMAGE3D_MAX_HEIGHT, size_type) \
1090     F(cl_device_info, CL_DEVICE_IMAGE3D_MAX_DEPTH, size_type) \
1091     F(cl_device_info, CL_DEVICE_IMAGE_SUPPORT, cl_bool) \
1092     F(cl_device_info, CL_DEVICE_MAX_PARAMETER_SIZE, size_type) \
1093     F(cl_device_info, CL_DEVICE_MAX_SAMPLERS, cl_uint) \
1094     F(cl_device_info, CL_DEVICE_MEM_BASE_ADDR_ALIGN, cl_uint) \
1095     F(cl_device_info, CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE, cl_uint) \
1096     F(cl_device_info, CL_DEVICE_SINGLE_FP_CONFIG, cl_device_fp_config) \
1097     F(cl_device_info, CL_DEVICE_GLOBAL_MEM_CACHE_TYPE, cl_device_mem_cache_type) \
1098     F(cl_device_info, CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE, cl_uint)\
1099     F(cl_device_info, CL_DEVICE_GLOBAL_MEM_CACHE_SIZE, cl_ulong) \
1100     F(cl_device_info, CL_DEVICE_GLOBAL_MEM_SIZE, cl_ulong) \
1101     F(cl_device_info, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE, cl_ulong) \
1102     F(cl_device_info, CL_DEVICE_MAX_CONSTANT_ARGS, cl_uint) \
1103     F(cl_device_info, CL_DEVICE_LOCAL_MEM_TYPE, cl_device_local_mem_type) \
1104     F(cl_device_info, CL_DEVICE_LOCAL_MEM_SIZE, cl_ulong) \
1105     F(cl_device_info, CL_DEVICE_ERROR_CORRECTION_SUPPORT, cl_bool) \
1106     F(cl_device_info, CL_DEVICE_PROFILING_TIMER_RESOLUTION, size_type) \
1107     F(cl_device_info, CL_DEVICE_ENDIAN_LITTLE, cl_bool) \
1108     F(cl_device_info, CL_DEVICE_AVAILABLE, cl_bool) \
1109     F(cl_device_info, CL_DEVICE_COMPILER_AVAILABLE, cl_bool) \
1110     F(cl_device_info, CL_DEVICE_EXECUTION_CAPABILITIES, cl_device_exec_capabilities) \
1111     F(cl_device_info, CL_DEVICE_PLATFORM, cl_platform_id) \
1112     F(cl_device_info, CL_DEVICE_NAME, string) \
1113     F(cl_device_info, CL_DEVICE_VENDOR, string) \
1114     F(cl_device_info, CL_DRIVER_VERSION, string) \
1115     F(cl_device_info, CL_DEVICE_PROFILE, string) \
1116     F(cl_device_info, CL_DEVICE_VERSION, string) \
1117     F(cl_device_info, CL_DEVICE_EXTENSIONS, string) \
1118     \
1119     F(cl_context_info, CL_CONTEXT_REFERENCE_COUNT, cl_uint) \
1120     F(cl_context_info, CL_CONTEXT_DEVICES, cl::vector<Device>) \
1121     F(cl_context_info, CL_CONTEXT_PROPERTIES, cl::vector<cl_context_properties>) \
1122     \
1123     F(cl_event_info, CL_EVENT_COMMAND_QUEUE, cl::CommandQueue) \
1124     F(cl_event_info, CL_EVENT_COMMAND_TYPE, cl_command_type) \
1125     F(cl_event_info, CL_EVENT_REFERENCE_COUNT, cl_uint) \
1126     F(cl_event_info, CL_EVENT_COMMAND_EXECUTION_STATUS, cl_int) \
1127     \
1128     F(cl_profiling_info, CL_PROFILING_COMMAND_QUEUED, cl_ulong) \
1129     F(cl_profiling_info, CL_PROFILING_COMMAND_SUBMIT, cl_ulong) \
1130     F(cl_profiling_info, CL_PROFILING_COMMAND_START, cl_ulong) \
1131     F(cl_profiling_info, CL_PROFILING_COMMAND_END, cl_ulong) \
1132     \
1133     F(cl_mem_info, CL_MEM_TYPE, cl_mem_object_type) \
1134     F(cl_mem_info, CL_MEM_FLAGS, cl_mem_flags) \
1135     F(cl_mem_info, CL_MEM_SIZE, size_type) \
1136     F(cl_mem_info, CL_MEM_HOST_PTR, void*) \
1137     F(cl_mem_info, CL_MEM_MAP_COUNT, cl_uint) \
1138     F(cl_mem_info, CL_MEM_REFERENCE_COUNT, cl_uint) \
1139     F(cl_mem_info, CL_MEM_CONTEXT, cl::Context) \
1140     \
1141     F(cl_image_info, CL_IMAGE_FORMAT, cl_image_format) \
1142     F(cl_image_info, CL_IMAGE_ELEMENT_SIZE, size_type) \
1143     F(cl_image_info, CL_IMAGE_ROW_PITCH, size_type) \
1144     F(cl_image_info, CL_IMAGE_SLICE_PITCH, size_type) \
1145     F(cl_image_info, CL_IMAGE_WIDTH, size_type) \
1146     F(cl_image_info, CL_IMAGE_HEIGHT, size_type) \
1147     F(cl_image_info, CL_IMAGE_DEPTH, size_type) \
1148     \
1149     F(cl_sampler_info, CL_SAMPLER_REFERENCE_COUNT, cl_uint) \
1150     F(cl_sampler_info, CL_SAMPLER_CONTEXT, cl::Context) \
1151     F(cl_sampler_info, CL_SAMPLER_NORMALIZED_COORDS, cl_bool) \
1152     F(cl_sampler_info, CL_SAMPLER_ADDRESSING_MODE, cl_addressing_mode) \
1153     F(cl_sampler_info, CL_SAMPLER_FILTER_MODE, cl_filter_mode) \
1154     \
1155     F(cl_program_info, CL_PROGRAM_REFERENCE_COUNT, cl_uint) \
1156     F(cl_program_info, CL_PROGRAM_CONTEXT, cl::Context) \
1157     F(cl_program_info, CL_PROGRAM_NUM_DEVICES, cl_uint) \
1158     F(cl_program_info, CL_PROGRAM_DEVICES, cl::vector<Device>) \
1159     F(cl_program_info, CL_PROGRAM_SOURCE, string) \
1160     F(cl_program_info, CL_PROGRAM_BINARY_SIZES, cl::vector<size_type>) \
1161     F(cl_program_info, CL_PROGRAM_BINARIES, cl::vector<cl::vector<unsigned char>>) \
1162     \
1163     F(cl_program_build_info, CL_PROGRAM_BUILD_STATUS, cl_build_status) \
1164     F(cl_program_build_info, CL_PROGRAM_BUILD_OPTIONS, string) \
1165     F(cl_program_build_info, CL_PROGRAM_BUILD_LOG, string) \
1166     \
1167     F(cl_kernel_info, CL_KERNEL_FUNCTION_NAME, string) \
1168     F(cl_kernel_info, CL_KERNEL_NUM_ARGS, cl_uint) \
1169     F(cl_kernel_info, CL_KERNEL_REFERENCE_COUNT, cl_uint) \
1170     F(cl_kernel_info, CL_KERNEL_CONTEXT, cl::Context) \
1171     F(cl_kernel_info, CL_KERNEL_PROGRAM, cl::Program) \
1172     \
1173     F(cl_kernel_work_group_info, CL_KERNEL_WORK_GROUP_SIZE, size_type) \
1174     F(cl_kernel_work_group_info, CL_KERNEL_COMPILE_WORK_GROUP_SIZE, cl::detail::size_t_array) \
1175     F(cl_kernel_work_group_info, CL_KERNEL_LOCAL_MEM_SIZE, cl_ulong) \
1176     \
1177     F(cl_command_queue_info, CL_QUEUE_CONTEXT, cl::Context) \
1178     F(cl_command_queue_info, CL_QUEUE_DEVICE, cl::Device) \
1179     F(cl_command_queue_info, CL_QUEUE_REFERENCE_COUNT, cl_uint) \
1180     F(cl_command_queue_info, CL_QUEUE_PROPERTIES, cl_command_queue_properties)
1181
1182
1183 #define CL_HPP_PARAM_NAME_INFO_1_1_(F) \
1184     F(cl_context_info, CL_CONTEXT_NUM_DEVICES, cl_uint)\
1185     F(cl_device_info, CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF, cl_uint) \
1186     F(cl_device_info, CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR, cl_uint) \
1187     F(cl_device_info, CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT, cl_uint) \
1188     F(cl_device_info, CL_DEVICE_NATIVE_VECTOR_WIDTH_INT, cl_uint) \
1189     F(cl_device_info, CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG, cl_uint) \
1190     F(cl_device_info, CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT, cl_uint) \
1191     F(cl_device_info, CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE, cl_uint) \
1192     F(cl_device_info, CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF, cl_uint) \
1193     F(cl_device_info, CL_DEVICE_DOUBLE_FP_CONFIG, cl_device_fp_config) \
1194     F(cl_device_info, CL_DEVICE_HALF_FP_CONFIG, cl_device_fp_config) \
1195     F(cl_device_info, CL_DEVICE_OPENCL_C_VERSION, string) \
1196     \
1197     F(cl_mem_info, CL_MEM_ASSOCIATED_MEMOBJECT, cl::Memory) \
1198     F(cl_mem_info, CL_MEM_OFFSET, size_type) \
1199     \
1200     F(cl_kernel_work_group_info, CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE, size_type) \
1201     F(cl_kernel_work_group_info, CL_KERNEL_PRIVATE_MEM_SIZE, cl_ulong) \
1202     \
1203     F(cl_event_info, CL_EVENT_CONTEXT, cl::Context)
1204
1205 #define CL_HPP_PARAM_NAME_INFO_1_2_(F) \
1206     F(cl_program_info, CL_PROGRAM_NUM_KERNELS, size_type) \
1207     F(cl_program_info, CL_PROGRAM_KERNEL_NAMES, string) \
1208     \
1209     F(cl_program_build_info, CL_PROGRAM_BINARY_TYPE, cl_program_binary_type) \
1210     \
1211     F(cl_kernel_info, CL_KERNEL_ATTRIBUTES, string) \
1212     \
1213     F(cl_kernel_arg_info, CL_KERNEL_ARG_ADDRESS_QUALIFIER, cl_kernel_arg_address_qualifier) \
1214     F(cl_kernel_arg_info, CL_KERNEL_ARG_ACCESS_QUALIFIER, cl_kernel_arg_access_qualifier) \
1215     F(cl_kernel_arg_info, CL_KERNEL_ARG_TYPE_NAME, string) \
1216     F(cl_kernel_arg_info, CL_KERNEL_ARG_NAME, string) \
1217     F(cl_kernel_arg_info, CL_KERNEL_ARG_TYPE_QUALIFIER, cl_kernel_arg_type_qualifier) \
1218     \
1219     F(cl_device_info, CL_DEVICE_PARENT_DEVICE, cl::Device) \
1220     F(cl_device_info, CL_DEVICE_PARTITION_PROPERTIES, cl::vector<cl_device_partition_property>) \
1221     F(cl_device_info, CL_DEVICE_PARTITION_TYPE, cl::vector<cl_device_partition_property>)  \
1222     F(cl_device_info, CL_DEVICE_REFERENCE_COUNT, cl_uint) \
1223     F(cl_device_info, CL_DEVICE_PREFERRED_INTEROP_USER_SYNC, size_type) \
1224     F(cl_device_info, CL_DEVICE_PARTITION_AFFINITY_DOMAIN, cl_device_affinity_domain) \
1225     F(cl_device_info, CL_DEVICE_BUILT_IN_KERNELS, string) \
1226     \
1227     F(cl_image_info, CL_IMAGE_ARRAY_SIZE, size_type) \
1228     F(cl_image_info, CL_IMAGE_NUM_MIP_LEVELS, cl_uint) \
1229     F(cl_image_info, CL_IMAGE_NUM_SAMPLES, cl_uint)
1230
1231 #define CL_HPP_PARAM_NAME_INFO_2_0_(F) \
1232     F(cl_device_info, CL_DEVICE_QUEUE_ON_HOST_PROPERTIES, cl_command_queue_properties) \
1233     F(cl_device_info, CL_DEVICE_QUEUE_ON_DEVICE_PROPERTIES, cl_command_queue_properties) \
1234     F(cl_device_info, CL_DEVICE_QUEUE_ON_DEVICE_PREFERRED_SIZE, cl_uint) \
1235     F(cl_device_info, CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE, cl_uint) \
1236     F(cl_device_info, CL_DEVICE_MAX_ON_DEVICE_QUEUES, cl_uint) \
1237     F(cl_device_info, CL_DEVICE_MAX_ON_DEVICE_EVENTS, cl_uint) \
1238     F(cl_device_info, CL_DEVICE_MAX_PIPE_ARGS, cl_uint) \
1239     F(cl_device_info, CL_DEVICE_PIPE_MAX_ACTIVE_RESERVATIONS, cl_uint) \
1240     F(cl_device_info, CL_DEVICE_PIPE_MAX_PACKET_SIZE, cl_uint) \
1241     F(cl_device_info, CL_DEVICE_SVM_CAPABILITIES, cl_device_svm_capabilities) \
1242     F(cl_device_info, CL_DEVICE_PREFERRED_PLATFORM_ATOMIC_ALIGNMENT, cl_uint) \
1243     F(cl_device_info, CL_DEVICE_PREFERRED_GLOBAL_ATOMIC_ALIGNMENT, cl_uint) \
1244     F(cl_device_info, CL_DEVICE_PREFERRED_LOCAL_ATOMIC_ALIGNMENT, cl_uint) \
1245     F(cl_command_queue_info, CL_QUEUE_SIZE, cl_uint) \
1246     F(cl_mem_info, CL_MEM_USES_SVM_POINTER, cl_bool) \
1247     F(cl_program_build_info, CL_PROGRAM_BUILD_GLOBAL_VARIABLE_TOTAL_SIZE, size_type) \
1248     F(cl_pipe_info, CL_PIPE_PACKET_SIZE, cl_uint) \
1249     F(cl_pipe_info, CL_PIPE_MAX_PACKETS, cl_uint)
1250
1251 #define CL_HPP_PARAM_NAME_DEVICE_FISSION_(F) \
1252     F(cl_device_info, CL_DEVICE_PARENT_DEVICE_EXT, cl_device_id) \
1253     F(cl_device_info, CL_DEVICE_PARTITION_TYPES_EXT, cl::vector<cl_device_partition_property_ext>) \
1254     F(cl_device_info, CL_DEVICE_AFFINITY_DOMAINS_EXT, cl::vector<cl_device_partition_property_ext>) \
1255     F(cl_device_info, CL_DEVICE_REFERENCE_COUNT_EXT , cl_uint) \
1256     F(cl_device_info, CL_DEVICE_PARTITION_STYLE_EXT, cl::vector<cl_device_partition_property_ext>)
1257
1258 template <typename enum_type, cl_int Name>
1259 struct param_traits {};
1260
1261 #define CL_HPP_DECLARE_PARAM_TRAITS_(token, param_name, T) \
1262 struct token;                                        \
1263 template<>                                           \
1264 struct param_traits<detail:: token,param_name>       \
1265 {                                                    \
1266     enum { value = param_name };                     \
1267     typedef T param_type;                            \
1268 };
1269
1270 CL_HPP_PARAM_NAME_INFO_1_0_(CL_HPP_DECLARE_PARAM_TRAITS_)
1271 #if CL_HPP_TARGET_OPENCL_VERSION >= 110
1272 CL_HPP_PARAM_NAME_INFO_1_1_(CL_HPP_DECLARE_PARAM_TRAITS_)
1273 #endif // CL_HPP_TARGET_OPENCL_VERSION >= 110
1274 #if CL_HPP_TARGET_OPENCL_VERSION >= 120
1275 CL_HPP_PARAM_NAME_INFO_1_2_(CL_HPP_DECLARE_PARAM_TRAITS_)
1276 #endif // CL_HPP_TARGET_OPENCL_VERSION >= 110
1277 #if CL_HPP_TARGET_OPENCL_VERSION >= 200
1278 CL_HPP_PARAM_NAME_INFO_2_0_(CL_HPP_DECLARE_PARAM_TRAITS_)
1279 #endif // CL_HPP_TARGET_OPENCL_VERSION >= 110
1280
1281
1282 // Flags deprecated in OpenCL 2.0
1283 #define CL_HPP_PARAM_NAME_INFO_1_0_DEPRECATED_IN_2_0_(F) \
1284     F(cl_device_info, CL_DEVICE_QUEUE_PROPERTIES, cl_command_queue_properties)
1285
1286 #define CL_HPP_PARAM_NAME_INFO_1_1_DEPRECATED_IN_2_0_(F) \
1287     F(cl_device_info, CL_DEVICE_HOST_UNIFIED_MEMORY, cl_bool)
1288
1289 #define CL_HPP_PARAM_NAME_INFO_1_2_DEPRECATED_IN_2_0_(F) \
1290     F(cl_image_info, CL_IMAGE_BUFFER, cl::Buffer)
1291
1292 // Include deprecated query flags based on versions
1293 // Only include deprecated 1.0 flags if 2.0 not active as there is an enum clash
1294 #if CL_HPP_TARGET_OPENCL_VERSION > 100 && CL_HPP_MINIMUM_OPENCL_VERSION < 200 && CL_HPP_TARGET_OPENCL_VERSION < 200
1295 CL_HPP_PARAM_NAME_INFO_1_0_DEPRECATED_IN_2_0_(CL_HPP_DECLARE_PARAM_TRAITS_)
1296 #endif // CL_HPP_MINIMUM_OPENCL_VERSION < 110
1297 #if CL_HPP_TARGET_OPENCL_VERSION > 110 && CL_HPP_MINIMUM_OPENCL_VERSION < 200
1298 CL_HPP_PARAM_NAME_INFO_1_1_DEPRECATED_IN_2_0_(CL_HPP_DECLARE_PARAM_TRAITS_)
1299 #endif // CL_HPP_MINIMUM_OPENCL_VERSION < 120
1300 #if CL_HPP_TARGET_OPENCL_VERSION > 120 && CL_HPP_MINIMUM_OPENCL_VERSION < 200
1301 CL_HPP_PARAM_NAME_INFO_1_2_DEPRECATED_IN_2_0_(CL_HPP_DECLARE_PARAM_TRAITS_)
1302 #endif // CL_HPP_MINIMUM_OPENCL_VERSION < 200
1303
1304 #if defined(CL_HPP_USE_CL_DEVICE_FISSION)
1305 CL_HPP_PARAM_NAME_DEVICE_FISSION_(CL_HPP_DECLARE_PARAM_TRAITS_);
1306 #endif // CL_HPP_USE_CL_DEVICE_FISSION
1307
1308 #ifdef CL_PLATFORM_ICD_SUFFIX_KHR
1309 CL_HPP_DECLARE_PARAM_TRAITS_(cl_platform_info, CL_PLATFORM_ICD_SUFFIX_KHR, string)
1310 #endif
1311
1312 #ifdef CL_DEVICE_PROFILING_TIMER_OFFSET_AMD
1313 CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_PROFILING_TIMER_OFFSET_AMD, cl_ulong)
1314 #endif
1315
1316 #ifdef CL_DEVICE_GLOBAL_FREE_MEMORY_AMD
1317 CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_GLOBAL_FREE_MEMORY_AMD, vector<size_type>)
1318 #endif
1319 #ifdef CL_DEVICE_SIMD_PER_COMPUTE_UNIT_AMD
1320 CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_SIMD_PER_COMPUTE_UNIT_AMD, cl_uint)
1321 #endif
1322 #ifdef CL_DEVICE_SIMD_WIDTH_AMD
1323 CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_SIMD_WIDTH_AMD, cl_uint)
1324 #endif
1325 #ifdef CL_DEVICE_SIMD_INSTRUCTION_WIDTH_AMD
1326 CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_SIMD_INSTRUCTION_WIDTH_AMD, cl_uint)
1327 #endif
1328 #ifdef CL_DEVICE_WAVEFRONT_WIDTH_AMD
1329 CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_WAVEFRONT_WIDTH_AMD, cl_uint)
1330 #endif
1331 #ifdef CL_DEVICE_GLOBAL_MEM_CHANNELS_AMD
1332 CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_GLOBAL_MEM_CHANNELS_AMD, cl_uint)
1333 #endif
1334 #ifdef CL_DEVICE_GLOBAL_MEM_CHANNEL_BANKS_AMD
1335 CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_GLOBAL_MEM_CHANNEL_BANKS_AMD, cl_uint)
1336 #endif
1337 #ifdef CL_DEVICE_GLOBAL_MEM_CHANNEL_BANK_WIDTH_AMD
1338 CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_GLOBAL_MEM_CHANNEL_BANK_WIDTH_AMD, cl_uint)
1339 #endif
1340 #ifdef CL_DEVICE_LOCAL_MEM_SIZE_PER_COMPUTE_UNIT_AMD
1341 CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_LOCAL_MEM_SIZE_PER_COMPUTE_UNIT_AMD, cl_uint)
1342 #endif
1343 #ifdef CL_DEVICE_LOCAL_MEM_BANKS_AMD
1344 CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_LOCAL_MEM_BANKS_AMD, cl_uint)
1345 #endif
1346
1347 #ifdef CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV
1348 CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV, cl_uint)
1349 #endif
1350 #ifdef CL_DEVICE_COMPUTE_CAPABILITY_MINOR_NV
1351 CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_COMPUTE_CAPABILITY_MINOR_NV, cl_uint)
1352 #endif
1353 #ifdef CL_DEVICE_REGISTERS_PER_BLOCK_NV
1354 CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_REGISTERS_PER_BLOCK_NV, cl_uint)
1355 #endif
1356 #ifdef CL_DEVICE_WARP_SIZE_NV
1357 CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_WARP_SIZE_NV, cl_uint)
1358 #endif
1359 #ifdef CL_DEVICE_GPU_OVERLAP_NV
1360 CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_GPU_OVERLAP_NV, cl_bool)
1361 #endif
1362 #ifdef CL_DEVICE_KERNEL_EXEC_TIMEOUT_NV
1363 CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_KERNEL_EXEC_TIMEOUT_NV, cl_bool)
1364 #endif
1365 #ifdef CL_DEVICE_INTEGRATED_MEMORY_NV
1366 CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_INTEGRATED_MEMORY_NV, cl_bool)
1367 #endif
1368
1369 // Convenience functions
1370
1371 template <typename Func, typename T>
1372 inline cl_int
1373 getInfo(Func f, cl_uint name, T* param)
1374 {
1375     return getInfoHelper(f, name, param, 0);
1376 }
1377
1378 template <typename Func, typename Arg0>
1379 struct GetInfoFunctor0
1380 {
1381     Func f_; const Arg0& arg0_;
1382     cl_int operator ()(
1383         cl_uint param, size_type size, void* value, size_type* size_ret)
1384     { return f_(arg0_, param, size, value, size_ret); }
1385 };
1386
1387 template <typename Func, typename Arg0, typename Arg1>
1388 struct GetInfoFunctor1
1389 {
1390     Func f_; const Arg0& arg0_; const Arg1& arg1_;
1391     cl_int operator ()(
1392         cl_uint param, size_type size, void* value, size_type* size_ret)
1393     { return f_(arg0_, arg1_, param, size, value, size_ret); }
1394 };
1395
1396 template <typename Func, typename Arg0, typename T>
1397 inline cl_int
1398 getInfo(Func f, const Arg0& arg0, cl_uint name, T* param)
1399 {
1400     GetInfoFunctor0<Func, Arg0> f0 = { f, arg0 };
1401     return getInfoHelper(f0, name, param, 0);
1402 }
1403
1404 template <typename Func, typename Arg0, typename Arg1, typename T>
1405 inline cl_int
1406 getInfo(Func f, const Arg0& arg0, const Arg1& arg1, cl_uint name, T* param)
1407 {
1408     GetInfoFunctor1<Func, Arg0, Arg1> f0 = { f, arg0, arg1 };
1409     return getInfoHelper(f0, name, param, 0);
1410 }
1411
1412
1413 template<typename T>
1414 struct ReferenceHandler
1415 { };
1416
1417 #if CL_HPP_TARGET_OPENCL_VERSION >= 120
1418 /**
1419  * OpenCL 1.2 devices do have retain/release.
1420  */
1421 template <>
1422 struct ReferenceHandler<cl_device_id>
1423 {
1424     /**
1425      * Retain the device.
1426      * \param device A valid device created using createSubDevices
1427      * \return 
1428      *   CL_SUCCESS if the function executed successfully.
1429      *   CL_INVALID_DEVICE if device was not a valid subdevice
1430      *   CL_OUT_OF_RESOURCES
1431      *   CL_OUT_OF_HOST_MEMORY
1432      */
1433     static cl_int retain(cl_device_id device)
1434     { return ::clRetainDevice(device); }
1435     /**
1436      * Retain the device.
1437      * \param device A valid device created using createSubDevices
1438      * \return 
1439      *   CL_SUCCESS if the function executed successfully.
1440      *   CL_INVALID_DEVICE if device was not a valid subdevice
1441      *   CL_OUT_OF_RESOURCES
1442      *   CL_OUT_OF_HOST_MEMORY
1443      */
1444     static cl_int release(cl_device_id device)
1445     { return ::clReleaseDevice(device); }
1446 };
1447 #else // CL_HPP_TARGET_OPENCL_VERSION >= 120
1448 /**
1449  * OpenCL 1.1 devices do not have retain/release.
1450  */
1451 template <>
1452 struct ReferenceHandler<cl_device_id>
1453 {
1454     // cl_device_id does not have retain().
1455     static cl_int retain(cl_device_id)
1456     { return CL_SUCCESS; }
1457     // cl_device_id does not have release().
1458     static cl_int release(cl_device_id)
1459     { return CL_SUCCESS; }
1460 };
1461 #endif // ! (CL_HPP_TARGET_OPENCL_VERSION >= 120)
1462
1463 template <>
1464 struct ReferenceHandler<cl_platform_id>
1465 {
1466     // cl_platform_id does not have retain().
1467     static cl_int retain(cl_platform_id)
1468     { return CL_SUCCESS; }
1469     // cl_platform_id does not have release().
1470     static cl_int release(cl_platform_id)
1471     { return CL_SUCCESS; }
1472 };
1473
1474 template <>
1475 struct ReferenceHandler<cl_context>
1476 {
1477     static cl_int retain(cl_context context)
1478     { return ::clRetainContext(context); }
1479     static cl_int release(cl_context context)
1480     { return ::clReleaseContext(context); }
1481 };
1482
1483 template <>
1484 struct ReferenceHandler<cl_command_queue>
1485 {
1486     static cl_int retain(cl_command_queue queue)
1487     { return ::clRetainCommandQueue(queue); }
1488     static cl_int release(cl_command_queue queue)
1489     { return ::clReleaseCommandQueue(queue); }
1490 };
1491
1492 template <>
1493 struct ReferenceHandler<cl_mem>
1494 {
1495     static cl_int retain(cl_mem memory)
1496     { return ::clRetainMemObject(memory); }
1497     static cl_int release(cl_mem memory)
1498     { return ::clReleaseMemObject(memory); }
1499 };
1500
1501 template <>
1502 struct ReferenceHandler<cl_sampler>
1503 {
1504     static cl_int retain(cl_sampler sampler)
1505     { return ::clRetainSampler(sampler); }
1506     static cl_int release(cl_sampler sampler)
1507     { return ::clReleaseSampler(sampler); }
1508 };
1509
1510 template <>
1511 struct ReferenceHandler<cl_program>
1512 {
1513     static cl_int retain(cl_program program)
1514     { return ::clRetainProgram(program); }
1515     static cl_int release(cl_program program)
1516     { return ::clReleaseProgram(program); }
1517 };
1518
1519 template <>
1520 struct ReferenceHandler<cl_kernel>
1521 {
1522     static cl_int retain(cl_kernel kernel)
1523     { return ::clRetainKernel(kernel); }
1524     static cl_int release(cl_kernel kernel)
1525     { return ::clReleaseKernel(kernel); }
1526 };
1527
1528 template <>
1529 struct ReferenceHandler<cl_event>
1530 {
1531     static cl_int retain(cl_event event)
1532     { return ::clRetainEvent(event); }
1533     static cl_int release(cl_event event)
1534     { return ::clReleaseEvent(event); }
1535 };
1536
1537 #if CL_HPP_TARGET_OPENCL_VERSION >= 120 && CL_HPP_MINIMUM_OPENCL_VERSION < 120
1538
1539 // Extracts version number with major in the upper 16 bits, minor in the lower 16
1540 static cl_uint getVersion(const vector<char> &versionInfo)
1541 {
1542     int highVersion = 0;
1543     int lowVersion = 0;
1544     int index = 7;
1545     while(versionInfo[index] != '.' ) {
1546         highVersion *= 10;
1547         highVersion += versionInfo[index]-'0';
1548         ++index;
1549     }
1550     ++index;
1551     while(versionInfo[index] != ' ' &&  versionInfo[index] != '\0') {
1552         lowVersion *= 10;
1553         lowVersion += versionInfo[index]-'0';
1554         ++index;
1555     }
1556     return (highVersion << 16) | lowVersion;
1557 }
1558
1559
1560 static cl_uint getPlatformVersion(cl_platform_id platform)
1561 {
1562     size_type size = 0;
1563     clGetPlatformInfo(platform, CL_PLATFORM_VERSION, 0, NULL, &size);
1564     
1565     vector<char> versionInfo(size);
1566     clGetPlatformInfo(platform, CL_PLATFORM_VERSION, size, versionInfo.data(), &size);
1567     return getVersion(versionInfo);
1568 }
1569
1570 static cl_uint getDevicePlatformVersion(cl_device_id device)
1571 {
1572     cl_platform_id platform;
1573     clGetDeviceInfo(device, CL_DEVICE_PLATFORM, sizeof(platform), &platform, NULL);
1574     return getPlatformVersion(platform);
1575 }
1576
1577 static cl_uint getContextPlatformVersion(cl_context context)
1578 {
1579     // The platform cannot be queried directly, so we first have to grab a
1580     // device and obtain its context
1581     size_type size = 0;
1582     clGetContextInfo(context, CL_CONTEXT_DEVICES, 0, NULL, &size);
1583     if (size == 0)
1584         return 0;
1585     vector<cl_device_id> devices(size/sizeof(cl_device_id));
1586     clGetContextInfo(context, CL_CONTEXT_DEVICES, size, devices.data(), NULL);
1587     return getDevicePlatformVersion(devices[0]);
1588 }
1589 #endif // CL_HPP_TARGET_OPENCL_VERSION >= 120 && CL_HPP_MINIMUM_OPENCL_VERSION < 120
1590
1591 template <typename T>
1592 class Wrapper
1593 {
1594 public:
1595     typedef T cl_type;
1596
1597 protected:
1598     cl_type object_;
1599
1600 public:
1601     Wrapper() : object_(NULL) { }
1602     
1603     Wrapper(const cl_type &obj, bool retainObject) : object_(obj) 
1604     {
1605         if (retainObject) { 
1606             detail::errHandler(retain(), __RETAIN_ERR); 
1607         }
1608     }
1609
1610     ~Wrapper()
1611     {
1612         if (object_ != NULL) { release(); }
1613     }
1614
1615     Wrapper(const Wrapper<cl_type>& rhs)
1616     {
1617         object_ = rhs.object_;
1618         detail::errHandler(retain(), __RETAIN_ERR);
1619     }
1620
1621     Wrapper(Wrapper<cl_type>&& rhs) CL_HPP_NOEXCEPT_
1622     {
1623         object_ = rhs.object_;
1624         rhs.object_ = NULL;
1625     }
1626
1627     Wrapper<cl_type>& operator = (const Wrapper<cl_type>& rhs)
1628     {
1629         if (this != &rhs) {
1630             detail::errHandler(release(), __RELEASE_ERR);
1631             object_ = rhs.object_;
1632             detail::errHandler(retain(), __RETAIN_ERR);
1633         }
1634         return *this;
1635     }
1636
1637     Wrapper<cl_type>& operator = (Wrapper<cl_type>&& rhs)
1638     {
1639         if (this != &rhs) {
1640             detail::errHandler(release(), __RELEASE_ERR);
1641             object_ = rhs.object_;
1642             rhs.object_ = NULL;
1643         }
1644         return *this;
1645     }
1646
1647     Wrapper<cl_type>& operator = (const cl_type &rhs)
1648     {
1649         detail::errHandler(release(), __RELEASE_ERR);
1650         object_ = rhs;
1651         return *this;
1652     }
1653
1654     const cl_type& operator ()() const { return object_; }
1655
1656     cl_type& operator ()() { return object_; }
1657
1658     const cl_type get() const { return object_; }
1659
1660     cl_type get() { return object_; }
1661
1662
1663 protected:
1664     template<typename Func, typename U>
1665     friend inline cl_int getInfoHelper(Func, cl_uint, U*, int, typename U::cl_type);
1666
1667     cl_int retain() const
1668     {
1669         if (object_ != nullptr) {
1670             return ReferenceHandler<cl_type>::retain(object_);
1671         }
1672         else {
1673             return CL_SUCCESS;
1674         }
1675     }
1676
1677     cl_int release() const
1678     {
1679         if (object_ != nullptr) {
1680             return ReferenceHandler<cl_type>::release(object_);
1681         }
1682         else {
1683             return CL_SUCCESS;
1684         }
1685     }
1686 };
1687
1688 template <>
1689 class Wrapper<cl_device_id>
1690 {
1691 public:
1692     typedef cl_device_id cl_type;
1693
1694 protected:
1695     cl_type object_;
1696     bool referenceCountable_;
1697
1698     static bool isReferenceCountable(cl_device_id device)
1699     {
1700         bool retVal = false;
1701 #if CL_HPP_TARGET_OPENCL_VERSION >= 120
1702 #if CL_HPP_MINIMUM_OPENCL_VERSION < 120
1703         if (device != NULL) {
1704             int version = getDevicePlatformVersion(device);
1705             if(version > ((1 << 16) + 1)) {
1706                 retVal = true;
1707             }
1708         }
1709 #else // CL_HPP_MINIMUM_OPENCL_VERSION < 120
1710         retVal = true;
1711 #endif // CL_HPP_MINIMUM_OPENCL_VERSION < 120
1712 #endif // CL_HPP_TARGET_OPENCL_VERSION >= 120
1713         return retVal;
1714     }
1715
1716 public:
1717     Wrapper() : object_(NULL), referenceCountable_(false) 
1718     { 
1719     }
1720     
1721     Wrapper(const cl_type &obj, bool retainObject) : 
1722         object_(obj), 
1723         referenceCountable_(false) 
1724     {
1725         referenceCountable_ = isReferenceCountable(obj); 
1726
1727         if (retainObject) {
1728             detail::errHandler(retain(), __RETAIN_ERR);
1729         }
1730     }
1731
1732     ~Wrapper()
1733     {
1734         release();
1735     }
1736     
1737     Wrapper(const Wrapper<cl_type>& rhs)
1738     {
1739         object_ = rhs.object_;
1740         referenceCountable_ = isReferenceCountable(object_); 
1741         detail::errHandler(retain(), __RETAIN_ERR);
1742     }
1743
1744     Wrapper(Wrapper<cl_type>&& rhs) CL_HPP_NOEXCEPT_
1745     {
1746         object_ = rhs.object_;
1747         referenceCountable_ = rhs.referenceCountable_;
1748         rhs.object_ = NULL;
1749         rhs.referenceCountable_ = false;
1750     }
1751
1752     Wrapper<cl_type>& operator = (const Wrapper<cl_type>& rhs)
1753     {
1754         if (this != &rhs) {
1755             detail::errHandler(release(), __RELEASE_ERR);
1756             object_ = rhs.object_;
1757             referenceCountable_ = rhs.referenceCountable_;
1758             detail::errHandler(retain(), __RETAIN_ERR);
1759         }
1760         return *this;
1761     }
1762
1763     Wrapper<cl_type>& operator = (Wrapper<cl_type>&& rhs)
1764     {
1765         if (this != &rhs) {
1766             detail::errHandler(release(), __RELEASE_ERR);
1767             object_ = rhs.object_;
1768             referenceCountable_ = rhs.referenceCountable_;
1769             rhs.object_ = NULL;
1770             rhs.referenceCountable_ = false;
1771         }
1772         return *this;
1773     }
1774
1775     Wrapper<cl_type>& operator = (const cl_type &rhs)
1776     {
1777         detail::errHandler(release(), __RELEASE_ERR);
1778         object_ = rhs;
1779         referenceCountable_ = isReferenceCountable(object_); 
1780         return *this;
1781     }
1782
1783     const cl_type& operator ()() const { return object_; }
1784
1785     cl_type& operator ()() { return object_; }
1786
1787     const cl_type get() const { return object_; }
1788
1789     cl_type get() { return object_; }
1790
1791 protected:
1792     template<typename Func, typename U>
1793     friend inline cl_int getInfoHelper(Func, cl_uint, U*, int, typename U::cl_type);
1794
1795     template<typename Func, typename U>
1796     friend inline cl_int getInfoHelper(Func, cl_uint, vector<U>*, int, typename U::cl_type);
1797
1798     cl_int retain() const
1799     {
1800         if( object_ != nullptr && referenceCountable_ ) {
1801             return ReferenceHandler<cl_type>::retain(object_);
1802         }
1803         else {
1804             return CL_SUCCESS;
1805         }
1806     }
1807
1808     cl_int release() const
1809     {
1810         if (object_ != nullptr && referenceCountable_) {
1811             return ReferenceHandler<cl_type>::release(object_);
1812         }
1813         else {
1814             return CL_SUCCESS;
1815         }
1816     }
1817 };
1818
1819 template <typename T>
1820 inline bool operator==(const Wrapper<T> &lhs, const Wrapper<T> &rhs)
1821 {
1822     return lhs() == rhs();
1823 }
1824
1825 template <typename T>
1826 inline bool operator!=(const Wrapper<T> &lhs, const Wrapper<T> &rhs)
1827 {
1828     return !operator==(lhs, rhs);
1829 }
1830
1831 } // namespace detail
1832 //! \endcond
1833
1834
1835 using BuildLogType = vector<std::pair<cl::Device, typename detail::param_traits<detail::cl_program_build_info, CL_PROGRAM_BUILD_LOG>::param_type>>;
1836 #if defined(CL_HPP_ENABLE_EXCEPTIONS)
1837 /**
1838 * Exception class for build errors to carry build info
1839 */
1840 class BuildError : public Error
1841 {
1842 private:
1843     BuildLogType buildLogs;
1844 public:
1845     BuildError(cl_int err, const char * errStr, const BuildLogType &vec) : Error(err, errStr), buildLogs(vec)
1846     {
1847     }
1848
1849     BuildLogType getBuildLog() const
1850     {
1851         return buildLogs;
1852     }
1853 };
1854 namespace detail {
1855     static inline cl_int buildErrHandler(
1856         cl_int err,
1857         const char * errStr,
1858         const BuildLogType &buildLogs)
1859     {
1860         if (err != CL_SUCCESS) {
1861             throw BuildError(err, errStr, buildLogs);
1862         }
1863         return err;
1864     }
1865 } // namespace detail
1866
1867 #else
1868 namespace detail {
1869     static inline cl_int buildErrHandler(
1870         cl_int err,
1871         const char * errStr,
1872         const BuildLogType &buildLogs)
1873     {
1874         (void)buildLogs; // suppress unused variable warning
1875         (void)errStr;
1876         return err;
1877     }
1878 } // namespace detail
1879 #endif // #if defined(CL_HPP_ENABLE_EXCEPTIONS)
1880
1881
1882 /*! \stuct ImageFormat
1883  *  \brief Adds constructors and member functions for cl_image_format.
1884  *
1885  *  \see cl_image_format
1886  */
1887 struct ImageFormat : public cl_image_format
1888 {
1889     //! \brief Default constructor - performs no initialization.
1890     ImageFormat(){}
1891
1892     //! \brief Initializing constructor.
1893     ImageFormat(cl_channel_order order, cl_channel_type type)
1894     {
1895         image_channel_order = order;
1896         image_channel_data_type = type;
1897     }
1898
1899     //! \brief Assignment operator.
1900     ImageFormat& operator = (const ImageFormat& rhs)
1901     {
1902         if (this != &rhs) {
1903             this->image_channel_data_type = rhs.image_channel_data_type;
1904             this->image_channel_order     = rhs.image_channel_order;
1905         }
1906         return *this;
1907     }
1908 };
1909
1910 /*! \brief Class interface for cl_device_id.
1911  *
1912  *  \note Copies of these objects are inexpensive, since they don't 'own'
1913  *        any underlying resources or data structures.
1914  *
1915  *  \see cl_device_id
1916  */
1917 class Device : public detail::Wrapper<cl_device_id>
1918 {
1919 private:
1920     static std::once_flag default_initialized_;
1921     static Device default_;
1922     static cl_int default_error_;
1923
1924     /*! \brief Create the default context.
1925     *
1926     * This sets @c default_ and @c default_error_. It does not throw
1927     * @c cl::Error.
1928     */
1929     static void makeDefault();
1930
1931     /*! \brief Create the default platform from a provided platform.
1932     *
1933     * This sets @c default_. It does not throw
1934     * @c cl::Error.
1935     */
1936     static void makeDefaultProvided(const Device &p) {
1937         default_ = p;
1938     }
1939
1940 public:
1941 #ifdef CL_HPP_UNIT_TEST_ENABLE
1942     /*! \brief Reset the default.
1943     *
1944     * This sets @c default_ to an empty value to support cleanup in
1945     * the unit test framework.
1946     * This function is not thread safe.
1947     */
1948     static void unitTestClearDefault() {
1949         default_ = Device();
1950     }
1951 #endif // #ifdef CL_HPP_UNIT_TEST_ENABLE
1952
1953     //! \brief Default constructor - initializes to NULL.
1954     Device() : detail::Wrapper<cl_type>() { }
1955
1956     /*! \brief Constructor from cl_device_id.
1957      * 
1958      *  This simply copies the device ID value, which is an inexpensive operation.
1959      */
1960     explicit Device(const cl_device_id &device, bool retainObject = false) : 
1961         detail::Wrapper<cl_type>(device, retainObject) { }
1962
1963     /*! \brief Returns the first device on the default context.
1964      *
1965      *  \see Context::getDefault()
1966      */
1967     static Device getDefault(
1968         cl_int *errResult = NULL)
1969     {
1970         std::call_once(default_initialized_, makeDefault);
1971         detail::errHandler(default_error_);
1972         if (errResult != NULL) {
1973             *errResult = default_error_;
1974         }
1975         return default_;
1976     }
1977
1978     /**
1979     * Modify the default device to be used by
1980     * subsequent operations.
1981     * Will only set the default if no default was previously created.
1982     * @return updated default device.
1983     *         Should be compared to the passed value to ensure that it was updated.
1984     */
1985     static Device setDefault(const Device &default_device)
1986     {
1987         std::call_once(default_initialized_, makeDefaultProvided, std::cref(default_device));
1988         detail::errHandler(default_error_);
1989         return default_;
1990     }
1991
1992     /*! \brief Assignment operator from cl_device_id.
1993      * 
1994      *  This simply copies the device ID value, which is an inexpensive operation.
1995      */
1996     Device& operator = (const cl_device_id& rhs)
1997     {
1998         detail::Wrapper<cl_type>::operator=(rhs);
1999         return *this;
2000     }
2001
2002     /*! \brief Copy constructor to forward copy to the superclass correctly.
2003     * Required for MSVC.
2004     */
2005     Device(const Device& dev) : detail::Wrapper<cl_type>(dev) {}
2006
2007     /*! \brief Copy assignment to forward copy to the superclass correctly.
2008     * Required for MSVC.
2009     */
2010     Device& operator = (const Device &dev)
2011     {
2012         detail::Wrapper<cl_type>::operator=(dev);
2013         return *this;
2014     }
2015
2016     /*! \brief Move constructor to forward move to the superclass correctly.
2017     * Required for MSVC.
2018     */
2019     Device(Device&& dev) CL_HPP_NOEXCEPT_ : detail::Wrapper<cl_type>(std::move(dev)) {}
2020
2021     /*! \brief Move assignment to forward move to the superclass correctly.
2022     * Required for MSVC.
2023     */
2024     Device& operator = (Device &&dev)
2025     {
2026         detail::Wrapper<cl_type>::operator=(std::move(dev));
2027         return *this;
2028     }
2029
2030     //! \brief Wrapper for clGetDeviceInfo().
2031     template <typename T>
2032     cl_int getInfo(cl_device_info name, T* param) const
2033     {
2034         return detail::errHandler(
2035             detail::getInfo(&::clGetDeviceInfo, object_, name, param),
2036             __GET_DEVICE_INFO_ERR);
2037     }
2038
2039     //! \brief Wrapper for clGetDeviceInfo() that returns by value.
2040     template <cl_int name> typename
2041     detail::param_traits<detail::cl_device_info, name>::param_type
2042     getInfo(cl_int* err = NULL) const
2043     {
2044         typename detail::param_traits<
2045             detail::cl_device_info, name>::param_type param;
2046         cl_int result = getInfo(name, &param);
2047         if (err != NULL) {
2048             *err = result;
2049         }
2050         return param;
2051     }
2052
2053     /**
2054      * CL 1.2 version
2055      */
2056 #if CL_HPP_TARGET_OPENCL_VERSION >= 120
2057     //! \brief Wrapper for clCreateSubDevices().
2058     cl_int createSubDevices(
2059         const cl_device_partition_property * properties,
2060         vector<Device>* devices)
2061     {
2062         cl_uint n = 0;
2063         cl_int err = clCreateSubDevices(object_, properties, 0, NULL, &n);
2064         if (err != CL_SUCCESS) {
2065             return detail::errHandler(err, __CREATE_SUB_DEVICES_ERR);
2066         }
2067
2068         vector<cl_device_id> ids(n);
2069         err = clCreateSubDevices(object_, properties, n, ids.data(), NULL);
2070         if (err != CL_SUCCESS) {
2071             return detail::errHandler(err, __CREATE_SUB_DEVICES_ERR);
2072         }
2073
2074         // Cannot trivially assign because we need to capture intermediates 
2075         // with safe construction
2076         if (devices) {
2077             devices->resize(ids.size());
2078
2079             // Assign to param, constructing with retain behaviour
2080             // to correctly capture each underlying CL object
2081             for (size_type i = 0; i < ids.size(); i++) {
2082                 // We do not need to retain because this device is being created 
2083                 // by the runtime
2084                 (*devices)[i] = Device(ids[i], false);
2085             }
2086         }
2087
2088         return CL_SUCCESS;
2089     }
2090 #elif defined(CL_HPP_USE_CL_DEVICE_FISSION)
2091
2092 /**
2093  * CL 1.1 version that uses device fission extension.
2094  */
2095     cl_int createSubDevices(
2096         const cl_device_partition_property_ext * properties,
2097         vector<Device>* devices)
2098     {
2099         typedef CL_API_ENTRY cl_int 
2100             ( CL_API_CALL * PFN_clCreateSubDevicesEXT)(
2101                 cl_device_id /*in_device*/,
2102                 const cl_device_partition_property_ext * /* properties */,
2103                 cl_uint /*num_entries*/,
2104                 cl_device_id * /*out_devices*/,
2105                 cl_uint * /*num_devices*/ ) CL_EXT_SUFFIX__VERSION_1_1;
2106
2107         static PFN_clCreateSubDevicesEXT pfn_clCreateSubDevicesEXT = NULL;
2108         CL_HPP_INIT_CL_EXT_FCN_PTR_(clCreateSubDevicesEXT);
2109
2110         cl_uint n = 0;
2111         cl_int err = pfn_clCreateSubDevicesEXT(object_, properties, 0, NULL, &n);
2112         if (err != CL_SUCCESS) {
2113             return detail::errHandler(err, __CREATE_SUB_DEVICES_ERR);
2114         }
2115
2116         vector<cl_device_id> ids(n);
2117         err = pfn_clCreateSubDevicesEXT(object_, properties, n, ids.data(), NULL);
2118         if (err != CL_SUCCESS) {
2119             return detail::errHandler(err, __CREATE_SUB_DEVICES_ERR);
2120         }
2121         // Cannot trivially assign because we need to capture intermediates 
2122         // with safe construction
2123         if (devices) {
2124             devices->resize(ids.size());
2125
2126             // Assign to param, constructing with retain behaviour
2127             // to correctly capture each underlying CL object
2128             for (size_type i = 0; i < ids.size(); i++) {
2129                 // We do not need to retain because this device is being created 
2130                 // by the runtime
2131                 (*devices)[i] = Device(ids[i], false);
2132             }
2133         }
2134         return CL_SUCCESS;
2135     }
2136 #endif // defined(CL_HPP_USE_CL_DEVICE_FISSION)
2137 };
2138
2139 CL_HPP_DEFINE_STATIC_MEMBER_ std::once_flag Device::default_initialized_;
2140 CL_HPP_DEFINE_STATIC_MEMBER_ Device Device::default_;
2141 CL_HPP_DEFINE_STATIC_MEMBER_ cl_int Device::default_error_ = CL_SUCCESS;
2142
2143 /*! \brief Class interface for cl_platform_id.
2144  *
2145  *  \note Copies of these objects are inexpensive, since they don't 'own'
2146  *        any underlying resources or data structures.
2147  *
2148  *  \see cl_platform_id
2149  */
2150 class Platform : public detail::Wrapper<cl_platform_id>
2151 {
2152 private:
2153     static std::once_flag default_initialized_;
2154     static Platform default_;
2155     static cl_int default_error_;
2156
2157     /*! \brief Create the default context.
2158     *
2159     * This sets @c default_ and @c default_error_. It does not throw
2160     * @c cl::Error.
2161     */
2162     static void makeDefault() {
2163         /* Throwing an exception from a call_once invocation does not do
2164         * what we wish, so we catch it and save the error.
2165         */
2166 #if defined(CL_HPP_ENABLE_EXCEPTIONS)
2167         try
2168 #endif
2169         {
2170             // If default wasn't passed ,generate one
2171             // Otherwise set it
2172             cl_uint n = 0;
2173
2174             cl_int err = ::clGetPlatformIDs(0, NULL, &n);
2175             if (err != CL_SUCCESS) {
2176                 default_error_ = err;
2177                 return;
2178             }
2179             if (n == 0) {
2180                 default_error_ = CL_INVALID_PLATFORM;
2181                 return;
2182             }
2183
2184             vector<cl_platform_id> ids(n);
2185             err = ::clGetPlatformIDs(n, ids.data(), NULL);
2186             if (err != CL_SUCCESS) {
2187                 default_error_ = err;
2188                 return;
2189             }
2190
2191             default_ = Platform(ids[0]);
2192         }
2193 #if defined(CL_HPP_ENABLE_EXCEPTIONS)
2194         catch (cl::Error &e) {
2195             default_error_ = e.err();
2196         }
2197 #endif
2198     }
2199
2200     /*! \brief Create the default platform from a provided platform.
2201      *
2202      * This sets @c default_. It does not throw
2203      * @c cl::Error.
2204      */
2205     static void makeDefaultProvided(const Platform &p) {
2206        default_ = p;
2207     }
2208     
2209 public:
2210 #ifdef CL_HPP_UNIT_TEST_ENABLE
2211     /*! \brief Reset the default.
2212     *
2213     * This sets @c default_ to an empty value to support cleanup in
2214     * the unit test framework.
2215     * This function is not thread safe.
2216     */
2217     static void unitTestClearDefault() {
2218         default_ = Platform();
2219     }
2220 #endif // #ifdef CL_HPP_UNIT_TEST_ENABLE
2221
2222     //! \brief Default constructor - initializes to NULL.
2223     Platform() : detail::Wrapper<cl_type>()  { }
2224
2225     /*! \brief Constructor from cl_platform_id.
2226      * 
2227      * \param retainObject will cause the constructor to retain its cl object.
2228      *                     Defaults to false to maintain compatibility with
2229      *                     earlier versions.
2230      *  This simply copies the platform ID value, which is an inexpensive operation.
2231      */
2232     explicit Platform(const cl_platform_id &platform, bool retainObject = false) : 
2233         detail::Wrapper<cl_type>(platform, retainObject) { }
2234
2235     /*! \brief Assignment operator from cl_platform_id.
2236      * 
2237      *  This simply copies the platform ID value, which is an inexpensive operation.
2238      */
2239     Platform& operator = (const cl_platform_id& rhs)
2240     {
2241         detail::Wrapper<cl_type>::operator=(rhs);
2242         return *this;
2243     }
2244
2245     static Platform getDefault(
2246         cl_int *errResult = NULL)
2247     {
2248         std::call_once(default_initialized_, makeDefault);
2249         detail::errHandler(default_error_);
2250         if (errResult != NULL) {
2251             *errResult = default_error_;
2252         }
2253         return default_;
2254     }
2255
2256     /**
2257      * Modify the default platform to be used by 
2258      * subsequent operations.
2259      * Will only set the default if no default was previously created.
2260      * @return updated default platform. 
2261      *         Should be compared to the passed value to ensure that it was updated.
2262      */
2263     static Platform setDefault(const Platform &default_platform)
2264     {
2265         std::call_once(default_initialized_, makeDefaultProvided, std::cref(default_platform));
2266         detail::errHandler(default_error_);
2267         return default_;
2268     }
2269
2270     //! \brief Wrapper for clGetPlatformInfo().
2271     cl_int getInfo(cl_platform_info name, string* param) const
2272     {
2273         return detail::errHandler(
2274             detail::getInfo(&::clGetPlatformInfo, object_, name, param),
2275             __GET_PLATFORM_INFO_ERR);
2276     }
2277
2278     //! \brief Wrapper for clGetPlatformInfo() that returns by value.
2279     template <cl_int name> typename
2280     detail::param_traits<detail::cl_platform_info, name>::param_type
2281     getInfo(cl_int* err = NULL) const
2282     {
2283         typename detail::param_traits<
2284             detail::cl_platform_info, name>::param_type param;
2285         cl_int result = getInfo(name, &param);
2286         if (err != NULL) {
2287             *err = result;
2288         }
2289         return param;
2290     }
2291
2292     /*! \brief Gets a list of devices for this platform.
2293      * 
2294      *  Wraps clGetDeviceIDs().
2295      */
2296     cl_int getDevices(
2297         cl_device_type type,
2298         vector<Device>* devices) const
2299     {
2300         cl_uint n = 0;
2301         if( devices == NULL ) {
2302             return detail::errHandler(CL_INVALID_ARG_VALUE, __GET_DEVICE_IDS_ERR);
2303         }
2304         cl_int err = ::clGetDeviceIDs(object_, type, 0, NULL, &n);
2305         if (err != CL_SUCCESS) {
2306             return detail::errHandler(err, __GET_DEVICE_IDS_ERR);
2307         }
2308
2309         vector<cl_device_id> ids(n);
2310         err = ::clGetDeviceIDs(object_, type, n, ids.data(), NULL);
2311         if (err != CL_SUCCESS) {
2312             return detail::errHandler(err, __GET_DEVICE_IDS_ERR);
2313         }
2314
2315         // Cannot trivially assign because we need to capture intermediates 
2316         // with safe construction
2317         // We must retain things we obtain from the API to avoid releasing
2318         // API-owned objects.
2319         if (devices) {
2320             devices->resize(ids.size());
2321
2322             // Assign to param, constructing with retain behaviour
2323             // to correctly capture each underlying CL object
2324             for (size_type i = 0; i < ids.size(); i++) {
2325                 (*devices)[i] = Device(ids[i], true);
2326             }
2327         }
2328         return CL_SUCCESS;
2329     }
2330
2331 #if defined(CL_HPP_USE_DX_INTEROP)
2332    /*! \brief Get the list of available D3D10 devices.
2333      *
2334      *  \param d3d_device_source.
2335      *
2336      *  \param d3d_object.
2337      *
2338      *  \param d3d_device_set.
2339      *
2340      *  \param devices returns a vector of OpenCL D3D10 devices found. The cl::Device
2341      *  values returned in devices can be used to identify a specific OpenCL
2342      *  device. If \a devices argument is NULL, this argument is ignored.
2343      *
2344      *  \return One of the following values:
2345      *    - CL_SUCCESS if the function is executed successfully.
2346      *
2347      *  The application can query specific capabilities of the OpenCL device(s)
2348      *  returned by cl::getDevices. This can be used by the application to
2349      *  determine which device(s) to use.
2350      *
2351      * \note In the case that exceptions are enabled and a return value
2352      * other than CL_SUCCESS is generated, then cl::Error exception is
2353      * generated.
2354      */
2355     cl_int getDevices(
2356         cl_d3d10_device_source_khr d3d_device_source,
2357         void *                     d3d_object,
2358         cl_d3d10_device_set_khr    d3d_device_set,
2359         vector<Device>* devices) const
2360     {
2361         typedef CL_API_ENTRY cl_int (CL_API_CALL *PFN_clGetDeviceIDsFromD3D10KHR)(
2362             cl_platform_id platform, 
2363             cl_d3d10_device_source_khr d3d_device_source, 
2364             void * d3d_object,
2365             cl_d3d10_device_set_khr d3d_device_set,
2366             cl_uint num_entries,
2367             cl_device_id * devices,
2368             cl_uint* num_devices);
2369
2370         if( devices == NULL ) {
2371             return detail::errHandler(CL_INVALID_ARG_VALUE, __GET_DEVICE_IDS_ERR);
2372         }
2373
2374         static PFN_clGetDeviceIDsFromD3D10KHR pfn_clGetDeviceIDsFromD3D10KHR = NULL;
2375         CL_HPP_INIT_CL_EXT_FCN_PTR_PLATFORM_(object_, clGetDeviceIDsFromD3D10KHR);
2376
2377         cl_uint n = 0;
2378         cl_int err = pfn_clGetDeviceIDsFromD3D10KHR(
2379             object_, 
2380             d3d_device_source, 
2381             d3d_object,
2382             d3d_device_set, 
2383             0, 
2384             NULL, 
2385             &n);
2386         if (err != CL_SUCCESS) {
2387             return detail::errHandler(err, __GET_DEVICE_IDS_ERR);
2388         }
2389
2390         vector<cl_device_id> ids(n);
2391         err = pfn_clGetDeviceIDsFromD3D10KHR(
2392             object_, 
2393             d3d_device_source, 
2394             d3d_object,
2395             d3d_device_set,
2396             n, 
2397             ids.data(), 
2398             NULL);
2399         if (err != CL_SUCCESS) {
2400             return detail::errHandler(err, __GET_DEVICE_IDS_ERR);
2401         }
2402
2403         // Cannot trivially assign because we need to capture intermediates 
2404         // with safe construction
2405         // We must retain things we obtain from the API to avoid releasing
2406         // API-owned objects.
2407         if (devices) {
2408             devices->resize(ids.size());
2409
2410             // Assign to param, constructing with retain behaviour
2411             // to correctly capture each underlying CL object
2412             for (size_type i = 0; i < ids.size(); i++) {
2413                 (*devices)[i] = Device(ids[i], true);
2414             }
2415         }
2416         return CL_SUCCESS;
2417     }
2418 #endif
2419
2420     /*! \brief Gets a list of available platforms.
2421      * 
2422      *  Wraps clGetPlatformIDs().
2423      */
2424     static cl_int get(
2425         vector<Platform>* platforms)
2426     {
2427         cl_uint n = 0;
2428
2429         if( platforms == NULL ) {
2430             return detail::errHandler(CL_INVALID_ARG_VALUE, __GET_PLATFORM_IDS_ERR);
2431         }
2432
2433         cl_int err = ::clGetPlatformIDs(0, NULL, &n);
2434         if (err != CL_SUCCESS) {
2435             return detail::errHandler(err, __GET_PLATFORM_IDS_ERR);
2436         }
2437
2438         vector<cl_platform_id> ids(n);
2439         err = ::clGetPlatformIDs(n, ids.data(), NULL);
2440         if (err != CL_SUCCESS) {
2441             return detail::errHandler(err, __GET_PLATFORM_IDS_ERR);
2442         }
2443
2444         if (platforms) {
2445             platforms->resize(ids.size());
2446
2447             // Platforms don't reference count
2448             for (size_type i = 0; i < ids.size(); i++) {
2449                 (*platforms)[i] = Platform(ids[i]);
2450             }
2451         }
2452         return CL_SUCCESS;
2453     }
2454
2455     /*! \brief Gets the first available platform.
2456      * 
2457      *  Wraps clGetPlatformIDs(), returning the first result.
2458      */
2459     static cl_int get(
2460         Platform * platform)
2461     {
2462         cl_int err;
2463         Platform default_platform = Platform::getDefault(&err);
2464         if (platform) {
2465             *platform = default_platform;
2466         }
2467         return err;
2468     }
2469
2470     /*! \brief Gets the first available platform, returning it by value.
2471      *
2472      * \return Returns a valid platform if one is available.
2473      *         If no platform is available will return a null platform.
2474      * Throws an exception if no platforms are available
2475      * or an error condition occurs.
2476      * Wraps clGetPlatformIDs(), returning the first result.
2477      */
2478     static Platform get(
2479         cl_int * errResult = NULL)
2480     {
2481         cl_int err;
2482         Platform default_platform = Platform::getDefault(&err);
2483         if (errResult) {
2484             *errResult = err;
2485         }
2486         return default_platform;
2487     }    
2488     
2489 #if CL_HPP_TARGET_OPENCL_VERSION >= 120
2490     //! \brief Wrapper for clUnloadCompiler().
2491     cl_int
2492     unloadCompiler()
2493     {
2494         return ::clUnloadPlatformCompiler(object_);
2495     }
2496 #endif // CL_HPP_TARGET_OPENCL_VERSION >= 120
2497 }; // class Platform
2498
2499 CL_HPP_DEFINE_STATIC_MEMBER_ std::once_flag Platform::default_initialized_;
2500 CL_HPP_DEFINE_STATIC_MEMBER_ Platform Platform::default_;
2501 CL_HPP_DEFINE_STATIC_MEMBER_ cl_int Platform::default_error_ = CL_SUCCESS;
2502
2503
2504 /**
2505  * Deprecated APIs for 1.2
2506  */
2507 #if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS)
2508 /**
2509  * Unload the OpenCL compiler.
2510  * \note Deprecated for OpenCL 1.2. Use Platform::unloadCompiler instead.
2511  */
2512 inline CL_EXT_PREFIX__VERSION_1_1_DEPRECATED cl_int
2513 UnloadCompiler() CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED;
2514 inline cl_int
2515 UnloadCompiler()
2516 {
2517     return ::clUnloadCompiler();
2518 }
2519 #endif // #if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS)
2520
2521 /*! \brief Class interface for cl_context.
2522  *
2523  *  \note Copies of these objects are shallow, meaning that the copy will refer
2524  *        to the same underlying cl_context as the original.  For details, see
2525  *        clRetainContext() and clReleaseContext().
2526  *
2527  *  \see cl_context
2528  */
2529 class Context 
2530     : public detail::Wrapper<cl_context>
2531 {
2532 private:
2533     static std::once_flag default_initialized_;
2534     static Context default_;
2535     static cl_int default_error_;
2536
2537     /*! \brief Create the default context from the default device type in the default platform.
2538      *
2539      * This sets @c default_ and @c default_error_. It does not throw
2540      * @c cl::Error.
2541      */
2542     static void makeDefault() {
2543         /* Throwing an exception from a call_once invocation does not do
2544          * what we wish, so we catch it and save the error.
2545          */
2546 #if defined(CL_HPP_ENABLE_EXCEPTIONS)
2547         try
2548 #endif
2549         {
2550 #if !defined(__APPLE__) && !defined(__MACOS)
2551             const Platform &p = Platform::getDefault();
2552             cl_platform_id defaultPlatform = p();
2553             cl_context_properties properties[3] = {
2554                 CL_CONTEXT_PLATFORM, (cl_context_properties)defaultPlatform, 0
2555             };
2556 #else // #if !defined(__APPLE__) && !defined(__MACOS)
2557             cl_context_properties *properties = nullptr;
2558 #endif // #if !defined(__APPLE__) && !defined(__MACOS)
2559
2560             default_ = Context(
2561                 CL_DEVICE_TYPE_DEFAULT,
2562                 properties,
2563                 NULL,
2564                 NULL,
2565                 &default_error_);
2566         }
2567 #if defined(CL_HPP_ENABLE_EXCEPTIONS)
2568         catch (cl::Error &e) {
2569             default_error_ = e.err();
2570         }
2571 #endif
2572     }
2573
2574
2575     /*! \brief Create the default context from a provided Context.
2576      *
2577      * This sets @c default_. It does not throw
2578      * @c cl::Error.
2579      */
2580     static void makeDefaultProvided(const Context &c) {
2581         default_ = c;
2582     }
2583     
2584 public:
2585 #ifdef CL_HPP_UNIT_TEST_ENABLE
2586     /*! \brief Reset the default.
2587     *
2588     * This sets @c default_ to an empty value to support cleanup in
2589     * the unit test framework.
2590     * This function is not thread safe.
2591     */
2592     static void unitTestClearDefault() {
2593         default_ = Context();
2594     }
2595 #endif // #ifdef CL_HPP_UNIT_TEST_ENABLE
2596
2597     /*! \brief Constructs a context including a list of specified devices.
2598      *
2599      *  Wraps clCreateContext().
2600      */
2601     Context(
2602         const vector<Device>& devices,
2603         cl_context_properties* properties = NULL,
2604         void (CL_CALLBACK * notifyFptr)(
2605             const char *,
2606             const void *,
2607             size_type,
2608             void *) = NULL,
2609         void* data = NULL,
2610         cl_int* err = NULL)
2611     {
2612         cl_int error;
2613
2614         size_type numDevices = devices.size();
2615         vector<cl_device_id> deviceIDs(numDevices);
2616
2617         for( size_type deviceIndex = 0; deviceIndex < numDevices; ++deviceIndex ) {
2618             deviceIDs[deviceIndex] = (devices[deviceIndex])();
2619         }
2620
2621         object_ = ::clCreateContext(
2622             properties, (cl_uint) numDevices,
2623             deviceIDs.data(),
2624             notifyFptr, data, &error);
2625
2626         detail::errHandler(error, __CREATE_CONTEXT_ERR);
2627         if (err != NULL) {
2628             *err = error;
2629         }
2630     }
2631
2632     Context(
2633         const Device& device,
2634         cl_context_properties* properties = NULL,
2635         void (CL_CALLBACK * notifyFptr)(
2636             const char *,
2637             const void *,
2638             size_type,
2639             void *) = NULL,
2640         void* data = NULL,
2641         cl_int* err = NULL)
2642     {
2643         cl_int error;
2644
2645         cl_device_id deviceID = device();
2646
2647         object_ = ::clCreateContext(
2648             properties, 1,
2649             &deviceID,
2650             notifyFptr, data, &error);
2651
2652         detail::errHandler(error, __CREATE_CONTEXT_ERR);
2653         if (err != NULL) {
2654             *err = error;
2655         }
2656     }
2657     
2658     /*! \brief Constructs a context including all or a subset of devices of a specified type.
2659      *
2660      *  Wraps clCreateContextFromType().
2661      */
2662     Context(
2663         cl_device_type type,
2664         cl_context_properties* properties = NULL,
2665         void (CL_CALLBACK * notifyFptr)(
2666             const char *,
2667             const void *,
2668             size_type,
2669             void *) = NULL,
2670         void* data = NULL,
2671         cl_int* err = NULL)
2672     {
2673         cl_int error;
2674
2675 #if !defined(__APPLE__) && !defined(__MACOS)
2676         cl_context_properties prop[4] = {CL_CONTEXT_PLATFORM, 0, 0, 0 };
2677
2678         if (properties == NULL) {
2679             // Get a valid platform ID as we cannot send in a blank one
2680             vector<Platform> platforms;
2681             error = Platform::get(&platforms);
2682             if (error != CL_SUCCESS) {
2683                 detail::errHandler(error, __CREATE_CONTEXT_FROM_TYPE_ERR);
2684                 if (err != NULL) {
2685                     *err = error;
2686                 }
2687                 return;
2688             }
2689
2690             // Check the platforms we found for a device of our specified type
2691             cl_context_properties platform_id = 0;
2692             for (unsigned int i = 0; i < platforms.size(); i++) {
2693
2694                 vector<Device> devices;
2695
2696 #if defined(CL_HPP_ENABLE_EXCEPTIONS)
2697                 try {
2698 #endif
2699
2700                     error = platforms[i].getDevices(type, &devices);
2701
2702 #if defined(CL_HPP_ENABLE_EXCEPTIONS)
2703                 } catch (Error) {}
2704     // Catch if exceptions are enabled as we don't want to exit if first platform has no devices of type
2705     // We do error checking next anyway, and can throw there if needed
2706 #endif
2707
2708                 // Only squash CL_SUCCESS and CL_DEVICE_NOT_FOUND
2709                 if (error != CL_SUCCESS && error != CL_DEVICE_NOT_FOUND) {
2710                     detail::errHandler(error, __CREATE_CONTEXT_FROM_TYPE_ERR);
2711                     if (err != NULL) {
2712                         *err = error;
2713                     }
2714                 }
2715
2716                 if (devices.size() > 0) {
2717                     platform_id = (cl_context_properties)platforms[i]();
2718                     break;
2719                 }
2720             }
2721
2722             if (platform_id == 0) {
2723                 detail::errHandler(CL_DEVICE_NOT_FOUND, __CREATE_CONTEXT_FROM_TYPE_ERR);
2724                 if (err != NULL) {
2725                     *err = CL_DEVICE_NOT_FOUND;
2726                 }
2727                 return;
2728             }
2729
2730             prop[1] = platform_id;
2731             properties = &prop[0];
2732         }
2733 #endif
2734         object_ = ::clCreateContextFromType(
2735             properties, type, notifyFptr, data, &error);
2736
2737         detail::errHandler(error, __CREATE_CONTEXT_FROM_TYPE_ERR);
2738         if (err != NULL) {
2739             *err = error;
2740         }
2741     }
2742
2743     /*! \brief Copy constructor to forward copy to the superclass correctly.
2744      * Required for MSVC.
2745      */
2746     Context(const Context& ctx) : detail::Wrapper<cl_type>(ctx) {}
2747
2748     /*! \brief Copy assignment to forward copy to the superclass correctly.
2749      * Required for MSVC.
2750      */
2751     Context& operator = (const Context &ctx)
2752     {
2753         detail::Wrapper<cl_type>::operator=(ctx);
2754         return *this;
2755     }
2756
2757     /*! \brief Move constructor to forward move to the superclass correctly.
2758      * Required for MSVC.
2759      */
2760     Context(Context&& ctx) CL_HPP_NOEXCEPT_ : detail::Wrapper<cl_type>(std::move(ctx)) {}
2761
2762     /*! \brief Move assignment to forward move to the superclass correctly.
2763      * Required for MSVC.
2764      */
2765     Context& operator = (Context &&ctx)
2766     {
2767         detail::Wrapper<cl_type>::operator=(std::move(ctx));
2768         return *this;
2769     }
2770
2771
2772     /*! \brief Returns a singleton context including all devices of CL_DEVICE_TYPE_DEFAULT.
2773      *
2774      *  \note All calls to this function return the same cl_context as the first.
2775      */
2776     static Context getDefault(cl_int * err = NULL) 
2777     {
2778         std::call_once(default_initialized_, makeDefault);
2779         detail::errHandler(default_error_);
2780         if (err != NULL) {
2781             *err = default_error_;
2782         }
2783         return default_;
2784     }
2785
2786     /**
2787      * Modify the default context to be used by
2788      * subsequent operations.
2789      * Will only set the default if no default was previously created.
2790      * @return updated default context.
2791      *         Should be compared to the passed value to ensure that it was updated.
2792      */
2793     static Context setDefault(const Context &default_context)
2794     {
2795         std::call_once(default_initialized_, makeDefaultProvided, std::cref(default_context));
2796         detail::errHandler(default_error_);
2797         return default_;
2798     }
2799
2800     //! \brief Default constructor - initializes to NULL.
2801     Context() : detail::Wrapper<cl_type>() { }
2802
2803     /*! \brief Constructor from cl_context - takes ownership.
2804      * 
2805      *  This effectively transfers ownership of a refcount on the cl_context
2806      *  into the new Context object.
2807      */
2808     explicit Context(const cl_context& context, bool retainObject = false) : 
2809         detail::Wrapper<cl_type>(context, retainObject) { }
2810
2811     /*! \brief Assignment operator from cl_context - takes ownership.
2812      * 
2813      *  This effectively transfers ownership of a refcount on the rhs and calls
2814      *  clReleaseContext() on the value previously held by this instance.
2815      */
2816     Context& operator = (const cl_context& rhs)
2817     {
2818         detail::Wrapper<cl_type>::operator=(rhs);
2819         return *this;
2820     }
2821
2822     //! \brief Wrapper for clGetContextInfo().
2823     template <typename T>
2824     cl_int getInfo(cl_context_info name, T* param) const
2825     {
2826         return detail::errHandler(
2827             detail::getInfo(&::clGetContextInfo, object_, name, param),
2828             __GET_CONTEXT_INFO_ERR);
2829     }
2830
2831     //! \brief Wrapper for clGetContextInfo() that returns by value.
2832     template <cl_int name> typename
2833     detail::param_traits<detail::cl_context_info, name>::param_type
2834     getInfo(cl_int* err = NULL) const
2835     {
2836         typename detail::param_traits<
2837             detail::cl_context_info, name>::param_type param;
2838         cl_int result = getInfo(name, &param);
2839         if (err != NULL) {
2840             *err = result;
2841         }
2842         return param;
2843     }
2844
2845     /*! \brief Gets a list of supported image formats.
2846      *  
2847      *  Wraps clGetSupportedImageFormats().
2848      */
2849     cl_int getSupportedImageFormats(
2850         cl_mem_flags flags,
2851         cl_mem_object_type type,
2852         vector<ImageFormat>* formats) const
2853     {
2854         cl_uint numEntries;
2855         
2856         if (!formats) {
2857             return CL_SUCCESS;
2858         }
2859
2860         cl_int err = ::clGetSupportedImageFormats(
2861            object_, 
2862            flags,
2863            type, 
2864            0, 
2865            NULL, 
2866            &numEntries);
2867         if (err != CL_SUCCESS) {
2868             return detail::errHandler(err, __GET_SUPPORTED_IMAGE_FORMATS_ERR);
2869         }
2870
2871         if (numEntries > 0) {
2872             vector<ImageFormat> value(numEntries);
2873             err = ::clGetSupportedImageFormats(
2874                 object_,
2875                 flags,
2876                 type,
2877                 numEntries,
2878                 (cl_image_format*)value.data(),
2879                 NULL);
2880             if (err != CL_SUCCESS) {
2881                 return detail::errHandler(err, __GET_SUPPORTED_IMAGE_FORMATS_ERR);
2882             }
2883
2884             formats->assign(begin(value), end(value));
2885         }
2886         else {
2887             // If no values are being returned, ensure an empty vector comes back
2888             formats->clear();
2889         }
2890
2891         return CL_SUCCESS;
2892     }
2893 };
2894
2895 inline void Device::makeDefault()
2896 {
2897     /* Throwing an exception from a call_once invocation does not do
2898     * what we wish, so we catch it and save the error.
2899     */
2900 #if defined(CL_HPP_ENABLE_EXCEPTIONS)
2901     try
2902 #endif
2903     {
2904         cl_int error = 0;
2905
2906         Context context = Context::getDefault(&error);
2907         detail::errHandler(error, __CREATE_CONTEXT_ERR);
2908
2909         if (error != CL_SUCCESS) {
2910             default_error_ = error;
2911         }
2912         else {
2913             default_ = context.getInfo<CL_CONTEXT_DEVICES>()[0];
2914             default_error_ = CL_SUCCESS;
2915         }
2916     }
2917 #if defined(CL_HPP_ENABLE_EXCEPTIONS)
2918     catch (cl::Error &e) {
2919         default_error_ = e.err();
2920     }
2921 #endif
2922 }
2923
2924 CL_HPP_DEFINE_STATIC_MEMBER_ std::once_flag Context::default_initialized_;
2925 CL_HPP_DEFINE_STATIC_MEMBER_ Context Context::default_;
2926 CL_HPP_DEFINE_STATIC_MEMBER_ cl_int Context::default_error_ = CL_SUCCESS;
2927
2928 /*! \brief Class interface for cl_event.
2929  *
2930  *  \note Copies of these objects are shallow, meaning that the copy will refer
2931  *        to the same underlying cl_event as the original.  For details, see
2932  *        clRetainEvent() and clReleaseEvent().
2933  *
2934  *  \see cl_event
2935  */
2936 class Event : public detail::Wrapper<cl_event>
2937 {
2938 public:
2939     //! \brief Default constructor - initializes to NULL.
2940     Event() : detail::Wrapper<cl_type>() { }
2941
2942     /*! \brief Constructor from cl_event - takes ownership.
2943      * 
2944      * \param retainObject will cause the constructor to retain its cl object.
2945      *                     Defaults to false to maintain compatibility with
2946      *                     earlier versions.
2947      *  This effectively transfers ownership of a refcount on the cl_event
2948      *  into the new Event object.
2949      */
2950     explicit Event(const cl_event& event, bool retainObject = false) : 
2951         detail::Wrapper<cl_type>(event, retainObject) { }
2952
2953     /*! \brief Assignment operator from cl_event - takes ownership.
2954      *
2955      *  This effectively transfers ownership of a refcount on the rhs and calls
2956      *  clReleaseEvent() on the value previously held by this instance.
2957      */
2958     Event& operator = (const cl_event& rhs)
2959     {
2960         detail::Wrapper<cl_type>::operator=(rhs);
2961         return *this;
2962     }
2963
2964     //! \brief Wrapper for clGetEventInfo().
2965     template <typename T>
2966     cl_int getInfo(cl_event_info name, T* param) const
2967     {
2968         return detail::errHandler(
2969             detail::getInfo(&::clGetEventInfo, object_, name, param),
2970             __GET_EVENT_INFO_ERR);
2971     }
2972
2973     //! \brief Wrapper for clGetEventInfo() that returns by value.
2974     template <cl_int name> typename
2975     detail::param_traits<detail::cl_event_info, name>::param_type
2976     getInfo(cl_int* err = NULL) const
2977     {
2978         typename detail::param_traits<
2979             detail::cl_event_info, name>::param_type param;
2980         cl_int result = getInfo(name, &param);
2981         if (err != NULL) {
2982             *err = result;
2983         }
2984         return param;
2985     }
2986
2987     //! \brief Wrapper for clGetEventProfilingInfo().
2988     template <typename T>
2989     cl_int getProfilingInfo(cl_profiling_info name, T* param) const
2990     {
2991         return detail::errHandler(detail::getInfo(
2992             &::clGetEventProfilingInfo, object_, name, param),
2993             __GET_EVENT_PROFILE_INFO_ERR);
2994     }
2995
2996     //! \brief Wrapper for clGetEventProfilingInfo() that returns by value.
2997     template <cl_int name> typename
2998     detail::param_traits<detail::cl_profiling_info, name>::param_type
2999     getProfilingInfo(cl_int* err = NULL) const
3000     {
3001         typename detail::param_traits<
3002             detail::cl_profiling_info, name>::param_type param;
3003         cl_int result = getProfilingInfo(name, &param);
3004         if (err != NULL) {
3005             *err = result;
3006         }
3007         return param;
3008     }
3009
3010     /*! \brief Blocks the calling thread until this event completes.
3011      * 
3012      *  Wraps clWaitForEvents().
3013      */
3014     cl_int wait() const
3015     {
3016         return detail::errHandler(
3017             ::clWaitForEvents(1, &object_),
3018             __WAIT_FOR_EVENTS_ERR);
3019     }
3020
3021 #if CL_HPP_TARGET_OPENCL_VERSION >= 110
3022     /*! \brief Registers a user callback function for a specific command execution status.
3023      *
3024      *  Wraps clSetEventCallback().
3025      */
3026     cl_int setCallback(
3027         cl_int type,
3028         void (CL_CALLBACK * pfn_notify)(cl_event, cl_int, void *),              
3029         void * user_data = NULL)
3030     {
3031         return detail::errHandler(
3032             ::clSetEventCallback(
3033                 object_,
3034                 type,
3035                 pfn_notify,
3036                 user_data), 
3037             __SET_EVENT_CALLBACK_ERR);
3038     }
3039 #endif // CL_HPP_TARGET_OPENCL_VERSION >= 110
3040
3041     /*! \brief Blocks the calling thread until every event specified is complete.
3042      * 
3043      *  Wraps clWaitForEvents().
3044      */
3045     static cl_int
3046     waitForEvents(const vector<Event>& events)
3047     {
3048         return detail::errHandler(
3049             ::clWaitForEvents(
3050                 (cl_uint) events.size(), (events.size() > 0) ? (cl_event*)&events.front() : NULL),
3051             __WAIT_FOR_EVENTS_ERR);
3052     }
3053 };
3054
3055 #if CL_HPP_TARGET_OPENCL_VERSION >= 110
3056 /*! \brief Class interface for user events (a subset of cl_event's).
3057  * 
3058  *  See Event for details about copy semantics, etc.
3059  */
3060 class UserEvent : public Event
3061 {
3062 public:
3063     /*! \brief Constructs a user event on a given context.
3064      *
3065      *  Wraps clCreateUserEvent().
3066      */
3067     UserEvent(
3068         const Context& context,
3069         cl_int * err = NULL)
3070     {
3071         cl_int error;
3072         object_ = ::clCreateUserEvent(
3073             context(),
3074             &error);
3075
3076         detail::errHandler(error, __CREATE_USER_EVENT_ERR);
3077         if (err != NULL) {
3078             *err = error;
3079         }
3080     }
3081
3082     //! \brief Default constructor - initializes to NULL.
3083     UserEvent() : Event() { }
3084
3085     /*! \brief Sets the execution status of a user event object.
3086      *
3087      *  Wraps clSetUserEventStatus().
3088      */
3089     cl_int setStatus(cl_int status)
3090     {
3091         return detail::errHandler(
3092             ::clSetUserEventStatus(object_,status), 
3093             __SET_USER_EVENT_STATUS_ERR);
3094     }
3095 };
3096 #endif // CL_HPP_TARGET_OPENCL_VERSION >= 110
3097
3098 /*! \brief Blocks the calling thread until every event specified is complete.
3099  * 
3100  *  Wraps clWaitForEvents().
3101  */
3102 inline static cl_int
3103 WaitForEvents(const vector<Event>& events)
3104 {
3105     return detail::errHandler(
3106         ::clWaitForEvents(
3107             (cl_uint) events.size(), (events.size() > 0) ? (cl_event*)&events.front() : NULL),
3108         __WAIT_FOR_EVENTS_ERR);
3109 }
3110
3111 /*! \brief Class interface for cl_mem.
3112  *
3113  *  \note Copies of these objects are shallow, meaning that the copy will refer
3114  *        to the same underlying cl_mem as the original.  For details, see
3115  *        clRetainMemObject() and clReleaseMemObject().
3116  *
3117  *  \see cl_mem
3118  */
3119 class Memory : public detail::Wrapper<cl_mem>
3120 {
3121 public:
3122     //! \brief Default constructor - initializes to NULL.
3123     Memory() : detail::Wrapper<cl_type>() { }
3124
3125     /*! \brief Constructor from cl_mem - takes ownership.
3126      *
3127      *  Optionally transfer ownership of a refcount on the cl_mem
3128      *  into the new Memory object.
3129      *
3130      * \param retainObject will cause the constructor to retain its cl object.
3131      *                     Defaults to false to maintain compatibility with
3132      *                     earlier versions.
3133      *
3134      *  See Memory for further details.
3135      */
3136     explicit Memory(const cl_mem& memory, bool retainObject) :
3137         detail::Wrapper<cl_type>(memory, retainObject) { }
3138
3139     /*! \brief Assignment operator from cl_mem - takes ownership.
3140      *
3141      *  This effectively transfers ownership of a refcount on the rhs and calls
3142      *  clReleaseMemObject() on the value previously held by this instance.
3143      */
3144     Memory& operator = (const cl_mem& rhs)
3145     {
3146         detail::Wrapper<cl_type>::operator=(rhs);
3147         return *this;
3148     }
3149
3150     /*! \brief Copy constructor to forward copy to the superclass correctly.
3151      * Required for MSVC.
3152      */
3153     Memory(const Memory& mem) : detail::Wrapper<cl_type>(mem) {}
3154
3155     /*! \brief Copy assignment to forward copy to the superclass correctly.
3156      * Required for MSVC.
3157      */
3158     Memory& operator = (const Memory &mem)
3159     {
3160         detail::Wrapper<cl_type>::operator=(mem);
3161         return *this;
3162     }
3163
3164     /*! \brief Move constructor to forward move to the superclass correctly.
3165      * Required for MSVC.
3166      */
3167     Memory(Memory&& mem) CL_HPP_NOEXCEPT_ : detail::Wrapper<cl_type>(std::move(mem)) {}
3168
3169     /*! \brief Move assignment to forward move to the superclass correctly.
3170      * Required for MSVC.
3171      */
3172     Memory& operator = (Memory &&mem)
3173     {
3174         detail::Wrapper<cl_type>::operator=(std::move(mem));
3175         return *this;
3176     }
3177
3178
3179     //! \brief Wrapper for clGetMemObjectInfo().
3180     template <typename T>
3181     cl_int getInfo(cl_mem_info name, T* param) const
3182     {
3183         return detail::errHandler(
3184             detail::getInfo(&::clGetMemObjectInfo, object_, name, param),
3185             __GET_MEM_OBJECT_INFO_ERR);
3186     }
3187
3188     //! \brief Wrapper for clGetMemObjectInfo() that returns by value.
3189     template <cl_int name> typename
3190     detail::param_traits<detail::cl_mem_info, name>::param_type
3191     getInfo(cl_int* err = NULL) const
3192     {
3193         typename detail::param_traits<
3194             detail::cl_mem_info, name>::param_type param;
3195         cl_int result = getInfo(name, &param);
3196         if (err != NULL) {
3197             *err = result;
3198         }
3199         return param;
3200     }
3201
3202 #if CL_HPP_TARGET_OPENCL_VERSION >= 110
3203     /*! \brief Registers a callback function to be called when the memory object
3204      *         is no longer needed.
3205      *
3206      *  Wraps clSetMemObjectDestructorCallback().
3207      *
3208      *  Repeated calls to this function, for a given cl_mem value, will append
3209      *  to the list of functions called (in reverse order) when memory object's
3210      *  resources are freed and the memory object is deleted.
3211      *
3212      *  \note
3213      *  The registered callbacks are associated with the underlying cl_mem
3214      *  value - not the Memory class instance.
3215      */
3216     cl_int setDestructorCallback(
3217         void (CL_CALLBACK * pfn_notify)(cl_mem, void *),                
3218         void * user_data = NULL)
3219     {
3220         return detail::errHandler(
3221             ::clSetMemObjectDestructorCallback(
3222                 object_,
3223                 pfn_notify,
3224                 user_data), 
3225             __SET_MEM_OBJECT_DESTRUCTOR_CALLBACK_ERR);
3226     }
3227 #endif // CL_HPP_TARGET_OPENCL_VERSION >= 110
3228
3229 };
3230
3231 // Pre-declare copy functions
3232 class Buffer;
3233 template< typename IteratorType >
3234 cl_int copy( IteratorType startIterator, IteratorType endIterator, cl::Buffer &buffer );
3235 template< typename IteratorType >
3236 cl_int copy( const cl::Buffer &buffer, IteratorType startIterator, IteratorType endIterator );
3237 template< typename IteratorType >
3238 cl_int copy( const CommandQueue &queue, IteratorType startIterator, IteratorType endIterator, cl::Buffer &buffer );
3239 template< typename IteratorType >
3240 cl_int copy( const CommandQueue &queue, const cl::Buffer &buffer, IteratorType startIterator, IteratorType endIterator );
3241
3242
3243 #if CL_HPP_TARGET_OPENCL_VERSION >= 200
3244 namespace detail
3245 {
3246     class SVMTraitNull
3247     {
3248     public:
3249         static cl_svm_mem_flags getSVMMemFlags()
3250         {
3251             return 0;
3252         }
3253     };
3254 } // namespace detail
3255
3256 template<class Trait = detail::SVMTraitNull>
3257 class SVMTraitReadWrite
3258 {
3259 public:
3260     static cl_svm_mem_flags getSVMMemFlags()
3261     {
3262         return CL_MEM_READ_WRITE |
3263             Trait::getSVMMemFlags();
3264     }
3265 };
3266
3267 template<class Trait = detail::SVMTraitNull>
3268 class SVMTraitReadOnly
3269 {
3270 public:
3271     static cl_svm_mem_flags getSVMMemFlags()
3272     {
3273         return CL_MEM_READ_ONLY |
3274             Trait::getSVMMemFlags();
3275     }
3276 };
3277
3278 template<class Trait = detail::SVMTraitNull>
3279 class SVMTraitWriteOnly
3280 {
3281 public:
3282     static cl_svm_mem_flags getSVMMemFlags()
3283     {
3284         return CL_MEM_WRITE_ONLY |
3285             Trait::getSVMMemFlags();
3286     }
3287 };
3288
3289 template<class Trait = SVMTraitReadWrite<>>
3290 class SVMTraitCoarse
3291 {
3292 public:
3293     static cl_svm_mem_flags getSVMMemFlags()
3294     {
3295         return Trait::getSVMMemFlags();
3296     }
3297 };
3298
3299 template<class Trait = SVMTraitReadWrite<>>
3300 class SVMTraitFine
3301 {
3302 public:
3303     static cl_svm_mem_flags getSVMMemFlags()
3304     {
3305         return CL_MEM_SVM_FINE_GRAIN_BUFFER |
3306             Trait::getSVMMemFlags();
3307     }
3308 };
3309
3310 template<class Trait = SVMTraitReadWrite<>>
3311 class SVMTraitAtomic
3312 {
3313 public:
3314     static cl_svm_mem_flags getSVMMemFlags()
3315     {
3316         return
3317             CL_MEM_SVM_FINE_GRAIN_BUFFER |
3318             CL_MEM_SVM_ATOMICS |
3319             Trait::getSVMMemFlags();
3320     }
3321 };
3322
3323 // Pre-declare SVM map function
3324 template<typename T>
3325 inline cl_int enqueueMapSVM(
3326     T* ptr,
3327     cl_bool blocking,
3328     cl_map_flags flags,
3329     size_type size,
3330     const vector<Event>* events = NULL,
3331     Event* event = NULL);
3332
3333 /**
3334  * STL-like allocator class for managing SVM objects provided for convenience.
3335  *
3336  * Note that while this behaves like an allocator for the purposes of constructing vectors and similar objects,
3337  * care must be taken when using with smart pointers.
3338  * The allocator should not be used to construct a unique_ptr if we are using coarse-grained SVM mode because
3339  * the coarse-grained management behaviour would behave incorrectly with respect to reference counting.
3340  *
3341  * Instead the allocator embeds a Deleter which may be used with unique_ptr and is used
3342  * with the allocate_shared and allocate_ptr supplied operations.
3343  */
3344 template<typename T, class SVMTrait>
3345 class SVMAllocator {
3346 private:
3347     Context context_;
3348
3349 public:
3350     typedef T value_type;
3351     typedef value_type* pointer;
3352     typedef const value_type* const_pointer;
3353     typedef value_type& reference;
3354     typedef const value_type& const_reference;
3355     typedef std::size_t size_type;
3356     typedef std::ptrdiff_t difference_type;
3357
3358     template<typename U>
3359     struct rebind
3360     {
3361         typedef SVMAllocator<U, SVMTrait> other;
3362     };
3363
3364     template<typename U, typename V>
3365     friend class SVMAllocator;
3366
3367     SVMAllocator() :
3368         context_(Context::getDefault())
3369     {
3370     }
3371
3372     explicit SVMAllocator(cl::Context context) :
3373         context_(context)
3374     {
3375     }
3376
3377
3378     SVMAllocator(const SVMAllocator &other) :
3379         context_(other.context_)
3380     {
3381     }
3382
3383     template<typename U>
3384     SVMAllocator(const SVMAllocator<U, SVMTrait> &other) :
3385         context_(other.context_)
3386     {
3387     }
3388
3389     ~SVMAllocator()
3390     {
3391     }
3392
3393     pointer address(reference r) CL_HPP_NOEXCEPT_
3394     {
3395         return std::addressof(r);
3396     }
3397
3398     const_pointer address(const_reference r) CL_HPP_NOEXCEPT_
3399     {
3400         return std::addressof(r);
3401     }
3402
3403     /**
3404      * Allocate an SVM pointer.
3405      *
3406      * If the allocator is coarse-grained, this will take ownership to allow
3407      * containers to correctly construct data in place. 
3408      */
3409     pointer allocate(
3410         size_type size,
3411         typename cl::SVMAllocator<void, SVMTrait>::const_pointer = 0)
3412     {
3413         // Allocate memory with default alignment matching the size of the type
3414         void* voidPointer =
3415             clSVMAlloc(
3416             context_(),
3417             SVMTrait::getSVMMemFlags(),
3418             size*sizeof(T),
3419             sizeof(T));
3420         pointer retValue = reinterpret_cast<pointer>(
3421             voidPointer);
3422 #if defined(CL_HPP_ENABLE_EXCEPTIONS)
3423         if (!retValue) {
3424             std::bad_alloc excep;
3425             throw excep;
3426         }
3427 #endif // #if defined(CL_HPP_ENABLE_EXCEPTIONS)
3428
3429         // If allocation was coarse-grained then map it
3430         if (!(SVMTrait::getSVMMemFlags() & CL_MEM_SVM_FINE_GRAIN_BUFFER)) {
3431             cl_int err = enqueueMapSVM(retValue, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, size*sizeof(T));
3432             if (err != CL_SUCCESS) {
3433                 std::bad_alloc excep;
3434                 throw excep;
3435             }
3436         }
3437
3438         // If exceptions disabled, return null pointer from allocator
3439         return retValue;
3440     }
3441
3442     void deallocate(pointer p, size_type)
3443     {
3444         clSVMFree(context_(), p);
3445     }
3446
3447     /**
3448      * Return the maximum possible allocation size.
3449      * This is the minimum of the maximum sizes of all devices in the context.
3450      */
3451     size_type max_size() const CL_HPP_NOEXCEPT_
3452     {
3453         size_type maxSize = std::numeric_limits<size_type>::max() / sizeof(T);
3454
3455         for (Device &d : context_.getInfo<CL_CONTEXT_DEVICES>()) {
3456             maxSize = std::min(
3457                 maxSize, 
3458                 static_cast<size_type>(d.getInfo<CL_DEVICE_MAX_MEM_ALLOC_SIZE>()));
3459         }
3460
3461         return maxSize;
3462     }
3463
3464     template< class U, class... Args >
3465     void construct(U* p, Args&&... args)
3466     {
3467         new(p)T(args...);
3468     }
3469
3470     template< class U >
3471     void destroy(U* p)
3472     {
3473         p->~U();
3474     }
3475
3476     /**
3477      * Returns true if the contexts match.
3478      */
3479     inline bool operator==(SVMAllocator const& rhs)
3480     {
3481         return (context_==rhs.context_);
3482     }
3483
3484     inline bool operator!=(SVMAllocator const& a)
3485     {
3486         return !operator==(a);
3487     }
3488 }; // class SVMAllocator        return cl::pointer<T>(tmp, detail::Deleter<T, Alloc>{alloc, copies});
3489
3490
3491 template<class SVMTrait>
3492 class SVMAllocator<void, SVMTrait> {
3493 public:
3494     typedef void value_type;
3495     typedef value_type* pointer;
3496     typedef const value_type* const_pointer;
3497
3498     template<typename U>
3499     struct rebind
3500     {
3501         typedef SVMAllocator<U, SVMTrait> other;
3502     };
3503
3504     template<typename U, typename V>
3505     friend class SVMAllocator;
3506 };
3507
3508 #if !defined(CL_HPP_NO_STD_UNIQUE_PTR)
3509 namespace detail
3510 {
3511     template<class Alloc>
3512     class Deleter {
3513     private:
3514         Alloc alloc_;
3515         size_type copies_;
3516
3517     public:
3518         typedef typename std::allocator_traits<Alloc>::pointer pointer;
3519
3520         Deleter(const Alloc &alloc, size_type copies) : alloc_{ alloc }, copies_{ copies }
3521         {
3522         }
3523
3524         void operator()(pointer ptr) const {
3525             Alloc tmpAlloc{ alloc_ };
3526             std::allocator_traits<Alloc>::destroy(tmpAlloc, std::addressof(*ptr));
3527             std::allocator_traits<Alloc>::deallocate(tmpAlloc, ptr, copies_);
3528         }
3529     };
3530 } // namespace detail
3531
3532 /**
3533  * Allocation operation compatible with std::allocate_ptr.
3534  * Creates a unique_ptr<T> by default.
3535  * This requirement is to ensure that the control block is not
3536  * allocated in memory inaccessible to the host.
3537  */
3538 template <class T, class Alloc, class... Args>
3539 cl::pointer<T, detail::Deleter<Alloc>> allocate_pointer(const Alloc &alloc_, Args&&... args)
3540 {
3541     Alloc alloc(alloc_);
3542     static const size_t copies = 1;
3543
3544     // Ensure that creation of the management block and the
3545     // object are dealt with separately such that we only provide a deleter
3546
3547     T* tmp = std::allocator_traits<Alloc>::allocate(alloc, copies);
3548     if (!tmp) {
3549         std::bad_alloc excep;
3550         throw excep;
3551     }
3552     try {
3553         std::allocator_traits<Alloc>::construct(
3554             alloc,
3555             std::addressof(*tmp),
3556             std::forward<Args>(args)...);
3557
3558         return cl::pointer<T, detail::Deleter<Alloc>>(tmp, detail::Deleter<Alloc>{alloc, copies});
3559     }
3560     catch (std::bad_alloc b)
3561     {
3562         std::allocator_traits<Alloc>::deallocate(alloc, tmp, copies);
3563         throw;
3564     }
3565 }
3566
3567 template< class T, class SVMTrait, class... Args >
3568 cl::pointer<T, detail::Deleter<SVMAllocator<T, SVMTrait>>> allocate_svm(Args... args)
3569 {
3570     SVMAllocator<T, SVMTrait> alloc;
3571     return cl::allocate_pointer<T>(alloc, args...);
3572 }
3573
3574 template< class T, class SVMTrait, class... Args >
3575 cl::pointer<T, detail::Deleter<SVMAllocator<T, SVMTrait>>> allocate_svm(const cl::Context &c, Args... args)
3576 {
3577     SVMAllocator<T, SVMTrait> alloc(c);
3578     return cl::allocate_pointer<T>(alloc, args...);
3579 }
3580 #endif // #if !defined(CL_HPP_NO_STD_UNIQUE_PTR)
3581
3582 /*! \brief Vector alias to simplify contruction of coarse-grained SVM containers.
3583  * 
3584  */
3585 template < class T >
3586 using coarse_svm_vector = vector<T, cl::SVMAllocator<int, cl::SVMTraitCoarse<>>>;
3587
3588 /*! \brief Vector alias to simplify contruction of fine-grained SVM containers.
3589 *
3590 */
3591 template < class T >
3592 using fine_svm_vector = vector<T, cl::SVMAllocator<int, cl::SVMTraitFine<>>>;
3593
3594 /*! \brief Vector alias to simplify contruction of fine-grained SVM containers that support platform atomics.
3595 *
3596 */
3597 template < class T >
3598 using atomic_svm_vector = vector<T, cl::SVMAllocator<int, cl::SVMTraitAtomic<>>>;
3599
3600 #endif // #if CL_HPP_TARGET_OPENCL_VERSION >= 200
3601
3602
3603 /*! \brief Class interface for Buffer Memory Objects.
3604  * 
3605  *  See Memory for details about copy semantics, etc.
3606  *
3607  *  \see Memory
3608  */
3609 class Buffer : public Memory
3610 {
3611 public:
3612
3613     /*! \brief Constructs a Buffer in a specified context.
3614      *
3615      *  Wraps clCreateBuffer().
3616      *
3617      *  \param host_ptr Storage to be used if the CL_MEM_USE_HOST_PTR flag was
3618      *                  specified.  Note alignment & exclusivity requirements.
3619      */
3620     Buffer(
3621         const Context& context,
3622         cl_mem_flags flags,
3623         size_type size,
3624         void* host_ptr = NULL,
3625         cl_int* err = NULL)
3626     {
3627         cl_int error;
3628         object_ = ::clCreateBuffer(context(), flags, size, host_ptr, &error);
3629
3630         detail::errHandler(error, __CREATE_BUFFER_ERR);
3631         if (err != NULL) {
3632             *err = error;
3633         }
3634     }
3635
3636     /*! \brief Constructs a Buffer in the default context.
3637      *
3638      *  Wraps clCreateBuffer().
3639      *
3640      *  \param host_ptr Storage to be used if the CL_MEM_USE_HOST_PTR flag was
3641      *                  specified.  Note alignment & exclusivity requirements.
3642      *
3643      *  \see Context::getDefault()
3644      */
3645     Buffer(
3646          cl_mem_flags flags,
3647         size_type size,
3648         void* host_ptr = NULL,
3649         cl_int* err = NULL)
3650     {
3651         cl_int error;
3652
3653         Context context = Context::getDefault(err);
3654
3655         object_ = ::clCreateBuffer(context(), flags, size, host_ptr, &error);
3656
3657         detail::errHandler(error, __CREATE_BUFFER_ERR);
3658         if (err != NULL) {
3659             *err = error;
3660         }
3661     }
3662
3663     /*!
3664      * \brief Construct a Buffer from a host container via iterators.
3665      * IteratorType must be random access.
3666      * If useHostPtr is specified iterators must represent contiguous data.
3667      */
3668     template< typename IteratorType >
3669     Buffer(
3670         IteratorType startIterator,
3671         IteratorType endIterator,
3672         bool readOnly,
3673         bool useHostPtr = false,
3674         cl_int* err = NULL)
3675     {
3676         typedef typename std::iterator_traits<IteratorType>::value_type DataType;
3677         cl_int error;
3678
3679         cl_mem_flags flags = 0;
3680         if( readOnly ) {
3681             flags |= CL_MEM_READ_ONLY;
3682         }
3683         else {
3684             flags |= CL_MEM_READ_WRITE;
3685         }
3686         if( useHostPtr ) {
3687             flags |= CL_MEM_USE_HOST_PTR;
3688         }
3689         
3690         size_type size = sizeof(DataType)*(endIterator - startIterator);
3691
3692         Context context = Context::getDefault(err);
3693
3694         if( useHostPtr ) {
3695             object_ = ::clCreateBuffer(context(), flags, size, static_cast<DataType*>(&*startIterator), &error);
3696         } else {
3697             object_ = ::clCreateBuffer(context(), flags, size, 0, &error);
3698         }
3699
3700         detail::errHandler(error, __CREATE_BUFFER_ERR);
3701         if (err != NULL) {
3702             *err = error;
3703         }
3704
3705         if( !useHostPtr ) {
3706             error = cl::copy(startIterator, endIterator, *this);
3707             detail::errHandler(error, __CREATE_BUFFER_ERR);
3708             if (err != NULL) {
3709                 *err = error;
3710             }
3711         }
3712     }
3713
3714     /*!
3715      * \brief Construct a Buffer from a host container via iterators using a specified context.
3716      * IteratorType must be random access.
3717      * If useHostPtr is specified iterators must represent contiguous data.
3718      */
3719     template< typename IteratorType >
3720     Buffer(const Context &context, IteratorType startIterator, IteratorType endIterator,
3721         bool readOnly, bool useHostPtr = false, cl_int* err = NULL);
3722     
3723     /*!
3724     * \brief Construct a Buffer from a host container via iterators using a specified queue.
3725     * If useHostPtr is specified iterators must be random access.
3726     */
3727     template< typename IteratorType >
3728     Buffer(const CommandQueue &queue, IteratorType startIterator, IteratorType endIterator,
3729         bool readOnly, bool useHostPtr = false, cl_int* err = NULL);
3730
3731     //! \brief Default constructor - initializes to NULL.
3732     Buffer() : Memory() { }
3733
3734     /*! \brief Constructor from cl_mem - takes ownership.
3735      *
3736      * \param retainObject will cause the constructor to retain its cl object.
3737      *                     Defaults to false to maintain compatibility with earlier versions.
3738      *
3739      *  See Memory for further details.
3740      */
3741     explicit Buffer(const cl_mem& buffer, bool retainObject = false) :
3742         Memory(buffer, retainObject) { }
3743
3744     /*! \brief Assignment from cl_mem - performs shallow copy.
3745     *
3746     *  See Memory for further details.
3747     */
3748     Buffer& operator = (const cl_mem& rhs)
3749     {
3750         Memory::operator=(rhs);
3751         return *this;
3752     }
3753
3754     /*! \brief Copy constructor to forward copy to the superclass correctly.
3755      * Required for MSVC.
3756      */
3757     Buffer(const Buffer& buf) : Memory(buf) {}
3758
3759     /*! \brief Copy assignment to forward copy to the superclass correctly.
3760      * Required for MSVC.
3761      */
3762     Buffer& operator = (const Buffer &buf)
3763     {
3764         Memory::operator=(buf);
3765         return *this;
3766     }
3767
3768     /*! \brief Move constructor to forward move to the superclass correctly.
3769      * Required for MSVC.
3770      */
3771     Buffer(Buffer&& buf) CL_HPP_NOEXCEPT_ : Memory(std::move(buf)) {}
3772
3773     /*! \brief Move assignment to forward move to the superclass correctly.
3774      * Required for MSVC.
3775      */
3776     Buffer& operator = (Buffer &&buf)
3777     {
3778         Memory::operator=(std::move(buf));
3779         return *this;
3780     }
3781
3782 #if CL_HPP_TARGET_OPENCL_VERSION >= 110
3783     /*! \brief Creates a new buffer object from this.
3784      *
3785      *  Wraps clCreateSubBuffer().
3786      */
3787     Buffer createSubBuffer(
3788         cl_mem_flags flags,
3789         cl_buffer_create_type buffer_create_type,
3790         const void * buffer_create_info,
3791         cl_int * err = NULL)
3792     {
3793         Buffer result;
3794         cl_int error;
3795         result.object_ = ::clCreateSubBuffer(
3796             object_, 
3797             flags, 
3798             buffer_create_type, 
3799             buffer_create_info, 
3800             &error);
3801
3802         detail::errHandler(error, __CREATE_SUBBUFFER_ERR);
3803         if (err != NULL) {
3804             *err = error;
3805         }
3806
3807         return result;
3808     }           
3809 #endif // CL_HPP_TARGET_OPENCL_VERSION >= 110
3810 };
3811
3812 #if defined (CL_HPP_USE_DX_INTEROP)
3813 /*! \brief Class interface for creating OpenCL buffers from ID3D10Buffer's.
3814  *
3815  *  This is provided to facilitate interoperability with Direct3D.
3816  * 
3817  *  See Memory for details about copy semantics, etc.
3818  *
3819  *  \see Memory
3820  */
3821 class BufferD3D10 : public Buffer
3822 {
3823 public:
3824    
3825
3826     /*! \brief Constructs a BufferD3D10, in a specified context, from a
3827      *         given ID3D10Buffer.
3828      *
3829      *  Wraps clCreateFromD3D10BufferKHR().
3830      */
3831     BufferD3D10(
3832         const Context& context,
3833         cl_mem_flags flags,
3834         ID3D10Buffer* bufobj,
3835         cl_int * err = NULL) : pfn_clCreateFromD3D10BufferKHR(nullptr)
3836     {
3837         typedef CL_API_ENTRY cl_mem (CL_API_CALL *PFN_clCreateFromD3D10BufferKHR)(
3838             cl_context context, cl_mem_flags flags, ID3D10Buffer*  buffer,
3839             cl_int* errcode_ret);
3840         PFN_clCreateFromD3D10BufferKHR pfn_clCreateFromD3D10BufferKHR;
3841 #if CL_HPP_TARGET_OPENCL_VERSION >= 120
3842         vector<cl_context_properties> props = context.getInfo<CL_CONTEXT_PROPERTIES>();
3843         cl_platform platform = -1;
3844         for( int i = 0; i < props.size(); ++i ) {
3845             if( props[i] == CL_CONTEXT_PLATFORM ) {
3846                 platform = props[i+1];
3847             }
3848         }
3849         CL_HPP_INIT_CL_EXT_FCN_PTR_PLATFORM_(platform, clCreateFromD3D10BufferKHR);
3850 #elif CL_HPP_TARGET_OPENCL_VERSION >= 110
3851         CL_HPP_INIT_CL_EXT_FCN_PTR_(clCreateFromD3D10BufferKHR);
3852 #endif
3853
3854         cl_int error;
3855         object_ = pfn_clCreateFromD3D10BufferKHR(
3856             context(),
3857             flags,
3858             bufobj,
3859             &error);
3860
3861         detail::errHandler(error, __CREATE_GL_BUFFER_ERR);
3862         if (err != NULL) {
3863             *err = error;
3864         }
3865     }
3866
3867     //! \brief Default constructor - initializes to NULL.
3868     BufferD3D10() : Buffer() { }
3869
3870     /*! \brief Constructor from cl_mem - takes ownership.
3871      *
3872      * \param retainObject will cause the constructor to retain its cl object.
3873      *                     Defaults to false to maintain compatibility with 
3874      *                     earlier versions.
3875      *  See Memory for further details.
3876      */
3877     explicit BufferD3D10(const cl_mem& buffer, bool retainObject = false) : 
3878         Buffer(buffer, retainObject) { }
3879
3880     /*! \brief Assignment from cl_mem - performs shallow copy.
3881      *
3882      *  See Memory for further details.
3883      */
3884     BufferD3D10& operator = (const cl_mem& rhs)
3885     {
3886         Buffer::operator=(rhs);
3887         return *this;
3888     }
3889
3890     /*! \brief Copy constructor to forward copy to the superclass correctly.
3891      * Required for MSVC.
3892      */
3893     BufferD3D10(const BufferD3D10& buf) : 
3894         Buffer(buf) {}
3895
3896     /*! \brief Copy assignment to forward copy to the superclass correctly.
3897      * Required for MSVC.
3898      */
3899     BufferD3D10& operator = (const BufferD3D10 &buf)
3900     {
3901         Buffer::operator=(buf);
3902         return *this;
3903     }
3904
3905     /*! \brief Move constructor to forward move to the superclass correctly.
3906      * Required for MSVC.
3907      */
3908     BufferD3D10(BufferD3D10&& buf) CL_HPP_NOEXCEPT_ : Buffer(std::move(buf)) {}
3909
3910     /*! \brief Move assignment to forward move to the superclass correctly.
3911      * Required for MSVC.
3912      */
3913     BufferD3D10& operator = (BufferD3D10 &&buf)
3914     {
3915         Buffer::operator=(std::move(buf));
3916         return *this;
3917     }
3918 };
3919 #endif
3920
3921 /*! \brief Class interface for GL Buffer Memory Objects.
3922  *
3923  *  This is provided to facilitate interoperability with OpenGL.
3924  * 
3925  *  See Memory for details about copy semantics, etc.
3926  * 
3927  *  \see Memory
3928  */
3929 class BufferGL : public Buffer
3930 {
3931 public:
3932     /*! \brief Constructs a BufferGL in a specified context, from a given
3933      *         GL buffer.
3934      *
3935      *  Wraps clCreateFromGLBuffer().
3936      */
3937     BufferGL(
3938         const Context& context,
3939         cl_mem_flags flags,
3940         cl_GLuint bufobj,
3941         cl_int * err = NULL)
3942     {
3943         cl_int error;
3944         object_ = ::clCreateFromGLBuffer(
3945             context(),
3946             flags,
3947             bufobj,
3948             &error);
3949
3950         detail::errHandler(error, __CREATE_GL_BUFFER_ERR);
3951         if (err != NULL) {
3952             *err = error;
3953         }
3954     }
3955
3956     //! \brief Default constructor - initializes to NULL.
3957     BufferGL() : Buffer() { }
3958
3959     /*! \brief Constructor from cl_mem - takes ownership.
3960      *
3961      * \param retainObject will cause the constructor to retain its cl object.
3962      *                     Defaults to false to maintain compatibility with
3963      *                     earlier versions.
3964      *  See Memory for further details.
3965      */
3966     explicit BufferGL(const cl_mem& buffer, bool retainObject = false) :
3967         Buffer(buffer, retainObject) { }
3968
3969     /*! \brief Assignment from cl_mem - performs shallow copy.
3970      *
3971      *  See Memory for further details.
3972      */
3973     BufferGL& operator = (const cl_mem& rhs)
3974     {
3975         Buffer::operator=(rhs);
3976         return *this;
3977     }
3978
3979     /*! \brief Copy constructor to forward copy to the superclass correctly.
3980      * Required for MSVC.
3981      */
3982     BufferGL(const BufferGL& buf) : Buffer(buf) {}
3983
3984     /*! \brief Copy assignment to forward copy to the superclass correctly.
3985      * Required for MSVC.
3986      */
3987     BufferGL& operator = (const BufferGL &buf)
3988     {
3989         Buffer::operator=(buf);
3990         return *this;
3991     }
3992
3993     /*! \brief Move constructor to forward move to the superclass correctly.
3994      * Required for MSVC.
3995      */
3996     BufferGL(BufferGL&& buf) CL_HPP_NOEXCEPT_ : Buffer(std::move(buf)) {}
3997
3998     /*! \brief Move assignment to forward move to the superclass correctly.
3999      * Required for MSVC.
4000      */
4001     BufferGL& operator = (BufferGL &&buf)
4002     {
4003         Buffer::operator=(std::move(buf));
4004         return *this;
4005     }
4006
4007     //! \brief Wrapper for clGetGLObjectInfo().
4008     cl_int getObjectInfo(
4009         cl_gl_object_type *type,
4010         cl_GLuint * gl_object_name)
4011     {
4012         return detail::errHandler(
4013             ::clGetGLObjectInfo(object_,type,gl_object_name),
4014             __GET_GL_OBJECT_INFO_ERR);
4015     }
4016 };
4017
4018 /*! \brief Class interface for GL Render Buffer Memory Objects.
4019  *
4020  *  This is provided to facilitate interoperability with OpenGL.
4021  * 
4022  *  See Memory for details about copy semantics, etc.
4023  * 
4024  *  \see Memory
4025  */
4026 class BufferRenderGL : public Buffer
4027 {
4028 public:
4029     /*! \brief Constructs a BufferRenderGL in a specified context, from a given
4030      *         GL Renderbuffer.
4031      *
4032      *  Wraps clCreateFromGLRenderbuffer().
4033      */
4034     BufferRenderGL(
4035         const Context& context,
4036         cl_mem_flags flags,
4037         cl_GLuint bufobj,
4038         cl_int * err = NULL)
4039     {
4040         cl_int error;
4041         object_ = ::clCreateFromGLRenderbuffer(
4042             context(),
4043             flags,
4044             bufobj,
4045             &error);
4046
4047         detail::errHandler(error, __CREATE_GL_RENDER_BUFFER_ERR);
4048         if (err != NULL) {
4049             *err = error;
4050         }
4051     }
4052
4053     //! \brief Default constructor - initializes to NULL.
4054     BufferRenderGL() : Buffer() { }
4055
4056     /*! \brief Constructor from cl_mem - takes ownership.
4057      *
4058      * \param retainObject will cause the constructor to retain its cl object.
4059      *                     Defaults to false to maintain compatibility with 
4060      *                     earlier versions.
4061      *  See Memory for further details.
4062      */
4063     explicit BufferRenderGL(const cl_mem& buffer, bool retainObject = false) :
4064         Buffer(buffer, retainObject) { }
4065
4066     /*! \brief Assignment from cl_mem - performs shallow copy.
4067      *
4068      *  See Memory for further details.
4069      */
4070     BufferRenderGL& operator = (const cl_mem& rhs)
4071     {
4072         Buffer::operator=(rhs);
4073         return *this;
4074     }
4075
4076     /*! \brief Copy constructor to forward copy to the superclass correctly.
4077      * Required for MSVC.
4078      */
4079     BufferRenderGL(const BufferRenderGL& buf) : Buffer(buf) {}
4080
4081     /*! \brief Copy assignment to forward copy to the superclass correctly.
4082      * Required for MSVC.
4083      */
4084     BufferRenderGL& operator = (const BufferRenderGL &buf)
4085     {
4086         Buffer::operator=(buf);
4087         return *this;
4088     }
4089
4090     /*! \brief Move constructor to forward move to the superclass correctly.
4091      * Required for MSVC.
4092      */
4093     BufferRenderGL(BufferRenderGL&& buf) CL_HPP_NOEXCEPT_ : Buffer(std::move(buf)) {}
4094
4095     /*! \brief Move assignment to forward move to the superclass correctly.
4096      * Required for MSVC.
4097      */
4098     BufferRenderGL& operator = (BufferRenderGL &&buf)
4099     {
4100         Buffer::operator=(std::move(buf));
4101         return *this;
4102     }
4103
4104     //! \brief Wrapper for clGetGLObjectInfo().
4105     cl_int getObjectInfo(
4106         cl_gl_object_type *type,
4107         cl_GLuint * gl_object_name)
4108     {
4109         return detail::errHandler(
4110             ::clGetGLObjectInfo(object_,type,gl_object_name),
4111             __GET_GL_OBJECT_INFO_ERR);
4112     }
4113 };
4114
4115 /*! \brief C++ base class for Image Memory objects.
4116  *
4117  *  See Memory for details about copy semantics, etc.
4118  * 
4119  *  \see Memory
4120  */
4121 class Image : public Memory
4122 {
4123 protected:
4124     //! \brief Default constructor - initializes to NULL.
4125     Image() : Memory() { }
4126
4127     /*! \brief Constructor from cl_mem - takes ownership.
4128      *
4129      * \param retainObject will cause the constructor to retain its cl object.
4130      *                     Defaults to false to maintain compatibility with
4131      *                     earlier versions.
4132      *  See Memory for further details.
4133      */
4134     explicit Image(const cl_mem& image, bool retainObject = false) :
4135         Memory(image, retainObject) { }
4136
4137     /*! \brief Assignment from cl_mem - performs shallow copy.
4138      *
4139      *  See Memory for further details.
4140      */
4141     Image& operator = (const cl_mem& rhs)
4142     {
4143         Memory::operator=(rhs);
4144         return *this;
4145     }
4146
4147     /*! \brief Copy constructor to forward copy to the superclass correctly.
4148      * Required for MSVC.
4149      */
4150     Image(const Image& img) : Memory(img) {}
4151
4152     /*! \brief Copy assignment to forward copy to the superclass correctly.
4153      * Required for MSVC.
4154      */
4155     Image& operator = (const Image &img)
4156     {
4157         Memory::operator=(img);
4158         return *this;
4159     }
4160
4161     /*! \brief Move constructor to forward move to the superclass correctly.
4162      * Required for MSVC.
4163      */
4164     Image(Image&& img) CL_HPP_NOEXCEPT_ : Memory(std::move(img)) {}
4165
4166     /*! \brief Move assignment to forward move to the superclass correctly.
4167      * Required for MSVC.
4168      */
4169     Image& operator = (Image &&img)
4170     {
4171         Memory::operator=(std::move(img));
4172         return *this;
4173     }
4174
4175
4176 public:
4177     //! \brief Wrapper for clGetImageInfo().
4178     template <typename T>
4179     cl_int getImageInfo(cl_image_info name, T* param) const
4180     {
4181         return detail::errHandler(
4182             detail::getInfo(&::clGetImageInfo, object_, name, param),
4183             __GET_IMAGE_INFO_ERR);
4184     }
4185     
4186     //! \brief Wrapper for clGetImageInfo() that returns by value.
4187     template <cl_int name> typename
4188     detail::param_traits<detail::cl_image_info, name>::param_type
4189     getImageInfo(cl_int* err = NULL) const
4190     {
4191         typename detail::param_traits<
4192             detail::cl_image_info, name>::param_type param;
4193         cl_int result = getImageInfo(name, &param);
4194         if (err != NULL) {
4195             *err = result;
4196         }
4197         return param;
4198     }
4199 };
4200
4201 #if CL_HPP_TARGET_OPENCL_VERSION >= 120
4202 /*! \brief Class interface for 1D Image Memory objects.
4203  *
4204  *  See Memory for details about copy semantics, etc.
4205  * 
4206  *  \see Memory
4207  */
4208 class Image1D : public Image
4209 {
4210 public:
4211     /*! \brief Constructs a 1D Image in a specified context.
4212      *
4213      *  Wraps clCreateImage().
4214      */
4215     Image1D(
4216         const Context& context,
4217         cl_mem_flags flags,
4218         ImageFormat format,
4219         size_type width,
4220         void* host_ptr = NULL,
4221         cl_int* err = NULL)
4222     {
4223         cl_int error;
4224         cl_image_desc desc =
4225         {
4226             CL_MEM_OBJECT_IMAGE1D,
4227             width,
4228             0, 0, 0, 0, 0, 0, 0, 0
4229         };
4230         object_ = ::clCreateImage(
4231             context(), 
4232             flags, 
4233             &format, 
4234             &desc, 
4235             host_ptr, 
4236             &error);
4237
4238         detail::errHandler(error, __CREATE_IMAGE_ERR);
4239         if (err != NULL) {
4240             *err = error;
4241         }
4242     }
4243
4244     //! \brief Default constructor - initializes to NULL.
4245     Image1D() { }
4246
4247     /*! \brief Constructor from cl_mem - takes ownership.
4248      *
4249      * \param retainObject will cause the constructor to retain its cl object.
4250      *                     Defaults to false to maintain compatibility with
4251      *                     earlier versions.
4252      *  See Memory for further details.
4253      */
4254     explicit Image1D(const cl_mem& image1D, bool retainObject = false) :
4255         Image(image1D, retainObject) { }
4256
4257     /*! \brief Assignment from cl_mem - performs shallow copy.
4258      *
4259      *  See Memory for further details.
4260      */
4261     Image1D& operator = (const cl_mem& rhs)
4262     {
4263         Image::operator=(rhs);
4264         return *this;
4265     }
4266
4267     /*! \brief Copy constructor to forward copy to the superclass correctly.
4268      * Required for MSVC.
4269      */
4270     Image1D(const Image1D& img) : Image(img) {}
4271
4272     /*! \brief Copy assignment to forward copy to the superclass correctly.
4273      * Required for MSVC.
4274      */
4275     Image1D& operator = (const Image1D &img)
4276     {
4277         Image::operator=(img);
4278         return *this;
4279     }
4280
4281     /*! \brief Move constructor to forward move to the superclass correctly.
4282      * Required for MSVC.
4283      */
4284     Image1D(Image1D&& img) CL_HPP_NOEXCEPT_ : Image(std::move(img)) {}
4285
4286     /*! \brief Move assignment to forward move to the superclass correctly.
4287      * Required for MSVC.
4288      */
4289     Image1D& operator = (Image1D &&img)
4290     {
4291         Image::operator=(std::move(img));
4292         return *this;
4293     }
4294
4295 };
4296
4297 /*! \class Image1DBuffer
4298  * \brief Image interface for 1D buffer images.
4299  */
4300 class Image1DBuffer : public Image
4301 {
4302 public:
4303     Image1DBuffer(
4304         const Context& context,
4305         cl_mem_flags flags,
4306         ImageFormat format,
4307         size_type width,
4308         const Buffer &buffer,
4309         cl_int* err = NULL)
4310     {
4311         cl_int error;
4312         cl_image_desc desc =
4313         {
4314             CL_MEM_OBJECT_IMAGE1D_BUFFER,
4315             width,
4316             0, 0, 0, 0, 0, 0, 0,
4317             buffer()
4318         };
4319         object_ = ::clCreateImage(
4320             context(), 
4321             flags, 
4322             &format, 
4323             &desc, 
4324             NULL, 
4325             &error);
4326
4327         detail::errHandler(error, __CREATE_IMAGE_ERR);
4328         if (err != NULL) {
4329             *err = error;
4330         }
4331     }
4332
4333     Image1DBuffer() { }
4334
4335     /*! \brief Constructor from cl_mem - takes ownership.
4336      *
4337      * \param retainObject will cause the constructor to retain its cl object.
4338      *                     Defaults to false to maintain compatibility with
4339      *                     earlier versions.
4340      *  See Memory for further details.
4341      */
4342     explicit Image1DBuffer(const cl_mem& image1D, bool retainObject = false) :
4343         Image(image1D, retainObject) { }
4344
4345     Image1DBuffer& operator = (const cl_mem& rhs)
4346     {
4347         Image::operator=(rhs);
4348         return *this;
4349     }
4350
4351     /*! \brief Copy constructor to forward copy to the superclass correctly.
4352      * Required for MSVC.
4353      */
4354     Image1DBuffer(const Image1DBuffer& img) : Image(img) {}
4355
4356     /*! \brief Copy assignment to forward copy to the superclass correctly.
4357      * Required for MSVC.
4358      */
4359     Image1DBuffer& operator = (const Image1DBuffer &img)
4360     {
4361         Image::operator=(img);
4362         return *this;
4363     }
4364
4365     /*! \brief Move constructor to forward move to the superclass correctly.
4366      * Required for MSVC.
4367      */
4368     Image1DBuffer(Image1DBuffer&& img) CL_HPP_NOEXCEPT_ : Image(std::move(img)) {}
4369
4370     /*! \brief Move assignment to forward move to the superclass correctly.
4371      * Required for MSVC.
4372      */
4373     Image1DBuffer& operator = (Image1DBuffer &&img)
4374     {
4375         Image::operator=(std::move(img));
4376         return *this;
4377     }
4378
4379 };
4380
4381 /*! \class Image1DArray
4382  * \brief Image interface for arrays of 1D images.
4383  */
4384 class Image1DArray : public Image
4385 {
4386 public:
4387     Image1DArray(
4388         const Context& context,
4389         cl_mem_flags flags,
4390         ImageFormat format,
4391         size_type arraySize,
4392         size_type width,
4393         size_type rowPitch,
4394         void* host_ptr = NULL,
4395         cl_int* err = NULL)
4396     {
4397         cl_int error;
4398         cl_image_desc desc =
4399         {
4400             CL_MEM_OBJECT_IMAGE1D_ARRAY,
4401             width,
4402             0, 0,  // height, depth (unused)
4403             arraySize,
4404             rowPitch,
4405             0, 0, 0, 0
4406         };
4407         object_ = ::clCreateImage(
4408             context(), 
4409             flags, 
4410             &format, 
4411             &desc, 
4412             host_ptr, 
4413             &error);
4414
4415         detail::errHandler(error, __CREATE_IMAGE_ERR);
4416         if (err != NULL) {
4417             *err = error;
4418         }
4419     }
4420
4421     Image1DArray() { }
4422   
4423     /*! \brief Constructor from cl_mem - takes ownership.
4424      *
4425      * \param retainObject will cause the constructor to retain its cl object.
4426      *                     Defaults to false to maintain compatibility with
4427      *                     earlier versions.
4428      *  See Memory for further details.
4429      */
4430     explicit Image1DArray(const cl_mem& imageArray, bool retainObject = false) :
4431         Image(imageArray, retainObject) { }
4432
4433
4434     Image1DArray& operator = (const cl_mem& rhs)
4435     {
4436         Image::operator=(rhs);
4437         return *this;
4438     }
4439
4440     /*! \brief Copy constructor to forward copy to the superclass correctly.
4441      * Required for MSVC.
4442      */
4443     Image1DArray(const Image1DArray& img) : Image(img) {}
4444
4445     /*! \brief Copy assignment to forward copy to the superclass correctly.
4446      * Required for MSVC.
4447      */
4448     Image1DArray& operator = (const Image1DArray &img)
4449     {
4450         Image::operator=(img);
4451         return *this;
4452     }
4453
4454     /*! \brief Move constructor to forward move to the superclass correctly.
4455      * Required for MSVC.
4456      */
4457     Image1DArray(Image1DArray&& img) CL_HPP_NOEXCEPT_ : Image(std::move(img)) {}
4458
4459     /*! \brief Move assignment to forward move to the superclass correctly.
4460      * Required for MSVC.
4461      */
4462     Image1DArray& operator = (Image1DArray &&img)
4463     {
4464         Image::operator=(std::move(img));
4465         return *this;
4466     }
4467
4468 };
4469 #endif // #if CL_HPP_TARGET_OPENCL_VERSION >= 120
4470
4471
4472 /*! \brief Class interface for 2D Image Memory objects.
4473  *
4474  *  See Memory for details about copy semantics, etc.
4475  * 
4476  *  \see Memory
4477  */
4478 class Image2D : public Image
4479 {
4480 public:
4481     /*! \brief Constructs a 2D Image in a specified context.
4482      *
4483      *  Wraps clCreateImage().
4484      */
4485     Image2D(
4486         const Context& context,
4487         cl_mem_flags flags,
4488         ImageFormat format,
4489         size_type width,
4490         size_type height,
4491         size_type row_pitch = 0,
4492         void* host_ptr = NULL,
4493         cl_int* err = NULL)
4494     {
4495         cl_int error;
4496         bool useCreateImage;
4497
4498 #if CL_HPP_TARGET_OPENCL_VERSION >= 120 && CL_HPP_MINIMUM_OPENCL_VERSION < 120
4499         // Run-time decision based on the actual platform
4500         {
4501             cl_uint version = detail::getContextPlatformVersion(context());
4502             useCreateImage = (version >= 0x10002); // OpenCL 1.2 or above
4503         }
4504 #elif CL_HPP_TARGET_OPENCL_VERSION >= 120
4505         useCreateImage = true;
4506 #else
4507         useCreateImage = false;
4508 #endif
4509
4510 #if CL_HPP_TARGET_OPENCL_VERSION >= 120
4511         if (useCreateImage)
4512         {
4513             cl_image_desc desc =
4514             {
4515                 CL_MEM_OBJECT_IMAGE2D,
4516                 width,
4517                 height,
4518                 0, 0, // depth, array size (unused)
4519                 row_pitch,
4520                 0, 0, 0, 0
4521             };
4522             object_ = ::clCreateImage(
4523                 context(),
4524                 flags,
4525                 &format,
4526                 &desc,
4527                 host_ptr,
4528                 &error);
4529
4530             detail::errHandler(error, __CREATE_IMAGE_ERR);
4531             if (err != NULL) {
4532                 *err = error;
4533             }
4534         }
4535 #endif // CL_HPP_TARGET_OPENCL_VERSION >= 120
4536 #if CL_HPP_MINIMUM_OPENCL_VERSION < 120
4537         if (!useCreateImage)
4538         {
4539             object_ = ::clCreateImage2D(
4540                 context(), flags,&format, width, height, row_pitch, host_ptr, &error);
4541
4542             detail::errHandler(error, __CREATE_IMAGE2D_ERR);
4543             if (err != NULL) {
4544                 *err = error;
4545             }
4546         }
4547 #endif // CL_HPP_MINIMUM_OPENCL_VERSION < 120
4548     }
4549
4550 #if CL_HPP_TARGET_OPENCL_VERSION >= 200
4551     /*! \brief Constructs a 2D Image from a buffer.
4552     * \note This will share storage with the underlying buffer.
4553     *
4554     *  Wraps clCreateImage().
4555     */
4556     Image2D(
4557         const Context& context,
4558         ImageFormat format,
4559         const Buffer &sourceBuffer,
4560         size_type width,
4561         size_type height,
4562         size_type row_pitch = 0,
4563         cl_int* err = nullptr)
4564     {
4565         cl_int error;
4566
4567         cl_image_desc desc =
4568         {
4569             CL_MEM_OBJECT_IMAGE2D,
4570             width,
4571             height,
4572             0, 0, // depth, array size (unused)
4573             row_pitch,
4574             0, 0, 0,
4575             // Use buffer as input to image
4576             sourceBuffer()
4577         };
4578         object_ = ::clCreateImage(
4579             context(),
4580             0, // flags inherited from buffer
4581             &format,
4582             &desc,
4583             nullptr,
4584             &error);
4585
4586         detail::errHandler(error, __CREATE_IMAGE_ERR);
4587         if (err != nullptr) {
4588             *err = error;
4589         }
4590     }
4591 #endif //#if CL_HPP_TARGET_OPENCL_VERSION >= 200
4592
4593 #if CL_HPP_TARGET_OPENCL_VERSION >= 200
4594     /*! \brief Constructs a 2D Image from an image.
4595     * \note This will share storage with the underlying image but may
4596     *       reinterpret the channel order and type.
4597     *
4598     * The image will be created matching with a descriptor matching the source. 
4599     *
4600     * \param order is the channel order to reinterpret the image data as.
4601     *              The channel order may differ as described in the OpenCL 
4602     *              2.0 API specification.
4603     *
4604     * Wraps clCreateImage().
4605     */
4606     Image2D(
4607         const Context& context,
4608         cl_channel_order order,
4609         const Image &sourceImage,
4610         cl_int* err = nullptr)
4611     {
4612         cl_int error;
4613
4614         // Descriptor fields have to match source image
4615         size_type sourceWidth = 
4616             sourceImage.getImageInfo<CL_IMAGE_WIDTH>();
4617         size_type sourceHeight = 
4618             sourceImage.getImageInfo<CL_IMAGE_HEIGHT>();
4619         size_type sourceRowPitch =
4620             sourceImage.getImageInfo<CL_IMAGE_ROW_PITCH>();
4621         cl_uint sourceNumMIPLevels =
4622             sourceImage.getImageInfo<CL_IMAGE_NUM_MIP_LEVELS>();
4623         cl_uint sourceNumSamples =
4624             sourceImage.getImageInfo<CL_IMAGE_NUM_SAMPLES>();
4625         cl_image_format sourceFormat =
4626             sourceImage.getImageInfo<CL_IMAGE_FORMAT>();
4627
4628         // Update only the channel order. 
4629         // Channel format inherited from source.
4630         sourceFormat.image_channel_order = order;
4631         cl_image_desc desc =
4632         {
4633             CL_MEM_OBJECT_IMAGE2D,
4634             sourceWidth,
4635             sourceHeight,
4636             0, 0, // depth (unused), array size (unused)
4637             sourceRowPitch,
4638             0, // slice pitch (unused)
4639             sourceNumMIPLevels,
4640             sourceNumSamples,
4641             // Use buffer as input to image
4642             sourceImage()
4643         };
4644         object_ = ::clCreateImage(
4645             context(),
4646             0, // flags should be inherited from mem_object
4647             &sourceFormat,
4648             &desc,
4649             nullptr,
4650             &error);
4651
4652         detail::errHandler(error, __CREATE_IMAGE_ERR);
4653         if (err != nullptr) {
4654             *err = error;
4655         }
4656     }
4657 #endif //#if CL_HPP_TARGET_OPENCL_VERSION >= 200
4658
4659     //! \brief Default constructor - initializes to NULL.
4660     Image2D() { }
4661
4662     /*! \brief Constructor from cl_mem - takes ownership.
4663      *
4664      * \param retainObject will cause the constructor to retain its cl object.
4665      *                     Defaults to false to maintain compatibility with
4666      *                     earlier versions.
4667      *  See Memory for further details.
4668      */
4669     explicit Image2D(const cl_mem& image2D, bool retainObject = false) :
4670         Image(image2D, retainObject) { }
4671
4672     /*! \brief Assignment from cl_mem - performs shallow copy.
4673      *
4674      *  See Memory for further details.
4675      */
4676     Image2D& operator = (const cl_mem& rhs)
4677     {
4678         Image::operator=(rhs);
4679         return *this;
4680     }
4681
4682     /*! \brief Copy constructor to forward copy to the superclass correctly.
4683      * Required for MSVC.
4684      */
4685     Image2D(const Image2D& img) : Image(img) {}
4686
4687     /*! \brief Copy assignment to forward copy to the superclass correctly.
4688      * Required for MSVC.
4689      */
4690     Image2D& operator = (const Image2D &img)
4691     {
4692         Image::operator=(img);
4693         return *this;
4694     }
4695
4696     /*! \brief Move constructor to forward move to the superclass correctly.
4697      * Required for MSVC.
4698      */
4699     Image2D(Image2D&& img) CL_HPP_NOEXCEPT_ : Image(std::move(img)) {}
4700
4701     /*! \brief Move assignment to forward move to the superclass correctly.
4702      * Required for MSVC.
4703      */
4704     Image2D& operator = (Image2D &&img)
4705     {
4706         Image::operator=(std::move(img));
4707         return *this;
4708     }
4709
4710 };
4711
4712
4713 #if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS)
4714 /*! \brief Class interface for GL 2D Image Memory objects.
4715  *
4716  *  This is provided to facilitate interoperability with OpenGL.
4717  * 
4718  *  See Memory for details about copy semantics, etc.
4719  * 
4720  *  \see Memory
4721  *  \note Deprecated for OpenCL 1.2. Please use ImageGL instead.
4722  */
4723 class CL_EXT_PREFIX__VERSION_1_1_DEPRECATED Image2DGL : public Image2D 
4724 {
4725 public:
4726     /*! \brief Constructs an Image2DGL in a specified context, from a given
4727      *         GL Texture.
4728      *
4729      *  Wraps clCreateFromGLTexture2D().
4730      */
4731     Image2DGL(
4732         const Context& context,
4733         cl_mem_flags flags,
4734         cl_GLenum target,
4735         cl_GLint  miplevel,
4736         cl_GLuint texobj,
4737         cl_int * err = NULL)
4738     {
4739         cl_int error;
4740         object_ = ::clCreateFromGLTexture2D(
4741             context(),
4742             flags,
4743             target,
4744             miplevel,
4745             texobj,
4746             &error);
4747
4748         detail::errHandler(error, __CREATE_GL_TEXTURE_2D_ERR);
4749         if (err != NULL) {
4750             *err = error;
4751         }
4752
4753     }
4754     
4755     //! \brief Default constructor - initializes to NULL.
4756     Image2DGL() : Image2D() { }
4757
4758     /*! \brief Constructor from cl_mem - takes ownership.
4759      *
4760      * \param retainObject will cause the constructor to retain its cl object.
4761      *                     Defaults to false to maintain compatibility with
4762      *                     earlier versions.
4763      *  See Memory for further details.
4764      */
4765     explicit Image2DGL(const cl_mem& image, bool retainObject = false) : 
4766         Image2D(image, retainObject) { }
4767
4768     /*! \brief Assignment from cl_mem - performs shallow copy.
4769      *c
4770      *  See Memory for further details.
4771      */
4772     Image2DGL& operator = (const cl_mem& rhs)
4773     {
4774         Image2D::operator=(rhs);
4775         return *this;
4776     }
4777
4778     /*! \brief Copy constructor to forward copy to the superclass correctly.
4779      * Required for MSVC.
4780      */
4781     Image2DGL(const Image2DGL& img) : Image2D(img) {}
4782
4783     /*! \brief Copy assignment to forward copy to the superclass correctly.
4784      * Required for MSVC.
4785      */
4786     Image2DGL& operator = (const Image2DGL &img)
4787     {
4788         Image2D::operator=(img);
4789         return *this;
4790     }
4791
4792     /*! \brief Move constructor to forward move to the superclass correctly.
4793      * Required for MSVC.
4794      */
4795     Image2DGL(Image2DGL&& img) CL_HPP_NOEXCEPT_ : Image2D(std::move(img)) {}
4796
4797     /*! \brief Move assignment to forward move to the superclass correctly.
4798      * Required for MSVC.
4799      */
4800     Image2DGL& operator = (Image2DGL &&img)
4801     {
4802         Image2D::operator=(std::move(img));
4803         return *this;
4804     }
4805
4806 } CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED;
4807 #endif // CL_USE_DEPRECATED_OPENCL_1_1_APIS
4808
4809 #if CL_HPP_TARGET_OPENCL_VERSION >= 120
4810 /*! \class Image2DArray
4811  * \brief Image interface for arrays of 2D images.
4812  */
4813 class Image2DArray : public Image
4814 {
4815 public:
4816     Image2DArray(
4817         const Context& context,
4818         cl_mem_flags flags,
4819         ImageFormat format,
4820         size_type arraySize,
4821         size_type width,
4822         size_type height,
4823         size_type rowPitch,
4824         size_type slicePitch,
4825         void* host_ptr = NULL,
4826         cl_int* err = NULL)
4827     {
4828         cl_int error;
4829         cl_image_desc desc =
4830         {
4831             CL_MEM_OBJECT_IMAGE2D_ARRAY,
4832             width,
4833             height,
4834             0,       // depth (unused)
4835             arraySize,
4836             rowPitch,
4837             slicePitch,
4838             0, 0, 0
4839         };
4840         object_ = ::clCreateImage(
4841             context(), 
4842             flags, 
4843             &format, 
4844             &desc, 
4845             host_ptr, 
4846             &error);
4847
4848         detail::errHandler(error, __CREATE_IMAGE_ERR);
4849         if (err != NULL) {
4850             *err = error;
4851         }
4852     }
4853
4854     Image2DArray() { }
4855     
4856     /*! \brief Constructor from cl_mem - takes ownership.
4857      *
4858      * \param retainObject will cause the constructor to retain its cl object.
4859      *                     Defaults to false to maintain compatibility with
4860      *                     earlier versions.
4861      *  See Memory for further details.
4862      */
4863     explicit Image2DArray(const cl_mem& imageArray, bool retainObject = false) : Image(imageArray, retainObject) { }
4864
4865     Image2DArray& operator = (const cl_mem& rhs)
4866     {
4867         Image::operator=(rhs);
4868         return *this;
4869     }
4870
4871     /*! \brief Copy constructor to forward copy to the superclass correctly.
4872      * Required for MSVC.
4873      */
4874     Image2DArray(const Image2DArray& img) : Image(img) {}
4875
4876     /*! \brief Copy assignment to forward copy to the superclass correctly.
4877      * Required for MSVC.
4878      */
4879     Image2DArray& operator = (const Image2DArray &img)
4880     {
4881         Image::operator=(img);
4882         return *this;
4883     }
4884
4885     /*! \brief Move constructor to forward move to the superclass correctly.
4886      * Required for MSVC.
4887      */
4888     Image2DArray(Image2DArray&& img) CL_HPP_NOEXCEPT_ : Image(std::move(img)) {}
4889
4890     /*! \brief Move assignment to forward move to the superclass correctly.
4891      * Required for MSVC.
4892      */
4893     Image2DArray& operator = (Image2DArray &&img)
4894     {
4895         Image::operator=(std::move(img));
4896         return *this;
4897     }
4898 };
4899 #endif // #if CL_HPP_TARGET_OPENCL_VERSION >= 120
4900
4901 /*! \brief Class interface for 3D Image Memory objects.
4902  *
4903  *  See Memory for details about copy semantics, etc.
4904  * 
4905  *  \see Memory
4906  */
4907 class Image3D : public Image
4908 {
4909 public:
4910     /*! \brief Constructs a 3D Image in a specified context.
4911      *
4912      *  Wraps clCreateImage().
4913      */
4914     Image3D(
4915         const Context& context,
4916         cl_mem_flags flags,
4917         ImageFormat format,
4918         size_type width,
4919         size_type height,
4920         size_type depth,
4921         size_type row_pitch = 0,
4922         size_type slice_pitch = 0,
4923         void* host_ptr = NULL,
4924         cl_int* err = NULL)
4925     {
4926         cl_int error;
4927         bool useCreateImage;
4928
4929 #if CL_HPP_TARGET_OPENCL_VERSION >= 120 && CL_HPP_MINIMUM_OPENCL_VERSION < 120
4930         // Run-time decision based on the actual platform
4931         {
4932             cl_uint version = detail::getContextPlatformVersion(context());
4933             useCreateImage = (version >= 0x10002); // OpenCL 1.2 or above
4934         }
4935 #elif CL_HPP_TARGET_OPENCL_VERSION >= 120
4936         useCreateImage = true;
4937 #else
4938         useCreateImage = false;
4939 #endif
4940
4941 #if CL_HPP_TARGET_OPENCL_VERSION >= 120
4942         if (useCreateImage)
4943         {
4944             cl_image_desc desc =
4945             {
4946                 CL_MEM_OBJECT_IMAGE3D,
4947                 width,
4948                 height,
4949                 depth,
4950                 0,      // array size (unused)
4951                 row_pitch,
4952                 slice_pitch,
4953                 0, 0, 0
4954             };
4955             object_ = ::clCreateImage(
4956                 context(), 
4957                 flags, 
4958                 &format, 
4959                 &desc, 
4960                 host_ptr, 
4961                 &error);
4962
4963             detail::errHandler(error, __CREATE_IMAGE_ERR);
4964             if (err != NULL) {
4965                 *err = error;
4966             }
4967         }
4968 #endif  // CL_HPP_TARGET_OPENCL_VERSION >= 120
4969 #if CL_HPP_MINIMUM_OPENCL_VERSION < 120
4970         if (!useCreateImage)
4971         {
4972             object_ = ::clCreateImage3D(
4973                 context(), flags, &format, width, height, depth, row_pitch,
4974                 slice_pitch, host_ptr, &error);
4975
4976             detail::errHandler(error, __CREATE_IMAGE3D_ERR);
4977             if (err != NULL) {
4978                 *err = error;
4979             }
4980         }
4981 #endif // CL_HPP_MINIMUM_OPENCL_VERSION < 120
4982     }
4983
4984     //! \brief Default constructor - initializes to NULL.
4985     Image3D() : Image() { }
4986
4987     /*! \brief Constructor from cl_mem - takes ownership.
4988      *
4989      * \param retainObject will cause the constructor to retain its cl object.
4990      *                     Defaults to false to maintain compatibility with
4991      *                     earlier versions.
4992      *  See Memory for further details.
4993      */
4994     explicit Image3D(const cl_mem& image3D, bool retainObject = false) : 
4995         Image(image3D, retainObject) { }
4996
4997     /*! \brief Assignment from cl_mem - performs shallow copy.
4998      *
4999      *  See Memory for further details.
5000      */
5001     Image3D& operator = (const cl_mem& rhs)
5002     {
5003         Image::operator=(rhs);
5004         return *this;
5005     }
5006
5007     /*! \brief Copy constructor to forward copy to the superclass correctly.
5008      * Required for MSVC.
5009      */
5010     Image3D(const Image3D& img) : Image(img) {}
5011
5012     /*! \brief Copy assignment to forward copy to the superclass correctly.
5013      * Required for MSVC.
5014      */
5015     Image3D& operator = (const Image3D &img)
5016     {
5017         Image::operator=(img);
5018         return *this;
5019     }
5020
5021     /*! \brief Move constructor to forward move to the superclass correctly.
5022      * Required for MSVC.
5023      */
5024     Image3D(Image3D&& img) CL_HPP_NOEXCEPT_ : Image(std::move(img)) {}
5025
5026     /*! \brief Move assignment to forward move to the superclass correctly.
5027      * Required for MSVC.
5028      */
5029     Image3D& operator = (Image3D &&img)
5030     {
5031         Image::operator=(std::move(img));
5032         return *this;
5033     }
5034 };
5035
5036 #if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS)
5037 /*! \brief Class interface for GL 3D Image Memory objects.
5038  *
5039  *  This is provided to facilitate interoperability with OpenGL.
5040  * 
5041  *  See Memory for details about copy semantics, etc.
5042  * 
5043  *  \see Memory
5044  */
5045 class Image3DGL : public Image3D
5046 {
5047 public:
5048     /*! \brief Constructs an Image3DGL in a specified context, from a given
5049      *         GL Texture.
5050      *
5051      *  Wraps clCreateFromGLTexture3D().
5052      */
5053     Image3DGL(
5054         const Context& context,
5055         cl_mem_flags flags,
5056         cl_GLenum target,
5057         cl_GLint  miplevel,
5058         cl_GLuint texobj,
5059         cl_int * err = NULL)
5060     {
5061         cl_int error;
5062         object_ = ::clCreateFromGLTexture3D(
5063             context(),
5064             flags,
5065             target,
5066             miplevel,
5067             texobj,
5068             &error);
5069
5070         detail::errHandler(error, __CREATE_GL_TEXTURE_3D_ERR);
5071         if (err != NULL) {
5072             *err = error;
5073         }
5074     }
5075
5076     //! \brief Default constructor - initializes to NULL.
5077     Image3DGL() : Image3D() { }
5078
5079     /*! \brief Constructor from cl_mem - takes ownership.
5080      *
5081      * \param retainObject will cause the constructor to retain its cl object.
5082      *                     Defaults to false to maintain compatibility with
5083      *                     earlier versions.
5084      *  See Memory for further details.
5085      */
5086     explicit Image3DGL(const cl_mem& image, bool retainObject = false) : 
5087         Image3D(image, retainObject) { }
5088
5089     /*! \brief Assignment from cl_mem - performs shallow copy.
5090      *
5091      *  See Memory for further details.
5092      */
5093     Image3DGL& operator = (const cl_mem& rhs)
5094     {
5095         Image3D::operator=(rhs);
5096         return *this;
5097     }
5098
5099     /*! \brief Copy constructor to forward copy to the superclass correctly.
5100      * Required for MSVC.
5101      */
5102     Image3DGL(const Image3DGL& img) : Image3D(img) {}
5103
5104     /*! \brief Copy assignment to forward copy to the superclass correctly.
5105      * Required for MSVC.
5106      */
5107     Image3DGL& operator = (const Image3DGL &img)
5108     {
5109         Image3D::operator=(img);
5110         return *this;
5111     }
5112
5113     /*! \brief Move constructor to forward move to the superclass correctly.
5114      * Required for MSVC.
5115      */
5116     Image3DGL(Image3DGL&& img) CL_HPP_NOEXCEPT_ : Image3D(std::move(img)) {}
5117
5118     /*! \brief Move assignment to forward move to the superclass correctly.
5119      * Required for MSVC.
5120      */
5121     Image3DGL& operator = (Image3DGL &&img)
5122     {
5123         Image3D::operator=(std::move(img));
5124         return *this;
5125     }
5126 };
5127 #endif // CL_USE_DEPRECATED_OPENCL_1_1_APIS
5128
5129 #if CL_HPP_TARGET_OPENCL_VERSION >= 120
5130 /*! \class ImageGL
5131  * \brief general image interface for GL interop.
5132  * We abstract the 2D and 3D GL images into a single instance here
5133  * that wraps all GL sourced images on the grounds that setup information
5134  * was performed by OpenCL anyway.
5135  */
5136 class ImageGL : public Image
5137 {
5138 public:
5139     ImageGL(
5140         const Context& context,
5141         cl_mem_flags flags,
5142         cl_GLenum target,
5143         cl_GLint  miplevel,
5144         cl_GLuint texobj,
5145         cl_int * err = NULL)
5146     {
5147         cl_int error;
5148         object_ = ::clCreateFromGLTexture(
5149             context(), 
5150             flags, 
5151             target,
5152             miplevel,
5153             texobj,
5154             &error);
5155
5156         detail::errHandler(error, __CREATE_GL_TEXTURE_ERR);
5157         if (err != NULL) {
5158             *err = error;
5159         }
5160     }
5161
5162     ImageGL() : Image() { }
5163     
5164     /*! \brief Constructor from cl_mem - takes ownership.
5165      *
5166      * \param retainObject will cause the constructor to retain its cl object.
5167      *                     Defaults to false to maintain compatibility with
5168      *                     earlier versions.
5169      *  See Memory for further details.
5170      */
5171     explicit ImageGL(const cl_mem& image, bool retainObject = false) : 
5172         Image(image, retainObject) { }
5173
5174     ImageGL& operator = (const cl_mem& rhs)
5175     {
5176         Image::operator=(rhs);
5177         return *this;
5178     }
5179
5180     /*! \brief Copy constructor to forward copy to the superclass correctly.
5181      * Required for MSVC.
5182      */
5183     ImageGL(const ImageGL& img) : Image(img) {}
5184
5185     /*! \brief Copy assignment to forward copy to the superclass correctly.
5186      * Required for MSVC.
5187      */
5188     ImageGL& operator = (const ImageGL &img)
5189     {
5190         Image::operator=(img);
5191         return *this;
5192     }
5193
5194     /*! \brief Move constructor to forward move to the superclass correctly.
5195      * Required for MSVC.
5196      */
5197     ImageGL(ImageGL&& img) CL_HPP_NOEXCEPT_ : Image(std::move(img)) {}
5198
5199     /*! \brief Move assignment to forward move to the superclass correctly.
5200      * Required for MSVC.
5201      */
5202     ImageGL& operator = (ImageGL &&img)
5203     {
5204         Image::operator=(std::move(img));
5205         return *this;
5206     }
5207 };
5208 #endif // CL_HPP_TARGET_OPENCL_VERSION >= 120
5209
5210
5211
5212 #if CL_HPP_TARGET_OPENCL_VERSION >= 200
5213 /*! \brief Class interface for Pipe Memory Objects.
5214 *
5215 *  See Memory for details about copy semantics, etc.
5216 *
5217 *  \see Memory
5218 */
5219 class Pipe : public Memory
5220 {
5221 public:
5222
5223     /*! \brief Constructs a Pipe in a specified context.
5224      *
5225      * Wraps clCreatePipe().
5226      * @param context Context in which to create the pipe.
5227      * @param flags Bitfield. Only CL_MEM_READ_WRITE and CL_MEM_HOST_NO_ACCESS are valid.
5228      * @param packet_size Size in bytes of a single packet of the pipe.
5229      * @param max_packets Number of packets that may be stored in the pipe.
5230      *
5231      */
5232     Pipe(
5233         const Context& context,
5234         cl_uint packet_size,
5235         cl_uint max_packets,
5236         cl_int* err = NULL)
5237     {
5238         cl_int error;
5239
5240         cl_mem_flags flags = CL_MEM_READ_WRITE | CL_MEM_HOST_NO_ACCESS;
5241         object_ = ::clCreatePipe(context(), flags, packet_size, max_packets, nullptr, &error);
5242
5243         detail::errHandler(error, __CREATE_PIPE_ERR);
5244         if (err != NULL) {
5245             *err = error;
5246         }
5247     }
5248
5249     /*! \brief Constructs a Pipe in a the default context.
5250      *
5251      * Wraps clCreatePipe().
5252      * @param flags Bitfield. Only CL_MEM_READ_WRITE and CL_MEM_HOST_NO_ACCESS are valid.
5253      * @param packet_size Size in bytes of a single packet of the pipe.
5254      * @param max_packets Number of packets that may be stored in the pipe.
5255      *
5256      */
5257     Pipe(
5258         cl_uint packet_size,
5259         cl_uint max_packets,
5260         cl_int* err = NULL)
5261     {
5262         cl_int error;
5263
5264         Context context = Context::getDefault(err);
5265
5266         cl_mem_flags flags = CL_MEM_READ_WRITE | CL_MEM_HOST_NO_ACCESS;
5267         object_ = ::clCreatePipe(context(), flags, packet_size, max_packets, nullptr, &error);
5268
5269         detail::errHandler(error, __CREATE_PIPE_ERR);
5270         if (err != NULL) {
5271             *err = error;
5272         }
5273     }
5274
5275     //! \brief Default constructor - initializes to NULL.
5276     Pipe() : Memory() { }
5277
5278     /*! \brief Constructor from cl_mem - takes ownership.
5279      *
5280      * \param retainObject will cause the constructor to retain its cl object.
5281      *                     Defaults to false to maintain compatibility with earlier versions.
5282      *
5283      *  See Memory for further details.
5284      */
5285     explicit Pipe(const cl_mem& pipe, bool retainObject = false) :
5286         Memory(pipe, retainObject) { }
5287
5288     /*! \brief Assignment from cl_mem - performs shallow copy.
5289      *
5290      *  See Memory for further details.
5291      */
5292     Pipe& operator = (const cl_mem& rhs)
5293     {
5294         Memory::operator=(rhs);
5295         return *this;
5296     }
5297
5298     /*! \brief Copy constructor to forward copy to the superclass correctly.
5299      * Required for MSVC.
5300      */
5301     Pipe(const Pipe& pipe) : Memory(pipe) {}
5302
5303     /*! \brief Copy assignment to forward copy to the superclass correctly.
5304      * Required for MSVC.
5305      */
5306     Pipe& operator = (const Pipe &pipe)
5307     {
5308         Memory::operator=(pipe);
5309         return *this;
5310     }
5311
5312     /*! \brief Move constructor to forward move to the superclass correctly.
5313      * Required for MSVC.
5314      */
5315     Pipe(Pipe&& pipe) CL_HPP_NOEXCEPT_ : Memory(std::move(pipe)) {}
5316
5317     /*! \brief Move assignment to forward move to the superclass correctly.
5318      * Required for MSVC.
5319      */
5320     Pipe& operator = (Pipe &&pipe)
5321     {
5322         Memory::operator=(std::move(pipe));
5323         return *this;
5324     }
5325
5326     //! \brief Wrapper for clGetMemObjectInfo().
5327     template <typename T>
5328     cl_int getInfo(cl_pipe_info name, T* param) const
5329     {
5330         return detail::errHandler(
5331             detail::getInfo(&::clGetPipeInfo, object_, name, param),
5332             __GET_PIPE_INFO_ERR);
5333     }
5334
5335     //! \brief Wrapper for clGetMemObjectInfo() that returns by value.
5336     template <cl_int name> typename
5337         detail::param_traits<detail::cl_pipe_info, name>::param_type
5338         getInfo(cl_int* err = NULL) const
5339     {
5340         typename detail::param_traits<
5341             detail::cl_pipe_info, name>::param_type param;
5342         cl_int result = getInfo(name, &param);
5343         if (err != NULL) {
5344             *err = result;
5345         }
5346         return param;
5347     }
5348 }; // class Pipe
5349 #endif // CL_HPP_TARGET_OPENCL_VERSION >= 200
5350
5351
5352 /*! \brief Class interface for cl_sampler.
5353  *
5354  *  \note Copies of these objects are shallow, meaning that the copy will refer
5355  *        to the same underlying cl_sampler as the original.  For details, see
5356  *        clRetainSampler() and clReleaseSampler().
5357  *
5358  *  \see cl_sampler 
5359  */
5360 class Sampler : public detail::Wrapper<cl_sampler>
5361 {
5362 public:
5363     //! \brief Default constructor - initializes to NULL.
5364     Sampler() { }
5365
5366     /*! \brief Constructs a Sampler in a specified context.
5367      *
5368      *  Wraps clCreateSampler().
5369      */
5370     Sampler(
5371         const Context& context,
5372         cl_bool normalized_coords,
5373         cl_addressing_mode addressing_mode,
5374         cl_filter_mode filter_mode,
5375         cl_int* err = NULL)
5376     {
5377         cl_int error;
5378
5379 #if CL_HPP_TARGET_OPENCL_VERSION >= 200
5380         cl_sampler_properties sampler_properties[] = {
5381             CL_SAMPLER_NORMALIZED_COORDS, normalized_coords,
5382             CL_SAMPLER_ADDRESSING_MODE, addressing_mode,
5383             CL_SAMPLER_FILTER_MODE, filter_mode,
5384             0 };
5385         object_ = ::clCreateSamplerWithProperties(
5386             context(),
5387             sampler_properties,
5388             &error);
5389
5390         detail::errHandler(error, __CREATE_SAMPLER_WITH_PROPERTIES_ERR);
5391         if (err != NULL) {
5392             *err = error;
5393         }
5394 #else
5395         object_ = ::clCreateSampler(
5396             context(),
5397             normalized_coords,
5398             addressing_mode,
5399             filter_mode,
5400             &error);
5401
5402         detail::errHandler(error, __CREATE_SAMPLER_ERR);
5403         if (err != NULL) {
5404             *err = error;
5405         }
5406 #endif        
5407     }
5408
5409     /*! \brief Constructor from cl_sampler - takes ownership.
5410      * 
5411      * \param retainObject will cause the constructor to retain its cl object.
5412      *                     Defaults to false to maintain compatibility with
5413      *                     earlier versions.
5414      *  This effectively transfers ownership of a refcount on the cl_sampler
5415      *  into the new Sampler object.
5416      */
5417     explicit Sampler(const cl_sampler& sampler, bool retainObject = false) : 
5418         detail::Wrapper<cl_type>(sampler, retainObject) { }
5419
5420     /*! \brief Assignment operator from cl_sampler - takes ownership.
5421      *
5422      *  This effectively transfers ownership of a refcount on the rhs and calls
5423      *  clReleaseSampler() on the value previously held by this instance.
5424      */
5425     Sampler& operator = (const cl_sampler& rhs)
5426     {
5427         detail::Wrapper<cl_type>::operator=(rhs);
5428         return *this;
5429     }
5430
5431     /*! \brief Copy constructor to forward copy to the superclass correctly.
5432      * Required for MSVC.
5433      */
5434     Sampler(const Sampler& sam) : detail::Wrapper<cl_type>(sam) {}
5435
5436     /*! \brief Copy assignment to forward copy to the superclass correctly.
5437      * Required for MSVC.
5438      */
5439     Sampler& operator = (const Sampler &sam)
5440     {
5441         detail::Wrapper<cl_type>::operator=(sam);
5442         return *this;
5443     }
5444
5445     /*! \brief Move constructor to forward move to the superclass correctly.
5446      * Required for MSVC.
5447      */
5448     Sampler(Sampler&& sam) CL_HPP_NOEXCEPT_ : detail::Wrapper<cl_type>(std::move(sam)) {}
5449
5450     /*! \brief Move assignment to forward move to the superclass correctly.
5451      * Required for MSVC.
5452      */
5453     Sampler& operator = (Sampler &&sam)
5454     {
5455         detail::Wrapper<cl_type>::operator=(std::move(sam));
5456         return *this;
5457     }
5458
5459     //! \brief Wrapper for clGetSamplerInfo().
5460     template <typename T>
5461     cl_int getInfo(cl_sampler_info name, T* param) const
5462     {
5463         return detail::errHandler(
5464             detail::getInfo(&::clGetSamplerInfo, object_, name, param),
5465             __GET_SAMPLER_INFO_ERR);
5466     }
5467
5468     //! \brief Wrapper for clGetSamplerInfo() that returns by value.
5469     template <cl_int name> typename
5470     detail::param_traits<detail::cl_sampler_info, name>::param_type
5471     getInfo(cl_int* err = NULL) const
5472     {
5473         typename detail::param_traits<
5474             detail::cl_sampler_info, name>::param_type param;
5475         cl_int result = getInfo(name, &param);
5476         if (err != NULL) {
5477             *err = result;
5478         }
5479         return param;
5480     }
5481 };
5482
5483 class Program;
5484 class CommandQueue;
5485 class DeviceCommandQueue;
5486 class Kernel;
5487
5488 //! \brief Class interface for specifying NDRange values.
5489 class NDRange
5490 {
5491 private:
5492     size_type sizes_[3];
5493     cl_uint dimensions_;
5494
5495 public:
5496     //! \brief Default constructor - resulting range has zero dimensions.
5497     NDRange()
5498         : dimensions_(0)
5499     {
5500         sizes_[0] = 0;
5501         sizes_[1] = 0;
5502         sizes_[2] = 0;
5503     }
5504
5505     //! \brief Constructs one-dimensional range.
5506     NDRange(size_type size0)
5507         : dimensions_(1)
5508     {
5509         sizes_[0] = size0;
5510         sizes_[1] = 1;
5511         sizes_[2] = 1;
5512     }
5513
5514     //! \brief Constructs two-dimensional range.
5515     NDRange(size_type size0, size_type size1)
5516         : dimensions_(2)
5517     {
5518         sizes_[0] = size0;
5519         sizes_[1] = size1;
5520         sizes_[2] = 1;
5521     }
5522
5523     //! \brief Constructs three-dimensional range.
5524     NDRange(size_type size0, size_type size1, size_type size2)
5525         : dimensions_(3)
5526     {
5527         sizes_[0] = size0;
5528         sizes_[1] = size1;
5529         sizes_[2] = size2;
5530     }
5531
5532     /*! \brief Conversion operator to const size_type *.
5533      *  
5534      *  \returns a pointer to the size of the first dimension.
5535      */
5536     operator const size_type*() const { 
5537         return sizes_; 
5538     }
5539
5540     //! \brief Queries the number of dimensions in the range.
5541     size_type dimensions() const 
5542     { 
5543         return dimensions_; 
5544     }
5545
5546     //! \brief Returns the size of the object in bytes based on the
5547     // runtime number of dimensions
5548     size_type size() const
5549     {
5550         return dimensions_*sizeof(size_type);
5551     }
5552
5553     size_type* get()
5554     {
5555         return sizes_;
5556     }
5557     
5558     const size_type* get() const
5559     {
5560         return sizes_;
5561     }
5562 };
5563
5564 //! \brief A zero-dimensional range.
5565 static const NDRange NullRange;
5566
5567 //! \brief Local address wrapper for use with Kernel::setArg
5568 struct LocalSpaceArg
5569 {
5570     size_type size_;
5571 };
5572
5573 namespace detail {
5574
5575 template <typename T, class Enable = void>
5576 struct KernelArgumentHandler;
5577
5578 // Enable for objects that are not subclasses of memory
5579 // Pointers, constants etc
5580 template <typename T>
5581 struct KernelArgumentHandler<T, typename std::enable_if<!std::is_base_of<cl::Memory, T>::value>::type>
5582 {
5583     static size_type size(const T&) { return sizeof(T); }
5584     static const T* ptr(const T& value) { return &value; }
5585 };
5586
5587 // Enable for subclasses of memory where we want to get a reference to the cl_mem out
5588 // and pass that in for safety
5589 template <typename T>
5590 struct KernelArgumentHandler<T, typename std::enable_if<std::is_base_of<cl::Memory, T>::value>::type>
5591 {
5592     static size_type size(const T&) { return sizeof(cl_mem); }
5593     static const cl_mem* ptr(const T& value) { return &(value()); }
5594 };
5595
5596 // Specialization for DeviceCommandQueue defined later
5597
5598 template <>
5599 struct KernelArgumentHandler<LocalSpaceArg, void>
5600 {
5601     static size_type size(const LocalSpaceArg& value) { return value.size_; }
5602     static const void* ptr(const LocalSpaceArg&) { return NULL; }
5603 };
5604
5605
5606 //! \endcond
5607
5608 /*! Local
5609  * \brief Helper function for generating LocalSpaceArg objects.
5610  */
5611 inline LocalSpaceArg
5612 Local(size_type size)
5613 {
5614     LocalSpaceArg ret = { size };
5615     return ret;
5616 }
5617
5618 /*! \brief Class interface for cl_kernel.
5619  *
5620  *  \note Copies of these objects are shallow, meaning that the copy will refer
5621  *        to the same underlying cl_kernel as the original.  For details, see
5622  *        clRetainKernel() and clReleaseKernel().
5623  *
5624  *  \see cl_kernel
5625  */
5626 class Kernel : public detail::Wrapper<cl_kernel>
5627 {
5628 public:
5629     inline Kernel(const Program& program, const char* name, cl_int* err = NULL);
5630
5631     //! \brief Default constructor - initializes to NULL.
5632     Kernel() { }
5633
5634     /*! \brief Constructor from cl_kernel - takes ownership.
5635      * 
5636      * \param retainObject will cause the constructor to retain its cl object.
5637      *                     Defaults to false to maintain compatibility with
5638      *                     earlier versions.
5639      *  This effectively transfers ownership of a refcount on the cl_kernel
5640      *  into the new Kernel object.
5641      */
5642     explicit Kernel(const cl_kernel& kernel, bool retainObject = false) : 
5643         detail::Wrapper<cl_type>(kernel, retainObject) { }
5644
5645     /*! \brief Assignment operator from cl_kernel - takes ownership.
5646      *
5647      *  This effectively transfers ownership of a refcount on the rhs and calls
5648      *  clReleaseKernel() on the value previously held by this instance.
5649      */
5650     Kernel& operator = (const cl_kernel& rhs)
5651     {
5652         detail::Wrapper<cl_type>::operator=(rhs);
5653         return *this;
5654     }
5655
5656     /*! \brief Copy constructor to forward copy to the superclass correctly.
5657      * Required for MSVC.
5658      */
5659     Kernel(const Kernel& kernel) : detail::Wrapper<cl_type>(kernel) {}
5660
5661     /*! \brief Copy assignment to forward copy to the superclass correctly.
5662      * Required for MSVC.
5663      */
5664     Kernel& operator = (const Kernel &kernel)
5665     {
5666         detail::Wrapper<cl_type>::operator=(kernel);
5667         return *this;
5668     }
5669
5670     /*! \brief Move constructor to forward move to the superclass correctly.
5671      * Required for MSVC.
5672      */
5673     Kernel(Kernel&& kernel) CL_HPP_NOEXCEPT_ : detail::Wrapper<cl_type>(std::move(kernel)) {}
5674
5675     /*! \brief Move assignment to forward move to the superclass correctly.
5676      * Required for MSVC.
5677      */
5678     Kernel& operator = (Kernel &&kernel)
5679     {
5680         detail::Wrapper<cl_type>::operator=(std::move(kernel));
5681         return *this;
5682     }
5683
5684     template <typename T>
5685     cl_int getInfo(cl_kernel_info name, T* param) const
5686     {
5687         return detail::errHandler(
5688             detail::getInfo(&::clGetKernelInfo, object_, name, param),
5689             __GET_KERNEL_INFO_ERR);
5690     }
5691
5692     template <cl_int name> typename
5693     detail::param_traits<detail::cl_kernel_info, name>::param_type
5694     getInfo(cl_int* err = NULL) const
5695     {
5696         typename detail::param_traits<
5697             detail::cl_kernel_info, name>::param_type param;
5698         cl_int result = getInfo(name, &param);
5699         if (err != NULL) {
5700             *err = result;
5701         }
5702         return param;
5703     }
5704
5705 #if CL_HPP_TARGET_OPENCL_VERSION >= 120
5706     template <typename T>
5707     cl_int getArgInfo(cl_uint argIndex, cl_kernel_arg_info name, T* param) const
5708     {
5709         return detail::errHandler(
5710             detail::getInfo(&::clGetKernelArgInfo, object_, argIndex, name, param),
5711             __GET_KERNEL_ARG_INFO_ERR);
5712     }
5713
5714     template <cl_int name> typename
5715     detail::param_traits<detail::cl_kernel_arg_info, name>::param_type
5716     getArgInfo(cl_uint argIndex, cl_int* err = NULL) const
5717     {
5718         typename detail::param_traits<
5719             detail::cl_kernel_arg_info, name>::param_type param;
5720         cl_int result = getArgInfo(argIndex, name, &param);
5721         if (err != NULL) {
5722             *err = result;
5723         }
5724         return param;
5725     }
5726 #endif // CL_HPP_TARGET_OPENCL_VERSION >= 120
5727
5728     template <typename T>
5729     cl_int getWorkGroupInfo(
5730         const Device& device, cl_kernel_work_group_info name, T* param) const
5731     {
5732         return detail::errHandler(
5733             detail::getInfo(
5734                 &::clGetKernelWorkGroupInfo, object_, device(), name, param),
5735                 __GET_KERNEL_WORK_GROUP_INFO_ERR);
5736     }
5737
5738     template <cl_int name> typename
5739     detail::param_traits<detail::cl_kernel_work_group_info, name>::param_type
5740         getWorkGroupInfo(const Device& device, cl_int* err = NULL) const
5741     {
5742         typename detail::param_traits<
5743         detail::cl_kernel_work_group_info, name>::param_type param;
5744         cl_int result = getWorkGroupInfo(device, name, &param);
5745         if (err != NULL) {
5746             *err = result;
5747         }
5748         return param;
5749     }
5750     
5751 #if CL_HPP_TARGET_OPENCL_VERSION >= 200
5752 #if defined(CL_HPP_USE_CL_SUB_GROUPS_KHR)
5753     cl_int getSubGroupInfo(const cl::Device &dev, cl_kernel_sub_group_info name, const cl::NDRange &range, size_type* param) const
5754     {
5755         typedef clGetKernelSubGroupInfoKHR_fn PFN_clGetKernelSubGroupInfoKHR;
5756         static PFN_clGetKernelSubGroupInfoKHR pfn_clGetKernelSubGroupInfoKHR = NULL;
5757         CL_HPP_INIT_CL_EXT_FCN_PTR_(clGetKernelSubGroupInfoKHR);
5758
5759         return detail::errHandler(
5760             pfn_clGetKernelSubGroupInfoKHR(object_, dev(), name, range.size(), range.get(), sizeof(size_type), param, nullptr),
5761             __GET_KERNEL_ARG_INFO_ERR);
5762     }
5763
5764     template <cl_int name>
5765         size_type getSubGroupInfo(const cl::Device &dev, const cl::NDRange &range, cl_int* err = NULL) const
5766     {
5767         size_type param;
5768         cl_int result = getSubGroupInfo(dev, name, range, &param);
5769         if (err != NULL) {
5770             *err = result;
5771         }
5772         return param;
5773     }
5774 #endif // #if defined(CL_HPP_USE_CL_SUB_GROUPS_KHR)
5775 #endif // #if CL_HPP_TARGET_OPENCL_VERSION >= 200
5776
5777 #if CL_HPP_TARGET_OPENCL_VERSION >= 200
5778     /*! \brief setArg overload taking a shared_ptr type
5779      */
5780     template<typename T, class D>
5781     cl_int setArg(cl_uint index, const cl::pointer<T, D> &argPtr)
5782     {
5783         return detail::errHandler(
5784             ::clSetKernelArgSVMPointer(object_, index, argPtr.get()),
5785             __SET_KERNEL_ARGS_ERR);
5786     }
5787
5788     /*! \brief setArg overload taking a vector type.
5789      */
5790     template<typename T, class Alloc>
5791     cl_int setArg(cl_uint index, const cl::vector<T, Alloc> &argPtr)
5792     {
5793         return detail::errHandler(
5794             ::clSetKernelArgSVMPointer(object_, index, argPtr.data()),
5795             __SET_KERNEL_ARGS_ERR);
5796     }
5797
5798     /*! \brief setArg overload taking a pointer type
5799      */
5800     template<typename T>
5801     typename std::enable_if<std::is_pointer<T>::value, cl_int>::type
5802         setArg(cl_uint index, const T argPtr)
5803     {
5804         return detail::errHandler(
5805             ::clSetKernelArgSVMPointer(object_, index, argPtr),
5806             __SET_KERNEL_ARGS_ERR);
5807     }
5808 #endif // #if CL_HPP_TARGET_OPENCL_VERSION >= 200
5809
5810     /*! \brief setArg overload taking a POD type
5811      */
5812     template <typename T>
5813     typename std::enable_if<!std::is_pointer<T>::value, cl_int>::type
5814         setArg(cl_uint index, const T &value)
5815     {
5816         return detail::errHandler(
5817             ::clSetKernelArg(
5818                 object_,
5819                 index,
5820                 detail::KernelArgumentHandler<T>::size(value),
5821                 detail::KernelArgumentHandler<T>::ptr(value)),
5822             __SET_KERNEL_ARGS_ERR);
5823     }
5824
5825     cl_int setArg(cl_uint index, size_type size, const void* argPtr)
5826     {
5827         return detail::errHandler(
5828             ::clSetKernelArg(object_, index, size, argPtr),
5829             __SET_KERNEL_ARGS_ERR);
5830     }
5831
5832 #if CL_HPP_TARGET_OPENCL_VERSION >= 200
5833     /*!
5834      * Specify a vector of SVM pointers that the kernel may access in 
5835      * addition to its arguments.
5836      */
5837     cl_int setSVMPointers(const vector<void*> &pointerList)
5838     {
5839         return detail::errHandler(
5840             ::clSetKernelExecInfo(
5841                 object_,
5842                 CL_KERNEL_EXEC_INFO_SVM_PTRS,
5843                 sizeof(void*)*pointerList.size(),
5844                 pointerList.data()));
5845     }
5846
5847     /*!
5848      * Specify a std::array of SVM pointers that the kernel may access in
5849      * addition to its arguments.
5850      */
5851     template<int ArrayLength>
5852     cl_int setSVMPointers(const std::array<void*, ArrayLength> &pointerList)
5853     {
5854         return detail::errHandler(
5855             ::clSetKernelExecInfo(
5856                 object_,
5857                 CL_KERNEL_EXEC_INFO_SVM_PTRS,
5858                 sizeof(void*)*pointerList.size(),
5859                 pointerList.data()));
5860     }
5861
5862     /*! \brief Enable fine-grained system SVM.
5863      *
5864      * \note It is only possible to enable fine-grained system SVM if all devices
5865      *       in the context associated with kernel support it.
5866      * 
5867      * \param svmEnabled True if fine-grained system SVM is requested. False otherwise.
5868      * \return CL_SUCCESS if the function was executed succesfully. CL_INVALID_OPERATION
5869      *         if no devices in the context support fine-grained system SVM.
5870      *
5871      * \see clSetKernelExecInfo
5872      */
5873     cl_int enableFineGrainedSystemSVM(bool svmEnabled)
5874     {
5875         cl_bool svmEnabled_ = svmEnabled ? CL_TRUE : CL_FALSE;
5876         return detail::errHandler(
5877             ::clSetKernelExecInfo(
5878                 object_,
5879                 CL_KERNEL_EXEC_INFO_SVM_FINE_GRAIN_SYSTEM,
5880                 sizeof(cl_bool),
5881                 &svmEnabled_
5882                 )
5883             );
5884     }
5885     
5886     template<int index, int ArrayLength, class D, typename T0, typename... Ts>
5887     void setSVMPointersHelper(std::array<void*, ArrayLength> &pointerList, const pointer<T0, D> &t0, Ts... ts)
5888     {
5889         pointerList[index] = static_cast<void*>(t0.get());
5890         setSVMPointersHelper<index + 1, Ts...>(ts...);
5891     }
5892
5893     template<int index, int ArrayLength, typename T0, typename... Ts>
5894     typename std::enable_if<std::is_pointer<T0>::value, void>::type
5895     setSVMPointersHelper(std::array<void*, ArrayLength> &pointerList, T0 t0, Ts... ts)
5896     {
5897         pointerList[index] = static_cast<void*>(t0);
5898         setSVMPointersHelper<index + 1, Ts...>(ts...);
5899     }
5900     
5901     template<int index, int ArrayLength, typename T0, class D>
5902     void setSVMPointersHelper(std::array<void*, ArrayLength> &pointerList, const pointer<T0, D> &t0)
5903     {
5904         pointerList[index] = static_cast<void*>(t0.get());
5905     }
5906
5907     template<int index, int ArrayLength, typename T0>
5908     typename std::enable_if<std::is_pointer<T0>::value, void>::type
5909     setSVMPointersHelper(std::array<void*, ArrayLength> &pointerList, T0 t0)
5910     {
5911         pointerList[index] = static_cast<void*>(t0);
5912     }
5913
5914     template<typename T0, typename... Ts>
5915     cl_int setSVMPointers(const T0 &t0, Ts... ts)
5916     {
5917         std::array<void*, 1 + sizeof...(Ts)> pointerList;
5918
5919         setSVMPointersHelper<0, 1 + sizeof...(Ts)>(pointerList, t0, ts...);
5920         return detail::errHandler(
5921             ::clSetKernelExecInfo(
5922             object_,
5923             CL_KERNEL_EXEC_INFO_SVM_PTRS,
5924             sizeof(void*)*(1 + sizeof...(Ts)),
5925             pointerList.data()));
5926     }
5927 #endif // #if CL_HPP_TARGET_OPENCL_VERSION >= 200
5928 };
5929
5930 /*! \class Program
5931  * \brief Program interface that implements cl_program.
5932  */
5933 class Program : public detail::Wrapper<cl_program>
5934 {
5935 public:
5936 #if !defined(CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY)
5937     typedef vector<vector<unsigned char>> Binaries;
5938     typedef vector<string> Sources;
5939 #else // #if !defined(CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY)
5940     typedef vector<std::pair<const void*, size_type> > Binaries;
5941     typedef vector<std::pair<const char*, size_type> > Sources;
5942 #endif // #if !defined(CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY)
5943     
5944     Program(
5945         const string& source,
5946         bool build = false,
5947         cl_int* err = NULL)
5948     {
5949         cl_int error;
5950
5951         const char * strings = source.c_str();
5952         const size_type length  = source.size();
5953
5954         Context context = Context::getDefault(err);
5955
5956         object_ = ::clCreateProgramWithSource(
5957             context(), (cl_uint)1, &strings, &length, &error);
5958
5959         detail::errHandler(error, __CREATE_PROGRAM_WITH_SOURCE_ERR);
5960
5961         if (error == CL_SUCCESS && build) {
5962
5963             error = ::clBuildProgram(
5964                 object_,
5965                 0,
5966                 NULL,
5967 #if !defined(CL_HPP_CL_1_2_DEFAULT_BUILD)
5968                 "-cl-std=CL2.0",
5969 #else
5970                 "",
5971 #endif // #if !defined(CL_HPP_CL_1_2_DEFAULT_BUILD)
5972                 NULL,
5973                 NULL);
5974
5975             detail::buildErrHandler(error, __BUILD_PROGRAM_ERR, getBuildInfo<CL_PROGRAM_BUILD_LOG>());
5976         }
5977
5978         if (err != NULL) {
5979             *err = error;
5980         }
5981     }
5982
5983     Program(
5984         const Context& context,
5985         const string& source,
5986         bool build = false,
5987         cl_int* err = NULL)
5988     {
5989         cl_int error;
5990
5991         const char * strings = source.c_str();
5992         const size_type length  = source.size();
5993
5994         object_ = ::clCreateProgramWithSource(
5995             context(), (cl_uint)1, &strings, &length, &error);
5996
5997         detail::errHandler(error, __CREATE_PROGRAM_WITH_SOURCE_ERR);
5998
5999         if (error == CL_SUCCESS && build) {
6000             error = ::clBuildProgram(
6001                 object_,
6002                 0,
6003                 NULL,
6004 #if !defined(CL_HPP_CL_1_2_DEFAULT_BUILD)
6005                 "-cl-std=CL2.0",
6006 #else
6007                 "",
6008 #endif // #if !defined(CL_HPP_CL_1_2_DEFAULT_BUILD)
6009                 NULL,
6010                 NULL);
6011             
6012             detail::buildErrHandler(error, __BUILD_PROGRAM_ERR, getBuildInfo<CL_PROGRAM_BUILD_LOG>());
6013         }
6014
6015         if (err != NULL) {
6016             *err = error;
6017         }
6018     }
6019
6020     /**
6021      * Create a program from a vector of source strings and the default context.
6022      * Does not compile or link the program.
6023      */
6024     Program(
6025         const Sources& sources,
6026         cl_int* err = NULL)
6027     {
6028         cl_int error;
6029         Context context = Context::getDefault(err);
6030
6031         const size_type n = (size_type)sources.size();
6032
6033         vector<size_type> lengths(n);
6034         vector<const char*> strings(n);
6035
6036         for (size_type i = 0; i < n; ++i) {
6037 #if !defined(CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY)
6038             strings[i] = sources[(int)i].data();
6039             lengths[i] = sources[(int)i].length();
6040 #else // #if !defined(CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY)
6041             strings[i] = sources[(int)i].first;
6042             lengths[i] = sources[(int)i].second;
6043 #endif // #if !defined(CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY)
6044         }
6045
6046         object_ = ::clCreateProgramWithSource(
6047             context(), (cl_uint)n, strings.data(), lengths.data(), &error);
6048
6049         detail::errHandler(error, __CREATE_PROGRAM_WITH_SOURCE_ERR);
6050         if (err != NULL) {
6051             *err = error;
6052         }
6053     }
6054
6055     /**
6056      * Create a program from a vector of source strings and a provided context.
6057      * Does not compile or link the program.
6058      */
6059     Program(
6060         const Context& context,
6061         const Sources& sources,
6062         cl_int* err = NULL)
6063     {
6064         cl_int error;
6065
6066         const size_type n = (size_type)sources.size();
6067
6068         vector<size_type> lengths(n);
6069         vector<const char*> strings(n);
6070
6071         for (size_type i = 0; i < n; ++i) {
6072 #if !defined(CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY)
6073             strings[i] = sources[(int)i].data();
6074             lengths[i] = sources[(int)i].length();
6075 #else // #if !defined(CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY)
6076             strings[i] = sources[(int)i].first;
6077             lengths[i] = sources[(int)i].second;
6078 #endif // #if !defined(CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY)
6079         }
6080
6081         object_ = ::clCreateProgramWithSource(
6082             context(), (cl_uint)n, strings.data(), lengths.data(), &error);
6083
6084         detail::errHandler(error, __CREATE_PROGRAM_WITH_SOURCE_ERR);
6085         if (err != NULL) {
6086             *err = error;
6087         }
6088     }
6089
6090     /**
6091      * Construct a program object from a list of devices and a per-device list of binaries.
6092      * \param context A valid OpenCL context in which to construct the program.
6093      * \param devices A vector of OpenCL device objects for which the program will be created.
6094      * \param binaries A vector of pairs of a pointer to a binary object and its length.
6095      * \param binaryStatus An optional vector that on completion will be resized to
6096      *   match the size of binaries and filled with values to specify if each binary
6097      *   was successfully loaded.
6098      *   Set to CL_SUCCESS if the binary was successfully loaded.
6099      *   Set to CL_INVALID_VALUE if the length is 0 or the binary pointer is NULL.
6100      *   Set to CL_INVALID_BINARY if the binary provided is not valid for the matching device.
6101      * \param err if non-NULL will be set to CL_SUCCESS on successful operation or one of the following errors:
6102      *   CL_INVALID_CONTEXT if context is not a valid context.
6103      *   CL_INVALID_VALUE if the length of devices is zero; or if the length of binaries does not match the length of devices; 
6104      *     or if any entry in binaries is NULL or has length 0.
6105      *   CL_INVALID_DEVICE if OpenCL devices listed in devices are not in the list of devices associated with context.
6106      *   CL_INVALID_BINARY if an invalid program binary was encountered for any device. binaryStatus will return specific status for each device.
6107      *   CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources required by the OpenCL implementation on the host.
6108      */
6109     Program(
6110         const Context& context,
6111         const vector<Device>& devices,
6112         const Binaries& binaries,
6113         vector<cl_int>* binaryStatus = NULL,
6114         cl_int* err = NULL)
6115     {
6116         cl_int error;
6117         
6118         const size_type numDevices = devices.size();
6119         
6120         // Catch size mismatch early and return
6121         if(binaries.size() != numDevices) {
6122             error = CL_INVALID_VALUE;
6123             detail::errHandler(error, __CREATE_PROGRAM_WITH_BINARY_ERR);
6124             if (err != NULL) {
6125                 *err = error;
6126             }
6127             return;
6128         }
6129
6130
6131         vector<size_type> lengths(numDevices);
6132         vector<const unsigned char*> images(numDevices);
6133 #if !defined(CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY)
6134         for (size_type i = 0; i < numDevices; ++i) {
6135             images[i] = binaries[i].data();
6136             lengths[i] = binaries[(int)i].size();
6137         }
6138 #else // #if !defined(CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY)
6139         for (size_type i = 0; i < numDevices; ++i) {
6140             images[i] = (const unsigned char*)binaries[i].first;
6141             lengths[i] = binaries[(int)i].second;
6142         }
6143 #endif // #if !defined(CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY)
6144         
6145         vector<cl_device_id> deviceIDs(numDevices);
6146         for( size_type deviceIndex = 0; deviceIndex < numDevices; ++deviceIndex ) {
6147             deviceIDs[deviceIndex] = (devices[deviceIndex])();
6148         }
6149
6150         if(binaryStatus) {
6151             binaryStatus->resize(numDevices);
6152         }
6153         
6154         object_ = ::clCreateProgramWithBinary(
6155             context(), (cl_uint) devices.size(),
6156             deviceIDs.data(),
6157             lengths.data(), images.data(), (binaryStatus != NULL && numDevices > 0)
6158                ? &binaryStatus->front()
6159                : NULL, &error);
6160
6161         detail::errHandler(error, __CREATE_PROGRAM_WITH_BINARY_ERR);
6162         if (err != NULL) {
6163             *err = error;
6164         }
6165     }
6166
6167     
6168 #if CL_HPP_TARGET_OPENCL_VERSION >= 120
6169     /**
6170      * Create program using builtin kernels.
6171      * \param kernelNames Semi-colon separated list of builtin kernel names
6172      */
6173     Program(
6174         const Context& context,
6175         const vector<Device>& devices,
6176         const string& kernelNames,
6177         cl_int* err = NULL)
6178     {
6179         cl_int error;
6180
6181
6182         size_type numDevices = devices.size();
6183         vector<cl_device_id> deviceIDs(numDevices);
6184         for( size_type deviceIndex = 0; deviceIndex < numDevices; ++deviceIndex ) {
6185             deviceIDs[deviceIndex] = (devices[deviceIndex])();
6186         }
6187         
6188         object_ = ::clCreateProgramWithBuiltInKernels(
6189             context(), 
6190             (cl_uint) devices.size(),
6191             deviceIDs.data(),
6192             kernelNames.c_str(), 
6193             &error);
6194
6195         detail::errHandler(error, __CREATE_PROGRAM_WITH_BUILT_IN_KERNELS_ERR);
6196         if (err != NULL) {
6197             *err = error;
6198         }
6199     }
6200 #endif // CL_HPP_TARGET_OPENCL_VERSION >= 120
6201
6202     Program() { }
6203     
6204
6205     /*! \brief Constructor from cl_mem - takes ownership.
6206      *
6207      * \param retainObject will cause the constructor to retain its cl object.
6208      *                     Defaults to false to maintain compatibility with
6209      *                     earlier versions.
6210      */
6211     explicit Program(const cl_program& program, bool retainObject = false) : 
6212         detail::Wrapper<cl_type>(program, retainObject) { }
6213
6214     Program& operator = (const cl_program& rhs)
6215     {
6216         detail::Wrapper<cl_type>::operator=(rhs);
6217         return *this;
6218     }
6219
6220     /*! \brief Copy constructor to forward copy to the superclass correctly.
6221      * Required for MSVC.
6222      */
6223     Program(const Program& program) : detail::Wrapper<cl_type>(program) {}
6224
6225     /*! \brief Copy assignment to forward copy to the superclass correctly.
6226      * Required for MSVC.
6227      */
6228     Program& operator = (const Program &program)
6229     {
6230         detail::Wrapper<cl_type>::operator=(program);
6231         return *this;
6232     }
6233
6234     /*! \brief Move constructor to forward move to the superclass correctly.
6235      * Required for MSVC.
6236      */
6237     Program(Program&& program) CL_HPP_NOEXCEPT_ : detail::Wrapper<cl_type>(std::move(program)) {}
6238
6239     /*! \brief Move assignment to forward move to the superclass correctly.
6240      * Required for MSVC.
6241      */
6242     Program& operator = (Program &&program)
6243     {
6244         detail::Wrapper<cl_type>::operator=(std::move(program));
6245         return *this;
6246     }
6247
6248     cl_int build(
6249         const vector<Device>& devices,
6250         const char* options = NULL,
6251         void (CL_CALLBACK * notifyFptr)(cl_program, void *) = NULL,
6252         void* data = NULL) const
6253     {
6254         size_type numDevices = devices.size();
6255         vector<cl_device_id> deviceIDs(numDevices);
6256         
6257         for( size_type deviceIndex = 0; deviceIndex < numDevices; ++deviceIndex ) {
6258             deviceIDs[deviceIndex] = (devices[deviceIndex])();
6259         }
6260
6261         cl_int buildError = ::clBuildProgram(
6262             object_,
6263             (cl_uint)
6264             devices.size(),
6265             deviceIDs.data(),
6266             options,
6267             notifyFptr,
6268             data);
6269
6270         return detail::buildErrHandler(buildError, __BUILD_PROGRAM_ERR, getBuildInfo<CL_PROGRAM_BUILD_LOG>());
6271     }
6272
6273     cl_int build(
6274         const char* options = NULL,
6275         void (CL_CALLBACK * notifyFptr)(cl_program, void *) = NULL,
6276         void* data = NULL) const
6277     {
6278         cl_int buildError = ::clBuildProgram(
6279             object_,
6280             0,
6281             NULL,
6282             options,
6283             notifyFptr,
6284             data);
6285
6286
6287         return detail::buildErrHandler(buildError, __BUILD_PROGRAM_ERR, getBuildInfo<CL_PROGRAM_BUILD_LOG>());
6288     }
6289
6290 #if CL_HPP_TARGET_OPENCL_VERSION >= 120
6291     cl_int compile(
6292         const char* options = NULL,
6293         void (CL_CALLBACK * notifyFptr)(cl_program, void *) = NULL,
6294         void* data = NULL) const
6295     {
6296         cl_int error = ::clCompileProgram(
6297             object_,
6298             0,
6299             NULL,
6300             options,
6301             0,
6302             NULL,
6303             NULL,
6304             notifyFptr,
6305             data);
6306         return detail::buildErrHandler(error, __COMPILE_PROGRAM_ERR, getBuildInfo<CL_PROGRAM_BUILD_LOG>());
6307     }
6308 #endif // CL_HPP_TARGET_OPENCL_VERSION >= 120
6309
6310     template <typename T>
6311     cl_int getInfo(cl_program_info name, T* param) const
6312     {
6313         return detail::errHandler(
6314             detail::getInfo(&::clGetProgramInfo, object_, name, param),
6315             __GET_PROGRAM_INFO_ERR);
6316     }
6317
6318     template <cl_int name> typename
6319     detail::param_traits<detail::cl_program_info, name>::param_type
6320     getInfo(cl_int* err = NULL) const
6321     {
6322         typename detail::param_traits<
6323             detail::cl_program_info, name>::param_type param;
6324         cl_int result = getInfo(name, &param);
6325         if (err != NULL) {
6326             *err = result;
6327         }
6328         return param;
6329     }
6330
6331     template <typename T>
6332     cl_int getBuildInfo(
6333         const Device& device, cl_program_build_info name, T* param) const
6334     {
6335         return detail::errHandler(
6336             detail::getInfo(
6337                 &::clGetProgramBuildInfo, object_, device(), name, param),
6338                 __GET_PROGRAM_BUILD_INFO_ERR);
6339     }
6340
6341     template <cl_int name> typename
6342     detail::param_traits<detail::cl_program_build_info, name>::param_type
6343     getBuildInfo(const Device& device, cl_int* err = NULL) const
6344     {
6345         typename detail::param_traits<
6346             detail::cl_program_build_info, name>::param_type param;
6347         cl_int result = getBuildInfo(device, name, &param);
6348         if (err != NULL) {
6349             *err = result;
6350         }
6351         return param;
6352     }
6353     
6354     /**
6355      * Build info function that returns a vector of device/info pairs for the specified 
6356      * info type and for all devices in the program.
6357      * On an error reading the info for any device, an empty vector of info will be returned.
6358      */
6359     template <cl_int name>
6360     vector<std::pair<cl::Device, typename detail::param_traits<detail::cl_program_build_info, name>::param_type>>
6361         getBuildInfo(cl_int *err = NULL) const
6362     {
6363         cl_int result = CL_SUCCESS;
6364
6365         auto devs = getInfo<CL_PROGRAM_DEVICES>(&result);
6366         vector<std::pair<cl::Device, typename detail::param_traits<detail::cl_program_build_info, name>::param_type>>
6367             devInfo;
6368
6369         // If there was an initial error from getInfo return the error
6370         if (result != CL_SUCCESS) {
6371             if (err != NULL) {
6372                 *err = result;
6373             }
6374             return devInfo;
6375         }
6376
6377         for (cl::Device d : devs) {
6378             typename detail::param_traits<
6379                 detail::cl_program_build_info, name>::param_type param;
6380             result = getBuildInfo(d, name, &param);
6381             devInfo.push_back(
6382                 std::pair<cl::Device, typename detail::param_traits<detail::cl_program_build_info, name>::param_type>
6383                 (d, param));
6384             if (result != CL_SUCCESS) {
6385                 // On error, leave the loop and return the error code
6386                 break;
6387             }
6388         }
6389         if (err != NULL) {
6390             *err = result;
6391         }
6392         if (result != CL_SUCCESS) {
6393             devInfo.clear();
6394         }
6395         return devInfo;
6396     }
6397
6398     cl_int createKernels(vector<Kernel>* kernels)
6399     {
6400         cl_uint numKernels;
6401         cl_int err = ::clCreateKernelsInProgram(object_, 0, NULL, &numKernels);
6402         if (err != CL_SUCCESS) {
6403             return detail::errHandler(err, __CREATE_KERNELS_IN_PROGRAM_ERR);
6404         }
6405
6406         vector<cl_kernel> value(numKernels);
6407         
6408         err = ::clCreateKernelsInProgram(
6409             object_, numKernels, value.data(), NULL);
6410         if (err != CL_SUCCESS) {
6411             return detail::errHandler(err, __CREATE_KERNELS_IN_PROGRAM_ERR);
6412         }
6413
6414         if (kernels) {
6415             kernels->resize(value.size());
6416
6417             // Assign to param, constructing with retain behaviour
6418             // to correctly capture each underlying CL object
6419             for (size_type i = 0; i < value.size(); i++) {
6420                 // We do not need to retain because this kernel is being created 
6421                 // by the runtime
6422                 (*kernels)[i] = Kernel(value[i], false);
6423             }
6424         }
6425         return CL_SUCCESS;
6426     }
6427 };
6428
6429 #if CL_HPP_TARGET_OPENCL_VERSION >= 120
6430 inline Program linkProgram(
6431     Program input1,
6432     Program input2,
6433     const char* options = NULL,
6434     void (CL_CALLBACK * notifyFptr)(cl_program, void *) = NULL,
6435     void* data = NULL,
6436     cl_int* err = NULL) 
6437 {
6438     cl_int error_local = CL_SUCCESS;
6439
6440     cl_program programs[2] = { input1(), input2() };
6441
6442     Context ctx = input1.getInfo<CL_PROGRAM_CONTEXT>(&error_local);
6443     if(error_local!=CL_SUCCESS) {
6444         detail::errHandler(error_local, __LINK_PROGRAM_ERR);
6445     }
6446
6447     cl_program prog = ::clLinkProgram(
6448         ctx(),
6449         0,
6450         NULL,
6451         options,
6452         2,
6453         programs,
6454         notifyFptr,
6455         data,
6456         &error_local);
6457
6458     detail::errHandler(error_local,__COMPILE_PROGRAM_ERR);
6459     if (err != NULL) {
6460         *err = error_local;
6461     }
6462
6463     return Program(prog);
6464 }
6465
6466 inline Program linkProgram(
6467     vector<Program> inputPrograms,
6468     const char* options = NULL,
6469     void (CL_CALLBACK * notifyFptr)(cl_program, void *) = NULL,
6470     void* data = NULL,
6471     cl_int* err = NULL) 
6472 {
6473     cl_int error_local = CL_SUCCESS;
6474
6475     vector<cl_program> programs(inputPrograms.size());
6476
6477     for (unsigned int i = 0; i < inputPrograms.size(); i++) {
6478         programs[i] = inputPrograms[i]();
6479     }
6480     
6481     Context ctx;
6482     if(inputPrograms.size() > 0) {
6483         ctx = inputPrograms[0].getInfo<CL_PROGRAM_CONTEXT>(&error_local);
6484         if(error_local!=CL_SUCCESS) {
6485             detail::errHandler(error_local, __LINK_PROGRAM_ERR);
6486         }
6487     }
6488     cl_program prog = ::clLinkProgram(
6489         ctx(),
6490         0,
6491         NULL,
6492         options,
6493         (cl_uint)inputPrograms.size(),
6494         programs.data(),
6495         notifyFptr,
6496         data,
6497         &error_local);
6498
6499     detail::errHandler(error_local,__COMPILE_PROGRAM_ERR);
6500     if (err != NULL) {
6501         *err = error_local;
6502     }
6503
6504     return Program(prog, false);
6505 }
6506 #endif // CL_HPP_TARGET_OPENCL_VERSION >= 120
6507
6508 // Template specialization for CL_PROGRAM_BINARIES
6509 template <>
6510 inline cl_int cl::Program::getInfo(cl_program_info name, vector<vector<unsigned char>>* param) const
6511 {
6512     if (name != CL_PROGRAM_BINARIES) {
6513         return CL_INVALID_VALUE;
6514     }
6515     if (param) {
6516         // Resize the parameter array appropriately for each allocation
6517         // and pass down to the helper
6518
6519         vector<size_type> sizes = getInfo<CL_PROGRAM_BINARY_SIZES>();
6520         size_type numBinaries = sizes.size();
6521
6522         // Resize the parameter array and constituent arrays
6523         param->resize(numBinaries);
6524         for (int i = 0; i < numBinaries; ++i) {
6525             (*param)[i].resize(sizes[i]);
6526         }
6527
6528         return detail::errHandler(
6529             detail::getInfo(&::clGetProgramInfo, object_, name, param),
6530             __GET_PROGRAM_INFO_ERR);
6531     }
6532
6533     return CL_SUCCESS;
6534 }
6535
6536 template<>
6537 inline vector<vector<unsigned char>> cl::Program::getInfo<CL_PROGRAM_BINARIES>(cl_int* err) const
6538 {
6539     vector<vector<unsigned char>> binariesVectors;
6540
6541     cl_int result = getInfo(CL_PROGRAM_BINARIES, &binariesVectors);
6542     if (err != NULL) {
6543         *err = result;
6544     }
6545     return binariesVectors;
6546 }
6547
6548 inline Kernel::Kernel(const Program& program, const char* name, cl_int* err)
6549 {
6550     cl_int error;
6551
6552     object_ = ::clCreateKernel(program(), name, &error);
6553     detail::errHandler(error, __CREATE_KERNEL_ERR);
6554
6555     if (err != NULL) {
6556         *err = error;
6557     }
6558
6559 }
6560
6561 enum class QueueProperties : cl_command_queue_properties
6562 {
6563     None = 0,
6564     Profiling = CL_QUEUE_PROFILING_ENABLE,
6565     OutOfOrder = CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE,
6566 };
6567
6568 inline QueueProperties operator|(QueueProperties lhs, QueueProperties rhs)
6569 {
6570     return static_cast<QueueProperties>(static_cast<cl_command_queue_properties>(lhs) | static_cast<cl_command_queue_properties>(rhs));
6571 }
6572
6573 /*! \class CommandQueue
6574  * \brief CommandQueue interface for cl_command_queue.
6575  */
6576 class CommandQueue : public detail::Wrapper<cl_command_queue>
6577 {
6578 private:
6579     static std::once_flag default_initialized_;
6580     static CommandQueue default_;
6581     static cl_int default_error_;
6582
6583     /*! \brief Create the default command queue returned by @ref getDefault.
6584      *
6585      * It sets default_error_ to indicate success or failure. It does not throw
6586      * @c cl::Error.
6587      */
6588     static void makeDefault()
6589     {
6590         /* We don't want to throw an error from this function, so we have to
6591          * catch and set the error flag.
6592          */
6593 #if defined(CL_HPP_ENABLE_EXCEPTIONS)
6594         try
6595 #endif
6596         {
6597             int error;
6598             Context context = Context::getDefault(&error);
6599
6600             if (error != CL_SUCCESS) {
6601                 default_error_ = error;
6602             }
6603             else {
6604                 Device device = Device::getDefault();
6605                 default_ = CommandQueue(context, device, 0, &default_error_);
6606             }
6607         }
6608 #if defined(CL_HPP_ENABLE_EXCEPTIONS)
6609         catch (cl::Error &e) {
6610             default_error_ = e.err();
6611         }
6612 #endif
6613     }
6614
6615     /*! \brief Create the default command queue.
6616      *
6617      * This sets @c default_. It does not throw
6618      * @c cl::Error.
6619      */
6620     static void makeDefaultProvided(const CommandQueue &c) {
6621         default_ = c;
6622     }
6623
6624 public:
6625 #ifdef CL_HPP_UNIT_TEST_ENABLE
6626     /*! \brief Reset the default.
6627     *
6628     * This sets @c default_ to an empty value to support cleanup in
6629     * the unit test framework.
6630     * This function is not thread safe.
6631     */
6632     static void unitTestClearDefault() {
6633         default_ = CommandQueue();
6634     }
6635 #endif // #ifdef CL_HPP_UNIT_TEST_ENABLE
6636         
6637
6638     /*!
6639      * \brief Constructs a CommandQueue based on passed properties.
6640      * Will return an CL_INVALID_QUEUE_PROPERTIES error if CL_QUEUE_ON_DEVICE is specified.
6641      */
6642    CommandQueue(
6643         cl_command_queue_properties properties,
6644         cl_int* err = NULL)
6645     {
6646         cl_int error;
6647
6648         Context context = Context::getDefault(&error);
6649         detail::errHandler(error, __CREATE_CONTEXT_ERR);
6650
6651         if (error != CL_SUCCESS) {
6652             if (err != NULL) {
6653                 *err = error;
6654             }
6655         }
6656         else {
6657             Device device = context.getInfo<CL_CONTEXT_DEVICES>()[0];
6658
6659 #if CL_HPP_TARGET_OPENCL_VERSION >= 200
6660             cl_queue_properties queue_properties[] = {
6661                 CL_QUEUE_PROPERTIES, properties, 0 };
6662             if ((properties & CL_QUEUE_ON_DEVICE) == 0) {
6663                 object_ = ::clCreateCommandQueueWithProperties(
6664                     context(), device(), queue_properties, &error);
6665             }
6666             else {
6667                 error = CL_INVALID_QUEUE_PROPERTIES;
6668             }
6669
6670             detail::errHandler(error, __CREATE_COMMAND_QUEUE_WITH_PROPERTIES_ERR);
6671             if (err != NULL) {
6672                 *err = error;
6673             }
6674 #else
6675             object_ = ::clCreateCommandQueue(
6676                 context(), device(), properties, &error);
6677
6678             detail::errHandler(error, __CREATE_COMMAND_QUEUE_ERR);
6679             if (err != NULL) {
6680                 *err = error;
6681             }
6682 #endif
6683         }
6684     }
6685
6686    /*!
6687     * \brief Constructs a CommandQueue based on passed properties.
6688     * Will return an CL_INVALID_QUEUE_PROPERTIES error if CL_QUEUE_ON_DEVICE is specified.
6689     */
6690    CommandQueue(
6691        QueueProperties properties,
6692        cl_int* err = NULL)
6693    {
6694        cl_int error;
6695
6696        Context context = Context::getDefault(&error);
6697        detail::errHandler(error, __CREATE_CONTEXT_ERR);
6698
6699        if (error != CL_SUCCESS) {
6700            if (err != NULL) {
6701                *err = error;
6702            }
6703        }
6704        else {
6705            Device device = context.getInfo<CL_CONTEXT_DEVICES>()[0];
6706
6707 #if CL_HPP_TARGET_OPENCL_VERSION >= 200
6708            cl_queue_properties queue_properties[] = {
6709                CL_QUEUE_PROPERTIES, static_cast<cl_queue_properties>(properties), 0 };
6710
6711            object_ = ::clCreateCommandQueueWithProperties(
6712                context(), device(), queue_properties, &error);
6713
6714
6715            detail::errHandler(error, __CREATE_COMMAND_QUEUE_WITH_PROPERTIES_ERR);
6716            if (err != NULL) {
6717                *err = error;
6718            }
6719 #else
6720            object_ = ::clCreateCommandQueue(
6721                context(), device(), static_cast<cl_command_queue_properties>(properties), &error);
6722
6723            detail::errHandler(error, __CREATE_COMMAND_QUEUE_ERR);
6724            if (err != NULL) {
6725                *err = error;
6726            }
6727 #endif
6728        }
6729    }
6730
6731     /*!
6732      * \brief Constructs a CommandQueue for an implementation defined device in the given context
6733      * Will return an CL_INVALID_QUEUE_PROPERTIES error if CL_QUEUE_ON_DEVICE is specified.
6734      */
6735     explicit CommandQueue(
6736         const Context& context,
6737         cl_command_queue_properties properties = 0,
6738         cl_int* err = NULL)
6739     {
6740         cl_int error;
6741         vector<cl::Device> devices;
6742         error = context.getInfo(CL_CONTEXT_DEVICES, &devices);
6743
6744         detail::errHandler(error, __CREATE_CONTEXT_ERR);
6745
6746         if (error != CL_SUCCESS)
6747         {
6748             if (err != NULL) {
6749                 *err = error;
6750             }
6751             return;
6752         }
6753
6754 #if CL_HPP_TARGET_OPENCL_VERSION >= 200
6755         cl_queue_properties queue_properties[] = {
6756             CL_QUEUE_PROPERTIES, properties, 0 };
6757         if ((properties & CL_QUEUE_ON_DEVICE) == 0) {
6758             object_ = ::clCreateCommandQueueWithProperties(
6759                 context(), devices[0](), queue_properties, &error);
6760         }
6761         else {
6762             error = CL_INVALID_QUEUE_PROPERTIES;
6763         }
6764
6765         detail::errHandler(error, __CREATE_COMMAND_QUEUE_WITH_PROPERTIES_ERR);
6766         if (err != NULL) {
6767             *err = error;
6768         }
6769 #else
6770         object_ = ::clCreateCommandQueue(
6771             context(), devices[0](), properties, &error);
6772
6773         detail::errHandler(error, __CREATE_COMMAND_QUEUE_ERR);
6774         if (err != NULL) {
6775             *err = error;
6776         }
6777 #endif
6778
6779     }
6780
6781     /*!
6782     * \brief Constructs a CommandQueue for an implementation defined device in the given context
6783     * Will return an CL_INVALID_QUEUE_PROPERTIES error if CL_QUEUE_ON_DEVICE is specified.
6784     */
6785     explicit CommandQueue(
6786         const Context& context,
6787         QueueProperties properties,
6788         cl_int* err = NULL)
6789     {
6790         cl_int error;
6791         vector<cl::Device> devices;
6792         error = context.getInfo(CL_CONTEXT_DEVICES, &devices);
6793
6794         detail::errHandler(error, __CREATE_CONTEXT_ERR);
6795
6796         if (error != CL_SUCCESS)
6797         {
6798             if (err != NULL) {
6799                 *err = error;
6800             }
6801             return;
6802         }
6803
6804 #if CL_HPP_TARGET_OPENCL_VERSION >= 200
6805         cl_queue_properties queue_properties[] = {
6806             CL_QUEUE_PROPERTIES, static_cast<cl_queue_properties>(properties), 0 };
6807         object_ = ::clCreateCommandQueueWithProperties(
6808             context(), devices[0](), queue_properties, &error);
6809        
6810         detail::errHandler(error, __CREATE_COMMAND_QUEUE_WITH_PROPERTIES_ERR);
6811         if (err != NULL) {
6812             *err = error;
6813         }
6814 #else
6815         object_ = ::clCreateCommandQueue(
6816             context(), devices[0](), static_cast<cl_command_queue_properties>(properties), &error);
6817
6818         detail::errHandler(error, __CREATE_COMMAND_QUEUE_ERR);
6819         if (err != NULL) {
6820             *err = error;
6821         }
6822 #endif
6823
6824     }
6825
6826     /*!
6827      * \brief Constructs a CommandQueue for a passed device and context
6828      * Will return an CL_INVALID_QUEUE_PROPERTIES error if CL_QUEUE_ON_DEVICE is specified.
6829      */
6830     CommandQueue(
6831         const Context& context,
6832         const Device& device,
6833         cl_command_queue_properties properties = 0,
6834         cl_int* err = NULL)
6835     {
6836         cl_int error;
6837
6838 #if CL_HPP_TARGET_OPENCL_VERSION >= 200
6839         cl_queue_properties queue_properties[] = {
6840             CL_QUEUE_PROPERTIES, properties, 0 };
6841         object_ = ::clCreateCommandQueueWithProperties(
6842             context(), device(), queue_properties, &error);
6843         
6844         detail::errHandler(error, __CREATE_COMMAND_QUEUE_WITH_PROPERTIES_ERR);
6845         if (err != NULL) {
6846             *err = error;
6847         }
6848 #else
6849         object_ = ::clCreateCommandQueue(
6850             context(), device(), properties, &error);
6851
6852         detail::errHandler(error, __CREATE_COMMAND_QUEUE_ERR);
6853         if (err != NULL) {
6854             *err = error;
6855         }
6856 #endif
6857     }
6858
6859     /*!
6860      * \brief Constructs a CommandQueue for a passed device and context
6861      * Will return an CL_INVALID_QUEUE_PROPERTIES error if CL_QUEUE_ON_DEVICE is specified.
6862      */
6863     CommandQueue(
6864         const Context& context,
6865         const Device& device,
6866         QueueProperties properties,
6867         cl_int* err = NULL)
6868     {
6869             cl_int error;
6870
6871 #if CL_HPP_TARGET_OPENCL_VERSION >= 200
6872             cl_queue_properties queue_properties[] = {
6873                 CL_QUEUE_PROPERTIES, static_cast<cl_queue_properties>(properties), 0 };
6874             object_ = ::clCreateCommandQueueWithProperties(
6875                 context(), device(), queue_properties, &error);
6876       
6877             detail::errHandler(error, __CREATE_COMMAND_QUEUE_WITH_PROPERTIES_ERR);
6878             if (err != NULL) {
6879                 *err = error;
6880             }
6881 #else
6882             object_ = ::clCreateCommandQueue(
6883                 context(), device(), static_cast<cl_command_queue_properties>(properties), &error);
6884
6885             detail::errHandler(error, __CREATE_COMMAND_QUEUE_ERR);
6886             if (err != NULL) {
6887                 *err = error;
6888             }
6889 #endif
6890         }
6891
6892     static CommandQueue getDefault(cl_int * err = NULL) 
6893     {
6894         std::call_once(default_initialized_, makeDefault);
6895 #if CL_HPP_TARGET_OPENCL_VERSION >= 200
6896         detail::errHandler(default_error_, __CREATE_COMMAND_QUEUE_WITH_PROPERTIES_ERR);
6897 #else // CL_HPP_TARGET_OPENCL_VERSION >= 200
6898         detail::errHandler(default_error_, __CREATE_COMMAND_QUEUE_ERR);
6899 #endif // CL_HPP_TARGET_OPENCL_VERSION >= 200
6900         if (err != NULL) {
6901             *err = default_error_;
6902         }
6903         return default_;
6904     }
6905
6906     /**
6907      * Modify the default command queue to be used by
6908      * subsequent operations.
6909      * Will only set the default if no default was previously created.
6910      * @return updated default command queue.
6911      *         Should be compared to the passed value to ensure that it was updated.
6912      */
6913     static CommandQueue setDefault(const CommandQueue &default_queue)
6914     {
6915         std::call_once(default_initialized_, makeDefaultProvided, std::cref(default_queue));
6916         detail::errHandler(default_error_);
6917         return default_;
6918     }
6919
6920     CommandQueue() { }
6921
6922
6923     /*! \brief Constructor from cl_mem - takes ownership.
6924      *
6925      * \param retainObject will cause the constructor to retain its cl object.
6926      *                     Defaults to false to maintain compatibility with
6927      *                     earlier versions.
6928      */
6929     explicit CommandQueue(const cl_command_queue& commandQueue, bool retainObject = false) : 
6930         detail::Wrapper<cl_type>(commandQueue, retainObject) { }
6931
6932     CommandQueue& operator = (const cl_command_queue& rhs)
6933     {
6934         detail::Wrapper<cl_type>::operator=(rhs);
6935         return *this;
6936     }
6937
6938     /*! \brief Copy constructor to forward copy to the superclass correctly.
6939      * Required for MSVC.
6940      */
6941     CommandQueue(const CommandQueue& queue) : detail::Wrapper<cl_type>(queue) {}
6942
6943     /*! \brief Copy assignment to forward copy to the superclass correctly.
6944      * Required for MSVC.
6945      */
6946     CommandQueue& operator = (const CommandQueue &queue)
6947     {
6948         detail::Wrapper<cl_type>::operator=(queue);
6949         return *this;
6950     }
6951
6952     /*! \brief Move constructor to forward move to the superclass correctly.
6953      * Required for MSVC.
6954      */
6955     CommandQueue(CommandQueue&& queue) CL_HPP_NOEXCEPT_ : detail::Wrapper<cl_type>(std::move(queue)) {}
6956
6957     /*! \brief Move assignment to forward move to the superclass correctly.
6958      * Required for MSVC.
6959      */
6960     CommandQueue& operator = (CommandQueue &&queue)
6961     {
6962         detail::Wrapper<cl_type>::operator=(std::move(queue));
6963         return *this;
6964     }
6965
6966     template <typename T>
6967     cl_int getInfo(cl_command_queue_info name, T* param) const
6968     {
6969         return detail::errHandler(
6970             detail::getInfo(
6971                 &::clGetCommandQueueInfo, object_, name, param),
6972                 __GET_COMMAND_QUEUE_INFO_ERR);
6973     }
6974
6975     template <cl_int name> typename
6976     detail::param_traits<detail::cl_command_queue_info, name>::param_type
6977     getInfo(cl_int* err = NULL) const
6978     {
6979         typename detail::param_traits<
6980             detail::cl_command_queue_info, name>::param_type param;
6981         cl_int result = getInfo(name, &param);
6982         if (err != NULL) {
6983             *err = result;
6984         }
6985         return param;
6986     }
6987
6988     cl_int enqueueReadBuffer(
6989         const Buffer& buffer,
6990         cl_bool blocking,
6991         size_type offset,
6992         size_type size,
6993         void* ptr,
6994         const vector<Event>* events = NULL,
6995         Event* event = NULL) const
6996     {
6997         cl_event tmp;
6998         cl_int err = detail::errHandler(
6999             ::clEnqueueReadBuffer(
7000                 object_, buffer(), blocking, offset, size,
7001                 ptr,
7002                 (events != NULL) ? (cl_uint) events->size() : 0,
7003                 (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,
7004                 (event != NULL) ? &tmp : NULL),
7005             __ENQUEUE_READ_BUFFER_ERR);
7006
7007         if (event != NULL && err == CL_SUCCESS)
7008             *event = tmp;
7009
7010         return err;
7011     }
7012
7013     cl_int enqueueWriteBuffer(
7014         const Buffer& buffer,
7015         cl_bool blocking,
7016         size_type offset,
7017         size_type size,
7018         const void* ptr,
7019         const vector<Event>* events = NULL,
7020         Event* event = NULL) const
7021     {
7022         cl_event tmp;
7023         cl_int err = detail::errHandler(
7024             ::clEnqueueWriteBuffer(
7025                 object_, buffer(), blocking, offset, size,
7026                 ptr,
7027                 (events != NULL) ? (cl_uint) events->size() : 0,
7028                 (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,
7029                 (event != NULL) ? &tmp : NULL),
7030                 __ENQUEUE_WRITE_BUFFER_ERR);
7031
7032         if (event != NULL && err == CL_SUCCESS)
7033             *event = tmp;
7034
7035         return err;
7036     }
7037
7038     cl_int enqueueCopyBuffer(
7039         const Buffer& src,
7040         const Buffer& dst,
7041         size_type src_offset,
7042         size_type dst_offset,
7043         size_type size,
7044         const vector<Event>* events = NULL,
7045         Event* event = NULL) const
7046     {
7047         cl_event tmp;
7048         cl_int err = detail::errHandler(
7049             ::clEnqueueCopyBuffer(
7050                 object_, src(), dst(), src_offset, dst_offset, size,
7051                 (events != NULL) ? (cl_uint) events->size() : 0,
7052                 (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,
7053                 (event != NULL) ? &tmp : NULL),
7054             __ENQEUE_COPY_BUFFER_ERR);
7055
7056         if (event != NULL && err == CL_SUCCESS)
7057             *event = tmp;
7058
7059         return err;
7060     }
7061
7062     cl_int enqueueReadBufferRect(
7063         const Buffer& buffer,
7064         cl_bool blocking,
7065         const array<size_type, 3>& buffer_offset,
7066         const array<size_type, 3>& host_offset,
7067         const array<size_type, 3>& region,
7068         size_type buffer_row_pitch,
7069         size_type buffer_slice_pitch,
7070         size_type host_row_pitch,
7071         size_type host_slice_pitch,
7072         void *ptr,
7073         const vector<Event>* events = NULL,
7074         Event* event = NULL) const
7075     {
7076         cl_event tmp;
7077         cl_int err = detail::errHandler(
7078             ::clEnqueueReadBufferRect(
7079                 object_, 
7080                 buffer(), 
7081                 blocking,
7082                 buffer_offset.data(),
7083                 host_offset.data(),
7084                 region.data(),
7085                 buffer_row_pitch,
7086                 buffer_slice_pitch,
7087                 host_row_pitch,
7088                 host_slice_pitch,
7089                 ptr,
7090                 (events != NULL) ? (cl_uint) events->size() : 0,
7091                 (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,
7092                 (event != NULL) ? &tmp : NULL),
7093                 __ENQUEUE_READ_BUFFER_RECT_ERR);
7094
7095         if (event != NULL && err == CL_SUCCESS)
7096             *event = tmp;
7097
7098         return err;
7099     }
7100
7101     cl_int enqueueWriteBufferRect(
7102         const Buffer& buffer,
7103         cl_bool blocking,
7104         const array<size_type, 3>& buffer_offset,
7105         const array<size_type, 3>& host_offset,
7106         const array<size_type, 3>& region,
7107         size_type buffer_row_pitch,
7108         size_type buffer_slice_pitch,
7109         size_type host_row_pitch,
7110         size_type host_slice_pitch,
7111         void *ptr,
7112         const vector<Event>* events = NULL,
7113         Event* event = NULL) const
7114     {
7115         cl_event tmp;
7116         cl_int err = detail::errHandler(
7117             ::clEnqueueWriteBufferRect(
7118                 object_, 
7119                 buffer(), 
7120                 blocking,
7121                 buffer_offset.data(),
7122                 host_offset.data(),
7123                 region.data(),
7124                 buffer_row_pitch,
7125                 buffer_slice_pitch,
7126                 host_row_pitch,
7127                 host_slice_pitch,
7128                 ptr,
7129                 (events != NULL) ? (cl_uint) events->size() : 0,
7130                 (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,
7131                 (event != NULL) ? &tmp : NULL),
7132                 __ENQUEUE_WRITE_BUFFER_RECT_ERR);
7133
7134         if (event != NULL && err == CL_SUCCESS)
7135             *event = tmp;
7136
7137         return err;
7138     }
7139
7140     cl_int enqueueCopyBufferRect(
7141         const Buffer& src,
7142         const Buffer& dst,
7143         const array<size_type, 3>& src_origin,
7144         const array<size_type, 3>& dst_origin,
7145         const array<size_type, 3>& region,
7146         size_type src_row_pitch,
7147         size_type src_slice_pitch,
7148         size_type dst_row_pitch,
7149         size_type dst_slice_pitch,
7150         const vector<Event>* events = NULL,
7151         Event* event = NULL) const
7152     {
7153         cl_event tmp;
7154         cl_int err = detail::errHandler(
7155             ::clEnqueueCopyBufferRect(
7156                 object_, 
7157                 src(), 
7158                 dst(), 
7159                 src_origin.data(),
7160                 dst_origin.data(),
7161                 region.data(),
7162                 src_row_pitch,
7163                 src_slice_pitch,
7164                 dst_row_pitch,
7165                 dst_slice_pitch,
7166                 (events != NULL) ? (cl_uint) events->size() : 0,
7167                 (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,
7168                 (event != NULL) ? &tmp : NULL),
7169             __ENQEUE_COPY_BUFFER_RECT_ERR);
7170
7171         if (event != NULL && err == CL_SUCCESS)
7172             *event = tmp;
7173
7174         return err;
7175     }
7176
7177 #if CL_HPP_TARGET_OPENCL_VERSION >= 120
7178     /**
7179      * Enqueue a command to fill a buffer object with a pattern
7180      * of a given size. The pattern is specified as a vector type.
7181      * \tparam PatternType The datatype of the pattern field. 
7182      *     The pattern type must be an accepted OpenCL data type.
7183      * \tparam offset Is the offset in bytes into the buffer at 
7184      *     which to start filling. This must be a multiple of 
7185      *     the pattern size.
7186      * \tparam size Is the size in bytes of the region to fill.
7187      *     This must be a multiple of the pattern size.
7188      */
7189     template<typename PatternType>
7190     cl_int enqueueFillBuffer(
7191         const Buffer& buffer,
7192         PatternType pattern,
7193         size_type offset,
7194         size_type size,
7195         const vector<Event>* events = NULL,
7196         Event* event = NULL) const
7197     {
7198         cl_event tmp;
7199         cl_int err = detail::errHandler(
7200             ::clEnqueueFillBuffer(
7201                 object_, 
7202                 buffer(),
7203                 static_cast<void*>(&pattern),
7204                 sizeof(PatternType), 
7205                 offset, 
7206                 size,
7207                 (events != NULL) ? (cl_uint) events->size() : 0,
7208                 (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,
7209                 (event != NULL) ? &tmp : NULL),
7210                 __ENQUEUE_FILL_BUFFER_ERR);
7211
7212         if (event != NULL && err == CL_SUCCESS)
7213             *event = tmp;
7214
7215         return err;
7216     }
7217 #endif // CL_HPP_TARGET_OPENCL_VERSION >= 120
7218
7219     cl_int enqueueReadImage(
7220         const Image& image,
7221         cl_bool blocking,
7222         const array<size_type, 3>& origin,
7223         const array<size_type, 3>& region,
7224         size_type row_pitch,
7225         size_type slice_pitch,
7226         void* ptr,
7227         const vector<Event>* events = NULL,
7228         Event* event = NULL) const
7229     {
7230         cl_event tmp;
7231         cl_int err = detail::errHandler(
7232             ::clEnqueueReadImage(
7233                 object_, 
7234                 image(), 
7235                 blocking, 
7236                 origin.data(),
7237                 region.data(), 
7238                 row_pitch, 
7239                 slice_pitch, 
7240                 ptr,
7241                 (events != NULL) ? (cl_uint) events->size() : 0,
7242                 (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,
7243                 (event != NULL) ? &tmp : NULL),
7244             __ENQUEUE_READ_IMAGE_ERR);
7245
7246         if (event != NULL && err == CL_SUCCESS)
7247             *event = tmp;
7248
7249         return err;
7250     }
7251
7252     cl_int enqueueWriteImage(
7253         const Image& image,
7254         cl_bool blocking,
7255         const array<size_type, 3>& origin,
7256         const array<size_type, 3>& region,
7257         size_type row_pitch,
7258         size_type slice_pitch,
7259         void* ptr,
7260         const vector<Event>* events = NULL,
7261         Event* event = NULL) const
7262     {
7263         cl_event tmp;
7264         cl_int err = detail::errHandler(
7265             ::clEnqueueWriteImage(
7266                 object_, 
7267                 image(), 
7268                 blocking, 
7269                 origin.data(),
7270                 region.data(), 
7271                 row_pitch, 
7272                 slice_pitch, 
7273                 ptr,
7274                 (events != NULL) ? (cl_uint) events->size() : 0,
7275                 (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,
7276                 (event != NULL) ? &tmp : NULL),
7277             __ENQUEUE_WRITE_IMAGE_ERR);
7278
7279         if (event != NULL && err == CL_SUCCESS)
7280             *event = tmp;
7281
7282         return err;
7283     }
7284
7285     cl_int enqueueCopyImage(
7286         const Image& src,
7287         const Image& dst,
7288         const array<size_type, 3>& src_origin,
7289         const array<size_type, 3>& dst_origin,
7290         const array<size_type, 3>& region,
7291         const vector<Event>* events = NULL,
7292         Event* event = NULL) const
7293     {
7294         cl_event tmp;
7295         cl_int err = detail::errHandler(
7296             ::clEnqueueCopyImage(
7297                 object_, 
7298                 src(), 
7299                 dst(), 
7300                 src_origin.data(),
7301                 dst_origin.data(), 
7302                 region.data(),
7303                 (events != NULL) ? (cl_uint) events->size() : 0,
7304                 (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,
7305                 (event != NULL) ? &tmp : NULL),
7306             __ENQUEUE_COPY_IMAGE_ERR);
7307
7308         if (event != NULL && err == CL_SUCCESS)
7309             *event = tmp;
7310
7311         return err;
7312     }
7313
7314 #if CL_HPP_TARGET_OPENCL_VERSION >= 120
7315     /**
7316      * Enqueue a command to fill an image object with a specified color.
7317      * \param fillColor is the color to use to fill the image.
7318      *     This is a four component RGBA floating-point color value if
7319      *     the image channel data type is not an unnormalized signed or
7320      *     unsigned data type.
7321      */
7322     cl_int enqueueFillImage(
7323         const Image& image,
7324         cl_float4 fillColor,
7325         const array<size_type, 3>& origin,
7326         const array<size_type, 3>& region,
7327         const vector<Event>* events = NULL,
7328         Event* event = NULL) const
7329     {
7330         cl_event tmp;
7331         cl_int err = detail::errHandler(
7332             ::clEnqueueFillImage(
7333                 object_, 
7334                 image(),
7335                 static_cast<void*>(&fillColor), 
7336                 origin.data(),
7337                 region.data(),
7338                 (events != NULL) ? (cl_uint) events->size() : 0,
7339                 (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,
7340                 (event != NULL) ? &tmp : NULL),
7341                 __ENQUEUE_FILL_IMAGE_ERR);
7342
7343         if (event != NULL && err == CL_SUCCESS)
7344             *event = tmp;
7345
7346         return err;
7347     }
7348
7349     /**
7350      * Enqueue a command to fill an image object with a specified color.
7351      * \param fillColor is the color to use to fill the image.
7352      *     This is a four component RGBA signed integer color value if
7353      *     the image channel data type is an unnormalized signed integer
7354      *     type.
7355      */
7356     cl_int enqueueFillImage(
7357         const Image& image,
7358         cl_int4 fillColor,
7359         const array<size_type, 3>& origin,
7360         const array<size_type, 3>& region,
7361         const vector<Event>* events = NULL,
7362         Event* event = NULL) const
7363     {
7364         cl_event tmp;
7365         cl_int err = detail::errHandler(
7366             ::clEnqueueFillImage(
7367                 object_, 
7368                 image(),
7369                 static_cast<void*>(&fillColor), 
7370                 origin.data(),
7371                 region.data(),
7372                 (events != NULL) ? (cl_uint) events->size() : 0,
7373                 (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,
7374                 (event != NULL) ? &tmp : NULL),
7375                 __ENQUEUE_FILL_IMAGE_ERR);
7376
7377         if (event != NULL && err == CL_SUCCESS)
7378             *event = tmp;
7379
7380         return err;
7381     }
7382
7383     /**
7384      * Enqueue a command to fill an image object with a specified color.
7385      * \param fillColor is the color to use to fill the image.
7386      *     This is a four component RGBA unsigned integer color value if
7387      *     the image channel data type is an unnormalized unsigned integer
7388      *     type.
7389      */
7390     cl_int enqueueFillImage(
7391         const Image& image,
7392         cl_uint4 fillColor,
7393         const array<size_type, 3>& origin,
7394         const array<size_type, 3>& region,
7395         const vector<Event>* events = NULL,
7396         Event* event = NULL) const
7397     {
7398         cl_event tmp;
7399         cl_int err = detail::errHandler(
7400             ::clEnqueueFillImage(
7401                 object_, 
7402                 image(),
7403                 static_cast<void*>(&fillColor), 
7404                 origin.data(),
7405                 region.data(),
7406                 (events != NULL) ? (cl_uint) events->size() : 0,
7407                 (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,
7408                 (event != NULL) ? &tmp : NULL),
7409                 __ENQUEUE_FILL_IMAGE_ERR);
7410
7411         if (event != NULL && err == CL_SUCCESS)
7412             *event = tmp;
7413
7414         return err;
7415     }
7416 #endif // CL_HPP_TARGET_OPENCL_VERSION >= 120
7417
7418     cl_int enqueueCopyImageToBuffer(
7419         const Image& src,
7420         const Buffer& dst,
7421         const array<size_type, 3>& src_origin,
7422         const array<size_type, 3>& region,
7423         size_type dst_offset,
7424         const vector<Event>* events = NULL,
7425         Event* event = NULL) const
7426     {
7427         cl_event tmp;
7428         cl_int err = detail::errHandler(
7429             ::clEnqueueCopyImageToBuffer(
7430                 object_, 
7431                 src(), 
7432                 dst(), 
7433                 src_origin.data(),
7434                 region.data(), 
7435                 dst_offset,
7436                 (events != NULL) ? (cl_uint) events->size() : 0,
7437                 (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,
7438                 (event != NULL) ? &tmp : NULL),
7439             __ENQUEUE_COPY_IMAGE_TO_BUFFER_ERR);
7440
7441         if (event != NULL && err == CL_SUCCESS)
7442             *event = tmp;
7443
7444         return err;
7445     }
7446
7447     cl_int enqueueCopyBufferToImage(
7448         const Buffer& src,
7449         const Image& dst,
7450         size_type src_offset,
7451         const array<size_type, 3>& dst_origin,
7452         const array<size_type, 3>& region,
7453         const vector<Event>* events = NULL,
7454         Event* event = NULL) const
7455     {
7456         cl_event tmp;
7457         cl_int err = detail::errHandler(
7458             ::clEnqueueCopyBufferToImage(
7459                 object_, 
7460                 src(), 
7461                 dst(), 
7462                 src_offset,
7463                 dst_origin.data(), 
7464                 region.data(),
7465                 (events != NULL) ? (cl_uint) events->size() : 0,
7466                 (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,
7467                 (event != NULL) ? &tmp : NULL),
7468             __ENQUEUE_COPY_BUFFER_TO_IMAGE_ERR);
7469
7470         if (event != NULL && err == CL_SUCCESS)
7471             *event = tmp;
7472
7473         return err;
7474     }
7475
7476     void* enqueueMapBuffer(
7477         const Buffer& buffer,
7478         cl_bool blocking,
7479         cl_map_flags flags,
7480         size_type offset,
7481         size_type size,
7482         const vector<Event>* events = NULL,
7483         Event* event = NULL,
7484         cl_int* err = NULL) const
7485     {
7486         cl_event tmp;
7487         cl_int error;
7488         void * result = ::clEnqueueMapBuffer(
7489             object_, buffer(), blocking, flags, offset, size,
7490             (events != NULL) ? (cl_uint) events->size() : 0,
7491             (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,
7492             (event != NULL) ? &tmp : NULL,
7493             &error);
7494
7495         detail::errHandler(error, __ENQUEUE_MAP_BUFFER_ERR);
7496         if (err != NULL) {
7497             *err = error;
7498         }
7499         if (event != NULL && error == CL_SUCCESS)
7500             *event = tmp;
7501
7502         return result;
7503     }
7504
7505     void* enqueueMapImage(
7506         const Image& buffer,
7507         cl_bool blocking,
7508         cl_map_flags flags,
7509         const array<size_type, 3>& origin,
7510         const array<size_type, 3>& region,
7511         size_type * row_pitch,
7512         size_type * slice_pitch,
7513         const vector<Event>* events = NULL,
7514         Event* event = NULL,
7515         cl_int* err = NULL) const
7516     {
7517         cl_event tmp;
7518         cl_int error;
7519         void * result = ::clEnqueueMapImage(
7520             object_, buffer(), blocking, flags,
7521             origin.data(), 
7522             region.data(),
7523             row_pitch, slice_pitch,
7524             (events != NULL) ? (cl_uint) events->size() : 0,
7525             (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,
7526             (event != NULL) ? &tmp : NULL,
7527             &error);
7528
7529         detail::errHandler(error, __ENQUEUE_MAP_IMAGE_ERR);
7530         if (err != NULL) {
7531               *err = error;
7532         }
7533         if (event != NULL && error == CL_SUCCESS)
7534             *event = tmp;
7535         return result;
7536     }
7537
7538 #if CL_HPP_TARGET_OPENCL_VERSION >= 200
7539     /**
7540      * Enqueues a command that will allow the host to update a region of a coarse-grained SVM buffer.
7541      * This variant takes a raw SVM pointer.
7542      */
7543     template<typename T>
7544     cl_int enqueueMapSVM(
7545         T* ptr,
7546         cl_bool blocking,
7547         cl_map_flags flags,
7548         size_type size,
7549         const vector<Event>* events = NULL,
7550         Event* event = NULL) const
7551     {
7552         cl_event tmp;
7553         cl_int err = detail::errHandler(::clEnqueueSVMMap(
7554             object_, blocking, flags, static_cast<void*>(ptr), size,
7555             (events != NULL) ? (cl_uint)events->size() : 0,
7556             (events != NULL && events->size() > 0) ? (cl_event*)&events->front() : NULL,
7557             (event != NULL) ? &tmp : NULL),
7558             __ENQUEUE_MAP_BUFFER_ERR);
7559
7560         if (event != NULL && err == CL_SUCCESS)
7561             *event = tmp;
7562
7563         return err;
7564     }
7565
7566
7567     /**
7568      * Enqueues a command that will allow the host to update a region of a coarse-grained SVM buffer.
7569      * This variant takes a cl::pointer instance.
7570      */
7571     template<typename T, class D>
7572     cl_int enqueueMapSVM(
7573         cl::pointer<T, D> &ptr,
7574         cl_bool blocking,
7575         cl_map_flags flags,
7576         size_type size,
7577         const vector<Event>* events = NULL,
7578         Event* event = NULL) const
7579     {
7580         cl_event tmp;
7581         cl_int err = detail::errHandler(::clEnqueueSVMMap(
7582             object_, blocking, flags, static_cast<void*>(ptr.get()), size,
7583             (events != NULL) ? (cl_uint)events->size() : 0,
7584             (events != NULL && events->size() > 0) ? (cl_event*)&events->front() : NULL,
7585             (event != NULL) ? &tmp : NULL),
7586             __ENQUEUE_MAP_BUFFER_ERR);
7587
7588         if (event != NULL && err == CL_SUCCESS)
7589             *event = tmp;
7590
7591         return err;
7592     }
7593
7594     /**
7595      * Enqueues a command that will allow the host to update a region of a coarse-grained SVM buffer.
7596      * This variant takes a cl::vector instance.
7597      */
7598     template<typename T, class Alloc>
7599     cl_int enqueueMapSVM(
7600         cl::vector<T, Alloc> &container,
7601         cl_bool blocking,
7602         cl_map_flags flags,
7603         const vector<Event>* events = NULL,
7604         Event* event = NULL) const
7605     {
7606         cl_event tmp;
7607         cl_int err = detail::errHandler(::clEnqueueSVMMap(
7608             object_, blocking, flags, static_cast<void*>(container.data()), container.size(),
7609             (events != NULL) ? (cl_uint)events->size() : 0,
7610             (events != NULL && events->size() > 0) ? (cl_event*)&events->front() : NULL,
7611             (event != NULL) ? &tmp : NULL),
7612             __ENQUEUE_MAP_BUFFER_ERR);
7613
7614         if (event != NULL && err == CL_SUCCESS)
7615             *event = tmp;
7616
7617         return err;
7618     }
7619 #endif // #if CL_HPP_TARGET_OPENCL_VERSION >= 200
7620
7621     cl_int enqueueUnmapMemObject(
7622         const Memory& memory,
7623         void* mapped_ptr,
7624         const vector<Event>* events = NULL,
7625         Event* event = NULL) const
7626     {
7627         cl_event tmp;
7628         cl_int err = detail::errHandler(
7629             ::clEnqueueUnmapMemObject(
7630                 object_, memory(), mapped_ptr,
7631                 (events != NULL) ? (cl_uint) events->size() : 0,
7632                 (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,
7633                 (event != NULL) ? &tmp : NULL),
7634             __ENQUEUE_UNMAP_MEM_OBJECT_ERR);
7635
7636         if (event != NULL && err == CL_SUCCESS)
7637             *event = tmp;
7638
7639         return err;
7640     }
7641
7642
7643 #if CL_HPP_TARGET_OPENCL_VERSION >= 200
7644     /**
7645      * Enqueues a command that will release a coarse-grained SVM buffer back to the OpenCL runtime.
7646      * This variant takes a raw SVM pointer.
7647      */
7648     template<typename T>
7649     cl_int enqueueUnmapSVM(
7650         T* ptr,
7651         const vector<Event>* events = NULL,
7652         Event* event = NULL) const
7653     {
7654         cl_event tmp;
7655         cl_int err = detail::errHandler(
7656             ::clEnqueueSVMUnmap(
7657             object_, static_cast<void*>(ptr),
7658             (events != NULL) ? (cl_uint)events->size() : 0,
7659             (events != NULL && events->size() > 0) ? (cl_event*)&events->front() : NULL,
7660             (event != NULL) ? &tmp : NULL),
7661             __ENQUEUE_UNMAP_MEM_OBJECT_ERR);
7662
7663         if (event != NULL && err == CL_SUCCESS)
7664             *event = tmp;
7665
7666         return err;
7667     }
7668
7669     /**
7670      * Enqueues a command that will release a coarse-grained SVM buffer back to the OpenCL runtime.
7671      * This variant takes a cl::pointer instance.
7672      */
7673     template<typename T, class D>
7674     cl_int enqueueUnmapSVM(
7675         cl::pointer<T, D> &ptr,
7676         const vector<Event>* events = NULL,
7677         Event* event = NULL) const
7678     {
7679         cl_event tmp;
7680         cl_int err = detail::errHandler(
7681             ::clEnqueueSVMUnmap(
7682             object_, static_cast<void*>(ptr.get()),
7683             (events != NULL) ? (cl_uint)events->size() : 0,
7684             (events != NULL && events->size() > 0) ? (cl_event*)&events->front() : NULL,
7685             (event != NULL) ? &tmp : NULL),
7686             __ENQUEUE_UNMAP_MEM_OBJECT_ERR);
7687
7688         if (event != NULL && err == CL_SUCCESS)
7689             *event = tmp;
7690
7691         return err;
7692     }
7693
7694     /**
7695      * Enqueues a command that will release a coarse-grained SVM buffer back to the OpenCL runtime.
7696      * This variant takes a cl::vector instance.
7697      */
7698     template<typename T, class Alloc>
7699     cl_int enqueueUnmapSVM(
7700         cl::vector<T, Alloc> &container,
7701         const vector<Event>* events = NULL,
7702         Event* event = NULL) const
7703     {
7704         cl_event tmp;
7705         cl_int err = detail::errHandler(
7706             ::clEnqueueSVMUnmap(
7707             object_, static_cast<void*>(container.data()),
7708             (events != NULL) ? (cl_uint)events->size() : 0,
7709             (events != NULL && events->size() > 0) ? (cl_event*)&events->front() : NULL,
7710             (event != NULL) ? &tmp : NULL),
7711             __ENQUEUE_UNMAP_MEM_OBJECT_ERR);
7712
7713         if (event != NULL && err == CL_SUCCESS)
7714             *event = tmp;
7715
7716         return err;
7717     }
7718 #endif // #if CL_HPP_TARGET_OPENCL_VERSION >= 200
7719
7720 #if CL_HPP_TARGET_OPENCL_VERSION >= 120
7721     /**
7722      * Enqueues a marker command which waits for either a list of events to complete, 
7723      * or all previously enqueued commands to complete.
7724      *
7725      * Enqueues a marker command which waits for either a list of events to complete, 
7726      * or if the list is empty it waits for all commands previously enqueued in command_queue 
7727      * to complete before it completes. This command returns an event which can be waited on, 
7728      * i.e. this event can be waited on to insure that all events either in the event_wait_list 
7729      * or all previously enqueued commands, queued before this command to command_queue, 
7730      * have completed.
7731      */
7732     cl_int enqueueMarkerWithWaitList(
7733         const vector<Event> *events = 0,
7734         Event *event = 0)
7735     {
7736         cl_event tmp;
7737         cl_int err = detail::errHandler(
7738             ::clEnqueueMarkerWithWaitList(
7739                 object_,
7740                 (events != NULL) ? (cl_uint) events->size() : 0,
7741                 (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,
7742                 (event != NULL) ? &tmp : NULL),
7743             __ENQUEUE_MARKER_WAIT_LIST_ERR);
7744
7745         if (event != NULL && err == CL_SUCCESS)
7746             *event = tmp;
7747
7748         return err;
7749     }
7750
7751     /**
7752      * A synchronization point that enqueues a barrier operation.
7753      *
7754      * Enqueues a barrier command which waits for either a list of events to complete, 
7755      * or if the list is empty it waits for all commands previously enqueued in command_queue 
7756      * to complete before it completes. This command blocks command execution, that is, any 
7757      * following commands enqueued after it do not execute until it completes. This command 
7758      * returns an event which can be waited on, i.e. this event can be waited on to insure that 
7759      * all events either in the event_wait_list or all previously enqueued commands, queued 
7760      * before this command to command_queue, have completed.
7761      */
7762     cl_int enqueueBarrierWithWaitList(
7763         const vector<Event> *events = 0,
7764         Event *event = 0)
7765     {
7766         cl_event tmp;
7767         cl_int err = detail::errHandler(
7768             ::clEnqueueBarrierWithWaitList(
7769                 object_,
7770                 (events != NULL) ? (cl_uint) events->size() : 0,
7771                 (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,
7772                 (event != NULL) ? &tmp : NULL),
7773             __ENQUEUE_BARRIER_WAIT_LIST_ERR);
7774
7775         if (event != NULL && err == CL_SUCCESS)
7776             *event = tmp;
7777
7778         return err;
7779     }
7780     
7781     /**
7782      * Enqueues a command to indicate with which device a set of memory objects
7783      * should be associated.
7784      */
7785     cl_int enqueueMigrateMemObjects(
7786         const vector<Memory> &memObjects,
7787         cl_mem_migration_flags flags,
7788         const vector<Event>* events = NULL,
7789         Event* event = NULL
7790         )
7791     {
7792         cl_event tmp;
7793         
7794         vector<cl_mem> localMemObjects(memObjects.size());
7795
7796         for( int i = 0; i < (int)memObjects.size(); ++i ) {
7797             localMemObjects[i] = memObjects[i]();
7798         }
7799
7800
7801         cl_int err = detail::errHandler(
7802             ::clEnqueueMigrateMemObjects(
7803                 object_, 
7804                 (cl_uint)memObjects.size(), 
7805                 localMemObjects.data(),
7806                 flags,
7807                 (events != NULL) ? (cl_uint) events->size() : 0,
7808                 (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,
7809                 (event != NULL) ? &tmp : NULL),
7810             __ENQUEUE_UNMAP_MEM_OBJECT_ERR);
7811
7812         if (event != NULL && err == CL_SUCCESS)
7813             *event = tmp;
7814
7815         return err;
7816     }
7817 #endif // CL_HPP_TARGET_OPENCL_VERSION >= 120
7818
7819     cl_int enqueueNDRangeKernel(
7820         const Kernel& kernel,
7821         const NDRange& offset,
7822         const NDRange& global,
7823         const NDRange& local = NullRange,
7824         const vector<Event>* events = NULL,
7825         Event* event = NULL) const
7826     {
7827         cl_event tmp;
7828         cl_int err = detail::errHandler(
7829             ::clEnqueueNDRangeKernel(
7830                 object_, kernel(), (cl_uint) global.dimensions(),
7831                 offset.dimensions() != 0 ? (const size_type*) offset : NULL,
7832                 (const size_type*) global,
7833                 local.dimensions() != 0 ? (const size_type*) local : NULL,
7834                 (events != NULL) ? (cl_uint) events->size() : 0,
7835                 (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,
7836                 (event != NULL) ? &tmp : NULL),
7837             __ENQUEUE_NDRANGE_KERNEL_ERR);
7838
7839         if (event != NULL && err == CL_SUCCESS)
7840             *event = tmp;
7841
7842         return err;
7843     }
7844
7845 #if defined(CL_USE_DEPRECATED_OPENCL_1_2_APIS)
7846     CL_EXT_PREFIX__VERSION_1_2_DEPRECATED cl_int enqueueTask(
7847         const Kernel& kernel,
7848         const vector<Event>* events = NULL,
7849         Event* event = NULL) CL_EXT_SUFFIX__VERSION_1_2_DEPRECATED const
7850     {
7851         cl_event tmp;
7852         cl_int err = detail::errHandler(
7853             ::clEnqueueTask(
7854                 object_, kernel(),
7855                 (events != NULL) ? (cl_uint) events->size() : 0,
7856                 (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,
7857                 (event != NULL) ? &tmp : NULL),
7858             __ENQUEUE_TASK_ERR);
7859
7860         if (event != NULL && err == CL_SUCCESS)
7861             *event = tmp;
7862
7863         return err;
7864     }
7865 #endif // #if defined(CL_USE_DEPRECATED_OPENCL_1_2_APIS)
7866
7867     cl_int enqueueNativeKernel(
7868         void (CL_CALLBACK *userFptr)(void *),
7869         std::pair<void*, size_type> args,
7870         const vector<Memory>* mem_objects = NULL,
7871         const vector<const void*>* mem_locs = NULL,
7872         const vector<Event>* events = NULL,
7873         Event* event = NULL) const
7874     {
7875         size_type elements = 0;
7876         if (mem_objects != NULL) {
7877             elements = mem_objects->size();
7878         }
7879         vector<cl_mem> mems(elements);
7880         for (unsigned int i = 0; i < elements; i++) {
7881             mems[i] = ((*mem_objects)[i])();
7882         }
7883         
7884         cl_event tmp;
7885         cl_int err = detail::errHandler(
7886             ::clEnqueueNativeKernel(
7887                 object_, userFptr, args.first, args.second,
7888                 (mem_objects != NULL) ? (cl_uint) mem_objects->size() : 0,
7889                 mems.data(),
7890                 (mem_locs != NULL && mem_locs->size() > 0) ? (const void **) &mem_locs->front() : NULL,
7891                 (events != NULL) ? (cl_uint) events->size() : 0,
7892                 (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,
7893                 (event != NULL) ? &tmp : NULL),
7894             __ENQUEUE_NATIVE_KERNEL);
7895
7896         if (event != NULL && err == CL_SUCCESS)
7897             *event = tmp;
7898
7899         return err;
7900     }
7901
7902 /**
7903  * Deprecated APIs for 1.2
7904  */
7905 #if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS)
7906     CL_EXT_PREFIX__VERSION_1_1_DEPRECATED 
7907     cl_int enqueueMarker(Event* event = NULL) const CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED
7908     {
7909         cl_event tmp;
7910         cl_int err = detail::errHandler(
7911             ::clEnqueueMarker(
7912                 object_, 
7913                 (event != NULL) ? &tmp : NULL),
7914             __ENQUEUE_MARKER_ERR);
7915
7916         if (event != NULL && err == CL_SUCCESS)
7917             *event = tmp;
7918
7919         return err;
7920     }
7921
7922     CL_EXT_PREFIX__VERSION_1_1_DEPRECATED
7923     cl_int enqueueWaitForEvents(const vector<Event>& events) const CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED
7924     {
7925         return detail::errHandler(
7926             ::clEnqueueWaitForEvents(
7927                 object_,
7928                 (cl_uint) events.size(),
7929                 events.size() > 0 ? (const cl_event*) &events.front() : NULL),
7930             __ENQUEUE_WAIT_FOR_EVENTS_ERR);
7931     }
7932 #endif // defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS)
7933
7934     cl_int enqueueAcquireGLObjects(
7935          const vector<Memory>* mem_objects = NULL,
7936          const vector<Event>* events = NULL,
7937          Event* event = NULL) const
7938      {
7939         cl_event tmp;
7940         cl_int err = detail::errHandler(
7941              ::clEnqueueAcquireGLObjects(
7942                  object_,
7943                  (mem_objects != NULL) ? (cl_uint) mem_objects->size() : 0,
7944                  (mem_objects != NULL && mem_objects->size() > 0) ? (const cl_mem *) &mem_objects->front(): NULL,
7945                  (events != NULL) ? (cl_uint) events->size() : 0,
7946                  (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,
7947                  (event != NULL) ? &tmp : NULL),
7948              __ENQUEUE_ACQUIRE_GL_ERR);
7949
7950         if (event != NULL && err == CL_SUCCESS)
7951             *event = tmp;
7952
7953         return err;
7954      }
7955
7956     cl_int enqueueReleaseGLObjects(
7957          const vector<Memory>* mem_objects = NULL,
7958          const vector<Event>* events = NULL,
7959          Event* event = NULL) const
7960      {
7961         cl_event tmp;
7962         cl_int err = detail::errHandler(
7963              ::clEnqueueReleaseGLObjects(
7964                  object_,
7965                  (mem_objects != NULL) ? (cl_uint) mem_objects->size() : 0,
7966                  (mem_objects != NULL && mem_objects->size() > 0) ? (const cl_mem *) &mem_objects->front(): NULL,
7967                  (events != NULL) ? (cl_uint) events->size() : 0,
7968                  (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,
7969                  (event != NULL) ? &tmp : NULL),
7970              __ENQUEUE_RELEASE_GL_ERR);
7971
7972         if (event != NULL && err == CL_SUCCESS)
7973             *event = tmp;
7974
7975         return err;
7976      }
7977
7978 #if defined (CL_HPP_USE_DX_INTEROP)
7979 typedef CL_API_ENTRY cl_int (CL_API_CALL *PFN_clEnqueueAcquireD3D10ObjectsKHR)(
7980     cl_command_queue command_queue, cl_uint num_objects,
7981     const cl_mem* mem_objects, cl_uint num_events_in_wait_list,
7982     const cl_event* event_wait_list, cl_event* event);
7983 typedef CL_API_ENTRY cl_int (CL_API_CALL *PFN_clEnqueueReleaseD3D10ObjectsKHR)(
7984     cl_command_queue command_queue, cl_uint num_objects,
7985     const cl_mem* mem_objects,  cl_uint num_events_in_wait_list,
7986     const cl_event* event_wait_list, cl_event* event);
7987
7988     cl_int enqueueAcquireD3D10Objects(
7989          const vector<Memory>* mem_objects = NULL,
7990          const vector<Event>* events = NULL,
7991          Event* event = NULL) const
7992     {
7993         static PFN_clEnqueueAcquireD3D10ObjectsKHR pfn_clEnqueueAcquireD3D10ObjectsKHR = NULL;
7994 #if CL_HPP_TARGET_OPENCL_VERSION >= 120
7995         cl_context context = getInfo<CL_QUEUE_CONTEXT>();
7996         cl::Device device(getInfo<CL_QUEUE_DEVICE>());
7997         cl_platform_id platform = device.getInfo<CL_DEVICE_PLATFORM>();
7998         CL_HPP_INIT_CL_EXT_FCN_PTR_PLATFORM_(platform, clEnqueueAcquireD3D10ObjectsKHR);
7999 #endif
8000 #if CL_HPP_TARGET_OPENCL_VERSION >= 110
8001         CL_HPP_INIT_CL_EXT_FCN_PTR_(clEnqueueAcquireD3D10ObjectsKHR);
8002 #endif
8003         
8004         cl_event tmp;
8005         cl_int err = detail::errHandler(
8006              pfn_clEnqueueAcquireD3D10ObjectsKHR(
8007                  object_,
8008                  (mem_objects != NULL) ? (cl_uint) mem_objects->size() : 0,
8009                  (mem_objects != NULL && mem_objects->size() > 0) ? (const cl_mem *) &mem_objects->front(): NULL,
8010                  (events != NULL) ? (cl_uint) events->size() : 0,
8011                  (events != NULL) ? (cl_event*) &events->front() : NULL,
8012                  (event != NULL) ? &tmp : NULL),
8013              __ENQUEUE_ACQUIRE_GL_ERR);
8014
8015         if (event != NULL && err == CL_SUCCESS)
8016             *event = tmp;
8017
8018         return err;
8019      }
8020
8021     cl_int enqueueReleaseD3D10Objects(
8022          const vector<Memory>* mem_objects = NULL,
8023          const vector<Event>* events = NULL,
8024          Event* event = NULL) const
8025     {
8026         static PFN_clEnqueueReleaseD3D10ObjectsKHR pfn_clEnqueueReleaseD3D10ObjectsKHR = NULL;
8027 #if CL_HPP_TARGET_OPENCL_VERSION >= 120
8028         cl_context context = getInfo<CL_QUEUE_CONTEXT>();
8029         cl::Device device(getInfo<CL_QUEUE_DEVICE>());
8030         cl_platform_id platform = device.getInfo<CL_DEVICE_PLATFORM>();
8031         CL_HPP_INIT_CL_EXT_FCN_PTR_PLATFORM_(platform, clEnqueueReleaseD3D10ObjectsKHR);
8032 #endif // CL_HPP_TARGET_OPENCL_VERSION >= 120
8033 #if CL_HPP_TARGET_OPENCL_VERSION >= 110
8034         CL_HPP_INIT_CL_EXT_FCN_PTR_(clEnqueueReleaseD3D10ObjectsKHR);
8035 #endif // CL_HPP_TARGET_OPENCL_VERSION >= 110
8036
8037         cl_event tmp;
8038         cl_int err = detail::errHandler(
8039             pfn_clEnqueueReleaseD3D10ObjectsKHR(
8040                 object_,
8041                 (mem_objects != NULL) ? (cl_uint) mem_objects->size() : 0,
8042                 (mem_objects != NULL && mem_objects->size() > 0) ? (const cl_mem *) &mem_objects->front(): NULL,
8043                 (events != NULL) ? (cl_uint) events->size() : 0,
8044                 (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,
8045                 (event != NULL) ? &tmp : NULL),
8046             __ENQUEUE_RELEASE_GL_ERR);
8047
8048         if (event != NULL && err == CL_SUCCESS)
8049             *event = tmp;
8050
8051         return err;
8052     }
8053 #endif
8054
8055 /**
8056  * Deprecated APIs for 1.2
8057  */
8058 #if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS)
8059     CL_EXT_PREFIX__VERSION_1_1_DEPRECATED
8060     cl_int enqueueBarrier() const CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED
8061     {
8062         return detail::errHandler(
8063             ::clEnqueueBarrier(object_),
8064             __ENQUEUE_BARRIER_ERR);
8065     }
8066 #endif // CL_USE_DEPRECATED_OPENCL_1_1_APIS
8067
8068     cl_int flush() const
8069     {
8070         return detail::errHandler(::clFlush(object_), __FLUSH_ERR);
8071     }
8072
8073     cl_int finish() const
8074     {
8075         return detail::errHandler(::clFinish(object_), __FINISH_ERR);
8076     }
8077 }; // CommandQueue
8078
8079 CL_HPP_DEFINE_STATIC_MEMBER_ std::once_flag CommandQueue::default_initialized_;
8080 CL_HPP_DEFINE_STATIC_MEMBER_ CommandQueue CommandQueue::default_;
8081 CL_HPP_DEFINE_STATIC_MEMBER_ cl_int CommandQueue::default_error_ = CL_SUCCESS;
8082
8083
8084 #if CL_HPP_TARGET_OPENCL_VERSION >= 200
8085 enum class DeviceQueueProperties : cl_command_queue_properties
8086 {
8087     None = 0,
8088     Profiling = CL_QUEUE_PROFILING_ENABLE,
8089 };
8090
8091 inline DeviceQueueProperties operator|(DeviceQueueProperties lhs, DeviceQueueProperties rhs)
8092 {
8093     return static_cast<DeviceQueueProperties>(static_cast<cl_command_queue_properties>(lhs) | static_cast<cl_command_queue_properties>(rhs));
8094 }
8095
8096 /*! \class DeviceCommandQueue
8097  * \brief DeviceCommandQueue interface for device cl_command_queues.
8098  */
8099 class DeviceCommandQueue : public detail::Wrapper<cl_command_queue>
8100 {
8101 public:
8102
8103     /*!
8104      * Trivial empty constructor to create a null queue.
8105      */
8106     DeviceCommandQueue() { }
8107
8108     /*!
8109      * Default construct device command queue on default context and device
8110      */
8111     DeviceCommandQueue(DeviceQueueProperties properties, cl_int* err = NULL)
8112     {
8113         cl_int error;
8114         cl::Context context = cl::Context::getDefault();
8115         cl::Device device = cl::Device::getDefault();
8116
8117         cl_command_queue_properties mergedProperties =
8118             CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE | CL_QUEUE_ON_DEVICE | static_cast<cl_command_queue_properties>(properties);
8119
8120         cl_queue_properties queue_properties[] = {
8121             CL_QUEUE_PROPERTIES, mergedProperties, 0 };
8122         object_ = ::clCreateCommandQueueWithProperties(
8123             context(), device(), queue_properties, &error);
8124
8125         detail::errHandler(error, __CREATE_COMMAND_QUEUE_WITH_PROPERTIES_ERR);
8126         if (err != NULL) {
8127             *err = error;
8128         }
8129     }
8130
8131     /*!
8132      * Create a device command queue for a specified device in the passed context.
8133      */
8134     DeviceCommandQueue(
8135         const Context& context,
8136         const Device& device,
8137         DeviceQueueProperties properties = DeviceQueueProperties::None,
8138         cl_int* err = NULL)
8139     {
8140         cl_int error;
8141
8142         cl_command_queue_properties mergedProperties =
8143             CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE | CL_QUEUE_ON_DEVICE | static_cast<cl_command_queue_properties>(properties);
8144         cl_queue_properties queue_properties[] = {
8145             CL_QUEUE_PROPERTIES, mergedProperties, 0 };
8146         object_ = ::clCreateCommandQueueWithProperties(
8147             context(), device(), queue_properties, &error);
8148
8149         detail::errHandler(error, __CREATE_COMMAND_QUEUE_WITH_PROPERTIES_ERR);
8150         if (err != NULL) {
8151             *err = error;
8152         }
8153     }
8154
8155     /*!
8156      * Create a device command queue for a specified device in the passed context.
8157      */
8158     DeviceCommandQueue(
8159         const Context& context,
8160         const Device& device,
8161         cl_uint queueSize,
8162         DeviceQueueProperties properties = DeviceQueueProperties::None,
8163         cl_int* err = NULL)
8164     {
8165         cl_int error;
8166
8167         cl_command_queue_properties mergedProperties =
8168             CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE | CL_QUEUE_ON_DEVICE | static_cast<cl_command_queue_properties>(properties);
8169         cl_queue_properties queue_properties[] = {
8170             CL_QUEUE_PROPERTIES, mergedProperties,
8171             CL_QUEUE_SIZE, queueSize, 
8172             0 };
8173         object_ = ::clCreateCommandQueueWithProperties(
8174             context(), device(), queue_properties, &error);
8175
8176         detail::errHandler(error, __CREATE_COMMAND_QUEUE_WITH_PROPERTIES_ERR);
8177         if (err != NULL) {
8178             *err = error;
8179         }
8180     }
8181
8182     /*! \brief Constructor from cl_command_queue - takes ownership.
8183     *
8184     * \param retainObject will cause the constructor to retain its cl object.
8185     *                     Defaults to false to maintain compatibility with
8186     *                     earlier versions.
8187     */
8188     explicit DeviceCommandQueue(const cl_command_queue& commandQueue, bool retainObject = false) :
8189         detail::Wrapper<cl_type>(commandQueue, retainObject) { }
8190
8191     DeviceCommandQueue& operator = (const cl_command_queue& rhs)
8192     {
8193         detail::Wrapper<cl_type>::operator=(rhs);
8194         return *this;
8195     }
8196
8197     /*! \brief Copy constructor to forward copy to the superclass correctly.
8198      * Required for MSVC.
8199      */
8200     DeviceCommandQueue(const DeviceCommandQueue& queue) : detail::Wrapper<cl_type>(queue) {}
8201
8202     /*! \brief Copy assignment to forward copy to the superclass correctly.
8203      * Required for MSVC.
8204      */
8205     DeviceCommandQueue& operator = (const DeviceCommandQueue &queue)
8206     {
8207         detail::Wrapper<cl_type>::operator=(queue);
8208         return *this;
8209     }
8210
8211     /*! \brief Move constructor to forward move to the superclass correctly.
8212      * Required for MSVC.
8213      */
8214     DeviceCommandQueue(DeviceCommandQueue&& queue) CL_HPP_NOEXCEPT_ : detail::Wrapper<cl_type>(std::move(queue)) {}
8215
8216     /*! \brief Move assignment to forward move to the superclass correctly.
8217      * Required for MSVC.
8218      */
8219     DeviceCommandQueue& operator = (DeviceCommandQueue &&queue)
8220     {
8221         detail::Wrapper<cl_type>::operator=(std::move(queue));
8222         return *this;
8223     }
8224
8225     template <typename T>
8226     cl_int getInfo(cl_command_queue_info name, T* param) const
8227     {
8228         return detail::errHandler(
8229             detail::getInfo(
8230             &::clGetCommandQueueInfo, object_, name, param),
8231             __GET_COMMAND_QUEUE_INFO_ERR);
8232     }
8233
8234     template <cl_int name> typename
8235         detail::param_traits<detail::cl_command_queue_info, name>::param_type
8236         getInfo(cl_int* err = NULL) const
8237     {
8238         typename detail::param_traits<
8239             detail::cl_command_queue_info, name>::param_type param;
8240         cl_int result = getInfo(name, &param);
8241         if (err != NULL) {
8242             *err = result;
8243         }
8244         return param;
8245     }
8246
8247     /*!
8248     * Create a new default device command queue for the default device,
8249     * in the default context and of the default size.
8250     * If there is already a default queue for the specified device this
8251     * function will return the pre-existing queue.
8252     */
8253     static DeviceCommandQueue makeDefault(
8254         cl_int *err = nullptr)
8255     {
8256         cl_int error;
8257         cl::Context context = cl::Context::getDefault();
8258         cl::Device device = cl::Device::getDefault();
8259
8260         cl_command_queue_properties properties =
8261             CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE | CL_QUEUE_ON_DEVICE | CL_QUEUE_ON_DEVICE_DEFAULT;
8262         cl_queue_properties queue_properties[] = {
8263             CL_QUEUE_PROPERTIES, properties,
8264             0 };
8265         DeviceCommandQueue deviceQueue(
8266             ::clCreateCommandQueueWithProperties(
8267             context(), device(), queue_properties, &error));
8268
8269         detail::errHandler(error, __CREATE_COMMAND_QUEUE_WITH_PROPERTIES_ERR);
8270         if (err != NULL) {
8271             *err = error;
8272         }
8273
8274         return deviceQueue;
8275     }
8276
8277     /*!
8278     * Create a new default device command queue for the specified device
8279     * and of the default size.
8280     * If there is already a default queue for the specified device this
8281     * function will return the pre-existing queue.
8282     */
8283     static DeviceCommandQueue makeDefault(
8284         const Context &context, const Device &device, cl_int *err = nullptr)
8285     {
8286         cl_int error;
8287
8288         cl_command_queue_properties properties =
8289             CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE | CL_QUEUE_ON_DEVICE | CL_QUEUE_ON_DEVICE_DEFAULT;
8290         cl_queue_properties queue_properties[] = {
8291             CL_QUEUE_PROPERTIES, properties,
8292             0 };
8293         DeviceCommandQueue deviceQueue(
8294             ::clCreateCommandQueueWithProperties(
8295             context(), device(), queue_properties, &error));
8296
8297         detail::errHandler(error, __CREATE_COMMAND_QUEUE_WITH_PROPERTIES_ERR);
8298         if (err != NULL) {
8299             *err = error;
8300         }
8301
8302         return deviceQueue;
8303     }
8304
8305     /*!
8306      * Create a new default device command queue for the specified device 
8307      * and of the requested size in bytes.
8308      * If there is already a default queue for the specified device this
8309      * function will return the pre-existing queue.
8310      */
8311     static DeviceCommandQueue makeDefault(
8312         const Context &context, const Device &device, cl_uint queueSize, cl_int *err = nullptr)
8313     {
8314         cl_int error;
8315
8316         cl_command_queue_properties properties =
8317             CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE | CL_QUEUE_ON_DEVICE | CL_QUEUE_ON_DEVICE_DEFAULT;
8318         cl_queue_properties queue_properties[] = {
8319             CL_QUEUE_PROPERTIES, properties,
8320             CL_QUEUE_SIZE, queueSize,
8321             0 };
8322         DeviceCommandQueue deviceQueue(
8323             ::clCreateCommandQueueWithProperties(
8324                 context(), device(), queue_properties, &error));
8325
8326         detail::errHandler(error, __CREATE_COMMAND_QUEUE_WITH_PROPERTIES_ERR);
8327         if (err != NULL) {
8328             *err = error;
8329         }
8330
8331         return deviceQueue;
8332     }
8333 }; // DeviceCommandQueue
8334
8335 namespace detail
8336 {
8337     // Specialization for device command queue
8338     template <>
8339     struct KernelArgumentHandler<cl::DeviceCommandQueue, void>
8340     {
8341         static size_type size(const cl::DeviceCommandQueue&) { return sizeof(cl_command_queue); }
8342         static const cl_command_queue* ptr(const cl::DeviceCommandQueue& value) { return &(value()); }
8343     };
8344 } // namespace detail
8345
8346 #endif // #if CL_HPP_TARGET_OPENCL_VERSION >= 200
8347
8348
8349 template< typename IteratorType >
8350 Buffer::Buffer(
8351     const Context &context,
8352     IteratorType startIterator,
8353     IteratorType endIterator,
8354     bool readOnly,
8355     bool useHostPtr,
8356     cl_int* err)
8357 {
8358     typedef typename std::iterator_traits<IteratorType>::value_type DataType;
8359     cl_int error;
8360
8361     cl_mem_flags flags = 0;
8362     if( readOnly ) {
8363         flags |= CL_MEM_READ_ONLY;
8364     }
8365     else {
8366         flags |= CL_MEM_READ_WRITE;
8367     }
8368     if( useHostPtr ) {
8369         flags |= CL_MEM_USE_HOST_PTR;
8370     }
8371     
8372     size_type size = sizeof(DataType)*(endIterator - startIterator);
8373
8374     if( useHostPtr ) {
8375         object_ = ::clCreateBuffer(context(), flags, size, static_cast<DataType*>(&*startIterator), &error);
8376     } else {
8377         object_ = ::clCreateBuffer(context(), flags, size, 0, &error);
8378     }
8379
8380     detail::errHandler(error, __CREATE_BUFFER_ERR);
8381     if (err != NULL) {
8382         *err = error;
8383     }
8384
8385     if( !useHostPtr ) {
8386         CommandQueue queue(context, 0, &error);
8387         detail::errHandler(error, __CREATE_BUFFER_ERR);
8388         if (err != NULL) {
8389             *err = error;
8390         }
8391
8392         error = cl::copy(queue, startIterator, endIterator, *this);
8393         detail::errHandler(error, __CREATE_BUFFER_ERR);
8394         if (err != NULL) {
8395             *err = error;
8396         }
8397     }
8398 }
8399
8400 template< typename IteratorType >
8401 Buffer::Buffer(
8402     const CommandQueue &queue,
8403     IteratorType startIterator,
8404     IteratorType endIterator,
8405     bool readOnly,
8406     bool useHostPtr,
8407     cl_int* err)
8408 {
8409     typedef typename std::iterator_traits<IteratorType>::value_type DataType;
8410     cl_int error;
8411
8412     cl_mem_flags flags = 0;
8413     if (readOnly) {
8414         flags |= CL_MEM_READ_ONLY;
8415     }
8416     else {
8417         flags |= CL_MEM_READ_WRITE;
8418     }
8419     if (useHostPtr) {
8420         flags |= CL_MEM_USE_HOST_PTR;
8421     }
8422
8423     size_type size = sizeof(DataType)*(endIterator - startIterator);
8424
8425     Context context = queue.getInfo<CL_QUEUE_CONTEXT>();
8426
8427     if (useHostPtr) {
8428         object_ = ::clCreateBuffer(context(), flags, size, static_cast<DataType*>(&*startIterator), &error);
8429     }
8430     else {
8431         object_ = ::clCreateBuffer(context(), flags, size, 0, &error);
8432     }
8433
8434     detail::errHandler(error, __CREATE_BUFFER_ERR);
8435     if (err != NULL) {
8436         *err = error;
8437     }
8438
8439     if (!useHostPtr) {
8440         error = cl::copy(queue, startIterator, endIterator, *this);
8441         detail::errHandler(error, __CREATE_BUFFER_ERR);
8442         if (err != NULL) {
8443             *err = error;
8444         }
8445     }
8446 }
8447
8448 inline cl_int enqueueReadBuffer(
8449     const Buffer& buffer,
8450     cl_bool blocking,
8451     size_type offset,
8452     size_type size,
8453     void* ptr,
8454     const vector<Event>* events = NULL,
8455     Event* event = NULL)
8456 {
8457     cl_int error;
8458     CommandQueue queue = CommandQueue::getDefault(&error);
8459
8460     if (error != CL_SUCCESS) {
8461         return error;
8462     }
8463
8464     return queue.enqueueReadBuffer(buffer, blocking, offset, size, ptr, events, event);
8465 }
8466
8467 inline cl_int enqueueWriteBuffer(
8468         const Buffer& buffer,
8469         cl_bool blocking,
8470         size_type offset,
8471         size_type size,
8472         const void* ptr,
8473         const vector<Event>* events = NULL,
8474         Event* event = NULL)
8475 {
8476     cl_int error;
8477     CommandQueue queue = CommandQueue::getDefault(&error);
8478
8479     if (error != CL_SUCCESS) {
8480         return error;
8481     }
8482
8483     return queue.enqueueWriteBuffer(buffer, blocking, offset, size, ptr, events, event);
8484 }
8485
8486 inline void* enqueueMapBuffer(
8487         const Buffer& buffer,
8488         cl_bool blocking,
8489         cl_map_flags flags,
8490         size_type offset,
8491         size_type size,
8492         const vector<Event>* events = NULL,
8493         Event* event = NULL,
8494         cl_int* err = NULL)
8495 {
8496     cl_int error;
8497     CommandQueue queue = CommandQueue::getDefault(&error);
8498     detail::errHandler(error, __ENQUEUE_MAP_BUFFER_ERR);
8499     if (err != NULL) {
8500         *err = error;
8501     }
8502
8503     void * result = ::clEnqueueMapBuffer(
8504             queue(), buffer(), blocking, flags, offset, size,
8505             (events != NULL) ? (cl_uint) events->size() : 0,
8506             (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,
8507             (cl_event*) event,
8508             &error);
8509
8510     detail::errHandler(error, __ENQUEUE_MAP_BUFFER_ERR);
8511     if (err != NULL) {
8512         *err = error;
8513     }
8514     return result;
8515 }
8516
8517
8518 #if CL_HPP_TARGET_OPENCL_VERSION >= 200
8519 /**
8520  * Enqueues to the default queue a command that will allow the host to
8521  * update a region of a coarse-grained SVM buffer.
8522  * This variant takes a raw SVM pointer.
8523  */
8524 template<typename T>
8525 inline cl_int enqueueMapSVM(
8526     T* ptr,
8527     cl_bool blocking,
8528     cl_map_flags flags,
8529     size_type size,
8530     const vector<Event>* events,
8531     Event* event)
8532 {
8533     cl_int error;
8534     CommandQueue queue = CommandQueue::getDefault(&error);
8535     if (error != CL_SUCCESS) {
8536         return detail::errHandler(error, __ENQUEUE_MAP_BUFFER_ERR);
8537     }
8538
8539     return queue.enqueueMapSVM(
8540         ptr, blocking, flags, size, events, event);
8541 }
8542
8543 /**
8544  * Enqueues to the default queue a command that will allow the host to 
8545  * update a region of a coarse-grained SVM buffer.
8546  * This variant takes a cl::pointer instance.
8547  */
8548 template<typename T, class D>
8549 inline cl_int enqueueMapSVM(
8550     cl::pointer<T, D> ptr,
8551     cl_bool blocking,
8552     cl_map_flags flags,
8553     size_type size,
8554     const vector<Event>* events = NULL,
8555     Event* event = NULL)
8556 {
8557     cl_int error;
8558     CommandQueue queue = CommandQueue::getDefault(&error);
8559     if (error != CL_SUCCESS) {
8560         return detail::errHandler(error, __ENQUEUE_MAP_BUFFER_ERR);
8561     }
8562
8563     return queue.enqueueMapSVM(
8564         ptr, blocking, flags, size, events, event);
8565 }
8566
8567 /**
8568  * Enqueues to the default queue a command that will allow the host to
8569  * update a region of a coarse-grained SVM buffer.
8570  * This variant takes a cl::vector instance.
8571  */
8572 template<typename T, class Alloc>
8573 inline cl_int enqueueMapSVM(
8574     cl::vector<T, Alloc> container,
8575     cl_bool blocking,
8576     cl_map_flags flags,
8577     const vector<Event>* events = NULL,
8578     Event* event = NULL)
8579 {
8580     cl_int error;
8581     CommandQueue queue = CommandQueue::getDefault(&error);
8582     if (error != CL_SUCCESS) {
8583         return detail::errHandler(error, __ENQUEUE_MAP_BUFFER_ERR);
8584     }
8585
8586     return queue.enqueueMapSVM(
8587         container, blocking, flags, events, event);
8588 }
8589
8590 #endif // #if CL_HPP_TARGET_OPENCL_VERSION >= 200
8591
8592 inline cl_int enqueueUnmapMemObject(
8593     const Memory& memory,
8594     void* mapped_ptr,
8595     const vector<Event>* events = NULL,
8596     Event* event = NULL)
8597 {
8598     cl_int error;
8599     CommandQueue queue = CommandQueue::getDefault(&error);
8600     detail::errHandler(error, __ENQUEUE_MAP_BUFFER_ERR);
8601     if (error != CL_SUCCESS) {
8602         return error;
8603     }
8604
8605     cl_event tmp;
8606     cl_int err = detail::errHandler(
8607         ::clEnqueueUnmapMemObject(
8608         queue(), memory(), mapped_ptr,
8609         (events != NULL) ? (cl_uint)events->size() : 0,
8610         (events != NULL && events->size() > 0) ? (cl_event*)&events->front() : NULL,
8611         (event != NULL) ? &tmp : NULL),
8612         __ENQUEUE_UNMAP_MEM_OBJECT_ERR);
8613
8614     if (event != NULL && err == CL_SUCCESS)
8615         *event = tmp;
8616
8617     return err;
8618 }
8619
8620 #if CL_HPP_TARGET_OPENCL_VERSION >= 200
8621 /**
8622  * Enqueues to the default queue a command that will release a coarse-grained 
8623  * SVM buffer back to the OpenCL runtime.
8624  * This variant takes a raw SVM pointer.
8625  */
8626 template<typename T>
8627 inline cl_int enqueueUnmapSVM(
8628     T* ptr,
8629     const vector<Event>* events = NULL,
8630     Event* event = NULL)
8631 {
8632     cl_int error;
8633     CommandQueue queue = CommandQueue::getDefault(&error);
8634     if (error != CL_SUCCESS) {
8635         return detail::errHandler(error, __ENQUEUE_UNMAP_MEM_OBJECT_ERR);
8636     }
8637
8638     return detail::errHandler(queue.enqueueUnmapSVM(ptr, events, event), 
8639         __ENQUEUE_UNMAP_MEM_OBJECT_ERR);
8640
8641 }
8642
8643 /**
8644  * Enqueues to the default queue a command that will release a coarse-grained 
8645  * SVM buffer back to the OpenCL runtime.
8646  * This variant takes a cl::pointer instance.
8647  */
8648 template<typename T, class D>
8649 inline cl_int enqueueUnmapSVM(
8650     cl::pointer<T, D> &ptr,
8651     const vector<Event>* events = NULL,
8652     Event* event = NULL)
8653 {
8654     cl_int error;
8655     CommandQueue queue = CommandQueue::getDefault(&error);
8656     if (error != CL_SUCCESS) {
8657         return detail::errHandler(error, __ENQUEUE_UNMAP_MEM_OBJECT_ERR);
8658     }
8659
8660     return detail::errHandler(queue.enqueueUnmapSVM(ptr, events, event),
8661         __ENQUEUE_UNMAP_MEM_OBJECT_ERR);
8662 }
8663
8664 /**
8665  * Enqueues to the default queue a command that will release a coarse-grained 
8666  * SVM buffer back to the OpenCL runtime.
8667  * This variant takes a cl::vector instance.
8668  */
8669 template<typename T, class Alloc>
8670 inline cl_int enqueueUnmapSVM(
8671     cl::vector<T, Alloc> &container,
8672     const vector<Event>* events = NULL,
8673     Event* event = NULL)
8674 {
8675     cl_int error;
8676     CommandQueue queue = CommandQueue::getDefault(&error);
8677     if (error != CL_SUCCESS) {
8678         return detail::errHandler(error, __ENQUEUE_UNMAP_MEM_OBJECT_ERR);
8679     }
8680
8681     return detail::errHandler(queue.enqueueUnmapSVM(container, events, event),
8682         __ENQUEUE_UNMAP_MEM_OBJECT_ERR);
8683 }
8684
8685 #endif // #if CL_HPP_TARGET_OPENCL_VERSION >= 200
8686
8687 inline cl_int enqueueCopyBuffer(
8688         const Buffer& src,
8689         const Buffer& dst,
8690         size_type src_offset,
8691         size_type dst_offset,
8692         size_type size,
8693         const vector<Event>* events = NULL,
8694         Event* event = NULL)
8695 {
8696     cl_int error;
8697     CommandQueue queue = CommandQueue::getDefault(&error);
8698
8699     if (error != CL_SUCCESS) {
8700         return error;
8701     }
8702
8703     return queue.enqueueCopyBuffer(src, dst, src_offset, dst_offset, size, events, event);
8704 }
8705
8706 /**
8707  * Blocking copy operation between iterators and a buffer.
8708  * Host to Device.
8709  * Uses default command queue.
8710  */
8711 template< typename IteratorType >
8712 inline cl_int copy( IteratorType startIterator, IteratorType endIterator, cl::Buffer &buffer )
8713 {
8714     cl_int error;
8715     CommandQueue queue = CommandQueue::getDefault(&error);
8716     if (error != CL_SUCCESS)
8717         return error;
8718
8719     return cl::copy(queue, startIterator, endIterator, buffer);
8720 }
8721
8722 /**
8723  * Blocking copy operation between iterators and a buffer.
8724  * Device to Host.
8725  * Uses default command queue.
8726  */
8727 template< typename IteratorType >
8728 inline cl_int copy( const cl::Buffer &buffer, IteratorType startIterator, IteratorType endIterator )
8729 {
8730     cl_int error;
8731     CommandQueue queue = CommandQueue::getDefault(&error);
8732     if (error != CL_SUCCESS)
8733         return error;
8734
8735     return cl::copy(queue, buffer, startIterator, endIterator);
8736 }
8737
8738 /**
8739  * Blocking copy operation between iterators and a buffer.
8740  * Host to Device.
8741  * Uses specified queue.
8742  */
8743 template< typename IteratorType >
8744 inline cl_int copy( const CommandQueue &queue, IteratorType startIterator, IteratorType endIterator, cl::Buffer &buffer )
8745 {
8746     typedef typename std::iterator_traits<IteratorType>::value_type DataType;
8747     cl_int error;
8748     
8749     size_type length = endIterator-startIterator;
8750     size_type byteLength = length*sizeof(DataType);
8751
8752     DataType *pointer = 
8753         static_cast<DataType*>(queue.enqueueMapBuffer(buffer, CL_TRUE, CL_MAP_WRITE, 0, byteLength, 0, 0, &error));
8754     // if exceptions enabled, enqueueMapBuffer will throw
8755     if( error != CL_SUCCESS ) {
8756         return error;
8757     }
8758 #if defined(_MSC_VER)
8759     std::copy(
8760         startIterator, 
8761         endIterator, 
8762         stdext::checked_array_iterator<DataType*>(
8763             pointer, length));
8764 #else
8765     std::copy(startIterator, endIterator, pointer);
8766 #endif
8767     Event endEvent;
8768     error = queue.enqueueUnmapMemObject(buffer, pointer, 0, &endEvent);
8769     // if exceptions enabled, enqueueUnmapMemObject will throw
8770     if( error != CL_SUCCESS ) { 
8771         return error;
8772     }
8773     endEvent.wait();
8774     return CL_SUCCESS;
8775 }
8776
8777 /**
8778  * Blocking copy operation between iterators and a buffer.
8779  * Device to Host.
8780  * Uses specified queue.
8781  */
8782 template< typename IteratorType >
8783 inline cl_int copy( const CommandQueue &queue, const cl::Buffer &buffer, IteratorType startIterator, IteratorType endIterator )
8784 {
8785     typedef typename std::iterator_traits<IteratorType>::value_type DataType;
8786     cl_int error;
8787         
8788     size_type length = endIterator-startIterator;
8789     size_type byteLength = length*sizeof(DataType);
8790
8791     DataType *pointer = 
8792         static_cast<DataType*>(queue.enqueueMapBuffer(buffer, CL_TRUE, CL_MAP_READ, 0, byteLength, 0, 0, &error));
8793     // if exceptions enabled, enqueueMapBuffer will throw
8794     if( error != CL_SUCCESS ) {
8795         return error;
8796     }
8797     std::copy(pointer, pointer + length, startIterator);
8798     Event endEvent;
8799     error = queue.enqueueUnmapMemObject(buffer, pointer, 0, &endEvent);
8800     // if exceptions enabled, enqueueUnmapMemObject will throw
8801     if( error != CL_SUCCESS ) { 
8802         return error;
8803     }
8804     endEvent.wait();
8805     return CL_SUCCESS;
8806 }
8807
8808
8809 #if CL_HPP_TARGET_OPENCL_VERSION >= 200
8810 /**
8811  * Blocking SVM map operation - performs a blocking map underneath.
8812  */
8813 template<typename T, class Alloc>
8814 inline cl_int mapSVM(cl::vector<T, Alloc> &container)
8815 {
8816     return enqueueMapSVM(container, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE);
8817 }
8818
8819 /**
8820 * Blocking SVM map operation - performs a blocking map underneath.
8821 */
8822 template<typename T, class Alloc>
8823 inline cl_int unmapSVM(cl::vector<T, Alloc> &container)
8824 {
8825     return enqueueUnmapSVM(container);
8826 }
8827
8828 #endif // #if CL_HPP_TARGET_OPENCL_VERSION >= 200
8829
8830 #if CL_HPP_TARGET_OPENCL_VERSION >= 110
8831 inline cl_int enqueueReadBufferRect(
8832     const Buffer& buffer,
8833     cl_bool blocking,
8834     const array<size_type, 3>& buffer_offset,
8835     const array<size_type, 3>& host_offset,
8836     const array<size_type, 3>& region,
8837     size_type buffer_row_pitch,
8838     size_type buffer_slice_pitch,
8839     size_type host_row_pitch,
8840     size_type host_slice_pitch,
8841     void *ptr,
8842     const vector<Event>* events = NULL,
8843     Event* event = NULL)
8844 {
8845     cl_int error;
8846     CommandQueue queue = CommandQueue::getDefault(&error);
8847
8848     if (error != CL_SUCCESS) {
8849         return error;
8850     }
8851
8852     return queue.enqueueReadBufferRect(
8853         buffer, 
8854         blocking, 
8855         buffer_offset, 
8856         host_offset,
8857         region,
8858         buffer_row_pitch,
8859         buffer_slice_pitch,
8860         host_row_pitch,
8861         host_slice_pitch,
8862         ptr, 
8863         events, 
8864         event);
8865 }
8866
8867 inline cl_int enqueueWriteBufferRect(
8868     const Buffer& buffer,
8869     cl_bool blocking,
8870     const array<size_type, 3>& buffer_offset,
8871     const array<size_type, 3>& host_offset,
8872     const array<size_type, 3>& region,
8873     size_type buffer_row_pitch,
8874     size_type buffer_slice_pitch,
8875     size_type host_row_pitch,
8876     size_type host_slice_pitch,
8877     void *ptr,
8878     const vector<Event>* events = NULL,
8879     Event* event = NULL)
8880 {
8881     cl_int error;
8882     CommandQueue queue = CommandQueue::getDefault(&error);
8883
8884     if (error != CL_SUCCESS) {
8885         return error;
8886     }
8887
8888     return queue.enqueueWriteBufferRect(
8889         buffer, 
8890         blocking, 
8891         buffer_offset, 
8892         host_offset,
8893         region,
8894         buffer_row_pitch,
8895         buffer_slice_pitch,
8896         host_row_pitch,
8897         host_slice_pitch,
8898         ptr, 
8899         events, 
8900         event);
8901 }
8902
8903 inline cl_int enqueueCopyBufferRect(
8904     const Buffer& src,
8905     const Buffer& dst,
8906     const array<size_type, 3>& src_origin,
8907     const array<size_type, 3>& dst_origin,
8908     const array<size_type, 3>& region,
8909     size_type src_row_pitch,
8910     size_type src_slice_pitch,
8911     size_type dst_row_pitch,
8912     size_type dst_slice_pitch,
8913     const vector<Event>* events = NULL,
8914     Event* event = NULL)
8915 {
8916     cl_int error;
8917     CommandQueue queue = CommandQueue::getDefault(&error);
8918
8919     if (error != CL_SUCCESS) {
8920         return error;
8921     }
8922
8923     return queue.enqueueCopyBufferRect(
8924         src,
8925         dst,
8926         src_origin,
8927         dst_origin,
8928         region,
8929         src_row_pitch,
8930         src_slice_pitch,
8931         dst_row_pitch,
8932         dst_slice_pitch,
8933         events, 
8934         event);
8935 }
8936 #endif // CL_HPP_TARGET_OPENCL_VERSION >= 110
8937
8938 inline cl_int enqueueReadImage(
8939     const Image& image,
8940     cl_bool blocking,
8941     const array<size_type, 3>& origin,
8942     const array<size_type, 3>& region,
8943     size_type row_pitch,
8944     size_type slice_pitch,
8945     void* ptr,
8946     const vector<Event>* events = NULL,
8947     Event* event = NULL) 
8948 {
8949     cl_int error;
8950     CommandQueue queue = CommandQueue::getDefault(&error);
8951
8952     if (error != CL_SUCCESS) {
8953         return error;
8954     }
8955
8956     return queue.enqueueReadImage(
8957         image,
8958         blocking,
8959         origin,
8960         region,
8961         row_pitch,
8962         slice_pitch,
8963         ptr,
8964         events, 
8965         event);
8966 }
8967
8968 inline cl_int enqueueWriteImage(
8969     const Image& image,
8970     cl_bool blocking,
8971     const array<size_type, 3>& origin,
8972     const array<size_type, 3>& region,
8973     size_type row_pitch,
8974     size_type slice_pitch,
8975     void* ptr,
8976     const vector<Event>* events = NULL,
8977     Event* event = NULL)
8978 {
8979     cl_int error;
8980     CommandQueue queue = CommandQueue::getDefault(&error);
8981
8982     if (error != CL_SUCCESS) {
8983         return error;
8984     }
8985
8986     return queue.enqueueWriteImage(
8987         image,
8988         blocking,
8989         origin,
8990         region,
8991         row_pitch,
8992         slice_pitch,
8993         ptr,
8994         events, 
8995         event);
8996 }
8997
8998 inline cl_int enqueueCopyImage(
8999     const Image& src,
9000     const Image& dst,
9001     const array<size_type, 3>& src_origin,
9002     const array<size_type, 3>& dst_origin,
9003     const array<size_type, 3>& region,
9004     const vector<Event>* events = NULL,
9005     Event* event = NULL)
9006 {
9007     cl_int error;
9008     CommandQueue queue = CommandQueue::getDefault(&error);
9009
9010     if (error != CL_SUCCESS) {
9011         return error;
9012     }
9013
9014     return queue.enqueueCopyImage(
9015         src,
9016         dst,
9017         src_origin,
9018         dst_origin,
9019         region,
9020         events,
9021         event);
9022 }
9023
9024 inline cl_int enqueueCopyImageToBuffer(
9025     const Image& src,
9026     const Buffer& dst,
9027     const array<size_type, 3>& src_origin,
9028     const array<size_type, 3>& region,
9029     size_type dst_offset,
9030     const vector<Event>* events = NULL,
9031     Event* event = NULL)
9032 {
9033     cl_int error;
9034     CommandQueue queue = CommandQueue::getDefault(&error);
9035
9036     if (error != CL_SUCCESS) {
9037         return error;
9038     }
9039
9040     return queue.enqueueCopyImageToBuffer(
9041         src,
9042         dst,
9043         src_origin,
9044         region,
9045         dst_offset,
9046         events,
9047         event);
9048 }
9049
9050 inline cl_int enqueueCopyBufferToImage(
9051     const Buffer& src,
9052     const Image& dst,
9053     size_type src_offset,
9054     const array<size_type, 3>& dst_origin,
9055     const array<size_type, 3>& region,
9056     const vector<Event>* events = NULL,
9057     Event* event = NULL)
9058 {
9059     cl_int error;
9060     CommandQueue queue = CommandQueue::getDefault(&error);
9061
9062     if (error != CL_SUCCESS) {
9063         return error;
9064     }
9065
9066     return queue.enqueueCopyBufferToImage(
9067         src,
9068         dst,
9069         src_offset,
9070         dst_origin,
9071         region,
9072         events,
9073         event);
9074 }
9075
9076
9077 inline cl_int flush(void)
9078 {
9079     cl_int error;
9080     CommandQueue queue = CommandQueue::getDefault(&error);
9081
9082     if (error != CL_SUCCESS) {
9083         return error;
9084     }
9085
9086     return queue.flush();
9087 }
9088
9089 inline cl_int finish(void)
9090 {
9091     cl_int error;
9092     CommandQueue queue = CommandQueue::getDefault(&error);
9093
9094     if (error != CL_SUCCESS) {
9095         return error;
9096     } 
9097
9098
9099     return queue.finish();
9100 }
9101
9102 class EnqueueArgs
9103 {
9104 private:
9105     CommandQueue queue_;
9106     const NDRange offset_;
9107     const NDRange global_;
9108     const NDRange local_;
9109     vector<Event> events_;
9110
9111     template<typename... Ts>
9112     friend class KernelFunctor;
9113
9114 public:
9115     EnqueueArgs(NDRange global) : 
9116       queue_(CommandQueue::getDefault()),
9117       offset_(NullRange), 
9118       global_(global),
9119       local_(NullRange)
9120     {
9121
9122     }
9123
9124     EnqueueArgs(NDRange global, NDRange local) : 
9125       queue_(CommandQueue::getDefault()),
9126       offset_(NullRange), 
9127       global_(global),
9128       local_(local)
9129     {
9130
9131     }
9132
9133     EnqueueArgs(NDRange offset, NDRange global, NDRange local) : 
9134       queue_(CommandQueue::getDefault()),
9135       offset_(offset), 
9136       global_(global),
9137       local_(local)
9138     {
9139
9140     }
9141
9142     EnqueueArgs(Event e, NDRange global) : 
9143       queue_(CommandQueue::getDefault()),
9144       offset_(NullRange), 
9145       global_(global),
9146       local_(NullRange)
9147     {
9148         events_.push_back(e);
9149     }
9150
9151     EnqueueArgs(Event e, NDRange global, NDRange local) : 
9152       queue_(CommandQueue::getDefault()),
9153       offset_(NullRange), 
9154       global_(global),
9155       local_(local)
9156     {
9157         events_.push_back(e);
9158     }
9159
9160     EnqueueArgs(Event e, NDRange offset, NDRange global, NDRange local) : 
9161       queue_(CommandQueue::getDefault()),
9162       offset_(offset), 
9163       global_(global),
9164       local_(local)
9165     {
9166         events_.push_back(e);
9167     }
9168
9169     EnqueueArgs(const vector<Event> &events, NDRange global) : 
9170       queue_(CommandQueue::getDefault()),
9171       offset_(NullRange), 
9172       global_(global),
9173       local_(NullRange),
9174       events_(events)
9175     {
9176
9177     }
9178
9179     EnqueueArgs(const vector<Event> &events, NDRange global, NDRange local) : 
9180       queue_(CommandQueue::getDefault()),
9181       offset_(NullRange), 
9182       global_(global),
9183       local_(local),
9184       events_(events)
9185     {
9186
9187     }
9188
9189     EnqueueArgs(const vector<Event> &events, NDRange offset, NDRange global, NDRange local) : 
9190       queue_(CommandQueue::getDefault()),
9191       offset_(offset), 
9192       global_(global),
9193       local_(local),
9194       events_(events)
9195     {
9196
9197     }
9198
9199     EnqueueArgs(CommandQueue &queue, NDRange global) : 
9200       queue_(queue),
9201       offset_(NullRange), 
9202       global_(global),
9203       local_(NullRange)
9204     {
9205
9206     }
9207
9208     EnqueueArgs(CommandQueue &queue, NDRange global, NDRange local) : 
9209       queue_(queue),
9210       offset_(NullRange), 
9211       global_(global),
9212       local_(local)
9213     {
9214
9215     }
9216
9217     EnqueueArgs(CommandQueue &queue, NDRange offset, NDRange global, NDRange local) : 
9218       queue_(queue),
9219       offset_(offset), 
9220       global_(global),
9221       local_(local)
9222     {
9223
9224     }
9225
9226     EnqueueArgs(CommandQueue &queue, Event e, NDRange global) : 
9227       queue_(queue),
9228       offset_(NullRange), 
9229       global_(global),
9230       local_(NullRange)
9231     {
9232         events_.push_back(e);
9233     }
9234
9235     EnqueueArgs(CommandQueue &queue, Event e, NDRange global, NDRange local) : 
9236       queue_(queue),
9237       offset_(NullRange), 
9238       global_(global),
9239       local_(local)
9240     {
9241         events_.push_back(e);
9242     }
9243
9244     EnqueueArgs(CommandQueue &queue, Event e, NDRange offset, NDRange global, NDRange local) : 
9245       queue_(queue),
9246       offset_(offset), 
9247       global_(global),
9248       local_(local)
9249     {
9250         events_.push_back(e);
9251     }
9252
9253     EnqueueArgs(CommandQueue &queue, const vector<Event> &events, NDRange global) : 
9254       queue_(queue),
9255       offset_(NullRange), 
9256       global_(global),
9257       local_(NullRange),
9258       events_(events)
9259     {
9260
9261     }
9262
9263     EnqueueArgs(CommandQueue &queue, const vector<Event> &events, NDRange global, NDRange local) : 
9264       queue_(queue),
9265       offset_(NullRange), 
9266       global_(global),
9267       local_(local),
9268       events_(events)
9269     {
9270
9271     }
9272
9273     EnqueueArgs(CommandQueue &queue, const vector<Event> &events, NDRange offset, NDRange global, NDRange local) : 
9274       queue_(queue),
9275       offset_(offset), 
9276       global_(global),
9277       local_(local),
9278       events_(events)
9279     {
9280
9281     }
9282 };
9283
9284
9285 //----------------------------------------------------------------------------------------------
9286
9287
9288 /**
9289  * Type safe kernel functor.
9290  * 
9291  */
9292 template<typename... Ts>
9293 class KernelFunctor
9294 {
9295 private:
9296     Kernel kernel_;
9297
9298     template<int index, typename T0, typename... T1s>
9299     void setArgs(T0&& t0, T1s&&... t1s)
9300     {
9301         kernel_.setArg(index, t0);
9302         setArgs<index + 1, T1s...>(std::forward<T1s>(t1s)...);
9303     }
9304
9305     template<int index, typename T0>
9306     void setArgs(T0&& t0)
9307     {
9308         kernel_.setArg(index, t0);
9309     }
9310
9311     template<int index>
9312     void setArgs()
9313     {
9314     }
9315
9316
9317 public:
9318     KernelFunctor(Kernel kernel) : kernel_(kernel)
9319     {}
9320
9321     KernelFunctor(
9322         const Program& program,
9323         const string name,
9324         cl_int * err = NULL) :
9325         kernel_(program, name.c_str(), err)
9326     {}
9327
9328     //! \brief Return type of the functor
9329     typedef Event result_type;
9330
9331     /**
9332      * Enqueue kernel.
9333      * @param args Launch parameters of the kernel.
9334      * @param t0... List of kernel arguments based on the template type of the functor.
9335      */
9336     Event operator() (
9337         const EnqueueArgs& args,
9338         Ts... ts)
9339     {
9340         Event event;
9341         setArgs<0>(std::forward<Ts>(ts)...);
9342         
9343         args.queue_.enqueueNDRangeKernel(
9344             kernel_,
9345             args.offset_,
9346             args.global_,
9347             args.local_,
9348             &args.events_,
9349             &event);
9350
9351         return event;
9352     }
9353
9354     /**
9355     * Enqueue kernel with support for error code.
9356     * @param args Launch parameters of the kernel.
9357     * @param t0... List of kernel arguments based on the template type of the functor.
9358     * @param error Out parameter returning the error code from the execution.
9359     */
9360     Event operator() (
9361         const EnqueueArgs& args,
9362         Ts... ts,
9363         cl_int &error)
9364     {
9365         Event event;
9366         setArgs<0>(std::forward<Ts>(ts)...);
9367
9368         error = args.queue_.enqueueNDRangeKernel(
9369             kernel_,
9370             args.offset_,
9371             args.global_,
9372             args.local_,
9373             &args.events_,
9374             &event);
9375         
9376         return event;
9377     }
9378
9379 #if CL_HPP_TARGET_OPENCL_VERSION >= 200
9380     cl_int setSVMPointers(const vector<void*> &pointerList)
9381     {
9382         return kernel_.setSVMPointers(pointerList);
9383     }
9384
9385     template<typename T0, typename... T1s>
9386     cl_int setSVMPointers(const T0 &t0, T1s... ts)
9387     {
9388         return kernel_.setSVMPointers(t0, ts...);
9389     }
9390 #endif // #if CL_HPP_TARGET_OPENCL_VERSION >= 200
9391
9392     Kernel getKernel()
9393     {
9394         return kernel_;
9395     }
9396 };
9397
9398 namespace compatibility {
9399     /**
9400      * Backward compatibility class to ensure that cl.hpp code works with cl2.hpp.
9401      * Please use KernelFunctor directly.
9402      */
9403     template<typename... Ts>
9404     struct make_kernel
9405     {
9406         typedef KernelFunctor<Ts...> FunctorType;
9407
9408         FunctorType functor_;
9409
9410         make_kernel(
9411             const Program& program,
9412             const string name,
9413             cl_int * err = NULL) :
9414             functor_(FunctorType(program, name, err))
9415         {}
9416
9417         make_kernel(
9418             const Kernel kernel) :
9419             functor_(FunctorType(kernel))
9420         {}
9421
9422         //! \brief Return type of the functor
9423         typedef Event result_type;
9424
9425         //! \brief Function signature of kernel functor with no event dependency.
9426         typedef Event type_(
9427             const EnqueueArgs&,
9428             Ts...);
9429
9430         Event operator()(
9431             const EnqueueArgs& enqueueArgs,
9432             Ts... args)
9433         {
9434             return functor_(
9435                 enqueueArgs, args...);
9436         }
9437     };
9438 } // namespace compatibility
9439
9440
9441 //----------------------------------------------------------------------------------------------------------------------
9442
9443 #undef CL_HPP_ERR_STR_
9444 #if !defined(CL_HPP_USER_OVERRIDE_ERROR_STRINGS)
9445 #undef __GET_DEVICE_INFO_ERR
9446 #undef __GET_PLATFORM_INFO_ERR
9447 #undef __GET_DEVICE_IDS_ERR
9448 #undef __GET_CONTEXT_INFO_ERR
9449 #undef __GET_EVENT_INFO_ERR
9450 #undef __GET_EVENT_PROFILE_INFO_ERR
9451 #undef __GET_MEM_OBJECT_INFO_ERR
9452 #undef __GET_IMAGE_INFO_ERR
9453 #undef __GET_SAMPLER_INFO_ERR
9454 #undef __GET_KERNEL_INFO_ERR
9455 #undef __GET_KERNEL_ARG_INFO_ERR
9456 #undef __GET_KERNEL_WORK_GROUP_INFO_ERR
9457 #undef __GET_PROGRAM_INFO_ERR
9458 #undef __GET_PROGRAM_BUILD_INFO_ERR
9459 #undef __GET_COMMAND_QUEUE_INFO_ERR
9460
9461 #undef __CREATE_CONTEXT_ERR
9462 #undef __CREATE_CONTEXT_FROM_TYPE_ERR
9463 #undef __GET_SUPPORTED_IMAGE_FORMATS_ERR
9464
9465 #undef __CREATE_BUFFER_ERR
9466 #undef __CREATE_SUBBUFFER_ERR
9467 #undef __CREATE_IMAGE2D_ERR
9468 #undef __CREATE_IMAGE3D_ERR
9469 #undef __CREATE_SAMPLER_ERR
9470 #undef __SET_MEM_OBJECT_DESTRUCTOR_CALLBACK_ERR
9471
9472 #undef __CREATE_USER_EVENT_ERR
9473 #undef __SET_USER_EVENT_STATUS_ERR
9474 #undef __SET_EVENT_CALLBACK_ERR
9475 #undef __SET_PRINTF_CALLBACK_ERR
9476
9477 #undef __WAIT_FOR_EVENTS_ERR
9478
9479 #undef __CREATE_KERNEL_ERR
9480 #undef __SET_KERNEL_ARGS_ERR
9481 #undef __CREATE_PROGRAM_WITH_SOURCE_ERR
9482 #undef __CREATE_PROGRAM_WITH_BINARY_ERR
9483 #undef __CREATE_PROGRAM_WITH_BUILT_IN_KERNELS_ERR
9484 #undef __BUILD_PROGRAM_ERR
9485 #undef __CREATE_KERNELS_IN_PROGRAM_ERR
9486
9487 #undef __CREATE_COMMAND_QUEUE_ERR
9488 #undef __SET_COMMAND_QUEUE_PROPERTY_ERR
9489 #undef __ENQUEUE_READ_BUFFER_ERR
9490 #undef __ENQUEUE_WRITE_BUFFER_ERR
9491 #undef __ENQUEUE_READ_BUFFER_RECT_ERR
9492 #undef __ENQUEUE_WRITE_BUFFER_RECT_ERR
9493 #undef __ENQEUE_COPY_BUFFER_ERR
9494 #undef __ENQEUE_COPY_BUFFER_RECT_ERR
9495 #undef __ENQUEUE_READ_IMAGE_ERR
9496 #undef __ENQUEUE_WRITE_IMAGE_ERR
9497 #undef __ENQUEUE_COPY_IMAGE_ERR
9498 #undef __ENQUEUE_COPY_IMAGE_TO_BUFFER_ERR
9499 #undef __ENQUEUE_COPY_BUFFER_TO_IMAGE_ERR
9500 #undef __ENQUEUE_MAP_BUFFER_ERR
9501 #undef __ENQUEUE_MAP_IMAGE_ERR
9502 #undef __ENQUEUE_UNMAP_MEM_OBJECT_ERR
9503 #undef __ENQUEUE_NDRANGE_KERNEL_ERR
9504 #undef __ENQUEUE_TASK_ERR
9505 #undef __ENQUEUE_NATIVE_KERNEL
9506
9507 #undef __UNLOAD_COMPILER_ERR
9508 #undef __CREATE_SUB_DEVICES_ERR
9509
9510 #undef __CREATE_PIPE_ERR
9511 #undef __GET_PIPE_INFO_ERR
9512
9513 #endif //CL_HPP_USER_OVERRIDE_ERROR_STRINGS
9514
9515 // Extensions
9516 #undef CL_HPP_INIT_CL_EXT_FCN_PTR_
9517 #undef CL_HPP_INIT_CL_EXT_FCN_PTR_PLATFORM_
9518
9519 #if defined(CL_HPP_USE_CL_DEVICE_FISSION)
9520 #undef CL_HPP_PARAM_NAME_DEVICE_FISSION_
9521 #endif // CL_HPP_USE_CL_DEVICE_FISSION
9522
9523 #undef CL_HPP_NOEXCEPT_
9524 #undef CL_HPP_DEFINE_STATIC_MEMBER_
9525
9526 } // namespace cl
9527
9528 #endif // CL_HPP_