ddemidov / vexcl
1
/*******************************************************************************
2
 * Copyright (c) 2008-2015 The Khronos Group Inc.
3
 *
4
 * Permission is hereby granted, free of charge, to any person obtaining a
5
 * copy of this software and/or associated documentation files (the
6
 * "Materials"), to deal in the Materials without restriction, including
7
 * without limitation the rights to use, copy, modify, merge, publish,
8
 * distribute, sublicense, and/or sell copies of the Materials, and to
9
 * permit persons to whom the Materials are furnished to do so, subject to
10
 * the following conditions:
11
 *
12
 * The above copyright notice and this permission notice shall be included
13
 * in all copies or substantial portions of the Materials.
14
 *
15
 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21
 * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
22
 ******************************************************************************/
23

24
/*! \file
25
 *
26
 *   \brief C++ bindings for OpenCL 1.0 (rev 48), OpenCL 1.1 (rev 33) and 
27
 *       OpenCL 1.2 (rev 15)    
28
 *   \author Benedict R. Gaster, Laurent Morichetti and Lee Howes
29
 *   
30
 *   Additions and fixes from:
31
 *       Brian Cole, March 3rd 2010 and April 2012 
32
 *       Matt Gruenke, April 2012.
33
 *       Bruce Merry, February 2013.
34
 *       Tom Deakin and Simon McIntosh-Smith, July 2013
35
 *   
36
 *   \version 1.2.8
37
 *   \date October 2015
38
 *
39
 *   Optional extension support
40
 *
41
 *         cl
42
 *         cl_ext_device_fission
43
 *				#define USE_CL_DEVICE_FISSION
44
 */
45

46
/*! \mainpage
47
 * \section intro Introduction
48
 * For many large applications C++ is the language of choice and so it seems
49
 * reasonable to define C++ bindings for OpenCL.
50
 *
51
 *
52
 * The interface is contained with a single C++ header file \em cl.hpp and all
53
 * definitions are contained within the namespace \em cl. There is no additional
54
 * requirement to include \em cl.h and to use either the C++ or original C
55
 * bindings it is enough to simply include \em cl.hpp.
56
 *
57
 * The bindings themselves are lightweight and correspond closely to the
58
 * underlying C API. Using the C++ bindings introduces no additional execution
59
 * overhead.
60
 *
61
 * For detail documentation on the bindings see:
62
 *
63
 * The OpenCL C++ Wrapper API 1.2 (revision 09)
64
 *  http://www.khronos.org/registry/cl/specs/opencl-cplusplus-1.2.pdf
65
 *
66
 * \section example Example
67
 *
68
 * The following example shows a general use case for the C++
69
 * bindings, including support for the optional exception feature and
70
 * also the supplied vector and string classes, see following sections for
71
 * decriptions of these features.
72
 *
73
 * \code
74
 * #define __CL_ENABLE_EXCEPTIONS
75
 * 
76
 * #if defined(__APPLE__) || defined(__MACOSX)
77
 * #include <OpenCL/cl.hpp>
78
 * #else
79
 * #include <CL/cl.hpp>
80
 * #endif
81
 * #include <cstdio>
82
 * #include <cstdlib>
83
 * #include <iostream>
84
 * 
85
 *  const char * helloStr  = "__kernel void "
86
 *                           "hello(void) "
87
 *                           "{ "
88
 *                           "  "
89
 *                           "} ";
90
 * 
91
 *  int
92
 *  main(void)
93
 *  {
94
 *     cl_int err = CL_SUCCESS;
95
 *     try {
96
 *
97
 *       std::vector<cl::Platform> platforms;
98
 *       cl::Platform::get(&platforms);
99
 *       if (platforms.size() == 0) {
100
 *           std::cout << "Platform size 0\n";
101
 *           return -1;
102
 *       }
103
 *
104
 *       cl_context_properties properties[] = 
105
 *          { CL_CONTEXT_PLATFORM, (cl_context_properties)(platforms[0])(), 0};
106
 *       cl::Context context(CL_DEVICE_TYPE_CPU, properties); 
107
 * 
108
 *       std::vector<cl::Device> devices = context.getInfo<CL_CONTEXT_DEVICES>();
109
 * 
110
 *       cl::Program::Sources source(1,
111
 *           std::make_pair(helloStr,strlen(helloStr)));
112
 *       cl::Program program_ = cl::Program(context, source);
113
 *       program_.build(devices);
114
 * 
115
 *       cl::Kernel kernel(program_, "hello", &err);
116
 * 
117
 *       cl::Event event;
118
 *       cl::CommandQueue queue(context, devices[0], 0, &err);
119
 *       queue.enqueueNDRangeKernel(
120
 *           kernel, 
121
 *           cl::NullRange, 
122
 *           cl::NDRange(4,4),
123
 *           cl::NullRange,
124
 *           NULL,
125
 *           &event); 
126
 * 
127
 *       event.wait();
128
 *     }
129
 *     catch (cl::Error err) {
130
 *        std::cerr 
131
 *           << "ERROR: "
132
 *           << err.what()
133
 *           << "("
134
 *           << err.err()
135
 *           << ")"
136
 *           << std::endl;
137
 *     }
138
 * 
139
 *    return EXIT_SUCCESS;
140
 *  }
141
 * 
142
 * \endcode
143
 *
144
 */
145
#ifndef CL_HPP_
146
#define CL_HPP_
147

148
#ifdef _WIN32
149

150
#include <malloc.h>
151

152
#if defined(USE_DX_INTEROP)
153
#include <CL/cl_d3d10.h>
154
#include <CL/cl_dx9_media_sharing.h>
155
#endif
156
#endif // _WIN32
157

158
#if defined(_MSC_VER)
159
#include <intrin.h>
160
#endif // _MSC_VER
161

162
// 
163
#if defined(USE_CL_DEVICE_FISSION)
164
#include <CL/cl_ext.h>
165
#endif
166

167
#if defined(__APPLE__) || defined(__MACOSX)
168
#include <OpenCL/opencl.h>
169
#else
170
#include <CL/opencl.h>
171
#endif // !__APPLE__
172

173
#if (_MSC_VER >= 1700) || (__cplusplus >= 201103L)
174
#define CL_HPP_RVALUE_REFERENCES_SUPPORTED
175
#define CL_HPP_CPP11_ATOMICS_SUPPORTED
176
#include <atomic>
177
#endif
178

179
#if (__cplusplus >= 201103L)
180
#define CL_HPP_NOEXCEPT noexcept
181
#else
182
#define CL_HPP_NOEXCEPT
183
#endif
184

185

186
// To avoid accidentally taking ownership of core OpenCL types
187
// such as cl_kernel constructors are made explicit
188
// under OpenCL 1.2
189
#if defined(CL_VERSION_1_2) && !defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS)
190
#define __CL_EXPLICIT_CONSTRUCTORS explicit
191
#else // #if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS)
192
#define __CL_EXPLICIT_CONSTRUCTORS 
193
#endif // #if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS)
194

195
// Define deprecated prefixes and suffixes to ensure compilation
196
// in case they are not pre-defined
197
#if !defined(CL_EXT_PREFIX__VERSION_1_1_DEPRECATED)
198
#define CL_EXT_PREFIX__VERSION_1_1_DEPRECATED  
199
#endif // #if !defined(CL_EXT_PREFIX__VERSION_1_1_DEPRECATED)
200
#if !defined(CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED)
201
#define CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED
202
#endif // #if !defined(CL_EXT_PREFIX__VERSION_1_1_DEPRECATED)
203

204
#if !defined(CL_CALLBACK)
205
#define CL_CALLBACK
206
#endif //CL_CALLBACK
207

208
#include <utility>
209
#include <limits>
210
#include <iterator>
211

212
#if defined(__CL_ENABLE_EXCEPTIONS)
213
#include <exception>
214
#endif // #if defined(__CL_ENABLE_EXCEPTIONS)
215

216
#if !defined(__NO_STD_VECTOR)
217
#include <vector>
218
#endif
219

220
#if !defined(__NO_STD_STRING)
221
#include <string>
222
#endif 
223

224
#if defined(__ANDROID__) || defined(linux) || defined(__APPLE__) || defined(__MACOSX)
225
#include <alloca.h>
226
#endif // linux
227

228
#include <cstring>
229

230

231
/*! \namespace cl
232
 *
233
 * \brief The OpenCL C++ bindings are defined within this namespace.
234
 *
235
 */
