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 28using namespace clover; 29 30namespace { 31 std::string 32 supported_il_versions_as_string(const device &dev) { 33 std::string il_versions_string; 34 35 for (const auto &il_version : dev.supported_il_versions()) { 36 if (!il_versions_string.empty()) 37 il_versions_string += " "; 38 39 il_versions_string += std::string(il_version.name) + "_" + 40 std::to_string(CL_VERSION_MAJOR(il_version.version)) + "." + 41 std::to_string(CL_VERSION_MINOR(il_version.version)); 42 } 43 return il_versions_string; 44 } 45} 46 47CLOVER_API cl_int 48clGetDeviceIDs(cl_platform_id d_platform, cl_device_type device_type, 49 cl_uint num_entries, cl_device_id *rd_devices, 50 cl_uint *rnum_devices) try { 51 auto &platform = obj(d_platform); 52 std::vector<cl_device_id> d_devs; 53 54 if ((!num_entries && rd_devices) || 55 (!rnum_devices && !rd_devices)) 56 throw error(CL_INVALID_VALUE); 57 58 // Collect matching devices 59 for (device &dev : platform) { 60 if (((device_type & CL_DEVICE_TYPE_DEFAULT) && 61 dev == platform.front()) || 62 (device_type & dev.type())) 63 d_devs.push_back(desc(dev)); 64 } 65 66 if (d_devs.empty()) 67 throw error(CL_DEVICE_NOT_FOUND); 68 69 // ...and return the requested data. 70 if (rnum_devices) 71 *rnum_devices = d_devs.size(); 72 if (rd_devices) 73 copy(range(d_devs.begin(), 74 std::min((unsigned)d_devs.size(), num_entries)), 75 rd_devices); 76 77 return CL_SUCCESS; 78 79} catch (error &e) { 80 return e.get(); 81} 82 83CLOVER_API cl_int 84clCreateSubDevices(cl_device_id d_dev, 85 const cl_device_partition_property *props, 86 cl_uint num_devs, cl_device_id *rd_devs, 87 cl_uint *rnum_devs) { 88 // There are no currently supported partitioning schemes. 89 return CL_INVALID_VALUE; 90} 91 92CLOVER_API cl_int 93clRetainDevice(cl_device_id d_dev) try { 94 obj(d_dev); 95 96 // The reference count doesn't change for root devices. 97 return CL_SUCCESS; 98 99} catch (error &e) { 100 return e.get(); 101} 102 103CLOVER_API cl_int 104clReleaseDevice(cl_device_id d_dev) try { 105 obj(d_dev); 106 107 // The reference count doesn't change for root devices. 108 return CL_SUCCESS; 109 110} catch (error &e) { 111 return e.get(); 112} 113 114CLOVER_API cl_int 115clGetDeviceInfo(cl_device_id d_dev, cl_device_info param, 116 size_t size, void *r_buf, size_t *r_size) try { 117 property_buffer buf { r_buf, size, r_size }; 118 auto &dev = obj(d_dev); 119 120 switch (param) { 121 case CL_DEVICE_TYPE: 122 buf.as_scalar<cl_device_type>() = dev.type(); 123 break; 124 125 case CL_DEVICE_VENDOR_ID: 126 buf.as_scalar<cl_uint>() = dev.vendor_id(); 127 break; 128 129 case CL_DEVICE_MAX_COMPUTE_UNITS: 130 buf.as_scalar<cl_uint>() = dev.max_compute_units(); 131 break; 132 133 case CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS: 134 buf.as_scalar<cl_uint>() = dev.max_block_size().size(); 135 break; 136 137 case CL_DEVICE_MAX_WORK_ITEM_SIZES: 138 buf.as_vector<size_t>() = dev.max_block_size(); 139 break; 140 141 case CL_DEVICE_MAX_WORK_GROUP_SIZE: 142 buf.as_scalar<size_t>() = dev.max_threads_per_block(); 143 break; 144 145 case CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR: 146 buf.as_scalar<cl_uint>() = 16; 147 break; 148 149 case CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT: 150 buf.as_scalar<cl_uint>() = 8; 151 break; 152 153 case CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT: 154 buf.as_scalar<cl_uint>() = 4; 155 break; 156 157 case CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG: 158 buf.as_scalar<cl_uint>() = 2; 159 break; 160 161 case CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT: 162 buf.as_scalar<cl_uint>() = 4; 163 break; 164 165 case CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE: 166 buf.as_scalar<cl_uint>() = dev.has_doubles() ? 2 : 0; 167 break; 168 169 case CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF: 170 buf.as_scalar<cl_uint>() = dev.has_halves() ? 8 : 0; 171 break; 172 173 case CL_DEVICE_MAX_CLOCK_FREQUENCY: 174 buf.as_scalar<cl_uint>() = dev.max_clock_frequency(); 175 break; 176 177 case CL_DEVICE_ADDRESS_BITS: 178 buf.as_scalar<cl_uint>() = dev.address_bits(); 179 break; 180 181 case CL_DEVICE_MAX_READ_IMAGE_ARGS: 182 buf.as_scalar<cl_uint>() = dev.max_images_read(); 183 break; 184 185 case CL_DEVICE_MAX_WRITE_IMAGE_ARGS: 186 buf.as_scalar<cl_uint>() = dev.max_images_write(); 187 break; 188 189 case CL_DEVICE_MAX_MEM_ALLOC_SIZE: 190 buf.as_scalar<cl_ulong>() = dev.max_mem_alloc_size(); 191 break; 192 193 case CL_DEVICE_IMAGE2D_MAX_WIDTH: 194 case CL_DEVICE_IMAGE2D_MAX_HEIGHT: 195 buf.as_scalar<size_t>() = dev.max_image_size(); 196 break; 197 198 case CL_DEVICE_IMAGE3D_MAX_WIDTH: 199 case CL_DEVICE_IMAGE3D_MAX_HEIGHT: 200 case CL_DEVICE_IMAGE3D_MAX_DEPTH: 201 buf.as_scalar<size_t>() = dev.max_image_size_3d(); 202 break; 203 204 case CL_DEVICE_IMAGE_MAX_BUFFER_SIZE: 205 buf.as_scalar<size_t>() = dev.max_image_buffer_size(); 206 break; 207 208 case CL_DEVICE_IMAGE_MAX_ARRAY_SIZE: 209 buf.as_scalar<size_t>() = dev.max_image_array_number(); 210 break; 211 212 case CL_DEVICE_IMAGE_SUPPORT: 213 buf.as_scalar<cl_bool>() = dev.image_support(); 214 break; 215 216 case CL_DEVICE_MAX_PARAMETER_SIZE: 217 buf.as_scalar<size_t>() = dev.max_mem_input(); 218 break; 219 220 case CL_DEVICE_MAX_SAMPLERS: 221 buf.as_scalar<cl_uint>() = dev.max_samplers(); 222 break; 223 224 case CL_DEVICE_MEM_BASE_ADDR_ALIGN: 225 buf.as_scalar<cl_uint>() = 8 * dev.mem_base_addr_align(); 226 break; 227 228 case CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE: 229 buf.as_scalar<cl_uint>() = 128; 230 break; 231 232 case CL_DEVICE_HALF_FP_CONFIG: 233 // This is the "mandated minimum half precision floating-point 234 // capability" for OpenCL 1.x. 235 buf.as_scalar<cl_device_fp_config>() = 236 CL_FP_INF_NAN | CL_FP_ROUND_TO_NEAREST; 237 break; 238 239 case CL_DEVICE_SINGLE_FP_CONFIG: 240 // This is the "mandated minimum single precision floating-point 241 // capability" for OpenCL 1.1. In OpenCL 1.2, nothing is required for 242 // custom devices. 243 buf.as_scalar<cl_device_fp_config>() = 244 CL_FP_INF_NAN | CL_FP_ROUND_TO_NEAREST; 245 break; 246 247 case CL_DEVICE_DOUBLE_FP_CONFIG: 248 if (dev.has_doubles()) 249 // This is the "mandated minimum double precision floating-point 250 // capability" 251 buf.as_scalar<cl_device_fp_config>() = 252 CL_FP_FMA 253 | CL_FP_ROUND_TO_NEAREST 254 | CL_FP_ROUND_TO_ZERO 255 | CL_FP_ROUND_TO_INF 256 | CL_FP_INF_NAN 257 | CL_FP_DENORM; 258 else 259 buf.as_scalar<cl_device_fp_config>() = 0; 260 break; 261 262 case CL_DEVICE_GLOBAL_MEM_CACHE_TYPE: 263 buf.as_scalar<cl_device_mem_cache_type>() = CL_NONE; 264 break; 265 266 case CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE: 267 buf.as_scalar<cl_uint>() = 0; 268 break; 269 270 case CL_DEVICE_GLOBAL_MEM_CACHE_SIZE: 271 buf.as_scalar<cl_ulong>() = 0; 272 break; 273 274 case CL_DEVICE_GLOBAL_MEM_SIZE: 275 buf.as_scalar<cl_ulong>() = dev.max_mem_global(); 276 break; 277 278 case CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE: 279 buf.as_scalar<cl_ulong>() = dev.max_const_buffer_size(); 280 break; 281 282 case CL_DEVICE_MAX_CONSTANT_ARGS: 283 buf.as_scalar<cl_uint>() = dev.max_const_buffers(); 284 break; 285 286 case CL_DEVICE_LOCAL_MEM_TYPE: 287 buf.as_scalar<cl_device_local_mem_type>() = CL_LOCAL; 288 break; 289 290 case CL_DEVICE_LOCAL_MEM_SIZE: 291 buf.as_scalar<cl_ulong>() = dev.max_mem_local(); 292 break; 293 294 case CL_DEVICE_ERROR_CORRECTION_SUPPORT: 295 buf.as_scalar<cl_bool>() = CL_FALSE; 296 break; 297 298 case CL_DEVICE_PROFILING_TIMER_RESOLUTION: 299 buf.as_scalar<size_t>() = 0; 300 break; 301 302 case CL_DEVICE_ENDIAN_LITTLE: 303 buf.as_scalar<cl_bool>() = (dev.endianness() == PIPE_ENDIAN_LITTLE); 304 break; 305 306 case CL_DEVICE_AVAILABLE: 307 case CL_DEVICE_COMPILER_AVAILABLE: 308 case CL_DEVICE_LINKER_AVAILABLE: 309 buf.as_scalar<cl_bool>() = CL_TRUE; 310 break; 311 312 case CL_DEVICE_EXECUTION_CAPABILITIES: 313 buf.as_scalar<cl_device_exec_capabilities>() = CL_EXEC_KERNEL; 314 break; 315 316 case CL_DEVICE_QUEUE_PROPERTIES: 317 buf.as_scalar<cl_command_queue_properties>() = CL_QUEUE_PROFILING_ENABLE; 318 break; 319 320 case CL_DEVICE_BUILT_IN_KERNELS: 321 buf.as_string() = ""; 322 break; 323 324 case CL_DEVICE_NAME: 325 buf.as_string() = dev.device_name(); 326 break; 327 328 case CL_DEVICE_VENDOR: 329 buf.as_string() = dev.vendor_name(); 330 break; 331 332 case CL_DRIVER_VERSION: 333 buf.as_string() = PACKAGE_VERSION; 334 break; 335 336 case CL_DEVICE_PROFILE: 337 buf.as_string() = "FULL_PROFILE"; 338 break; 339 340 case CL_DEVICE_VERSION: 341 buf.as_string() = "OpenCL " + dev.device_version_as_string() + " Mesa " PACKAGE_VERSION MESA_GIT_SHA1; 342 break; 343 344 case CL_DEVICE_EXTENSIONS: 345 buf.as_string() = dev.supported_extensions_as_string(); 346 break; 347 348 case CL_DEVICE_PLATFORM: 349 buf.as_scalar<cl_platform_id>() = desc(dev.platform); 350 break; 351 352 case CL_DEVICE_HOST_UNIFIED_MEMORY: 353 buf.as_scalar<cl_bool>() = dev.has_unified_memory(); 354 break; 355 356 case CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR: 357 buf.as_scalar<cl_uint>() = 16; 358 break; 359 360 case CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT: 361 buf.as_scalar<cl_uint>() = 8; 362 break; 363 364 case CL_DEVICE_NATIVE_VECTOR_WIDTH_INT: 365 buf.as_scalar<cl_uint>() = 4; 366 break; 367 368 case CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG: 369 buf.as_scalar<cl_uint>() = 2; 370 break; 371 372 case CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT: 373 buf.as_scalar<cl_uint>() = 4; 374 break; 375 376 case CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE: 377 buf.as_scalar<cl_uint>() = dev.has_doubles() ? 2 : 0; 378 break; 379 380 case CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF: 381 buf.as_scalar<cl_uint>() = dev.has_halves() ? 8 : 0; 382 break; 383 384 case CL_DEVICE_OPENCL_C_VERSION: 385 buf.as_string() = "OpenCL C " + dev.device_clc_version_as_string() + " "; 386 break; 387 388 case CL_DEVICE_PRINTF_BUFFER_SIZE: 389 buf.as_scalar<size_t>() = dev.max_printf_buffer_size(); 390 break; 391 392 case CL_DEVICE_PREFERRED_INTEROP_USER_SYNC: 393 buf.as_scalar<cl_bool>() = CL_TRUE; 394 break; 395 396 case CL_DEVICE_PARENT_DEVICE: 397 buf.as_scalar<cl_device_id>() = NULL; 398 break; 399 400 case CL_DEVICE_PARTITION_MAX_SUB_DEVICES: 401 buf.as_scalar<cl_uint>() = 0; 402 break; 403 404 case CL_DEVICE_PARTITION_PROPERTIES: 405 buf.as_vector<cl_device_partition_property>() = 406 desc(property_list<cl_device_partition_property>()); 407 break; 408 409 case CL_DEVICE_PARTITION_AFFINITY_DOMAIN: 410 buf.as_scalar<cl_device_affinity_domain>() = 0; 411 break; 412 413 case CL_DEVICE_PARTITION_TYPE: 414 buf.as_vector<cl_device_partition_property>() = 415 desc(property_list<cl_device_partition_property>()); 416 break; 417 418 case CL_DEVICE_REFERENCE_COUNT: 419 buf.as_scalar<cl_uint>() = 1; 420 break; 421 422 case CL_DEVICE_SVM_CAPABILITIES: 423 case CL_DEVICE_SVM_CAPABILITIES_ARM: 424 buf.as_scalar<cl_device_svm_capabilities>() = dev.svm_support(); 425 break; 426 427 case CL_DEVICE_NUMERIC_VERSION: 428 buf.as_scalar<cl_version>() = dev.device_version(); 429 break; 430 431 case CL_DEVICE_OPENCL_C_NUMERIC_VERSION_KHR: 432 buf.as_scalar<cl_version>() = dev.device_clc_version(true); 433 break; 434 435 case CL_DEVICE_OPENCL_C_ALL_VERSIONS: 436 buf.as_vector<cl_name_version>() = dev.opencl_c_all_versions(); 437 break; 438 439 case CL_DEVICE_EXTENSIONS_WITH_VERSION: 440 buf.as_vector<cl_name_version>() = dev.supported_extensions(); 441 break; 442 443 case CL_DEVICE_OPENCL_C_FEATURES: 444 buf.as_vector<cl_name_version>() = dev.opencl_c_features(); 445 break; 446 447 case CL_DEVICE_IL_VERSION: 448 if (dev.supported_extensions_as_string().find("cl_khr_il_program") == std::string::npos) 449 throw error(CL_INVALID_VALUE); 450 buf.as_string() = supported_il_versions_as_string(dev); 451 break; 452 453 case CL_DEVICE_ILS_WITH_VERSION: 454 buf.as_vector<cl_name_version>() = dev.supported_il_versions(); 455 break; 456 457 case CL_DEVICE_BUILT_IN_KERNELS_WITH_VERSION: 458 buf.as_vector<cl_name_version>() = std::vector<cl_name_version>{}; 459 break; 460 461 case CL_DEVICE_MAX_READ_WRITE_IMAGE_ARGS: 462 case CL_DEVICE_IMAGE_PITCH_ALIGNMENT: 463 case CL_DEVICE_IMAGE_BASE_ADDRESS_ALIGNMENT: 464 case CL_DEVICE_PREFERRED_PLATFORM_ATOMIC_ALIGNMENT: 465 case CL_DEVICE_PREFERRED_GLOBAL_ATOMIC_ALIGNMENT: 466 case CL_DEVICE_PREFERRED_LOCAL_ATOMIC_ALIGNMENT: 467 case CL_DEVICE_MAX_NUM_SUB_GROUPS: 468 case CL_DEVICE_QUEUE_ON_DEVICE_PREFERRED_SIZE: 469 case CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE: 470 case CL_DEVICE_MAX_ON_DEVICE_QUEUES: 471 case CL_DEVICE_MAX_ON_DEVICE_EVENTS: 472 case CL_DEVICE_MAX_PIPE_ARGS: 473 case CL_DEVICE_PIPE_MAX_ACTIVE_RESERVATIONS: 474 case CL_DEVICE_PIPE_MAX_PACKET_SIZE: 475 buf.as_scalar<cl_uint>() = 0; 476 break; 477 478 case CL_DEVICE_MAX_GLOBAL_VARIABLE_SIZE: 479 case CL_DEVICE_GLOBAL_VARIABLE_PREFERRED_TOTAL_SIZE: 480 buf.as_scalar<size_t>() = 0; 481 break; 482 483 case CL_DEVICE_SUB_GROUP_INDEPENDENT_FORWARD_PROGRESS: 484 case CL_DEVICE_NON_UNIFORM_WORK_GROUP_SUPPORT: 485 case CL_DEVICE_WORK_GROUP_COLLECTIVE_FUNCTIONS_SUPPORT: 486 case CL_DEVICE_GENERIC_ADDRESS_SPACE_SUPPORT: 487 case CL_DEVICE_PIPE_SUPPORT: 488 buf.as_scalar<cl_bool>() = CL_FALSE; 489 break; 490 491 case CL_DEVICE_QUEUE_ON_DEVICE_PROPERTIES: 492 buf.as_scalar<cl_command_queue_properties>() = 0; 493 break; 494 495 case CL_DEVICE_ATOMIC_MEMORY_CAPABILITIES: 496 buf.as_scalar<cl_device_atomic_capabilities>() = (CL_DEVICE_ATOMIC_ORDER_RELAXED | 497 CL_DEVICE_ATOMIC_SCOPE_WORK_GROUP); 498 break; 499 case CL_DEVICE_ATOMIC_FENCE_CAPABILITIES: 500 buf.as_scalar<cl_device_atomic_capabilities>() = (CL_DEVICE_ATOMIC_ORDER_RELAXED | 501 CL_DEVICE_ATOMIC_ORDER_ACQ_REL | 502 CL_DEVICE_ATOMIC_SCOPE_WORK_GROUP); 503 break; 504 505 case CL_DEVICE_DEVICE_ENQUEUE_CAPABILITIES: 506 buf.as_scalar<cl_device_device_enqueue_capabilities>() = 0; 507 break; 508 509 case CL_DEVICE_PREFERRED_WORK_GROUP_SIZE_MULTIPLE: 510 buf.as_scalar<size_t>() = 1; 511 break; 512 513 case CL_DEVICE_LATEST_CONFORMANCE_VERSION_PASSED: 514 buf.as_string() = ""; 515 break; 516 517 default: 518 throw error(CL_INVALID_VALUE); 519 } 520 521 return CL_SUCCESS; 522 523} catch (error &e) { 524 return e.get(); 525} 526