radeon/vce: fix VCE fail after rebase
[mesa.git] / src / gallium / state_trackers / clover / api / program.cpp
1 //
2 // Copyright 2012 Francisco Jerez
3 //
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:
10 //
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
13 //
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.
21 //
22
23 #include "api/util.hpp"
24 #include "core/program.hpp"
25
26 #include <sstream>
27
28 using namespace clover;
29
30 namespace {
31 void validate_build_program_common(const program &prog, cl_uint num_devs,
32 const cl_device_id *d_devs,
33 void (*pfn_notify)(cl_program, void *),
34 void *user_data) {
35
36 if ((!pfn_notify && user_data))
37 throw error(CL_INVALID_VALUE);
38
39 if (prog.kernel_ref_count())
40 throw error(CL_INVALID_OPERATION);
41
42 if (any_of([&](const device &dev) {
43 return !count(dev, prog.context().devices());
44 }, objs<allow_empty_tag>(d_devs, num_devs)))
45 throw error(CL_INVALID_DEVICE);
46 }
47 }
48
49 CLOVER_API cl_program
50 clCreateProgramWithSource(cl_context d_ctx, cl_uint count,
51 const char **strings, const size_t *lengths,
52 cl_int *r_errcode) try {
53 auto &ctx = obj(d_ctx);
54 std::string source;
55
56 if (!count || !strings ||
57 any_of(is_zero(), range(strings, count)))
58 throw error(CL_INVALID_VALUE);
59
60 // Concatenate all the provided fragments together
61 for (unsigned i = 0; i < count; ++i)
62 source += (lengths && lengths[i] ?
63 std::string(strings[i], strings[i] + lengths[i]) :
64 std::string(strings[i]));
65
66 // ...and create a program object for them.
67 ret_error(r_errcode, CL_SUCCESS);
68 return new program(ctx, source);
69
70 } catch (error &e) {
71 ret_error(r_errcode, e);
72 return NULL;
73 }
74
75 CLOVER_API cl_program
76 clCreateProgramWithBinary(cl_context d_ctx, cl_uint n,
77 const cl_device_id *d_devs,
78 const size_t *lengths,
79 const unsigned char **binaries,
80 cl_int *r_status, cl_int *r_errcode) try {
81 auto &ctx = obj(d_ctx);
82 auto devs = objs(d_devs, n);
83
84 if (!lengths || !binaries)
85 throw error(CL_INVALID_VALUE);
86
87 if (any_of([&](const device &dev) {
88 return !count(dev, ctx.devices());
89 }, devs))
90 throw error(CL_INVALID_DEVICE);
91
92 // Deserialize the provided binaries,
93 std::vector<std::pair<cl_int, module>> result = map(
94 [](const unsigned char *p, size_t l) -> std::pair<cl_int, module> {
95 if (!p || !l)
96 return { CL_INVALID_VALUE, {} };
97
98 try {
99 std::stringbuf bin( { (char*)p, l } );
100 std::istream s(&bin);
101
102 return { CL_SUCCESS, module::deserialize(s) };
103
104 } catch (std::istream::failure &e) {
105 return { CL_INVALID_BINARY, {} };
106 }
107 },
108 range(binaries, n),
109 range(lengths, n));
110
111 // update the status array,
112 if (r_status)
113 copy(map(keys(), result), r_status);
114
115 if (any_of(key_equals(CL_INVALID_VALUE), result))
116 throw error(CL_INVALID_VALUE);
117
118 if (any_of(key_equals(CL_INVALID_BINARY), result))
119 throw error(CL_INVALID_BINARY);
120
121 // initialize a program object with them.
122 ret_error(r_errcode, CL_SUCCESS);
123 return new program(ctx, devs, map(values(), result));
124
125 } catch (error &e) {
126 ret_error(r_errcode, e);
127 return NULL;
128 }
129
130 CLOVER_API cl_program
131 clCreateProgramWithBuiltInKernels(cl_context d_ctx, cl_uint n,
132 const cl_device_id *d_devs,
133 const char *kernel_names,
134 cl_int *r_errcode) try {
135 auto &ctx = obj(d_ctx);
136 auto devs = objs(d_devs, n);
137
138 if (any_of([&](const device &dev) {
139 return !count(dev, ctx.devices());
140 }, devs))
141 throw error(CL_INVALID_DEVICE);
142
143 // No currently supported built-in kernels.
144 throw error(CL_INVALID_VALUE);
145
146 } catch (error &e) {
147 ret_error(r_errcode, e);
148 return NULL;
149 }
150
151
152 CLOVER_API cl_int
153 clRetainProgram(cl_program d_prog) try {
154 obj(d_prog).retain();
155 return CL_SUCCESS;
156
157 } catch (error &e) {
158 return e.get();
159 }
160
161 CLOVER_API cl_int
162 clReleaseProgram(cl_program d_prog) try {
163 if (obj(d_prog).release())
164 delete pobj(d_prog);
165
166 return CL_SUCCESS;
167
168 } catch (error &e) {
169 return e.get();
170 }
171
172 CLOVER_API cl_int
173 clBuildProgram(cl_program d_prog, cl_uint num_devs,
174 const cl_device_id *d_devs, const char *p_opts,
175 void (*pfn_notify)(cl_program, void *),
176 void *user_data) try {
177 auto &prog = obj(d_prog);
178 auto devs = (d_devs ? objs(d_devs, num_devs) :
179 ref_vector<device>(prog.context().devices()));
180 auto opts = (p_opts ? p_opts : "");
181
182 validate_build_program_common(prog, num_devs, d_devs, pfn_notify, user_data);
183
184 prog.build(devs, opts);
185 return CL_SUCCESS;
186 } catch (error &e) {
187 if (e.get() == CL_INVALID_COMPILER_OPTIONS)
188 return CL_INVALID_BUILD_OPTIONS;
189 if (e.get() == CL_COMPILE_PROGRAM_FAILURE)
190 return CL_BUILD_PROGRAM_FAILURE;
191 return e.get();
192 }
193
194 CLOVER_API cl_int
195 clCompileProgram(cl_program d_prog, cl_uint num_devs,
196 const cl_device_id *d_devs, const char *p_opts,
197 cl_uint num_headers, const cl_program *d_header_progs,
198 const char **header_names,
199 void (*pfn_notify)(cl_program, void *),
200 void *user_data) try {
201 auto &prog = obj(d_prog);
202 auto devs = (d_devs ? objs(d_devs, num_devs) :
203 ref_vector<device>(prog.context().devices()));
204 auto opts = (p_opts ? p_opts : "");
205 header_map headers;
206
207 validate_build_program_common(prog, num_devs, d_devs, pfn_notify, user_data);
208
209 if (bool(num_headers) != bool(header_names))
210 throw error(CL_INVALID_VALUE);
211
212 if (!prog.has_source)
213 throw error(CL_INVALID_OPERATION);
214
215
216 for_each([&](const char *name, const program &header) {
217 if (!header.has_source)
218 throw error(CL_INVALID_OPERATION);
219
220 if (!any_of(key_equals(name), headers))
221 headers.push_back(std::pair<std::string, std::string>(
222 name, header.source()));
223 },
224 range(header_names, num_headers),
225 objs<allow_empty_tag>(d_header_progs, num_headers));
226
227 prog.build(devs, opts, headers);
228 return CL_SUCCESS;
229
230 } catch (error &e) {
231 return e.get();
232 }
233
234 CLOVER_API cl_program
235 clLinkProgram(cl_context d_ctx, cl_uint num_devs, const cl_device_id *d_devs,
236 const char *p_opts, cl_uint num_progs, const cl_program *d_progs,
237 void (*pfn_notify)(cl_program, void *), void *user_data,
238 cl_int *r_errcode) {
239 CLOVER_NOT_SUPPORTED_UNTIL("1.2");
240 ret_error(r_errcode, CL_LINKER_NOT_AVAILABLE);
241 return NULL;
242 }
243
244 CLOVER_API cl_int
245 clUnloadCompiler() {
246 return CL_SUCCESS;
247 }
248
249 CLOVER_API cl_int
250 clUnloadPlatformCompiler(cl_platform_id d_platform) {
251 return CL_SUCCESS;
252 }
253
254 CLOVER_API cl_int
255 clGetProgramInfo(cl_program d_prog, cl_program_info param,
256 size_t size, void *r_buf, size_t *r_size) try {
257 property_buffer buf { r_buf, size, r_size };
258 auto &prog = obj(d_prog);
259
260 switch (param) {
261 case CL_PROGRAM_REFERENCE_COUNT:
262 buf.as_scalar<cl_uint>() = prog.ref_count();
263 break;
264
265 case CL_PROGRAM_CONTEXT:
266 buf.as_scalar<cl_context>() = desc(prog.context());
267 break;
268
269 case CL_PROGRAM_NUM_DEVICES:
270 buf.as_scalar<cl_uint>() = (prog.devices().size() ?
271 prog.devices().size() :
272 prog.context().devices().size());
273 break;
274
275 case CL_PROGRAM_DEVICES:
276 buf.as_vector<cl_device_id>() = (prog.devices().size() ?
277 descs(prog.devices()) :
278 descs(prog.context().devices()));
279 break;
280
281 case CL_PROGRAM_SOURCE:
282 buf.as_string() = prog.source();
283 break;
284
285 case CL_PROGRAM_BINARY_SIZES:
286 buf.as_vector<size_t>() = map([&](const device &dev) {
287 return prog.binary(dev).size();
288 },
289 prog.devices());
290 break;
291
292 case CL_PROGRAM_BINARIES:
293 buf.as_matrix<unsigned char>() = map([&](const device &dev) {
294 std::stringbuf bin;
295 std::ostream s(&bin);
296 prog.binary(dev).serialize(s);
297 return bin.str();
298 },
299 prog.devices());
300 break;
301
302 case CL_PROGRAM_NUM_KERNELS:
303 buf.as_scalar<cl_uint>() = prog.symbols().size();
304 break;
305
306 case CL_PROGRAM_KERNEL_NAMES:
307 buf.as_string() = fold([](const std::string &a, const module::symbol &s) {
308 return ((a.empty() ? "" : a + ";") + s.name);
309 }, std::string(), prog.symbols());
310 break;
311
312 default:
313 throw error(CL_INVALID_VALUE);
314 }
315
316 return CL_SUCCESS;
317
318 } catch (error &e) {
319 return e.get();
320 }
321
322 CLOVER_API cl_int
323 clGetProgramBuildInfo(cl_program d_prog, cl_device_id d_dev,
324 cl_program_build_info param,
325 size_t size, void *r_buf, size_t *r_size) try {
326 property_buffer buf { r_buf, size, r_size };
327 auto &prog = obj(d_prog);
328 auto &dev = obj(d_dev);
329
330 if (!count(dev, prog.context().devices()))
331 return CL_INVALID_DEVICE;
332
333 switch (param) {
334 case CL_PROGRAM_BUILD_STATUS:
335 buf.as_scalar<cl_build_status>() = prog.build_status(dev);
336 break;
337
338 case CL_PROGRAM_BUILD_OPTIONS:
339 buf.as_string() = prog.build_opts(dev);
340 break;
341
342 case CL_PROGRAM_BUILD_LOG:
343 buf.as_string() = prog.build_log(dev);
344 break;
345
346 default:
347 throw error(CL_INVALID_VALUE);
348 }
349
350 return CL_SUCCESS;
351
352 } catch (error &e) {
353 return e.get();
354 }