blob: 4d4565d6fda5f17dbba13e73c428b53d3c26aeaf [file] [log] [blame]
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001/*
2 * Copyright (c) 2016, 2017 ARM Limited.
3 *
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{
36/** Program class */
37class Program
38{
39public:
40 /** Default constructor. */
41 Program();
42 /** Construct program from source file.
43 *
44 * @param[in] context CL context used to create the program.
45 * @param[in] name Program name.
46 * @param[in] source Program source.
47 */
48 Program(cl::Context context, std::string name, std::string source);
49 /** Construct program from binary file.
50 *
51 * @param[in] context CL context used to create the program.
52 * @param[in] device CL device for which the programs are created.
53 * @param[in] name Program name.
54 * @param[in] binary Program binary.
55 */
56 Program(cl::Context context, cl::Device device, std::string name, std::vector<unsigned char> binary);
57 /** Default Copy Constructor. */
58 Program(const Program &) = default;
59 /** Default Move Constructor. */
60 Program(Program &&) = default;
61 /** Default copy assignment operator. */
62 Program &operator=(const Program &) = default;
63 /** Default move assignment operator. */
64 Program &operator=(Program &&) = default;
65 /**Returns program name.
66 *
67 * @return Program's name.
68 */
69 std::string name() const
70 {
71 return _name;
72 }
73 /** User-defined conversion to the underlying CL program.
74 *
75 * @return The CL program object.
76 */
77 explicit operator cl::Program() const;
78
79 static bool build(const cl::Program &program, const std::string &build_options = "");
80 /** Build the underlying CL program.
81 *
82 * @param[in] build_options Options used to build the CL program.
83 *
84 * @return A reference to itself.
85 */
86 cl::Program build(const std::string &build_options = "") const;
87
88private:
89 cl::Context _context; /**< Underlying CL context. */
90 cl::Device _device; /**< CL device for which the programs are created. */
91 bool _is_binary; /**< Create program from binary? */
92 std::string _name; /**< Program name. */
93 std::string _source; /**< Source code for the program. */
94 std::vector<unsigned char> _binary; /**< Binary from which to create the program. */
95};
96
97/** Kernel class */
98class Kernel
99{
100public:
101 /** Default Constructor. */
102 Kernel();
103 /** Default Copy Constructor. */
104 Kernel(const Kernel &) = default;
105 /** Default Move Constructor. */
106 Kernel(Kernel &&) = default;
107 /** Default copy assignment operator. */
108 Kernel &operator=(const Kernel &) = default;
109 /** Default move assignment operator. */
110 Kernel &operator=(Kernel &&) = default;
111 /** Constructor.
112 *
113 * @param[in] name Kernel name.
114 * @param[in] program Built program.
115 */
116 Kernel(std::string name, const cl::Program &program);
117 /** Returns kernel name.
118 *
119 * @return Kernel's name.
120 */
121 std::string name() const
122 {
123 return _name;
124 }
125 /** Returns OpenCL kernel.
126 *
127 * @return OpenCL Kernel.
128 */
129 explicit operator cl::Kernel() const
130 {
131 return _kernel;
132 }
133
134private:
135 std::string _name; /**< Kernel name */
136 cl::Kernel _kernel; /**< OpenCL Kernel */
137};
138
139/** CLKernelLibrary class */
140class CLKernelLibrary
141{
142 using StringSet = std::set<std::string>;
143
144private:
145 /** Default Constructor. */
146 CLKernelLibrary();
147
148public:
149 /** Prevent instances of this class from being copied. */
150 CLKernelLibrary(const CLKernelLibrary &) = delete;
151 /** Prevent instances of this class from being copied. */
152 const CLKernelLibrary &operator=(const CLKernelLibrary &) = delete;
153 /** Access the KernelLibrary singleton.
154 * @return The KernelLibrary instance.
155 */
156 static CLKernelLibrary &get();
157 /** Initialises the kernel library.
158 *
159 * @param[in] kernel_path (Optional) Path of the directory from which kernel sources are loaded.
160 * @param[in] context (Optional) CL context used to create programs.
161 * @param[in] device (Optional) CL device for which the programs are created.
162 */
163 void init(std::string kernel_path = ".", cl::Context context = cl::Context::getDefault(), cl::Device device = cl::Device::getDefault())
164 {
steniu015f910722017-08-23 10:15:22 +0100165 _kernel_path = std::move(kernel_path);
166 _context = std::move(context);
167 _device = std::move(device);
168 _max_workgroup_size = 0;
169 max_local_workgroup_size();
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100170 }
171 /** Sets the path that the kernels reside in.
172 *
173 * @param[in] kernel_path Path of the kernel.
174 */
175 void set_kernel_path(const std::string &kernel_path)
176 {
177 _kernel_path = kernel_path;
178 };
Michalis Spyroud7e82812017-06-20 15:00:14 +0100179 /** Gets the path that the kernels reside in.
180 */
181 std::string get_kernel_path()
182 {
183 return _kernel_path;
184 };
185 /** Gets the source of the selected program
186 *
187 * @param[in] program_name Program name.
188 */
189 std::string get_program_source(const std::string &program_name);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100190 /** Sets the CL context used to create programs.
191 *
192 * @note Setting the context also resets the device to the
193 * first one available in the new context.
194 *
195 * @param[in] context A CL context.
196 */
197 void set_context(cl::Context context)
198 {
199 _context = std::move(context);
200
201 const auto cl_devices = _context.getInfo<CL_CONTEXT_DEVICES>();
202
203 if(cl_devices.empty())
204 {
205 _device = cl::Device();
206 }
207 else
208 {
209 _device = cl_devices[0];
210 }
steniu015f910722017-08-23 10:15:22 +0100211
212 _max_workgroup_size = 0;
213 max_local_workgroup_size();
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100214 };
215 /** Sets the CL device for which the programs are created.
216 *
217 * @param[in] device A CL device.
218 */
219 void set_device(cl::Device device)
220 {
steniu015f910722017-08-23 10:15:22 +0100221 _device = std::move(device);
222 _max_workgroup_size = 0;
223 max_local_workgroup_size();
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100224 };
225 /** Creates a kernel from the kernel library.
226 *
227 * @param[in] kernel_name Kernel name.
228 * @param[in] build_options_set Kernel build options as a set.
229 *
230 * @return The created kernel.
231 */
232 Kernel create_kernel(const std::string &kernel_name, const StringSet &build_options_set = {}) const;
233 /** Serializes and saves programs to a binary.
234 *
235 */
236 void save_binary();
237 /** Load serialized binary with all the programs.
238 *
239 */
240 void load_binary();
steniu015f910722017-08-23 10:15:22 +0100241 /** Find the maximum number of local work items in a workgroup can be supported by the device
242 *
243 */
244 size_t max_local_workgroup_size();
245
246 /** Return the default NDRange that is suitable for the device.
247 *
248 */
249 cl::NDRange default_ndrange();
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100250
251private:
252 /** Load program and its dependencies.
253 *
254 * @param[in] program_name Name of the program to load.
255 */
256 const Program &load_program(const std::string &program_name) const;
257 /** Concatenates contents of a set into a single string.
258 *
259 * @param[in] s Input set to concatenate.
260 *
261 * @return Concatenated string.
262 */
263 std::string stringify_set(const StringSet &s) const;
264
265 cl::Context _context; /**< Underlying CL context. */
266 cl::Device _device; /**< Underlying CL device. */
267 std::string _kernel_path; /**< Path to the kernels folder. */
268 mutable std::map<std::string, const Program> _programs_map; /**< Map with all already loaded program data. */
269 mutable std::map<std::string, cl::Program> _built_programs_map; /**< Map with all already built program data. */
270 static const std::map<std::string, std::string> _kernel_program_map; /**< Map that associates kernel names with programs. */
271 static const std::map<std::string, std::string> _program_source_map; /**< Contains sources for all programs.
272 Used for compile-time kernel inclusion. >*/
steniu015f910722017-08-23 10:15:22 +0100273 size_t _max_workgroup_size; /** Maximum local workgroup size supported on the device */
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100274};
275}
276#endif /* __ARM_COMPUTE_CLKERNELLIBRARY_H__ */