Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5564 serge 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 
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(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> result = map(
94
      [](const unsigned char *p, size_t l) -> std::pair {
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(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(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(
222
                                 name, header.source()));
223
      },
224
      range(header_names, num_headers),
225
      objs(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_int
235
clUnloadCompiler() {
236
   return CL_SUCCESS;
237
}
238
 
239
CLOVER_API cl_int
240
clUnloadPlatformCompiler(cl_platform_id d_platform) {
241
   return CL_SUCCESS;
242
}
243
 
244
CLOVER_API cl_int
245
clGetProgramInfo(cl_program d_prog, cl_program_info param,
246
                 size_t size, void *r_buf, size_t *r_size) try {
247
   property_buffer buf { r_buf, size, r_size };
248
   auto &prog = obj(d_prog);
249
 
250
   switch (param) {
251
   case CL_PROGRAM_REFERENCE_COUNT:
252
      buf.as_scalar() = prog.ref_count();
253
      break;
254
 
255
   case CL_PROGRAM_CONTEXT:
256
      buf.as_scalar() = desc(prog.context());
257
      break;
258
 
259
   case CL_PROGRAM_NUM_DEVICES:
260
      buf.as_scalar() = (prog.devices().size() ?
261
                                  prog.devices().size() :
262
                                  prog.context().devices().size());
263
      break;
264
 
265
   case CL_PROGRAM_DEVICES:
266
      buf.as_vector() = (prog.devices().size() ?
267
                                       descs(prog.devices()) :
268
                                       descs(prog.context().devices()));
269
      break;
270
 
271
   case CL_PROGRAM_SOURCE:
272
      buf.as_string() = prog.source();
273
      break;
274
 
275
   case CL_PROGRAM_BINARY_SIZES:
276
      buf.as_vector() = map([&](const device &dev) {
277
            return prog.binary(dev).size();
278
         },
279
         prog.devices());
280
      break;
281
 
282
   case CL_PROGRAM_BINARIES:
283
      buf.as_matrix() = map([&](const device &dev) {
284
            std::stringbuf bin;
285
            std::ostream s(&bin);
286
            prog.binary(dev).serialize(s);
287
            return bin.str();
288
         },
289
         prog.devices());
290
      break;
291
 
292
   case CL_PROGRAM_NUM_KERNELS:
293
      buf.as_scalar() = prog.symbols().size();
294
      break;
295
 
296
   case CL_PROGRAM_KERNEL_NAMES:
297
      buf.as_string() = fold([](const std::string &a, const module::symbol &s) {
298
            return ((a.empty() ? "" : a + ";") + s.name);
299
         }, std::string(), prog.symbols());
300
      break;
301
 
302
   default:
303
      throw error(CL_INVALID_VALUE);
304
   }
305
 
306
   return CL_SUCCESS;
307
 
308
} catch (error &e) {
309
   return e.get();
310
}
311
 
312
CLOVER_API cl_int
313
clGetProgramBuildInfo(cl_program d_prog, cl_device_id d_dev,
314
                      cl_program_build_info param,
315
                      size_t size, void *r_buf, size_t *r_size) try {
316
   property_buffer buf { r_buf, size, r_size };
317
   auto &prog = obj(d_prog);
318
   auto &dev = obj(d_dev);
319
 
320
   if (!count(dev, prog.context().devices()))
321
      return CL_INVALID_DEVICE;
322
 
323
   switch (param) {
324
   case CL_PROGRAM_BUILD_STATUS:
325
      buf.as_scalar() = prog.build_status(dev);
326
      break;
327
 
328
   case CL_PROGRAM_BUILD_OPTIONS:
329
      buf.as_string() = prog.build_opts(dev);
330
      break;
331
 
332
   case CL_PROGRAM_BUILD_LOG:
333
      buf.as_string() = prog.build_log(dev);
334
      break;
335
 
336
   default:
337
      throw error(CL_INVALID_VALUE);
338
   }
339
 
340
   return CL_SUCCESS;
341
 
342
} catch (error &e) {
343
   return e.get();
344
}