236
namespace cl {
237

238
class Memory;
239

240
/**
241
 * Deprecated APIs for 1.2
242
 */
243
#if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) || (defined(CL_VERSION_1_1) && !defined(CL_VERSION_1_2)) 
244
#define __INIT_CL_EXT_FCN_PTR(name) \
245
    if(!pfn_##name) { \
246
        pfn_##name = (PFN_##name) \
247
            clGetExtensionFunctionAddress(#name); \
248
        if(!pfn_##name) { \
249
        } \
250
    }
251
#endif // #if defined(CL_VERSION_1_1)
252

253
#if defined(CL_VERSION_1_2)
254
#define __INIT_CL_EXT_FCN_PTR_PLATFORM(platform, name) \
255
    if(!pfn_##name) { \
256
        pfn_##name = (PFN_##name) \
257
            clGetExtensionFunctionAddressForPlatform(platform, #name); \
258
        if(!pfn_##name) { \
259
        } \
260
    }
261
#endif // #if defined(CL_VERSION_1_1)
262

263
class Program;
264
class Device;
265
class Context;
266
class CommandQueue;
267
class Memory;
268
class Buffer;
269

270
#if defined(__CL_ENABLE_EXCEPTIONS)
271
/*! \brief Exception class 
272
 * 
273
 *  This may be thrown by API functions when __CL_ENABLE_EXCEPTIONS is defined.
274
 */
275
class Error : public std::exception
276
{
277
private:
278
    cl_int err_;
279
    const char * errStr_;
280
public:
281
    /*! \brief Create a new CL error exception for a given error code
282
     *  and corresponding message.
283
     * 
284
     *  \param err error code value.
285
     *
286
     *  \param errStr a descriptive string that must remain in scope until
287
     *                handling of the exception has concluded.  If set, it
288
     *                will be returned by what().
289
     */
290 0
    Error(cl_int err, const char * errStr = NULL) : err_(err), errStr_(errStr)
291 0
    {}
292

293 0
    ~Error() throw() {}
294

295
    /*! \brief Get error string associated with exception
296
     *
297
     * \return A memory pointer to the error message string.
298
     */
299
    virtual const char * what() const throw () override
300
    {
301 0
        if (errStr_ == NULL) {
302 0
            return "empty";
303
        }
304
        else {
305 0
            return errStr_;
306
        }
307
    }
308

309
    /*! \brief Get error code associated with exception
310
     *
311
     *  \return The error code.
312
     */
313
    cl_int err(void) const { return err_; }
314
};
315

316
#define __ERR_STR(x) #x
317
#else
318
#define __ERR_STR(x) NULL
319
#endif // __CL_ENABLE_EXCEPTIONS
320

321

322
namespace detail
323
{
324
#if defined(__CL_ENABLE_EXCEPTIONS)
325
static inline cl_int errHandler (
326
    cl_int err,
327
    const char * errStr = NULL)
328
{
329 0
    if (err != CL_SUCCESS) {
330 0
        throw Error(err, errStr);
331
    }
332 0
    return err;
333
}
334
#else
335
static inline cl_int errHandler (cl_int err, const char * errStr = NULL)
336
{
337
    (void) errStr; // suppress unused variable warning
338
    return err;
339
}
340
#endif // __CL_ENABLE_EXCEPTIONS
341
}
342

343

344

345
//! \cond DOXYGEN_DETAIL
346
#if !defined(__CL_USER_OVERRIDE_ERROR_STRINGS)
347
#define __GET_DEVICE_INFO_ERR               __ERR_STR(clGetDeviceInfo)
348
#define __GET_PLATFORM_INFO_ERR             __ERR_STR(clGetPlatformInfo)
349
#define __GET_DEVICE_IDS_ERR                __ERR_STR(clGetDeviceIDs)
350
#define __GET_PLATFORM_IDS_ERR              __ERR_STR(clGetPlatformIDs)
351
#define __GET_CONTEXT_INFO_ERR              __ERR_STR(clGetContextInfo)
352
#define __GET_EVENT_INFO_ERR                __ERR_STR(clGetEventInfo)
353
#define __GET_EVENT_PROFILE_INFO_ERR        __ERR_STR(clGetEventProfileInfo)
354
#define __GET_MEM_OBJECT_INFO_ERR           __ERR_STR(clGetMemObjectInfo)
355
#define __GET_IMAGE_INFO_ERR                __ERR_STR(clGetImageInfo)
356
#define __GET_SAMPLER_INFO_ERR              __ERR_STR(clGetSamplerInfo)
357
#define __GET_KERNEL_INFO_ERR               __ERR_STR(clGetKernelInfo)
358
#if defined(CL_VERSION_1_2)
359
#define __GET_KERNEL_ARG_INFO_ERR               __ERR_STR(clGetKernelArgInfo)
360
#endif // #if defined(CL_VERSION_1_2)
361
#define __GET_KERNEL_WORK_GROUP_INFO_ERR    __ERR_STR(clGetKernelWorkGroupInfo)
362
#define __GET_PROGRAM_INFO_ERR              __ERR_STR(clGetProgramInfo)
363
#define __GET_PROGRAM_BUILD_INFO_ERR        __ERR_STR(clGetProgramBuildInfo)
364
#define __GET_COMMAND_QUEUE_INFO_ERR        __ERR_STR(clGetCommandQueueInfo)
365

366
#define __CREATE_CONTEXT_ERR                __ERR_STR(clCreateContext)
367
#define __CREATE_CONTEXT_FROM_TYPE_ERR      __ERR_STR(clCreateContextFromType)
368
#define __GET_SUPPORTED_IMAGE_FORMATS_ERR   __ERR_STR(clGetSupportedImageFormats)
369

370
#define __CREATE_BUFFER_ERR                 __ERR_STR(clCreateBuffer)
371
#define __COPY_ERR                          __ERR_STR(cl::copy)
372
#define __CREATE_SUBBUFFER_ERR              __ERR_STR(clCreateSubBuffer)
373
#define __CREATE_GL_BUFFER_ERR              __ERR_STR(clCreateFromGLBuffer)
374
#define __CREATE_GL_RENDER_BUFFER_ERR       __ERR_STR(clCreateFromGLBuffer)
375
#define __GET_GL_OBJECT_INFO_ERR            __ERR_STR(clGetGLObjectInfo)
376
#if defined(CL_VERSION_1_2)
377
#define __CREATE_IMAGE_ERR                  __ERR_STR(clCreateImage)
378
#define __CREATE_GL_TEXTURE_ERR             __ERR_STR(clCreateFromGLTexture)
379
#define __IMAGE_DIMENSION_ERR               __ERR_STR(Incorrect image dimensions)
380
#endif // #if defined(CL_VERSION_1_2)
381
#define __CREATE_SAMPLER_ERR                __ERR_STR(clCreateSampler)
382
#define __SET_MEM_OBJECT_DESTRUCTOR_CALLBACK_ERR __ERR_STR(clSetMemObjectDestructorCallback)
383

384
#define __CREATE_USER_EVENT_ERR             __ERR_STR(clCreateUserEvent)
385
#define __SET_USER_EVENT_STATUS_ERR         __ERR_STR(clSetUserEventStatus)
386
#define __SET_EVENT_CALLBACK_ERR            __ERR_STR(clSetEventCallback)
387
#define __WAIT_FOR_EVENTS_ERR               __ERR_STR(clWaitForEvents)
388

389
#define __CREATE_KERNEL_ERR                 __ERR_STR(clCreateKernel)
390
#define __SET_KERNEL_ARGS_ERR               __ERR_STR(clSetKernelArg)
391
#define __CREATE_PROGRAM_WITH_SOURCE_ERR    __ERR_STR(clCreateProgramWithSource)
392
#define __CREATE_PROGRAM_WITH_BINARY_ERR    __ERR_STR(clCreateProgramWithBinary)
393
#if defined(CL_VERSION_1_2)
394
#define __CREATE_PROGRAM_WITH_BUILT_IN_KERNELS_ERR    __ERR_STR(clCreateProgramWithBuiltInKernels)
395
#endif // #if defined(CL_VERSION_1_2)
396
#define __BUILD_PROGRAM_ERR                 __ERR_STR(clBuildProgram)
397
#if defined(CL_VERSION_1_2)
398
#define __COMPILE_PROGRAM_ERR                  __ERR_STR(clCompileProgram)
399
#define __LINK_PROGRAM_ERR                  __ERR_STR(clLinkProgram)
400
#endif // #if defined(CL_VERSION_1_2)
401
#define __CREATE_KERNELS_IN_PROGRAM_ERR     __ERR_STR(clCreateKernelsInProgram)
402

403
#define __CREATE_COMMAND_QUEUE_ERR          __ERR_STR(clCreateCommandQueue)
404
#define __SET_COMMAND_QUEUE_PROPERTY_ERR    __ERR_STR(clSetCommandQueueProperty)
405
#define __ENQUEUE_READ_BUFFER_ERR           __ERR_STR(clEnqueueReadBuffer)
406
#define __ENQUEUE_READ_BUFFER_RECT_ERR      __ERR_STR(clEnqueueReadBufferRect)
407
#define __ENQUEUE_WRITE_BUFFER_ERR          __ERR_STR(clEnqueueWriteBuffer)
408
#define __ENQUEUE_WRITE_BUFFER_RECT_ERR     __ERR_STR(clEnqueueWriteBufferRect)
409
#define __ENQEUE_COPY_BUFFER_ERR            __ERR_STR(clEnqueueCopyBuffer)
410
#define __ENQEUE_COPY_BUFFER_RECT_ERR       __ERR_STR(clEnqueueCopyBufferRect)
411
#define __ENQUEUE_FILL_BUFFER_ERR           __ERR_STR(clEnqueueFillBuffer)
412
#define __ENQUEUE_READ_IMAGE_ERR            __ERR_STR(clEnqueueReadImage)
413
#define __ENQUEUE_WRITE_IMAGE_ERR           __ERR_STR(clEnqueueWriteImage)
414
#define __ENQUEUE_COPY_IMAGE_ERR            __ERR_STR(clEnqueueCopyImage)
415
#define __ENQUEUE_FILL_IMAGE_ERR           __ERR_STR(clEnqueueFillImage)
416
#define __ENQUEUE_COPY_IMAGE_TO_BUFFER_ERR  __ERR_STR(clEnqueueCopyImageToBuffer)
417
#define __ENQUEUE_COPY_BUFFER_TO_IMAGE_ERR  __ERR_STR(clEnqueueCopyBufferToImage)
418
#define __ENQUEUE_MAP_BUFFER_ERR            __ERR_STR(clEnqueueMapBuffer)
419
#define __ENQUEUE_MAP_IMAGE_ERR             __ERR_STR(clEnqueueMapImage)
420
#define __ENQUEUE_UNMAP_MEM_OBJECT_ERR      __ERR_STR(clEnqueueUnMapMemObject)
421
#define __ENQUEUE_NDRANGE_KERNEL_ERR        __ERR_STR(clEnqueueNDRangeKernel)
422
#define __ENQUEUE_TASK_ERR                  __ERR_STR(clEnqueueTask)
423
#define __ENQUEUE_NATIVE_KERNEL             __ERR_STR(clEnqueueNativeKernel)
424
#if defined(CL_VERSION_1_2)
425
#define __ENQUEUE_MIGRATE_MEM_OBJECTS_ERR   __ERR_STR(clEnqueueMigrateMemObjects)
426
#endif // #if defined(CL_VERSION_1_2)
427

428
#define __ENQUEUE_ACQUIRE_GL_ERR            __ERR_STR(clEnqueueAcquireGLObjects)
429
#define __ENQUEUE_RELEASE_GL_ERR            __ERR_STR(clEnqueueReleaseGLObjects)
430

431

432
#define __RETAIN_ERR                        __ERR_STR(Retain Object)
433
#define __RELEASE_ERR                       __ERR_STR(Release Object)
434
#define __FLUSH_ERR                         __ERR_STR(clFlush)
435
#define __FINISH_ERR                        __ERR_STR(clFinish)
436
#define __VECTOR_CAPACITY_ERR               __ERR_STR(Vector capacity error)
437

438
/**
439
 * CL 1.2 version that uses device fission.
440
 */
441
#if defined(CL_VERSION_1_2)
442
#define __CREATE_SUB_DEVICES                __ERR_STR(clCreateSubDevices)
443
#else
444
#define __CREATE_SUB_DEVICES                __ERR_STR(clCreateSubDevicesEXT)
445
#endif // #if defined(CL_VERSION_1_2)
446

447
/**
448
 * Deprecated APIs for 1.2
449
 */
450
#if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) || (defined(CL_VERSION_1_1) && !defined(CL_VERSION_1_2)) 
451
#define __ENQUEUE_MARKER_ERR                __ERR_STR(clEnqueueMarker)
452
#define __ENQUEUE_WAIT_FOR_EVENTS_ERR       __ERR_STR(clEnqueueWaitForEvents)
453
#define __ENQUEUE_BARRIER_ERR               __ERR_STR(clEnqueueBarrier)
454
#define __UNLOAD_COMPILER_ERR               __ERR_STR(clUnloadCompiler)
455
#define __CREATE_GL_TEXTURE_2D_ERR          __ERR_STR(clCreateFromGLTexture2D)
456
#define __CREATE_GL_TEXTURE_3D_ERR          __ERR_STR(clCreateFromGLTexture3D)
457
#define __CREATE_IMAGE2D_ERR                __ERR_STR(clCreateImage2D)
458
#define __CREATE_IMAGE3D_ERR                __ERR_STR(clCreateImage3D)
459
#endif // #if defined(CL_VERSION_1_1)
460

461
#endif // __CL_USER_OVERRIDE_ERROR_STRINGS
462
//! \endcond
463

464
/**
465
 * CL 1.2 marker and barrier commands
466
 */
467
#if defined(CL_VERSION_1_2)
468
#define __ENQUEUE_MARKER_WAIT_LIST_ERR                __ERR_STR(clEnqueueMarkerWithWaitList)
469
#define __ENQUEUE_BARRIER_WAIT_LIST_ERR               __ERR_STR(clEnqueueBarrierWithWaitList)
470
#endif // #if defined(CL_VERSION_1_2)
471

472
#if !defined(__USE_DEV_STRING) && !defined(__NO_STD_STRING)
473
typedef std::string STRING_CLASS;
474
#elif !defined(__USE_DEV_STRING) 
475

476
/*! \class string
477
 * \brief Simple string class, that provides a limited subset of std::string
478
 * functionality but avoids many of the issues that come with that class.
479
 
480
 *  \note Deprecated. Please use std::string as default or
481
 *  re-define the string class to match the std::string
482
 *  interface by defining STRING_CLASS
483
 */
484
class CL_EXT_PREFIX__VERSION_1_1_DEPRECATED string CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED
485
{
486
private:
487
    ::size_t size_;
488
    char * str_;
489
public:
490
    //! \brief Constructs an empty string, allocating no memory.
491
    string(void) : size_(0), str_(NULL)
492
    {
493
    }
494

495
    /*! \brief Constructs a string populated from an arbitrary value of
496
     *  specified size.
497
     * 
498
     *  An extra '\0' is added, in case none was contained in str.
499
     *
500
     *  \param str the initial value of the string instance.  Note that '\0'     
501
     *             characters receive no special treatment.  If NULL,
502
     *             the string is left empty, with a size of 0.
503
     *
504
     *  \param size the number of characters to copy from str.
505
     */
506
    string(const char * str, ::size_t size) :
507
        size_(size),
508
        str_(NULL)
509
    {
510
        if( size > 0 ) {
511
            str_ = new char[size_+1];
512
            if (str_ != NULL) {
513
                memcpy(str_, str, size_  * sizeof(char));
514
                str_[size_] = '\0';
515
            }
516
            else {
517
                size_ = 0;
518
            }
519
        }
520
    }
521

522
    /*! \brief Constructs a string populated from a null-terminated value.
523
     *
524
     *  \param str the null-terminated initial value of the string instance.
525
     *             If NULL, the string is left empty, with a size of 0.
526
     */
527
    string(const char * str) :
528
        size_(0),
529
        str_(NULL)
530
    {
531
        if( str ) {
532
            size_= ::strlen(str);
533
        }
534
        if( size_ > 0 ) {
535
            str_ = new char[size_ + 1];
536
            if (str_ != NULL) {
537
                memcpy(str_, str, (size_ + 1) * sizeof(char));
538
            }
539
        }
540
    }
541

542
    void resize( ::size_t n )
543
    {
544
        if( size_ == n ) {
545
            return;
546
        }
547
        if (n == 0) {
548
            if( str_ ) {
549
                delete [] str_;
550
            }
551
            str_ = NULL;
552
            size_ = 0;
553
        } 
554
        else {
555
            char *newString = new char[n + 1];
556
            ::size_t copySize = n;
557
            if( size_ < n ) {
558
                copySize = size_;
559
            }
560
            size_ = n;
561
            
562
            if(str_) {
563
                memcpy(newString, str_, (copySize + 1) * sizeof(char));
564
            }
565
            if( copySize < size_ ) {
566
                memset(newString + copySize, 0, size_ - copySize);
567
            }
568
            newString[size_] = '\0';
569

570
            delete [] str_;
571
            str_ = newString;
572
        }
573
    }
574

575
    const char& operator[] ( ::size_t pos ) const
576
    {
577
        return str_[pos];
578
    }
579

580
    char& operator[] ( ::size_t pos )
581
    {
582
        return str_[pos];
583
    }
584

585
    /*! \brief Copies the value of another string to this one.
586
     *
587
     *  \param rhs the string to copy.
588
     *
589
     *  \returns a reference to the modified instance.
590
     */
591
    string& operator=(const string& rhs)
592
    {
593
        if (this == &rhs) {
594
            return *this;
595
        }
596

597
        if( str_ != NULL ) {
598
            delete [] str_;
599
            str_ = NULL;
600
            size_ = 0;
601
        }
602

603
        if (rhs.size_ == 0 || rhs.str_ == NULL) {
604
            str_ = NULL;
605
            size_ = 0;
606
        } 
607
        else {
608
            str_ = new char[rhs.size_ + 1];
609
            size_ = rhs.size_;
610
            
611
            if (str_ != NULL) {
612
                memcpy(str_, rhs.str_, (size_ + 1) * sizeof(char));
613
            }
614
            else {
615
                size_ = 0;
616
            }
617
        }
618

619
        return *this;
620
    }
621

622
    /*! \brief Constructs a string by copying the value of another instance.
623
     *
624
     *  \param rhs the string to copy.
625
     */
626
    string(const string& rhs) :
627
        size_(0),
628
        str_(NULL)
629
    {
630
        *this = rhs;
631
    }
632

633
    //! \brief Destructor - frees memory used to hold the current value.
634
    ~string()
635
    {
636
        delete[] str_;
637
        str_ = NULL;
638
    }
639
    
640
    //! \brief Queries the length of the string, excluding any added '\0's.
641
    ::size_t size(void) const   { return size_; }
642

643
    //! \brief Queries the length of the string, excluding any added '\0's.
644
    ::size_t length(void) const { return size(); }
645

646
    /*! \brief Returns a pointer to the private copy held by this instance,
647
     *  or "" if empty/unset.
648
     */
649
    const char * c_str(void) const { return (str_) ? str_ : "";}
650
};
651
typedef cl::string STRING_CLASS;
652
#endif // #elif !defined(__USE_DEV_STRING) 
653

654
#if !defined(__USE_DEV_VECTOR) && !defined(__NO_STD_VECTOR)
655
#define VECTOR_CLASS std::vector
656
#elif !defined(__USE_DEV_VECTOR) 
657
#define VECTOR_CLASS cl::vector 
658

659
#if !defined(__MAX_DEFAULT_VECTOR_SIZE)
660
#define __MAX_DEFAULT_VECTOR_SIZE 10
661
#endif
662

663
/*! \class vector
664
 * \brief Fixed sized vector implementation that mirroring 
665
 *
666
 *  \note Deprecated. Please use std::vector as default or
667
 *  re-define the vector class to match the std::vector
668
 *  interface by defining VECTOR_CLASS
669

670
 *  \note Not recommended for use with custom objects as
671
 *  current implementation will construct N elements
672
 *
673
 * std::vector functionality.
674
 *  \brief Fixed sized vector compatible with std::vector.
675
 *
676
 *  \note
677
 *  This differs from std::vector<> not just in memory allocation,
678
 *  but also in terms of when members are constructed, destroyed,
679
 *  and assigned instead of being copy constructed.
680
 *
681
 *  \param T type of element contained in the vector.
682
 *
683
 *  \param N maximum size of the vector.
684
 */
685
template <typename T, unsigned int N = __MAX_DEFAULT_VECTOR_SIZE>
686
class CL_EXT_PREFIX__VERSION_1_1_DEPRECATED vector
687
{
688
private:
689
    T data_[N];
690
    unsigned int size_;
691

692
public:
693
    //! \brief Constructs an empty vector with no memory allocated.
694
    vector() :  
695
        size_(static_cast<unsigned int>(0))
696
    {}
697

698
    //! \brief Deallocates the vector's memory and destroys all of its elements.
699
    ~vector() 
700
    {
701
        clear();
702
    }
703

704
    //! \brief Returns the number of elements currently contained.
705
    unsigned int size(void) const
706
    {
707
        return size_;
708
    }
709
    
710
    /*! \brief Empties the vector of all elements.
711
     *  \note
712
     *  This does not deallocate memory but will invoke destructors
713
     *  on contained elements.
714
     */
715
    void clear()
716
    {
717
        while(!empty()) {
718
            pop_back();
719
        }
720
    }
721

722
    /*! \brief Appends an element after the last valid element.
723
     * Calling this on a vector that has reached capacity will throw an 
724
     * exception if exceptions are enabled.
725
     */
726
    void push_back (const T& x)
727
    { 
728
        if (size() < N) {
729
            new (&data_[size_]) T(x);
730
            size_++;
731
        } else {
732
            detail::errHandler(CL_MEM_OBJECT_ALLOCATION_FAILURE, __VECTOR_CAPACITY_ERR);
733
        }
734
    }
735

736
    /*! \brief Removes the last valid element from the vector.
737
     * Calling this on an empty vector will throw an exception
738
     * if exceptions are enabled.
739
     */
740
    void pop_back(void)
741
    {
742
        if (size_ != 0) {
743
            --size_;
744
            data_[size_].~T();
745
        } else {
746
            detail::errHandler(CL_MEM_OBJECT_ALLOCATION_FAILURE, __VECTOR_CAPACITY_ERR);
747
        }
748
    }
749

750
    /*! \brief Constructs with a value copied from another.
751
     *
752
     *  \param vec the vector to copy.
753
     */
754
    vector(const vector<T, N>& vec) : 
755
        size_(vec.size_)
756
    {
757
        if (size_ != 0) {
758
            assign(vec.begin(), vec.end());
759
        }
760
    } 
761

762
    /*! \brief Constructs with a specified number of initial elements.
763
     *
764
     *  \param size number of initial elements.
765
     *
766
     *  \param val value of initial elements.
767
     */
768
    vector(unsigned int size, const T& val = T()) :
769
        size_(0)
770
    {
771
        for (unsigned int i = 0; i < size; i++) {
772
            push_back(val);
773
        }
774
    }
775

776
    /*! \brief Overwrites the current content with that copied from another
777
     *         instance.
778
     *
779
     *  \param rhs vector to copy.
780
     *
781
     *  \returns a reference to this.
782
     */
783
    vector<T, N>& operator=(const vector<T, N>& rhs)
784
    {
785
        if (this == &rhs) {
786
            return *this;
787
        }
788

789
        if (rhs.size_ != 0) {	
790
            assign(rhs.begin(), rhs.end());
791
        } else {
792
            clear();
793
        }
794

795
        return *this;
796
    }
797

798
    /*! \brief Tests equality against another instance.
799
     *
800
     *  \param vec the vector against which to compare.
801
     */
802
    bool operator==(vector<T,N> &vec)
803
    {
804
        if (size() != vec.size()) {
805
            return false;
806
        }
807

808
        for( unsigned int i = 0; i < size(); ++i ) {
809
            if( operator[](i) != vec[i] ) {
810
                return false;
811
            }
812
        }
813
        return true;
814
    }
815
  
816
    //! \brief Conversion operator to T*.
817
    operator T* ()             { return data_; }
818

819
    //! \brief Conversion operator to const T*.
820
    operator const T* () const { return data_; }
821
   
822
    //! \brief Tests whether this instance has any elements.
823
    bool empty (void) const
824
    {
825
        return size_==0;
826
    }
827
  
828
    //! \brief Returns the maximum number of elements this instance can hold.
829
    unsigned int max_size (void) const
830
    {
831
        return N;
832
    }
833

834
    //! \brief Returns the maximum number of elements this instance can hold.
835
    unsigned int capacity () const
836
    {
837
        return N;
838
    }
839

840
    //! \brief Resizes the vector to the given size
841
    void resize(unsigned int newSize, T fill = T())
842
    {
843
        if (newSize > N)
844
        {
845
            detail::errHandler(CL_MEM_OBJECT_ALLOCATION_FAILURE, __VECTOR_CAPACITY_ERR);
846
        }
847
        else
848
        {
849
            while (size_ < newSize)
850
            {
851
                new (&data_[size_]) T(fill);
852
                size_++;
853
            }
854
            while (size_ > newSize)
855
            {
856
                --size_;
857
                data_[size_].~T();
858
            }
859
        }
860
    }
861

862
    /*! \brief Returns a reference to a given element.
863
     *
864
     *  \param index which element to access.     *
865
     *  \note
866
     *  The caller is responsible for ensuring index is >= 0 and < size().
867
     */
868
    T& operator[](int index)
869
    {
870
        return data_[index];
871
    }
872
  
873
    /*! \brief Returns a const reference to a given element.
874
     *
875
     *  \param index which element to access.
876
     *
877
     *  \note
878
     *  The caller is responsible for ensuring index is >= 0 and < size().
879
     */
880
    const T& operator[](int index) const
881
    {
882
        return data_[index];
883
    }
884
  
885
    /*! \brief Assigns elements of the vector based on a source iterator range.
886
     *
887
     *  \param start Beginning iterator of source range
888
     *  \param end Enditerator of source range
889
     *
890
     *  \note
891
     *  Will throw an exception if exceptions are enabled and size exceeded.
892
     */
893
    template<class I>
894
    void assign(I start, I end)
895
    {
896
        clear();   
897
        while(start != end) {
898
            push_back(*start);
899
            start++;
900
        }
901
    }
902

903
    /*! \class iterator
904
     * \brief Const iterator class for vectors
905
     */
906
    class iterator
907
    {
908
    private:
909
        const vector<T,N> *vec_;
910
        int index_;
911

912
        /**
913
         * Internal iterator constructor to capture reference
914
         * to the vector it iterates over rather than taking 
915
         * the vector by copy.
916
         */
917
        iterator (const vector<T,N> &vec, int index) :
918
            vec_(&vec)
919
        {            
920
            if( !vec.empty() ) {
921
                index_ = index;
922
            } else {
923
                index_ = -1;
924
            }
925
        }
926

927
    public:
928
        iterator(void) : 
929
            index_(-1),
930
            vec_(NULL)
931
        {
932
        }
933

934
        iterator(const iterator& rhs) :
935
            vec_(rhs.vec_),
936
            index_(rhs.index_)
937
        {
938
        }
939

940
        ~iterator(void) {}
941

942
        static iterator begin(const cl::vector<T,N> &vec)
943
        {
944
            iterator i(vec, 0);
945

946
            return i;
947
        }
948

949
        static iterator end(const cl::vector<T,N> &vec)
950
        {
951
            iterator i(vec, vec.size());
952

953
            return i;
954
        }
955
    
956
        bool operator==(iterator i)
957
        {
958
            return ((vec_ == i.vec_) && 
959
                    (index_ == i.index_));
960
        }
961

962
        bool operator!=(iterator i)
963
        {
964
            return (!(*this==i));
965
        }
966

967
        iterator& operator++()
968
        {
969
            ++index_;
970
            return *this;
971
        }
972

973
        iterator operator++(int)
974
        {
975
            iterator retVal(*this);
976
            ++index_;
977
            return retVal;
978
        }
979

980
        iterator& operator--()
981
        {
982
            --index_;
983
            return *this;
984
        }
985

986
        iterator operator--(int)
987
        {
988
            iterator retVal(*this);
989
            --index_;
990
            return retVal;
991
        }
992

993
        const T& operator *() const
994
        {
995
            return (*vec_)[index_];
996
        }
997
    };
998

999
    iterator begin(void)
1000
    {
1001
        return iterator::begin(*this);
1002
    }
1003

1004
    iterator begin(void) const
1005
    {
1006
        return iterator::begin(*this);
1007
    }
1008

1009
    iterator end(void)
1010
    {
1011
        return iterator::end(*this);
1012
    }
1013

1014
    iterator end(void) const
1015
    {
1016
        return iterator::end(*this);
1017
    }
1018

1019
    T& front(void)
1020
    {
1021
        return data_[0];
1022
    }
1023

1024
    T& back(void)
1025
    {
1026
        return data_[size_];
1027
    }
1028

1029
    const T& front(void) const
1030
    {
1031
        return data_[0];
1032
    }
1033

1034
    const T& back(void) const
1035
    {
1036
        return data_[size_-1];
1037
    }
1038
} CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED;
1039
#endif // #if !defined(__USE_DEV_VECTOR) && !defined(__NO_STD_VECTOR)
1040

1041

1042

1043

1044

1045
namespace detail {
1046
#define __DEFAULT_NOT_INITIALIZED 1 
1047
#define __DEFAULT_BEING_INITIALIZED 2
1048
#define __DEFAULT_INITIALIZED 4
1049

1050
    /*
1051
     * Compare and exchange primitives are needed for handling of defaults
1052
    */
1053

1054
#ifdef CL_HPP_CPP11_ATOMICS_SUPPORTED
1055
    inline int compare_exchange(std::atomic<int> * dest, int exchange, int comparand)
1056
#else // !CL_HPP_CPP11_ATOMICS_SUPPORTED
1057
    inline int compare_exchange(volatile int * dest, int exchange, int comparand)
1058
#endif // !CL_HPP_CPP11_ATOMICS_SUPPORTED
1059
    {
1060
#ifdef CL_HPP_CPP11_ATOMICS_SUPPORTED
1061
        std::atomic_compare_exchange_strong(dest, &comparand, exchange);
1062
        return comparand;
1063
#elif _MSC_VER
1064
        return (int)(_InterlockedCompareExchange(
1065
            (volatile long*)dest,
1066
            (long)exchange,
1067
            (long)comparand));
1068
#else // !_MSC_VER && !CL_HPP_CPP11_ATOMICS_SUPPORTED
1069
        return (__sync_val_compare_and_swap(
1070
            dest,
1071
            comparand,
1072
            exchange));
1073
#endif // !CL_HPP_CPP11_ATOMICS_SUPPORTED
1074
    }
1075

1076
    inline void fence() {
1077
#ifdef CL_HPP_CPP11_ATOMICS_SUPPORTED
1078
        std::atomic_thread_fence(std::memory_order_seq_cst);
1079
#elif _MSC_VER // !CL_HPP_CPP11_ATOMICS_SUPPORTED
1080
        _ReadWriteBarrier();
1081
#else // !_MSC_VER && !CL_HPP_CPP11_ATOMICS_SUPPORTED
1082
        __sync_synchronize();
1083
#endif // !CL_HPP_CPP11_ATOMICS_SUPPORTED
1084
    }
1085
} // namespace detail
1086

1087
    
1088
/*! \brief class used to interface between C++ and
1089
 *  OpenCL C calls that require arrays of size_t values, whose
1090
 *  size is known statically.
1091
 */
1092
template <int N>
1093
class size_t
1094
{ 
1095
private:
1096
    ::size_t data_[N];
1097

1098
public:
1099
    //! \brief Initialize size_t to all 0s
1100
    size_t()
1101
    {
1102 0
        for( int i = 0; i < N; ++i ) {
1103 0
            data_[i] = 0;
1104
        }
1105
    }
1106

1107
    ::size_t& operator[](int index)
1108
    {
1109
        return data_[index];
1110
    }
1111

1112
    const ::size_t& operator[](int index) const
1113
    {
1114
        return data_[index];
1115
    }
1116

1117
    //! \brief Conversion operator to T*.
1118
    operator ::size_t* ()             { return data_; }
1119

1120
    //! \brief Conversion operator to const T*.
1121
    operator const ::size_t* () const { return data_; }
1122
};
1123

1124
namespace detail {
1125

1126
// Generic getInfoHelper. The final parameter is used to guide overload
1127
// resolution: the actual parameter passed is an int, which makes this
1128
// a worse conversion sequence than a specialization that declares the
1129
// parameter as an int.
1130
template<typename Functor, typename T>
1131
inline cl_int getInfoHelper(Functor f, cl_uint name, T* param, long)
1132
{
1133 0
    return f(name, sizeof(T), param, NULL);
1134
}
1135

1136
// Specialized getInfoHelper for VECTOR_CLASS params
1137
template <typename Func, typename T>
1138
inline cl_int getInfoHelper(Func f, cl_uint name, VECTOR_CLASS<T>* param, long)
1139
{
1140
    ::size_t required;
1141
    cl_int err = f(name, 0, NULL, &required);
1142
    if (err != CL_SUCCESS) {
1143
        return err;
1144
    }
1145

1146
    T* value = (T*) alloca(required);
1147
    err = f(name, required, value, NULL);
1148
    if (err != CL_SUCCESS) {
1149
        return err;
1150
    }
1151

1152
    param->assign(&value[0], &value[required/sizeof(T)]);
1153
    return CL_SUCCESS;
1154
}
1155

1156
/* Specialization for reference-counted types. This depends on the
1157
 * existence of Wrapper<T>::cl_type, and none of the other types having the
1158
 * cl_type member. Note that simplify specifying the parameter as Wrapper<T>
1159
 * does not work, because when using a derived type (e.g. Context) the generic
1160
 * template will provide a better match.
1161
 */
1162
template <typename Func, typename T>
1163
inline cl_int getInfoHelper(Func f, cl_uint name, VECTOR_CLASS<T>* param, int, typename T::cl_type = 0)
1164
{
1165
    ::size_t required;
1166
    cl_int err = f(name, 0, NULL, &required);
1167
    if (err != CL_SUCCESS) {
1168
        return err;
1169
    }
1170

1171
    typename T::cl_type * value = (typename T::cl_type *) alloca(required);
1172
    err = f(name, required, value, NULL);
1173
    if (err != CL_SUCCESS) {
1174
        return err;
1175
    }
1176

1177
    ::size_t elements = required / sizeof(typename T::cl_type);
1178
    param->assign(&value[0], &value[elements]);
1179
    for (::size_t i = 0; i < elements; i++)
1180
    {
1181
        if (value[i] != NULL)
1182
        {
1183
            err = (*param)[i].retain();
1184
            if (err != CL_SUCCESS) {
1185
                return err;
1186
            }
1187
        }
1188
    }
1189
    return CL_SUCCESS;
1190
}
1191

1192
// Specialized for getInfo<CL_PROGRAM_BINARIES>
1193
template <typename Func>
1194
inline cl_int getInfoHelper(Func f, cl_uint name, VECTOR_CLASS<char *>* param, int)
1195
{
1196
    cl_int err = f(name, param->size() * sizeof(char *), &(*param)[0], NULL);
1197

1198
    if (err != CL_SUCCESS) {
1199
        return err;
1200
    }
1201

1202
    return CL_SUCCESS;
1203
}
1204

1205
// Specialized GetInfoHelper for STRING_CLASS params
1206
template <typename Func>
1207
inline cl_int getInfoHelper(Func f, cl_uint name, STRING_CLASS* param, long)
1208
{
1209
#if defined(__NO_STD_VECTOR) || defined(__NO_STD_STRING)
1210
    ::size_t required;
1211
    cl_int err = f(name, 0, NULL, &required);
1212
    if (err != CL_SUCCESS) {
1213
        return err;
1214
    }
1215

1216
    char* value = (char*)alloca(required);
1217
    err = f(name, required, value, NULL);
1218
    if (err != CL_SUCCESS) {
1219
        return err;
1220
    }
1221

1222
    *param = value;
1223
    return CL_SUCCESS;
1224
#else 
1225
    ::size_t required;
1226 0
    cl_int err = f(name, 0, NULL, &required);
1227 0
    if (err != CL_SUCCESS) {
1228 0
        return err;
1229
    }
1230

1231
    // std::string has a constant data member
1232
    // a char vector does not
1233 0
    VECTOR_CLASS<char> value(required);
1234 0
    err = f(name, required, value.data(), NULL);
1235 0
    if (err != CL_SUCCESS) {
1236 0
        return err;
1237
    }
1238 0
    if (param) {
1239 0
        param->assign(value.begin(), value.end());
1240
    }
1241
#endif
1242 0
    return CL_SUCCESS;
1243
}
1244

1245
// Specialized GetInfoHelper for cl::size_t params
1246
template <typename Func, ::size_t N>
1247
inline cl_int getInfoHelper(Func f, cl_uint name, size_t<N>* param, long)
1248
{
1249
    ::size_t required;
1250
    cl_int err = f(name, 0, NULL, &required);
1251
    if (err != CL_SUCCESS) {
1252
        return err;
1253
    }
1254

1255
    ::size_t* value = (::size_t*) alloca(required);
1256
    err = f(name, required, value, NULL);
1257
    if (err != CL_SUCCESS) {
1258
        return err;
1259
    }
1260

1261
    for(int i = 0; i < N; ++i) {
1262
        (*param)[i] = value[i];
1263
    }
1264

1265
    return CL_SUCCESS;
1266
}
1267

1268
template<typename T> struct ReferenceHandler;
1269

1270
/* Specialization for reference-counted types. This depends on the
1271
 * existence of Wrapper<T>::cl_type, and none of the other types having the
1272
 * cl_type member. Note that simplify specifying the parameter as Wrapper<T>
1273
 * does not work, because when using a derived type (e.g. Context) the generic
1274
 * template will provide a better match.
1275
 */
1276
template<typename Func, typename T>
1277
inline cl_int getInfoHelper(Func f, cl_uint name, T* param, int, typename T::cl_type = 0)
1278
{
1279
    typename T::cl_type value;
1280 0
    cl_int err = f(name, sizeof(value), &value, NULL);
1281 0
    if (err != CL_SUCCESS) {
1282 0
        return err;
1283
    }
1284 0
    *param = value;
1285 0
    if (value != NULL)
1286
    {
1287 0
        err = param->retain();
1288 0
        if (err != CL_SUCCESS) {
1289 0
            return err;
1290
        }
1291
    }
1292 0
    return CL_SUCCESS;
1293
}
1294

1295
#define __PARAM_NAME_INFO_1_0(F) \
1296
    F(cl_platform_info, CL_PLATFORM_PROFILE, STRING_CLASS) \
1297
    F(cl_platform_info, CL_PLATFORM_VERSION, STRING_CLASS) \
1298
    F(cl_platform_info, CL_PLATFORM_NAME, STRING_CLASS) \
1299
    F(cl_platform_info, CL_PLATFORM_VENDOR, STRING_CLASS) \
1300
    F(cl_platform_info, CL_PLATFORM_EXTENSIONS, STRING_CLASS) \
1301
    \
1302
    F(cl_device_info, CL_DEVICE_TYPE, cl_device_type) \
1303
    F(cl_device_info, CL_DEVICE_VENDOR_ID, cl_uint) \
1304
    F(cl_device_info, CL_DEVICE_MAX_COMPUTE_UNITS, cl_uint) \
1305
    F(cl_device_info, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, cl_uint) \
1306
    F(cl_device_info, CL_DEVICE_MAX_WORK_GROUP_SIZE, ::size_t) \
1307
    F(cl_device_info, CL_DEVICE_MAX_WORK_ITEM_SIZES, VECTOR_CLASS< ::size_t>) \
1308
    F(cl_device_info, CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR, cl_uint) \
1309
    F(cl_device_info, CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT, cl_uint) \
1310
    F(cl_device_info, CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT, cl_uint) \
1311
    F(cl_device_info, CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG, cl_uint) \
1312
    F(cl_device_info, CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT, cl_uint) \
1313
    F(cl_device_info, CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE, cl_uint) \
1314
    F(cl_device_info, CL_DEVICE_MAX_CLOCK_FREQUENCY, cl_uint) \
1315
    F(cl_device_info, CL_DEVICE_ADDRESS_BITS, cl_uint) \
1316
    F(cl_device_info, CL_DEVICE_MAX_READ_IMAGE_ARGS, cl_uint) \
1317
    F(cl_device_info, CL_DEVICE_MAX_WRITE_IMAGE_ARGS, cl_uint) \
1318
    F(cl_device_info, CL_DEVICE_MAX_MEM_ALLOC_SIZE, cl_ulong) \
1319
    F(cl_device_info, CL_DEVICE_IMAGE2D_MAX_WIDTH, ::size_t) \
1320
    F(cl_device_info, CL_DEVICE_IMAGE2D_MAX_HEIGHT, ::size_t) \
1321
    F(cl_device_info, CL_DEVICE_IMAGE3D_MAX_WIDTH, ::size_t) \
1322
    F(cl_device_info, CL_DEVICE_IMAGE3D_MAX_HEIGHT, ::size_t) \
1323
    F(cl_device_info, CL_DEVICE_IMAGE3D_MAX_DEPTH, ::size_t) \
1324
    F(cl_device_info, CL_DEVICE_IMAGE_SUPPORT, cl_bool) \
1325
    F(cl_device_info, CL_DEVICE_MAX_PARAMETER_SIZE, ::size_t) \
1326
    F(cl_device_info, CL_DEVICE_MAX_SAMPLERS, cl_uint) \
1327
    F(cl_device_info, CL_DEVICE_MEM_BASE_ADDR_ALIGN, cl_uint) \
1328
    F(cl_device_info, CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE, cl_uint) \
1329
    F(cl_device_info, CL_DEVICE_SINGLE_FP_CONFIG, cl_device_fp_config) \
1330
    F(cl_device_info, CL_DEVICE_GLOBAL_MEM_CACHE_TYPE, cl_device_mem_cache_type) \
1331
    F(cl_device_info, CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE, cl_uint)\
1332
    F(cl_device_info, CL_DEVICE_GLOBAL_MEM_CACHE_SIZE, cl_ulong) \
1333
    F(cl_device_info, CL_DEVICE_GLOBAL_MEM_SIZE, cl_ulong) \
1334
    F(cl_device_info, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE, cl_ulong) \
1335
    F(cl_device_info, CL_DEVICE_MAX_CONSTANT_ARGS, cl_uint) \
1336
    F(cl_device_info, CL_DEVICE_LOCAL_MEM_TYPE, cl_device_local_mem_type) \
1337
    F(cl_device_info, CL_DEVICE_LOCAL_MEM_SIZE, cl_ulong) \
1338
    F(cl_device_info, CL_DEVICE_ERROR_CORRECTION_SUPPORT, cl_bool) \
1339
    F(cl_device_info, CL_DEVICE_PROFILING_TIMER_RESOLUTION, ::size_t) \
1340
    F(cl_device_info, CL_DEVICE_ENDIAN_LITTLE, cl_bool) \
1341
    F(cl_device_info, CL_DEVICE_AVAILABLE, cl_bool) \
1342
    F(cl_device_info, CL_DEVICE_COMPILER_AVAILABLE, cl_bool) \
1343
    F(cl_device_info, CL_DEVICE_EXECUTION_CAPABILITIES, cl_device_exec_capabilities) \
1344
    F(cl_device_info, CL_DEVICE_QUEUE_PROPERTIES, cl_command_queue_properties) \
1345
    F(cl_device_info, CL_DEVICE_PLATFORM, cl_platform_id) \
1346
    F(cl_device_info, CL_DEVICE_NAME, STRING_CLASS) \
1347
    F(cl_device_info, CL_DEVICE_VENDOR, STRING_CLASS) \
1348
    F(cl_device_info, CL_DRIVER_VERSION, STRING_CLASS) \
1349
    F(cl_device_info, CL_DEVICE_PROFILE, STRING_CLASS) \
1350
    F(cl_device_info, CL_DEVICE_VERSION, STRING_CLASS) \
1351
    F(cl_device_info, CL_DEVICE_EXTENSIONS, STRING_CLASS) \
1352
    \
1353
    F(cl_context_info, CL_CONTEXT_REFERENCE_COUNT, cl_uint) \
1354
    F(cl_context_info, CL_CONTEXT_DEVICES, VECTOR_CLASS<Device>) \
1355
    F(cl_context_info, CL_CONTEXT_PROPERTIES, VECTOR_CLASS<cl_context_properties>) \
1356
    \
1357
    F(cl_event_info, CL_EVENT_COMMAND_QUEUE, cl::CommandQueue) \
1358
    F(cl_event_info, CL_EVENT_COMMAND_TYPE, cl_command_type) \
1359
    F(cl_event_info, CL_EVENT_REFERENCE_COUNT, cl_uint) \
1360
    F(cl_event_info, CL_EVENT_COMMAND_EXECUTION_STATUS, cl_int) \
1361
    \
1362
    F(cl_profiling_info, CL_PROFILING_COMMAND_QUEUED, cl_ulong) \
1363
    F(cl_profiling_info, CL_PROFILING_COMMAND_SUBMIT, cl_ulong) \
1364
    F(cl_profiling_info, CL_PROFILING_COMMAND_START, cl_ulong) \
1365
    F(cl_profiling_info, CL_PROFILING_COMMAND_END, cl_ulong) \
1366
    \
1367
    F(cl_mem_info, CL_MEM_TYPE, cl_mem_object_type) \
1368
    F(cl_mem_info, CL_MEM_FLAGS, cl_mem_flags) \
1369
    F(cl_mem_info, CL_MEM_SIZE, ::size_t) \
1370
    F(cl_mem_info, CL_MEM_HOST_PTR, void*) \
1371
    F(cl_mem_info, CL_MEM_MAP_COUNT, cl_uint) \
1372
    F(cl_mem_info, CL_MEM_REFERENCE_COUNT, cl_uint) \
1373
    F(cl_mem_info, CL_MEM_CONTEXT, cl::Context) \
1374
    \
1375
    F(cl_image_info, CL_IMAGE_FORMAT, cl_image_format) \
1376
    F(cl_image_info, CL_IMAGE_ELEMENT_SIZE, ::size_t) \
1377
    F(cl_image_info, CL_IMAGE_ROW_PITCH, ::size_t) \
1378
    F(cl_image_info, CL_IMAGE_SLICE_PITCH, ::size_t) \
1379
    F(cl_image_info, CL_IMAGE_WIDTH, ::size_t) \
1380
    F(cl_image_info, CL_IMAGE_HEIGHT, ::size_t) \
1381
    F(cl_image_info, CL_IMAGE_DEPTH, ::size_t) \
1382
    \
1383
    F(cl_sampler_info, CL_SAMPLER_REFERENCE_COUNT, cl_uint) \
1384
    F(cl_sampler_info, CL_SAMPLER_CONTEXT, cl::Context) \
1385
    F(cl_sampler_info, CL_SAMPLER_NORMALIZED_COORDS, cl_bool) \
1386
    F(cl_sampler_info, CL_SAMPLER_ADDRESSING_MODE, cl_addressing_mode) \
1387
    F(cl_sampler_info, CL_SAMPLER_FILTER_MODE, cl_filter_mode) \
1388
    \
1389
    F(cl_program_info, CL_PROGRAM_REFERENCE_COUNT, cl_uint) \
1390
    F(cl_program_info, CL_PROGRAM_CONTEXT, cl::Context) \
1391
    F(cl_program_info, CL_PROGRAM_NUM_DEVICES, cl_uint) \
1392
    F(cl_program_info, CL_PROGRAM_DEVICES, VECTOR_CLASS<Device>) \
1393
    F(cl_program_info, CL_PROGRAM_SOURCE, STRING_CLASS) \
1394
    F(cl_program_info, CL_PROGRAM_BINARY_SIZES, VECTOR_CLASS< ::size_t>) \
1395
    F(cl_program_info, CL_PROGRAM_BINARIES, VECTOR_CLASS<char *>) \
1396
    \
1397
    F(cl_program_build_info, CL_PROGRAM_BUILD_STATUS, cl_build_status) \
1398
    F(cl_program_build_info, CL_PROGRAM_BUILD_OPTIONS, STRING_CLASS) \
1399
    F(cl_program_build_info, CL_PROGRAM_BUILD_LOG, STRING_CLASS) \
1400
    \
1401
    F(cl_kernel_info, CL_KERNEL_FUNCTION_NAME, STRING_CLASS) \
1402
    F(cl_kernel_info, CL_KERNEL_NUM_ARGS, cl_uint) \
1403
    F(cl_kernel_info, CL_KERNEL_REFERENCE_COUNT, cl_uint) \
1404
    F(cl_kernel_info, CL_KERNEL_CONTEXT, cl::Context) \
1405
    F(cl_kernel_info, CL_KERNEL_PROGRAM, cl::Program) \
1406
    \
1407
    F(cl_kernel_work_group_info, CL_KERNEL_WORK_GROUP_SIZE, ::size_t) \
1408
    F(cl_kernel_work_group_info, CL_KERNEL_COMPILE_WORK_GROUP_SIZE, cl::size_t<3>) \
1409
    F(cl_kernel_work_group_info, CL_KERNEL_LOCAL_MEM_SIZE, cl_ulong) \
1410
    \
1411
    F(cl_command_queue_info, CL_QUEUE_CONTEXT, cl::Context) \
1412
    F(cl_command_queue_info, CL_QUEUE_DEVICE, cl::Device) \
1413
    F(cl_command_queue_info, CL_QUEUE_REFERENCE_COUNT, cl_uint) \
1414
    F(cl_command_queue_info, CL_QUEUE_PROPERTIES, cl_command_queue_properties)
1415

1416
#if defined(CL_VERSION_1_1)
1417
#define __PARAM_NAME_INFO_1_1(F) \
1418
    F(cl_context_info, CL_CONTEXT_NUM_DEVICES, cl_uint)\
1419
    F(cl_device_info, CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF, cl_uint) \
1420
    F(cl_device_info, CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR, cl_uint) \
1421
    F(cl_device_info, CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT, cl_uint) \
1422
    F(cl_device_info, CL_DEVICE_NATIVE_VECTOR_WIDTH_INT, cl_uint) \
1423
    F(cl_device_info, CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG, cl_uint) \
1424
    F(cl_device_info, CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT, cl_uint) \
1425
    F(cl_device_info, CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE, cl_uint) \
1426
    F(cl_device_info, CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF, cl_uint) \
1427
    F(cl_device_info, CL_DEVICE_DOUBLE_FP_CONFIG, cl_device_fp_config) \
1428
    F(cl_device_info, CL_DEVICE_HALF_FP_CONFIG, cl_device_fp_config) \
1429
    F(cl_device_info, CL_DEVICE_HOST_UNIFIED_MEMORY, cl_bool) \
1430
    F(cl_device_info, CL_DEVICE_OPENCL_C_VERSION, STRING_CLASS) \
1431
    \
1432
    F(cl_mem_info, CL_MEM_ASSOCIATED_MEMOBJECT, cl::Memory) \
1433
    F(cl_mem_info, CL_MEM_OFFSET, ::size_t) \
1434
    \
1435
    F(cl_kernel_work_group_info, CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE, ::size_t) \
1436
    F(cl_kernel_work_group_info, CL_KERNEL_PRIVATE_MEM_SIZE, cl_ulong) \
1437
    \
1438
    F(cl_event_info, CL_EVENT_CONTEXT, cl::Context)
1439
#endif // CL_VERSION_1_1
1440

1441
    
1442
#if defined(CL_VERSION_1_2)
1443
#define __PARAM_NAME_INFO_1_2(F) \
1444
    F(cl_image_info, CL_IMAGE_BUFFER, cl::Buffer) \
1445
    \
1446
    F(cl_program_info, CL_PROGRAM_NUM_KERNELS, ::size_t) \
1447
    F(cl_program_info, CL_PROGRAM_KERNEL_NAMES, STRING_CLASS) \
1448
    \
1449
    F(cl_program_build_info, CL_PROGRAM_BINARY_TYPE, cl_program_binary_type) \
1450
    \
1451
    F(cl_kernel_info, CL_KERNEL_ATTRIBUTES, STRING_CLASS) \
1452
    \
1453
    F(cl_kernel_arg_info, CL_KERNEL_ARG_ADDRESS_QUALIFIER, cl_kernel_arg_address_qualifier) \
1454
    F(cl_kernel_arg_info, CL_KERNEL_ARG_ACCESS_QUALIFIER, cl_kernel_arg_access_qualifier) \
1455
    F(cl_kernel_arg_info, CL_KERNEL_ARG_TYPE_NAME, STRING_CLASS) \
1456
    F(cl_kernel_arg_info, CL_KERNEL_ARG_NAME, STRING_CLASS) \
1457
    F(cl_kernel_arg_info, CL_KERNEL_ARG_TYPE_QUALIFIER, cl_kernel_arg_type_qualifier) \
1458
    \
1459
    F(cl_device_info, CL_DEVICE_PARENT_DEVICE, cl_device_id) \
1460
    F(cl_device_info, CL_DEVICE_PARTITION_PROPERTIES, VECTOR_CLASS<cl_device_partition_property>) \
1461
    F(cl_device_info, CL_DEVICE_PARTITION_TYPE, VECTOR_CLASS<cl_device_partition_property>)  \
1462
    F(cl_device_info, CL_DEVICE_REFERENCE_COUNT, cl_uint) \
1463
    F(cl_device_info, CL_DEVICE_PREFERRED_INTEROP_USER_SYNC, ::size_t) \
1464
    F(cl_device_info, CL_DEVICE_PARTITION_AFFINITY_DOMAIN, cl_device_affinity_domain) \
1465
    F(cl_device_info, CL_DEVICE_BUILT_IN_KERNELS, STRING_CLASS)
1466
#endif // #if defined(CL_VERSION_1_2)
1467

1468
#if defined(USE_CL_DEVICE_FISSION)
1469
#define __PARAM_NAME_DEVICE_FISSION(F) \
1470
    F(cl_device_info, CL_DEVICE_PARENT_DEVICE_EXT, cl_device_id) \
1471
    F(cl_device_info, CL_DEVICE_PARTITION_TYPES_EXT, VECTOR_CLASS<cl_device_partition_property_ext>) \
1472
    F(cl_device_info, CL_DEVICE_AFFINITY_DOMAINS_EXT, VECTOR_CLASS<cl_device_partition_property_ext>) \
1473
    F(cl_device_info, CL_DEVICE_REFERENCE_COUNT_EXT , cl_uint) \
1474
    F(cl_device_info, CL_DEVICE_PARTITION_STYLE_EXT, VECTOR_CLASS<cl_device_partition_property_ext>)
1475
#endif // USE_CL_DEVICE_FISSION
1476

1477
template <typename enum_type, cl_int Name>
1478
struct param_traits {};
1479

1480
#define __CL_DECLARE_PARAM_TRAITS(token, param_name, T) \
1481
struct token;                                        \
1482
template<>                                           \
1483
struct param_traits<detail:: token,param_name>       \
1484
{                                                    \
1485
    enum { value = param_name };                     \
1486
    typedef T param_type;                            \
1487
};
1488

1489
__PARAM_NAME_INFO_1_0(__CL_DECLARE_PARAM_TRAITS)
1490
#if defined(CL_VERSION_1_1)
1491
__PARAM_NAME_INFO_1_1(__CL_DECLARE_PARAM_TRAITS)
1492
#endif // CL_VERSION_1_1
1493
#if defined(CL_VERSION_1_2)
1494
__PARAM_NAME_INFO_1_2(__CL_DECLARE_PARAM_TRAITS)
1495
#endif // CL_VERSION_1_1
1496

1497
#if defined(USE_CL_DEVICE_FISSION)
1498
__PARAM_NAME_DEVICE_FISSION(__CL_DECLARE_PARAM_TRAITS);
1499
#endif // USE_CL_DEVICE_FISSION
1500

1501
#ifdef CL_PLATFORM_ICD_SUFFIX_KHR
1502
__CL_DECLARE_PARAM_TRAITS(cl_platform_info, CL_PLATFORM_ICD_SUFFIX_KHR, STRING_CLASS)
1503
#endif
1504

1505
#ifdef CL_DEVICE_PROFILING_TIMER_OFFSET_AMD
1506
__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_PROFILING_TIMER_OFFSET_AMD, cl_ulong)
1507
#endif
1508

1509
#ifdef CL_DEVICE_GLOBAL_FREE_MEMORY_AMD
1510
__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_GLOBAL_FREE_MEMORY_AMD, VECTOR_CLASS< ::size_t>)
1511
#endif
1512
#ifdef CL_DEVICE_SIMD_PER_COMPUTE_UNIT_AMD
1513
__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_SIMD_PER_COMPUTE_UNIT_AMD, cl_uint)
1514
#endif
1515
#ifdef CL_DEVICE_SIMD_WIDTH_AMD
1516
__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_SIMD_WIDTH_AMD, cl_uint)
1517
#endif
1518
#ifdef CL_DEVICE_SIMD_INSTRUCTION_WIDTH_AMD
1519
__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_SIMD_INSTRUCTION_WIDTH_AMD, cl_uint)
1520
#endif
1521
#ifdef CL_DEVICE_WAVEFRONT_WIDTH_AMD
1522
__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_WAVEFRONT_WIDTH_AMD, cl_uint)
1523
#endif
1524
#ifdef CL_DEVICE_GLOBAL_MEM_CHANNELS_AMD
1525
__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_GLOBAL_MEM_CHANNELS_AMD, cl_uint)
1526
#endif
1527
#ifdef CL_DEVICE_GLOBAL_MEM_CHANNEL_BANKS_AMD
1528
__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_GLOBAL_MEM_CHANNEL_BANKS_AMD, cl_uint)
1529
#endif
1530
#ifdef CL_DEVICE_GLOBAL_MEM_CHANNEL_BANK_WIDTH_AMD
1531
__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_GLOBAL_MEM_CHANNEL_BANK_WIDTH_AMD, cl_uint)
1532
#endif
1533
#ifdef CL_DEVICE_LOCAL_MEM_SIZE_PER_COMPUTE_UNIT_AMD
1534
__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_LOCAL_MEM_SIZE_PER_COMPUTE_UNIT_AMD, cl_uint)
1535
#endif
1536
#ifdef CL_DEVICE_LOCAL_MEM_BANKS_AMD
1537
__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_LOCAL_MEM_BANKS_AMD, cl_uint)
1538
#endif
1539

