Home | History | Annotate | Download | only in core
      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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
     18 // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
     19 // OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     20 // SOFTWARE.
     21 //
     22 
     23 #include "core/device.hpp"
     24 #include "pipe/p_screen.h"
     25 #include "pipe/p_state.h"
     26 
     27 using namespace clover;
     28 
     29 namespace {
     30    template<typename T>
     31    std::vector<T>
     32    get_compute_param(pipe_screen *pipe, pipe_compute_cap cap) {
     33       int sz = pipe->get_compute_param(pipe, cap, NULL);
     34       std::vector<T> v(sz / sizeof(T));
     35 
     36       pipe->get_compute_param(pipe, cap, &v.front());
     37       return v;
     38    }
     39 }
     40 
     41 _cl_device_id::_cl_device_id(pipe_loader_device *ldev) : ldev(ldev) {
     42    pipe = pipe_loader_create_screen(ldev, PIPE_SEARCH_DIR);
     43    if (!pipe || !pipe->get_param(pipe, PIPE_CAP_COMPUTE))
     44       throw error(CL_INVALID_DEVICE);
     45 }
     46 
     47 _cl_device_id::_cl_device_id(_cl_device_id &&dev) : pipe(dev.pipe), ldev(dev.ldev) {
     48    dev.ldev = NULL;
     49    dev.pipe = NULL;
     50 }
     51 
     52 _cl_device_id::~_cl_device_id() {
     53    if (pipe)
     54       pipe->destroy(pipe);
     55    if (ldev)
     56       pipe_loader_release(&ldev, 1);
     57 }
     58 
     59 cl_device_type
     60 _cl_device_id::type() const {
     61    switch (ldev->type) {
     62    case PIPE_LOADER_DEVICE_SOFTWARE:
     63       return CL_DEVICE_TYPE_CPU;
     64    case PIPE_LOADER_DEVICE_PCI:
     65       return CL_DEVICE_TYPE_GPU;
     66    default:
     67       assert(0);
     68       return 0;
     69    }
     70 }
     71 
     72 cl_uint
     73 _cl_device_id::vendor_id() const {
     74    switch (ldev->type) {
     75    case PIPE_LOADER_DEVICE_SOFTWARE:
     76       return 0;
     77    case PIPE_LOADER_DEVICE_PCI:
     78       return ldev->u.pci.vendor_id;
     79    default:
     80       assert(0);
     81       return 0;
     82    }
     83 }
     84 
     85 size_t
     86 _cl_device_id::max_images_read() const {
     87    return PIPE_MAX_SHADER_RESOURCES;
     88 }
     89 
     90 size_t
     91 _cl_device_id::max_images_write() const {
     92    return PIPE_MAX_SHADER_RESOURCES;
     93 }
     94 
     95 cl_uint
     96 _cl_device_id::max_image_levels_2d() const {
     97    return pipe->get_param(pipe, PIPE_CAP_MAX_TEXTURE_2D_LEVELS);
     98 }
     99 
    100 cl_uint
    101 _cl_device_id::max_image_levels_3d() const {
    102    return pipe->get_param(pipe, PIPE_CAP_MAX_TEXTURE_3D_LEVELS);
    103 }
    104 
    105 cl_uint
    106 _cl_device_id::max_samplers() const {
    107    return pipe->get_shader_param(pipe, PIPE_SHADER_COMPUTE,
    108                                  PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS);
    109 }
    110 
    111 cl_ulong
    112 _cl_device_id::max_mem_global() const {
    113    return get_compute_param<uint64_t>(pipe,
    114                                       PIPE_COMPUTE_CAP_MAX_GLOBAL_SIZE)[0];
    115 }
    116 
    117 cl_ulong
    118 _cl_device_id::max_mem_local() const {
    119    return get_compute_param<uint64_t>(pipe,
    120                                       PIPE_COMPUTE_CAP_MAX_LOCAL_SIZE)[0];
    121 }
    122 
    123 cl_ulong
    124 _cl_device_id::max_mem_input() const {
    125    return get_compute_param<uint64_t>(pipe,
    126                                       PIPE_COMPUTE_CAP_MAX_INPUT_SIZE)[0];
    127 }
    128 
    129 cl_ulong
    130 _cl_device_id::max_const_buffer_size() const {
    131    return pipe->get_shader_param(pipe, PIPE_SHADER_COMPUTE,
    132                                  PIPE_SHADER_CAP_MAX_CONSTS) * 16;
    133 }
    134 
    135 cl_uint
    136 _cl_device_id::max_const_buffers() const {
    137    return pipe->get_shader_param(pipe, PIPE_SHADER_COMPUTE,
    138                                  PIPE_SHADER_CAP_MAX_CONST_BUFFERS);
    139 }
    140 
    141 size_t
    142 _cl_device_id::max_threads_per_block() const {
    143    return get_compute_param<uint64_t>(
    144       pipe, PIPE_COMPUTE_CAP_MAX_THREADS_PER_BLOCK)[0];
    145 }
    146 
    147 std::vector<size_t>
    148 _cl_device_id::max_block_size() const {
    149    auto v = get_compute_param<uint64_t>(pipe, PIPE_COMPUTE_CAP_MAX_BLOCK_SIZE);
    150    return { v.begin(), v.end() };
    151 }
    152 
    153 std::string
    154 _cl_device_id::device_name() const {
    155    return pipe->get_name(pipe);
    156 }
    157 
    158 std::string
    159 _cl_device_id::vendor_name() const {
    160    return pipe->get_vendor(pipe);
    161 }
    162 
    163 enum pipe_shader_ir
    164 _cl_device_id::ir_format() const {
    165    return (enum pipe_shader_ir) pipe->get_shader_param(pipe,
    166                                                   PIPE_SHADER_COMPUTE,
    167                                                   PIPE_SHADER_CAP_PREFERRED_IR);
    168 }
    169 
    170 std::string
    171 _cl_device_id::ir_target() const {
    172    std::vector<char> target = get_compute_param<char>(pipe,
    173                                                     PIPE_COMPUTE_CAP_IR_TARGET);
    174    return { target.data() };
    175 }
    176 
    177 device_registry::device_registry() {
    178    int n = pipe_loader_probe(NULL, 0);
    179    std::vector<pipe_loader_device *> ldevs(n);
    180 
    181    pipe_loader_probe(&ldevs.front(), n);
    182 
    183    for (pipe_loader_device *ldev : ldevs) {
    184       try {
    185          devs.emplace_back(ldev);
    186       } catch (error &) {}
    187    }
    188 }
    189