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
.devices())
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 (!any_of(std::mem_fn(&device::image_support
), ctx
.devices()))
110 throw error(CL_INVALID_OPERATION
);
112 if (flags
& ~(CL_MEM_READ_WRITE
| CL_MEM_WRITE_ONLY
| CL_MEM_READ_ONLY
|
113 CL_MEM_USE_HOST_PTR
| CL_MEM_ALLOC_HOST_PTR
|
114 CL_MEM_COPY_HOST_PTR
))
115 throw error(CL_INVALID_VALUE
);
118 throw error(CL_INVALID_IMAGE_FORMAT_DESCRIPTOR
);
120 if (width
< 1 || height
< 1)
121 throw error(CL_INVALID_IMAGE_SIZE
);
123 if (bool(host_ptr
) != bool(flags
& (CL_MEM_USE_HOST_PTR
|
124 CL_MEM_COPY_HOST_PTR
)))
125 throw error(CL_INVALID_HOST_PTR
);
127 if (!supported_formats(ctx
, CL_MEM_OBJECT_IMAGE2D
).count(*format
))
128 throw error(CL_IMAGE_FORMAT_NOT_SUPPORTED
);
130 ret_error(r_errcode
, CL_SUCCESS
);
131 return new image2d(ctx
, flags
, format
, width
, height
,
132 row_pitch
, host_ptr
);
135 ret_error(r_errcode
, e
);
140 clCreateImage3D(cl_context d_ctx
, cl_mem_flags flags
,
141 const cl_image_format
*format
,
142 size_t width
, size_t height
, size_t depth
,
143 size_t row_pitch
, size_t slice_pitch
,
144 void *host_ptr
, cl_int
*r_errcode
) try {
145 auto &ctx
= obj(d_ctx
);
147 if (!any_of(std::mem_fn(&device::image_support
), ctx
.devices()))
148 throw error(CL_INVALID_OPERATION
);
150 if (flags
& ~(CL_MEM_READ_WRITE
| CL_MEM_WRITE_ONLY
| CL_MEM_READ_ONLY
|
151 CL_MEM_USE_HOST_PTR
| CL_MEM_ALLOC_HOST_PTR
|
152 CL_MEM_COPY_HOST_PTR
))
153 throw error(CL_INVALID_VALUE
);
156 throw error(CL_INVALID_IMAGE_FORMAT_DESCRIPTOR
);
158 if (width
< 1 || height
< 1 || depth
< 2)
159 throw error(CL_INVALID_IMAGE_SIZE
);
161 if (bool(host_ptr
) != bool(flags
& (CL_MEM_USE_HOST_PTR
|
162 CL_MEM_COPY_HOST_PTR
)))
163 throw error(CL_INVALID_HOST_PTR
);
165 if (!supported_formats(ctx
, CL_MEM_OBJECT_IMAGE3D
).count(*format
))
166 throw error(CL_IMAGE_FORMAT_NOT_SUPPORTED
);
168 ret_error(r_errcode
, CL_SUCCESS
);
169 return new image3d(ctx
, flags
, format
, width
, height
, depth
,
170 row_pitch
, slice_pitch
, host_ptr
);
173 ret_error(r_errcode
, e
);
178 clGetSupportedImageFormats(cl_context d_ctx
, cl_mem_flags flags
,
179 cl_mem_object_type type
, cl_uint count
,
180 cl_image_format
*r_buf
, cl_uint
*r_count
) try {
181 auto &ctx
= obj(d_ctx
);
183 if (flags
& ~(CL_MEM_READ_WRITE
| CL_MEM_WRITE_ONLY
| CL_MEM_READ_ONLY
|
184 CL_MEM_USE_HOST_PTR
| CL_MEM_ALLOC_HOST_PTR
|
185 CL_MEM_COPY_HOST_PTR
))
186 throw error(CL_INVALID_VALUE
);
188 if (r_buf
&& !r_count
)
189 throw error(CL_INVALID_VALUE
);
191 auto formats
= supported_formats(ctx
, type
);
194 std::copy_n(formats
.begin(),
195 std::min((cl_uint
)formats
.size(), count
),
199 *r_count
= formats
.size();
208 clGetMemObjectInfo(cl_mem d_mem
, cl_mem_info param
,
209 size_t size
, void *r_buf
, size_t *r_size
) try {
210 property_buffer buf
{ r_buf
, size
, r_size
};
211 auto &mem
= obj(d_mem
);
215 buf
.as_scalar
<cl_mem_object_type
>() = mem
.type();
219 buf
.as_scalar
<cl_mem_flags
>() = mem
.flags();
223 buf
.as_scalar
<size_t>() = mem
.size();
226 case CL_MEM_HOST_PTR
:
227 buf
.as_scalar
<void *>() = mem
.host_ptr();
230 case CL_MEM_MAP_COUNT
:
231 buf
.as_scalar
<cl_uint
>() = 0;
234 case CL_MEM_REFERENCE_COUNT
:
235 buf
.as_scalar
<cl_uint
>() = mem
.ref_count();
239 buf
.as_scalar
<cl_context
>() = desc(mem
.context());
242 case CL_MEM_ASSOCIATED_MEMOBJECT
: {
243 sub_buffer
*sub
= dynamic_cast<sub_buffer
*>(&mem
);
244 buf
.as_scalar
<cl_mem
>() = (sub
? desc(sub
->parent()) : NULL
);
247 case CL_MEM_OFFSET
: {
248 sub_buffer
*sub
= dynamic_cast<sub_buffer
*>(&mem
);
249 buf
.as_scalar
<size_t>() = (sub
? sub
->offset() : 0);
253 throw error(CL_INVALID_VALUE
);
263 clGetImageInfo(cl_mem d_mem
, cl_image_info param
,
264 size_t size
, void *r_buf
, size_t *r_size
) try {
265 property_buffer buf
{ r_buf
, size
, r_size
};
266 auto &img
= obj
<image
>(d_mem
);
269 case CL_IMAGE_FORMAT
:
270 buf
.as_scalar
<cl_image_format
>() = img
.format();
273 case CL_IMAGE_ELEMENT_SIZE
:
274 buf
.as_scalar
<size_t>() = 0;
277 case CL_IMAGE_ROW_PITCH
:
278 buf
.as_scalar
<size_t>() = img
.row_pitch();
281 case CL_IMAGE_SLICE_PITCH
:
282 buf
.as_scalar
<size_t>() = img
.slice_pitch();
286 buf
.as_scalar
<size_t>() = img
.width();
289 case CL_IMAGE_HEIGHT
:
290 buf
.as_scalar
<size_t>() = img
.height();
294 buf
.as_scalar
<size_t>() = img
.depth();
298 throw error(CL_INVALID_VALUE
);
308 clRetainMemObject(cl_mem d_mem
) try {
317 clReleaseMemObject(cl_mem d_mem
) try {
318 if (obj(d_mem
).release())
328 clSetMemObjectDestructorCallback(cl_mem d_mem
,
329 void (CL_CALLBACK
*pfn_notify
)(cl_mem
, void *),
330 void *user_data
) try {
331 auto &mem
= obj(d_mem
);
334 return CL_INVALID_VALUE
;
336 mem
.destroy_notify([=]{ pfn_notify(d_mem
, user_data
); });
345 clCreateImage(cl_context d_ctx
, cl_mem_flags flags
,
346 const cl_image_format
*format
,
347 const cl_image_desc
*image_desc
,
348 void *host_ptr
, cl_int
*r_errcode
) {
349 // This function was added in OpenCL 1.2
350 std::cerr
<< "CL user error: clCreateImage() not supported by OpenCL 1.1." <<
352 ret_error(r_errcode
, CL_INVALID_OPERATION
);