1540
#ifdef CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV
1541
__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV, cl_uint)
1542
#endif
1543
#ifdef CL_DEVICE_COMPUTE_CAPABILITY_MINOR_NV
1544
__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_COMPUTE_CAPABILITY_MINOR_NV, cl_uint)
1545
#endif
1546
#ifdef CL_DEVICE_REGISTERS_PER_BLOCK_NV
1547
__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_REGISTERS_PER_BLOCK_NV, cl_uint)
1548
#endif
1549
#ifdef CL_DEVICE_WARP_SIZE_NV
1550
__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_WARP_SIZE_NV, cl_uint)
1551
#endif
1552
#ifdef CL_DEVICE_GPU_OVERLAP_NV
1553
__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_GPU_OVERLAP_NV, cl_bool)
1554
#endif
1555
#ifdef CL_DEVICE_KERNEL_EXEC_TIMEOUT_NV
1556
__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_KERNEL_EXEC_TIMEOUT_NV, cl_bool)
1557
#endif
1558
#ifdef CL_DEVICE_INTEGRATED_MEMORY_NV
1559
__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_INTEGRATED_MEMORY_NV, cl_bool)
1560
#endif
1561

1562
// Convenience functions
1563

1564
template <typename Func, typename T>
1565
inline cl_int
1566
getInfo(Func f, cl_uint name, T* param)
1567
{
1568
    return getInfoHelper(f, name, param, 0);
1569
}
1570

