2 // Copyright 2012 Francisco Jerez
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:
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
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.
23 #include "util/u_math.h"
24 #include "api/util.hpp"
25 #include "core/memory.hpp"
26 #include "core/format.hpp"
28 using namespace clover;
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);
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);
40 size > fold(maximum(), cl_ulong(0),
41 map(std::mem_fn(&device::max_mem_alloc_size), ctx.devs())
43 throw error(CL_INVALID_BUFFER_SIZE);
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);
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);
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);
58 ret_error(r_errcode, CL_SUCCESS);
59 return new root_buffer(ctx, flags, size, host_ptr);
62 ret_error(r_errcode, e);
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);
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 |
77 throw error(CL_INVALID_VALUE);
79 if (op == CL_BUFFER_CREATE_TYPE_REGION) {
80 auto reg = reinterpret_cast<const cl_buffer_region *>(op_info);
83 reg->origin > parent.size() ||
84 reg->origin + reg->size > parent.size())
85 throw error(CL_INVALID_VALUE);
88 throw error(CL_INVALID_BUFFER_SIZE);
90 ret_error(r_errcode, CL_SUCCESS);
91 return new sub_buffer(parent, flags, reg->origin, reg->size);
94 throw error(CL_INVALID_VALUE);
98 ret_error(r_errcode, e);
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);
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);
115 throw error(CL_INVALID_IMAGE_FORMAT_DESCRIPTOR);
117 if (width < 1 || height < 1)
118 throw error(CL_INVALID_IMAGE_SIZE);
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);
124 if (!supported_formats(ctx, CL_MEM_OBJECT_IMAGE2D).count(*format))
125 throw error(CL_IMAGE_FORMAT_NOT_SUPPORTED);
127 ret_error(r_errcode, CL_SUCCESS);
128 return new image2d(ctx, flags, format, width, height,
129 row_pitch, host_ptr);
132 ret_error(r_errcode, e);
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);
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);
150 throw error(CL_INVALID_IMAGE_FORMAT_DESCRIPTOR);
152 if (width < 1 || height < 1 || depth < 2)
153 throw error(CL_INVALID_IMAGE_SIZE);
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);
159 if (!supported_formats(ctx, CL_MEM_OBJECT_IMAGE3D).count(*format))
160 throw error(CL_IMAGE_FORMAT_NOT_SUPPORTED);
162 ret_error(r_errcode, CL_SUCCESS);
163 return new image3d(ctx, flags, format, width, height, depth,
164 row_pitch, slice_pitch, host_ptr);
167 ret_error(r_errcode, e);
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);
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);
182 if (r_buf && !r_count)
183 throw error(CL_INVALID_VALUE);
185 auto formats = supported_formats(ctx, type);
188 std::copy_n(formats.begin(),
189 std::min((cl_uint)formats.size(), count),
193 *r_count = formats.size();
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);
209 buf.as_scalar<cl_mem_object_type>() = mem.type();
213 buf.as_scalar<cl_mem_flags>() = mem.flags();
217 buf.as_scalar<size_t>() = mem.size();
220 case CL_MEM_HOST_PTR:
221 buf.as_scalar<void *>() = mem.host_ptr();
224 case CL_MEM_MAP_COUNT:
225 buf.as_scalar<cl_uint>() = 0;
228 case CL_MEM_REFERENCE_COUNT:
229 buf.as_scalar<cl_uint>() = mem.ref_count();
233 buf.as_scalar<cl_context>() = desc(mem.context());
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);
241 case CL_MEM_OFFSET: {
242 sub_buffer *sub = dynamic_cast<sub_buffer *>(&mem);
243 buf.as_scalar<size_t>() = (sub ? sub->offset() : 0);
247 throw error(CL_INVALID_VALUE);
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);
263 case CL_IMAGE_FORMAT:
264 buf.as_scalar<cl_image_format>() = img.format();
267 case CL_IMAGE_ELEMENT_SIZE:
268 buf.as_scalar<size_t>() = 0;
271 case CL_IMAGE_ROW_PITCH:
272 buf.as_scalar<size_t>() = img.row_pitch();
275 case CL_IMAGE_SLICE_PITCH:
276 buf.as_scalar<size_t>() = img.slice_pitch();
280 buf.as_scalar<size_t>() = img.width();
283 case CL_IMAGE_HEIGHT:
284 buf.as_scalar<size_t>() = img.height();
288 buf.as_scalar<size_t>() = img.depth();
292 throw error(CL_INVALID_VALUE);
302 clRetainMemObject(cl_mem d_mem) try {
311 clReleaseMemObject(cl_mem d_mem) try {
312 if (obj(d_mem).release())
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);
328 return CL_INVALID_VALUE;
330 mem.destroy_notify([=]{ pfn_notify(d_mem, user_data); });