OSDN Git Service

84b3bcb4c09d8af7787291f8a00ded5f7908776f
[android-x86/external-mesa.git] / src / gallium / state_trackers / clover / api / memory.cpp
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 "util/u_math.h"
24 #include "api/util.hpp"
25 #include "core/memory.hpp"
26 #include "core/format.hpp"
27
28 using namespace clover;
29
30 CLOVER_API cl_mem
31 clCreateBuffer(cl_context d_ctx, cl_mem_flags flags, size_t size,
32                void *host_ptr, cl_int *r_errcode) try {
33    auto &ctx = obj(d_ctx);
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        size > fold(maximum(), cl_ulong(0),
41                    map(std::mem_fn(&device::max_mem_alloc_size), ctx.devs())
42           ))
43       throw error(CL_INVALID_BUFFER_SIZE);
44
45    if (flags & ~(CL_MEM_READ_WRITE | CL_MEM_WRITE_ONLY | CL_MEM_READ_ONLY |
46                  CL_MEM_USE_HOST_PTR | CL_MEM_ALLOC_HOST_PTR |
47                  CL_MEM_COPY_HOST_PTR))
48       throw error(CL_INVALID_VALUE);
49
50    if (util_bitcount(flags & (CL_MEM_READ_ONLY | CL_MEM_WRITE_ONLY |
51                               CL_MEM_READ_WRITE)) > 1)
52       throw error(CL_INVALID_VALUE);
53
54    if ((flags & CL_MEM_USE_HOST_PTR) &&
55        (flags & (CL_MEM_COPY_HOST_PTR | CL_MEM_ALLOC_HOST_PTR)))
56       throw error(CL_INVALID_VALUE);
57
58    ret_error(r_errcode, CL_SUCCESS);
59    return new root_buffer(ctx, flags, size, host_ptr);
60
61 } catch (error &e) {
62    ret_error(r_errcode, e);
63    return NULL;
64 }
65
66 CLOVER_API cl_mem
67 clCreateSubBuffer(cl_mem d_mem, cl_mem_flags flags,
68                   cl_buffer_create_type op,
69                   const void *op_info, cl_int *r_errcode) try {
70    auto &parent = obj<root_buffer>(d_mem);
71
72    if ((flags & (CL_MEM_USE_HOST_PTR |
73                  CL_MEM_ALLOC_HOST_PTR |
74                  CL_MEM_COPY_HOST_PTR)) ||
75        (~flags & parent.flags() & (CL_MEM_READ_ONLY |
76                                    CL_MEM_WRITE_ONLY)))
77       throw error(CL_INVALID_VALUE);
78
79    if (op == CL_BUFFER_CREATE_TYPE_REGION) {
80       auto reg = reinterpret_cast<const cl_buffer_region *>(op_info);
81
82       if (!reg ||
83           reg->origin > parent.size() ||
84           reg->origin + reg->size > parent.size())
85          throw error(CL_INVALID_VALUE);
86
87       if (!reg->size)
88          throw error(CL_INVALID_BUFFER_SIZE);
89
90       ret_error(r_errcode, CL_SUCCESS);
91       return new sub_buffer(parent, flags, reg->origin, reg->size);
92
93    } else {
94       throw error(CL_INVALID_VALUE);
95    }
96
97 } catch (error &e) {
98    ret_error(r_errcode, e);
99    return NULL;
100 }
101
102 CLOVER_API cl_mem
103 clCreateImage2D(cl_context d_ctx, cl_mem_flags flags,
104                 const cl_image_format *format,
105                 size_t width, size_t height, size_t row_pitch,
106                 void *host_ptr, cl_int *r_errcode) try {
107    auto &ctx = obj(d_ctx);
108
109    if (flags & ~(CL_MEM_READ_WRITE | CL_MEM_WRITE_ONLY | CL_MEM_READ_ONLY |
110                  CL_MEM_USE_HOST_PTR | CL_MEM_ALLOC_HOST_PTR |
111                  CL_MEM_COPY_HOST_PTR))
112       throw error(CL_INVALID_VALUE);
113
114    if (!format)
115       throw error(CL_INVALID_IMAGE_FORMAT_DESCRIPTOR);
116
117    if (width < 1 || height < 1)
118       throw error(CL_INVALID_IMAGE_SIZE);
119
120    if (bool(host_ptr) != bool(flags & (CL_MEM_USE_HOST_PTR |
121                                        CL_MEM_COPY_HOST_PTR)))
122       throw error(CL_INVALID_HOST_PTR);
123
124    if (!supported_formats(ctx, CL_MEM_OBJECT_IMAGE2D).count(*format))
125       throw error(CL_IMAGE_FORMAT_NOT_SUPPORTED);
126
127    ret_error(r_errcode, CL_SUCCESS);
128    return new image2d(ctx, flags, format, width, height,
129                       row_pitch, host_ptr);
130
131 } catch (error &e) {
132    ret_error(r_errcode, e);
133    return NULL;
134 }
135
136 CLOVER_API cl_mem
137 clCreateImage3D(cl_context d_ctx, cl_mem_flags flags,
138                 const cl_image_format *format,
139                 size_t width, size_t height, size_t depth,
140                 size_t row_pitch, size_t slice_pitch,
141                 void *host_ptr, cl_int *r_errcode) try {
142    auto &ctx = obj(d_ctx);
143
144    if (flags & ~(CL_MEM_READ_WRITE | CL_MEM_WRITE_ONLY | CL_MEM_READ_ONLY |
145                  CL_MEM_USE_HOST_PTR | CL_MEM_ALLOC_HOST_PTR |
146                  CL_MEM_COPY_HOST_PTR))
147       throw error(CL_INVALID_VALUE);
148
149    if (!format)
150       throw error(CL_INVALID_IMAGE_FORMAT_DESCRIPTOR);
151
152    if (width < 1 || height < 1 || depth < 2)
153       throw error(CL_INVALID_IMAGE_SIZE);
154
155    if (bool(host_ptr) != bool(flags & (CL_MEM_USE_HOST_PTR |
156                                        CL_MEM_COPY_HOST_PTR)))
157       throw error(CL_INVALID_HOST_PTR);
158
159    if (!supported_formats(ctx, CL_MEM_OBJECT_IMAGE3D).count(*format))
160       throw error(CL_IMAGE_FORMAT_NOT_SUPPORTED);
161
162    ret_error(r_errcode, CL_SUCCESS);
163    return new image3d(ctx, flags, format, width, height, depth,
164                       row_pitch, slice_pitch, host_ptr);
165
166 } catch (error &e) {
167    ret_error(r_errcode, e);
168    return NULL;
169 }
170
171 CLOVER_API cl_int
172 clGetSupportedImageFormats(cl_context d_ctx, cl_mem_flags flags,
173                            cl_mem_object_type type, cl_uint count,
174                            cl_image_format *r_buf, cl_uint *r_count) try {
175    auto &ctx = obj(d_ctx);
176
177    if (flags & ~(CL_MEM_READ_WRITE | CL_MEM_WRITE_ONLY | CL_MEM_READ_ONLY |
178                  CL_MEM_USE_HOST_PTR | CL_MEM_ALLOC_HOST_PTR |
179                  CL_MEM_COPY_HOST_PTR))
180       throw error(CL_INVALID_VALUE);
181
182    if (r_buf && !r_count)
183       throw error(CL_INVALID_VALUE);
184
185    auto formats = supported_formats(ctx, type);
186
187    if (r_buf)
188       std::copy_n(formats.begin(),
189                   std::min((cl_uint)formats.size(), count),
190                   r_buf);
191
192    if (r_count)
193       *r_count = formats.size();
194
195    return CL_SUCCESS;
196
197 } catch (error &e) {
198    return e.get();
199 }
200
201 CLOVER_API cl_int
202 clGetMemObjectInfo(cl_mem d_mem, cl_mem_info param,
203                    size_t size, void *r_buf, size_t *r_size) try {
204    property_buffer buf { r_buf, size, r_size };
205    auto &mem = obj(d_mem);
206
207    switch (param) {
208    case CL_MEM_TYPE:
209       buf.as_scalar<cl_mem_object_type>() = mem.type();
210       break;
211
212    case CL_MEM_FLAGS:
213       buf.as_scalar<cl_mem_flags>() = mem.flags();
214       break;
215
216    case CL_MEM_SIZE:
217       buf.as_scalar<size_t>() = mem.size();
218       break;
219
220    case CL_MEM_HOST_PTR:
221       buf.as_scalar<void *>() = mem.host_ptr();
222       break;
223
224    case CL_MEM_MAP_COUNT:
225       buf.as_scalar<cl_uint>() = 0;
226       break;
227
228    case CL_MEM_REFERENCE_COUNT:
229       buf.as_scalar<cl_uint>() = mem.ref_count();
230       break;
231
232    case CL_MEM_CONTEXT:
233       buf.as_scalar<cl_context>() = desc(mem.context());
234       break;
235
236    case CL_MEM_ASSOCIATED_MEMOBJECT: {
237       sub_buffer *sub = dynamic_cast<sub_buffer *>(&mem);
238       buf.as_scalar<cl_mem>() = (sub ? desc(sub->parent()) : NULL);
239       break;
240    }
241    case CL_MEM_OFFSET: {
242       sub_buffer *sub = dynamic_cast<sub_buffer *>(&mem);
243       buf.as_scalar<size_t>() = (sub ? sub->offset() : 0);
244       break;
245    }
246    default:
247       throw error(CL_INVALID_VALUE);
248    }
249
250    return CL_SUCCESS;
251
252 } catch (error &e) {
253    return e.get();
254 }
255
256 CLOVER_API cl_int
257 clGetImageInfo(cl_mem d_mem, cl_image_info param,
258                size_t size, void *r_buf, size_t *r_size) try {
259    property_buffer buf { r_buf, size, r_size };
260    auto &img = obj<image>(d_mem);
261
262    switch (param) {
263    case CL_IMAGE_FORMAT:
264       buf.as_scalar<cl_image_format>() = img.format();
265       break;
266
267    case CL_IMAGE_ELEMENT_SIZE:
268       buf.as_scalar<size_t>() = 0;
269       break;
270
271    case CL_IMAGE_ROW_PITCH:
272       buf.as_scalar<size_t>() = img.row_pitch();
273       break;
274
275    case CL_IMAGE_SLICE_PITCH:
276       buf.as_scalar<size_t>() = img.slice_pitch();
277       break;
278
279    case CL_IMAGE_WIDTH:
280       buf.as_scalar<size_t>() = img.width();
281       break;
282
283    case CL_IMAGE_HEIGHT:
284       buf.as_scalar<size_t>() = img.height();
285       break;
286
287    case CL_IMAGE_DEPTH:
288       buf.as_scalar<size_t>() = img.depth();
289       break;
290
291    default:
292       throw error(CL_INVALID_VALUE);
293    }
294
295    return CL_SUCCESS;
296
297 } catch (error &e) {
298    return e.get();
299 }
300
301 CLOVER_API cl_int
302 clRetainMemObject(cl_mem d_mem) try {
303    obj(d_mem).retain();
304    return CL_SUCCESS;
305
306 } catch (error &e) {
307    return e.get();
308 }
309
310 CLOVER_API cl_int
311 clReleaseMemObject(cl_mem d_mem) try {
312    if (obj(d_mem).release())
313       delete pobj(d_mem);
314
315    return CL_SUCCESS;
316
317 } catch (error &e) {
318    return e.get();
319 }
320
321 CLOVER_API cl_int
322 clSetMemObjectDestructorCallback(cl_mem d_mem,
323                                  void (CL_CALLBACK *pfn_notify)(cl_mem, void *),
324                                  void *user_data) try {
325    auto &mem = obj(d_mem);
326
327    if (!pfn_notify)
328       return CL_INVALID_VALUE;
329
330    mem.destroy_notify([=]{ pfn_notify(d_mem, user_data); });
331
332    return CL_SUCCESS;
333
334 } catch (error &e) {
335    return e.get();
336 }