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 "context.h" 00034 #include "deviceinterface.h" 00035 #include "propertylist.h" 00036 00037 #include <cstring> 00038 #include <cstdlib> 00039 00040 #include <llvm/Target/TargetSelect.h> 00041 00042 using namespace Coal; 00043 00044 static void default_pfn_notify(const char *, const void *, size_t, void *) 00045 { 00046 return; 00047 } 00048 00049 Context::Context(const cl_context_properties *properties, 00050 cl_uint num_devices, 00051 const cl_device_id *devices, 00052 void (CL_CALLBACK *pfn_notify)(const char *, const void *, 00053 size_t, void *), 00054 void *user_data, 00055 cl_int *errcode_ret) 00056 : Object(Object::T_Context, 0), p_properties(0), p_pfn_notify(pfn_notify), 00057 p_user_data(user_data), p_devices(0), p_num_devices(0), p_props_len(0), 00058 p_platform(0) 00059 { 00060 if (!p_pfn_notify) 00061 p_pfn_notify = &default_pfn_notify; 00062 00063 // Intialize LLVM, this can be done more than one time per program 00064 llvm::InitializeNativeTarget(); 00065 llvm::InitializeNativeTargetAsmPrinter(); 00066 00067 // Explore the properties 00068 if (properties) 00069 { 00070 const unsigned char *props = (const unsigned char *)properties; 00071 cl_context_properties prop; 00072 size_t props_len = 0; 00073 00074 #define GET_PROP(type, var) \ 00075 var = *(const type *)props; \ 00076 props += sizeof(type); \ 00077 props_len += sizeof(type); 00078 00079 while (true) 00080 { 00081 GET_PROP(cl_context_properties, prop) 00082 00083 if (!prop) 00084 break; 00085 00086 switch (prop) 00087 { 00088 case CL_CONTEXT_PLATFORM: 00089 GET_PROP(cl_platform_id, p_platform); 00090 break; 00091 00092 default: 00093 *errcode_ret = CL_INVALID_PROPERTY; 00094 return; 00095 } 00096 } 00097 00098 // properties may be allocated on the stack of the client application 00099 // copy it into a real buffer 00100 p_properties = (cl_context_properties *)std::malloc(props_len); 00101 p_props_len = props_len; 00102 00103 if (!p_properties) 00104 { 00105 *errcode_ret = CL_OUT_OF_HOST_MEMORY; 00106 return; 00107 } 00108 00109 std::memcpy((void *)p_properties, (const void *)properties, props_len); 00110 } 00111 00112 // Verify that the platform is good 00113 if (p_platform != 0) 00114 { 00115 *errcode_ret = CL_INVALID_PLATFORM; 00116 return; 00117 } 00118 00119 // Explore the devices 00120 p_devices = (DeviceInterface **)std::malloc(num_devices * sizeof(DeviceInterface *)); 00121 p_num_devices = num_devices; 00122 00123 if (!p_devices) 00124 { 00125 *errcode_ret = CL_OUT_OF_HOST_MEMORY; 00126 return; 00127 } 00128 00129 for (cl_uint i=0; i<num_devices; ++i) 00130 { 00131 cl_device_id device = devices[i]; 00132 00133 if (device == 0) 00134 { 00135 *errcode_ret = CL_INVALID_DEVICE; 00136 return; 00137 } 00138 00139 // Verify that the device is available 00140 cl_bool device_available; 00141 00142 *errcode_ret = device->info(CL_DEVICE_AVAILABLE, 00143 sizeof(device_available), 00144 &device_available, 00145 0); 00146 00147 if (*errcode_ret != CL_SUCCESS) 00148 return; 00149 00150 if (!device_available) 00151 { 00152 *errcode_ret = CL_DEVICE_NOT_AVAILABLE; 00153 return; 00154 } 00155 00156 // Add the device to the list 00157 p_devices[i] = (DeviceInterface *)device; 00158 } 00159 } 00160 00161 Context::~Context() 00162 { 00163 if (p_properties) 00164 std::free((void *)p_properties); 00165 00166 if (p_devices) 00167 std::free((void *)p_devices); 00168 } 00169 00170 cl_int Context::info(cl_context_info param_name, 00171 size_t param_value_size, 00172 void *param_value, 00173 size_t *param_value_size_ret) const 00174 { 00175 void *value = 0; 00176 size_t value_length = 0; 00177 00178 union { 00179 cl_uint cl_uint_var; 00180 }; 00181 00182 switch (param_name) 00183 { 00184 case CL_CONTEXT_REFERENCE_COUNT: 00185 SIMPLE_ASSIGN(cl_uint, references()); 00186 break; 00187 00188 case CL_CONTEXT_NUM_DEVICES: 00189 SIMPLE_ASSIGN(cl_uint, p_num_devices); 00190 break; 00191 00192 case CL_CONTEXT_DEVICES: 00193 MEM_ASSIGN(p_num_devices * sizeof(DeviceInterface *), p_devices); 00194 break; 00195 00196 case CL_CONTEXT_PROPERTIES: 00197 MEM_ASSIGN(p_props_len, p_properties); 00198 break; 00199 00200 default: 00201 return CL_INVALID_VALUE; 00202 } 00203 00204 if (param_value && param_value_size < value_length) 00205 return CL_INVALID_VALUE; 00206 00207 if (param_value_size_ret) 00208 *param_value_size_ret = value_length; 00209 00210 if (param_value && value_length /* CONTEXT_PROPERTIES can be of length 0 */) 00211 std::memcpy(param_value, value, value_length); 00212 00213 return CL_SUCCESS; 00214 } 00215 00216 bool Context::hasDevice(DeviceInterface *device) const 00217 { 00218 for (unsigned int i=0; i<p_num_devices; ++i) 00219 if (p_devices[i] == device) 00220 return true; 00221 00222 return false; 00223 }