1 // 2 // Copyright 2012 Francisco Jerez 3 // 4 // Permission is hereby granted, free of charge, to any person obtaining a 5 // copy of this software and associated documentation files (the "Software"), 6 // to deal in the Software without restriction, including without limitation 7 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 // and/or sell copies of the Software, and to permit persons to whom the 9 // Software is furnished to do so, subject to the following conditions: 10 // 11 // The above copyright notice and this permission notice shall be included in 12 // all copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 // OTHER DEALINGS IN THE SOFTWARE. 21 // 22 23 #include "api/util.hpp" 24 #include "core/platform.hpp" 25 #include "core/device.hpp" 26 #include "git_sha1.h" 27 28 using namespace clover; 29 30 CLOVER_API cl_int 31 clGetDeviceIDs(cl_platform_id d_platform, cl_device_type device_type, 32 cl_uint num_entries, cl_device_id *rd_devices, 33 cl_uint *rnum_devices) try { 34 auto &platform = obj(d_platform); 35 std::vector<cl_device_id> d_devs; 36 37 if ((!num_entries && rd_devices) || 38 (!rnum_devices && !rd_devices)) 39 throw error(CL_INVALID_VALUE); 40 41 // Collect matching devices 42 for (device &dev : platform) { 43 if (((device_type & CL_DEVICE_TYPE_DEFAULT) && 44 dev == platform.front()) || 45 (device_type & dev.type())) 46 d_devs.push_back(desc(dev)); 47 } 48 49 if (d_devs.empty()) 50 throw error(CL_DEVICE_NOT_FOUND); 51 52 // ...and return the requested data. 53 if (rnum_devices) 54 *rnum_devices = d_devs.size(); 55 if (rd_devices) 56 copy(range(d_devs.begin(), 57 std::min((unsigned)d_devs.size(), num_entries)), 58 rd_devices); 59 60 return CL_SUCCESS; 61 62 } catch (error &e) { 63 return e.get(); 64 } 65 66 CLOVER_API cl_int 67 clCreateSubDevices(cl_device_id d_dev, 68 const cl_device_partition_property *props, 69 cl_uint num_devs, cl_device_id *rd_devs, 70 cl_uint *rnum_devs) { 71 // There are no currently supported partitioning schemes. 72 return CL_INVALID_VALUE; 73 } 74 75 CLOVER_API cl_int 76 clRetainDevice(cl_device_id d_dev) try { 77 obj(d_dev); 78 79 // The reference count doesn't change for root devices. 80 return CL_SUCCESS; 81 82 } catch (error &e) { 83 return e.get(); 84 } 85 86 CLOVER_API cl_int 87 clReleaseDevice(cl_device_id d_dev) try { 88 obj(d_dev); 89 90 // The reference count doesn't change for root devices. 91 return CL_SUCCESS; 92 93 } catch (error &e) { 94 return e.get(); 95 } 96 97 CLOVER_API cl_int 98 clGetDeviceInfo(cl_device_id d_dev, cl_device_info param, 99 size_t size, void *r_buf, size_t *r_size) try { 100 property_buffer buf { r_buf, size, r_size }; 101 auto &dev = obj(d_dev); 102 103 switch (param) { 104 case CL_DEVICE_TYPE: 105 buf.as_scalar<cl_device_type>() = dev.type(); 106 break; 107 108 case CL_DEVICE_VENDOR_ID: 109 buf.as_scalar<cl_uint>() = dev.vendor_id(); 110 break; 111 112 case CL_DEVICE_MAX_COMPUTE_UNITS: 113 buf.as_scalar<cl_uint>() = dev.max_compute_units(); 114 break; 115 116 case CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS: 117 buf.as_scalar<cl_uint>() = dev.max_block_size().size(); 118 break; 119 120 case CL_DEVICE_MAX_WORK_ITEM_SIZES: 121 buf.as_vector<size_t>() = dev.max_block_size(); 122 break; 123 124 case CL_DEVICE_MAX_WORK_GROUP_SIZE: 125 buf.as_scalar<size_t>() = dev.max_threads_per_block(); 126 break; 127 128 case CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR: 129 buf.as_scalar<cl_uint>() = 16; 130 break; 131 132 case CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT: 133 buf.as_scalar<cl_uint>() = 8; 134 break; 135 136 case CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT: 137 buf.as_scalar<cl_uint>() = 4; 138 break; 139 140 case CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG: 141 buf.as_scalar<cl_uint>() = 2; 142 break; 143 144 case CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT: 145 buf.as_scalar<cl_uint>() = 4; 146 break; 147 148 case CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE: 149 buf.as_scalar<cl_uint>() = dev.has_doubles() ? 2 : 0; 150 break; 151 152 case CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF: 153 buf.as_scalar<cl_uint>() = 0; 154 break; 155 156 case CL_DEVICE_MAX_CLOCK_FREQUENCY: 157 buf.as_scalar<cl_uint>() = dev.max_clock_frequency(); 158 break; 159 160 case CL_DEVICE_ADDRESS_BITS: 161 buf.as_scalar<cl_uint>() = dev.address_bits(); 162 break; 163 164 case CL_DEVICE_MAX_READ_IMAGE_ARGS: 165 buf.as_scalar<cl_uint>() = dev.max_images_read(); 166 break; 167 168 case CL_DEVICE_MAX_WRITE_IMAGE_ARGS: 169 buf.as_scalar<cl_uint>() = dev.max_images_write(); 170 break; 171 172 case CL_DEVICE_MAX_MEM_ALLOC_SIZE: 173 buf.as_scalar<cl_ulong>() = dev.max_mem_alloc_size(); 174 break; 175 176 case CL_DEVICE_IMAGE2D_MAX_WIDTH: 177 case CL_DEVICE_IMAGE2D_MAX_HEIGHT: 178 buf.as_scalar<size_t>() = 1 << dev.max_image_levels_2d(); 179 break; 180 181 case CL_DEVICE_IMAGE3D_MAX_WIDTH: 182 case CL_DEVICE_IMAGE3D_MAX_HEIGHT: 183 case CL_DEVICE_IMAGE3D_MAX_DEPTH: 184 buf.as_scalar<size_t>() = 1 << dev.max_image_levels_3d(); 185 break; 186 187 case CL_DEVICE_IMAGE_MAX_BUFFER_SIZE: 188 buf.as_scalar<size_t>() = dev.max_image_buffer_size(); 189 break; 190 191 case CL_DEVICE_IMAGE_MAX_ARRAY_SIZE: 192 buf.as_scalar<size_t>() = dev.max_image_array_number(); 193 break; 194 195 case CL_DEVICE_IMAGE_SUPPORT: 196 buf.as_scalar<cl_bool>() = dev.image_support(); 197 break; 198 199 case CL_DEVICE_MAX_PARAMETER_SIZE: 200 buf.as_scalar<size_t>() = dev.max_mem_input(); 201 break; 202 203 case CL_DEVICE_MAX_SAMPLERS: 204 buf.as_scalar<cl_uint>() = dev.max_samplers(); 205 break; 206 207 case CL_DEVICE_MEM_BASE_ADDR_ALIGN: 208 buf.as_scalar<cl_uint>() = 128 * 8; 209 break; 210 211 case CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE: 212 buf.as_scalar<cl_uint>() = 128; 213 break; 214 215 case CL_DEVICE_SINGLE_FP_CONFIG: 216 // This is the "mandated minimum single precision floating-point 217 // capability" for OpenCL 1.1. In OpenCL 1.2, nothing is required for 218 // custom devices. 219 buf.as_scalar<cl_device_fp_config>() = 220 CL_FP_INF_NAN | CL_FP_ROUND_TO_NEAREST; 221 break; 222 223 case CL_DEVICE_DOUBLE_FP_CONFIG: 224 if (dev.has_doubles()) 225 // This is the "mandated minimum double precision floating-point 226 // capability" 227 buf.as_scalar<cl_device_fp_config>() = 228 CL_FP_FMA 229 | CL_FP_ROUND_TO_NEAREST 230 | CL_FP_ROUND_TO_ZERO 231 | CL_FP_ROUND_TO_INF 232 | CL_FP_INF_NAN 233 | CL_FP_DENORM; 234 else 235 buf.as_scalar<cl_device_fp_config>() = 0; 236 break; 237 238 case CL_DEVICE_GLOBAL_MEM_CACHE_TYPE: 239 buf.as_scalar<cl_device_mem_cache_type>() = CL_NONE; 240 break; 241 242 case CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE: 243 buf.as_scalar<cl_uint>() = 0; 244 break; 245 246 case CL_DEVICE_GLOBAL_MEM_CACHE_SIZE: 247 buf.as_scalar<cl_ulong>() = 0; 248 break; 249 250 case CL_DEVICE_GLOBAL_MEM_SIZE: 251 buf.as_scalar<cl_ulong>() = dev.max_mem_global(); 252 break; 253 254 case CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE: 255 buf.as_scalar<cl_ulong>() = dev.max_const_buffer_size(); 256 break; 257 258 case CL_DEVICE_MAX_CONSTANT_ARGS: 259 buf.as_scalar<cl_uint>() = dev.max_const_buffers(); 260 break; 261 262 case CL_DEVICE_LOCAL_MEM_TYPE: 263 buf.as_scalar<cl_device_local_mem_type>() = CL_LOCAL; 264 break; 265 266 case CL_DEVICE_LOCAL_MEM_SIZE: 267 buf.as_scalar<cl_ulong>() = dev.max_mem_local(); 268 break; 269 270 case CL_DEVICE_ERROR_CORRECTION_SUPPORT: 271 buf.as_scalar<cl_bool>() = CL_FALSE; 272 break; 273 274 case CL_DEVICE_PROFILING_TIMER_RESOLUTION: 275 buf.as_scalar<size_t>() = 0; 276 break; 277 278 case CL_DEVICE_ENDIAN_LITTLE: 279 buf.as_scalar<cl_bool>() = (dev.endianness() == PIPE_ENDIAN_LITTLE); 280 break; 281 282 case CL_DEVICE_AVAILABLE: 283 case CL_DEVICE_COMPILER_AVAILABLE: 284 case CL_DEVICE_LINKER_AVAILABLE: 285 buf.as_scalar<cl_bool>() = CL_TRUE; 286 break; 287 288 case CL_DEVICE_EXECUTION_CAPABILITIES: 289 buf.as_scalar<cl_device_exec_capabilities>() = CL_EXEC_KERNEL; 290 break; 291 292 case CL_DEVICE_QUEUE_PROPERTIES: 293 buf.as_scalar<cl_command_queue_properties>() = CL_QUEUE_PROFILING_ENABLE; 294 break; 295 296 case CL_DEVICE_BUILT_IN_KERNELS: 297 buf.as_string() = ""; 298 break; 299 300 case CL_DEVICE_NAME: 301 buf.as_string() = dev.device_name(); 302 break; 303 304 case CL_DEVICE_VENDOR: 305 buf.as_string() = dev.vendor_name(); 306 break; 307 308 case CL_DRIVER_VERSION: 309 buf.as_string() = PACKAGE_VERSION; 310 break; 311 312 case CL_DEVICE_PROFILE: 313 buf.as_string() = "FULL_PROFILE"; 314 break; 315 316 case CL_DEVICE_VERSION: 317 buf.as_string() = "OpenCL 1.1 Mesa " PACKAGE_VERSION 318 #ifdef MESA_GIT_SHA1 319 " (" MESA_GIT_SHA1 ")" 320 #endif 321 ; 322 break; 323 324 case CL_DEVICE_EXTENSIONS: 325 buf.as_string() = 326 "cl_khr_global_int32_base_atomics" 327 " cl_khr_global_int32_extended_atomics" 328 " cl_khr_local_int32_base_atomics" 329 " cl_khr_local_int32_extended_atomics" 330 " cl_khr_byte_addressable_store" 331 + std::string(dev.has_doubles() ? " cl_khr_fp64" : ""); 332 break; 333 334 case CL_DEVICE_PLATFORM: 335 buf.as_scalar<cl_platform_id>() = desc(dev.platform); 336 break; 337 338 case CL_DEVICE_HOST_UNIFIED_MEMORY: 339 buf.as_scalar<cl_bool>() = CL_TRUE; 340 break; 341 342 case CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR: 343 buf.as_scalar<cl_uint>() = 16; 344 break; 345 346 case CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT: 347 buf.as_scalar<cl_uint>() = 8; 348 break; 349 350 case CL_DEVICE_NATIVE_VECTOR_WIDTH_INT: 351 buf.as_scalar<cl_uint>() = 4; 352 break; 353 354 case CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG: 355 buf.as_scalar<cl_uint>() = 2; 356 break; 357 358 case CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT: 359 buf.as_scalar<cl_uint>() = 4; 360 break; 361 362 case CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE: 363 buf.as_scalar<cl_uint>() = dev.has_doubles() ? 2 : 0; 364 break; 365 366 case CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF: 367 buf.as_scalar<cl_uint>() = 0; 368 break; 369 370 case CL_DEVICE_OPENCL_C_VERSION: 371 buf.as_string() = "OpenCL C 1.1 "; 372 break; 373 374 case CL_DEVICE_PRINTF_BUFFER_SIZE: 375 // Per the spec, the minimum value for the FULL profile is 1 MB. 376 // However, clover is not ready yet to support it 377 buf.as_scalar<size_t>() = 0 /* 1024 */; 378 break; 379 380 case CL_DEVICE_PREFERRED_INTEROP_USER_SYNC: 381 buf.as_scalar<cl_bool>() = CL_TRUE; 382 break; 383 384 case CL_DEVICE_PARENT_DEVICE: 385 buf.as_scalar<cl_device_id>() = NULL; 386 break; 387 388 case CL_DEVICE_PARTITION_MAX_SUB_DEVICES: 389 buf.as_scalar<cl_uint>() = 0; 390 break; 391 392 case CL_DEVICE_PARTITION_PROPERTIES: 393 buf.as_vector<cl_device_partition_property>() = 394 desc(property_list<cl_device_partition_property>()); 395 break; 396 397 case CL_DEVICE_PARTITION_AFFINITY_DOMAIN: 398 buf.as_scalar<cl_device_affinity_domain>() = 0; 399 break; 400 401 case CL_DEVICE_PARTITION_TYPE: 402 buf.as_vector<cl_device_partition_property>() = 403 desc(property_list<cl_device_partition_property>()); 404 break; 405 406 case CL_DEVICE_REFERENCE_COUNT: 407 buf.as_scalar<cl_uint>() = 1; 408 break; 409 410 default: 411 throw error(CL_INVALID_VALUE); 412 } 413 414 return CL_SUCCESS; 415 416 } catch (error &e) { 417 return e.get(); 418 } 419