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 "api/util.hpp"
24 #include "core/memory.hpp"
25 #include "core/format.hpp"
27 using namespace clover
;
30 clCreateBuffer(cl_context ctx
, cl_mem_flags flags
, size_t size
,
31 void *host_ptr
, cl_int
*errcode_ret
) try {
33 throw error(CL_INVALID_CONTEXT
);
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 throw error(CL_INVALID_BUFFER_SIZE
);
42 if (flags
& ~(CL_MEM_READ_WRITE
| CL_MEM_WRITE_ONLY
| CL_MEM_READ_ONLY
|
43 CL_MEM_USE_HOST_PTR
| CL_MEM_ALLOC_HOST_PTR
|
44 CL_MEM_COPY_HOST_PTR
))
45 throw error(CL_INVALID_VALUE
);
47 ret_error(errcode_ret
, CL_SUCCESS
);
48 return new root_buffer(obj(ctx
), flags
, size
, host_ptr
);
51 ret_error(errcode_ret
, e
);
56 clCreateSubBuffer(cl_mem obj
, cl_mem_flags flags
, cl_buffer_create_type op
,
57 const void *op_info
, cl_int
*errcode_ret
) try {
58 root_buffer
*parent
= dynamic_cast<root_buffer
*>(obj
);
61 throw error(CL_INVALID_MEM_OBJECT
);
63 if ((flags
& (CL_MEM_USE_HOST_PTR
|
64 CL_MEM_ALLOC_HOST_PTR
|
65 CL_MEM_COPY_HOST_PTR
)) ||
66 (~flags
& parent
->flags() & (CL_MEM_READ_ONLY
|
68 throw error(CL_INVALID_VALUE
);
70 if (op
== CL_BUFFER_CREATE_TYPE_REGION
) {
71 const cl_buffer_region
*reg
= (const cl_buffer_region
*)op_info
;
74 reg
->origin
> parent
->size() ||
75 reg
->origin
+ reg
->size
> parent
->size())
76 throw error(CL_INVALID_VALUE
);
79 throw error(CL_INVALID_BUFFER_SIZE
);
81 ret_error(errcode_ret
, CL_SUCCESS
);
82 return new sub_buffer(*parent
, flags
, reg
->origin
, reg
->size
);
85 throw error(CL_INVALID_VALUE
);
89 ret_error(errcode_ret
, e
);
94 clCreateImage2D(cl_context d_ctx
, cl_mem_flags flags
,
95 const cl_image_format
*format
,
96 size_t width
, size_t height
, size_t row_pitch
,
97 void *host_ptr
, cl_int
*errcode_ret
) try {
98 auto &ctx
= obj(d_ctx
);
100 if (flags
& ~(CL_MEM_READ_WRITE
| CL_MEM_WRITE_ONLY
| CL_MEM_READ_ONLY
|
101 CL_MEM_USE_HOST_PTR
| CL_MEM_ALLOC_HOST_PTR
|
102 CL_MEM_COPY_HOST_PTR
))
103 throw error(CL_INVALID_VALUE
);
106 throw error(CL_INVALID_IMAGE_FORMAT_DESCRIPTOR
);
108 if (width
< 1 || height
< 1)
109 throw error(CL_INVALID_IMAGE_SIZE
);
111 if (bool(host_ptr
) != bool(flags
& (CL_MEM_USE_HOST_PTR
|
112 CL_MEM_COPY_HOST_PTR
)))
113 throw error(CL_INVALID_HOST_PTR
);
115 if (!supported_formats(ctx
, CL_MEM_OBJECT_IMAGE2D
).count(*format
))
116 throw error(CL_IMAGE_FORMAT_NOT_SUPPORTED
);
118 ret_error(errcode_ret
, CL_SUCCESS
);
119 return new image2d(ctx
, flags
, format
, width
, height
,
120 row_pitch
, host_ptr
);
123 ret_error(errcode_ret
, e
);
128 clCreateImage3D(cl_context d_ctx
, cl_mem_flags flags
,
129 const cl_image_format
*format
,
130 size_t width
, size_t height
, size_t depth
,
131 size_t row_pitch
, size_t slice_pitch
,
132 void *host_ptr
, cl_int
*errcode_ret
) try {
133 auto &ctx
= obj(d_ctx
);
135 if (flags
& ~(CL_MEM_READ_WRITE
| CL_MEM_WRITE_ONLY
| CL_MEM_READ_ONLY
|
136 CL_MEM_USE_HOST_PTR
| CL_MEM_ALLOC_HOST_PTR
|
137 CL_MEM_COPY_HOST_PTR
))
138 throw error(CL_INVALID_VALUE
);
141 throw error(CL_INVALID_IMAGE_FORMAT_DESCRIPTOR
);
143 if (width
< 1 || height
< 1 || depth
< 2)
144 throw error(CL_INVALID_IMAGE_SIZE
);
146 if (bool(host_ptr
) != bool(flags
& (CL_MEM_USE_HOST_PTR
|
147 CL_MEM_COPY_HOST_PTR
)))
148 throw error(CL_INVALID_HOST_PTR
);
150 if (!supported_formats(ctx
, CL_MEM_OBJECT_IMAGE3D
).count(*format
))
151 throw error(CL_IMAGE_FORMAT_NOT_SUPPORTED
);
153 ret_error(errcode_ret
, CL_SUCCESS
);
154 return new image3d(ctx
, flags
, format
, width
, height
, depth
,
155 row_pitch
, slice_pitch
, host_ptr
);
158 ret_error(errcode_ret
, e
);
163 clGetSupportedImageFormats(cl_context d_ctx
, cl_mem_flags flags
,
164 cl_mem_object_type type
, cl_uint count
,
165 cl_image_format
*buf
, cl_uint
*count_ret
) try {
166 auto &ctx
= obj(d_ctx
);
168 if (flags
& ~(CL_MEM_READ_WRITE
| CL_MEM_WRITE_ONLY
| CL_MEM_READ_ONLY
|
169 CL_MEM_USE_HOST_PTR
| CL_MEM_ALLOC_HOST_PTR
|
170 CL_MEM_COPY_HOST_PTR
))
171 throw error(CL_INVALID_VALUE
);
174 throw error(CL_INVALID_VALUE
);
176 auto formats
= supported_formats(ctx
, type
);
179 std::copy_n(formats
.begin(), std::min((cl_uint
)formats
.size(), count
),
182 *count_ret
= formats
.size();
191 clGetMemObjectInfo(cl_mem obj
, cl_mem_info param
,
192 size_t size
, void *r_buf
, size_t *r_size
) try {
193 property_buffer buf
{ r_buf
, size
, r_size
};
196 return CL_INVALID_MEM_OBJECT
;
200 buf
.as_scalar
<cl_mem_object_type
>() = obj
->type();
204 buf
.as_scalar
<cl_mem_flags
>() = obj
->flags();
208 buf
.as_scalar
<size_t>() = obj
->size();
211 case CL_MEM_HOST_PTR
:
212 buf
.as_scalar
<void *>() = obj
->host_ptr();
215 case CL_MEM_MAP_COUNT
:
216 buf
.as_scalar
<cl_uint
>() = 0;
219 case CL_MEM_REFERENCE_COUNT
:
220 buf
.as_scalar
<cl_uint
>() = obj
->ref_count();
224 buf
.as_scalar
<cl_context
>() = &obj
->ctx
;
227 case CL_MEM_ASSOCIATED_MEMOBJECT
: {
228 sub_buffer
*sub
= dynamic_cast<sub_buffer
*>(obj
);
229 buf
.as_scalar
<cl_mem
>() = (sub
? &sub
->parent
: NULL
);
232 case CL_MEM_OFFSET
: {
233 sub_buffer
*sub
= dynamic_cast<sub_buffer
*>(obj
);
234 buf
.as_scalar
<size_t>() = (sub
? sub
->offset() : 0);
238 throw error(CL_INVALID_VALUE
);
248 clGetImageInfo(cl_mem obj
, cl_image_info param
,
249 size_t size
, void *r_buf
, size_t *r_size
) try {
250 property_buffer buf
{ r_buf
, size
, r_size
};
251 image
*img
= dynamic_cast<image
*>(obj
);
254 return CL_INVALID_MEM_OBJECT
;
257 case CL_IMAGE_FORMAT
:
258 buf
.as_scalar
<cl_image_format
>() = img
->format();
261 case CL_IMAGE_ELEMENT_SIZE
:
262 buf
.as_scalar
<size_t>() = 0;
265 case CL_IMAGE_ROW_PITCH
:
266 buf
.as_scalar
<size_t>() = img
->row_pitch();
269 case CL_IMAGE_SLICE_PITCH
:
270 buf
.as_scalar
<size_t>() = img
->slice_pitch();
274 buf
.as_scalar
<size_t>() = img
->width();
277 case CL_IMAGE_HEIGHT
:
278 buf
.as_scalar
<size_t>() = img
->height();
282 buf
.as_scalar
<size_t>() = img
->depth();
286 throw error(CL_INVALID_VALUE
);
296 clRetainMemObject(cl_mem obj
) {
298 return CL_INVALID_MEM_OBJECT
;
305 clReleaseMemObject(cl_mem obj
) {
307 return CL_INVALID_MEM_OBJECT
;
316 clSetMemObjectDestructorCallback(cl_mem obj
,
317 void (CL_CALLBACK
*pfn_notify
)(cl_mem
, void *),
320 return CL_INVALID_MEM_OBJECT
;
323 return CL_INVALID_VALUE
;
325 obj
->destroy_notify([=]{ pfn_notify(obj
, user_data
); });