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 gallium frontend. 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 descriptorclover::descriptor49 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 validateclover::detail::descriptor_traits68 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 validate_listclover::detail::descriptor_traits76 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 validateclover::detail::descriptor_traits87 validate(D *d) { 88 if (!d || d->dispatch != &_dispatch) 89 throw invalid_object_error<object_type>(); 90 } 91 92 static void validate_listclover::detail::descriptor_traits93 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 validateclover::detail::descriptor_traits104 validate(D *d) { 105 if (!d || d->dispatch != &_dispatch) 106 throw invalid_object_error<object_type>(); 107 } 108 109 static void validate_listclover::detail::descriptor_traits110 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 validateclover::detail::descriptor_traits121 validate(D *d) { 122 if (!d || d->dispatch != &_dispatch) 123 throw invalid_wait_list_error(); 124 } 125 126 static void validate_listclover::detail::descriptor_traits127 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 & obj(D * d)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 * pobj(D * d)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 * desc(O & o)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 * desc(O * o)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> objs(D * const * ds,size_t n)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 *> descs(const Os & os)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