From 77eb21f7d9c6e34e985dfa96152fb8b6c40f9a8a Mon Sep 17 00:00:00 2001 From: Ioan-Cristian Szabo Date: Fri, 22 Dec 2017 17:32:17 +0000 Subject: Fix destruction order of singleton objects and resolve hang GLES issue. Change-Id: I9df42d4255b371b275a74aa521406e6796ee436b Reviewed-on: https://eu-gerrit-1.euhpc.arm.com/113901 Reviewed-by: Anthony Barbier Tested-by: Anthony Barbier --- arm_compute/core/GLES_COMPUTE/GCKernelLibrary.h | 14 +---- arm_compute/runtime/CL/CLScheduler.h | 3 + arm_compute/runtime/GLES_COMPUTE/GCScheduler.h | 24 ++++++-- src/core/GLES_COMPUTE/GCKernelLibrary.cpp | 64 +-------------------- src/runtime/CL/CLScheduler.cpp | 5 +- src/runtime/GLES_COMPUTE/GCScheduler.cpp | 74 ++++++++++++++++++++++++- 6 files changed, 100 insertions(+), 84 deletions(-) diff --git a/arm_compute/core/GLES_COMPUTE/GCKernelLibrary.h b/arm_compute/core/GLES_COMPUTE/GCKernelLibrary.h index db2d979156..34bd5673b8 100644 --- a/arm_compute/core/GLES_COMPUTE/GCKernelLibrary.h +++ b/arm_compute/core/GLES_COMPUTE/GCKernelLibrary.h @@ -191,14 +191,13 @@ class GCKernelLibrary private: /** Default Constructor. */ GCKernelLibrary(); + ~GCKernelLibrary(); public: /** Prevent instances of this class from being copied. */ GCKernelLibrary(const GCKernelLibrary &) = delete; /** Prevent instances of this class from being copied. */ const GCKernelLibrary &operator=(const GCKernelLibrary &) = delete; - /** Default Destructor. */ - ~GCKernelLibrary(); static GCKernelLibrary &get(); /** Initialises the kernel library. @@ -215,13 +214,6 @@ public: _display = dpy; _context = ctx; - if(_display == EGL_NO_DISPLAY || _context == EGL_NO_CONTEXT) - { - setup_context(); - - _own_context = true; - } - eglMakeCurrent(_display, EGL_NO_SURFACE, EGL_NO_SURFACE, _context); setup_dummy_fbo(); } @@ -289,15 +281,11 @@ private: * @return Concatenated string. */ std::string stringify_set(const StringSet &s) const; - /** Set up EGL context. - */ - void setup_context(); EGLDisplay _display; /**< Underlying EGL Display. */ EGLContext _context; /**< Underlying EGL Context. */ GLuint _frame_buffer; /**< Dummy fbo */ GLuint _tex_rt; /**< Dummy texture for render target */ - bool _own_context; /**< Self created context or not. */ std::string _shader_path; /**< Path to the shaders folder. */ mutable std::map _programs_map; /**< Map with all already loaded program data. */ mutable std::map _built_programs_map; /**< Map with all already built program data. */ diff --git a/arm_compute/runtime/CL/CLScheduler.h b/arm_compute/runtime/CL/CLScheduler.h index 1a7befc046..f700bbb679 100644 --- a/arm_compute/runtime/CL/CLScheduler.h +++ b/arm_compute/runtime/CL/CLScheduler.h @@ -199,6 +199,9 @@ private: */ cl::NDRange tune_kernel(ICLKernel &kernel); + /** Flag to ensure symbols initialisation is happening before Scheduler creation */ + static std::once_flag _initialize_symbols; + cl::Context _context; cl::CommandQueue _queue; GPUTarget _target; diff --git a/arm_compute/runtime/GLES_COMPUTE/GCScheduler.h b/arm_compute/runtime/GLES_COMPUTE/GCScheduler.h index 817f8b54b1..8aac9c4023 100644 --- a/arm_compute/runtime/GLES_COMPUTE/GCScheduler.h +++ b/arm_compute/runtime/GLES_COMPUTE/GCScheduler.h @@ -35,10 +35,6 @@ class IGCKernel; /** Provides global access to a OpenGL ES context and command queue. */ class GCScheduler { -private: - /** Constructor */ - GCScheduler(); - public: /** Access the scheduler singleton. * @@ -67,7 +63,25 @@ public: /** Blocks until all commands in the associated command queue have finished. */ void sync(); + +private: + /** Constructor */ + GCScheduler(); + /** Destructor */ + ~GCScheduler(); + /** Prevent instances of this class from being copied */ + GCScheduler(const GCScheduler &) = delete; + /** Prevent instances of this class from being copied */ + GCScheduler &operator=(const GCScheduler &) = delete; + + /** Set up EGL context */ + void setup_context(); + + /** Flag to ensure symbols initialisation is happening before Scheduler creation */ + static std::once_flag _initialize_symbols; + + EGLDisplay _display; /**< Underlying EGL Display. */ + EGLContext _context; /**< Underlying EGL Context. */ }; } - #endif /* __ARM_COMPUTE_GCSCHEDULER_H__ */ diff --git a/src/core/GLES_COMPUTE/GCKernelLibrary.cpp b/src/core/GLES_COMPUTE/GCKernelLibrary.cpp index 484c8aadfb..549c869bfe 100644 --- a/src/core/GLES_COMPUTE/GCKernelLibrary.cpp +++ b/src/core/GLES_COMPUTE/GCKernelLibrary.cpp @@ -298,7 +298,7 @@ const std::map GCKernelLibrary::_program_source_map = }; GCKernelLibrary::GCKernelLibrary() - : _display(EGL_NO_DISPLAY), _context(EGL_NO_CONTEXT), _frame_buffer(0), _tex_rt(0), _own_context(false), _shader_path("./"), _programs_map(), _built_programs_map() + : _display(EGL_NO_DISPLAY), _context(EGL_NO_CONTEXT), _frame_buffer(0), _tex_rt(0), _shader_path("./"), _programs_map(), _built_programs_map() { } @@ -632,59 +632,6 @@ const GCProgram &GCKernelLibrary::load_program(const std::string &program_name) return new_program.first->second; } -void GCKernelLibrary::setup_context() -{ - EGLBoolean res; - _display = eglGetDisplay(EGL_DEFAULT_DISPLAY); - - ARM_COMPUTE_ERROR_ON_MSG(_display == EGL_NO_DISPLAY, "Failed to get display: 0x%x.", eglGetError()); - - res = eglInitialize(_display, nullptr, nullptr); - - ARM_COMPUTE_ERROR_ON_MSG(res == EGL_FALSE, "Failed to initialize egl: 0x%x.", eglGetError()); - ARM_COMPUTE_UNUSED(res); - - const char *egl_extension_st = eglQueryString(_display, EGL_EXTENSIONS); - ARM_COMPUTE_ERROR_ON_MSG((strstr(egl_extension_st, "EGL_KHR_create_context") == nullptr), "Failed to query EGL_KHR_create_context"); - ARM_COMPUTE_ERROR_ON_MSG((strstr(egl_extension_st, "EGL_KHR_surfaceless_context") == nullptr), "Failed to query EGL_KHR_surfaceless_context"); - ARM_COMPUTE_UNUSED(egl_extension_st); - - const EGLint config_attribs[] = - { - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT_KHR, - EGL_NONE - }; - EGLConfig cfg; - EGLint count; - - res = eglChooseConfig(_display, config_attribs, &cfg, 1, &count); - - ARM_COMPUTE_ERROR_ON_MSG(res == EGL_FALSE, "Failed to choose config: 0x%x.", eglGetError()); - ARM_COMPUTE_UNUSED(res); - - res = eglBindAPI(EGL_OPENGL_ES_API); - - ARM_COMPUTE_ERROR_ON_MSG(res == EGL_FALSE, "Failed to bind api: 0x%x.", eglGetError()); - - const EGLint attribs[] = - { - EGL_CONTEXT_CLIENT_VERSION, 3, - EGL_NONE - }; - _context = eglCreateContext(_display, - cfg, - EGL_NO_CONTEXT, - attribs); - - ARM_COMPUTE_ERROR_ON_MSG(_context == EGL_NO_CONTEXT, "Failed to create context: 0x%x.", eglGetError()); - ARM_COMPUTE_UNUSED(res); - - res = eglMakeCurrent(_display, EGL_NO_SURFACE, EGL_NO_SURFACE, _context); - - ARM_COMPUTE_ERROR_ON_MSG(res == EGL_FALSE, "Failed to make current: 0x%x.", eglGetError()); - ARM_COMPUTE_UNUSED(res); -} - void GCKernelLibrary::setup_dummy_fbo() { ARM_COMPUTE_GL_CHECK(glGenFramebuffers(1, &_frame_buffer)); @@ -706,15 +653,6 @@ GCKernelLibrary::~GCKernelLibrary() ARM_COMPUTE_GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0)); ARM_COMPUTE_GL_CHECK(glDeleteTextures(1, &_tex_rt)); ARM_COMPUTE_GL_CHECK(glDeleteFramebuffers(1, &_frame_buffer)); - - if(_own_context) - { - eglDestroyContext(_display, _context); - eglTerminate(_display); - - _context = EGL_NO_CONTEXT; - _display = EGL_NO_DISPLAY; - } } std::string GCKernelLibrary::stringify_set(const StringSet &s) const diff --git a/src/runtime/CL/CLScheduler.cpp b/src/runtime/CL/CLScheduler.cpp index 71a749fe52..bf13a25693 100644 --- a/src/runtime/CL/CLScheduler.cpp +++ b/src/runtime/CL/CLScheduler.cpp @@ -28,6 +28,8 @@ using namespace arm_compute; +std::once_flag CLScheduler::_initialize_symbols; + CLScheduler::CLScheduler() : _context(), _queue(), _target(GPUTarget::MIDGARD), _is_initialised(false), _cl_tuner() { @@ -35,6 +37,7 @@ CLScheduler::CLScheduler() CLScheduler &CLScheduler::get() { + std::call_once(_initialize_symbols, opencl_is_available); static CLScheduler scheduler; return scheduler; } @@ -59,4 +62,4 @@ void CLScheduler::enqueue(ICLKernel &kernel, bool flush) { _queue.flush(); } -} \ No newline at end of file +} diff --git a/src/runtime/GLES_COMPUTE/GCScheduler.cpp b/src/runtime/GLES_COMPUTE/GCScheduler.cpp index b2235ea6f9..f19b43348d 100644 --- a/src/runtime/GLES_COMPUTE/GCScheduler.cpp +++ b/src/runtime/GLES_COMPUTE/GCScheduler.cpp @@ -28,11 +28,27 @@ using namespace arm_compute; -GCScheduler::GCScheduler() = default; +std::once_flag GCScheduler::_initialize_symbols; + +GCScheduler::GCScheduler() + : _display(EGL_NO_DISPLAY), _context(EGL_NO_CONTEXT) +{ +} + +GCScheduler::~GCScheduler() +{ + eglDestroyContext(_display, _context); + eglTerminate(_display); + + _context = EGL_NO_CONTEXT; + _display = EGL_NO_DISPLAY; +} void GCScheduler::default_init() { - GCKernelLibrary::get().init("./cs_shaders/"); + setup_context(); + + GCKernelLibrary::get().init("./cs_shaders/", _display, _context); } void GCScheduler::init(EGLDisplay dpy, EGLContext ctx) @@ -42,6 +58,7 @@ void GCScheduler::init(EGLDisplay dpy, EGLContext ctx) GCScheduler &GCScheduler::get() { + std::call_once(_initialize_symbols, opengles31_is_available); static GCScheduler scheduler; return scheduler; } @@ -59,3 +76,56 @@ void GCScheduler::sync() { ARM_COMPUTE_GL_CHECK(glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT)); } + +void GCScheduler::setup_context() +{ + EGLBoolean res; + _display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + + ARM_COMPUTE_ERROR_ON_MSG(_display == EGL_NO_DISPLAY, "Failed to get display: 0x%x.", eglGetError()); + + res = eglInitialize(_display, nullptr, nullptr); + + ARM_COMPUTE_ERROR_ON_MSG(res == EGL_FALSE, "Failed to initialize egl: 0x%x.", eglGetError()); + ARM_COMPUTE_UNUSED(res); + + const char *egl_extension_st = eglQueryString(_display, EGL_EXTENSIONS); + ARM_COMPUTE_ERROR_ON_MSG((strstr(egl_extension_st, "EGL_KHR_create_context") == nullptr), "Failed to query EGL_KHR_create_context"); + ARM_COMPUTE_ERROR_ON_MSG((strstr(egl_extension_st, "EGL_KHR_surfaceless_context") == nullptr), "Failed to query EGL_KHR_surfaceless_context"); + ARM_COMPUTE_UNUSED(egl_extension_st); + + const EGLint config_attribs[] = + { + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT_KHR, + EGL_NONE + }; + EGLConfig cfg; + EGLint count; + + res = eglChooseConfig(_display, config_attribs, &cfg, 1, &count); + + ARM_COMPUTE_ERROR_ON_MSG(res == EGL_FALSE, "Failed to choose config: 0x%x.", eglGetError()); + ARM_COMPUTE_UNUSED(res); + + res = eglBindAPI(EGL_OPENGL_ES_API); + + ARM_COMPUTE_ERROR_ON_MSG(res == EGL_FALSE, "Failed to bind api: 0x%x.", eglGetError()); + + const EGLint attribs[] = + { + EGL_CONTEXT_CLIENT_VERSION, 3, + EGL_NONE + }; + _context = eglCreateContext(_display, + cfg, + EGL_NO_CONTEXT, + attribs); + + ARM_COMPUTE_ERROR_ON_MSG(_context == EGL_NO_CONTEXT, "Failed to create context: 0x%x.", eglGetError()); + ARM_COMPUTE_UNUSED(res); + + res = eglMakeCurrent(_display, EGL_NO_SURFACE, EGL_NO_SURFACE, _context); + + ARM_COMPUTE_ERROR_ON_MSG(res == EGL_FALSE, "Failed to make current: 0x%x.", eglGetError()); + ARM_COMPUTE_UNUSED(res); +} -- cgit v1.2.1