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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 // OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 #include "api/util.hpp"
24 #include "core/program.hpp"
26 using namespace clover
;
29 clCreateProgramWithSource(cl_context ctx
, cl_uint count
,
30 const char **strings
, const size_t *lengths
,
31 cl_int
*errcode_ret
) try {
35 throw error(CL_INVALID_CONTEXT
);
37 if (!count
|| !strings
||
38 any_of(is_zero
<const char *>(), strings
, strings
+ count
))
39 throw error(CL_INVALID_VALUE
);
41 // Concatenate all the provided fragments together
42 for (unsigned i
= 0; i
< count
; ++i
)
43 source
+= (lengths
&& lengths
[i
] ?
44 std::string(strings
[i
], strings
[i
] + lengths
[i
]) :
45 std::string(strings
[i
]));
47 // ...and create a program object for them.
48 ret_error(errcode_ret
, CL_SUCCESS
);
49 return new program(*ctx
, source
);
52 ret_error(errcode_ret
, e
);
57 clCreateProgramWithBinary(cl_context ctx
, cl_uint count
,
58 const cl_device_id
*devs
, const size_t *lengths
,
59 const unsigned char **binaries
, cl_int
*status_ret
,
60 cl_int
*errcode_ret
) try {
62 throw error(CL_INVALID_CONTEXT
);
64 if (!count
|| !devs
|| !lengths
|| !binaries
)
65 throw error(CL_INVALID_VALUE
);
67 if (any_of([&](const cl_device_id dev
) {
68 return !ctx
->has_device(dev
);
69 }, devs
, devs
+ count
))
70 throw error(CL_INVALID_DEVICE
);
72 // Deserialize the provided binaries,
74 [](const unsigned char *p
, size_t l
) -> std::pair
<cl_int
, module
> {
76 return { CL_INVALID_VALUE
, {} };
79 compat::istream::buffer_t
bin(p
, l
);
80 compat::istream
s(bin
);
82 return { CL_SUCCESS
, module::deserialize(s
) };
84 } catch (compat::istream::error
&e
) {
85 return { CL_INVALID_BINARY
, {} };
88 binaries
, binaries
+ count
, lengths
);
90 // update the status array,
92 std::transform(modules
.begin(), modules
.end(), status_ret
,
93 keys
<cl_int
, module
>);
95 if (any_of(key_equals
<cl_int
, module
>(CL_INVALID_VALUE
),
96 modules
.begin(), modules
.end()))
97 throw error(CL_INVALID_VALUE
);
99 if (any_of(key_equals
<cl_int
, module
>(CL_INVALID_BINARY
),
100 modules
.begin(), modules
.end()))
101 throw error(CL_INVALID_BINARY
);
103 // initialize a program object with them.
104 ret_error(errcode_ret
, CL_SUCCESS
);
105 return new program(*ctx
, { devs
, devs
+ count
},
106 map(values
<cl_int
, module
>,
107 modules
.begin(), modules
.end()));
110 ret_error(errcode_ret
, e
);
115 clRetainProgram(cl_program prog
) {
117 return CL_INVALID_PROGRAM
;
124 clReleaseProgram(cl_program prog
) {
126 return CL_INVALID_PROGRAM
;
135 clBuildProgram(cl_program prog
, cl_uint count
, const cl_device_id
*devs
,
136 const char *opts
, void (*pfn_notify
)(cl_program
, void *),
137 void *user_data
) try {
139 throw error(CL_INVALID_PROGRAM
);
141 if (bool(count
) != bool(devs
) ||
142 (!pfn_notify
&& user_data
))
143 throw error(CL_INVALID_VALUE
);
146 if (any_of([&](const cl_device_id dev
) {
147 return !prog
->ctx
.has_device(dev
);
148 }, devs
, devs
+ count
))
149 throw error(CL_INVALID_DEVICE
);
151 prog
->build({ devs
, devs
+ count
});
153 prog
->build(prog
->ctx
.devs
);
168 clGetProgramInfo(cl_program prog
, cl_program_info param
,
169 size_t size
, void *buf
, size_t *size_ret
) {
171 return CL_INVALID_PROGRAM
;
174 case CL_PROGRAM_REFERENCE_COUNT
:
175 return scalar_property
<cl_uint
>(buf
, size
, size_ret
,
178 case CL_PROGRAM_CONTEXT
:
179 return scalar_property
<cl_context
>(buf
, size
, size_ret
,
182 case CL_PROGRAM_NUM_DEVICES
:
183 return scalar_property
<cl_uint
>(buf
, size
, size_ret
,
184 prog
->binaries().size());
186 case CL_PROGRAM_DEVICES
:
187 return vector_property
<cl_device_id
>(
189 map(keys
<device
*, module
>,
190 prog
->binaries().begin(), prog
->binaries().end()));
192 case CL_PROGRAM_SOURCE
:
193 return string_property(buf
, size
, size_ret
, prog
->source());
195 case CL_PROGRAM_BINARY_SIZES
:
196 return vector_property
<size_t>(
198 map([](const std::pair
<device
*, module
> &ent
) {
199 compat::ostream::buffer_t bin
;
200 compat::ostream
s(bin
);
201 ent
.second
.serialize(s
);
204 prog
->binaries().begin(), prog
->binaries().end()));
206 case CL_PROGRAM_BINARIES
:
207 return matrix_property
<unsigned char>(
209 map([](const std::pair
<device
*, module
> &ent
) {
210 compat::ostream::buffer_t bin
;
211 compat::ostream
s(bin
);
212 ent
.second
.serialize(s
);
215 prog
->binaries().begin(), prog
->binaries().end()));
218 return CL_INVALID_VALUE
;
223 clGetProgramBuildInfo(cl_program prog
, cl_device_id dev
,
224 cl_program_build_info param
,
225 size_t size
, void *buf
, size_t *size_ret
) {
227 return CL_INVALID_PROGRAM
;
229 if (!prog
->ctx
.has_device(dev
))
230 return CL_INVALID_DEVICE
;
233 case CL_PROGRAM_BUILD_STATUS
:
234 return scalar_property
<cl_build_status
>(buf
, size
, size_ret
,
235 prog
->build_status(dev
));
237 case CL_PROGRAM_BUILD_OPTIONS
:
238 return string_property(buf
, size
, size_ret
, prog
->build_opts(dev
));
240 case CL_PROGRAM_BUILD_LOG
:
241 return string_property(buf
, size
, size_ret
, prog
->build_log(dev
));
244 return CL_INVALID_VALUE
;