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