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 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 "api/util.hpp"
     24 #include "core/memory.hpp"
     25 #include "core/format.hpp"
     26 
     27 using namespace clover;
     28 
     29 PUBLIC cl_mem
     30 clCreateBuffer(cl_context ctx, cl_mem_flags flags, size_t size,
     31                void *host_ptr, cl_int *errcode_ret) try {
     32    if (!ctx)
     33       throw error(CL_INVALID_CONTEXT);
     34 
     35    if (bool(host_ptr) != bool(flags & (CL_MEM_USE_HOST_PTR |
     36                                        CL_MEM_COPY_HOST_PTR)))
     37       throw error(CL_INVALID_HOST_PTR);
     38 
     39    if (!size)
     40       throw error(CL_INVALID_BUFFER_SIZE);
     41 
     42    if (flags & ~(CL_MEM_READ_WRITE | CL_MEM_WRITE_ONLY | CL_MEM_READ_ONLY |
     43                  CL_MEM_USE_HOST_PTR | CL_MEM_ALLOC_HOST_PTR |
     44                  CL_MEM_COPY_HOST_PTR))
     45       throw error(CL_INVALID_VALUE);
     46 
     47    ret_error(errcode_ret, CL_SUCCESS);
     48    return new root_buffer(*ctx, flags, size, host_ptr);
     49 
     50 } catch (error &e) {
     51    ret_error(errcode_ret, e);
     52    return NULL;
     53 }
     54 
     55 PUBLIC cl_mem
     56 clCreateSubBuffer(cl_mem obj, cl_mem_flags flags, cl_buffer_create_type op,
     57                   const void *op_info, cl_int *errcode_ret) try {
     58    root_buffer *parent = dynamic_cast<root_buffer *>(obj);
     59 
     60    if (!parent)
     61       throw error(CL_INVALID_MEM_OBJECT);
     62 
     63    if ((flags & (CL_MEM_USE_HOST_PTR |
     64                  CL_MEM_ALLOC_HOST_PTR |
     65                  CL_MEM_COPY_HOST_PTR)) ||
     66        (~flags & parent->flags() & (CL_MEM_READ_ONLY |
     67                                     CL_MEM_WRITE_ONLY)))
     68       throw error(CL_INVALID_VALUE);
     69 
     70    if (op == CL_BUFFER_CREATE_TYPE_REGION) {
     71       const cl_buffer_region *reg = (const cl_buffer_region *)op_info;
     72 
     73       if (!reg ||
     74           reg->origin > parent->size() ||
     75           reg->origin + reg->size > parent->size())
     76          throw error(CL_INVALID_VALUE);
     77 
     78       if (!reg->size)
     79          throw error(CL_INVALID_BUFFER_SIZE);
     80 
     81       ret_error(errcode_ret, CL_SUCCESS);
     82       return new sub_buffer(*parent, flags, reg->origin, reg->size);
     83 
     84    } else {
     85       throw error(CL_INVALID_VALUE);
     86    }
     87 
     88 } catch (error &e) {
     89    ret_error(errcode_ret, e);
     90    return NULL;
     91 }
     92 
     93 PUBLIC cl_mem
     94 clCreateImage2D(cl_context ctx, cl_mem_flags flags,
     95                 const cl_image_format *format,
     96                 size_t width, size_t height, size_t row_pitch,
     97                 void *host_ptr, cl_int *errcode_ret) try {
     98    if (!ctx)
     99       throw error(CL_INVALID_CONTEXT);
    100 
    101    if (flags & ~(CL_MEM_READ_WRITE | CL_MEM_WRITE_ONLY | CL_MEM_READ_ONLY |
    102                  CL_MEM_USE_HOST_PTR | CL_MEM_ALLOC_HOST_PTR |
    103                  CL_MEM_COPY_HOST_PTR))
    104       throw error(CL_INVALID_VALUE);
    105 
    106    if (!format)
    107       throw error(CL_INVALID_IMAGE_FORMAT_DESCRIPTOR);
    108 
    109    if (width < 1 || height < 1)
    110       throw error(CL_INVALID_IMAGE_SIZE);
    111 
    112    if (bool(host_ptr) != bool(flags & (CL_MEM_USE_HOST_PTR |
    113                                        CL_MEM_COPY_HOST_PTR)))
    114       throw error(CL_INVALID_HOST_PTR);
    115 
    116    if (!supported_formats(ctx, CL_MEM_OBJECT_IMAGE2D).count(*format))
    117       throw error(CL_IMAGE_FORMAT_NOT_SUPPORTED);
    118 
    119    ret_error(errcode_ret, CL_SUCCESS);
    120    return new image2d(*ctx, flags, format, width, height,
    121                       row_pitch, host_ptr);
    122 
    123 } catch (error &e) {
    124    ret_error(errcode_ret, e);
    125    return NULL;
    126 }
    127 
    128 PUBLIC cl_mem
    129 clCreateImage3D(cl_context ctx, cl_mem_flags flags,
    130                 const cl_image_format *format,
    131                 size_t width, size_t height, size_t depth,
    132                 size_t row_pitch, size_t slice_pitch,
    133                 void *host_ptr, cl_int *errcode_ret) try {
    134    if (!ctx)
    135       throw error(CL_INVALID_CONTEXT);
    136 
    137    if (flags & ~(CL_MEM_READ_WRITE | CL_MEM_WRITE_ONLY | CL_MEM_READ_ONLY |
    138                  CL_MEM_USE_HOST_PTR | CL_MEM_ALLOC_HOST_PTR |
    139                  CL_MEM_COPY_HOST_PTR))
    140       throw error(CL_INVALID_VALUE);
    141 
    142    if (!format)
    143       throw error(CL_INVALID_IMAGE_FORMAT_DESCRIPTOR);
    144 
    145    if (width < 1 || height < 1 || depth < 2)
    146       throw error(CL_INVALID_IMAGE_SIZE);
    147 
    148    if (bool(host_ptr) != bool(flags & (CL_MEM_USE_HOST_PTR |
    149                                        CL_MEM_COPY_HOST_PTR)))
    150       throw error(CL_INVALID_HOST_PTR);
    151 
    152    if (!supported_formats(ctx, CL_MEM_OBJECT_IMAGE3D).count(*format))
    153       throw error(CL_IMAGE_FORMAT_NOT_SUPPORTED);
    154 
    155    ret_error(errcode_ret, CL_SUCCESS);
    156    return new image3d(*ctx, flags, format, width, height, depth,
    157                       row_pitch, slice_pitch, host_ptr);
    158 
    159 } catch (error &e) {
    160    ret_error(errcode_ret, e);
    161    return NULL;
    162 }
    163 
    164 PUBLIC cl_int
    165 clGetSupportedImageFormats(cl_context ctx, cl_mem_flags flags,
    166                            cl_mem_object_type type, cl_uint count,
    167                            cl_image_format *buf, cl_uint *count_ret) try {
    168    if (!ctx)
    169       throw error(CL_INVALID_CONTEXT);
    170 
    171    if (flags & ~(CL_MEM_READ_WRITE | CL_MEM_WRITE_ONLY | CL_MEM_READ_ONLY |
    172                  CL_MEM_USE_HOST_PTR | CL_MEM_ALLOC_HOST_PTR |
    173                  CL_MEM_COPY_HOST_PTR))
    174       throw error(CL_INVALID_VALUE);
    175 
    176    if (!count && buf)
    177       throw error(CL_INVALID_VALUE);
    178 
    179    auto formats = supported_formats(ctx, type);
    180 
    181    if (buf)
    182       std::copy_n(formats.begin(), std::min((cl_uint)formats.size(), count),
    183                   buf);
    184    if (count_ret)
    185       *count_ret = formats.size();
    186 
    187    return CL_SUCCESS;
    188 
    189 } catch (error &e) {
    190    return e.get();
    191 }
    192 
    193 PUBLIC cl_int
    194 clGetMemObjectInfo(cl_mem obj, cl_mem_info param,
    195                    size_t size, void *buf, size_t *size_ret) {
    196    if (!obj)
    197       return CL_INVALID_MEM_OBJECT;
    198 
    199    switch (param) {
    200    case CL_MEM_TYPE:
    201       return scalar_property<cl_mem_object_type>(buf, size, size_ret,
    202                                                  obj->type());
    203 
    204    case CL_MEM_FLAGS:
    205       return scalar_property<cl_mem_flags>(buf, size, size_ret, obj->flags());
    206 
    207    case CL_MEM_SIZE:
    208       return scalar_property<size_t>(buf, size, size_ret, obj->size());
    209 
    210    case CL_MEM_HOST_PTR:
    211       return scalar_property<void *>(buf, size, size_ret, obj->host_ptr());
    212 
    213    case CL_MEM_MAP_COUNT:
    214       return scalar_property<cl_uint>(buf, size, size_ret, 0);
    215 
    216    case CL_MEM_REFERENCE_COUNT:
    217       return scalar_property<cl_uint>(buf, size, size_ret, obj->ref_count());
    218 
    219    case CL_MEM_CONTEXT:
    220       return scalar_property<cl_context>(buf, size, size_ret, &obj->ctx);
    221 
    222    case CL_MEM_ASSOCIATED_MEMOBJECT: {
    223       sub_buffer *sub = dynamic_cast<sub_buffer *>(obj);
    224       return scalar_property<cl_mem>(buf, size, size_ret,
    225                                      (sub ? &sub->parent : NULL));
    226    }
    227    case CL_MEM_OFFSET: {
    228       sub_buffer *sub = dynamic_cast<sub_buffer *>(obj);
    229       return scalar_property<size_t>(buf, size, size_ret,
    230                                      (sub ? sub->offset() : 0));
    231    }
    232    default:
    233       return CL_INVALID_VALUE;
    234    }
    235 }
    236 
    237 PUBLIC cl_int
    238 clGetImageInfo(cl_mem obj, cl_image_info param,
    239                size_t size, void *buf, size_t *size_ret) {
    240    image *img = dynamic_cast<image *>(obj);
    241    if (!img)
    242       return CL_INVALID_MEM_OBJECT;
    243 
    244    switch (param) {
    245    case CL_IMAGE_FORMAT:
    246       return scalar_property<cl_image_format>(buf, size, size_ret,
    247                                               img->format());
    248 
    249    case CL_IMAGE_ELEMENT_SIZE:
    250       return scalar_property<size_t>(buf, size, size_ret, 0);
    251 
    252    case CL_IMAGE_ROW_PITCH:
    253       return scalar_property<size_t>(buf, size, size_ret, img->row_pitch());
    254 
    255    case CL_IMAGE_SLICE_PITCH:
    256       return scalar_property<size_t>(buf, size, size_ret, img->slice_pitch());
    257 
    258    case CL_IMAGE_WIDTH:
    259       return scalar_property<size_t>(buf, size, size_ret, img->width());
    260 
    261    case CL_IMAGE_HEIGHT:
    262       return scalar_property<size_t>(buf, size, size_ret, img->height());
    263 
    264    case CL_IMAGE_DEPTH:
    265       return scalar_property<size_t>(buf, size, size_ret, img->depth());
    266 
    267    default:
    268       return CL_INVALID_VALUE;
    269    }
    270 }
    271 
    272 PUBLIC cl_int
    273 clRetainMemObject(cl_mem obj) {
    274    if (!obj)
    275       return CL_INVALID_MEM_OBJECT;
    276 
    277    obj->retain();
    278    return CL_SUCCESS;
    279 }
    280 
    281 PUBLIC cl_int
    282 clReleaseMemObject(cl_mem obj) {
    283    if (!obj)
    284       return CL_INVALID_MEM_OBJECT;
    285 
    286    if (obj->release())
    287       delete obj;
    288 
    289    return CL_SUCCESS;
    290 }
    291 
    292 PUBLIC cl_int
    293 clSetMemObjectDestructorCallback(cl_mem obj,
    294                                  void (CL_CALLBACK *pfn_notify)(cl_mem, void *),
    295                                  void *user_data) {
    296    if (!obj)
    297       return CL_INVALID_MEM_OBJECT;
    298 
    299    if (!pfn_notify)
    300       return CL_INVALID_VALUE;
    301 
    302    obj->destroy_notify([=]{ pfn_notify(obj, user_data); });
    303 
    304    return CL_SUCCESS;
    305 }
    306