Home | History | Annotate | Download | only in api
      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