• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
clCreateBuffer(cl_context ctx,cl_mem_flags flags,size_t size,void * host_ptr,cl_int * errcode_ret)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
clCreateSubBuffer(cl_mem obj,cl_mem_flags flags,cl_buffer_create_type op,const void * op_info,cl_int * errcode_ret)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
clCreateImage2D(cl_context ctx,cl_mem_flags flags,const cl_image_format * format,size_t width,size_t height,size_t row_pitch,void * host_ptr,cl_int * errcode_ret)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
clCreateImage3D(cl_context ctx,cl_mem_flags flags,const cl_image_format * format,size_t width,size_t height,size_t depth,size_t row_pitch,size_t slice_pitch,void * host_ptr,cl_int * errcode_ret)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
clGetSupportedImageFormats(cl_context ctx,cl_mem_flags flags,cl_mem_object_type type,cl_uint count,cl_image_format * buf,cl_uint * count_ret)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
clGetMemObjectInfo(cl_mem obj,cl_mem_info param,size_t size,void * buf,size_t * size_ret)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
clGetImageInfo(cl_mem obj,cl_image_info param,size_t size,void * buf,size_t * size_ret)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
clRetainMemObject(cl_mem obj)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
clReleaseMemObject(cl_mem obj)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
clSetMemObjectDestructorCallback(cl_mem obj,void (CL_CALLBACK * pfn_notify)(cl_mem,void *),void * user_data)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