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/program.hpp"
26 using namespace clover
;
29 clCreateProgramWithSource(cl_context d_ctx
, cl_uint count
,
30 const char **strings
, const size_t *lengths
,
31 cl_int
*r_errcode
) try {
32 auto &ctx
= obj(d_ctx
);
35 if (!count
|| !strings
||
36 any_of(is_zero(), range(strings
, count
)))
37 throw error(CL_INVALID_VALUE
);
39 // Concatenate all the provided fragments together
40 for (unsigned i
= 0; i
< count
; ++i
)
41 source
+= (lengths
&& lengths
[i
] ?
42 std::string(strings
[i
], strings
[i
] + lengths
[i
]) :
43 std::string(strings
[i
]));
45 // ...and create a program object for them.
46 ret_error(r_errcode
, CL_SUCCESS
);
47 return new program(ctx
, source
);
50 ret_error(r_errcode
, e
);
55 clCreateProgramWithBinary(cl_context d_ctx
, cl_uint n
,
56 const cl_device_id
*d_devs
,
57 const size_t *lengths
,
58 const unsigned char **binaries
,
59 cl_int
*r_status
, cl_int
*r_errcode
) try {
60 auto &ctx
= obj(d_ctx
);
61 auto devs
= objs(d_devs
, n
);
63 if (!lengths
|| !binaries
)
64 throw error(CL_INVALID_VALUE
);
66 if (any_of([&](const device
&dev
) {
67 return !count(dev
, ctx
.devices());
69 throw error(CL_INVALID_DEVICE
);
71 // Deserialize the provided binaries,
72 std::vector
<std::pair
<cl_int
, module
>> result
= map(
73 [](const unsigned char *p
, size_t l
) -> std::pair
<cl_int
, module
> {
75 return { CL_INVALID_VALUE
, {} };
78 compat::istream::buffer_t
bin(p
, l
);
79 compat::istream
s(bin
);
81 return { CL_SUCCESS
, module::deserialize(s
) };
83 } catch (compat::istream::error
&e
) {
84 return { CL_INVALID_BINARY
, {} };
90 // update the status array,
92 copy(map(keys(), result
), r_status
);
94 if (any_of(key_equals(CL_INVALID_VALUE
), result
))
95 throw error(CL_INVALID_VALUE
);
97 if (any_of(key_equals(CL_INVALID_BINARY
), result
))
98 throw error(CL_INVALID_BINARY
);
100 // initialize a program object with them.
101 ret_error(r_errcode
, CL_SUCCESS
);
102 return new program(ctx
, devs
, map(values(), result
));
105 ret_error(r_errcode
, e
);
109 CLOVER_API cl_program
110 clCreateProgramWithBuiltInKernels(cl_context d_ctx
, cl_uint n
,
111 const cl_device_id
*d_devs
,
112 const char *kernel_names
,
113 cl_int
*r_errcode
) try {
114 auto &ctx
= obj(d_ctx
);
115 auto devs
= objs(d_devs
, n
);
117 if (any_of([&](const device
&dev
) {
118 return !count(dev
, ctx
.devices());
120 throw error(CL_INVALID_DEVICE
);
122 // No currently supported built-in kernels.
123 throw error(CL_INVALID_VALUE
);
126 ret_error(r_errcode
, e
);
132 clRetainProgram(cl_program d_prog
) try {
133 obj(d_prog
).retain();
141 clReleaseProgram(cl_program d_prog
) try {
142 if (obj(d_prog
).release())
152 clBuildProgram(cl_program d_prog
, cl_uint num_devs
,
153 const cl_device_id
*d_devs
, const char *p_opts
,
154 void (*pfn_notify
)(cl_program
, void *),
156 cl_int ret
= clCompileProgram(d_prog
, num_devs
, d_devs
, p_opts
,
157 0, NULL
, NULL
, pfn_notify
, user_data
);
159 return (ret
== CL_COMPILE_PROGRAM_FAILURE
?
160 CL_BUILD_PROGRAM_FAILURE
: ret
);
164 clCompileProgram(cl_program d_prog
, cl_uint num_devs
,
165 const cl_device_id
*d_devs
, const char *p_opts
,
166 cl_uint num_headers
, const cl_program
*d_header_progs
,
167 const char **header_names
,
168 void (*pfn_notify
)(cl_program
, void *),
169 void *user_data
) try {
170 auto &prog
= obj(d_prog
);
171 auto devs
= (d_devs
? objs(d_devs
, num_devs
) :
172 ref_vector
<device
>(prog
.context().devices()));
173 auto opts
= (p_opts
? p_opts
: "");
176 if (bool(num_devs
) != bool(d_devs
) ||
177 (!pfn_notify
&& user_data
) ||
178 bool(num_headers
) != bool(header_names
))
179 throw error(CL_INVALID_VALUE
);
181 if (any_of([&](const device
&dev
) {
182 return !count(dev
, prog
.context().devices());
184 throw error(CL_INVALID_DEVICE
);
186 if (prog
.kernel_ref_count() ||
188 throw error(CL_INVALID_OPERATION
);
191 for_each([&](const char *name
, const program
&header
) {
192 if (!header
.has_source
)
193 throw error(CL_INVALID_OPERATION
);
195 if (!any_of(key_equals(name
), headers
))
196 headers
.push_back(compat::pair
<compat::string
, compat::string
>(
197 name
, header
.source()));
199 range(header_names
, num_headers
),
200 objs
<allow_empty_tag
>(d_header_progs
, num_headers
));
202 prog
.build(devs
, opts
, headers
);
215 clUnloadPlatformCompiler(cl_platform_id d_platform
) {
220 clGetProgramInfo(cl_program d_prog
, cl_program_info param
,
221 size_t size
, void *r_buf
, size_t *r_size
) try {
222 property_buffer buf
{ r_buf
, size
, r_size
};
223 auto &prog
= obj(d_prog
);
226 case CL_PROGRAM_REFERENCE_COUNT
:
227 buf
.as_scalar
<cl_uint
>() = prog
.ref_count();
230 case CL_PROGRAM_CONTEXT
:
231 buf
.as_scalar
<cl_context
>() = desc(prog
.context());
234 case CL_PROGRAM_NUM_DEVICES
:
235 buf
.as_scalar
<cl_uint
>() = (prog
.devices().size() ?
236 prog
.devices().size() :
237 prog
.context().devices().size());
240 case CL_PROGRAM_DEVICES
:
241 buf
.as_vector
<cl_device_id
>() = (prog
.devices().size() ?
242 descs(prog
.devices()) :
243 descs(prog
.context().devices()));
246 case CL_PROGRAM_SOURCE
:
247 buf
.as_string() = prog
.source();
250 case CL_PROGRAM_BINARY_SIZES
:
251 buf
.as_vector
<size_t>() = map([&](const device
&dev
) {
252 return prog
.binary(dev
).size();
257 case CL_PROGRAM_BINARIES
:
258 buf
.as_matrix
<unsigned char>() = map([&](const device
&dev
) {
259 compat::ostream::buffer_t bin
;
260 compat::ostream
s(bin
);
261 prog
.binary(dev
).serialize(s
);
267 case CL_PROGRAM_NUM_KERNELS
:
268 buf
.as_scalar
<cl_uint
>() = prog
.symbols().size();
271 case CL_PROGRAM_KERNEL_NAMES
:
272 buf
.as_string() = fold([](const std::string
&a
, const module::symbol
&s
) {
273 return ((a
.empty() ? "" : a
+ ";") +
274 std::string(s
.name
.begin(), s
.name
.size()));
275 }, std::string(), prog
.symbols());
279 throw error(CL_INVALID_VALUE
);
289 clGetProgramBuildInfo(cl_program d_prog
, cl_device_id d_dev
,
290 cl_program_build_info param
,
291 size_t size
, void *r_buf
, size_t *r_size
) try {
292 property_buffer buf
{ r_buf
, size
, r_size
};
293 auto &prog
= obj(d_prog
);
294 auto &dev
= obj(d_dev
);
296 if (!count(dev
, prog
.context().devices()))
297 return CL_INVALID_DEVICE
;
300 case CL_PROGRAM_BUILD_STATUS
:
301 buf
.as_scalar
<cl_build_status
>() = prog
.build_status(dev
);
304 case CL_PROGRAM_BUILD_OPTIONS
:
305 buf
.as_string() = prog
.build_opts(dev
);
308 case CL_PROGRAM_BUILD_LOG
:
309 buf
.as_string() = prog
.build_log(dev
);
313 throw error(CL_INVALID_VALUE
);