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
.devs());
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
);
110 clRetainProgram(cl_program d_prog
) try {
111 obj(d_prog
).retain();
119 clReleaseProgram(cl_program d_prog
) try {
120 if (obj(d_prog
).release())
130 clBuildProgram(cl_program d_prog
, cl_uint num_devs
,
131 const cl_device_id
*d_devs
, const char *p_opts
,
132 void (*pfn_notify
)(cl_program
, void *),
133 void *user_data
) try {
134 auto &prog
= obj(d_prog
);
135 auto devs
= (d_devs
? objs(d_devs
, num_devs
) :
136 ref_vector
<device
>(prog
.context().devs()));
137 auto opts
= (p_opts
? p_opts
: "");
139 if (bool(num_devs
) != bool(d_devs
) ||
140 (!pfn_notify
&& user_data
))
141 throw error(CL_INVALID_VALUE
);
143 if (any_of([&](const device
&dev
) {
144 return !count(dev
, prog
.context().devs());
146 throw error(CL_INVALID_DEVICE
);
148 prog
.build(devs
, opts
);
161 clGetProgramInfo(cl_program d_prog
, cl_program_info param
,
162 size_t size
, void *r_buf
, size_t *r_size
) try {
163 property_buffer buf
{ r_buf
, size
, r_size
};
164 auto &prog
= obj(d_prog
);
167 case CL_PROGRAM_REFERENCE_COUNT
:
168 buf
.as_scalar
<cl_uint
>() = prog
.ref_count();
171 case CL_PROGRAM_CONTEXT
:
172 buf
.as_scalar
<cl_context
>() = desc(prog
.context());
175 case CL_PROGRAM_NUM_DEVICES
:
176 buf
.as_scalar
<cl_uint
>() = (prog
.devices().size() ?
177 prog
.devices().size() :
178 prog
.context().devs().size());
181 case CL_PROGRAM_DEVICES
:
182 buf
.as_vector
<cl_device_id
>() = (prog
.devices().size() ?
183 descs(prog
.devices()) :
184 descs(prog
.context().devs()));
187 case CL_PROGRAM_SOURCE
:
188 buf
.as_string() = prog
.source();
191 case CL_PROGRAM_BINARY_SIZES
:
192 buf
.as_vector
<size_t>() = map([&](const device
&dev
) {
193 compat::ostream::buffer_t bin
;
194 compat::ostream
s(bin
);
195 prog
.binary(dev
).serialize(s
);
201 case CL_PROGRAM_BINARIES
:
202 buf
.as_matrix
<unsigned char>() = map([&](const device
&dev
) {
203 compat::ostream::buffer_t bin
;
204 compat::ostream
s(bin
);
205 prog
.binary(dev
).serialize(s
);
212 throw error(CL_INVALID_VALUE
);
222 clGetProgramBuildInfo(cl_program d_prog
, cl_device_id d_dev
,
223 cl_program_build_info param
,
224 size_t size
, void *r_buf
, size_t *r_size
) try {
225 property_buffer buf
{ r_buf
, size
, r_size
};
226 auto &prog
= obj(d_prog
);
227 auto &dev
= obj(d_dev
);
229 if (!count(dev
, prog
.context().devs()))
230 return CL_INVALID_DEVICE
;
233 case CL_PROGRAM_BUILD_STATUS
:
234 buf
.as_scalar
<cl_build_status
>() = prog
.build_status(dev
);
237 case CL_PROGRAM_BUILD_OPTIONS
:
238 buf
.as_string() = prog
.build_opts(dev
);
241 case CL_PROGRAM_BUILD_LOG
:
242 buf
.as_string() = prog
.build_log(dev
);
246 throw error(CL_INVALID_VALUE
);