1571
template <typename Func, typename Arg0>
1572
struct GetInfoFunctor0
1573
{
1574
    Func f_; const Arg0& arg0_;
1575
    cl_int operator ()(
1576
        cl_uint param, ::size_t size, void* value, ::size_t* size_ret)
1577 0
    { return f_(arg0_, param, size, value, size_ret); }
1578
};
1579

1580
template <typename Func, typename Arg0, typename Arg1>
1581
struct GetInfoFunctor1
1582
{
1583
    Func f_; const Arg0& arg0_; const Arg1& arg1_;
1584
    cl_int operator ()(
1585
        cl_uint param, ::size_t size, void* value, ::size_t* size_ret)
1586
    { return f_(arg0_, arg1_, param, size, value, size_ret); }
1587
};
1588

1589
template <typename Func, typename Arg0, typename T>
1590
inline cl_int
1591
getInfo(Func f, const Arg0& arg0, cl_uint name, T* param)
1592
{
1593 0
    GetInfoFunctor0<Func, Arg0> f0 = { f, arg0 };
1594 0
    return getInfoHelper(f0, name, param, 0);
1595
}
1596

1597
template <typename Func, typename Arg0, typename Arg1, typename T>
1598
inline cl_int
1599
getInfo(Func f, const Arg0& arg0, const Arg1& arg1, cl_uint name, T* param)
1600
{
1601
    GetInfoFunctor1<Func, Arg0, Arg1> f0 = { f, arg0, arg1 };
1602
    return getInfoHelper(f0, name, param, 0);
1603
}
1604

1605
template<typename T>
1606
struct ReferenceHandler
1607
{ };
1608

1609
#if defined(CL_VERSION_1_2)
1610
/**
1611
 * OpenCL 1.2 devices do have retain/release.
1612
 */
1613
template <>
1614
struct ReferenceHandler<cl_device_id>
1615
{
1616
    /**
1617
     * Retain the device.
1618
     * \param device A valid device created using createSubDevices
1619
     * \return 
1620
     *   CL_SUCCESS if the function executed successfully.
1621
     *   CL_INVALID_DEVICE if device was not a valid subdevice
1622
     *   CL_OUT_OF_RESOURCES
1623
     *   CL_OUT_OF_HOST_MEMORY
1624
     */
1625
    static cl_int retain(cl_device_id device)
1626 0
    { return ::clRetainDevice(device); }
1627
    /**
1628
     * Retain the device.
1629
     * \param device A valid device created using createSubDevices
1630
     * \return 
1631
     *   CL_SUCCESS if the function executed successfully.
1632
     *   CL_INVALID_DEVICE if device was not a valid subdevice
1633
     *   CL_OUT_OF_RESOURCES
1634
     *   CL_OUT_OF_HOST_MEMORY
1635
     */
1636
    static cl_int release(cl_device_id device)
1637 0
    { return ::clReleaseDevice(device); }
1638
};
1639
#else // #if defined(CL_VERSION_1_2)
1640
/**
1641
 * OpenCL 1.1 devices do not have retain/release.
1642
 */
1643
template <>
1644
struct ReferenceHandler<cl_device_id>
1645
{
1646
    // cl_device_id does not have retain().
1647
    static cl_int retain(cl_device_id)
1648
    { return CL_SUCCESS; }
1649
    // cl_device_id does not have release().
1650
    static cl_int release(cl_device_id)
1651
    { return CL_SUCCESS; }
1652
};
1653
#endif // #if defined(CL_VERSION_1_2)
1654

1655
template <>
1656
struct ReferenceHandler<cl_platform_id>
1657
{
1658
    // cl_platform_id does not have retain().
1659
    static cl_int retain(cl_platform_id)
1660
    { return CL_SUCCESS; }
1661
    // cl_platform_id does not have release().
1662
    static cl_int release(cl_platform_id)
1663 0
    { return CL_SUCCESS; }
1664
};
1665

1666
template <>
1667
struct ReferenceHandler<cl_context>
1668
{
1669
    static cl_int retain(cl_context context)
1670 0
    { return ::clRetainContext(context); }
1671
    static cl_int release(cl_context context)
1672 0
    { return ::clReleaseContext(context); }
1673
};
1674

1675
template <>
1676
struct ReferenceHandler<cl_command_queue>
1677
{
1678
    static cl_int retain(cl_command_queue queue)
1679 0
    { return ::clRetainCommandQueue(queue); }
1680
    static cl_int release(cl_command_queue queue)
1681 0
    { return ::clReleaseCommandQueue(queue); }
1682
};
1683

1684
template <>
1685
struct ReferenceHandler<cl_mem>
1686
{
1687
    static cl_int retain(cl_mem memory)
1688
    { return ::clRetainMemObject(memory); }
1689
    static cl_int release(cl_mem memory)
1690
    { return ::clReleaseMemObject(memory); }
1691
};
1692

1693
template <>
1694
struct ReferenceHandler<cl_sampler>
1695
{
1696
    static cl_int retain(cl_sampler sampler)
1697
    { return ::clRetainSampler(sampler); }
1698
    static cl_int release(cl_sampler sampler)
1699
    { return ::clReleaseSampler(sampler); }
1700
};
1701

