Clover Git
OpenCL 1.1 software implementation
|
00001 /* 00002 * Copyright (c) 2011, Denis Steckelmacher <steckdenis@yahoo.fr> 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions are met: 00007 * * Redistributions of source code must retain the above copyright 00008 * notice, this list of conditions and the following disclaimer. 00009 * * Redistributions in binary form must reproduce the above copyright 00010 * notice, this list of conditions and the following disclaimer in the 00011 * documentation and/or other materials provided with the distribution. 00012 * * Neither the name of the copyright holder nor the 00013 * names of its contributors may be used to endorse or promote products 00014 * derived from this software without specific prior written permission. 00015 * 00016 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 00017 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00018 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00019 * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY 00020 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00021 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00022 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 00023 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00024 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00025 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00026 */ 00027 00033 #include "CL/cl.h" 00034 #include <core/program.h> 00035 #include <core/context.h> 00036 00037 #include <cstdlib> 00038 00039 // Program Object APIs 00040 cl_program 00041 clCreateProgramWithSource(cl_context context, 00042 cl_uint count, 00043 const char ** strings, 00044 const size_t * lengths, 00045 cl_int * errcode_ret) 00046 { 00047 cl_int dummy_errcode; 00048 00049 if (!errcode_ret) 00050 errcode_ret = &dummy_errcode; 00051 00052 if (!context->isA(Coal::Object::T_Context)) 00053 { 00054 *errcode_ret = CL_INVALID_CONTEXT; 00055 return 0; 00056 } 00057 00058 if (!count || !strings) 00059 { 00060 *errcode_ret = CL_INVALID_VALUE; 00061 return 0; 00062 } 00063 00064 Coal::Program *program = new Coal::Program(context); 00065 00066 *errcode_ret = CL_SUCCESS; 00067 *errcode_ret = program->loadSources(count, strings, lengths); 00068 00069 if (*errcode_ret != CL_SUCCESS) 00070 { 00071 delete program; 00072 return 0; 00073 } 00074 00075 return (cl_program)program; 00076 } 00077 00078 cl_program 00079 clCreateProgramWithBinary(cl_context context, 00080 cl_uint num_devices, 00081 const cl_device_id * device_list, 00082 const size_t * lengths, 00083 const unsigned char **binaries, 00084 cl_int * binary_status, 00085 cl_int * errcode_ret) 00086 { 00087 cl_int dummy_errcode; 00088 00089 if (!errcode_ret) 00090 errcode_ret = &dummy_errcode; 00091 00092 if (!context->isA(Coal::Object::T_Context)) 00093 { 00094 *errcode_ret = CL_INVALID_CONTEXT; 00095 return 0; 00096 } 00097 00098 if (!num_devices || !device_list || !lengths || !binaries) 00099 { 00100 *errcode_ret = CL_INVALID_VALUE; 00101 return 0; 00102 } 00103 00104 // Check the devices for compliance 00105 cl_uint context_num_devices = 0; 00106 cl_device_id *context_devices; 00107 00108 *errcode_ret = context->info(CL_CONTEXT_NUM_DEVICES, sizeof(cl_uint), 00109 &context_num_devices, 0); 00110 00111 if (*errcode_ret != CL_SUCCESS) 00112 return 0; 00113 00114 context_devices = 00115 (cl_device_id *)std::malloc(context_num_devices * sizeof(cl_device_id)); 00116 00117 *errcode_ret = context->info(CL_CONTEXT_DEVICES, 00118 context_num_devices * sizeof(cl_device_id), 00119 context_devices, 0); 00120 00121 if (*errcode_ret != CL_SUCCESS) 00122 return 0; 00123 00124 for (cl_uint i=0; i<num_devices; ++i) 00125 { 00126 bool found = false; 00127 00128 if (!lengths[i] || !binaries[i]) 00129 { 00130 if (binary_status) 00131 binary_status[i] = CL_INVALID_VALUE; 00132 00133 *errcode_ret = CL_INVALID_VALUE; 00134 return 0; 00135 } 00136 00137 for (cl_uint j=0; j<context_num_devices; ++j) 00138 { 00139 if (device_list[i] == context_devices[j]) 00140 { 00141 found = true; 00142 break; 00143 } 00144 } 00145 00146 if (!found) 00147 { 00148 *errcode_ret = CL_INVALID_DEVICE; 00149 return 0; 00150 } 00151 } 00152 00153 // Create a program 00154 Coal::Program *program = new Coal::Program(context); 00155 *errcode_ret = CL_SUCCESS; 00156 00157 // Init program 00158 *errcode_ret = program->loadBinaries(binaries, 00159 lengths, binary_status, num_devices, 00160 (Coal::DeviceInterface * const*)device_list); 00161 00162 if (*errcode_ret != CL_SUCCESS) 00163 { 00164 delete program; 00165 return 0; 00166 } 00167 00168 return (cl_program)program; 00169 } 00170 00171 cl_int 00172 clRetainProgram(cl_program program) 00173 { 00174 if (!program->isA(Coal::Object::T_Program)) 00175 return CL_INVALID_PROGRAM; 00176 00177 program->reference(); 00178 00179 return CL_SUCCESS; 00180 } 00181 00182 cl_int 00183 clReleaseProgram(cl_program program) 00184 { 00185 if (!program->isA(Coal::Object::T_Program)) 00186 return CL_INVALID_PROGRAM; 00187 00188 if (program->dereference()) 00189 delete program; 00190 00191 return CL_SUCCESS; 00192 } 00193 00194 cl_int 00195 clBuildProgram(cl_program program, 00196 cl_uint num_devices, 00197 const cl_device_id * device_list, 00198 const char * options, 00199 void (*pfn_notify)(cl_program program, void * user_data), 00200 void * user_data) 00201 { 00202 if (!program->isA(Coal::Object::T_Program)) 00203 return CL_INVALID_PROGRAM; 00204 00205 if (!device_list && num_devices > 0) 00206 return CL_INVALID_VALUE; 00207 00208 if (!num_devices && device_list) 00209 return CL_INVALID_VALUE; 00210 00211 if (!pfn_notify && user_data) 00212 return CL_INVALID_VALUE; 00213 00214 // Check the devices for compliance 00215 if (num_devices) 00216 { 00217 cl_uint context_num_devices = 0; 00218 cl_device_id *context_devices; 00219 Coal::Context *context = (Coal::Context *)program->parent(); 00220 cl_int result; 00221 00222 result = context->info(CL_CONTEXT_NUM_DEVICES, sizeof(cl_uint), 00223 &context_num_devices, 0); 00224 00225 if (result != CL_SUCCESS) 00226 return result; 00227 00228 context_devices = 00229 (cl_device_id *)std::malloc(context_num_devices * sizeof(cl_device_id)); 00230 00231 result = context->info(CL_CONTEXT_DEVICES, 00232 context_num_devices * sizeof(cl_device_id), 00233 context_devices, 0); 00234 00235 if (result != CL_SUCCESS) 00236 return result; 00237 00238 for (cl_uint i=0; i<num_devices; ++i) 00239 { 00240 bool found = false; 00241 00242 for (cl_uint j=0; j<context_num_devices; ++j) 00243 { 00244 if (device_list[i] == context_devices[j]) 00245 { 00246 found = true; 00247 break; 00248 } 00249 } 00250 00251 if (!found) 00252 return CL_INVALID_DEVICE; 00253 } 00254 } 00255 00256 // We cannot try to build a previously-failed program 00257 if (program->state() != Coal::Program::Loaded) 00258 return CL_INVALID_OPERATION; 00259 00260 // Build program 00261 return program->build(options, pfn_notify, user_data, num_devices, 00262 (Coal::DeviceInterface * const*)device_list); 00263 } 00264 00265 cl_int 00266 clUnloadCompiler(void) 00267 { 00268 return CL_SUCCESS; 00269 } 00270 00271 cl_int 00272 clGetProgramInfo(cl_program program, 00273 cl_program_info param_name, 00274 size_t param_value_size, 00275 void * param_value, 00276 size_t * param_value_size_ret) 00277 { 00278 if (!program->isA(Coal::Object::T_Program)) 00279 return CL_INVALID_PROGRAM; 00280 00281 return program->info(param_name, param_value_size, param_value, 00282 param_value_size_ret); 00283 } 00284 00285 cl_int 00286 clGetProgramBuildInfo(cl_program program, 00287 cl_device_id device, 00288 cl_program_build_info param_name, 00289 size_t param_value_size, 00290 void * param_value, 00291 size_t * param_value_size_ret) 00292 { 00293 if (!program->isA(Coal::Object::T_Program)) 00294 return CL_INVALID_PROGRAM; 00295 00296 return program->buildInfo((Coal::DeviceInterface *)device, param_name, 00297 param_value_size, param_value, 00298 param_value_size_ret); 00299 }