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 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
);
149 if (any_of([&](const cl_device_id dev
) {
150 return !prog
->ctx
.has_device(dev
);
151 }, devs
, devs
+ count
))
152 throw error(CL_INVALID_DEVICE
);
154 prog
->build({ devs
, devs
+ count
}, opts
);
156 prog
->build(prog
->ctx
.devs
, opts
);
171 clGetProgramInfo(cl_program prog
, cl_program_info param
,
172 size_t size
, void *buf
, size_t *size_ret
) {
174 return CL_INVALID_PROGRAM
;
177 case CL_PROGRAM_REFERENCE_COUNT
:
178 return scalar_property
<cl_uint
>(buf
, size
, size_ret
,
181 case CL_PROGRAM_CONTEXT
:
182 return scalar_property
<cl_context
>(buf
, size
, size_ret
,
185 case CL_PROGRAM_NUM_DEVICES
:
186 return scalar_property
<cl_uint
>(buf
, size
, size_ret
,
187 prog
->binaries().size());
189 case CL_PROGRAM_DEVICES
:
190 return vector_property
<cl_device_id
>(
192 map(keys
<device
*, module
>,
193 prog
->binaries().begin(), prog
->binaries().end()));
195 case CL_PROGRAM_SOURCE
:
196 return string_property(buf
, size
, size_ret
, prog
->source());
198 case CL_PROGRAM_BINARY_SIZES
:
199 return vector_property
<size_t>(
201 map([](const std::pair
<device
*, module
> &ent
) {
202 compat::ostream::buffer_t bin
;
203 compat::ostream
s(bin
);
204 ent
.second
.serialize(s
);
207 prog
->binaries().begin(), prog
->binaries().end()));
209 case CL_PROGRAM_BINARIES
:
210 return matrix_property
<unsigned char>(
212 map([](const std::pair
<device
*, module
> &ent
) {
213 compat::ostream::buffer_t bin
;
214 compat::ostream
s(bin
);
215 ent
.second
.serialize(s
);
218 prog
->binaries().begin(), prog
->binaries().end()));
221 return CL_INVALID_VALUE
;
226 clGetProgramBuildInfo(cl_program prog
, cl_device_id dev
,
227 cl_program_build_info param
,
228 size_t size
, void *buf
, size_t *size_ret
) {
230 return CL_INVALID_PROGRAM
;
232 if (!prog
->ctx
.has_device(dev
))
233 return CL_INVALID_DEVICE
;
236 case CL_PROGRAM_BUILD_STATUS
:
237 return scalar_property
<cl_build_status
>(buf
, size
, size_ret
,
238 prog
->build_status(dev
));
240 case CL_PROGRAM_BUILD_OPTIONS
:
241 return string_property(buf
, size
, size_ret
, prog
->build_opts(dev
));
243 case CL_PROGRAM_BUILD_LOG
:
244 return string_property(buf
, size
, size_ret
, prog
->build_log(dev
));
247 return CL_INVALID_VALUE
;