1702
template <>
1703
struct ReferenceHandler<cl_program>
1704
{
1705
    static cl_int retain(cl_program program)
1706
    { return ::clRetainProgram(program); }
1707
    static cl_int release(cl_program program)
1708
    { return ::clReleaseProgram(program); }
1709
};
1710

1711
template <>
1712
struct ReferenceHandler<cl_kernel>
1713
{
1714
    static cl_int retain(cl_kernel kernel)
1715
    { return ::clRetainKernel(kernel); }
1716
    static cl_int release(cl_kernel kernel)
1717
    { return ::clReleaseKernel(kernel); }
1718
};
1719

1720
template <>
1721
struct ReferenceHandler<cl_event>
1722
{
1723
    static cl_int retain(cl_event event)
1724
    { return ::clRetainEvent(event); }
1725
    static cl_int release(cl_event event)
1726
    { return ::clReleaseEvent(event); }
1727
};
1728

1729

1730
// Extracts version number with major in the upper 16 bits, minor in the lower 16
1731
static cl_uint getVersion(const char *versionInfo)
1732
{
1733 0
    int highVersion = 0;
1734 0
    int lowVersion = 0;
1735 0
    int index = 7;
1736 0
    while(versionInfo[index] != '.' ) {
1737 0
        highVersion *= 10;
1738 0
        highVersion += versionInfo[index]-'0';
1739 0
        ++index;
1740
    }
1741 0
    ++index;
1742 0
    while(versionInfo[index] != ' ' &&  versionInfo[index] != '\0') {
1743 0
        lowVersion *= 10;
1744 0
        lowVersion += versionInfo[index]-'0';
1745 0
        ++index;
1746
    }
1747 0
    return (highVersion << 16) | lowVersion;
1748
}
1749

1750
static cl_uint getPlatformVersion(cl_platform_id platform)
1751
{
1752 0
    ::size_t size = 0;
1753 0
    clGetPlatformInfo(platform, CL_PLATFORM_VERSION, 0, NULL, &size);
1754 0
    char *versionInfo = (char *) alloca(size);
1755 0
    clGetPlatformInfo(platform, CL_PLATFORM_VERSION, size, &versionInfo[0], &size);
1756 0
    return getVersion(versionInfo);
1757
}
1758

1759
static cl_uint getDevicePlatformVersion(cl_device_id device)
1760
{
1761
    cl_platform_id platform;
1762 0
    clGetDeviceInfo(device, CL_DEVICE_PLATFORM, sizeof(platform), &platform, NULL);
1763 0
    return getPlatformVersion(platform);
1764
}
1765

1766
#if defined(CL_VERSION_1_2) && defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS)
1767
static cl_uint getContextPlatformVersion(cl_context context)
1768
{
1769
    // The platform cannot be queried directly, so we first have to grab a
1770
    // device and obtain its context
1771
    ::size_t size = 0;
1772
    clGetContextInfo(context, CL_CONTEXT_DEVICES, 0, NULL, &size);
1773
    if (size == 0)
1774
        return 0;
1775
    cl_device_id *devices = (cl_device_id *) alloca(size);
1776
    clGetContextInfo(context, CL_CONTEXT_DEVICES, size, devices, NULL);
1777
    return getDevicePlatformVersion(devices[0]);
1778
}
1779
#endif // #if defined(CL_VERSION_1_2) && defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS)
1780

1781
template <typename T>
1782
class Wrapper
1783
{
1784
public:
1785
    typedef T cl_type;
1786

1787
protected:
1788
    cl_type object_;
1789

1790
public:
1791 0
    Wrapper() : object_(NULL) { }
1792

1793 0
    Wrapper(const cl_type &obj) : object_(obj) { }
1794

1795
    ~Wrapper()
1796
    {
1797 0
        if (object_ != NULL) { release(); }
1798
    }
1799

1800
    Wrapper(const Wrapper<cl_type>& rhs)
1801
    {
1802 0
        object_ = rhs.object_;
1803 0
        if (object_ != NULL) { detail::errHandler(retain(), __RETAIN_ERR); }
1804
    }
1805

1806
#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED)
1807
    Wrapper(Wrapper<cl_type>&& rhs) CL_HPP_NOEXCEPT
1808
    {
1809 0
        object_ = rhs.object_;
1810 0
        rhs.object_ = NULL;
1811
    }
1812
#endif
1813

1814
    Wrapper<cl_type>& operator = (const Wrapper<cl_type>& rhs)
1815
    {
1816
        if (this != &rhs) {
1817
            if (object_ != NULL) { detail::errHandler(release(), __RELEASE_ERR); }
1818
            object_ = rhs.object_;
1819
            if (object_ != NULL) { detail::errHandler(retain(), __RETAIN_ERR); }
1820
        }
1821
        return *this;
1822
    }
1823

1824
#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED)
1825
    Wrapper<cl_type>& operator = (Wrapper<cl_type>&& rhs)
1826
    {
1827
        if (this != &rhs) {
1828
            if (object_ != NULL) { detail::errHandler(release(), __RELEASE_ERR); }
1829
            object_ = rhs.object_;
1830
            rhs.object_ = NULL;
1831
        }
1832
        return *this;
1833
    }
1834
#endif
1835

1836
    Wrapper<cl_type>& operator = (const cl_type &rhs)
1837
    {
1838 0
        if (object_ != NULL) { detail::errHandler(release(), __RELEASE_ERR); }
1839 0
        object_ = rhs;
1840 0
        return *this;
1841
    }
1842

1843 0
    cl_type operator ()() const { return object_; }
1844

1845
    cl_type& operator ()() { return object_; }
1846

1847
protected:
1848
    template<typename Func, typename U>
1849
    friend inline cl_int getInfoHelper(Func, cl_uint, U*, int, typename U::cl_type);
1850

1851
    cl_int retain() const
1852
    {
1853 0
        return ReferenceHandler<cl_type>::retain(object_);
1854
    }
1855

1856
    cl_int release() const
1857
    {
1858 0
        return ReferenceHandler<cl_type>::release(object_);
1859
    }
1860
};
1861

1862
template <>
1863
class Wrapper<cl_device_id>
1864
{
1865
public:
1866
    typedef cl_device_id cl_type;
1867

1868
protected:
1869
    cl_type object_;
1870
    bool referenceCountable_;
1871

1872
    static bool isReferenceCountable(cl_device_id device)
1873
    {
1874 0
        bool retVal = false;
1875 0
        if (device != NULL) {
1876 0
            int version = getDevicePlatformVersion(device);
1877 0
            if(version > ((1 << 16) + 1)) {
1878 0
                retVal = true;
1879
            }
1880
        }
1881 0
        return retVal;
1882
    }
1883

1884
public:
1885 0
    Wrapper() : object_(NULL), referenceCountable_(false) 
1886
    { 
1887
    }
1888
    
1889 0
    Wrapper(const cl_type &obj) : object_(obj), referenceCountable_(false) 
1890
    {
1891 0
        referenceCountable_ = isReferenceCountable(obj); 
1892
    }
1893

1894
    ~Wrapper()
1895
    {
1896 0
        if (object_ != NULL) { release(); }
1897
    }
1898
    
1899
    Wrapper(const Wrapper<cl_type>& rhs)
1900
    {
1901 0
        object_ = rhs.object_;
1902 0
        referenceCountable_ = isReferenceCountable(object_); 
1903 0
        if (object_ != NULL) { detail::errHandler(retain(), __RETAIN_ERR); }
1904
    }
1905

1906
#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED)
1907
    Wrapper(Wrapper<cl_type>&& rhs) CL_HPP_NOEXCEPT
1908
    {
1909 0
        object_ = rhs.object_;
1910 0
        referenceCountable_ = rhs.referenceCountable_;
1911 0
        rhs.object_ = NULL;
1912 0
        rhs.referenceCountable_ = false;
1913
    }
1914
#endif
1915

1916
    Wrapper<cl_type>& operator = (const Wrapper<cl_type>& rhs)
1917
    {
1918
        if (this != &rhs) {
1919
            if (object_ != NULL) { detail::errHandler(release(), __RELEASE_ERR); }
1920
            object_ = rhs.object_;
1921
            referenceCountable_ = rhs.referenceCountable_;
1922
            if (object_ != NULL) { detail::errHandler(retain(), __RETAIN_ERR); }
1923
        }
1924
        return *this;
1925
    }
1926

1927
#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED)
1928
    Wrapper<cl_type>& operator = (Wrapper<cl_type>&& rhs)
1929
    {
1930
        if (this != &rhs) {
1931
            if (object_ != NULL) { detail::errHandler(release(), __RELEASE_ERR); }
1932
            object_ = rhs.object_;
1933
            referenceCountable_ = rhs.referenceCountable_;
1934
            rhs.object_ = NULL;
1935
            rhs.referenceCountable_ = false;
1936
        }
1937
        return *this;
1938
    }
1939
#endif
1940

1941
    Wrapper<cl_type>& operator = (const cl_type &rhs)
1942
    {
1943 0
        if (object_ != NULL) { detail::errHandler(release(), __RELEASE_ERR); }
1944 0
        object_ = rhs;
1945 0
        referenceCountable_ = isReferenceCountable(object_); 
1946 0
        return *this;
1947
    }
1948

1949 0
    cl_type operator ()() const { return object_; }
1950

1951
    cl_type& operator ()() { return object_; }
1952

1953
protected:
1954
    template<typename Func, typename U>
1955
    friend inline cl_int getInfoHelper(Func, cl_uint, U*, int, typename U::cl_type);
1956

1957
    template<typename Func, typename U>
1958
    friend inline cl_int getInfoHelper(Func, cl_uint, VECTOR_CLASS<U>*, int, typename U::cl_type);
1959

1960
    cl_int retain() const
1961
    {
1962 0
        if( referenceCountable_ ) {
1963 0
            return ReferenceHandler<cl_type>::retain(object_);
1964
        }
1965
        else {
1966 0
            return CL_SUCCESS;
1967
        }
1968
    }
1969

1970
    cl_int release() const
1971
    {
1972 0
        if( referenceCountable_ ) {
1973 0
            return ReferenceHandler<cl_type>::release(object_);
1974
        }
1975
        else {
1976 0
            return CL_SUCCESS;
1977
        }
1978
    }
1979
};
1980

1981
} // namespace detail
1982
//! \endcond
1983

1984
/*! \stuct ImageFormat
1985
 *  \brief Adds constructors and member functions for cl_image_format.
1986
 *
1987
 *  \see cl_image_format
1988
 */
1989
struct ImageFormat : public cl_image_format
1990
{
1991
    //! \brief Default constructor - performs no initialization.
1992
    ImageFormat(){}
1993

1994
    //! \brief Initializing constructor.
1995
    ImageFormat(cl_channel_order order, cl_channel_type type)
1996
    {
1997
        image_channel_order = order;
1998
        image_channel_data_type = type;
1999
    }
2000

2001
    //! \brief Assignment operator.
2002
    ImageFormat& operator = (const ImageFormat& rhs)
2003
    {
2004
        if (this != &rhs) {
2005
            this->image_channel_data_type = rhs.image_channel_data_type;
2006
            this->image_channel_order     = rhs.image_channel_order;
2007
        }
2008
        return *this;
2009
    }
2010
};
2011

2012
/*! \brief Class interface for cl_device_id.
2013
 *
2014
 *  \note Copies of these objects are inexpensive, since they don't 'own'
2015
 *        any underlying resources or data structures.
2016
 *
2017
 *  \see cl_device_id
2018
 */
2019 0
class Device : public detail::Wrapper<cl_device_id>
2020
{
2021
public:
2022
    //! \brief Default constructor - initializes to NULL.
2023 0
    Device() : detail::Wrapper<cl_type>() { }
2024

2025
    /*! \brief Constructor from cl_device_id.
2026
     * 
2027
     *  This simply copies the device ID value, which is an inexpensive operation.
2028
     */
2029 0
    __CL_EXPLICIT_CONSTRUCTORS Device(const cl_device_id &device) : detail::Wrapper<cl_type>(device) { }
2030

2031
    /*! \brief Returns the first device on the default context.
2032
     *
2033
     *  \see Context::getDefault()
2034
     */
2035
    static Device getDefault(cl_int * err = NULL);
2036

2037
    /*! \brief Assignment operator from cl_device_id.
2038
     * 
2039
     *  This simply copies the device ID value, which is an inexpensive operation.
2040
     */
2041
    Device& operator = (const cl_device_id& rhs)
2042
    {
2043 0
        detail::Wrapper<cl_type>::operator=(rhs);
2044 0
        return *this;
2045
    }
2046

2047
    /*! \brief Copy constructor to forward copy to the superclass correctly.
2048
     * Required for MSVC.
2049
     */
2050 0
    Device(const Device& dev) : detail::Wrapper<cl_type>(dev) {}
2051

2052
    /*! \brief Copy assignment to forward copy to the superclass correctly.
2053
     * Required for MSVC.
2054
     */
2055
    Device& operator = (const Device &dev)
2056
    {
2057
        detail::Wrapper<cl_type>::operator=(dev);
2058
        return *this;
2059
    }
2060

2061
#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED)
2062
    /*! \brief Move constructor to forward move to the superclass correctly.
2063
     * Required for MSVC.
2064
     */
2065 0
    Device(Device&& dev) CL_HPP_NOEXCEPT : detail::Wrapper<cl_type>(std::move(dev)) {}
2066

2067
    /*! \brief Move assignment to forward move to the superclass correctly.
2068
     * Required for MSVC.
2069
     */
2070
    Device& operator = (Device &&dev)
2071
    {
2072
        detail::Wrapper<cl_type>::operator=(std::move(dev));
2073
        return *this;
2074
    }
2075
#endif // #if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED)
2076

2077
    //! \brief Wrapper for clGetDeviceInfo().
2078
    template <typename T>
2079
    cl_int getInfo(cl_device_info name, T* param) const
2080
    {
2081 0
        return detail::errHandler(
2082 0
            detail::getInfo(&::clGetDeviceInfo, object_, name, param),
2083
            __GET_DEVICE_INFO_ERR);
2084
    }
2085

2086
    //! \brief Wrapper for clGetDeviceInfo() that returns by value.
2087
    template <cl_int name> typename
2088
    detail::param_traits<detail::cl_device_info, name>::param_type
2089
    getInfo(cl_int* err = NULL) const
2090
    {
2091 0
        typename detail::param_traits<
2092 0
            detail::cl_device_info, name>::param_type param;
2093 0
        cl_int result = getInfo(name, &param);
2094 0
        if (err != NULL) {
2095 0
            *err = result;
2096
        }
2097 0
        return param;
2098
    }
2099

2100
    /**
2101
     * CL 1.2 version
2102
     */
2103
#if defined(CL_VERSION_1_2)
2104
    //! \brief Wrapper for clCreateSubDevicesEXT().
2105
    cl_int createSubDevices(
2106
        const cl_device_partition_property * properties,
2107
        VECTOR_CLASS<Device>* devices)
2108
    {
2109
        cl_uint n = 0;
2110
        cl_int err = clCreateSubDevices(object_, properties, 0, NULL, &n);
2111
        if (err != CL_SUCCESS) {
2112
            return detail::errHandler(err, __CREATE_SUB_DEVICES);
2113
        }
2114

2115
        cl_device_id* ids = (cl_device_id*) alloca(n * sizeof(cl_device_id));
2116
        err = clCreateSubDevices(object_, properties, n, ids, NULL);
2117
        if (err != CL_SUCCESS) {
2118
            return detail::errHandler(err, __CREATE_SUB_DEVICES);
2119
        }
2120

2121
        devices->assign(&ids[0], &ids[n]);
2122
        return CL_SUCCESS;
2123
    }
2124
#endif // #if defined(CL_VERSION_1_2)
2125

2126
/**
2127
 * CL 1.1 version that uses device fission.
2128
 */
2129
#if defined(CL_VERSION_1_1)
2130
#if defined(USE_CL_DEVICE_FISSION)
2131
    cl_int createSubDevices(
2132
        const cl_device_partition_property_ext * properties,
2133
        VECTOR_CLASS<Device>* devices)
2134
    {
2135
        typedef CL_API_ENTRY cl_int 
2136
            ( CL_API_CALL * PFN_clCreateSubDevicesEXT)(
2137
                cl_device_id /*in_device*/,
2138
                const cl_device_partition_property_ext * /* properties */,
2139
                cl_uint /*num_entries*/,
2140
                cl_device_id * /*out_devices*/,
2141
                cl_uint * /*num_devices*/ ) CL_EXT_SUFFIX__VERSION_1_1;
2142

2143
        static PFN_clCreateSubDevicesEXT pfn_clCreateSubDevicesEXT = NULL;
2144
        __INIT_CL_EXT_FCN_PTR(clCreateSubDevicesEXT);
2145

2146
        cl_uint n = 0;
2147
        cl_int err = pfn_clCreateSubDevicesEXT(object_, properties, 0, NULL, &n);
2148
        if (err != CL_SUCCESS) {
2149
            return detail::errHandler(err, __CREATE_SUB_DEVICES);
2150
        }
2151

2152
        cl_device_id* ids = (cl_device_id*) alloca(n * sizeof(cl_device_id));
2153
        err = pfn_clCreateSubDevicesEXT(object_, properties, n, ids, NULL);
2154
        if (err != CL_SUCCESS) {
2155
            return detail::errHandler(err, __CREATE_SUB_DEVICES);
2156
        }
2157

2158
        devices->assign(&ids[0], &ids[n]);
2159
        return CL_SUCCESS;
2160
    }
2161
#endif // #if defined(USE_CL_DEVICE_FISSION)
2162
#endif // #if defined(CL_VERSION_1_1)
2163
};
2164

2165
/*! \brief Class interface for cl_platform_id.
2166
 *
2167
 *  \note Copies of these objects are inexpensive, since they don't 'own'
2168
 *        any underlying resources or data structures.
2169
 *
2170
 *  \see cl_platform_id
2171
 */
