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