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