2172 0
class Platform : public detail::Wrapper<cl_platform_id>
2173
{
2174
public:
2175
    //! \brief Default constructor - initializes to NULL.
2176
    Platform() : detail::Wrapper<cl_type>()  { }
2177

2178
    /*! \brief Constructor from cl_platform_id.
2179
     * 
2180
     *  This simply copies the platform ID value, which is an inexpensive operation.
2181
     */
2182 0
    __CL_EXPLICIT_CONSTRUCTORS Platform(const cl_platform_id &platform) : detail::Wrapper<cl_type>(platform) { }
2183

2184
    /*! \brief Assignment operator from cl_platform_id.
2185
     * 
2186
     *  This simply copies the platform ID value, which is an inexpensive operation.
2187
     */
2188
    Platform& operator = (const cl_platform_id& rhs)
2189
    {
2190 0
        detail::Wrapper<cl_type>::operator=(rhs);
2191 0
        return *this;
2192
    }
2193

2194
    //! \brief Wrapper for clGetPlatformInfo().
2195
    cl_int getInfo(cl_platform_info name, STRING_CLASS* param) const
2196
    {
2197 0
        return detail::errHandler(
2198 0
            detail::getInfo(&::clGetPlatformInfo, object_, name, param),
2199
            __GET_PLATFORM_INFO_ERR);
2200
    }
2201

2202
    //! \brief Wrapper for clGetPlatformInfo() that returns by value.
2203
    template <cl_int name> typename
2204
    detail::param_traits<detail::cl_platform_info, name>::param_type
2205
    getInfo(cl_int* err = NULL) const
2206
    {
2207 0
        typename detail::param_traits<
2208 0
            detail::cl_platform_info, name>::param_type param;
2209 0
        cl_int result = getInfo(name, &param);
2210 0
        if (err != NULL) {
2211 0
            *err = result;
2212
        }
2213 0
        return param;
2214
    }
2215

2216
    /*! \brief Gets a list of devices for this platform.
2217
     * 
2218
     *  Wraps clGetDeviceIDs().
2219
     */
2220
    cl_int getDevices(
2221
        cl_device_type type,
2222
        VECTOR_CLASS<Device>* devices) const
2223
    {
2224 0
        cl_uint n = 0;
2225 0
        if( devices == NULL ) {
2226 0
            return detail::errHandler(CL_INVALID_ARG_VALUE, __GET_DEVICE_IDS_ERR);
2227
        }
2228 0
        cl_int err = ::clGetDeviceIDs(object_, type, 0, NULL, &n);
2229 0
        if (err != CL_SUCCESS) {
2230 0
            return detail::errHandler(err, __GET_DEVICE_IDS_ERR);
2231
        }
2232

2233 0
        cl_device_id* ids = (cl_device_id*) alloca(n * sizeof(cl_device_id));
2234 0
        err = ::clGetDeviceIDs(object_, type, n, ids, NULL);
2235 0
        if (err != CL_SUCCESS) {
2236 0
            return detail::errHandler(err, __GET_DEVICE_IDS_ERR);
2237
        }
2238

2239 0
        devices->assign(&ids[0], &ids[n]);
2240 0
        return CL_SUCCESS;
2241
    }
2242

2243
#if defined(USE_DX_INTEROP)
2244
   /*! \brief Get the list of available D3D10 devices.
2245
     *
2246
     *  \param d3d_device_source.
2247
     *
2248
     *  \param d3d_object.
2249
     *
2250
     *  \param d3d_device_set.
2251
     *
2252
     *  \param devices returns a vector of OpenCL D3D10 devices found. The cl::Device
2253
     *  values returned in devices can be used to identify a specific OpenCL
2254
     *  device. If \a devices argument is NULL, this argument is ignored.
2255
     *
2256
     *  \return One of the following values:
2257
     *    - CL_SUCCESS if the function is executed successfully.
2258
     *
2259
     *  The application can query specific capabilities of the OpenCL device(s)
2260
     *  returned by cl::getDevices. This can be used by the application to
2261
     *  determine which device(s) to use.
2262
     *
2263
     * \note In the case that exceptions are enabled and a return value
2264
     * other than CL_SUCCESS is generated, then cl::Error exception is
2265
     * generated.
2266
     */
2267
    cl_int getDevices(
2268
        cl_d3d10_device_source_khr d3d_device_source,
2269
        void *                     d3d_object,
2270
        cl_d3d10_device_set_khr    d3d_device_set,
2271
        VECTOR_CLASS<Device>* devices) const
2272
    {
2273
        typedef CL_API_ENTRY cl_int (CL_API_CALL *PFN_clGetDeviceIDsFromD3D10KHR)(
2274
            cl_platform_id platform, 
2275
            cl_d3d10_device_source_khr d3d_device_source, 
2276
            void * d3d_object,
2277
            cl_d3d10_device_set_khr d3d_device_set,
2278
            cl_uint num_entries,
2279
            cl_device_id * devices,
2280
            cl_uint* num_devices);
2281

2282
        if( devices == NULL ) {
2283
            return detail::errHandler(CL_INVALID_ARG_VALUE, __GET_DEVICE_IDS_ERR);
2284
        }
2285

2286
        static PFN_clGetDeviceIDsFromD3D10KHR pfn_clGetDeviceIDsFromD3D10KHR = NULL;
2287
        __INIT_CL_EXT_FCN_PTR_PLATFORM(object_, clGetDeviceIDsFromD3D10KHR);
2288

2289
        cl_uint n = 0;
2290
        cl_int err = pfn_clGetDeviceIDsFromD3D10KHR(
2291
            object_, 
2292
            d3d_device_source, 
2293
            d3d_object,
2294
            d3d_device_set, 
2295
            0, 
2296
            NULL, 
2297
            &n);
2298
        if (err != CL_SUCCESS) {
2299
            return detail::errHandler(err, __GET_DEVICE_IDS_ERR);
2300
        }
2301

2302
        cl_device_id* ids = (cl_device_id*) alloca(n * sizeof(cl_device_id));
2303
        err = pfn_clGetDeviceIDsFromD3D10KHR(
2304
            object_, 
2305
            d3d_device_source, 
2306
            d3d_object,
2307
            d3d_device_set,
2308
            n, 
2309
            ids, 
2310
            NULL);
2311
        if (err != CL_SUCCESS) {
2312
            return detail::errHandler(err, __GET_DEVICE_IDS_ERR);
2313
        }
2314

2315
        devices->assign(&ids[0], &ids[n]);
2316
        return CL_SUCCESS;
2317
    }
2318
#endif
2319

2320
    /*! \brief Gets a list of available platforms.
2321
     * 
2322
     *  Wraps clGetPlatformIDs().
2323
     */
2324
    static cl_int get(
2325
        VECTOR_CLASS<Platform>* platforms)
2326
    {
2327 0
        cl_uint n = 0;
2328

2329 0
        if( platforms == NULL ) {
2330 0
            return detail::errHandler(CL_INVALID_ARG_VALUE, __GET_PLATFORM_IDS_ERR);
2331
        }
2332

2333 0
        cl_int err = ::clGetPlatformIDs(0, NULL, &n);
2334 0
        if (err != CL_SUCCESS) {
2335 0
            return detail::errHandler(err, __GET_PLATFORM_IDS_ERR);
2336
        }
2337

2338 0
        cl_platform_id* ids = (cl_platform_id*) alloca(
2339
            n * sizeof(cl_platform_id));
2340 0
        err = ::clGetPlatformIDs(n, ids, NULL);
2341 0
        if (err != CL_SUCCESS) {
2342 0
            return detail::errHandler(err, __GET_PLATFORM_IDS_ERR);
2343
        }
2344

2345 0
        platforms->assign(&ids[0], &ids[n]);
2346 0
        return CL_SUCCESS;
2347
    }
2348

2349
    /*! \brief Gets the first available platform.
2350
     * 
2351
     *  Wraps clGetPlatformIDs(), returning the first result.
2352
     */
2353
    static cl_int get(
2354
        Platform * platform)
2355
    {
2356
        cl_uint n = 0;
2357

2358
        if( platform == NULL ) {
2359
            return detail::errHandler(CL_INVALID_ARG_VALUE, __GET_PLATFORM_IDS_ERR);
2360
        }
2361

2362
        cl_int err = ::clGetPlatformIDs(0, NULL, &n);
2363
        if (err != CL_SUCCESS) {
2364
            return detail::errHandler(err, __GET_PLATFORM_IDS_ERR);
2365
        }
2366

2367
        cl_platform_id* ids = (cl_platform_id*) alloca(
2368
            n * sizeof(cl_platform_id));
2369
        err = ::clGetPlatformIDs(n, ids, NULL);
2370
        if (err != CL_SUCCESS) {
2371
            return detail::errHandler(err, __GET_PLATFORM_IDS_ERR);
2372
        }
2373

2374
        *platform = ids[0];
2375
        return CL_SUCCESS;
2376
    }
2377

2378
    /*! \brief Gets the first available platform, returning it by value.
2379
     * 
2380
     *  Wraps clGetPlatformIDs(), returning the first result.
2381
     */
2382
    static Platform get(
2383
        cl_int * errResult = NULL)
2384
    {
2385
        Platform platform;
2386
        cl_uint n = 0;
2387
        cl_int err = ::clGetPlatformIDs(0, NULL, &n);
2388
        if (err != CL_SUCCESS) {
2389
            detail::errHandler(err, __GET_PLATFORM_IDS_ERR);
2390
            if (errResult != NULL) {
2391
                *errResult = err;
2392
            }
2393
            return Platform();
2394
        }
2395

2396
        cl_platform_id* ids = (cl_platform_id*) alloca(
2397
            n * sizeof(cl_platform_id));
2398
        err = ::clGetPlatformIDs(n, ids, NULL);
2399

2400
        if (err != CL_SUCCESS) {
2401
            detail::errHandler(err, __GET_PLATFORM_IDS_ERR);
2402
            if (errResult != NULL) {
2403
                *errResult = err;
2404
            }
2405
            return Platform();
2406
        }
2407

2408
        
2409
        return Platform(ids[0]);
2410
    }
2411

2412
    static Platform getDefault( 
2413
        cl_int *errResult = NULL )
2414
    {
2415
        return get(errResult);
2416
    }
2417

2418
    
2419
#if defined(CL_VERSION_1_2)
2420
    //! \brief Wrapper for clUnloadCompiler().
2421
    cl_int
2422
    unloadCompiler()
2423
    {
2424
        return ::clUnloadPlatformCompiler(object_);
2425
    }
2426
#endif // #if defined(CL_VERSION_1_2)
2427
}; // class Platform
2428

2429
/**
2430
 * Deprecated APIs for 1.2
2431
 */
2432
#if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) || (defined(CL_VERSION_1_1) && !defined(CL_VERSION_1_2))
2433
/**
2434
 * Unload the OpenCL compiler.
2435
 * \note Deprecated for OpenCL 1.2. Use Platform::unloadCompiler instead.
2436
 */
2437
inline CL_EXT_PREFIX__VERSION_1_1_DEPRECATED cl_int
2438
UnloadCompiler() CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED;
2439
inline cl_int
2440
UnloadCompiler()
2441
{
2442
    return ::clUnloadCompiler();
2443
}
2444
#endif // #if defined(CL_VERSION_1_1)
2445

2446
/*! \brief Class interface for cl_context.
2447
 *
2448
 *  \note Copies of these objects are shallow, meaning that the copy will refer
2449
 *        to the same underlying cl_context as the original.  For details, see
2450
 *        clRetainContext() and clReleaseContext().
2451
 *
2452
 *  \see cl_context
2453
 */
2454 0
class Context 
2455
    : public detail::Wrapper<cl_context>
2456
{
2457
private:
2458

2459
#ifdef CL_HPP_CPP11_ATOMICS_SUPPORTED
2460
    static std::atomic<int> default_initialized_;
2461
#else // !CL_HPP_CPP11_ATOMICS_SUPPORTED
2462
    static volatile int default_initialized_;
2463
#endif // !CL_HPP_CPP11_ATOMICS_SUPPORTED
2464
    static Context default_;
2465
    static volatile cl_int default_error_;
2466
public:
2467
    /*! \brief Constructs a context including a list of specified devices.
2468
     *
2469
     *  Wraps clCreateContext().
2470
     */
2471 0
    Context(
2472
        const VECTOR_CLASS<Device>& devices,
2473
        cl_context_properties* properties = NULL,
2474
        void (CL_CALLBACK * notifyFptr)(
2475
            const char *,
2476
            const void *,
2477
            ::size_t,
2478
            void *) = NULL,
2479
        void* data = NULL,
2480
        cl_int* err = NULL)
2481
    {
2482
        cl_int error;
2483

2484 0
        ::size_t numDevices = devices.size();
2485 0
        cl_device_id* deviceIDs = (cl_device_id*) alloca(numDevices * sizeof(cl_device_id));
2486 0
        for( ::size_t deviceIndex = 0; deviceIndex < numDevices; ++deviceIndex ) {
2487 0
            deviceIDs[deviceIndex] = (devices[deviceIndex])();
2488
        }
2489

2490 0
        object_ = ::clCreateContext(
2491 0
            properties, (cl_uint) numDevices,
2492 0
            deviceIDs,
2493 0
            notifyFptr, data, &error);
2494

2495 0
        detail::errHandler(error, __CREATE_CONTEXT_ERR);
2496 0
        if (err != NULL) {
2497 0
            *err = error;
2498
        }
2499
    }
2500

2501
    Context(
2502
        const Device& device,
2503
        cl_context_properties* properties = NULL,
2504
        void (CL_CALLBACK * notifyFptr)(
2505
            const char *,
2506
            const void *,
2507
            ::size_t,
2508
            void *) = NULL,
2509
        void* data = NULL,
2510
        cl_int* err = NULL)
2511
    {
2512
        cl_int error;
2513

2514
        cl_device_id deviceID = device();
2515

2516
        object_ = ::clCreateContext(
2517
            properties, 1,
2518
            &deviceID,
2519
            notifyFptr, data, &error);
2520

2521
        detail::errHandler(error, __CREATE_CONTEXT_ERR);
2522
        if (err != NULL) {
2523
            *err = error;
2524
        }
2525
    }
2526

2527
    /*! \brief Constructs a context including all or a subset of devices of a specified type.
2528
     *
2529
     *  Wraps clCreateContextFromType().
2530
     */
2531
    Context(
2532
        cl_device_type type,
2533
        cl_context_properties* properties = NULL,
2534
        void (CL_CALLBACK * notifyFptr)(
2535
            const char *,
2536
            const void *,
2537
            ::size_t,
2538
            void *) = NULL,
2539
        void* data = NULL,
2540
        cl_int* err = NULL)
2541
    {
2542
        cl_int error;
2543

2544
#if !defined(__APPLE__) && !defined(__MACOS)
2545
        cl_context_properties prop[4] = {CL_CONTEXT_PLATFORM, 0, 0, 0 };
2546

2547
        if (properties == NULL) {
2548
            // Get a valid platform ID as we cannot send in a blank one
2549
            VECTOR_CLASS<Platform> platforms;
2550
            error = Platform::get(&platforms);
2551
            if (error != CL_SUCCESS) {
2552
                detail::errHandler(error, __CREATE_CONTEXT_FROM_TYPE_ERR);
2553
                if (err != NULL) {
2554
                    *err = error;
2555
                }
2556
                return;
2557
            }
2558

2559
            // Check the platforms we found for a device of our specified type
2560
            cl_context_properties platform_id = 0;
2561
            for (unsigned int i = 0; i < platforms.size(); i++) {
2562

2563
                VECTOR_CLASS<Device> devices;
2564

2565
#if defined(__CL_ENABLE_EXCEPTIONS)
2566
                try {
2567
#endif
2568

2569
                    error = platforms[i].getDevices(type, &devices);
2570

2571
#if defined(__CL_ENABLE_EXCEPTIONS)
2572
                } catch (Error) {}
2573
    // Catch if exceptions are enabled as we don't want to exit if first platform has no devices of type
2574
    // We do error checking next anyway, and can throw there if needed
2575
#endif
2576

2577
                // Only squash CL_SUCCESS and CL_DEVICE_NOT_FOUND
2578
                if (error != CL_SUCCESS && error != CL_DEVICE_NOT_FOUND) {
2579
                    detail::errHandler(error, __CREATE_CONTEXT_FROM_TYPE_ERR);
2580
                    if (err != NULL) {
2581
                        *err = error;
2582
                    }
2583
                }
2584

2585
                if (devices.size() > 0) {
2586
                    platform_id = (cl_context_properties)platforms[i]();
2587
                    break;
2588
                }
2589
            }
2590

2591
            if (platform_id == 0) {
2592
                detail::errHandler(CL_DEVICE_NOT_FOUND, __CREATE_CONTEXT_FROM_TYPE_ERR);
2593
                if (err != NULL) {
2594
                    *err = CL_DEVICE_NOT_FOUND;
2595
                }
2596
                return;
2597
            }
2598

2599
            prop[1] = platform_id;
2600
            properties = &prop[0];
2601
        }
2602
#endif
2603
        object_ = ::clCreateContextFromType(
2604
            properties, type, notifyFptr, data, &error);
2605

2606
        detail::errHandler(error, __CREATE_CONTEXT_FROM_TYPE_ERR);
2607
        if (err != NULL) {
2608
            *err = error;
2609
        }
2610
    }
2611

2612
    /*! \brief Copy constructor to forward copy to the superclass correctly.
2613
     * Required for MSVC.
2614
     */
2615 0
    Context(const Context& ctx) : detail::Wrapper<cl_type>(ctx) {}
2616

2617
    /*! \brief Copy assignment to forward copy to the superclass correctly.
2618
     * Required for MSVC.
2619
     */
2620
    Context& operator = (const Context &ctx)
2621
    {
2622
        detail::Wrapper<cl_type>::operator=(ctx);
2623
        return *this;
2624
    }
2625

2626
#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED)
2627
    /*! \brief Move constructor to forward move to the superclass correctly.
2628
     * Required for MSVC.
2629
     */
2630 0
    Context(Context&& ctx) CL_HPP_NOEXCEPT : detail::Wrapper<cl_type>(std::move(ctx)) {}
2631

2632
    /*! \brief Move assignment to forward move to the superclass correctly.
2633
     * Required for MSVC.
2634
     */
2635
    Context& operator = (Context &&ctx)
2636
    {
2637
        detail::Wrapper<cl_type>::operator=(std::move(ctx));
2638
        return *this;
2639
    }
2640
#endif // #if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED)
2641

2642
    /*! \brief Returns a singleton context including all devices of CL_DEVICE_TYPE_DEFAULT.
2643
     *
2644
     *  \note All calls to this function return the same cl_context as the first.
2645
     */
2646
    static Context getDefault(cl_int * err = NULL) 
2647
    {
2648
        int state = detail::compare_exchange(
2649
            &default_initialized_, 
2650
            __DEFAULT_BEING_INITIALIZED, __DEFAULT_NOT_INITIALIZED);
2651
        
2652
        if (state & __DEFAULT_INITIALIZED) {
2653
            if (err != NULL) {
2654
                *err = default_error_;
2655
            }
2656
            return default_;
2657
        }
2658

2659
        if (state & __DEFAULT_BEING_INITIALIZED) {
2660
              // Assume writes will propagate eventually...
2661
              while(default_initialized_ != __DEFAULT_INITIALIZED) {
2662
                  detail::fence();
2663
              }
2664

2665
            if (err != NULL) {
2666
                *err = default_error_;
2667
            }
2668
            return default_;
2669
        }
2670

2671
        cl_int error;
2672
        default_ = Context(
2673
            CL_DEVICE_TYPE_DEFAULT,
2674
            NULL,
2675
            NULL,
2676
            NULL,
2677
            &error);
2678

2679
        detail::fence();
2680

2681
        default_error_ = error;
2682
        // Assume writes will propagate eventually...
2683
        default_initialized_ = __DEFAULT_INITIALIZED;
2684

2685
        detail::fence();
2686

2687
        if (err != NULL) {
2688
            *err = default_error_;
2689
        }
2690
        return default_;
2691

2692
    }
2693

2694
    //! \brief Default constructor - initializes to NULL.
2695 0
    Context() : detail::Wrapper<cl_type>() { }
2696

2697
    /*! \brief Constructor from cl_context - takes ownership.
2698
     * 
2699
     *  This effectively transfers ownership of a refcount on the cl_context
2700
     *  into the new Context object.
2701
     */
2702
    __CL_EXPLICIT_CONSTRUCTORS Context(const cl_context& context) : detail::Wrapper<cl_type>(context) { }
2703

2704
    /*! \brief Assignment operator from cl_context - takes ownership.
2705
     * 
2706
     *  This effectively transfers ownership of a refcount on the rhs and calls
2707
     *  clReleaseContext() on the value previously held by this instance.
2708
     */
2709
    Context& operator = (const cl_context& rhs)
2710
    {
2711
        detail::Wrapper<cl_type>::operator=(rhs);
2712
        return *this;
2713
    }
2714

2715
    //! \brief Wrapper for clGetContextInfo().
2716
    template <typename T>
2717
    cl_int getInfo(cl_context_info name, T* param) const
2718
    {
2719
        return detail::errHandler(
2720
            detail::getInfo(&::clGetContextInfo, object_, name, param),
2721
            __GET_CONTEXT_INFO_ERR);
2722
    }
2723

2724
    //! \brief Wrapper for clGetContextInfo() that returns by value.
2725
    template <cl_int name> typename
2726
    detail::param_traits<detail::cl_context_info, name>::param_type
2727
    getInfo(cl_int* err = NULL) const
2728
    {
2729
        typename detail::param_traits<
2730
            detail::cl_context_info, name>::param_type param;
2731
        cl_int result = getInfo(name, &param);
2732
        if (err != NULL) {
2733
            *err = result;
2734
        }
2735
        return param;
2736
    }
2737

2738
    /*! \brief Gets a list of supported image formats.
2739
     *  
2740
     *  Wraps clGetSupportedImageFormats().
2741
     */
2742
    cl_int getSupportedImageFormats(
2743
        cl_mem_flags flags,
2744
        cl_mem_object_type type,
2745
        VECTOR_CLASS<ImageFormat>* formats) const
2746
    {
2747
        cl_uint numEntries;
2748

2749
        if (!formats) {
2750
            return CL_SUCCESS;
2751
        }
2752

2753
        cl_int err = ::clGetSupportedImageFormats(
2754
            object_,
2755
            flags,
2756
            type,
2757
            0,
2758
            NULL,
2759
            &numEntries);
2760
        if (err != CL_SUCCESS) {
2761
            return detail::errHandler(err, __GET_SUPPORTED_IMAGE_FORMATS_ERR);
2762
        }
2763

2764
        if (numEntries > 0) {
2765
            ImageFormat* value = (ImageFormat*)
2766
                alloca(numEntries * sizeof(ImageFormat));
2767
            err = ::clGetSupportedImageFormats(
2768
                object_,
2769
                flags,
2770
                type,
2771
                numEntries,
2772
                (cl_image_format*)value,
2773
                NULL);
2774
            if (err != CL_SUCCESS) {
2775
                return detail::errHandler(err, __GET_SUPPORTED_IMAGE_FORMATS_ERR);
2776
            }
2777

2778
            formats->assign(&value[0], &value[numEntries]);
2779
        }
2780
        else {
2781
            formats->clear();
2782
        }
2783
        return CL_SUCCESS;
2784
    }
2785
};
2786

