Open Source Computer Vision Library
https://opencv.org/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
756 lines
23 KiB
756 lines
23 KiB
/*M/////////////////////////////////////////////////////////////////////////////////////// |
|
// |
|
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. |
|
// |
|
// By downloading, copying, installing or using the software you agree to this license. |
|
// If you do not agree to this license, do not download, install, |
|
// copy or use the software. |
|
// |
|
// |
|
// License Agreement |
|
// For Open Source Computer Vision Library |
|
// |
|
// Copyright (C) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved. |
|
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. |
|
// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved. |
|
// Third party copyrights are property of their respective owners. |
|
// |
|
// @Authors |
|
// Guoping Long, longguoping@gmail.com |
|
// Niko Li, newlife20080214@gmail.com |
|
// Yao Wang, bitwangyaoyao@gmail.com |
|
// Redistribution and use in source and binary forms, with or without modification, |
|
// are permitted provided that the following conditions are met: |
|
// |
|
// * Redistribution's of source code must retain the above copyright notice, |
|
// this list of conditions and the following disclaimer. |
|
// |
|
// * Redistribution's in binary form must reproduce the above copyright notice, |
|
// this list of conditions and the following disclaimer in the documentation |
|
// and/or other oclMaterials provided with the distribution. |
|
// |
|
// * The name of the copyright holders may not be used to endorse or promote products |
|
// derived from this software without specific prior written permission. |
|
// |
|
// This software is provided by the copyright holders and contributors "as is" and |
|
// any express or implied warranties, including, but not limited to, the implied |
|
// warranties of merchantability and fitness for a particular purpose are disclaimed. |
|
// In no event shall the Intel Corporation or contributors be liable for any direct, |
|
// indirect, incidental, special, exemplary, or consequential damages |
|
// (including, but not limited to, procurement of substitute goods or services; |
|
// loss of use, data, or profits; or business interruption) however caused |
|
// and on any theory of liability, whether in contract, strict liability, |
|
// or tort (including negligence or otherwise) arising in any way out of |
|
// the use of this software, even if advised of the possibility of such damage. |
|
// |
|
//M*/ |
|
|
|
#include "precomp.hpp" |
|
#include <iomanip> |
|
#include <fstream> |
|
#include "cl_programcache.hpp" |
|
|
|
// workaround for OpenCL C++ bindings |
|
#if defined(HAVE_OPENCL12) |
|
#include "opencv2/ocl/cl_runtime/cl_runtime_opencl12_wrappers.hpp" |
|
#elif defined(HAVE_OPENCL11) |
|
#include "opencv2/ocl/cl_runtime/cl_runtime_opencl11_wrappers.hpp" |
|
#else |
|
#error Invalid OpenCL configuration |
|
#endif |
|
|
|
#if defined _MSC_VER && _MSC_VER >= 1200 |
|
#pragma warning( disable: 4100 4101 4127 4244 4267 4510 4512 4610) |
|
#endif |
|
#undef __CL_ENABLE_EXCEPTIONS |
|
#include <CL/cl.hpp> |
|
|
|
namespace cv { |
|
namespace ocl { |
|
|
|
struct PlatformInfoImpl |
|
{ |
|
cl_platform_id platform_id; |
|
|
|
std::vector<int> deviceIDs; |
|
|
|
PlatformInfo info; |
|
|
|
PlatformInfoImpl() |
|
: platform_id(NULL) |
|
{ |
|
} |
|
}; |
|
|
|
struct DeviceInfoImpl |
|
{ |
|
cl_platform_id platform_id; |
|
cl_device_id device_id; |
|
|
|
DeviceInfo info; |
|
|
|
DeviceInfoImpl() |
|
: platform_id(NULL), device_id(NULL) |
|
{ |
|
} |
|
}; |
|
|
|
static std::vector<PlatformInfoImpl> global_platforms; |
|
static std::vector<DeviceInfoImpl> global_devices; |
|
|
|
static bool parseOpenCLVersion(const std::string& versionStr, int& major, int& minor) |
|
{ |
|
size_t p0 = versionStr.find(' '); |
|
while (true) |
|
{ |
|
if (p0 == std::string::npos) |
|
break; |
|
if (p0 + 1 >= versionStr.length()) |
|
break; |
|
char c = versionStr[p0 + 1]; |
|
if (isdigit(c)) |
|
break; |
|
p0 = versionStr.find(' ', p0 + 1); |
|
} |
|
size_t p1 = versionStr.find('.', p0); |
|
size_t p2 = versionStr.find(' ', p1); |
|
if (p0 == std::string::npos || p1 == std::string::npos || p2 == std::string::npos) |
|
{ |
|
major = 0; |
|
minor = 0; |
|
return false; |
|
} |
|
std::string majorStr = versionStr.substr(p0 + 1, p1 - p0 - 1); |
|
std::string minorStr = versionStr.substr(p1 + 1, p2 - p1 - 1); |
|
major = atoi(majorStr.c_str()); |
|
minor = atoi(minorStr.c_str()); |
|
return true; |
|
} |
|
|
|
static void split(const std::string &s, char delim, std::vector<std::string> &elems) { |
|
std::stringstream ss(s); |
|
std::string item; |
|
while (std::getline(ss, item, delim)) { |
|
elems.push_back(item); |
|
} |
|
} |
|
|
|
static std::vector<std::string> split(const std::string &s, char delim) { |
|
std::vector<std::string> elems; |
|
split(s, delim, elems); |
|
return elems; |
|
} |
|
|
|
// Layout: <Platform>:<CPU|GPU|ACCELERATOR|nothing=GPU/CPU>:<deviceName> |
|
// Sample: AMD:GPU: |
|
// Sample: AMD:GPU:Tahiti |
|
// Sample: :GPU|CPU: = '' = ':' = '::' |
|
static bool parseOpenCLDeviceConfiguration(const std::string& configurationStr, |
|
std::string& platform, std::vector<std::string>& deviceTypes, std::string& deviceNameOrID) |
|
{ |
|
std::string deviceTypesStr; |
|
size_t p0 = configurationStr.find(':'); |
|
if (p0 != std::string::npos) |
|
{ |
|
size_t p1 = configurationStr.find(':', p0 + 1); |
|
if (p1 != std::string::npos) |
|
{ |
|
size_t p2 = configurationStr.find(':', p1 + 1); |
|
if (p2 != std::string::npos) |
|
{ |
|
std::cerr << "ERROR: Invalid configuration string for OpenCL device" << std::endl; |
|
return false; |
|
} |
|
else |
|
{ |
|
// assume platform + device types + device name/id |
|
platform = configurationStr.substr(0, p0); |
|
deviceTypesStr = configurationStr.substr(p0 + 1, p1 - (p0 + 1)); |
|
deviceNameOrID = configurationStr.substr(p1 + 1, configurationStr.length() - (p1 + 1)); |
|
} |
|
} |
|
else |
|
{ |
|
// assume platform + device types |
|
platform = configurationStr.substr(0, p0); |
|
deviceTypesStr = configurationStr.substr(p0 + 1, configurationStr.length() - (p0 + 1)); |
|
} |
|
} |
|
else |
|
{ |
|
// assume only platform |
|
platform = configurationStr; |
|
} |
|
deviceTypes = split(deviceTypesStr, '|'); |
|
return true; |
|
} |
|
|
|
static bool __deviceSelected = false; |
|
static bool selectOpenCLDevice() |
|
{ |
|
__deviceSelected = true; |
|
|
|
std::string platform; |
|
std::vector<std::string> deviceTypes; |
|
std::string deviceName; |
|
const char* configuration = getenv("OPENCV_OPENCL_DEVICE"); |
|
if (configuration) |
|
{ |
|
if (!parseOpenCLDeviceConfiguration(std::string(configuration), platform, deviceTypes, deviceName)) |
|
return false; |
|
} |
|
|
|
bool isID = false; |
|
int deviceID = -1; |
|
if (deviceName.length() == 1) |
|
// We limit ID range to 0..9, because we want to write: |
|
// - '2500' to mean i5-2500 |
|
// - '8350' to mean AMD FX-8350 |
|
// - '650' to mean GeForce 650 |
|
// To extend ID range change condition to '> 0' |
|
{ |
|
isID = true; |
|
for (size_t i = 0; i < deviceName.length(); i++) |
|
{ |
|
if (!isdigit(deviceName[i])) |
|
{ |
|
isID = false; |
|
break; |
|
} |
|
} |
|
if (isID) |
|
{ |
|
deviceID = atoi(deviceName.c_str()); |
|
CV_Assert(deviceID >= 0); |
|
} |
|
} |
|
|
|
const PlatformInfo* platformInfo = NULL; |
|
if (platform.length() > 0) |
|
{ |
|
PlatformsInfo platforms; |
|
getOpenCLPlatforms(platforms); |
|
for (size_t i = 0; i < platforms.size(); i++) |
|
{ |
|
if (platforms[i]->platformName.find(platform) != std::string::npos) |
|
{ |
|
platformInfo = platforms[i]; |
|
break; |
|
} |
|
} |
|
if (platformInfo == NULL) |
|
{ |
|
std::cerr << "ERROR: Can't find OpenCL platform by name: " << platform << std::endl; |
|
goto not_found; |
|
} |
|
} |
|
|
|
if (deviceTypes.size() == 0) |
|
{ |
|
if (!isID) |
|
{ |
|
deviceTypes.push_back("GPU"); |
|
deviceTypes.push_back("CPU"); |
|
} |
|
else |
|
{ |
|
deviceTypes.push_back("ALL"); |
|
} |
|
} |
|
for (size_t t = 0; t < deviceTypes.size(); t++) |
|
{ |
|
int deviceType = 0; |
|
if (deviceTypes[t] == "GPU") |
|
{ |
|
deviceType = CVCL_DEVICE_TYPE_GPU; |
|
} |
|
else if (deviceTypes[t] == "CPU") |
|
{ |
|
deviceType = CVCL_DEVICE_TYPE_CPU; |
|
} |
|
else if (deviceTypes[t] == "ACCELERATOR") |
|
{ |
|
deviceType = CVCL_DEVICE_TYPE_ACCELERATOR; |
|
} |
|
else if (deviceTypes[t] == "ALL") |
|
{ |
|
deviceType = CVCL_DEVICE_TYPE_ALL; |
|
} |
|
else |
|
{ |
|
std::cerr << "ERROR: Unsupported device type for OpenCL device (GPU, CPU, ACCELERATOR): " << deviceTypes[t] << std::endl; |
|
goto not_found; |
|
} |
|
|
|
DevicesInfo devices; |
|
getOpenCLDevices(devices, deviceType, platformInfo); |
|
|
|
for (size_t i = (isID ? deviceID : 0); |
|
(isID ? (i == (size_t)deviceID) : true) && (i < devices.size()); |
|
i++) |
|
{ |
|
if (isID || devices[i]->deviceName.find(deviceName) != std::string::npos) |
|
{ |
|
// check for OpenCL 1.1 |
|
if (devices[i]->deviceVersionMajor < 1 || |
|
(devices[i]->deviceVersionMajor == 1 && devices[i]->deviceVersionMinor < 1)) |
|
{ |
|
std::cerr << "Skip unsupported version of OpenCL device: " << devices[i]->deviceName |
|
<< "(" << devices[i]->platform->platformName << ")" << std::endl; |
|
continue; // unsupported version of device, skip it |
|
} |
|
try |
|
{ |
|
setDevice(devices[i]); |
|
} |
|
catch (...) |
|
{ |
|
std::cerr << "ERROR: Can't select OpenCL device: " << devices[i]->deviceName |
|
<< "(" << devices[i]->platform->platformName << ")" << std::endl; |
|
goto not_found; |
|
} |
|
return true; |
|
} |
|
} |
|
} |
|
not_found: |
|
std::cerr << "ERROR: Required OpenCL device not found, check configuration: " << (configuration == NULL ? "" : configuration) << std::endl |
|
<< " Platform: " << (platform.length() == 0 ? "any" : platform) << std::endl |
|
<< " Device types: "; |
|
for (size_t t = 0; t < deviceTypes.size(); t++) |
|
{ |
|
std::cerr << deviceTypes[t] << " "; |
|
} |
|
std::cerr << std::endl << " Device name: " << (deviceName.length() == 0 ? "any" : deviceName) << std::endl; |
|
return false; |
|
} |
|
|
|
static cv::Mutex __initializedMutex; |
|
static bool __initialized = false; |
|
static int initializeOpenCLDevices() |
|
{ |
|
assert(!__initialized); |
|
__initialized = true; |
|
|
|
assert(global_devices.size() == 0); |
|
|
|
std::vector<cl::Platform> platforms; |
|
try |
|
{ |
|
openCLSafeCall(cl::Platform::get(&platforms)); |
|
} |
|
catch (cv::Exception& e) |
|
{ |
|
return 0; // OpenCL not found |
|
} |
|
|
|
global_platforms.resize(platforms.size()); |
|
|
|
for (size_t i = 0; i < platforms.size(); ++i) |
|
{ |
|
PlatformInfoImpl& platformInfo = global_platforms[i]; |
|
platformInfo.info._id = i; |
|
|
|
cl::Platform& platform = platforms[i]; |
|
|
|
platformInfo.platform_id = platform(); |
|
openCLSafeCall(platform.getInfo(CL_PLATFORM_PROFILE, &platformInfo.info.platformProfile)); |
|
openCLSafeCall(platform.getInfo(CL_PLATFORM_VERSION, &platformInfo.info.platformVersion)); |
|
openCLSafeCall(platform.getInfo(CL_PLATFORM_NAME, &platformInfo.info.platformName)); |
|
openCLSafeCall(platform.getInfo(CL_PLATFORM_VENDOR, &platformInfo.info.platformVendor)); |
|
openCLSafeCall(platform.getInfo(CL_PLATFORM_EXTENSIONS, &platformInfo.info.platformExtensons)); |
|
|
|
parseOpenCLVersion(platformInfo.info.platformVersion, |
|
platformInfo.info.platformVersionMajor, platformInfo.info.platformVersionMinor); |
|
|
|
std::vector<cl::Device> devices; |
|
cl_int status = platform.getDevices(CL_DEVICE_TYPE_ALL, &devices); |
|
if(status != CL_DEVICE_NOT_FOUND) |
|
openCLVerifyCall(status); |
|
|
|
if(devices.size() > 0) |
|
{ |
|
int baseIndx = global_devices.size(); |
|
global_devices.resize(baseIndx + devices.size()); |
|
platformInfo.deviceIDs.resize(devices.size()); |
|
platformInfo.info.devices.resize(devices.size()); |
|
|
|
for(size_t j = 0; j < devices.size(); ++j) |
|
{ |
|
cl::Device& device = devices[j]; |
|
|
|
DeviceInfoImpl& deviceInfo = global_devices[baseIndx + j]; |
|
deviceInfo.info._id = baseIndx + j; |
|
deviceInfo.platform_id = platform(); |
|
deviceInfo.device_id = device(); |
|
|
|
deviceInfo.info.platform = &platformInfo.info; |
|
platformInfo.deviceIDs[j] = deviceInfo.info._id; |
|
|
|
cl_device_type type = cl_device_type(-1); |
|
openCLSafeCall(device.getInfo(CL_DEVICE_TYPE, &type)); |
|
deviceInfo.info.deviceType = DeviceType(type); |
|
|
|
openCLSafeCall(device.getInfo(CL_DEVICE_PROFILE, &deviceInfo.info.deviceProfile)); |
|
openCLSafeCall(device.getInfo(CL_DEVICE_VERSION, &deviceInfo.info.deviceVersion)); |
|
openCLSafeCall(device.getInfo(CL_DEVICE_NAME, &deviceInfo.info.deviceName)); |
|
openCLSafeCall(device.getInfo(CL_DEVICE_VENDOR, &deviceInfo.info.deviceVendor)); |
|
cl_uint vendorID = 0; |
|
openCLSafeCall(device.getInfo(CL_DEVICE_VENDOR_ID, &vendorID)); |
|
deviceInfo.info.deviceVendorId = vendorID; |
|
openCLSafeCall(device.getInfo(CL_DRIVER_VERSION, &deviceInfo.info.deviceDriverVersion)); |
|
openCLSafeCall(device.getInfo(CL_DEVICE_EXTENSIONS, &deviceInfo.info.deviceExtensions)); |
|
|
|
parseOpenCLVersion(deviceInfo.info.deviceVersion, |
|
deviceInfo.info.deviceVersionMajor, deviceInfo.info.deviceVersionMinor); |
|
|
|
size_t maxWorkGroupSize = 0; |
|
openCLSafeCall(device.getInfo(CL_DEVICE_MAX_WORK_GROUP_SIZE, &maxWorkGroupSize)); |
|
deviceInfo.info.maxWorkGroupSize = maxWorkGroupSize; |
|
|
|
cl_uint maxDimensions = 0; |
|
openCLSafeCall(device.getInfo(CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, &maxDimensions)); |
|
std::vector<size_t> maxWorkItemSizes(maxDimensions); |
|
openCLSafeCall(clGetDeviceInfo(device(), CL_DEVICE_MAX_WORK_ITEM_SIZES, sizeof(size_t) * maxDimensions, |
|
(void *)&maxWorkItemSizes[0], 0)); |
|
deviceInfo.info.maxWorkItemSizes = maxWorkItemSizes; |
|
|
|
cl_uint maxComputeUnits = 0; |
|
openCLSafeCall(device.getInfo(CL_DEVICE_MAX_COMPUTE_UNITS, &maxComputeUnits)); |
|
deviceInfo.info.maxComputeUnits = maxComputeUnits; |
|
|
|
cl_ulong localMemorySize = 0; |
|
openCLSafeCall(device.getInfo(CL_DEVICE_LOCAL_MEM_SIZE, &localMemorySize)); |
|
deviceInfo.info.localMemorySize = (size_t)localMemorySize; |
|
|
|
|
|
cl_bool unifiedMemory = false; |
|
openCLSafeCall(device.getInfo(CL_DEVICE_HOST_UNIFIED_MEMORY, &unifiedMemory)); |
|
deviceInfo.info.isUnifiedMemory = unifiedMemory != 0; |
|
|
|
//initialize extra options for compilation. Currently only fp64 is included. |
|
//Assume 4KB is enough to store all possible extensions. |
|
openCLSafeCall(device.getInfo(CL_DEVICE_EXTENSIONS, &deviceInfo.info.deviceExtensions)); |
|
|
|
size_t fp64_khr = deviceInfo.info.deviceExtensions.find("cl_khr_fp64"); |
|
if(fp64_khr != std::string::npos) |
|
{ |
|
deviceInfo.info.compilationExtraOptions += "-D DOUBLE_SUPPORT"; |
|
deviceInfo.info.haveDoubleSupport = true; |
|
} |
|
else |
|
{ |
|
deviceInfo.info.haveDoubleSupport = false; |
|
} |
|
} |
|
} |
|
} |
|
|
|
for (size_t i = 0; i < platforms.size(); ++i) |
|
{ |
|
PlatformInfoImpl& platformInfo = global_platforms[i]; |
|
for(size_t j = 0; j < platformInfo.deviceIDs.size(); ++j) |
|
{ |
|
DeviceInfoImpl& deviceInfo = global_devices[platformInfo.deviceIDs[j]]; |
|
platformInfo.info.devices[j] = &deviceInfo.info; |
|
} |
|
} |
|
|
|
return global_devices.size(); |
|
} |
|
|
|
|
|
DeviceInfo::DeviceInfo() |
|
: _id(-1), deviceType(DeviceType(0)), |
|
deviceVendorId(-1), |
|
maxWorkGroupSize(0), maxComputeUnits(0), localMemorySize(0), |
|
deviceVersionMajor(0), deviceVersionMinor(0), |
|
haveDoubleSupport(false), isUnifiedMemory(false), |
|
platform(NULL) |
|
{ |
|
// nothing |
|
} |
|
|
|
PlatformInfo::PlatformInfo() |
|
: _id(-1), |
|
platformVersionMajor(0), platformVersionMinor(0) |
|
{ |
|
// nothing |
|
} |
|
|
|
//////////////////////////////// OpenCL context //////////////////////// |
|
//This is a global singleton class used to represent a OpenCL context. |
|
class ContextImpl : public Context |
|
{ |
|
public: |
|
const cl_device_id clDeviceID; |
|
cl_context clContext; |
|
cl_command_queue clCmdQueue; |
|
const DeviceInfo& deviceInfo; |
|
|
|
protected: |
|
ContextImpl(const DeviceInfo& deviceInfo, cl_device_id clDeviceID) |
|
: clDeviceID(clDeviceID), clContext(NULL), clCmdQueue(NULL), deviceInfo(deviceInfo) |
|
{ |
|
// nothing |
|
} |
|
~ContextImpl(); |
|
public: |
|
static void setContext(const DeviceInfo* deviceInfo); |
|
|
|
bool supportsFeature(FEATURE_TYPE featureType) const; |
|
|
|
static void cleanupContext(void); |
|
}; |
|
|
|
static cv::Mutex currentContextMutex; |
|
static ContextImpl* currentContext = NULL; |
|
|
|
Context* Context::getContext() |
|
{ |
|
if (currentContext == NULL) |
|
{ |
|
if (!__initialized || !__deviceSelected) |
|
{ |
|
cv::AutoLock lock(__initializedMutex); |
|
if (!__initialized) |
|
{ |
|
if (initializeOpenCLDevices() == 0) |
|
{ |
|
CV_Error(CV_OpenCLInitError, "OpenCL not available"); |
|
} |
|
} |
|
if (!__deviceSelected) |
|
{ |
|
if (!selectOpenCLDevice()) |
|
{ |
|
CV_Error(CV_OpenCLInitError, "Can't select OpenCL device"); |
|
} |
|
} |
|
} |
|
CV_Assert(currentContext != NULL); |
|
} |
|
return currentContext; |
|
} |
|
|
|
bool Context::supportsFeature(FEATURE_TYPE featureType) const |
|
{ |
|
return ((ContextImpl*)this)->supportsFeature(featureType); |
|
} |
|
|
|
const DeviceInfo& Context::getDeviceInfo() const |
|
{ |
|
return ((ContextImpl*)this)->deviceInfo; |
|
} |
|
|
|
const void* Context::getOpenCLContextPtr() const |
|
{ |
|
return &(((ContextImpl*)this)->clContext); |
|
} |
|
|
|
const void* Context::getOpenCLCommandQueuePtr() const |
|
{ |
|
return &(((ContextImpl*)this)->clCmdQueue); |
|
} |
|
|
|
const void* Context::getOpenCLDeviceIDPtr() const |
|
{ |
|
return &(((ContextImpl*)this)->clDeviceID); |
|
} |
|
|
|
|
|
bool ContextImpl::supportsFeature(FEATURE_TYPE featureType) const |
|
{ |
|
switch (featureType) |
|
{ |
|
case FEATURE_CL_DOUBLE: |
|
return deviceInfo.haveDoubleSupport; |
|
case FEATURE_CL_UNIFIED_MEM: |
|
return deviceInfo.isUnifiedMemory; |
|
case FEATURE_CL_VER_1_2: |
|
return deviceInfo.deviceVersionMajor > 1 || (deviceInfo.deviceVersionMajor == 1 && deviceInfo.deviceVersionMinor >= 2); |
|
} |
|
CV_Error(CV_StsBadArg, "Invalid feature type"); |
|
return false; |
|
} |
|
|
|
#if defined(WIN32) |
|
static bool __termination = false; |
|
#endif |
|
|
|
ContextImpl::~ContextImpl() |
|
{ |
|
#ifdef WIN32 |
|
// if process is on termination stage (ExitProcess was called and other threads were terminated) |
|
// then disable command queue release because it may cause program hang |
|
if (!__termination) |
|
#endif |
|
{ |
|
if(clCmdQueue) |
|
{ |
|
openCLSafeCall(clReleaseCommandQueue(clCmdQueue)); // some cleanup problems are here |
|
} |
|
|
|
if(clContext) |
|
{ |
|
openCLSafeCall(clReleaseContext(clContext)); |
|
} |
|
} |
|
clCmdQueue = NULL; |
|
clContext = NULL; |
|
} |
|
|
|
void fft_teardown(); |
|
void clBlasTeardown(); |
|
|
|
void ContextImpl::cleanupContext(void) |
|
{ |
|
fft_teardown(); |
|
clBlasTeardown(); |
|
|
|
cv::AutoLock lock(currentContextMutex); |
|
if (currentContext) |
|
delete currentContext; |
|
currentContext = NULL; |
|
} |
|
|
|
void ContextImpl::setContext(const DeviceInfo* deviceInfo) |
|
{ |
|
CV_Assert(deviceInfo->_id >= 0 && deviceInfo->_id < (int)global_devices.size()); |
|
|
|
{ |
|
cv::AutoLock lock(currentContextMutex); |
|
if (currentContext) |
|
{ |
|
if (currentContext->deviceInfo._id == deviceInfo->_id) |
|
return; |
|
} |
|
} |
|
|
|
DeviceInfoImpl& infoImpl = global_devices[deviceInfo->_id]; |
|
CV_Assert(deviceInfo == &infoImpl.info); |
|
|
|
cl_int status = 0; |
|
cl_context_properties cps[3] = { CL_CONTEXT_PLATFORM, (cl_context_properties)(infoImpl.platform_id), 0 }; |
|
cl_context clContext = clCreateContext(cps, 1, &infoImpl.device_id, NULL, NULL, &status); |
|
openCLVerifyCall(status); |
|
// TODO add CL_QUEUE_PROFILING_ENABLE |
|
cl_command_queue clCmdQueue = clCreateCommandQueue(clContext, infoImpl.device_id, 0, &status); |
|
openCLVerifyCall(status); |
|
|
|
ContextImpl* ctx = new ContextImpl(infoImpl.info, infoImpl.device_id); |
|
ctx->clCmdQueue = clCmdQueue; |
|
ctx->clContext = clContext; |
|
|
|
ContextImpl* old = NULL; |
|
{ |
|
cv::AutoLock lock(currentContextMutex); |
|
old = currentContext; |
|
currentContext = ctx; |
|
} |
|
if (old != NULL) |
|
{ |
|
delete old; |
|
} |
|
} |
|
|
|
int getOpenCLPlatforms(PlatformsInfo& platforms) |
|
{ |
|
if (!__initialized) |
|
initializeOpenCLDevices(); |
|
|
|
platforms.clear(); |
|
|
|
for (size_t id = 0; id < global_platforms.size(); ++id) |
|
{ |
|
PlatformInfoImpl& impl = global_platforms[id]; |
|
platforms.push_back(&impl.info); |
|
} |
|
|
|
return platforms.size(); |
|
} |
|
|
|
int getOpenCLDevices(std::vector<const DeviceInfo*> &devices, int deviceType, const PlatformInfo* platform) |
|
{ |
|
if (!__initialized) |
|
initializeOpenCLDevices(); |
|
|
|
devices.clear(); |
|
|
|
switch(deviceType) |
|
{ |
|
case CVCL_DEVICE_TYPE_DEFAULT: |
|
case CVCL_DEVICE_TYPE_CPU: |
|
case CVCL_DEVICE_TYPE_GPU: |
|
case CVCL_DEVICE_TYPE_ACCELERATOR: |
|
case CVCL_DEVICE_TYPE_ALL: |
|
break; |
|
default: |
|
return 0; |
|
} |
|
|
|
if (platform == NULL) |
|
{ |
|
for (size_t id = 0; id < global_devices.size(); ++id) |
|
{ |
|
DeviceInfoImpl& deviceInfo = global_devices[id]; |
|
if (((int)deviceInfo.info.deviceType & deviceType) != 0) |
|
{ |
|
devices.push_back(&deviceInfo.info); |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
for (size_t id = 0; id < platform->devices.size(); ++id) |
|
{ |
|
const DeviceInfo* deviceInfo = platform->devices[id]; |
|
if (((int)deviceInfo->deviceType & deviceType) == deviceType) |
|
{ |
|
devices.push_back(deviceInfo); |
|
} |
|
} |
|
} |
|
|
|
return (int)devices.size(); |
|
} |
|
|
|
void setDevice(const DeviceInfo* info) |
|
{ |
|
if (!__deviceSelected) |
|
__deviceSelected = true; |
|
|
|
ContextImpl::setContext(info); |
|
} |
|
|
|
bool supportsFeature(FEATURE_TYPE featureType) |
|
{ |
|
return Context::getContext()->supportsFeature(featureType); |
|
} |
|
|
|
struct __Module |
|
{ |
|
__Module() { /* moved to Context::getContext(): initializeOpenCLDevices(); */ } |
|
~__Module() { ContextImpl::cleanupContext(); } |
|
}; |
|
static __Module __module; |
|
|
|
|
|
} // namespace ocl |
|
} // namespace cv |
|
|
|
|
|
#if defined(WIN32) && defined(CVAPI_EXPORTS) |
|
|
|
extern "C" |
|
BOOL WINAPI DllMain(HINSTANCE /*hInst*/, DWORD fdwReason, LPVOID lpReserved) |
|
{ |
|
if (fdwReason == DLL_PROCESS_DETACH) |
|
{ |
|
if (lpReserved != NULL) // called after ExitProcess() call |
|
cv::ocl::__termination = true; |
|
} |
|
return TRUE; |
|
} |
|
|
|
#endif
|
|
|