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