Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. //
  2. // Copyright 2013 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. #ifndef CLOVER_CORE_OBJECT_HPP
  24. #define CLOVER_CORE_OBJECT_HPP
  25.  
  26. #include <cassert>
  27. #include <functional>
  28. #include <vector>
  29.  
  30. #include "CL/cl.h"
  31.  
  32. #include "core/error.hpp"
  33. #include "core/property.hpp"
  34. #include "api/dispatch.hpp"
  35. #include "util/macros.h"
  36.  
  37. ///
  38. /// Main namespace of the CL state tracker.
  39. ///
  40. namespace clover {
  41.    ///
  42.    /// Class that represents a CL API object.
  43.    ///
  44.    template<typename T, typename S>
  45.    struct descriptor {
  46.       typedef T object_type;
  47.       typedef S descriptor_type;
  48.  
  49.       descriptor() : dispatch(&_dispatch) {
  50.          static_assert(std::is_standard_layout<descriptor_type>::value,
  51.                        "ICD requires CL API objects to be standard layout.");
  52.       }
  53.  
  54.       const _cl_icd_dispatch *dispatch;
  55.    };
  56.  
  57.    struct default_tag;
  58.    struct allow_empty_tag;
  59.    struct wait_list_tag;
  60.    struct property_list_tag;
  61.  
  62.    namespace detail {
  63.       template<typename T, typename D>
  64.       struct descriptor_traits {
  65.          typedef T object_type;
  66.  
  67.          static void
  68.          validate(D *d) {
  69.             auto o = static_cast<typename D::object_type *>(d);
  70.             if (!o || o->dispatch != &_dispatch ||
  71.                 !dynamic_cast<object_type *>(o))
  72.                throw invalid_object_error<T>();
  73.          }
  74.  
  75.          static void
  76.          validate_list(D * const *ds, size_t n) {
  77.             if (!ds || !n)
  78.                throw error(CL_INVALID_VALUE);
  79.          }
  80.       };
  81.  
  82.       template<typename D>
  83.       struct descriptor_traits<default_tag, D> {
  84.          typedef typename D::object_type object_type;
  85.  
  86.          static void
  87.          validate(D *d) {
  88.             if (!d || d->dispatch != &_dispatch)
  89.                throw invalid_object_error<object_type>();
  90.          }
  91.  
  92.          static void
  93.          validate_list(D *const *ds, size_t n) {
  94.             if (!ds || !n)
  95.                throw error(CL_INVALID_VALUE);
  96.          }
  97.       };
  98.  
  99.       template<typename D>
  100.       struct descriptor_traits<allow_empty_tag, D> {
  101.          typedef typename D::object_type object_type;
  102.  
  103.          static void
  104.          validate(D *d) {
  105.             if (!d || d->dispatch != &_dispatch)
  106.                throw invalid_object_error<object_type>();
  107.          }
  108.  
  109.          static void
  110.          validate_list(D *const *ds, size_t n) {
  111.             if (bool(ds) != bool(n))
  112.                throw error(CL_INVALID_VALUE);
  113.          }
  114.       };
  115.  
  116.       template<typename D>
  117.       struct descriptor_traits<wait_list_tag, D> {
  118.          typedef typename D::object_type object_type;
  119.  
  120.          static void
  121.          validate(D *d) {
  122.             if (!d || d->dispatch != &_dispatch)
  123.                throw invalid_wait_list_error();
  124.          }
  125.  
  126.          static void
  127.          validate_list(D *const *ds, size_t n) {
  128.             if (bool(ds) != bool(n))
  129.                throw invalid_wait_list_error();
  130.          }
  131.       };
  132.    }
  133.  
  134.    ///
  135.    /// Get a Clover object from an API object performing object
  136.    /// validation.
  137.    ///
  138.    /// \a T can either be the Clover object type to return or a \a tag
  139.    /// object to select some special validation behavior by means of a
  140.    /// specialization of the detail::descriptor_traits template.  The
  141.    /// default behavior is to infer the most general Clover object
  142.    /// type for the given API object.
  143.    ///
  144.    template<typename T = default_tag, typename D>
  145.    typename detail::descriptor_traits<T, D>::object_type &
  146.    obj(D *d) {
  147.       detail::descriptor_traits<T, D>::validate(d);
  148.  
  149.       return static_cast<
  150.          typename detail::descriptor_traits<T, D>::object_type &>(*d);
  151.    }
  152.  
  153.    ///
  154.    /// Get a pointer to a Clover object from an API object performing
  155.    /// object validation.  Returns \c NULL if its argument is \c NULL.
  156.    ///
  157.    /// \sa obj
  158.    ///
  159.    template<typename T = default_tag, typename D>
  160.    typename detail::descriptor_traits<T, D>::object_type *
  161.    pobj(D *d) {
  162.       if (d)
  163.          detail::descriptor_traits<T, D>::validate(d);
  164.  
  165.       return static_cast<
  166.          typename detail::descriptor_traits<T, D>::object_type *>(d);
  167.    }
  168.  
  169.    ///
  170.    /// Get an API object from a Clover object.
  171.    ///
  172.    template<typename O>
  173.    typename O::descriptor_type *
  174.    desc(O &o) {
  175.       return static_cast<typename O::descriptor_type *>(&o);
  176.    }
  177.  
  178.    ///
  179.    /// Get an API object from a pointer to a Clover object.
  180.    ///
  181.    template<typename O>
  182.    typename O::descriptor_type *
  183.    desc(O *o) {
  184.       return static_cast<typename O::descriptor_type *>(o);
  185.    }
  186.  
  187.    ///
  188.    /// Get a range of Clover objects from a range of API objects
  189.    /// performing object validation.
  190.    ///
  191.    /// \sa obj
  192.    ///
  193.    template<typename T = default_tag, typename D>
  194.    ref_vector<typename detail::descriptor_traits<T, D>::object_type>
  195.    objs(D *const *ds, size_t n) {
  196.       detail::descriptor_traits<T, D>::validate_list(ds, n);
  197.       return map(obj<T, D>, range(ds, n));
  198.    }
  199.  
  200.    ///
  201.    /// Get a range of API objects from a range of Clover objects.
  202.    ///
  203.    template<typename Os>
  204.    std::vector<typename Os::value_type::descriptor_type *>
  205.    descs(const Os &os) {
  206.       return map([](typename Os::value_type &o) {
  207.             return desc(o);
  208.          }, os);
  209.    }
  210. }
  211.  
  212. struct _cl_context :
  213.    public clover::descriptor<clover::context, _cl_context> {};
  214.  
  215. struct _cl_device_id :
  216.    public clover::descriptor<clover::device, _cl_device_id> {};
  217.  
  218. struct _cl_event :
  219.    public clover::descriptor<clover::event, _cl_event> {};
  220.  
  221. struct _cl_kernel :
  222.    public clover::descriptor<clover::kernel, _cl_kernel> {};
  223.  
  224. struct _cl_mem :
  225.    public clover::descriptor<clover::memory_obj, _cl_mem> {};
  226.  
  227. struct _cl_platform_id :
  228.    public clover::descriptor<clover::platform, _cl_platform_id> {};
  229.  
  230. struct _cl_program :
  231.    public clover::descriptor<clover::program, _cl_program> {};
  232.  
  233. struct _cl_command_queue :
  234.    public clover::descriptor<clover::command_queue, _cl_command_queue> {};
  235.  
  236. struct _cl_sampler :
  237.    public clover::descriptor<clover::sampler, _cl_sampler> {};
  238.  
  239. #endif
  240.