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 30CLOVER_API cl_int 31clGetDeviceIDs(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 66CLOVER_API cl_int 67clCreateSubDevices(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 75CLOVER_API cl_int 76clRetainDevice(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 86CLOVER_API cl_int 87clReleaseDevice(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 97CLOVER_API cl_int 98clGetDeviceInfo(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>() = dev.has_halves() ? 8 : 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>() = 8 * 209 std::max(dev.mem_base_addr_align(), (cl_uint) sizeof(cl_long) * 16); 210 break; 211 212 case CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE: 213 buf.as_scalar<cl_uint>() = 128; 214 break; 215 216 case CL_DEVICE_HALF_FP_CONFIG: 217 // This is the "mandated minimum half precision floating-point 218 // capability" for OpenCL 1.x. 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_SINGLE_FP_CONFIG: 224 // This is the "mandated minimum single precision floating-point 225 // capability" for OpenCL 1.1. In OpenCL 1.2, nothing is required for 226 // custom devices. 227 buf.as_scalar<cl_device_fp_config>() = 228 CL_FP_INF_NAN | CL_FP_ROUND_TO_NEAREST; 229 break; 230 231 case CL_DEVICE_DOUBLE_FP_CONFIG: 232 if (dev.has_doubles()) 233 // This is the "mandated minimum double precision floating-point 234 // capability" 235 buf.as_scalar<cl_device_fp_config>() = 236 CL_FP_FMA 237 | CL_FP_ROUND_TO_NEAREST 238 | CL_FP_ROUND_TO_ZERO 239 | CL_FP_ROUND_TO_INF 240 | CL_FP_INF_NAN 241 | CL_FP_DENORM; 242 else 243 buf.as_scalar<cl_device_fp_config>() = 0; 244 break; 245 246 case CL_DEVICE_GLOBAL_MEM_CACHE_TYPE: 247 buf.as_scalar<cl_device_mem_cache_type>() = CL_NONE; 248 break; 249 250 case CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE: 251 buf.as_scalar<cl_uint>() = 0; 252 break; 253 254 case CL_DEVICE_GLOBAL_MEM_CACHE_SIZE: 255 buf.as_scalar<cl_ulong>() = 0; 256 break; 257 258 case CL_DEVICE_GLOBAL_MEM_SIZE: 259 buf.as_scalar<cl_ulong>() = dev.max_mem_global(); 260 break; 261 262 case CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE: 263 buf.as_scalar<cl_ulong>() = dev.max_const_buffer_size(); 264 break; 265 266 case CL_DEVICE_MAX_CONSTANT_ARGS: 267 buf.as_scalar<cl_uint>() = dev.max_const_buffers(); 268 break; 269 270 case CL_DEVICE_LOCAL_MEM_TYPE: 271 buf.as_scalar<cl_device_local_mem_type>() = CL_LOCAL; 272 break; 273 274 case CL_DEVICE_LOCAL_MEM_SIZE: 275 buf.as_scalar<cl_ulong>() = dev.max_mem_local(); 276 break; 277 278 case CL_DEVICE_ERROR_CORRECTION_SUPPORT: 279 buf.as_scalar<cl_bool>() = CL_FALSE; 280 break; 281 282 case CL_DEVICE_PROFILING_TIMER_RESOLUTION: 283 buf.as_scalar<size_t>() = 0; 284 break; 285 286 case CL_DEVICE_ENDIAN_LITTLE: 287 buf.as_scalar<cl_bool>() = (dev.endianness() == PIPE_ENDIAN_LITTLE); 288 break; 289 290 case CL_DEVICE_AVAILABLE: 291 case CL_DEVICE_COMPILER_AVAILABLE: 292 case CL_DEVICE_LINKER_AVAILABLE: 293 buf.as_scalar<cl_bool>() = CL_TRUE; 294 break; 295 296 case CL_DEVICE_EXECUTION_CAPABILITIES: 297 buf.as_scalar<cl_device_exec_capabilities>() = CL_EXEC_KERNEL; 298 break; 299 300 case CL_DEVICE_QUEUE_PROPERTIES: 301 buf.as_scalar<cl_command_queue_properties>() = CL_QUEUE_PROFILING_ENABLE; 302 break; 303 304 case CL_DEVICE_BUILT_IN_KERNELS: 305 buf.as_string() = ""; 306 break; 307 308 case CL_DEVICE_NAME: 309 buf.as_string() = dev.device_name(); 310 break; 311 312 case CL_DEVICE_VENDOR: 313 buf.as_string() = dev.vendor_name(); 314 break; 315 316 case CL_DRIVER_VERSION: 317 buf.as_string() = PACKAGE_VERSION; 318 break; 319 320 case CL_DEVICE_PROFILE: 321 buf.as_string() = "FULL_PROFILE"; 322 break; 323 324 case CL_DEVICE_VERSION: 325 buf.as_string() = "OpenCL " + dev.device_version() + " Mesa " PACKAGE_VERSION MESA_GIT_SHA1; 326 break; 327 328 case CL_DEVICE_EXTENSIONS: 329 buf.as_string() = dev.supported_extensions(); 330 break; 331 332 case CL_DEVICE_PLATFORM: 333 buf.as_scalar<cl_platform_id>() = desc(dev.platform); 334 break; 335 336 case CL_DEVICE_HOST_UNIFIED_MEMORY: 337 buf.as_scalar<cl_bool>() = dev.has_unified_memory(); 338 break; 339 340 case CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR: 341 buf.as_scalar<cl_uint>() = 16; 342 break; 343 344 case CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT: 345 buf.as_scalar<cl_uint>() = 8; 346 break; 347 348 case CL_DEVICE_NATIVE_VECTOR_WIDTH_INT: 349 buf.as_scalar<cl_uint>() = 4; 350 break; 351 352 case CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG: 353 buf.as_scalar<cl_uint>() = 2; 354 break; 355 356 case CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT: 357 buf.as_scalar<cl_uint>() = 4; 358 break; 359 360 case CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE: 361 buf.as_scalar<cl_uint>() = dev.has_doubles() ? 2 : 0; 362 break; 363 364 case CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF: 365 buf.as_scalar<cl_uint>() = dev.has_halves() ? 8 : 0; 366 break; 367 368 case CL_DEVICE_OPENCL_C_VERSION: 369 buf.as_string() = "OpenCL C " + dev.device_clc_version() + " "; 370 break; 371 372 case CL_DEVICE_PRINTF_BUFFER_SIZE: 373 // Per the spec, the minimum value for the FULL profile is 1 MB. 374 // However, clover is not ready yet to support it 375 buf.as_scalar<size_t>() = 0 /* 1024 */; 376 break; 377 378 case CL_DEVICE_PREFERRED_INTEROP_USER_SYNC: 379 buf.as_scalar<cl_bool>() = CL_TRUE; 380 break; 381 382 case CL_DEVICE_PARENT_DEVICE: 383 buf.as_scalar<cl_device_id>() = NULL; 384 break; 385 386 case CL_DEVICE_PARTITION_MAX_SUB_DEVICES: 387 buf.as_scalar<cl_uint>() = 0; 388 break; 389 390 case CL_DEVICE_PARTITION_PROPERTIES: 391 buf.as_vector<cl_device_partition_property>() = 392 desc(property_list<cl_device_partition_property>()); 393 break; 394 395 case CL_DEVICE_PARTITION_AFFINITY_DOMAIN: 396 buf.as_scalar<cl_device_affinity_domain>() = 0; 397 break; 398 399 case CL_DEVICE_PARTITION_TYPE: 400 buf.as_vector<cl_device_partition_property>() = 401 desc(property_list<cl_device_partition_property>()); 402 break; 403 404 case CL_DEVICE_REFERENCE_COUNT: 405 buf.as_scalar<cl_uint>() = 1; 406 break; 407 408 default: 409 throw error(CL_INVALID_VALUE); 410 } 411 412 return CL_SUCCESS; 413 414} catch (error &e) { 415 return e.get(); 416} 417