2787
inline Device Device::getDefault(cl_int * err)
2788
{
2789
    cl_int error;
2790
    Device device;
2791

2792
    Context context = Context::getDefault(&error);
2793
    detail::errHandler(error, __CREATE_CONTEXT_ERR);
2794

2795
    if (error != CL_SUCCESS) {
2796
        if (err != NULL) {
2797
            *err = error;
2798
        }
2799
    }
2800
    else {
2801
        device = context.getInfo<CL_CONTEXT_DEVICES>()[0];
2802
        if (err != NULL) {
2803
            *err = CL_SUCCESS;
2804
        }
2805
    }
2806

2807
    return device;
2808
}
2809

2810

2811
#ifdef _WIN32
2812
#ifdef CL_HPP_CPP11_ATOMICS_SUPPORTED
2813
__declspec(selectany) std::atomic<int> Context::default_initialized_;
2814
#else // !CL_HPP_CPP11_ATOMICS_SUPPORTED
2815
__declspec(selectany) volatile int Context::default_initialized_ = __DEFAULT_NOT_INITIALIZED;
2816
#endif // !CL_HPP_CPP11_ATOMICS_SUPPORTED
2817
__declspec(selectany) Context Context::default_;
2818
__declspec(selectany) volatile cl_int Context::default_error_ = CL_SUCCESS;
2819
#else // !_WIN32
2820
#ifdef CL_HPP_CPP11_ATOMICS_SUPPORTED
2821
__attribute__((weak)) std::atomic<int> Context::default_initialized_;
2822
#else // !CL_HPP_CPP11_ATOMICS_SUPPORTED
2823
__attribute__((weak)) volatile int Context::default_initialized_ = __DEFAULT_NOT_INITIALIZED;
2824
#endif // !CL_HPP_CPP11_ATOMICS_SUPPORTED
2825 0
__attribute__((weak)) Context Context::default_;
2826
__attribute__((weak)) volatile cl_int Context::default_error_ = CL_SUCCESS;
2827
#endif // !_WIN32
2828

2829
/*! \brief Class interface for cl_event.
2830
 *
2831
 *  \note Copies of these objects are shallow, meaning that the copy will refer
2832
 *        to the same underlying cl_event as the original.  For details, see
2833
 *        clRetainEvent() and clReleaseEvent().
2834
 *
2835
 *  \see cl_event
2836
 */
2837
class Event : public detail::Wrapper<cl_event>
2838
{
2839
public:
2840
    //! \brief Default constructor - initializes to NULL.
2841
    Event() : detail::Wrapper<cl_type>() { }
2842

2843
    /*! \brief Constructor from cl_event - takes ownership.
2844
     * 
2845
     *  This effectively transfers ownership of a refcount on the cl_event
2846
     *  into the new Event object.
2847
     */
2848
    __CL_EXPLICIT_CONSTRUCTORS Event(const cl_event& event) : detail::Wrapper<cl_type>(event) { }
2849

2850
    /*! \brief Assignment operator from cl_event - takes ownership.
2851
     *
2852
     *  This effectively transfers ownership of a refcount on the rhs and calls
2853
     *  clReleaseEvent() on the value previously held by this instance.
2854
     */
2855
    Event& operator = (const cl_event& rhs)
2856
    {
2857
        detail::Wrapper<cl_type>::operator=(rhs);
2858
        return *this;
2859
    }
2860

2861
    //! \brief Wrapper for clGetEventInfo().
2862
    template <typename T>
2863
    cl_int getInfo(cl_event_info name, T* param) const
2864
    {
2865
        return detail::errHandler(
2866
            detail::getInfo(&::clGetEventInfo, object_, name, param),
2867
            __GET_EVENT_INFO_ERR);
2868
    }
2869

2870
    //! \brief Wrapper for clGetEventInfo() that returns by value.
2871
    template <cl_int name> typename
2872
    detail::param_traits<detail::cl_event_info, name>::param_type
2873
    getInfo(cl_int* err = NULL) const
2874
    {
2875
        typename detail::param_traits<
2876
            detail::cl_event_info, name>::param_type param;
2877
        cl_int result = getInfo(name, &param);
2878
        if (err != NULL) {
2879
            *err = result;
2880
        }
2881
        return param;
2882
    }
2883

2884
    //! \brief Wrapper for clGetEventProfilingInfo().
2885
    template <typename T>
2886
    cl_int getProfilingInfo(cl_profiling_info name, T* param) const
2887
    {
2888
        return detail::errHandler(detail::getInfo(
2889
            &::clGetEventProfilingInfo, object_, name, param),
2890
            __GET_EVENT_PROFILE_INFO_ERR);
2891
    }
2892

2893
    //! \brief Wrapper for clGetEventProfilingInfo() that returns by value.
2894
    template <cl_int name> typename
2895
    detail::param_traits<detail::cl_profiling_info, name>::param_type
2896
    getProfilingInfo(cl_int* err = NULL) const
2897
    {
2898
        typename detail::param_traits<
2899
            detail::cl_profiling_info, name>::param_type param;
2900
        cl_int result = getProfilingInfo(name, &param);
2901
        if (err != NULL) {
2902
            *err = result;
2903
        }
2904
        return param;
2905
    }
2906

2907
    /*! \brief Blocks the calling thread until this event completes.
2908
     * 
2909
     *  Wraps clWaitForEvents().
2910
     */
2911
    cl_int wait() const
2912
    {
2913
        return detail::errHandler(
2914
            ::clWaitForEvents(1, &object_),
2915
            __WAIT_FOR_EVENTS_ERR);
2916
    }
2917

2918
#if defined(CL_VERSION_1_1)
2919
    /*! \brief Registers a user callback function for a specific command execution status.
2920
     *
2921
     *  Wraps clSetEventCallback().
2922
     */
2923
    cl_int setCallback(
2924
        cl_int type,
2925
        void (CL_CALLBACK * pfn_notify)(cl_event, cl_int, void *),		
2926
        void * user_data = NULL)
2927
    {
2928
        return detail::errHandler(
2929
            ::clSetEventCallback(
2930
                object_,
2931
                type,
2932
                pfn_notify,
2933
                user_data), 
2934
            __SET_EVENT_CALLBACK_ERR);
2935
    }
2936
#endif
2937

2938
    /*! \brief Blocks the calling thread until every event specified is complete.
2939
     * 
2940
     *  Wraps clWaitForEvents().
2941
     */
2942
    static cl_int
2943
    waitForEvents(const VECTOR_CLASS<Event>& events)
2944
    {
2945
        return detail::errHandler(
2946
            ::clWaitForEvents(
2947
                (cl_uint) events.size(), (events.size() > 0) ? (cl_event*)&events.front() : NULL),
2948
            __WAIT_FOR_EVENTS_ERR);
2949
    }
2950
};
2951

2952
#if defined(CL_VERSION_1_1)
2953
/*! \brief Class interface for user events (a subset of cl_event's).
2954
 * 
2955
 *  See Event for details about copy semantics, etc.
2956
 */
2957
class UserEvent : public Event
2958
{
2959
public:
2960
    /*! \brief Constructs a user event on a given context.
2961
     *
2962
     *  Wraps clCreateUserEvent().
2963
     */
2964
    UserEvent(
2965
        const Context& context,
2966
        cl_int * err = NULL)
2967
    {
2968
        cl_int error;
2969
        object_ = ::clCreateUserEvent(
2970
            context(),
2971
            &error);
2972

2973
        detail::errHandler(error, __CREATE_USER_EVENT_ERR);
2974
        if (err != NULL) {
2975
            *err = error;
2976
        }
2977
    }
2978

2979
    //! \brief Default constructor - initializes to NULL.
2980
    UserEvent() : Event() { }
2981

2982
    /*! \brief Sets the execution status of a user event object.
2983
     *
2984
     *  Wraps clSetUserEventStatus().
2985
     */
2986
    cl_int setStatus(cl_int status)
2987
    {
2988
        return detail::errHandler(
2989
            ::clSetUserEventStatus(object_,status), 
2990
            __SET_USER_EVENT_STATUS_ERR);
2991
    }
2992
};
2993
#endif
2994

2995
/*! \brief Blocks the calling thread until every event specified is complete.
2996
 * 
2997
 *  Wraps clWaitForEvents().
2998
 */
2999
inline static cl_int
3000
WaitForEvents(const VECTOR_CLASS<Event>& events)
3001
{
3002
    return detail::errHandler(
3003
        ::clWaitForEvents(
3004
            (cl_uint) events.size(), (events.size() > 0) ? (cl_event*)&events.front() : NULL),
3005
        __WAIT_FOR_EVENTS_ERR);
3006
}
3007

3008
/*! \brief Class interface for cl_mem.
3009
 *
3010
 *  \note Copies of these objects are shallow, meaning that the copy will refer
3011
 *        to the same underlying cl_mem as the original.  For details, see
3012
 *        clRetainMemObject() and clReleaseMemObject().
3013
 *
3014
 *  \see cl_mem
3015
 */
3016
class Memory : public detail::Wrapper<cl_mem>
3017
{
3018
public:
3019
    //! \brief Default constructor - initializes to NULL.
3020
    Memory() : detail::Wrapper<cl_type>() { }
3021

3022
    /*! \brief Constructor from cl_mem - takes ownership.
3023
     * 
3024
     *  This effectively transfers ownership of a refcount on the cl_mem
3025
     *  into the new Memory object.
3026
     */
3027
    __CL_EXPLICIT_CONSTRUCTORS Memory(const cl_mem& memory) : detail::Wrapper<cl_type>(memory) { }
3028

3029
    /*! \brief Assignment operator from cl_mem - takes ownership.
3030
     *
3031
     *  This effectively transfers ownership of a refcount on the rhs and calls
3032
     *  clReleaseMemObject() on the value previously held by this instance.
3033
     */
3034
    Memory& operator = (const cl_mem& rhs)
3035
    {
3036
        detail::Wrapper<cl_type>::operator=(rhs);
3037
        return *this;
3038
    }
3039

3040
    /*! \brief Copy constructor to forward copy to the superclass correctly.
3041
     * Required for MSVC.
3042
     */
3043
    Memory(const Memory& mem) : detail::Wrapper<cl_type>(mem) {}
3044

3045
    /*! \brief Copy assignment to forward copy to the superclass correctly.
3046
     * Required for MSVC.
3047
     */
3048
    Memory& operator = (const Memory &mem)
3049
    {
3050
        detail::Wrapper<cl_type>::operator=(mem);
3051
        return *this;
3052
    }
3053

3054
#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED)
3055
    /*! \brief Move constructor to forward move to the superclass correctly.
3056
     * Required for MSVC.
3057
     */
3058
    Memory(Memory&& mem) CL_HPP_NOEXCEPT : detail::Wrapper<cl_type>(std::move(mem)) {}
3059

3060
    /*! \brief Move assignment to forward move to the superclass correctly.
3061
     * Required for MSVC.
3062
     */
3063
    Memory& operator = (Memory &&mem)
3064
    {
3065
        detail::Wrapper<cl_type>::operator=(std::move(mem));
3066
        return *this;
3067
    }
3068
#endif // #if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED)
3069

3070
    //! \brief Wrapper for clGetMemObjectInfo().
3071
    template <typename T>
3072
    cl_int getInfo(cl_mem_info name, T* param) const
3073
    {
3074
        return detail::errHandler(
3075
            detail::getInfo(&::clGetMemObjectInfo, object_, name, param),
3076
            __GET_MEM_OBJECT_INFO_ERR);
3077
    }
3078

3079
    //! \brief Wrapper for clGetMemObjectInfo() that returns by value.
3080
    template <cl_int name> typename
3081
    detail::param_traits<detail::cl_mem_info, name>::param_type
3082
    getInfo(cl_int* err = NULL) const
3083
    {
3084
        typename detail::param_traits<
3085
            detail::cl_mem_info, name>::param_type param;
3086
        cl_int result = getInfo(name, &param);
3087
        if (err != NULL) {
3088
            *err = result;
3089
        }
3090
        return param;
3091
    }
3092

3093
#if defined(CL_VERSION_1_1)
3094
    /*! \brief Registers a callback function to be called when the memory object
3095
     *         is no longer needed.
3096
     *
3097
     *  Wraps clSetMemObjectDestructorCallback().
3098
     *
3099
     *  Repeated calls to this function, for a given cl_mem value, will append
3100
     *  to the list of functions called (in reverse order) when memory object's
3101
     *  resources are freed and the memory object is deleted.
3102
     *
3103
     *  \note
3104
     *  The registered callbacks are associated with the underlying cl_mem
3105
     *  value - not the Memory class instance.
3106
     */
3107
    cl_int setDestructorCallback(
3108
        void (CL_CALLBACK * pfn_notify)(cl_mem, void *),		
3109
        void * user_data = NULL)
3110
    {
3111
        return detail::errHandler(
3112
            ::clSetMemObjectDestructorCallback(
3113
                object_,
3114
                pfn_notify,
3115
                user_data), 
3116
            __SET_MEM_OBJECT_DESTRUCTOR_CALLBACK_ERR);
3117
    }
3118
#endif
3119

3120
};
3121

3122
// Pre-declare copy functions
3123
class Buffer;
3124
template< typename IteratorType >
3125
cl_int copy( IteratorType startIterator, IteratorType endIterator, cl::Buffer &buffer );
3126
template< typename IteratorType >
3127
cl_int copy( const cl::Buffer &buffer, IteratorType startIterator, IteratorType endIterator );
3128
template< typename IteratorType >
3129
cl_int copy( const CommandQueue &queue, IteratorType startIterator, IteratorType endIterator, cl::Buffer &buffer );
3130
template< typename IteratorType >
3131
cl_int copy( const CommandQueue &queue, const cl::Buffer &buffer, IteratorType startIterator, IteratorType endIterator );
3132

3133

3134
/*! \brief Class interface for Buffer Memory Objects.
3135
 * 
3136
 *  See Memory for details about copy semantics, etc.
3137
 *
3138
 *  \see Memory
3139
 */
