Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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 "util/u_math.h"
  24. #include "api/util.hpp"
  25. #include "core/memory.hpp"
  26. #include "core/format.hpp"
  27.  
  28. using namespace clover;
  29.  
  30. namespace {
  31.    const cl_mem_flags dev_access_flags =
  32.       CL_MEM_READ_WRITE | CL_MEM_WRITE_ONLY | CL_MEM_READ_ONLY;
  33.    const cl_mem_flags host_ptr_flags =
  34.       CL_MEM_USE_HOST_PTR | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR;
  35.    const cl_mem_flags host_access_flags =
  36.       CL_MEM_HOST_WRITE_ONLY | CL_MEM_HOST_READ_ONLY | CL_MEM_HOST_NO_ACCESS;
  37.    const cl_mem_flags all_mem_flags =
  38.       dev_access_flags | host_ptr_flags | host_access_flags;
  39.  
  40.    void
  41.    validate_flags(cl_mem_flags flags, cl_mem_flags valid) {
  42.       if ((flags & ~valid) ||
  43.           util_bitcount(flags & dev_access_flags) > 1 ||
  44.           util_bitcount(flags & host_access_flags) > 1)
  45.          throw error(CL_INVALID_VALUE);
  46.  
  47.       if ((flags & CL_MEM_USE_HOST_PTR) &&
  48.           (flags & (CL_MEM_COPY_HOST_PTR | CL_MEM_ALLOC_HOST_PTR)))
  49.          throw error(CL_INVALID_VALUE);
  50.    }
  51. }
  52.  
  53. CLOVER_API cl_mem
  54. clCreateBuffer(cl_context d_ctx, cl_mem_flags d_flags, size_t size,
  55.                void *host_ptr, cl_int *r_errcode) try {
  56.    const cl_mem_flags flags = d_flags |
  57.       (d_flags & dev_access_flags ? 0 : CL_MEM_READ_WRITE);
  58.    auto &ctx = obj(d_ctx);
  59.  
  60.    validate_flags(d_flags, all_mem_flags);
  61.  
  62.    if (bool(host_ptr) != bool(flags & (CL_MEM_USE_HOST_PTR |
  63.                                        CL_MEM_COPY_HOST_PTR)))
  64.       throw error(CL_INVALID_HOST_PTR);
  65.  
  66.    if (!size ||
  67.        size > fold(maximum(), cl_ulong(0),
  68.                    map(std::mem_fn(&device::max_mem_alloc_size), ctx.devices())
  69.           ))
  70.       throw error(CL_INVALID_BUFFER_SIZE);
  71.  
  72.    ret_error(r_errcode, CL_SUCCESS);
  73.    return new root_buffer(ctx, flags, size, host_ptr);
  74.  
  75. } catch (error &e) {
  76.    ret_error(r_errcode, e);
  77.    return NULL;
  78. }
  79.  
  80. CLOVER_API cl_mem
  81. clCreateSubBuffer(cl_mem d_mem, cl_mem_flags d_flags,
  82.                   cl_buffer_create_type op,
  83.                   const void *op_info, cl_int *r_errcode) try {
  84.    auto &parent = obj<root_buffer>(d_mem);
  85.    const cl_mem_flags flags = d_flags |
  86.       (d_flags & dev_access_flags ? 0 : parent.flags() & dev_access_flags) |
  87.       (d_flags & host_access_flags ? 0 : parent.flags() & host_access_flags) |
  88.       (parent.flags() & host_ptr_flags);
  89.  
  90.    validate_flags(d_flags, dev_access_flags | host_access_flags);
  91.  
  92.    if (~flags & parent.flags() &
  93.        ((dev_access_flags & ~CL_MEM_READ_WRITE) | host_access_flags))
  94.       throw error(CL_INVALID_VALUE);
  95.  
  96.    if (op == CL_BUFFER_CREATE_TYPE_REGION) {
  97.       auto reg = reinterpret_cast<const cl_buffer_region *>(op_info);
  98.  
  99.       if (!reg ||
  100.           reg->origin > parent.size() ||
  101.           reg->origin + reg->size > parent.size())
  102.          throw error(CL_INVALID_VALUE);
  103.  
  104.       if (!reg->size)
  105.          throw error(CL_INVALID_BUFFER_SIZE);
  106.  
  107.       ret_error(r_errcode, CL_SUCCESS);
  108.       return new sub_buffer(parent, flags, reg->origin, reg->size);
  109.  
  110.    } else {
  111.       throw error(CL_INVALID_VALUE);
  112.    }
  113.  
  114. } catch (error &e) {
  115.    ret_error(r_errcode, e);
  116.    return NULL;
  117. }
  118.  
  119. CLOVER_API cl_mem
  120. clCreateImage2D(cl_context d_ctx, cl_mem_flags d_flags,
  121.                 const cl_image_format *format,
  122.                 size_t width, size_t height, size_t row_pitch,
  123.                 void *host_ptr, cl_int *r_errcode) try {
  124.    const cl_mem_flags flags = d_flags |
  125.       (d_flags & dev_access_flags ? 0 : CL_MEM_READ_WRITE);
  126.    auto &ctx = obj(d_ctx);
  127.  
  128.    validate_flags(d_flags, all_mem_flags);
  129.  
  130.    if (!any_of(std::mem_fn(&device::image_support), ctx.devices()))
  131.       throw error(CL_INVALID_OPERATION);
  132.  
  133.    if (!format)
  134.       throw error(CL_INVALID_IMAGE_FORMAT_DESCRIPTOR);
  135.  
  136.    if (width < 1 || height < 1)
  137.       throw error(CL_INVALID_IMAGE_SIZE);
  138.  
  139.    if (bool(host_ptr) != bool(flags & (CL_MEM_USE_HOST_PTR |
  140.                                        CL_MEM_COPY_HOST_PTR)))
  141.       throw error(CL_INVALID_HOST_PTR);
  142.  
  143.    if (!supported_formats(ctx, CL_MEM_OBJECT_IMAGE2D).count(*format))
  144.       throw error(CL_IMAGE_FORMAT_NOT_SUPPORTED);
  145.  
  146.    ret_error(r_errcode, CL_SUCCESS);
  147.    return new image2d(ctx, flags, format, width, height,
  148.                       row_pitch, host_ptr);
  149.  
  150. } catch (error &e) {
  151.    ret_error(r_errcode, e);
  152.    return NULL;
  153. }
  154.  
  155. CLOVER_API cl_mem
  156. clCreateImage3D(cl_context d_ctx, cl_mem_flags d_flags,
  157.                 const cl_image_format *format,
  158.                 size_t width, size_t height, size_t depth,
  159.                 size_t row_pitch, size_t slice_pitch,
  160.                 void *host_ptr, cl_int *r_errcode) try {
  161.    const cl_mem_flags flags = d_flags |
  162.       (d_flags & dev_access_flags ? 0 : CL_MEM_READ_WRITE);
  163.    auto &ctx = obj(d_ctx);
  164.  
  165.    validate_flags(d_flags, all_mem_flags);
  166.  
  167.    if (!any_of(std::mem_fn(&device::image_support), ctx.devices()))
  168.       throw error(CL_INVALID_OPERATION);
  169.  
  170.    if (!format)
  171.       throw error(CL_INVALID_IMAGE_FORMAT_DESCRIPTOR);
  172.  
  173.    if (width < 1 || height < 1 || depth < 2)
  174.       throw error(CL_INVALID_IMAGE_SIZE);
  175.  
  176.    if (bool(host_ptr) != bool(flags & (CL_MEM_USE_HOST_PTR |
  177.                                        CL_MEM_COPY_HOST_PTR)))
  178.       throw error(CL_INVALID_HOST_PTR);
  179.  
  180.    if (!supported_formats(ctx, CL_MEM_OBJECT_IMAGE3D).count(*format))
  181.       throw error(CL_IMAGE_FORMAT_NOT_SUPPORTED);
  182.  
  183.    ret_error(r_errcode, CL_SUCCESS);
  184.    return new image3d(ctx, flags, format, width, height, depth,
  185.                       row_pitch, slice_pitch, host_ptr);
  186.  
  187. } catch (error &e) {
  188.    ret_error(r_errcode, e);
  189.    return NULL;
  190. }
  191.  
  192. CLOVER_API cl_int
  193. clGetSupportedImageFormats(cl_context d_ctx, cl_mem_flags flags,
  194.                            cl_mem_object_type type, cl_uint count,
  195.                            cl_image_format *r_buf, cl_uint *r_count) try {
  196.    auto &ctx = obj(d_ctx);
  197.    auto formats = supported_formats(ctx, type);
  198.  
  199.    validate_flags(flags, all_mem_flags);
  200.  
  201.    if (r_buf && !r_count)
  202.       throw error(CL_INVALID_VALUE);
  203.  
  204.    if (r_buf)
  205.       std::copy_n(formats.begin(),
  206.                   std::min((cl_uint)formats.size(), count),
  207.                   r_buf);
  208.  
  209.    if (r_count)
  210.       *r_count = formats.size();
  211.  
  212.    return CL_SUCCESS;
  213.  
  214. } catch (error &e) {
  215.    return e.get();
  216. }
  217.  
  218. CLOVER_API cl_int
  219. clGetMemObjectInfo(cl_mem d_mem, cl_mem_info param,
  220.                    size_t size, void *r_buf, size_t *r_size) try {
  221.    property_buffer buf { r_buf, size, r_size };
  222.    auto &mem = obj(d_mem);
  223.  
  224.    switch (param) {
  225.    case CL_MEM_TYPE:
  226.       buf.as_scalar<cl_mem_object_type>() = mem.type();
  227.       break;
  228.  
  229.    case CL_MEM_FLAGS:
  230.       buf.as_scalar<cl_mem_flags>() = mem.flags();
  231.       break;
  232.  
  233.    case CL_MEM_SIZE:
  234.       buf.as_scalar<size_t>() = mem.size();
  235.       break;
  236.  
  237.    case CL_MEM_HOST_PTR:
  238.       buf.as_scalar<void *>() = mem.host_ptr();
  239.       break;
  240.  
  241.    case CL_MEM_MAP_COUNT:
  242.       buf.as_scalar<cl_uint>() = 0;
  243.       break;
  244.  
  245.    case CL_MEM_REFERENCE_COUNT:
  246.       buf.as_scalar<cl_uint>() = mem.ref_count();
  247.       break;
  248.  
  249.    case CL_MEM_CONTEXT:
  250.       buf.as_scalar<cl_context>() = desc(mem.context());
  251.       break;
  252.  
  253.    case CL_MEM_ASSOCIATED_MEMOBJECT: {
  254.       sub_buffer *sub = dynamic_cast<sub_buffer *>(&mem);
  255.       buf.as_scalar<cl_mem>() = (sub ? desc(sub->parent()) : NULL);
  256.       break;
  257.    }
  258.    case CL_MEM_OFFSET: {
  259.       sub_buffer *sub = dynamic_cast<sub_buffer *>(&mem);
  260.       buf.as_scalar<size_t>() = (sub ? sub->offset() : 0);
  261.       break;
  262.    }
  263.    default:
  264.       throw error(CL_INVALID_VALUE);
  265.    }
  266.  
  267.    return CL_SUCCESS;
  268.  
  269. } catch (error &e) {
  270.    return e.get();
  271. }
  272.  
  273. CLOVER_API cl_int
  274. clGetImageInfo(cl_mem d_mem, cl_image_info param,
  275.                size_t size, void *r_buf, size_t *r_size) try {
  276.    property_buffer buf { r_buf, size, r_size };
  277.    auto &img = obj<image>(d_mem);
  278.  
  279.    switch (param) {
  280.    case CL_IMAGE_FORMAT:
  281.       buf.as_scalar<cl_image_format>() = img.format();
  282.       break;
  283.  
  284.    case CL_IMAGE_ELEMENT_SIZE:
  285.       buf.as_scalar<size_t>() = 0;
  286.       break;
  287.  
  288.    case CL_IMAGE_ROW_PITCH:
  289.       buf.as_scalar<size_t>() = img.row_pitch();
  290.       break;
  291.  
  292.    case CL_IMAGE_SLICE_PITCH:
  293.       buf.as_scalar<size_t>() = img.slice_pitch();
  294.       break;
  295.  
  296.    case CL_IMAGE_WIDTH:
  297.       buf.as_scalar<size_t>() = img.width();
  298.       break;
  299.  
  300.    case CL_IMAGE_HEIGHT:
  301.       buf.as_scalar<size_t>() = img.height();
  302.       break;
  303.  
  304.    case CL_IMAGE_DEPTH:
  305.       buf.as_scalar<size_t>() = img.depth();
  306.       break;
  307.  
  308.    default:
  309.       throw error(CL_INVALID_VALUE);
  310.    }
  311.  
  312.    return CL_SUCCESS;
  313.  
  314. } catch (error &e) {
  315.    return e.get();
  316. }
  317.  
  318. CLOVER_API cl_int
  319. clRetainMemObject(cl_mem d_mem) try {
  320.    obj(d_mem).retain();
  321.    return CL_SUCCESS;
  322.  
  323. } catch (error &e) {
  324.    return e.get();
  325. }
  326.  
  327. CLOVER_API cl_int
  328. clReleaseMemObject(cl_mem d_mem) try {
  329.    if (obj(d_mem).release())
  330.       delete pobj(d_mem);
  331.  
  332.    return CL_SUCCESS;
  333.  
  334. } catch (error &e) {
  335.    return e.get();
  336. }
  337.  
  338. CLOVER_API cl_int
  339. clSetMemObjectDestructorCallback(cl_mem d_mem,
  340.                                  void (CL_CALLBACK *pfn_notify)(cl_mem, void *),
  341.                                  void *user_data) try {
  342.    auto &mem = obj(d_mem);
  343.  
  344.    if (!pfn_notify)
  345.       return CL_INVALID_VALUE;
  346.  
  347.    mem.destroy_notify([=]{ pfn_notify(d_mem, user_data); });
  348.  
  349.    return CL_SUCCESS;
  350.  
  351. } catch (error &e) {
  352.    return e.get();
  353. }
  354.  
  355. CLOVER_API cl_mem
  356. clCreateImage(cl_context d_ctx, cl_mem_flags flags,
  357.               const cl_image_format *format,
  358.               const cl_image_desc *image_desc,
  359.               void *host_ptr, cl_int *r_errcode) {
  360.    // This function was added in OpenCL 1.2
  361.    std::cerr << "CL user error: clCreateImage() not supported by OpenCL 1.1." <<
  362.                 std::endl;
  363.    ret_error(r_errcode, CL_INVALID_OPERATION);
  364.    return NULL;
  365. }
  366.