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(*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 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 {
99 throw error(CL_INVALID_CONTEXT
);
101 if (flags
& ~(CL_MEM_READ_WRITE
| CL_MEM_WRITE_ONLY
| CL_MEM_READ_ONLY
|
102 CL_MEM_USE_HOST_PTR
| CL_MEM_ALLOC_HOST_PTR
|
103 CL_MEM_COPY_HOST_PTR
))
104 throw error(CL_INVALID_VALUE
);
107 throw error(CL_INVALID_IMAGE_FORMAT_DESCRIPTOR
);
109 if (width
< 1 || height
< 1)
110 throw error(CL_INVALID_IMAGE_SIZE
);
112 if (bool(host_ptr
) != bool(flags
& (CL_MEM_USE_HOST_PTR
|
113 CL_MEM_COPY_HOST_PTR
)))
114 throw error(CL_INVALID_HOST_PTR
);
116 if (!supported_formats(ctx
, CL_MEM_OBJECT_IMAGE2D
).count(*format
))
117 throw error(CL_IMAGE_FORMAT_NOT_SUPPORTED
);
119 ret_error(errcode_ret
, CL_SUCCESS
);
120 return new image2d(*ctx
, flags
, format
, width
, height
,
121 row_pitch
, host_ptr
);
124 ret_error(errcode_ret
, e
);
129 clCreateImage3D(cl_context ctx
, cl_mem_flags flags
,
130 const cl_image_format
*format
,
131 size_t width
, size_t height
, size_t depth
,
132 size_t row_pitch
, size_t slice_pitch
,
133 void *host_ptr
, cl_int
*errcode_ret
) try {
135 throw error(CL_INVALID_CONTEXT
);
137 if (flags
& ~(CL_MEM_READ_WRITE
| CL_MEM_WRITE_ONLY
| CL_MEM_READ_ONLY
|
138 CL_MEM_USE_HOST_PTR
| CL_MEM_ALLOC_HOST_PTR
|
139 CL_MEM_COPY_HOST_PTR
))
140 throw error(CL_INVALID_VALUE
);
143 throw error(CL_INVALID_IMAGE_FORMAT_DESCRIPTOR
);
145 if (width
< 1 || height
< 1 || depth
< 2)
146 throw error(CL_INVALID_IMAGE_SIZE
);
148 if (bool(host_ptr
) != bool(flags
& (CL_MEM_USE_HOST_PTR
|
149 CL_MEM_COPY_HOST_PTR
)))
150 throw error(CL_INVALID_HOST_PTR
);
152 if (!supported_formats(ctx
, CL_MEM_OBJECT_IMAGE3D
).count(*format
))
153 throw error(CL_IMAGE_FORMAT_NOT_SUPPORTED
);
155 ret_error(errcode_ret
, CL_SUCCESS
);
156 return new image3d(*ctx
, flags
, format
, width
, height
, depth
,
157 row_pitch
, slice_pitch
, host_ptr
);
160 ret_error(errcode_ret
, e
);
165 clGetSupportedImageFormats(cl_context ctx
, cl_mem_flags flags
,
166 cl_mem_object_type type
, cl_uint count
,
167 cl_image_format
*buf
, cl_uint
*count_ret
) try {
169 throw error(CL_INVALID_CONTEXT
);
171 if (flags
& ~(CL_MEM_READ_WRITE
| CL_MEM_WRITE_ONLY
| CL_MEM_READ_ONLY
|
172 CL_MEM_USE_HOST_PTR
| CL_MEM_ALLOC_HOST_PTR
|
173 CL_MEM_COPY_HOST_PTR
))
174 throw error(CL_INVALID_VALUE
);
177 throw error(CL_INVALID_VALUE
);
179 auto formats
= supported_formats(ctx
, type
);
182 std::copy_n(formats
.begin(), std::min((cl_uint
)formats
.size(), count
),
185 *count_ret
= formats
.size();
194 clGetMemObjectInfo(cl_mem obj
, cl_mem_info param
,
195 size_t size
, void *r_buf
, size_t *r_size
) try {
196 property_buffer buf
{ r_buf
, size
, r_size
};
199 return CL_INVALID_MEM_OBJECT
;
203 buf
.as_scalar
<cl_mem_object_type
>() = obj
->type();
207 buf
.as_scalar
<cl_mem_flags
>() = obj
->flags();
211 buf
.as_scalar
<size_t>() = obj
->size();
214 case CL_MEM_HOST_PTR
:
215 buf
.as_scalar
<void *>() = obj
->host_ptr();
218 case CL_MEM_MAP_COUNT
:
219 buf
.as_scalar
<cl_uint
>() = 0;
222 case CL_MEM_REFERENCE_COUNT
:
223 buf
.as_scalar
<cl_uint
>() = obj
->ref_count();
227 buf
.as_scalar
<cl_context
>() = &obj
->ctx
;
230 case CL_MEM_ASSOCIATED_MEMOBJECT
: {
231 sub_buffer
*sub
= dynamic_cast<sub_buffer
*>(obj
);
232 buf
.as_scalar
<cl_mem
>() = (sub
? &sub
->parent
: NULL
);
235 case CL_MEM_OFFSET
: {
236 sub_buffer
*sub
= dynamic_cast<sub_buffer
*>(obj
);
237 buf
.as_scalar
<size_t>() = (sub
? sub
->offset() : 0);
241 throw error(CL_INVALID_VALUE
);
251 clGetImageInfo(cl_mem obj
, cl_image_info param
,
252 size_t size
, void *r_buf
, size_t *r_size
) try {
253 property_buffer buf
{ r_buf
, size
, r_size
};
254 image
*img
= dynamic_cast<image
*>(obj
);
257 return CL_INVALID_MEM_OBJECT
;
260 case CL_IMAGE_FORMAT
:
261 buf
.as_scalar
<cl_image_format
>() = img
->format();
264 case CL_IMAGE_ELEMENT_SIZE
:
265 buf
.as_scalar
<size_t>() = 0;
268 case CL_IMAGE_ROW_PITCH
:
269 buf
.as_scalar
<size_t>() = img
->row_pitch();
272 case CL_IMAGE_SLICE_PITCH
:
273 buf
.as_scalar
<size_t>() = img
->slice_pitch();
277 buf
.as_scalar
<size_t>() = img
->width();
280 case CL_IMAGE_HEIGHT
:
281 buf
.as_scalar
<size_t>() = img
->height();
285 buf
.as_scalar
<size_t>() = img
->depth();
289 throw error(CL_INVALID_VALUE
);
299 clRetainMemObject(cl_mem obj
) {
301 return CL_INVALID_MEM_OBJECT
;
308 clReleaseMemObject(cl_mem obj
) {
310 return CL_INVALID_MEM_OBJECT
;
319 clSetMemObjectDestructorCallback(cl_mem obj
,
320 void (CL_CALLBACK
*pfn_notify
)(cl_mem
, void *),
323 return CL_INVALID_MEM_OBJECT
;
326 return CL_INVALID_VALUE
;
328 obj
->destroy_notify([=]{ pfn_notify(obj
, user_data
); });