在OpenCL SDK根目录下的samples/template,存有程序的模板,其中“template.cpp”是宿主机代码模板,“assets/template.cl”是内核代码模板。“template.cpp”使用了common目录下的“common.cpp”库来建立环境。
1. 设置OpenCL环境
1.1 创建上下文
在第一个可用平台上创建一个上下文。
if (!createContext(&context))
{
cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numMemoryObjects);
cerr << "Failed to create an OpenCL context. " << __FILE__ << ":"<< __LINE__ << endl;
return 1;
}
1.2 创建命令队列
创建一个命令队列,排队到设备队列中。
if (!createCommandQueue(context, &commandQueue, &device))
{
cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numMemoryObjects);
cerr << "Failed to create the OpenCL command queue. " << __FILE__ << ":"<< __LINE__ << endl;
return 1;
}
1.3 创建程序对象
根据一个给定文件创建一个程序对象并编译。
if (!createProgram(context, device, "assets/template.cl", &program))
{
cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numMemoryObjects);
cerr << "Failed to create OpenCL program." << __FILE__ << ":"<< __LINE__ << endl;
return 1;
}
1.4 创建内核对象
为内核函数创建一个内核对象。
kernel = clCreateKernel(program, "template", &errorNumber);
if (!checkSuccess(errorNumber))
{
cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numMemoryObjects);
cerr << "Failed to create OpenCL kernel. " << __FILE__ << ":"<< __LINE__ << endl;
return 1;
}
2. 设置内存与数据
2.1 创建内存缓冲区
为任何你需要从设备中访问的数据请求内存缓冲区,更多信息参考样例"hello world"。
2.2 初始化输入数据
如果你需要从CPU端初始化数据,那么你需要:
a. 映射缓冲区到本地指针;
b. 使用映射的指针初始化数据;
c. 取消映射。
更多信息参考样例"hello world"。
2.3 设置内核参数
传递内存缓冲区或其它变量到内核对象,以作为参数。更多信息参考样例"hello world"。
3. 执行内核实例
3.1 定义内核实例数量
globalWorkSize决定运行多少个内核实例。
const int workDimensions = 1;
size_t globalWorkSize[workDimensions] = {1};
3.2 内核入队
内核入队等待执行,为获取检索信息,我们定义一个cl_event,并把它传递到clEnqueueNDRangeKernel()。
/* An event to associate with the kernel. Allows us to retrieve profiling information later. */
cl_event event = 0;
if (!checkSuccess(clEnqueueNDRangeKernel(commandQueue, kernel, workDimensions, NULL, globalWorkSize, NULL, 0, NULL, &event)))
{
cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numMemoryObjects);
cerr << "Failed enqueuing the kernel. " << __FILE__ << ":"<< __LINE__ << endl;
return 1;
}
3.3 等待内核执行
等待直到所有的内核实例执行完成。注意,这可能并不需要,具体取决于应用场合。
if (!checkSuccess(clFinish(commandQueue)))
{
cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numMemoryObjects);
cerr << "Failed waiting for kernel execution to finish. " << __FILE__ << ":"<< __LINE__ << endl;
return 1;
}
4. 内核执行后
4.1 打印检索信息
打印事件的检索信息(排队,等待和运行时间)。
printProfilingInfo(event);
/* Release the event object. */
if (!checkSuccess(clReleaseEvent(event)))
{
cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numMemoryObjects);
cerr << "Failed releasing the event object. " << __FILE__ << ":"<< __LINE__ << endl;
return 1;
}
4.2 检索结果
为了在CPU端访问计算结果,那么你需要:
a. 映射缓冲区到本地指针;
b. 使用映射的指针初始化数据;
c. 取消映射。
更多信息参考样例"hello world"。
4.3 释放OpenCL对象
释放任何已创建的OpenCL对象。
cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numMemoryObjects);
5. 样例运行
参考样例"hello world":http://blog.csdn.net/cloud_desktop/article/details/20048917
6. 模板源代码
6.1 宿主机源代码
/*
* This confidential and proprietary software may be used only as
* authorised by a licensing agreement from ARM Limited
* (C) COPYRIGHT 2013 ARM Limited
* ALL RIGHTS RESERVED
* The entire notice above must be reproduced on all authorised
* copies and copies may only be made to the extent permitted
* by a licensing agreement from ARM Limited.
*/
#include "common.h"
#include "image.h"
#include <CL/cl.h>
#include <iostream>
using namespace std;
/**
* \brief Simple template OpenCL sample.
* \details The basic code to run a kernel with no arguments.
* \return The exit code of the application, non-zero if a problem occurred.
*/
int main(void)
{
cl_context context = 0;
cl_command_queue commandQueue = 0;
cl_program program = 0;
cl_device_id device = 0;
cl_kernel kernel = 0;
const int numMemoryObjects = 1;
cl_mem memoryObjects[numMemoryObjects] = {0};
cl_int errorNumber;
/* Set up OpenCL environment: create context, command queue, program and kernel. */
/* [Create Context] */
if (!createContext(&context))
{
cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numMemoryObjects);
cerr << "Failed to create an OpenCL context. " << __FILE__ << ":"<< __LINE__ << endl;
return 1;
}
/* [Create Context] */
/* [Create Command Queue] */
if (!createCommandQueue(context, &commandQueue, &device))
{
cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numMemoryObjects);
cerr << "Failed to create the OpenCL command queue. " << __FILE__ << ":"<< __LINE__ << endl;
return 1;
}
/* [Create Command Queue] */
/* [Create Program] */
if (!createProgram(context, device, "assets/template.cl", &program))
{
cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numMemoryObjects);
cerr << "Failed to create OpenCL program." << __FILE__ << ":"<< __LINE__ << endl;
return 1;
}
/* [Create Program] */
/* [Create kernel] */
kernel = clCreateKernel(program, "template", &errorNumber);
if (!checkSuccess(errorNumber))
{
cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numMemoryObjects);
cerr << "Failed to create OpenCL kernel. " << __FILE__ << ":"<< __LINE__ << endl;
return 1;
}
/* [Create kernel] */
/*
* Add code here to set up memory/data, for example:
* - Create memory buffers.
* - Initialise the input data.
* - Set up kernel arguments.
*/
/* Execute the kernel instances. */
/* [Set the kernel work size] */
const int workDimensions = 1;
size_t globalWorkSize[workDimensions] = {1};
/* [Set the kernel work size] */
/* [Enqueue the kernel] */
/* An event to associate with the kernel. Allows us to retrieve profiling information later. */
cl_event event = 0;
if (!checkSuccess(clEnqueueNDRangeKernel(commandQueue, kernel, workDimensions, NULL, globalWorkSize, NULL, 0, NULL, &event)))
{
cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numMemoryObjects);
cerr << "Failed enqueuing the kernel. " << __FILE__ << ":"<< __LINE__ << endl;
return 1;
}
/* [Enqueue the kernel] */
/* [Wait for kernel execution completion] */
if (!checkSuccess(clFinish(commandQueue)))
{
cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numMemoryObjects);
cerr << "Failed waiting for kernel execution to finish. " << __FILE__ << ":"<< __LINE__ << endl;
return 1;
}
/* [Wait for kernel execution completion] */
/* After execution. */
/* [Print the profiling information for the event] */
printProfilingInfo(event);
/* Release the event object. */
if (!checkSuccess(clReleaseEvent(event)))
{
cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numMemoryObjects);
cerr << "Failed releasing the event object. " << __FILE__ << ":"<< __LINE__ << endl;
return 1;
}
/* [Print the profiling information for the event] */
/* Add code here to retrieve results of the kernel execution. */
/* [Release OpenCL objects] */
cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numMemoryObjects);
/* [Release OpenCL objects] */
return 0;
}
6.2 common.cpp库源代码
/*
* This confidential and proprietary software may be used only as
* authorised by a licensing agreement from ARM Limited
* (C) COPYRIGHT 2013 ARM Limited
* ALL RIGHTS RESERVED
* The entire notice above must be reproduced on all authorised
* copies and copies may only be made to the extent permitted
* by a licensing agreement from ARM Limited.
*/
#include "common.h"
#include <iostream>
#include <sstream>
#include <fstream>
using namespace std;
bool printProfilingInfo(cl_event event)
{
cl_ulong queuedTime = 0;
if (!checkSuccess(clGetEventProfilingInfo(event, CL_PROFILING_COMMAND_QUEUED, sizeof(cl_ulong), &queuedTime, NULL)))
{
cerr << "Retrieving CL_PROFILING_COMMAND_QUEUED OpenCL profiling information failed. " << __FILE__ << ":"<< __LINE__ << endl;
return false;
}
cl_ulong submittedTime = 0;
if (!checkSuccess(clGetEventProfilingInfo(event, CL_PROFILING_COMMAND_SUBMIT, sizeof(cl_ulong), &submittedTime, NULL)))
{
cerr << "Retrieving CL_PROFILING_COMMAND_SUBMIT OpenCL profiling information failed. " << __FILE__ << ":"<< __LINE__ << endl;
return false;
}
cl_ulong startTime = 0;
if (!checkSuccess(clGetEventProfilingInfo(event, CL_PROFILING_COMMAND_START, sizeof(cl_ulong), &startTime, NULL)))
{
cerr << "Retrieving CL_PROFILING_COMMAND_START OpenCL profiling information failed. " << __FILE__ << ":"<< __LINE__ << endl;
return false;
}
cl_ulong endTime = 0;
if (!checkSuccess(clGetEventProfilingInfo(event, CL_PROFILING_COMMAND_END, sizeof(cl_ulong), &endTime, NULL)))
{
cerr << "Retrieving CL_PROFILING_COMMAND_END OpenCL profiling information failed. " << __FILE__ << ":"<< __LINE__ << endl;
return false;
}
cout << "Profiling information:\n";
/* OpenCL returns times in nano seconds. Print out the times in milliseconds (divide by a million). */
cout << "Queued time: \t" << (submittedTime - queuedTime) / 1000000.0 << "ms\n";
cout << "Wait time: \t" << (startTime - submittedTime) / 1000000.0 << "ms\n";
cout << "Run time: \t" << (endTime - startTime) / 1000000.0 << "ms" << endl;
return true;
}
bool printSupported2DImageFormats(cl_context context)
{
/* Get the number of supported image formats in order to allocate the correct amount of memory. */
cl_uint numberOfImageFormats;
if (!checkSuccess(clGetSupportedImageFormats(context, 0, CL_MEM_OBJECT_IMAGE2D, 0, NULL, &numberOfImageFormats)))
{
cerr << "Getting the number of supported 2D image formats failed. " << __FILE__ << ":"<< __LINE__ << endl;
return false;
}
/* Get the list of supported image formats. */
cl_image_format* imageFormats = new cl_image_format[numberOfImageFormats];
if (!checkSuccess(clGetSupportedImageFormats(context, 0, CL_MEM_OBJECT_IMAGE3D, numberOfImageFormats, imageFormats, NULL)))
{
cerr << "Getting the list of supported 2D image formats failed. " << __FILE__ << ":"<< __LINE__ << endl;
return false;
}
cout << numberOfImageFormats << " Image formats supported";
if (numberOfImageFormats > 0)
{
cout << " (channel order, channel data type):" << endl;
}
else
{
cout << "." << endl;
}
for (unsigned int i = 0; i < numberOfImageFormats; i++)
{
cout << imageChannelOrderToString(imageFormats[i].image_channel_order) << ", " << imageChannelDataTypeToString(imageFormats[i].image_channel_data_type) << endl;
}
delete[] imageFormats;
return true;
}
string imageChannelOrderToString(cl_channel_order channelOrder)
{
switch (channelOrder)
{
case CL_R:
return "CL_R";
case CL_A:
return "CL_A";
case CL_RG:
return "CL_RG";
case CL_RA:
return "CL_RA";
case CL_RGB:
return "CL_RGB";
case CL_RGBA:
return "CL_RGBA";
case CL_BGRA:
return "CL_BGRA";
case CL_ARGB:
return "CL_ARGB";
case CL_INTENSITY:
return "CL_INTENSITY";
case CL_LUMINANCE:
return "CL_LUMINANCE";
case CL_Rx:
return "CL_Rx";
case CL_RGx:
return "CL_RGx";
case CL_RGBx:
return "CL_RGBx";
default:
return "Unknown image channel order";
}
}
string imageChannelDataTypeToString(cl_channel_type channelDataType)
{
switch (channelDataType)
{
case CL_SNORM_INT8:
return "CL_SNORM_INT8";
case CL_SNORM_INT16:
return "CL_SNORM_INT16";
case CL_UNORM_INT8:
return "CL_UNORM_INT8";
case CL_UNORM_INT16:
return "CL_UNORM_INT16";
case CL_UNORM_SHORT_565:
return "CL_UNORM_SHORT_565";
case CL_UNORM_SHORT_555:
return "CL_UNORM_SHORT_555";
case CL_UNORM_INT_101010:
return "CL_UNORM_INT_101010";
case CL_SIGNED_INT8:
return "CL_SIGNED_INT8";
case CL_SIGNED_INT16:
return "CL_SIGNED_INT16";
case CL_SIGNED_INT32:
return "CL_SIGNED_INT32";
case CL_UNSIGNED_INT8:
return "CL_UNSIGNED_INT8";
case CL_UNSIGNED_INT16:
return "CL_UNSIGNED_INT16";
case CL_UNSIGNED_INT32:
return "CL_UNSIGNED_INT32";
case CL_HALF_FLOAT:
return "CL_HALF_FLOAT";
case CL_FLOAT:
return "CL_FLOAT";
default:
return "Unknown image channel data type";
}
}
bool cleanUpOpenCL(cl_context context, cl_command_queue commandQueue, cl_program program, cl_kernel kernel, cl_mem* memoryObjects, int numberOfMemoryObjects)
{
bool returnValue = true;
if (context != 0)
{
if (!checkSuccess(clReleaseContext(context)))
{
cerr << "Releasing the OpenCL context failed. " << __FILE__ << ":"<< __LINE__ << endl;
returnValue = false;
}
}
if (commandQueue != 0)
{
if (!checkSuccess(clReleaseCommandQueue(commandQueue)))
{
cerr << "Releasing the OpenCL command queue failed. " << __FILE__ << ":"<< __LINE__ << endl;
returnValue = false;
}
}
if (kernel != 0)
{
if (!checkSuccess(clReleaseKernel(kernel)))
{
cerr << "Releasing the OpenCL kernel failed. " << __FILE__ << ":"<< __LINE__ << endl;
returnValue = false;
}
}
if (program != 0)
{
if (!checkSuccess(clReleaseProgram(program)))
{
cerr << "Releasing the OpenCL program failed. " << __FILE__ << ":"<< __LINE__ << endl;
returnValue = false;
}
}
for (int index = 0; index < numberOfMemoryObjects; index++)
{
if (memoryObjects[index] != 0)
{
if (!checkSuccess(clReleaseMemObject(memoryObjects[index])))
{
cerr << "Releasing the OpenCL memory object " << index << " failed. " << __FILE__ << ":"<< __LINE__ << endl;
returnValue = false;
}
}
}
return returnValue;
}
bool createContext(cl_context* context)
{
cl_int errorNumber = 0;
cl_uint numberOfPlatforms = 0;
cl_platform_id firstPlatformID = 0;
/* Retrieve a single platform ID. */
if (!checkSuccess(clGetPlatformIDs(1, &firstPlatformID, &numberOfPlatforms)))
{
cerr << "Retrieving OpenCL platforms failed. " << __FILE__ << ":"<< __LINE__ << endl;
return false;
}
if (numberOfPlatforms <= 0)
{
cerr << "No OpenCL platforms found. " << __FILE__ << ":"<< __LINE__ << endl;
return false;
}
/* Get a context with a GPU device from the platform found above. */
cl_context_properties contextProperties [] = {CL_CONTEXT_PLATFORM, (cl_context_properties)firstPlatformID, 0};
*context = clCreateContextFromType(contextProperties, CL_DEVICE_TYPE_GPU, NULL, NULL, &errorNumber);
if (!checkSuccess(errorNumber))
{
cerr << "Creating an OpenCL context failed. " << __FILE__ << ":"<< __LINE__ << endl;
return false;
}
return true;
}
bool createCommandQueue(cl_context context, cl_command_queue* commandQueue, cl_device_id* device)
{
cl_int errorNumber = 0;
cl_device_id* devices = NULL;
size_t deviceBufferSize = -1;
/* Retrieve the size of the buffer needed to contain information about the devices in this OpenCL context. */
if (!checkSuccess(clGetContextInfo(context, CL_CONTEXT_DEVICES, 0, NULL, &deviceBufferSize)))
{
cerr << "Failed to get OpenCL context information. " << __FILE__ << ":"<< __LINE__ << endl;
return false;
}
if(deviceBufferSize == 0)
{
cerr << "No OpenCL devices found. " << __FILE__ << ":"<< __LINE__ << endl;
return false;
}
/* Retrieve the list of devices available in this context. */
devices = new cl_device_id[deviceBufferSize / sizeof(cl_device_id)];
if (!checkSuccess(clGetContextInfo(context, CL_CONTEXT_DEVICES, deviceBufferSize, devices, NULL)))
{
cerr << "Failed to get the OpenCL context information. " << __FILE__ << ":"<< __LINE__ << endl;
delete [] devices;
return false;
}
/* Use the first available device in this context. */
*device = devices[0];
delete [] devices;
/* Set up the command queue with the selected device. */
*commandQueue = clCreateCommandQueue(context, *device, CL_QUEUE_PROFILING_ENABLE, &errorNumber);
if (!checkSuccess(errorNumber))
{
cerr << "Failed to create the OpenCL command queue. " << __FILE__ << ":"<< __LINE__ << endl;
return false;
}
return true;
}
bool createProgram(cl_context context, cl_device_id device, string filename, cl_program* program)
{
cl_int errorNumber = 0;
ifstream kernelFile(filename.c_str(), ios::in);
if(!kernelFile.is_open())
{
cerr << "Unable to open " << filename << ". " << __FILE__ << ":"<< __LINE__ << endl;
return false;
}
/*
* Read the kernel file into an output stream.
* Convert this into a char array for passing to OpenCL.
*/
ostringstream outputStringStream;
outputStringStream << kernelFile.rdbuf();
string srcStdStr = outputStringStream.str();
const char* charSource = srcStdStr.c_str();
*program = clCreateProgramWithSource(context, 1, &charSource, NULL, &errorNumber);
if (!checkSuccess(errorNumber) || program == NULL)
{
cerr << "Failed to create OpenCL program. " << __FILE__ << ":"<< __LINE__ << endl;
return false;
}
/* Try to build the OpenCL program. */
bool buildSuccess = checkSuccess(clBuildProgram(*program, 0, NULL, NULL, NULL, NULL));
/* Get the size of the build log. */
size_t logSize = 0;
clGetProgramBuildInfo(*program, device, CL_PROGRAM_BUILD_LOG, 0, NULL, &logSize);
/*
* If the build succeeds with no log, an empty string is returned (logSize = 1),
* we only want to print the message if it has some content (logSize > 1).
*/
if (logSize > 1)
{
char* log = new char[logSize];
clGetProgramBuildInfo(*program, device, CL_PROGRAM_BUILD_LOG, logSize, log, NULL);
string* stringChars = new string(log, logSize);
cerr << "Build log:\n " << *stringChars << endl;
delete[] log;
delete stringChars;
}
if (!buildSuccess)
{
clReleaseProgram(*program);
cerr << "Failed to build OpenCL program. " << __FILE__ << ":"<< __LINE__ << endl;
return false;
}
return true;
}
inline bool checkSuccess(cl_int errorNumber)
{
if (errorNumber != CL_SUCCESS)
{
cerr << "OpenCL error: " << errorNumberToString(errorNumber) << endl;
return false;
}
return true;
}
string errorNumberToString(cl_int errorNumber)
{
switch (errorNumber)
{
case CL_SUCCESS:
return "CL_SUCCESS";
case CL_DEVICE_NOT_FOUND:
return "CL_DEVICE_NOT_FOUND";
case CL_DEVICE_NOT_AVAILABLE:
return "CL_DEVICE_NOT_AVAILABLE";
case CL_COMPILER_NOT_AVAILABLE:
return "CL_COMPILER_NOT_AVAILABLE";
case CL_MEM_OBJECT_ALLOCATION_FAILURE:
return "CL_MEM_OBJECT_ALLOCATION_FAILURE";
case CL_OUT_OF_RESOURCES:
return "CL_OUT_OF_RESOURCES";
case CL_OUT_OF_HOST_MEMORY:
return "CL_OUT_OF_HOST_MEMORY";
case CL_PROFILING_INFO_NOT_AVAILABLE:
return "CL_PROFILING_INFO_NOT_AVAILABLE";
case CL_MEM_COPY_OVERLAP:
return "CL_MEM_COPY_OVERLAP";
case CL_IMAGE_FORMAT_MISMATCH:
return "CL_IMAGE_FORMAT_MISMATCH";
case CL_IMAGE_FORMAT_NOT_SUPPORTED:
return "CL_IMAGE_FORMAT_NOT_SUPPORTED";
case CL_BUILD_PROGRAM_FAILURE:
return "CL_BUILD_PROGRAM_FAILURE";
case CL_MAP_FAILURE:
return "CL_MAP_FAILURE";
case CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST:
return "CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST";
case CL_INVALID_VALUE:
return "CL_INVALID_VALUE";
case CL_INVALID_DEVICE_TYPE:
return "CL_INVALID_DEVICE_TYPE";
case CL_INVALID_PLATFORM:
return "CL_INVALID_PLATFORM";
case CL_INVALID_DEVICE:
return "CL_INVALID_DEVICE";
case CL_INVALID_CONTEXT:
return "CL_INVALID_CONTEXT";
case CL_INVALID_QUEUE_PROPERTIES:
return "CL_INVALID_QUEUE_PROPERTIES";
case CL_INVALID_COMMAND_QUEUE:
return "CL_INVALID_COMMAND_QUEUE";
case CL_INVALID_HOST_PTR:
return "CL_INVALID_HOST_PTR";
case CL_INVALID_MEM_OBJECT:
return "CL_INVALID_MEM_OBJECT";
case CL_INVALID_IMAGE_FORMAT_DESCRIPTOR:
return "CL_INVALID_IMAGE_FORMAT_DESCRIPTOR";
case CL_INVALID_IMAGE_SIZE:
return "CL_INVALID_IMAGE_SIZE";
case CL_INVALID_SAMPLER:
return "CL_INVALID_SAMPLER";
case CL_INVALID_BINARY:
return "CL_INVALID_BINARY";
case CL_INVALID_BUILD_OPTIONS:
return "CL_INVALID_BUILD_OPTIONS";
case CL_INVALID_PROGRAM:
return "CL_INVALID_PROGRAM";
case CL_INVALID_PROGRAM_EXECUTABLE:
return "CL_INVALID_PROGRAM_EXECUTABLE";
case CL_INVALID_KERNEL_NAME:
return "CL_INVALID_KERNEL_NAME";
case CL_INVALID_KERNEL_DEFINITION:
return "CL_INVALID_KERNEL_DEFINITION";
case CL_INVALID_KERNEL:
return "CL_INVALID_KERNEL";
case CL_INVALID_ARG_INDEX:
return "CL_INVALID_ARG_INDEX";
case CL_INVALID_ARG_VALUE:
return "CL_INVALID_ARG_VALUE";
case CL_INVALID_ARG_SIZE:
return "CL_INVALID_ARG_SIZE";
case CL_INVALID_KERNEL_ARGS:
return "CL_INVALID_KERNEL_ARGS";
case CL_INVALID_WORK_DIMENSION:
return "CL_INVALID_WORK_DIMENSION";
case CL_INVALID_WORK_GROUP_SIZE:
return "CL_INVALID_WORK_GROUP_SIZE";
case CL_INVALID_WORK_ITEM_SIZE:
return "CL_INVALID_WORK_ITEM_SIZE";
case CL_INVALID_GLOBAL_OFFSET:
return "CL_INVALID_GLOBAL_OFFSET";
case CL_INVALID_EVENT_WAIT_LIST:
return "CL_INVALID_EVENT_WAIT_LIST";
case CL_INVALID_EVENT:
return "CL_INVALID_EVENT";
case CL_INVALID_OPERATION:
return "CL_INVALID_OPERATION";
case CL_INVALID_GL_OBJECT:
return "CL_INVALID_GL_OBJECT";
case CL_INVALID_BUFFER_SIZE:
return "CL_INVALID_BUFFER_SIZE";
case CL_INVALID_MIP_LEVEL:
return "CL_INVALID_MIP_LEVEL";
default:
return "Unknown error";
}
}
bool isExtensionSupported(cl_device_id device, string extension)
{
if (extension.empty())
{
return false;
}
/* First find out how large the ouput of the OpenCL device query will be. */
size_t extensionsReturnSize = 0;
if (!checkSuccess(clGetDeviceInfo(device, CL_DEVICE_EXTENSIONS, 0, NULL, &extensionsReturnSize)))
{
cerr << "Failed to get return size from clGetDeviceInfo for parameter CL_DEVICE_EXTENSIONS. " << __FILE__ << ":"<< __LINE__ << endl;
return false;
}
/* Allocate enough memory for the output. */
char* extensions = new char[extensionsReturnSize];
/* Get the list of all extensions supported. */
if (!checkSuccess(clGetDeviceInfo(device, CL_DEVICE_EXTENSIONS, extensionsReturnSize, extensions, NULL)))
{
cerr << "Failed to get data from clGetDeviceInfo for parameter CL_DEVICE_EXTENSIONS. " << __FILE__ << ":"<< __LINE__ << endl;
delete [] extensions;
return false;
}
/* See if the requested extension is in the list. */
string* extensionsString = new string(extensions);
bool returnResult = false;
if (extensionsString->find(extension) != string::npos)
{
returnResult = true;
}
delete [] extensions;
delete extensionsString;
return returnResult;
}