OSDN Git Service

clover: Import OpenCL state tracker.
[android-x86/external-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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 // OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 // 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 (any_of([&](const cl_device_id dev) {
146             return !prog->ctx.has_device(dev);
147          }, devs, devs + count))
148       throw error(CL_INVALID_DEVICE);
149
150    prog->build({ devs, devs + count });
151    return CL_SUCCESS;
152
153 } catch (error &e) {
154    return e.get();
155 }
156
157 PUBLIC cl_int
158 clUnloadCompiler() {
159    return CL_SUCCESS;
160 }
161
162 PUBLIC cl_int
163 clGetProgramInfo(cl_program prog, cl_program_info param,
164                  size_t size, void *buf, size_t *size_ret) {
165    if (!prog)
166       return CL_INVALID_PROGRAM;
167
168    switch (param) {
169    case CL_PROGRAM_REFERENCE_COUNT:
170       return scalar_property<cl_uint>(buf, size, size_ret,
171                                       prog->ref_count());
172
173    case CL_PROGRAM_CONTEXT:
174       return scalar_property<cl_context>(buf, size, size_ret,
175                                          &prog->ctx);
176
177    case CL_PROGRAM_NUM_DEVICES:
178       return scalar_property<cl_uint>(buf, size, size_ret,
179                                       prog->binaries().size());
180
181    case CL_PROGRAM_DEVICES:
182       return vector_property<cl_device_id>(
183          buf, size, size_ret,
184          map(keys<device *, module>,
185              prog->binaries().begin(), prog->binaries().end()));
186
187    case CL_PROGRAM_SOURCE:
188       return string_property(buf, size, size_ret, prog->source());
189
190    case CL_PROGRAM_BINARY_SIZES:
191       return vector_property<size_t>(
192          buf, size, size_ret,
193          map([](const std::pair<device *, module> &ent) {
194                compat::ostream::buffer_t bin;
195                compat::ostream s(bin);
196                ent.second.serialize(s);
197                return bin.size();
198             },
199             prog->binaries().begin(), prog->binaries().end()));
200
201    case CL_PROGRAM_BINARIES:
202       return matrix_property<unsigned char>(
203          buf, size, size_ret,
204          map([](const std::pair<device *, module> &ent) {
205                compat::ostream::buffer_t bin;
206                compat::ostream s(bin);
207                ent.second.serialize(s);
208                return bin;
209             },
210             prog->binaries().begin(), prog->binaries().end()));
211
212    default:
213       return CL_INVALID_VALUE;
214    }
215 }
216
217 PUBLIC cl_int
218 clGetProgramBuildInfo(cl_program prog, cl_device_id dev,
219                       cl_program_build_info param,
220                       size_t size, void *buf, size_t *size_ret) {
221    if (!prog)
222       return CL_INVALID_PROGRAM;
223
224    if (!prog->ctx.has_device(dev))
225       return CL_INVALID_DEVICE;
226
227    switch (param) {
228    case CL_PROGRAM_BUILD_STATUS:
229       return scalar_property<cl_build_status>(buf, size, size_ret,
230                                               prog->build_status(dev));
231
232    case CL_PROGRAM_BUILD_OPTIONS:
233       return string_property(buf, size, size_ret, prog->build_opts(dev));
234
235    case CL_PROGRAM_BUILD_LOG:
236       return string_property(buf, size, size_ret, prog->build_log(dev));
237
238    default:
239       return CL_INVALID_VALUE;
240    }
241 }