mesa: Restore 78-column wrapping of license text in C++-style comments.
[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 using namespace clover;
27
28 PUBLIC cl_program
29 clCreateProgramWithSource(cl_context ctx, cl_uint count,
30 const char **strings, const size_t *lengths,
31 cl_int *errcode_ret) try {
32 std::string source;
33
34 if (!ctx)
35 throw error(CL_INVALID_CONTEXT);
36
37 if (!count || !strings ||
38 any_of(is_zero<const char *>, strings, strings + count))
39 throw error(CL_INVALID_VALUE);
40
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]));
46
47 // ...and create a program object for them.
48 ret_error(errcode_ret, CL_SUCCESS);
49 return new program(*ctx, source);
50
51 } catch (error &e) {
52 ret_error(errcode_ret, e);
53 return NULL;
54 }
55
56 PUBLIC cl_program
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 {
61 if (!ctx)
62 throw error(CL_INVALID_CONTEXT);
63
64 if (!count || !devs || !lengths || !binaries)
65 throw error(CL_INVALID_VALUE);
66
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);
71
72 // Deserialize the provided binaries,
73 auto modules = map(
74 [](const unsigned char *p, size_t l) -> std::pair<cl_int, module> {
75 if (!p || !l)
76 return { CL_INVALID_VALUE, {} };
77
78 try {
79 compat::istream::buffer_t bin(p, l);
80 compat::istream s(bin);
81
82 return { CL_SUCCESS, module::deserialize(s) };
83
84 } catch (compat::istream::error &e) {
85 return { CL_INVALID_BINARY, {} };
86 }
87 },
88 binaries, binaries + count, lengths);
89
90 // update the status array,
91 if (status_ret)
92 std::transform(modules.begin(), modules.end(), status_ret,
93 keys<cl_int, module>);
94
95 if (any_of(key_equals<cl_int, module>(CL_INVALID_VALUE),
96 modules.begin(), modules.end()))
97 throw error(CL_INVALID_VALUE);
98
99 if (any_of(key_equals<cl_int, module>(CL_INVALID_BINARY),
100 modules.begin(), modules.end()))
101 throw error(CL_INVALID_BINARY);
102
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()));
108
109 } catch (error &e) {
110 ret_error(errcode_ret, e);
111 return NULL;
112 }
113
114 PUBLIC cl_int
115 clRetainProgram(cl_program prog) {
116 if (!prog)
117 return CL_INVALID_PROGRAM;
118
119 prog->retain();
120 return CL_SUCCESS;
121 }
122
123 PUBLIC cl_int
124 clReleaseProgram(cl_program prog) {
125 if (!prog)
126 return CL_INVALID_PROGRAM;
127
128 if (prog->release())
129 delete prog;
130
131 return CL_SUCCESS;
132 }
133
134 PUBLIC cl_int
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 {
138 if (!prog)
139 throw error(CL_INVALID_PROGRAM);
140
141 if (bool(count) != bool(devs) ||
142 (!pfn_notify && user_data))
143 throw error(CL_INVALID_VALUE);
144
145 if (!opts)
146 opts = "";
147
148 if (devs) {
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);
153
154 prog->build({ devs, devs + count }, opts);
155 } else {
156 prog->build(prog->ctx.devs, opts);
157 }
158
159 return CL_SUCCESS;
160
161 } catch (error &e) {
162 return e.get();
163 }
164
165 PUBLIC cl_int
166 clUnloadCompiler() {
167 return CL_SUCCESS;
168 }
169
170 PUBLIC cl_int
171 clGetProgramInfo(cl_program prog, cl_program_info param,
172 size_t size, void *buf, size_t *size_ret) {
173 if (!prog)
174 return CL_INVALID_PROGRAM;
175
176 switch (param) {
177 case CL_PROGRAM_REFERENCE_COUNT:
178 return scalar_property<cl_uint>(buf, size, size_ret,
179 prog->ref_count());
180
181 case CL_PROGRAM_CONTEXT:
182 return scalar_property<cl_context>(buf, size, size_ret,
183 &prog->ctx);
184
185 case CL_PROGRAM_NUM_DEVICES:
186 return scalar_property<cl_uint>(buf, size, size_ret,
187 prog->binaries().size());
188
189 case CL_PROGRAM_DEVICES:
190 return vector_property<cl_device_id>(
191 buf, size, size_ret,
192 map(keys<device *, module>,
193 prog->binaries().begin(), prog->binaries().end()));
194
195 case CL_PROGRAM_SOURCE:
196 return string_property(buf, size, size_ret, prog->source());
197
198 case CL_PROGRAM_BINARY_SIZES:
199 return vector_property<size_t>(
200 buf, size, size_ret,
201 map([](const std::pair<device *, module> &ent) {
202 compat::ostream::buffer_t bin;
203 compat::ostream s(bin);
204 ent.second.serialize(s);
205 return bin.size();
206 },
207 prog->binaries().begin(), prog->binaries().end()));
208
209 case CL_PROGRAM_BINARIES:
210 return matrix_property<unsigned char>(
211 buf, size, size_ret,
212 map([](const std::pair<device *, module> &ent) {
213 compat::ostream::buffer_t bin;
214 compat::ostream s(bin);
215 ent.second.serialize(s);
216 return bin;
217 },
218 prog->binaries().begin(), prog->binaries().end()));
219
220 default:
221 return CL_INVALID_VALUE;
222 }
223 }
224
225 PUBLIC cl_int
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) {
229 if (!prog)
230 return CL_INVALID_PROGRAM;
231
232 if (!prog->ctx.has_device(dev))
233 return CL_INVALID_DEVICE;
234
235 switch (param) {
236 case CL_PROGRAM_BUILD_STATUS:
237 return scalar_property<cl_build_status>(buf, size, size_ret,
238 prog->build_status(dev));
239
240 case CL_PROGRAM_BUILD_OPTIONS:
241 return string_property(buf, size, size_ret, prog->build_opts(dev));
242
243 case CL_PROGRAM_BUILD_LOG:
244 return string_property(buf, size, size_ret, prog->build_log(dev));
245
246 default:
247 return CL_INVALID_VALUE;
248 }
249 }