3140
class Buffer : public Memory
3141
{
3142
public:
3143

3144
    /*! \brief Constructs a Buffer in a specified context.
3145
     *
3146
     *  Wraps clCreateBuffer().
3147
     *
3148
     *  \param host_ptr Storage to be used if the CL_MEM_USE_HOST_PTR flag was
3149
     *                  specified.  Note alignment & exclusivity requirements.
3150
     */
3151
    Buffer(
3152
        const Context& context,
3153
        cl_mem_flags flags,
3154
        ::size_t size,
3155
        void* host_ptr = NULL,
3156
        cl_int* err = NULL)
3157
    {
3158
        cl_int error;
3159
        object_ = ::clCreateBuffer(context(), flags, size, host_ptr, &error);
3160

3161
        detail::errHandler(error, __CREATE_BUFFER_ERR);
3162
        if (err != NULL) {
3163
            *err = error;
3164
        }
3165
    }
3166

3167
    /*! \brief Constructs a Buffer in the default context.
3168
     *
3169
     *  Wraps clCreateBuffer().
3170
     *
3171
     *  \param host_ptr Storage to be used if the CL_MEM_USE_HOST_PTR flag was
3172
     *                  specified.  Note alignment & exclusivity requirements.
3173
     *
3174
     *  \see Context::getDefault()
3175
     */
3176
    Buffer(
3177
         cl_mem_flags flags,
3178
        ::size_t size,
3179
        void* host_ptr = NULL,
3180
        cl_int* err = NULL)
3181
    {
3182
        cl_int error;
3183

3184
        Context context = Context::getDefault(err);
3185

3186
        object_ = ::clCreateBuffer(context(), flags, size, host_ptr, &error);
3187

3188
        detail::errHandler(error, __CREATE_BUFFER_ERR);
3189
        if (err != NULL) {
3190
            *err = error;
3191
        }
3192
    }
3193

3194
    /*!
3195
     * \brief Construct a Buffer from a host container via iterators.
3196
     * IteratorType must be random access.
3197
     * If useHostPtr is specified iterators must represent contiguous data.
3198
     */
3199
    template< typename IteratorType >
3200
    Buffer(
3201
        IteratorType startIterator,
3202
        IteratorType endIterator,
3203
        bool readOnly,
3204
        bool useHostPtr = false,
3205
        cl_int* err = NULL)
3206
    {
3207
        typedef typename std::iterator_traits<IteratorType>::value_type DataType;
3208
        cl_int error;
3209

3210
        cl_mem_flags flags = 0;
3211
        if( readOnly ) {
3212
            flags |= CL_MEM_READ_ONLY;
3213
        }
3214
        else {
3215
            flags |= CL_MEM_READ_WRITE;
3216
        }
3217
        if( useHostPtr ) {
3218
            flags |= CL_MEM_USE_HOST_PTR;
3219
        }
3220
        
3221
        ::size_t size = sizeof(DataType)*(endIterator - startIterator);
3222

3223
        Context context = Context::getDefault(err);
3224

3225
        if( useHostPtr ) {
3226
            object_ = ::clCreateBuffer(context(), flags, size, static_cast<DataType*>(&*startIterator), &error);
3227
        } else {
3228
            object_ = ::clCreateBuffer(context(), flags, size, 0, &error);
3229
        }
3230

3231
        detail::errHandler(error, __CREATE_BUFFER_ERR);
3232
        if (err != NULL) {
3233
            *err = error;
3234
        }
3235

3236
        if( !useHostPtr ) {
3237
            error = cl::copy(startIterator, endIterator, *this);
3238
            detail::errHandler(error, __CREATE_BUFFER_ERR);
3239
            if (err != NULL) {
3240
                *err = error;
3241
            }
3242
        }
3243
    }
3244

3245
    /*!
3246
     * \brief Construct a Buffer from a host container via iterators using a specified context.
3247
     * IteratorType must be random access.
3248
     * If useHostPtr is specified iterators must represent contiguous data.
3249
     */
3250
    template< typename IteratorType >
3251
    Buffer(const Context &context, IteratorType startIterator, IteratorType endIterator,
3252
        bool readOnly, bool useHostPtr = false, cl_int* err = NULL);
3253

3254
    /*!
3255
    * \brief Construct a Buffer from a host container via iterators using a specified queue.
3256
    * If useHostPtr is specified iterators must represent contiguous data.
3257
    */
3258
    template< typename IteratorType >
3259
    Buffer(const CommandQueue &queue, IteratorType startIterator, IteratorType endIterator,
3260
        bool readOnly, bool useHostPtr = false, cl_int* err = NULL);
3261

3262
    //! \brief Default constructor - initializes to NULL.
3263
    Buffer() : Memory() { }
3264

3265
    /*! \brief Constructor from cl_mem - takes ownership.
3266
     *
3267
     *  See Memory for further details.
3268
     */
3269
    __CL_EXPLICIT_CONSTRUCTORS Buffer(const cl_mem& buffer) : Memory(buffer) { }
3270

3271
    /*! \brief Assignment from cl_mem - performs shallow copy.
3272
     *
3273
     *  See Memory for further details.
3274
     */
3275
    Buffer& operator = (const cl_mem& rhs)
3276
    {
3277
        Memory::operator=(rhs);
3278
        return *this;
3279
    }
3280
    
3281
    /*! \brief Copy constructor to forward copy to the superclass correctly.
3282
     * Required for MSVC.
3283
     */
3284
    Buffer(const Buffer& buf) : Memory(buf) {}
3285

3286
    /*! \brief Copy assignment to forward copy to the superclass correctly.
3287
     * Required for MSVC.
3288
     */
3289
    Buffer& operator = (const Buffer &buf)
3290
    {
3291
        Memory::operator=(buf);
3292
        return *this;
3293
    }
3294
    
3295
#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED)
3296
    /*! \brief Move constructor to forward move to the superclass correctly.
3297
     * Required for MSVC.
3298
     */
3299
    Buffer(Buffer&& buf) CL_HPP_NOEXCEPT : Memory(std::move(buf)) {}
3300

3301
    /*! \brief Move assignment to forward move to the superclass correctly.
3302
     * Required for MSVC.
3303
     */
3304
    Buffer& operator = (Buffer &&buf)
3305
    {
3306
        Memory::operator=(std::move(buf));
3307
        return *this;
3308
    }
3309
#endif // #if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED)
3310

3311
#if defined(CL_VERSION_1_1)
3312
    /*! \brief Creates a new buffer object from this.
3313
     *
3314
     *  Wraps clCreateSubBuffer().
3315
     */
3316
    Buffer createSubBuffer(
3317
        cl_mem_flags flags,
3318
        cl_buffer_create_type buffer_create_type,
3319
        const void * buffer_create_info,
3320
        cl_int * err = NULL)
3321
    {
3322
        Buffer result;
3323
        cl_int error;
3324
        result.object_ = ::clCreateSubBuffer(
3325
            object_, 
3326
            flags, 
3327
            buffer_create_type, 
3328
            buffer_create_info, 
3329
            &error);
3330

3331
        detail::errHandler(error, __CREATE_SUBBUFFER_ERR);
3332
        if (err != NULL) {
3333
            *err = error;
3334
        }
3335

3336
        return result;
3337
    }		
3338
#endif
3339
};
3340

3341
#if defined (USE_DX_INTEROP)
3342
/*! \brief Class interface for creating OpenCL buffers from ID3D10Buffer's.
3343
 *
3344
 *  This is provided to facilitate interoperability with Direct3D.
3345
 * 
3346
 *  See Memory for details about copy semantics, etc.
3347
 *
3348
 *  \see Memory
3349
 */
3350
class BufferD3D10 : public Buffer
3351
{
3352
public:
3353
    typedef CL_API_ENTRY cl_mem (CL_API_CALL *PFN_clCreateFromD3D10BufferKHR)(
3354
    cl_context context, cl_mem_flags flags, ID3D10Buffer*  buffer,
3355
    cl_int* errcode_ret);
3356

3357
    /*! \brief Constructs a BufferD3D10, in a specified context, from a
3358
     *         given ID3D10Buffer.
3359
     *
3360
     *  Wraps clCreateFromD3D10BufferKHR().
3361
     */
3362
    BufferD3D10(
3363
        const Context& context,
3364
        cl_mem_flags flags,
3365
        ID3D10Buffer* bufobj,
3366
        cl_int * err = NULL)
3367
    {
3368
        static PFN_clCreateFromD3D10BufferKHR pfn_clCreateFromD3D10BufferKHR = NULL;
3369

3370
#if defined(CL_VERSION_1_2)
3371
        vector<cl_context_properties> props = context.getInfo<CL_CONTEXT_PROPERTIES>();
3372
        cl_platform platform = -1;
3373
        for( int i = 0; i < props.size(); ++i ) {
3374
            if( props[i] == CL_CONTEXT_PLATFORM ) {
3375
                platform = props[i+1];
3376
            }
3377
        }
3378
        __INIT_CL_EXT_FCN_PTR_PLATFORM(platform, clCreateFromD3D10BufferKHR);
3379
#endif
3380
#if defined(CL_VERSION_1_1)
3381
        __INIT_CL_EXT_FCN_PTR(clCreateFromD3D10BufferKHR);
3382
#endif
3383

3384
        cl_int error;
3385
        object_ = pfn_clCreateFromD3D10BufferKHR(
3386
            context(),
3387
            flags,
3388
            bufobj,
3389
            &error);
3390

3391
        detail::errHandler(error, __CREATE_GL_BUFFER_ERR);
3392
        if (err != NULL) {
3393
            *err = error;
3394
        }
3395
    }
3396

3397
    //! \brief Default constructor - initializes to NULL.
3398
    BufferD3D10() : Buffer() { }
3399

3400
    /*! \brief Constructor from cl_mem - takes ownership.
3401
     *
3402
     *  See Memory for further details.
3403
     */
3404
    __CL_EXPLICIT_CONSTRUCTORS BufferD3D10(const cl_mem& buffer) : Buffer(buffer) { }
3405

3406
    /*! \brief Assignment from cl_mem - performs shallow copy.
3407
     *
3408
     *  See Memory for further details.
3409
     */
3410
    BufferD3D10& operator = (const cl_mem& rhs)
3411
    {
3412
        Buffer::operator=(rhs);
3413
        return *this;
3414
    }
3415

3416
    /*! \brief Copy constructor to forward copy to the superclass correctly.
3417
    * Required for MSVC.
3418
    */
3419
    BufferD3D10(const BufferD3D10& buf) : Buffer(buf) {}
3420

3421
    /*! \brief Copy assignment to forward copy to the superclass correctly.
3422
    * Required for MSVC.
3423
    */
3424
    BufferD3D10& operator = (const BufferD3D10 &buf)
3425
    {
3426
        Buffer::operator=(buf);
3427
        return *this;
3428
    }
3429

3430
#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED)
3431
    /*! \brief Move constructor to forward move to the superclass correctly.
3432
    * Required for MSVC.
3433
    */
3434
    BufferD3D10(BufferD3D10&& buf) CL_HPP_NOEXCEPT : Buffer(std::move(buf)) {}
3435

3436
    /*! \brief Move assignment to forward move to the superclass correctly.
3437
    * Required for MSVC.
3438
    */
3439
    BufferD3D10& operator = (BufferD3D10 &&buf)
3440
    {
3441
        Buffer::operator=(std::move(buf));
3442
        return *this;
3443
    }
3444
#endif // #if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED)
3445
};
3446
#endif
3447

3448
/*! \brief Class interface for GL Buffer Memory Objects.
3449
 *
3450
 *  This is provided to facilitate interoperability with OpenGL.
3451
 * 
3452
 *  See Memory for details about copy semantics, etc.
3453
 * 
3454
 *  \see Memory
3455
 */
3456
class BufferGL : public Buffer
3457
{
3458
public:
3459
    /*! \brief Constructs a BufferGL in a specified context, from a given
3460
     *         GL buffer.
3461
     *
3462
     *  Wraps clCreateFromGLBuffer().
3463
     */
3464
    BufferGL(
3465
        const Context& context,
3466
        cl_mem_flags flags,
3467
        cl_GLuint bufobj,
3468
        cl_int * err = NULL)
3469
    {
3470
        cl_int error;
3471
        object_ = ::clCreateFromGLBuffer(
3472
            context(),
3473
            flags,
3474
            bufobj,
3475
            &error);
3476

3477
        detail::errHandler(error, __CREATE_GL_BUFFER_ERR);
3478
        if (err != NULL) {
3479
            *err = error;
3480
        }
3481
    }
3482

3483
    //! \brief Default constructor - initializes to NULL.
3484
    BufferGL() : Buffer() { }
3485

3486
    /*! \brief Constructor from cl_mem - takes ownership.
3487
     *
3488
     *  See Memory for further details.
3489
     */
3490
    __CL_EXPLICIT_CONSTRUCTORS BufferGL(const cl_mem& buffer) : Buffer(buffer) { }
3491

3492
    /*! \brief Assignment from cl_mem - performs shallow copy.
3493
     *
3494
     *  See Memory for further details.
3495
     */
3496
    BufferGL& operator = (const cl_mem& rhs)
3497
    {
3498
        Buffer::operator=(rhs);
3499
        return *this;
3500
    }
3501

3502
    /*! \brief Copy constructor to forward copy to the superclass correctly.
3503
    * Required for MSVC.
3504
    */
3505
    BufferGL(const BufferGL& buf) : Buffer(buf) {}
3506

3507
    /*! \brief Copy assignment to forward copy to the superclass correctly.
3508
    * Required for MSVC.
3509
    */
3510
    BufferGL& operator = (const BufferGL &buf)
3511
    {
3512
        Buffer::operator=(buf);
3513
        return *this;
3514
    }
3515

3516
#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED)
3517
    /*! \brief Move constructor to forward move to the superclass correctly.
3518
    * Required for MSVC.
3519
    */
3520
    BufferGL(BufferGL&& buf) CL_HPP_NOEXCEPT : Buffer(std::move(buf)) {}
3521

3522
    /*! \brief Move assignment to forward move to the superclass correctly.
3523
    * Required for MSVC.
3524
    */
3525
    BufferGL& operator = (BufferGL &&buf)
3526
    {
3527
        Buffer::operator=(std::move(buf));
3528
        return *this;
3529
    }
3530
#endif // #if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED)
3531

3532
    //! \brief Wrapper for clGetGLObjectInfo().
3533
    cl_int getObjectInfo(
3534
        cl_gl_object_type *type,
3535
        cl_GLuint * gl_object_name)
3536
    {
3537
        return detail::errHandler(
3538
            ::clGetGLObjectInfo(object_,type,gl_object_name),
3539
            __GET_GL_OBJECT_INFO_ERR);
3540
    }
3541
};
3542

3543
/*! \brief C++ base class for Image Memory objects.
3544
 *
3545
 *  See Memory for details about copy semantics, etc.
3546
 * 
3547
 *  \see Memory
3548
 */
3549
class Image : public Memory
3550
{
3551
protected:
3552
    //! \brief Default constructor - initializes to NULL.
3553
    Image() : Memory() { }
3554

3555
    /*! \brief Constructor from cl_mem - takes ownership.
3556
     *
3557
     *  See Memory for further details.
3558
     */
3559
    __CL_EXPLICIT_CONSTRUCTORS Image(const cl_mem& image) : Memory(image) { }
3560

3561
    /*! \brief Assignment from cl_mem - performs shallow copy.
3562
     *
3563
     *  See Memory for further details.
3564
     */
3565
    Image& operator = (const cl_mem& rhs)
3566
    {
3567
        Memory::operator=(rhs);
3568
        return *this;
3569
    }
3570

3571
    /*! \brief Copy constructor to forward copy to the superclass correctly.
3572
     * Required for MSVC.
3573
     */
3574
    Image(const Image& img) : Memory(img) {}
3575

3576
    /*! \brief Copy assignment to forward copy to the superclass correctly.
3577
     * Required for MSVC.
3578
     */
3579
    Image& operator = (const Image &img)
3580
    {
3581
        Memory::operator=(img);
3582
        return *this;
3583
    }
3584

3585
#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED)
3586
    /*! \brief Move constructor to forward move to the superclass correctly.
3587
     * Required for MSVC.
3588
     */
3589
    Image(Image&& img) CL_HPP_NOEXCEPT : Memory(std::move(img)) {}
3590

3591
    /*! \brief Move assignment to forward move to the superclass correctly.
3592
     * Required for MSVC.
3593
     */
3594
    Image& operator = (Image &&img)
3595
    {
3596
        Memory::operator=(std::move(img));
3597
        return *this;
3598
    }
3599
#endif // #if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED)
3600

3601
public:
3602
    //! \brief Wrapper for clGetImageInfo().
3603
    template <typename T>
3604
    cl_int getImageInfo(cl_image_info name, T* param) const
3605
    {
3606
        return detail::errHandler(
3607
            detail::getInfo(&::clGetImageInfo, object_, name, param),
3608
            __GET_IMAGE_INFO_ERR);
3609
    }
3610
    
3611
    //! \brief Wrapper for clGetImageInfo() that returns by value.
3612
    template <cl_int name> typename
3613
    detail::param_traits<detail::cl_image_info, name>::param_type
3614
    getImageInfo(cl_int* err = NULL) const
3615
    {
3616
        typename detail::param_traits<
3617
            detail::cl_image_info, name>::param_type param;
3618
        cl_int result = getImageInfo(name, &param);
3619
        if (err != NULL) {
3620
            *err = result;
3621
        }
3622
        return param;
3623
    }
3624
};
3625

3626
#if defined(CL_VERSION_1_2)
3627
/*! \brief Class interface for 1D Image Memory objects.
3628
 *
3629
 *  See Memory for details about copy semantics, etc.
3630
 * 
3631
 *  \see Memory
3632
 */
3633
class Image1D : public Image
3634
{
3635
public:
3636
    /*! \brief Constructs a 1D Image in a specified context.
3637
     *
3638
     *  Wraps clCreateImage().
3639
     */
3640
    Image1D(
3641
        const Context& context,
3642
        cl_mem_flags flags,
3643
        ImageFormat format,
3644
        ::size_t width,
3645
        void* host_ptr = NULL,
3646
        cl_int* err = NULL)
3647
    {
3648
        cl_int error;
3649
        cl_image_desc desc =
3650
        {
3651
            CL_MEM_OBJECT_IMAGE1D,
3652
            width,
3653
            0, 0, 0, 0, 0, 0, 0, 0
3654
        };
3655
        object_ = ::clCreateImage(
3656
            context(), 
3657
            flags, 
3658
            &format