00001
00010 #include "compute.h"
00011 #ifdef USE_CL
00012
00013
00014
00015
00016 TCompute::TCompute()
00017 {
00018 maxWorkItemSizes = NULL;
00019 groupSize = 256;
00020 }
00021
00022
00023
00024
00025
00026
00027 string TCompute::LoadSource(const char* source)
00028 {
00029 ifstream fin(source);
00030 if(!fin)
00031 {
00032 string msg = "Cannot open kernel source ";
00033 msg += source;
00034 ShowMessage(msg.c_str(), false);
00035 return "null";
00036 }
00037 string data;
00038 char ch;
00039 while(fin.get(ch))
00040 data+=ch;
00041
00042 return data;
00043 }
00044
00045
00046
00047
00048
00049
00050 bool TCompute::InitCL()
00051 {
00052
00053 cl_platform_id platform = NULL;
00054 status = clGetPlatformIDs(1, &platform, NULL);
00055 if(status != CL_SUCCESS)
00056 return false;
00057
00058
00059 status = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 1, &device, NULL);
00060 assert(device);
00061
00062
00063 cl_char vendor_name[1024] = {0};
00064 cl_char device_name[1024] = {0};
00065 status = clGetDeviceInfo(device, CL_DEVICE_VENDOR, sizeof(vendor_name), vendor_name, NULL);
00066 status |= clGetDeviceInfo(device, CL_DEVICE_NAME, sizeof(device_name), device_name, NULL);
00067 assert(status == CL_SUCCESS);
00068 printf("Connecting to %s %s...\n", vendor_name, device_name);
00069
00070
00071 context = clCreateContext(0, 1, &device, NULL, NULL, &status);
00072 assert(status == CL_SUCCESS);
00073
00074
00075 commandQueue = clCreateCommandQueue(context, device, CL_QUEUE_PROFILING_ENABLE, &status);
00076
00077
00078 status = clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(size_t), (void*)&maxWorkGroupSize, NULL);
00079 status = clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, sizeof(cl_uint), (void*)&maxDimensions, NULL);
00080 maxWorkItemSizes = new size_t[maxDimensions];
00081 status = clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_ITEM_SIZES, sizeof(size_t) * maxDimensions, (void*)maxWorkItemSizes, NULL);
00082 status = clGetDeviceInfo(device, CL_DEVICE_LOCAL_MEM_SIZE, sizeof(cl_ulong), (void *)&totalLocalMemory, NULL);
00083 assert(status == CL_SUCCESS);
00084
00085 return true;
00086 }
00087
00088
00089
00090
00091
00092
00093
00094
00095 bool TCompute::SetupKernel(const char* source_file, const char* func_name)
00096 {
00097
00098 string str_source = LoadSource(source_file);
00099 const char* source = str_source.c_str();
00100 size_t sourceSize[] = { str_source.length() };
00101 program = clCreateProgramWithSource(context,1, &source, sourceSize, &status);
00102 assert(status == CL_SUCCESS);
00103
00104
00105 status = clBuildProgram(program, 1, &device, NULL, NULL, NULL);
00106 if(status != CL_SUCCESS)
00107 {
00108 if(status == CL_BUILD_PROGRAM_FAILURE)
00109 {
00110 ShowMessage("Build program failed!",false);
00111 cl_int logStatus;
00112 char * buildLog = NULL;
00113 size_t buildLogSize = 0;
00114 logStatus = clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, buildLogSize, buildLog, &buildLogSize);
00115 buildLog = new char[buildLogSize];
00116 assert(buildLog != NULL);
00117 memset(buildLog, 0, buildLogSize);
00118
00119 logStatus = clGetProgramBuildInfo (program, device, CL_PROGRAM_BUILD_LOG, buildLogSize, buildLog, NULL);
00120 assert(logStatus == CL_SUCCESS);
00121
00122 cout<<buildLog<<endl;
00123 delete [] buildLog;
00124 }
00125 return false;
00126 }
00127
00128
00129 kernel = clCreateKernel(program, func_name, &status);
00130 assert(status == CL_SUCCESS);
00131
00132
00133 status = clGetKernelWorkGroupInfo(kernel, device, CL_KERNEL_LOCAL_MEM_SIZE, sizeof(cl_ulong), &usedLocalMemory, NULL);
00134 assert(status == CL_SUCCESS);
00135 if(usedLocalMemory > totalLocalMemory)
00136 {
00137 ShowMessage("Unsupported: Insufficient local memory on device.",false);
00138 return false;
00139 }
00140
00141 groupSize = 256;
00142
00143 if(groupSize > maxWorkItemSizes[0] || groupSize > maxWorkGroupSize)
00144 {
00145
00146 status = clGetKernelWorkGroupInfo(kernel, device, CL_KERNEL_WORK_GROUP_SIZE, sizeof(size_t), &groupSize, 0);
00147 assert(status == CL_SUCCESS);
00148 }
00149 cout<<"Work group size: "<<groupSize<<endl;
00150
00151 return SetupKernelArgs();
00152 }
00153
00154
00155
00156
00157
00158 bool TCompute::Destroy()
00159 {
00160
00161 cl_int status;
00162
00163 status = clReleaseKernel(kernel);
00164 status |= clReleaseProgram(program);
00165 status |= clReleaseCommandQueue(commandQueue);
00166 status |= clReleaseContext(context);
00167
00168 if(maxWorkItemSizes)
00169 delete [] maxWorkItemSizes;
00170
00171 if(status == CL_SUCCESS)
00172 return true;
00173 else
00174 return false;
00175 }
00176
00177 #endif
00178