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