Subversion Repositories Kolibri OS

Rev

Go to most recent revision | 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 "api/util.hpp"
  24. #include "core/program.hpp"
  25.  
  26. using namespace clover;
  27.  
  28. PUBLIC cl_program
  29. clCreateProgramWithSource(cl_context ctx, cl_uint count,
  30.                           const char **strings, const size_t *lengths,
  31.                           cl_int *errcode_ret) try {
  32.    std::string source;
  33.  
  34.    if (!ctx)
  35.       throw error(CL_INVALID_CONTEXT);
  36.  
  37.    if (!count || !strings ||
  38.        any_of(is_zero<const char *>, strings, strings + count))
  39.       throw error(CL_INVALID_VALUE);
  40.  
  41.    // Concatenate all the provided fragments together
  42.    for (unsigned i = 0; i < count; ++i)
  43.          source += (lengths && lengths[i] ?
  44.                     std::string(strings[i], strings[i] + lengths[i]) :
  45.                     std::string(strings[i]));
  46.  
  47.    // ...and create a program object for them.
  48.    ret_error(errcode_ret, CL_SUCCESS);
  49.    return new program(*ctx, source);
  50.  
  51. } catch (error &e) {
  52.    ret_error(errcode_ret, e);
  53.    return NULL;
  54. }
  55.  
  56. PUBLIC cl_program
  57. clCreateProgramWithBinary(cl_context ctx, cl_uint count,
  58.                           const cl_device_id *devs, const size_t *lengths,
  59.                           const unsigned char **binaries, cl_int *status_ret,
  60.                           cl_int *errcode_ret) try {
  61.    if (!ctx)
  62.       throw error(CL_INVALID_CONTEXT);
  63.  
  64.    if (!count || !devs || !lengths || !binaries)
  65.       throw error(CL_INVALID_VALUE);
  66.  
  67.    if (any_of([&](const cl_device_id dev) {
  68.             return !ctx->has_device(dev);
  69.          }, devs, devs + count))
  70.       throw error(CL_INVALID_DEVICE);
  71.  
  72.    // Deserialize the provided binaries,
  73.    auto modules = map(
  74.       [](const unsigned char *p, size_t l) -> std::pair<cl_int, module> {
  75.          if (!p || !l)
  76.             return { CL_INVALID_VALUE, {} };
  77.  
  78.          try {
  79.             compat::istream::buffer_t bin(p, l);
  80.             compat::istream s(bin);
  81.  
  82.             return { CL_SUCCESS, module::deserialize(s) };
  83.  
  84.          } catch (compat::istream::error &e) {
  85.             return { CL_INVALID_BINARY, {} };
  86.          }
  87.       },
  88.       binaries, binaries + count, lengths);
  89.  
  90.    // update the status array,
  91.    if (status_ret)
  92.       std::transform(modules.begin(), modules.end(), status_ret,
  93.                      keys<cl_int, module>);
  94.  
  95.    if (any_of(key_equals<cl_int, module>(CL_INVALID_VALUE),
  96.               modules.begin(), modules.end()))
  97.       throw error(CL_INVALID_VALUE);
  98.  
  99.    if (any_of(key_equals<cl_int, module>(CL_INVALID_BINARY),
  100.               modules.begin(), modules.end()))
  101.       throw error(CL_INVALID_BINARY);
  102.  
  103.    // initialize a program object with them.
  104.    ret_error(errcode_ret, CL_SUCCESS);
  105.    return new program(*ctx, { devs, devs + count },
  106.                       map(values<cl_int, module>,
  107.                           modules.begin(), modules.end()));
  108.  
  109. } catch (error &e) {
  110.    ret_error(errcode_ret, e);
  111.    return NULL;
  112. }
  113.  
  114. PUBLIC cl_int
  115. clRetainProgram(cl_program prog) {
  116.    if (!prog)
  117.       return CL_INVALID_PROGRAM;
  118.  
  119.    prog->retain();
  120.    return CL_SUCCESS;
  121. }
  122.  
  123. PUBLIC cl_int
  124. clReleaseProgram(cl_program prog) {
  125.    if (!prog)
  126.       return CL_INVALID_PROGRAM;
  127.  
  128.    if (prog->release())
  129.       delete prog;
  130.  
  131.    return CL_SUCCESS;
  132. }
  133.  
  134. PUBLIC cl_int
  135. clBuildProgram(cl_program prog, cl_uint count, const cl_device_id *devs,
  136.                const char *opts, void (*pfn_notify)(cl_program, void *),
  137.                void *user_data) try {
  138.    if (!prog)
  139.       throw error(CL_INVALID_PROGRAM);
  140.  
  141.    if (bool(count) != bool(devs) ||
  142.        (!pfn_notify && user_data))
  143.       throw error(CL_INVALID_VALUE);
  144.  
  145.    if (!opts)
  146.       opts = "";
  147.  
  148.    if (devs) {
  149.       if (any_of([&](const cl_device_id dev) {
  150.                return !prog->ctx.has_device(dev);
  151.             }, devs, devs + count))
  152.          throw error(CL_INVALID_DEVICE);
  153.  
  154.       prog->build({ devs, devs + count }, opts);
  155.    } else {
  156.       prog->build(prog->ctx.devs, opts);
  157.    }
  158.  
  159.    return CL_SUCCESS;
  160.  
  161. } catch (error &e) {
  162.    return e.get();
  163. }
  164.  
  165. PUBLIC cl_int
  166. clUnloadCompiler() {
  167.    return CL_SUCCESS;
  168. }
  169.  
  170. PUBLIC cl_int
  171. clGetProgramInfo(cl_program prog, cl_program_info param,
  172.                  size_t size, void *buf, size_t *size_ret) {
  173.    if (!prog)
  174.       return CL_INVALID_PROGRAM;
  175.  
  176.    switch (param) {
  177.    case CL_PROGRAM_REFERENCE_COUNT:
  178.       return scalar_property<cl_uint>(buf, size, size_ret,
  179.                                       prog->ref_count());
  180.  
  181.    case CL_PROGRAM_CONTEXT:
  182.       return scalar_property<cl_context>(buf, size, size_ret,
  183.                                          &prog->ctx);
  184.  
  185.    case CL_PROGRAM_NUM_DEVICES:
  186.       return scalar_property<cl_uint>(buf, size, size_ret,
  187.                                       prog->binaries().size());
  188.  
  189.    case CL_PROGRAM_DEVICES:
  190.       return vector_property<cl_device_id>(
  191.          buf, size, size_ret,
  192.          map(keys<device *, module>,
  193.              prog->binaries().begin(), prog->binaries().end()));
  194.  
  195.    case CL_PROGRAM_SOURCE:
  196.       return string_property(buf, size, size_ret, prog->source());
  197.  
  198.    case CL_PROGRAM_BINARY_SIZES:
  199.       return vector_property<size_t>(
  200.          buf, size, size_ret,
  201.          map([](const std::pair<device *, module> &ent) {
  202.                compat::ostream::buffer_t bin;
  203.                compat::ostream s(bin);
  204.                ent.second.serialize(s);
  205.                return bin.size();
  206.             },
  207.             prog->binaries().begin(), prog->binaries().end()));
  208.  
  209.    case CL_PROGRAM_BINARIES:
  210.       return matrix_property<unsigned char>(
  211.          buf, size, size_ret,
  212.          map([](const std::pair<device *, module> &ent) {
  213.                compat::ostream::buffer_t bin;
  214.                compat::ostream s(bin);
  215.                ent.second.serialize(s);
  216.                return bin;
  217.             },
  218.             prog->binaries().begin(), prog->binaries().end()));
  219.  
  220.    default:
  221.       return CL_INVALID_VALUE;
  222.    }
  223. }
  224.  
  225. PUBLIC cl_int
  226. clGetProgramBuildInfo(cl_program prog, cl_device_id dev,
  227.                       cl_program_build_info param,
  228.                       size_t size, void *buf, size_t *size_ret) {
  229.    if (!prog)
  230.       return CL_INVALID_PROGRAM;
  231.  
  232.    if (!prog->ctx.has_device(dev))
  233.       return CL_INVALID_DEVICE;
  234.  
  235.    switch (param) {
  236.    case CL_PROGRAM_BUILD_STATUS:
  237.       return scalar_property<cl_build_status>(buf, size, size_ret,
  238.                                               prog->build_status(dev));
  239.  
  240.    case CL_PROGRAM_BUILD_OPTIONS:
  241.       return string_property(buf, size, size_ret, prog->build_opts(dev));
  242.  
  243.    case CL_PROGRAM_BUILD_LOG:
  244.       return string_property(buf, size, size_ret, prog->build_log(dev));
  245.  
  246.    default:
  247.       return CL_INVALID_VALUE;
  248.    }
  249. }
  250.