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