diff --git a/modules/core/include/opencv2/core/ocl.hpp b/modules/core/include/opencv2/core/ocl.hpp index 95f0fcdd66..ca46cdc38a 100644 --- a/modules/core/include/opencv2/core/ocl.hpp +++ b/modules/core/include/opencv2/core/ocl.hpp @@ -720,7 +720,12 @@ public: String name() const; String vendor() const; + + /// See CL_PLATFORM_VERSION String version() const; + int versionMajor() const; + int versionMinor() const; + int deviceNumber() const; void getDevice(Device& device, int d) const; diff --git a/modules/core/src/ocl.cpp b/modules/core/src/ocl.cpp index 24b18dc7f8..8e5612f422 100644 --- a/modules/core/src/ocl.cpp +++ b/modules/core/src/ocl.cpp @@ -1162,25 +1162,27 @@ Platform& Platform::getDefault() /////////////////////////////////////// Device //////////////////////////////////////////// -// deviceVersion has format +// Version has format: // OpenCL // by specification // http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clGetDeviceInfo.html // http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clGetDeviceInfo.html -static void parseDeviceVersion(const String &deviceVersion, int &major, int &minor) +// https://www.khronos.org/registry/OpenCL/sdk/1.1/docs/man/xhtml/clGetPlatformInfo.html +// https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clGetPlatformInfo.html +static void parseOpenCLVersion(const String &version, int &major, int &minor) { major = minor = 0; - if (10 >= deviceVersion.length()) + if (10 >= version.length()) return; - const char *pstr = deviceVersion.c_str(); + const char *pstr = version.c_str(); if (0 != strncmp(pstr, "OpenCL ", 7)) return; - size_t ppos = deviceVersion.find('.', 7); + size_t ppos = version.find('.', 7); if (String::npos == ppos) return; - String temp = deviceVersion.substr(7, ppos - 7); + String temp = version.substr(7, ppos - 7); major = atoi(temp.c_str()); - temp = deviceVersion.substr(ppos + 1); + temp = version.substr(ppos + 1); minor = atoi(temp.c_str()); } @@ -1203,7 +1205,7 @@ struct Device::Impl addressBits_ = getProp(CL_DEVICE_ADDRESS_BITS); String deviceVersion_ = getStrProp(CL_DEVICE_VERSION); - parseDeviceVersion(deviceVersion_, deviceVersionMajor_, deviceVersionMinor_); + parseOpenCLVersion(deviceVersion_, deviceVersionMajor_, deviceVersionMinor_); size_t pos = 0; while (pos < extensions_.size()) @@ -5958,6 +5960,9 @@ struct PlatformInfo::Impl refcount = 1; handle = *(cl_platform_id*)id; getDevices(devices, handle); + + version_ = getStrProp(CL_PLATFORM_VERSION); + parseOpenCLVersion(version_, versionMajor_, versionMinor_); } String getStrProp(cl_platform_info prop) const @@ -5971,6 +5976,10 @@ struct PlatformInfo::Impl IMPLEMENT_REFCOUNTABLE(); std::vector devices; cl_platform_id handle; + + String version_; + int versionMajor_; + int versionMinor_; }; PlatformInfo::PlatformInfo() @@ -6033,7 +6042,19 @@ String PlatformInfo::vendor() const String PlatformInfo::version() const { - return p ? p->getStrProp(CL_PLATFORM_VERSION) : String(); + return p ? p->version_ : String(); +} + +int PlatformInfo::versionMajor() const +{ + CV_Assert(p); + return p->versionMajor_; +} + +int PlatformInfo::versionMinor() const +{ + CV_Assert(p); + return p->versionMinor_; } static void getPlatforms(std::vector& platforms) diff --git a/modules/core/src/opengl.cpp b/modules/core/src/opengl.cpp index dd6f23862b..02f28f5f1a 100644 --- a/modules/core/src/opengl.cpp +++ b/modules/core/src/opengl.cpp @@ -1575,6 +1575,7 @@ void cv::ogl::render(const ogl::Arrays& arr, InputArray indices, int mode, Scala // CL-GL Interoperability #ifdef HAVE_OPENCL +# include "opencv2/core/opencl/runtime/opencl_core.hpp" # include "opencv2/core/opencl/runtime/opencl_gl.hpp" # ifdef cl_khr_gl_sharing # define HAVE_OPENCL_OPENGL_SHARING @@ -1595,6 +1596,34 @@ void cv::ogl::render(const ogl::Arrays& arr, InputArray indices, int mode, Scala namespace cv { namespace ogl { +#if defined(HAVE_OPENCL) && defined(HAVE_OPENGL) && defined(HAVE_OPENCL_OPENGL_SHARING) +// Check to avoid crash in OpenCL runtime: https://github.com/opencv/opencv/issues/5209 +static void checkOpenCLVersion() +{ + using namespace cv::ocl; + const Device& device = Device::getDefault(); + //CV_Assert(!device.empty()); + cl_device_id dev = (cl_device_id)device.ptr(); + CV_Assert(dev); + + cl_platform_id platform_id = 0; + size_t sz = 0; + + cl_int status = clGetDeviceInfo(dev, CL_DEVICE_PLATFORM, sizeof(platform_id), &platform_id, &sz); + CV_Assert(status == CL_SUCCESS && sz == sizeof(cl_platform_id)); + CV_Assert(platform_id); + + PlatformInfo pi(&platform_id); + int versionMajor = pi.versionMajor(); + int versionMinor = pi.versionMinor(); + if (versionMajor < 1 || (versionMajor == 1 && versionMinor <= 1)) + CV_Error_(cv::Error::OpenCLApiCallError, + ("OpenCL: clCreateFromGLTexture requires OpenCL 1.2+ version: %d.%d - %s (%s)", + versionMajor, versionMinor, pi.name().c_str(), pi.version().c_str()) + ); +} +#endif + namespace ocl { Context& initializeContextFromGL() @@ -1714,6 +1743,8 @@ void convertToGLTexture2D(InputArray src, Texture2D& texture) Context& ctx = Context::getDefault(); cl_context context = (cl_context)ctx.ptr(); + checkOpenCLVersion(); // clCreateFromGLTexture requires OpenCL 1.2 + UMat u = src.getUMat(); // TODO Add support for roi @@ -1772,6 +1803,8 @@ void convertFromGLTexture2D(const Texture2D& texture, OutputArray dst) Context& ctx = Context::getDefault(); cl_context context = (cl_context)ctx.ptr(); + checkOpenCLVersion(); // clCreateFromGLTexture requires OpenCL 1.2 + // TODO Need to specify ACCESS_WRITE here somehow to prevent useless data copying! dst.create(texture.size(), textureType); UMat u = dst.getUMat();