blob: 4b3c5aa8696989777153994a8f053c529207ac0e [file] [log] [blame]
Anthony Barbier7068f992017-10-26 15:23:08 +01001/*
Michalis Spyroubcfd09a2019-05-01 13:03:59 +01002 * Copyright (c) 2017-2019 ARM Limited.
Anthony Barbier7068f992017-10-26 15:23:08 +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#include "arm_compute/core/GLES_COMPUTE/GCKernelLibrary.h"
25
26#include "arm_compute/core/Error.h"
27#include "arm_compute/core/Utils.h"
28
29#include <fstream>
30#include <iomanip>
31#include <iostream>
32#include <regex>
33#include <utility>
34#include <vector>
35
36using namespace arm_compute;
37
38GCProgram::GCProgram()
39 : _name(), _source()
40{
41}
42
43GCProgram::GCProgram(std::string name, std::string source)
44 : _name(std::move(name)), _source(std::move(source))
45{
46}
47
48GLuint GCProgram::link_program(GLuint shader)
49{
50 GLuint program = ARM_COMPUTE_GL_CHECK(glCreateProgram());
51
52 GLint rvalue;
53 GLsizei length;
54
55 ARM_COMPUTE_GL_CHECK(glAttachShader(program, shader));
56 ARM_COMPUTE_GL_CHECK(glLinkProgram(program));
57 ARM_COMPUTE_GL_CHECK(glDetachShader(program, shader));
58 ARM_COMPUTE_GL_CHECK(glDeleteShader(shader));
59
60 // Check if there were some issues when linking the shader.
61 ARM_COMPUTE_GL_CHECK(glGetProgramiv(program, GL_LINK_STATUS, &rvalue));
62
63 if(rvalue == 0)
64 {
65 ARM_COMPUTE_GL_CHECK(glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length));
66
67 std::vector<GLchar> log(length);
68 ARM_COMPUTE_GL_CHECK(glGetProgramInfoLog(program, length, nullptr, log.data()));
Michalis Spyrou7c60c992019-10-10 14:33:47 +010069 ARM_COMPUTE_ERROR_VAR("Error: Linker log:\n%s\n", log.data());
Anthony Barbier7068f992017-10-26 15:23:08 +010070
71 return 0;
72 }
73
74 ARM_COMPUTE_GL_CHECK(glUseProgram(program));
75
76 return program;
77}
78
79GLuint GCProgram::compile_shader(const std::string &build_options)
80{
81 GLuint shader = ARM_COMPUTE_GL_CHECK(glCreateShader(GL_COMPUTE_SHADER));
82
83 const char *src[]
84 {
85 "#version 310 es\n",
86 build_options.c_str(),
87 _source.c_str()
88 };
89
90 ARM_COMPUTE_GL_CHECK(glShaderSource(shader, sizeof(src) / sizeof(src[0]), src, nullptr));
91
92 ARM_COMPUTE_GL_CHECK(glCompileShader(shader));
93
94 // Check if there were any issues when compiling the shader
95 GLint rvalue;
96 GLsizei length;
97
98 ARM_COMPUTE_GL_CHECK(glGetShaderiv(shader, GL_COMPILE_STATUS, &rvalue));
99
100 if(rvalue == 0)
101 {
102 ARM_COMPUTE_GL_CHECK(glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length));
103
104 std::vector<GLchar> log(length);
105 ARM_COMPUTE_GL_CHECK(glGetShaderInfoLog(shader, length, nullptr, log.data()));
106
107#ifdef ARM_COMPUTE_DEBUG_ENABLED
108 std::istringstream ss(_source);
109 std::stringstream output_stream;
110 std::string line;
111 size_t line_num = 1;
112
113 ARM_COMPUTE_LOG_INFO_MSG_WITH_FORMAT_CORE("GLES Shader build options:\n%s\n", build_options.c_str());
114 while(std::getline(ss, line, '\n'))
115 {
116 output_stream << std::setw(6) << line_num << ": " << line << std::endl;
117 line_num++;
118 }
Joel Liangf1f3ebd2017-11-10 09:59:19 +0800119 ARM_COMPUTE_LOG_INFO_STREAM_CORE("GLES Shader source code:\n"
120 << output_stream.rdbuf());
Anthony Barbier7068f992017-10-26 15:23:08 +0100121#endif /* ARM_COMPUTE_DEBUG_ENABLED */
122
Michalis Spyrou7c60c992019-10-10 14:33:47 +0100123 ARM_COMPUTE_ERROR_VAR("Error: Compiler log:\n%s\n", log.data());
Anthony Barbier7068f992017-10-26 15:23:08 +0100124
125 return 0;
126 }
127
128 return shader;
129}
130
131GCKernel::GCKernel()
Joel Liangf1f3ebd2017-11-10 09:59:19 +0800132 : _name(), _program(), _shader_arguments(), _shader_params_ubo_name(), _shader_params_binding_point(), _shader_params_index(), _shader_params_size()
Anthony Barbier7068f992017-10-26 15:23:08 +0100133{
134}
135
Joel Liang5542ba82017-12-01 15:33:41 +0800136// Add a default destructor in cpp file to workaround the free unallocated value issue on Android
137GCKernel::~GCKernel() // NOLINT
138{
139}
140
Anthony Barbier7068f992017-10-26 15:23:08 +0100141GCKernel::GCKernel(std::string name, GLuint program)
142 : _name(std::move(name)),
143 _program(program),
Joel Liangf1f3ebd2017-11-10 09:59:19 +0800144 _shader_arguments(),
145 _shader_params_ubo_name(0),
Anthony Barbier7068f992017-10-26 15:23:08 +0100146 _shader_params_binding_point(0),
147 _shader_params_index(0),
148 _shader_params_size(0)
149{
Joel Liangf1f3ebd2017-11-10 09:59:19 +0800150 _shader_arguments.clear();
Anthony Barbier7068f992017-10-26 15:23:08 +0100151
Joel Liangf1f3ebd2017-11-10 09:59:19 +0800152 ARM_COMPUTE_GL_CHECK(glGenBuffers(1, &_shader_params_ubo_name));
Anthony Barbier7068f992017-10-26 15:23:08 +0100153
154 _shader_params_index = ARM_COMPUTE_GL_CHECK(glGetUniformBlockIndex(_program, _shader_params_name));
Michalis Spyrou7c60c992019-10-10 14:33:47 +0100155 ARM_COMPUTE_ERROR_ON_MSG_VAR(_shader_params_index == GL_INVALID_INDEX, "Failed to get index of %s", _shader_params_name);
Anthony Barbier7068f992017-10-26 15:23:08 +0100156 ARM_COMPUTE_GL_CHECK(glGetActiveUniformBlockiv(_program, _shader_params_index, GL_UNIFORM_BLOCK_DATA_SIZE, &_shader_params_size));
Michalis Spyrou7c60c992019-10-10 14:33:47 +0100157 ARM_COMPUTE_ERROR_ON_MSG_VAR(_shader_params_size == 0, "Failed to get size of %s", _shader_params_name);
Anthony Barbier7068f992017-10-26 15:23:08 +0100158}
159
160void GCKernel::cleanup()
161{
Joel Liangf1f3ebd2017-11-10 09:59:19 +0800162 ARM_COMPUTE_GL_CHECK(glDeleteBuffers(1, &_shader_params_ubo_name));
Anthony Barbier7068f992017-10-26 15:23:08 +0100163 ARM_COMPUTE_GL_CHECK(glBindBuffer(GL_UNIFORM_BUFFER, 0));
164 ARM_COMPUTE_GL_CHECK(glDeleteProgram(_program));
165 ARM_COMPUTE_GL_CHECK(glUseProgram(0));
166}
167
168void GCKernel::use()
169{
170 ARM_COMPUTE_GL_CHECK(glUseProgram(_program));
171}
172
173void GCKernel::unuse()
174{
175 ARM_COMPUTE_GL_CHECK(glUseProgram(0));
176}
177
178void GCKernel::update_shader_params()
179{
Michalis Spyrou7c60c992019-10-10 14:33:47 +0100180 ARM_COMPUTE_ERROR_ON_MSG_VAR((_shader_params_size != (int)(_shader_arguments.size() * sizeof(_shader_arguments[0]))), "Arguments size (%zu) is not equal to shader params block size (%d)",
181 _shader_arguments.size() * sizeof(_shader_arguments[0]), _shader_params_size);
Anthony Barbier7068f992017-10-26 15:23:08 +0100182
183 ARM_COMPUTE_GL_CHECK(glUniformBlockBinding(_program, _shader_params_index, _shader_params_binding_point));
Joel Liangf1f3ebd2017-11-10 09:59:19 +0800184 ARM_COMPUTE_GL_CHECK(glBindBufferBase(GL_UNIFORM_BUFFER, _shader_params_binding_point, _shader_params_ubo_name));
185 ARM_COMPUTE_GL_CHECK(glBindBuffer(GL_UNIFORM_BUFFER, _shader_params_ubo_name));
186 ARM_COMPUTE_GL_CHECK(glBufferData(GL_UNIFORM_BUFFER, _shader_params_size, _shader_arguments.data(), GL_DYNAMIC_DRAW));
Anthony Barbier7068f992017-10-26 15:23:08 +0100187 ARM_COMPUTE_GL_CHECK(glBindBuffer(GL_UNIFORM_BUFFER, 0));
188}
189
190const std::map<std::string, std::string> GCKernelLibrary::_shader_program_map =
191{
192 { "absdiff", "absdiff.cs" },
Xinghang Zhou33ff9ef2018-01-17 11:23:39 +0800193 { "tensorshift", "tensor_shift.cs" },
Anthony Barbier7068f992017-10-26 15:23:08 +0100194 { "direct_convolution1x1", "direct_convolution1x1.cs" },
195 { "direct_convolution3x3", "direct_convolution3x3.cs" },
196 { "direct_convolution5x5", "direct_convolution5x5.cs" },
197 { "pooling_layer_2", "pooling_layer.cs" },
198 { "pooling_layer_3", "pooling_layer.cs" },
199 { "pooling_layer_7", "pooling_layer.cs" },
200 { "pooling_layer_3_optimized", "pooling_layer.cs" },
201 { "pooling_layer_n", "pooling_layer.cs" },
202 { "fill_image_borders_replicate", "fill_border.cs" },
203 { "fill_image_borders_constant", "fill_border.cs" },
204 { "gemm_accumulate_biases", "gemm.cs" },
205 { "gemm_interleave4x4", "gemm.cs" },
206 { "gemm_ma", "gemm.cs" },
207 { "gemm_mm_interleaved_transposed", "gemm.cs" },
208 { "gemm_mm_floating_point", "gemm.cs" },
209 { "gemm_transpose1x4", "gemm.cs" },
Stephen Lie855c232018-01-04 14:13:22 +0800210 { "reshape_to_columns", "convolution_layer.cs" },
Anthony Barbier7068f992017-10-26 15:23:08 +0100211 { "im2col_kernel3x3_padx0_pady0", "convolution_layer.cs" },
212 { "im2col_generic", "convolution_layer.cs" },
213 { "im2col_reduced", "convolution_layer.cs" },
Stephen Lie855c232018-01-04 14:13:22 +0800214 { "col2im", "convolution_layer.cs" },
Anthony Barbier7068f992017-10-26 15:23:08 +0100215 { "transpose", "transpose.cs" },
216 { "activation_layer", "activation_layer.cs" },
217 { "softmax_layer_max", "softmax_layer.cs" },
218 { "softmax_layer_shift_exp_sum", "softmax_layer.cs" },
219 { "softmax_layer_norm", "softmax_layer.cs" },
220 { "pixelwise_mul_float", "pixelwise_mul_float.cs" },
221 { "normalization_layer", "normalization_layer.cs" },
222 { "batchnormalization_layer", "batchnormalization_layer.cs" },
223 { "concatenate_depth", "concatenate.cs" },
224 { "dropout", "dropout.cs" },
zhenglin0fb6cf52017-12-12 15:56:09 +0800225 { "normalize_planar_yuv_layer", "normalize_planar_yuv_layer.cs" },
Frank Lei57a150a2017-12-19 10:14:57 +0800226 { "scale_nearest_neighbour", "scale.cs" },
zhenglin926d5e12017-12-21 15:36:50 +0800227 { "arithmetic_add", "arithmetic_add.cs" },
Frank Lei8cdfdb82018-01-02 16:49:33 +0800228 { "depthwise_convolution_3x3", "depthwise_convolution3x3.cs" },
Anthony Barbier7068f992017-10-26 15:23:08 +0100229};
230
231const std::map<std::string, std::string> GCKernelLibrary::_program_source_map =
232{
233#ifdef EMBEDDED_KERNELS
234 {
Isabella Gottardi3f217ec2018-02-12 14:59:19 +0000235 "helpers_cs.h",
236#include "./cs_shaders/helpers_cs.hembed"
237 },
238 {
239 "activation_layer_helpers_cs.h",
240#include "./cs_shaders/activation_layer_helpers_cs.hembed"
241 },
242 {
Anthony Barbier7068f992017-10-26 15:23:08 +0100243 "absdiff.cs",
244#include "./cs_shaders/absdiff.csembed"
245 },
246 {
Xinghang Zhou33ff9ef2018-01-17 11:23:39 +0800247 "tensor_shift.cs",
248#include "./cs_shaders/tensor_shift.csembed"
249 },
250 {
Anthony Barbier7068f992017-10-26 15:23:08 +0100251 "convolution_layer.cs",
252#include "./cs_shaders/convolution_layer.csembed"
253 },
254 {
255 "direct_convolution1x1.cs",
256#include "./cs_shaders/direct_convolution1x1.csembed"
257 },
258 {
259 "direct_convolution3x3.cs",
260#include "./cs_shaders/direct_convolution3x3.csembed"
261 },
262 {
263 "direct_convolution5x5.cs",
264#include "./cs_shaders/direct_convolution5x5.csembed"
265 },
266 {
267 "pooling_layer.cs",
268#include "./cs_shaders/pooling_layer.csembed"
269 },
270 {
271 "fill_border.cs",
272#include "./cs_shaders/fill_border.csembed"
273 },
274 {
275 "gemm.cs",
276#include "./cs_shaders/gemm.csembed"
277 },
278 {
279 "transpose.cs",
280#include "./cs_shaders/transpose.csembed"
281 },
282 {
283 "activation_layer.cs",
284#include "./cs_shaders/activation_layer.csembed"
285 },
286 {
287 "softmax_layer.cs",
288#include "./cs_shaders/softmax_layer.csembed"
289 },
290 {
291 "pixelwise_mul_float.cs",
292#include "./cs_shaders/pixelwise_mul_float.csembed"
293 },
294 {
295 "normalization_layer.cs",
296#include "./cs_shaders/normalization_layer.csembed"
297 },
298 {
299 "batchnormalization_layer.cs",
300#include "./cs_shaders/batchnormalization_layer.csembed"
301 },
302 {
303 "concatenate.cs",
304#include "./cs_shaders/concatenate.csembed"
305 },
306 {
307 "dropout.cs",
308#include "./cs_shaders/dropout.csembed"
309 },
zhenglin0fb6cf52017-12-12 15:56:09 +0800310 {
311 "normalize_planar_yuv_layer.cs",
312#include "./cs_shaders/normalize_planar_yuv_layer.csembed"
313 },
Frank Lei57a150a2017-12-19 10:14:57 +0800314 {
315 "scale.cs",
316#include "./cs_shaders/scale.csembed"
317 },
zhenglin926d5e12017-12-21 15:36:50 +0800318 {
319 "arithmetic_add.cs",
320#include "./cs_shaders/arithmetic_add.csembed"
321 },
Frank Lei8cdfdb82018-01-02 16:49:33 +0800322 {
323 "depthwise_convolution3x3.cs",
324#include "./cs_shaders/depthwise_convolution3x3.csembed"
325 },
Anthony Barbier7068f992017-10-26 15:23:08 +0100326#endif /* EMBEDDED_KERNELS */
327};
328
329GCKernelLibrary::GCKernelLibrary()
Ioan-Cristian Szabo77eb21f2017-12-22 17:32:17 +0000330 : _display(EGL_NO_DISPLAY), _context(EGL_NO_CONTEXT), _frame_buffer(0), _tex_rt(0), _shader_path("./"), _programs_map(), _built_programs_map()
Anthony Barbier7068f992017-10-26 15:23:08 +0100331{
332}
333
334GCKernelLibrary &GCKernelLibrary::get()
335{
336 static GCKernelLibrary _kernel_library;
337 return _kernel_library;
338}
339
Georgios Pinitas7ae80a92019-10-25 18:25:17 +0100340void GCKernelLibrary::init(std::string shader_path, EGLDisplay dpy, EGLContext ctx)
341{
342 //TODO: deal with old display and context.
343 _shader_path = std::move(shader_path);
344
345 _display = dpy;
346 _context = ctx;
347
348 eglMakeCurrent(_display, EGL_NO_SURFACE, EGL_NO_SURFACE, _context);
349 setup_dummy_fbo();
350}
351
352void GCKernelLibrary::set_shader_path(const std::string &shader_path)
353{
354 _shader_path = shader_path;
355}
356
357void GCKernelLibrary::set_context(EGLDisplay dpy, EGLContext ctx)
358{
359 //TODO: deal with old display and context.
360 _display = dpy;
361 _context = ctx;
362
363 eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, ctx);
364 setup_dummy_fbo();
365}
366
Anthony Barbier7068f992017-10-26 15:23:08 +0100367GCKernel GCKernelLibrary::create_kernel(const std::string &shader_name, const StringSet &build_options_set) const
368{
369 // Find which program contains the kernel
370 auto shader_program_it = _shader_program_map.find(shader_name);
371
372 if(_shader_program_map.end() == shader_program_it)
373 {
Michalis Spyrou7c60c992019-10-10 14:33:47 +0100374 ARM_COMPUTE_ERROR_VAR("Shader %s not found in the GCKernelLibrary", shader_name.c_str());
Anthony Barbier7068f992017-10-26 15:23:08 +0100375 }
376
377 // Check if the program has been built before with same build options.
378 const std::string program_name = shader_program_it->second;
379 const std::string build_options = stringify_set(build_options_set);
380 const std::string built_program_name = program_name + "_" + build_options;
381 auto built_program_it = _built_programs_map.find(built_program_name);
382
383 GCKernel kernel;
384
385 if(_built_programs_map.end() != built_program_it)
386 {
387 // If program has been built, retrieve to create kernel from it
388 kernel = built_program_it->second;
Anthony Barbier7068f992017-10-26 15:23:08 +0100389 }
390 else
391 {
392 GCProgram program = load_program(program_name);
393
394 std::string source_name = _shader_path + shader_program_it->second;
395
396 // load shader
397 GLuint shader = program.compile_shader(build_options);
398
399 // Build program
400 GLuint gles_program = program.link_program(shader);
401
402 // Create GCKernel
403 kernel = GCKernel(shader_name, gles_program);
404
405 // Add built program to internal map
406 _built_programs_map.emplace(built_program_name, kernel);
407 }
408
Joel Liangf1f3ebd2017-11-10 09:59:19 +0800409 kernel.use();
410 kernel.clear_arguments();
411 // set shader params binding point
412 kernel.set_shader_params_binding_point(0);
413
Anthony Barbier7068f992017-10-26 15:23:08 +0100414 return kernel;
415}
416
Michalis Spyroubcfd09a2019-05-01 13:03:59 +0100417std::string GCKernelLibrary::preprocess_shader(const std::string &shader_source) const
Anthony Barbier7068f992017-10-26 15:23:08 +0100418{
419 enum class ParserStage
420 {
421 FIRST,
422 SKIP_COMMENTS = FIRST,
423 RESOLVE_INCLUDES,
Anthony Barbier7068f992017-10-26 15:23:08 +0100424 LAST
425 };
426
Anthony Barbier7068f992017-10-26 15:23:08 +0100427 // Define a GLES compute shader parser function
428 std::function<std::string(const std::string &, ParserStage, int)> cs_parser;
Michalis Spyroubcfd09a2019-05-01 13:03:59 +0100429 cs_parser = [&](const std::string & src, ParserStage stage, int) -> std::string
Anthony Barbier7068f992017-10-26 15:23:08 +0100430 {
431 std::string dst;
432
433 if(stage == ParserStage::LAST || std::regex_match(src, std::regex(R"(\s*)")))
434 {
435 return src;
436 }
437 auto next_stage = static_cast<ParserStage>(static_cast<int>(stage) + 1);
438
439 std::string search_pattern;
440 switch(stage)
441 {
442 case ParserStage::SKIP_COMMENTS:
443 search_pattern = R"((/\*([^*]|\n|(\*+([^*/]|\n)))*\*+/)|(//.*))";
444 break;
445 case ParserStage::RESOLVE_INCLUDES:
446 search_pattern = R"rgx((?:^|\n)[ \t]*#include "(.*)")rgx";
447 break;
Anthony Barbier7068f992017-10-26 15:23:08 +0100448 default:
449 break;
450 }
451
452 std::regex search_regex(search_pattern);
453 std::smatch match;
454 ptrdiff_t parsed_pos = 0;
455 if(std::regex_search(src, match, search_regex))
456 {
457 // Pass the content before the match to the next stage
458 dst.append(cs_parser(src.substr(0, match.position()), next_stage, 0));
459 parsed_pos = match.position() + match.length();
460
461 // Deal with the matched content
462 switch(stage)
463 {
464 case ParserStage::RESOLVE_INCLUDES:
465 {
466 // Replace with the included file contents
467 // And parse the content from the first stage
468 const std::string source_name = _shader_path + match.str(1);
469 dst.append(cs_parser(read_file(source_name, false), ParserStage::FIRST, 0));
470 break;
471 }
Anthony Barbier7068f992017-10-26 15:23:08 +0100472 case ParserStage::SKIP_COMMENTS:
Anthony Barbier7068f992017-10-26 15:23:08 +0100473 default:
474 dst.append(match.str());
475 break;
476 }
477 next_stage = stage;
478 }
479 dst.append(cs_parser(src.substr(parsed_pos, src.length() - parsed_pos), next_stage, 0));
480
481 return dst;
482 };
483
484 return cs_parser(shader_source, ParserStage::FIRST, 0);
485}
486
487const GCProgram &GCKernelLibrary::load_program(const std::string &program_name) const
488{
489 const auto program_it = _programs_map.find(program_name);
490
491 if(program_it != _programs_map.end())
492 {
493 return program_it->second;
494 }
495
496 GCProgram program;
497
498#ifdef EMBEDDED_KERNELS
499 const auto program_source_it = _program_source_map.find(program_name);
500
501 if(_program_source_map.end() == program_source_it)
502 {
Michalis Spyrou7c60c992019-10-10 14:33:47 +0100503 ARM_COMPUTE_ERROR_VAR("Embedded program for %s does not exist.", program_name.c_str());
Anthony Barbier7068f992017-10-26 15:23:08 +0100504 }
505
Joel Liangabd03cf2018-01-08 15:20:48 +0800506 program = GCProgram(program_name, program_source_it->second);
Anthony Barbier7068f992017-10-26 15:23:08 +0100507#else /* EMBEDDED_KERNELS */
508 // Check for binary
509 std::string source_name = _shader_path + program_name;
510 if(std::ifstream(source_name).is_open())
511 {
512 program = GCProgram(program_name, preprocess_shader(read_file(source_name, false)));
513 }
514 else
515 {
Michalis Spyrou7c60c992019-10-10 14:33:47 +0100516 ARM_COMPUTE_ERROR_VAR("Shader file %s does not exist.", source_name.c_str());
Anthony Barbier7068f992017-10-26 15:23:08 +0100517 }
518#endif /* EMBEDDED_KERNELS */
519
520 // Insert program to program map
521 const auto new_program = _programs_map.emplace(program_name, std::move(program));
522
523 return new_program.first->second;
524}
525
Anthony Barbier7068f992017-10-26 15:23:08 +0100526void GCKernelLibrary::setup_dummy_fbo()
527{
528 ARM_COMPUTE_GL_CHECK(glGenFramebuffers(1, &_frame_buffer));
529 ARM_COMPUTE_GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, _frame_buffer));
530 ARM_COMPUTE_GL_CHECK(glGenTextures(1, &_tex_rt));
531 ARM_COMPUTE_GL_CHECK(glBindTexture(GL_TEXTURE_2D, _tex_rt));
532 ARM_COMPUTE_GL_CHECK(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr));
533 ARM_COMPUTE_GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _tex_rt, 0));
534}
535
536GCKernelLibrary::~GCKernelLibrary()
537{
538 for(auto &program : _built_programs_map)
539 {
540 static_cast<GCKernel>(program.second).cleanup();
541 }
542
543 ARM_COMPUTE_GL_CHECK(glBindTexture(GL_TEXTURE_2D, 0));
544 ARM_COMPUTE_GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0));
545 ARM_COMPUTE_GL_CHECK(glDeleteTextures(1, &_tex_rt));
546 ARM_COMPUTE_GL_CHECK(glDeleteFramebuffers(1, &_frame_buffer));
Anthony Barbier7068f992017-10-26 15:23:08 +0100547}
548
549std::string GCKernelLibrary::stringify_set(const StringSet &s) const
550{
551 std::string concat_set;
552
553 // Concatenate set
554 for(const auto &el : s)
555 {
556 concat_set += el + "\n";
557 }
558
559 return concat_set;
560}