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