blob: 251196610211aa970b9f88f54b2b40fd981860f8 [file] [log] [blame]
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001/*
Anthony Barbier200b6e32018-01-16 17:21:45 +00002 * Copyright (c) 2016-2018 ARM Limited.
Anthony Barbier6ff3b192017-09-04 18:44:23 +01003 *
4 * SPDX-License-Identifier: MIT
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24#ifndef __ARM_COMPUTE_CLKERNELLIBRARY_H__
25#define __ARM_COMPUTE_CLKERNELLIBRARY_H__
26
27#include "arm_compute/core/CL/OpenCL.h"
28
29#include <map>
30#include <set>
31#include <string>
32#include <utility>
33
34namespace arm_compute
35{
Georgios Pinitas388d3ec2017-11-02 12:17:56 +000036/** Build options */
37class CLBuildOptions
38{
39 using StringSet = std::set<std::string>;
40
41public:
42 /** Default constructor. */
43 CLBuildOptions();
44 /** Adds option to the existing build option list
45 *
46 * @param[in] option Option to add
47 */
48 void add_option(std::string option);
49 /** Adds option if a given condition is true;
50 *
51 * @param[in] cond Condition to check
52 * @param[in] option Option to add if condition is true
53 */
54 void add_option_if(bool cond, std::string option);
55 /** Adds first option if condition is true else the second one
56 *
57 * @param[in] cond Condition to check
58 * @param[in] option_true Option to add if condition is true
59 * @param[in] option_false Option to add if condition is false
60 */
61 void add_option_if_else(bool cond, std::string option_true, std::string option_false);
Chunosovf450caa2017-11-08 16:09:35 +070062 /** Appends given build options to the current's objects options.
63 *
64 * @param[in] options Build options to append
65 */
66 void add_options(const StringSet &options);
67 /** Appends given build options to the current's objects options if a given condition is true.
68 *
69 * @param[in] cond Condition to check
70 * @param[in] options Option to add if condition is true
71 */
72 void add_options_if(bool cond, const StringSet &options);
Georgios Pinitas388d3ec2017-11-02 12:17:56 +000073 /** Gets the current options list set
74 *
75 * @return Build options set
76 */
Chunosovd621bca2017-11-03 17:33:15 +070077 const StringSet &options() const;
Georgios Pinitas388d3ec2017-11-02 12:17:56 +000078
79private:
80 StringSet _build_opts; /**< Build options set */
81};
Anthony Barbier6ff3b192017-09-04 18:44:23 +010082/** Program class */
83class Program
84{
85public:
86 /** Default constructor. */
87 Program();
88 /** Construct program from source file.
89 *
90 * @param[in] context CL context used to create the program.
91 * @param[in] name Program name.
92 * @param[in] source Program source.
93 */
94 Program(cl::Context context, std::string name, std::string source);
95 /** Construct program from binary file.
96 *
97 * @param[in] context CL context used to create the program.
98 * @param[in] device CL device for which the programs are created.
99 * @param[in] name Program name.
100 * @param[in] binary Program binary.
101 */
102 Program(cl::Context context, cl::Device device, std::string name, std::vector<unsigned char> binary);
103 /** Default Copy Constructor. */
104 Program(const Program &) = default;
105 /** Default Move Constructor. */
106 Program(Program &&) = default;
Alex Gildayc357c472018-03-21 13:54:09 +0000107 /** Default copy assignment operator */
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100108 Program &operator=(const Program &) = default;
Alex Gildayc357c472018-03-21 13:54:09 +0000109 /** Default move assignment operator */
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100110 Program &operator=(Program &&) = default;
Alex Gildayc357c472018-03-21 13:54:09 +0000111 /** Returns program name.
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100112 *
113 * @return Program's name.
114 */
115 std::string name() const
116 {
117 return _name;
118 }
119 /** User-defined conversion to the underlying CL program.
120 *
121 * @return The CL program object.
122 */
123 explicit operator cl::Program() const;
Alex Gildayc357c472018-03-21 13:54:09 +0000124 /** Build the given CL program.
125 *
126 * @param[in] program The CL program to build.
127 * @param[in] build_options Options to build the CL program.
128 *
129 * @return True if the CL program builds successfully.
130 */
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100131 static bool build(const cl::Program &program, const std::string &build_options = "");
132 /** Build the underlying CL program.
133 *
134 * @param[in] build_options Options used to build the CL program.
135 *
136 * @return A reference to itself.
137 */
138 cl::Program build(const std::string &build_options = "") const;
139
140private:
141 cl::Context _context; /**< Underlying CL context. */
142 cl::Device _device; /**< CL device for which the programs are created. */
143 bool _is_binary; /**< Create program from binary? */
144 std::string _name; /**< Program name. */
145 std::string _source; /**< Source code for the program. */
146 std::vector<unsigned char> _binary; /**< Binary from which to create the program. */
147};
148
149/** Kernel class */
150class Kernel
151{
152public:
153 /** Default Constructor. */
154 Kernel();
155 /** Default Copy Constructor. */
156 Kernel(const Kernel &) = default;
157 /** Default Move Constructor. */
158 Kernel(Kernel &&) = default;
Alex Gildayc357c472018-03-21 13:54:09 +0000159 /** Default copy assignment operator */
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100160 Kernel &operator=(const Kernel &) = default;
Alex Gildayc357c472018-03-21 13:54:09 +0000161 /** Default move assignment operator */
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100162 Kernel &operator=(Kernel &&) = default;
163 /** Constructor.
164 *
165 * @param[in] name Kernel name.
166 * @param[in] program Built program.
167 */
168 Kernel(std::string name, const cl::Program &program);
169 /** Returns kernel name.
170 *
171 * @return Kernel's name.
172 */
173 std::string name() const
174 {
175 return _name;
176 }
177 /** Returns OpenCL kernel.
178 *
179 * @return OpenCL Kernel.
180 */
181 explicit operator cl::Kernel() const
182 {
183 return _kernel;
184 }
185
186private:
187 std::string _name; /**< Kernel name */
188 cl::Kernel _kernel; /**< OpenCL Kernel */
189};
190
191/** CLKernelLibrary class */
192class CLKernelLibrary
193{
194 using StringSet = std::set<std::string>;
195
196private:
197 /** Default Constructor. */
198 CLKernelLibrary();
199
200public:
Alex Gildayc357c472018-03-21 13:54:09 +0000201 /** Prevent instances of this class from being copied */
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100202 CLKernelLibrary(const CLKernelLibrary &) = delete;
Alex Gildayc357c472018-03-21 13:54:09 +0000203 /** Prevent instances of this class from being copied */
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100204 const CLKernelLibrary &operator=(const CLKernelLibrary &) = delete;
205 /** Access the KernelLibrary singleton.
206 * @return The KernelLibrary instance.
207 */
208 static CLKernelLibrary &get();
209 /** Initialises the kernel library.
210 *
211 * @param[in] kernel_path (Optional) Path of the directory from which kernel sources are loaded.
212 * @param[in] context (Optional) CL context used to create programs.
213 * @param[in] device (Optional) CL device for which the programs are created.
214 */
215 void init(std::string kernel_path = ".", cl::Context context = cl::Context::getDefault(), cl::Device device = cl::Device::getDefault())
216 {
Abel Bernabeu5a6e0532017-09-28 09:53:45 +0100217 _kernel_path = std::move(kernel_path);
218 _context = std::move(context);
219 _device = std::move(device);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100220 }
221 /** Sets the path that the kernels reside in.
222 *
223 * @param[in] kernel_path Path of the kernel.
224 */
225 void set_kernel_path(const std::string &kernel_path)
226 {
227 _kernel_path = kernel_path;
228 };
Michalis Spyroud7e82812017-06-20 15:00:14 +0100229 /** Gets the path that the kernels reside in.
230 */
231 std::string get_kernel_path()
232 {
233 return _kernel_path;
234 };
Alex Gildayc357c472018-03-21 13:54:09 +0000235 /** Gets the source of the selected program.
Anthony Barbierf202e502017-11-23 18:02:04 +0000236 *
237 * @param[in] program_name Program name.
Alex Gildayc357c472018-03-21 13:54:09 +0000238 *
239 * @return Source of the selected program.
Michalis Spyroud7e82812017-06-20 15:00:14 +0100240 */
241 std::string get_program_source(const std::string &program_name);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100242 /** Sets the CL context used to create programs.
243 *
244 * @note Setting the context also resets the device to the
245 * first one available in the new context.
246 *
247 * @param[in] context A CL context.
248 */
249 void set_context(cl::Context context)
250 {
251 _context = std::move(context);
252
253 const auto cl_devices = _context.getInfo<CL_CONTEXT_DEVICES>();
254
255 if(cl_devices.empty())
256 {
257 _device = cl::Device();
258 }
259 else
260 {
261 _device = cl_devices[0];
262 }
Abel Bernabeu5a6e0532017-09-28 09:53:45 +0100263 }
Anthony Barbier4dcb5832018-05-08 11:29:05 +0100264
265 /** Accessor for the associated CL context.
266 *
267 * @return A CL context.
268 */
269 cl::Context &context()
270 {
271 return _context;
272 }
273
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100274 /** Sets the CL device for which the programs are created.
275 *
276 * @param[in] device A CL device.
277 */
278 void set_device(cl::Device device)
279 {
Abel Bernabeu5a6e0532017-09-28 09:53:45 +0100280 _device = std::move(device);
281 }
Anthony Barbier847864d2018-03-07 11:35:53 +0000282
283 /** Return the device version
284 *
285 * @return The content of CL_DEVICE_VERSION
286 */
287 std::string get_device_version();
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100288 /** Creates a kernel from the kernel library.
289 *
290 * @param[in] kernel_name Kernel name.
291 * @param[in] build_options_set Kernel build options as a set.
292 *
293 * @return The created kernel.
294 */
295 Kernel create_kernel(const std::string &kernel_name, const StringSet &build_options_set = {}) const;
Abel Bernabeu5a6e0532017-09-28 09:53:45 +0100296 /** Find the maximum number of local work items in a workgroup can be supported for the kernel.
steniu015f910722017-08-23 10:15:22 +0100297 *
298 */
Abel Bernabeu5a6e0532017-09-28 09:53:45 +0100299 size_t max_local_workgroup_size(const cl::Kernel &kernel) const;
300 /** Return the default NDRange for the device.
steniu015f910722017-08-23 10:15:22 +0100301 *
302 */
Abel Bernabeu5a6e0532017-09-28 09:53:45 +0100303 cl::NDRange default_ndrange() const;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100304
Anthony Barbier200b6e32018-01-16 17:21:45 +0000305 /** Clear the library's cache of binary programs
306 */
307 void clear_programs_cache()
308 {
309 _programs_map.clear();
310 _built_programs_map.clear();
311 }
312
Anthony Barbier48c19f12018-04-20 11:31:52 +0100313 /** Access the cache of built OpenCL programs */
Anthony Barbier7da55aa2018-04-13 16:58:43 +0100314 const std::map<std::string, cl::Program> &get_built_programs() const
315 {
316 return _built_programs_map;
317 }
318
319 /** Add a new built program to the cache
320 *
321 * @param[in] built_program_name Name of the program
322 * @param[in] program Built program to add to the cache
323 */
324 void add_built_program(const std::string &built_program_name, cl::Program program);
325
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100326private:
327 /** Load program and its dependencies.
328 *
329 * @param[in] program_name Name of the program to load.
330 */
331 const Program &load_program(const std::string &program_name) const;
332 /** Concatenates contents of a set into a single string.
333 *
334 * @param[in] s Input set to concatenate.
335 *
336 * @return Concatenated string.
337 */
338 std::string stringify_set(const StringSet &s) const;
339
340 cl::Context _context; /**< Underlying CL context. */
341 cl::Device _device; /**< Underlying CL device. */
342 std::string _kernel_path; /**< Path to the kernels folder. */
343 mutable std::map<std::string, const Program> _programs_map; /**< Map with all already loaded program data. */
344 mutable std::map<std::string, cl::Program> _built_programs_map; /**< Map with all already built program data. */
345 static const std::map<std::string, std::string> _kernel_program_map; /**< Map that associates kernel names with programs. */
346 static const std::map<std::string, std::string> _program_source_map; /**< Contains sources for all programs.
347 Used for compile-time kernel inclusion. >*/
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100348};
349}
350#endif /* __ARM_COMPUTE_CLKERNELLIBRARY_H__ */