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