1efb95b5ce77b2d3a048fc5c7b798317ea698feb
[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 namespace {
31 const cl_mem_flags dev_access_flags =
32 CL_MEM_READ_WRITE | CL_MEM_WRITE_ONLY | CL_MEM_READ_ONLY;
33 const cl_mem_flags host_ptr_flags =
34 CL_MEM_USE_HOST_PTR | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR;
35 const cl_mem_flags host_access_flags =
36 CL_MEM_HOST_WRITE_ONLY | CL_MEM_HOST_READ_ONLY | CL_MEM_HOST_NO_ACCESS;
37 const cl_mem_flags all_mem_flags =
38 dev_access_flags | host_ptr_flags | host_access_flags;
39
40 void
41 validate_flags(cl_mem_flags flags, cl_mem_flags valid) {
42 if ((flags & ~valid) ||
43 util_bitcount(flags & dev_access_flags) > 1 ||
44 util_bitcount(flags & host_access_flags) > 1)
45 throw error(CL_INVALID_VALUE);
46
47 if ((flags & CL_MEM_USE_HOST_PTR) &&
48 (flags & (CL_MEM_COPY_HOST_PTR | CL_MEM_ALLOC_HOST_PTR)))
49 throw error(CL_INVALID_VALUE);
50 }
51 }
52
53 CLOVER_API cl_mem
54 clCreateBuffer(cl_context d_ctx, cl_mem_flags d_flags, size_t size,
55 void *host_ptr, cl_int *r_errcode) try {
56 const cl_mem_flags flags = d_flags |
57 (d_flags & dev_access_flags ? 0 : CL_MEM_READ_WRITE);
58 auto &ctx = obj(d_ctx);
59
60 validate_flags(d_flags, all_mem_flags);
61
62 if (bool(host_ptr) != bool(flags & (CL_MEM_USE_HOST_PTR |
63 CL_MEM_COPY_HOST_PTR)))
64 throw error(CL_INVALID_HOST_PTR);
65
66 if (!size ||
67 size > fold(maximum(), cl_ulong(0),
68 map(std::mem_fn(&device::max_mem_alloc_size), ctx.devices())
69 ))
70 throw error(CL_INVALID_BUFFER_SIZE);
71
72 ret_error(r_errcode, CL_SUCCESS);
73 return new root_buffer(ctx, flags, size, host_ptr);
74
75 } catch (error &e) {
76 ret_error(r_errcode, e);
77 return NULL;
78 }
79
80 CLOVER_API cl_mem
81 clCreateSubBuffer(cl_mem d_mem, cl_mem_flags d_flags,
82 cl_buffer_create_type op,
83 const void *op_info, cl_int *r_errcode) try {
84 auto &parent = obj<root_buffer>(d_mem);
85 const cl_mem_flags flags = d_flags |
86 (d_flags & dev_access_flags ? 0 : parent.flags() & dev_access_flags) |
87 (d_flags & host_access_flags ? 0 : parent.flags() & host_access_flags) |
88 (parent.flags() & host_ptr_flags);
89
90 validate_flags(d_flags, dev_access_flags | host_access_flags);
91
92 if (~flags & parent.flags() &
93 ((dev_access_flags & ~CL_MEM_READ_WRITE) | host_access_flags))
94 throw error(CL_INVALID_VALUE);
95
96 if (op == CL_BUFFER_CREATE_TYPE_REGION) {
97 auto reg = reinterpret_cast<const cl_buffer_region *>(op_info);
98
99 if (!reg ||
100 reg->origin > parent.size() ||
101 reg->origin + reg->size > parent.size())
102 throw error(CL_INVALID_VALUE);
103
104 if (!reg->size)
105 throw error(CL_INVALID_BUFFER_SIZE);
106
107 ret_error(r_errcode, CL_SUCCESS);
108 return new sub_buffer(parent, flags, reg->origin, reg->size);
109
110 } else {
111 throw error(CL_INVALID_VALUE);
112 }
113
114 } catch (error &e) {
115 ret_error(r_errcode, e);
116 return NULL;
117 }
118
119 CLOVER_API cl_mem
120 clCreateImage2D(cl_context d_ctx, cl_mem_flags d_flags,
121 const cl_image_format *format,
122 size_t width, size_t height, size_t row_pitch,
123 void *host_ptr, cl_int *r_errcode) try {
124 const cl_mem_flags flags = d_flags |
125 (d_flags & dev_access_flags ? 0 : CL_MEM_READ_WRITE);
126 auto &ctx = obj(d_ctx);
127
128 validate_flags(d_flags, all_mem_flags);
129
130 if (!any_of(std::mem_fn(&device::image_support), ctx.devices()))
131 throw error(CL_INVALID_OPERATION);
132
133 if (!format)
134 throw error(CL_INVALID_IMAGE_FORMAT_DESCRIPTOR);
135
136 if (width < 1 || height < 1)
137 throw error(CL_INVALID_IMAGE_SIZE);
138
139 if (bool(host_ptr) != bool(flags & (CL_MEM_USE_HOST_PTR |
140 CL_MEM_COPY_HOST_PTR)))
141 throw error(CL_INVALID_HOST_PTR);
142
143 if (!supported_formats(ctx, CL_MEM_OBJECT_IMAGE2D).count(*format))
144 throw error(CL_IMAGE_FORMAT_NOT_SUPPORTED);
145
146 ret_error(r_errcode, CL_SUCCESS);
147 return new image2d(ctx, flags, format, width, height,
148 row_pitch, host_ptr);
149
150 } catch (error &e) {
151 ret_error(r_errcode, e);
152 return NULL;
153 }
154
155 CLOVER_API cl_mem
156 clCreateImage3D(cl_context d_ctx, cl_mem_flags d_flags,
157 const cl_image_format *format,
158 size_t width, size_t height, size_t depth,
159 size_t row_pitch, size_t slice_pitch,
160 void *host_ptr, cl_int *r_errcode) try {
161 const cl_mem_flags flags = d_flags |
162 (d_flags & dev_access_flags ? 0 : CL_MEM_READ_WRITE);
163 auto &ctx = obj(d_ctx);
164
165 validate_flags(d_flags, all_mem_flags);
166
167 if (!any_of(std::mem_fn(&device::image_support), ctx.devices()))
168 throw error(CL_INVALID_OPERATION);
169
170 if (!format)
171 throw error(CL_INVALID_IMAGE_FORMAT_DESCRIPTOR);
172
173 if (width < 1 || height < 1 || depth < 2)
174 throw error(CL_INVALID_IMAGE_SIZE);
175
176 if (bool(host_ptr) != bool(flags & (CL_MEM_USE_HOST_PTR |
177 CL_MEM_COPY_HOST_PTR)))
178 throw error(CL_INVALID_HOST_PTR);
179
180 if (!supported_formats(ctx, CL_MEM_OBJECT_IMAGE3D).count(*format))
181 throw error(CL_IMAGE_FORMAT_NOT_SUPPORTED);
182
183 ret_error(r_errcode, CL_SUCCESS);
184 return new image3d(ctx, flags, format, width, height, depth,
185 row_pitch, slice_pitch, host_ptr);
186
187 } catch (error &e) {
188 ret_error(r_errcode, e);
189 return NULL;
190 }
191
192 CLOVER_API cl_int
193 clGetSupportedImageFormats(cl_context d_ctx, cl_mem_flags flags,
194 cl_mem_object_type type, cl_uint count,
195 cl_image_format *r_buf, cl_uint *r_count) try {
196 auto &ctx = obj(d_ctx);
197 auto formats = supported_formats(ctx, type);
198
199 validate_flags(flags, all_mem_flags);
200
201 if (r_buf && !r_count)
202 throw error(CL_INVALID_VALUE);
203
204 if (r_buf)
205 std::copy_n(formats.begin(),
206 std::min((cl_uint)formats.size(), count),
207 r_buf);
208
209 if (r_count)
210 *r_count = formats.size();
211
212 return CL_SUCCESS;
213
214 } catch (error &e) {
215 return e.get();
216 }
217
218 CLOVER_API cl_int
219 clGetMemObjectInfo(cl_mem d_mem, cl_mem_info param,
220 size_t size, void *r_buf, size_t *r_size) try {
221 property_buffer buf { r_buf, size, r_size };
222 auto &mem = obj(d_mem);
223
224 switch (param) {
225 case CL_MEM_TYPE:
226 buf.as_scalar<cl_mem_object_type>() = mem.type();
227 break;
228
229 case CL_MEM_FLAGS:
230 buf.as_scalar<cl_mem_flags>() = mem.flags();
231 break;
232
233 case CL_MEM_SIZE:
234 buf.as_scalar<size_t>() = mem.size();
235 break;
236
237 case CL_MEM_HOST_PTR:
238 buf.as_scalar<void *>() = mem.host_ptr();
239 break;
240
241 case CL_MEM_MAP_COUNT:
242 buf.as_scalar<cl_uint>() = 0;
243 break;
244
245 case CL_MEM_REFERENCE_COUNT:
246 buf.as_scalar<cl_uint>() = mem.ref_count();
247 break;
248
249 case CL_MEM_CONTEXT:
250 buf.as_scalar<cl_context>() = desc(mem.context());
251 break;
252
253 case CL_MEM_ASSOCIATED_MEMOBJECT: {
254 sub_buffer *sub = dynamic_cast<sub_buffer *>(&mem);
255 buf.as_scalar<cl_mem>() = (sub ? desc(sub->parent()) : NULL);
256 break;
257 }
258 case CL_MEM_OFFSET: {
259 sub_buffer *sub = dynamic_cast<sub_buffer *>(&mem);
260 buf.as_scalar<size_t>() = (sub ? sub->offset() : 0);
261 break;
262 }
263 default:
264 throw error(CL_INVALID_VALUE);
265 }
266
267 return CL_SUCCESS;
268
269 } catch (error &e) {
270 return e.get();
271 }
272
273 CLOVER_API cl_int
274 clGetImageInfo(cl_mem d_mem, cl_image_info param,
275 size_t size, void *r_buf, size_t *r_size) try {
276 property_buffer buf { r_buf, size, r_size };
277 auto &img = obj<image>(d_mem);
278
279 switch (param) {
280 case CL_IMAGE_FORMAT:
281 buf.as_scalar<cl_image_format>() = img.format();
282 break;
283
284 case CL_IMAGE_ELEMENT_SIZE:
285 buf.as_scalar<size_t>() = 0;
286 break;
287
288 case CL_IMAGE_ROW_PITCH:
289 buf.as_scalar<size_t>() = img.row_pitch();
290 break;
291
292 case CL_IMAGE_SLICE_PITCH:
293 buf.as_scalar<size_t>() = img.slice_pitch();
294 break;
295
296 case CL_IMAGE_WIDTH:
297 buf.as_scalar<size_t>() = img.width();
298 break;
299
300 case CL_IMAGE_HEIGHT:
301 buf.as_scalar<size_t>() = img.height();
302 break;
303
304 case CL_IMAGE_DEPTH:
305 buf.as_scalar<size_t>() = img.depth();
306 break;
307
308 default:
309 throw error(CL_INVALID_VALUE);
310 }
311
312 return CL_SUCCESS;
313
314 } catch (error &e) {
315 return e.get();
316 }
317
318 CLOVER_API cl_int
319 clRetainMemObject(cl_mem d_mem) try {
320 obj(d_mem).retain();
321 return CL_SUCCESS;
322
323 } catch (error &e) {
324 return e.get();
325 }
326
327 CLOVER_API cl_int
328 clReleaseMemObject(cl_mem d_mem) try {
329 if (obj(d_mem).release())
330 delete pobj(d_mem);
331
332 return CL_SUCCESS;
333
334 } catch (error &e) {
335 return e.get();
336 }
337
338 CLOVER_API cl_int
339 clSetMemObjectDestructorCallback(cl_mem d_mem,
340 void (CL_CALLBACK *pfn_notify)(cl_mem, void *),
341 void *user_data) try {
342 auto &mem = obj(d_mem);
343
344 if (!pfn_notify)
345 return CL_INVALID_VALUE;
346
347 mem.destroy_notify([=]{ pfn_notify(d_mem, user_data); });
348
349 return CL_SUCCESS;
350
351 } catch (error &e) {
352 return e.get();
353 }
354
355 CLOVER_API cl_mem
356 clCreateImage(cl_context d_ctx, cl_mem_flags flags,
357 const cl_image_format *format,
358 const cl_image_desc *image_desc,
359 void *host_ptr, cl_int *r_errcode) {
360 CLOVER_NOT_SUPPORTED_UNTIL("1.2");
361 ret_error(r_errcode, CL_INVALID_OPERATION);
362 return NULL;
363 }
364
365 CLOVER_API cl_int
366 clEnqueueFillBuffer(cl_command_queue command_queue, cl_mem buffer,
367 const void *pattern, size_t pattern_size,
368 size_t offset, size_t size,
369 cl_uint num_events_in_wait_list,
370 const cl_event *event_wait_list,
371 cl_event *event) {
372 CLOVER_NOT_SUPPORTED_UNTIL("1.2");
373 return CL_INVALID_VALUE;
374 }
375
376 CLOVER_API cl_int
377 clEnqueueFillImage(cl_command_queue command_queue, cl_mem image,
378 const void *fill_color,
379 const size_t *origin, const size_t *region,
380 cl_uint num_events_in_wait_list,
381 const cl_event *event_wait_list,
382 cl_event *event) {
383 CLOVER_NOT_SUPPORTED_UNTIL("1.2");
384 return CL_INVALID_VALUE;
385 }