clover: Migrate a bunch of pointers and references in the object tree to smart refere...
[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 CLOVER_API cl_program
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);
33 std::string source;
34
35 if (!count || !strings ||
36 any_of(is_zero(), range(strings, count)))
37 throw error(CL_INVALID_VALUE);
38
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]));
44
45 // ...and create a program object for them.
46 ret_error(r_errcode, CL_SUCCESS);
47 return new program(ctx, source);
48
49 } catch (error &e) {
50 ret_error(r_errcode, e);
51 return NULL;
52 }
53
54 CLOVER_API cl_program
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);
62
63 if (!lengths || !binaries)
64 throw error(CL_INVALID_VALUE);
65
66 if (any_of([&](const device &dev) {
67 return !count(dev, ctx.devs());
68 }, devs))
69 throw error(CL_INVALID_DEVICE);
70
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> {
74 if (!p || !l)
75 return { CL_INVALID_VALUE, {} };
76
77 try {
78 compat::istream::buffer_t bin(p, l);
79 compat::istream s(bin);
80
81 return { CL_SUCCESS, module::deserialize(s) };
82
83 } catch (compat::istream::error &e) {
84 return { CL_INVALID_BINARY, {} };
85 }
86 },
87 range(binaries, n),
88 range(lengths, n));
89
90 // update the status array,
91 if (r_status)
92 copy(map(keys(), result), r_status);
93
94 if (any_of(key_equals(CL_INVALID_VALUE), result))
95 throw error(CL_INVALID_VALUE);
96
97 if (any_of(key_equals(CL_INVALID_BINARY), result))
98 throw error(CL_INVALID_BINARY);
99
100 // initialize a program object with them.
101 ret_error(r_errcode, CL_SUCCESS);
102 return new program(ctx, devs, map(values(), result));
103
104 } catch (error &e) {
105 ret_error(r_errcode, e);
106 return NULL;
107 }
108
109 CLOVER_API cl_int
110 clRetainProgram(cl_program d_prog) try {
111 obj(d_prog).retain();
112 return CL_SUCCESS;
113
114 } catch (error &e) {
115 return e.get();
116 }
117
118 CLOVER_API cl_int
119 clReleaseProgram(cl_program d_prog) try {
120 if (obj(d_prog).release())
121 delete pobj(d_prog);
122
123 return CL_SUCCESS;
124
125 } catch (error &e) {
126 return e.get();
127 }
128
129 CLOVER_API cl_int
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 : "");
138
139 if (bool(num_devs) != bool(d_devs) ||
140 (!pfn_notify && user_data))
141 throw error(CL_INVALID_VALUE);
142
143 if (any_of([&](const device &dev) {
144 return !count(dev, prog.context().devs());
145 }, devs))
146 throw error(CL_INVALID_DEVICE);
147
148 prog.build(devs, opts);
149 return CL_SUCCESS;
150
151 } catch (error &e) {
152 return e.get();
153 }
154
155 CLOVER_API cl_int
156 clUnloadCompiler() {
157 return CL_SUCCESS;
158 }
159
160 CLOVER_API cl_int
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);
165
166 switch (param) {
167 case CL_PROGRAM_REFERENCE_COUNT:
168 buf.as_scalar<cl_uint>() = prog.ref_count();
169 break;
170
171 case CL_PROGRAM_CONTEXT:
172 buf.as_scalar<cl_context>() = desc(prog.context());
173 break;
174
175 case CL_PROGRAM_NUM_DEVICES:
176 buf.as_scalar<cl_uint>() = (prog.devices().size() ?
177 prog.devices().size() :
178 prog.context().devs().size());
179 break;
180
181 case CL_PROGRAM_DEVICES:
182 buf.as_vector<cl_device_id>() = (prog.devices().size() ?
183 descs(prog.devices()) :
184 descs(prog.context().devs()));
185 break;
186
187 case CL_PROGRAM_SOURCE:
188 buf.as_string() = prog.source();
189 break;
190
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);
196 return bin.size();
197 },
198 prog.devices());
199 break;
200
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);
206 return bin;
207 },
208 prog.devices());
209 break;
210
211 default:
212 throw error(CL_INVALID_VALUE);
213 }
214
215 return CL_SUCCESS;
216
217 } catch (error &e) {
218 return e.get();
219 }
220
221 CLOVER_API cl_int
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);
228
229 if (!count(dev, prog.context().devs()))
230 return CL_INVALID_DEVICE;
231
232 switch (param) {
233 case CL_PROGRAM_BUILD_STATUS:
234 buf.as_scalar<cl_build_status>() = prog.build_status(dev);
235 break;
236
237 case CL_PROGRAM_BUILD_OPTIONS:
238 buf.as_string() = prog.build_opts(dev);
239 break;
240
241 case CL_PROGRAM_BUILD_LOG:
242 buf.as_string() = prog.build_log(dev);
243 break;
244
245 default:
246 throw error(CL_INVALID_VALUE);
247 }
248
249 return CL_SUCCESS;
250
251 } catch (error &e) {
252 return e.get();
253 }