ocl: add support for initialization from user-provided OpenCL handles
This commit is contained in:
parent
658282fcbe
commit
17ca7f9545
@ -5,4 +5,7 @@ endif()
|
|||||||
|
|
||||||
set(the_description "OpenCL-accelerated Computer Vision")
|
set(the_description "OpenCL-accelerated Computer Vision")
|
||||||
ocv_define_module(ocl opencv_core opencv_imgproc opencv_features2d opencv_objdetect opencv_video opencv_calib3d opencv_ml "${OPENCL_LIBRARIES}")
|
ocv_define_module(ocl opencv_core opencv_imgproc opencv_features2d opencv_objdetect opencv_video opencv_calib3d opencv_ml "${OPENCL_LIBRARIES}")
|
||||||
|
if(TARGET opencv_test_ocl)
|
||||||
|
target_link_libraries(opencv_test_ocl "${OPENCL_LIBRARIES}")
|
||||||
|
endif()
|
||||||
ocv_warnings_disable(CMAKE_CXX_FLAGS -Wshadow)
|
ocv_warnings_disable(CMAKE_CXX_FLAGS -Wshadow)
|
||||||
|
@ -25,12 +25,26 @@ Returns the list of devices
|
|||||||
|
|
||||||
ocl::setDevice
|
ocl::setDevice
|
||||||
--------------
|
--------------
|
||||||
Returns void
|
Initialize OpenCL computation context
|
||||||
|
|
||||||
.. ocv:function:: void ocl::setDevice( const DeviceInfo* info )
|
.. ocv:function:: void ocl::setDevice( const DeviceInfo* info )
|
||||||
|
|
||||||
:param info: device info
|
:param info: device info
|
||||||
|
|
||||||
|
ocl::initializeContext
|
||||||
|
--------------------------------
|
||||||
|
Alternative way to initialize OpenCL computation context.
|
||||||
|
|
||||||
|
.. ocv:function:: void ocl::initializeContext(void* pClPlatform, void* pClContext, void* pClDevice)
|
||||||
|
|
||||||
|
:param pClPlatform: selected ``platform_id`` (via pointer, parameter type is ``cl_platform_id*``)
|
||||||
|
|
||||||
|
:param pClContext: selected ``cl_context`` (via pointer, parameter type is ``cl_context*``)
|
||||||
|
|
||||||
|
:param pClDevice: selected ``cl_device_id`` (via pointer, parameter type is ``cl_device_id*``)
|
||||||
|
|
||||||
|
This function can be used for context initialization with D3D/OpenGL interoperability.
|
||||||
|
|
||||||
ocl::setBinaryPath
|
ocl::setBinaryPath
|
||||||
------------------
|
------------------
|
||||||
Returns void
|
Returns void
|
||||||
|
@ -118,6 +118,7 @@ namespace cv
|
|||||||
const PlatformInfo* platform;
|
const PlatformInfo* platform;
|
||||||
|
|
||||||
DeviceInfo();
|
DeviceInfo();
|
||||||
|
~DeviceInfo();
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PlatformInfo
|
struct PlatformInfo
|
||||||
@ -136,6 +137,7 @@ namespace cv
|
|||||||
std::vector<const DeviceInfo*> devices;
|
std::vector<const DeviceInfo*> devices;
|
||||||
|
|
||||||
PlatformInfo();
|
PlatformInfo();
|
||||||
|
~PlatformInfo();
|
||||||
};
|
};
|
||||||
|
|
||||||
//////////////////////////////// Initialization & Info ////////////////////////
|
//////////////////////////////// Initialization & Info ////////////////////////
|
||||||
@ -151,6 +153,10 @@ namespace cv
|
|||||||
// set device you want to use
|
// set device you want to use
|
||||||
CV_EXPORTS void setDevice(const DeviceInfo* info);
|
CV_EXPORTS void setDevice(const DeviceInfo* info);
|
||||||
|
|
||||||
|
// Initialize from OpenCL handles directly.
|
||||||
|
// Argument types is (pointers): cl_platform_id*, cl_context*, cl_device_id*
|
||||||
|
CV_EXPORTS void initializeContext(void* pClPlatform, void* pClContext, void* pClDevice);
|
||||||
|
|
||||||
//////////////////////////////// Error handling ////////////////////////
|
//////////////////////////////// Error handling ////////////////////////
|
||||||
CV_EXPORTS void error(const char *error_string, const char *file, const int line, const char *func);
|
CV_EXPORTS void error(const char *error_string, const char *file, const int line, const char *func);
|
||||||
|
|
||||||
|
@ -57,6 +57,8 @@
|
|||||||
namespace cv {
|
namespace cv {
|
||||||
namespace ocl {
|
namespace ocl {
|
||||||
|
|
||||||
|
using namespace cl_utils;
|
||||||
|
|
||||||
#if defined(WIN32)
|
#if defined(WIN32)
|
||||||
static bool __termination = false;
|
static bool __termination = false;
|
||||||
#endif
|
#endif
|
||||||
@ -75,36 +77,10 @@ cv::Mutex& getInitializationMutex()
|
|||||||
return __module.initializationMutex;
|
return __module.initializationMutex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static cv::Mutex& getCurrentContextMutex()
|
||||||
struct PlatformInfoImpl
|
|
||||||
{
|
{
|
||||||
cl_platform_id platform_id;
|
return __module.currentContextMutex;
|
||||||
|
}
|
||||||
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)
|
static bool parseOpenCLVersion(const std::string& versionStr, int& major, int& minor)
|
||||||
{
|
{
|
||||||
@ -135,6 +111,141 @@ static bool parseOpenCLVersion(const std::string& versionStr, int& major, int& m
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct PlatformInfoImpl : public PlatformInfo
|
||||||
|
{
|
||||||
|
cl_platform_id platform_id;
|
||||||
|
|
||||||
|
std::vector<int> deviceIDs;
|
||||||
|
|
||||||
|
PlatformInfoImpl()
|
||||||
|
: platform_id(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void init(int id, cl_platform_id platform)
|
||||||
|
{
|
||||||
|
CV_Assert(platform_id == NULL);
|
||||||
|
|
||||||
|
this->_id = id;
|
||||||
|
platform_id = platform;
|
||||||
|
|
||||||
|
openCLSafeCall(getStringInfo(clGetPlatformInfo, platform, CL_PLATFORM_PROFILE, this->platformProfile));
|
||||||
|
openCLSafeCall(getStringInfo(clGetPlatformInfo, platform, CL_PLATFORM_VERSION, this->platformVersion));
|
||||||
|
openCLSafeCall(getStringInfo(clGetPlatformInfo, platform, CL_PLATFORM_NAME, this->platformName));
|
||||||
|
openCLSafeCall(getStringInfo(clGetPlatformInfo, platform, CL_PLATFORM_VENDOR, this->platformVendor));
|
||||||
|
openCLSafeCall(getStringInfo(clGetPlatformInfo, platform, CL_PLATFORM_EXTENSIONS, this->platformExtensons));
|
||||||
|
|
||||||
|
parseOpenCLVersion(this->platformVersion,
|
||||||
|
this->platformVersionMajor, this->platformVersionMinor);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DeviceInfoImpl: public DeviceInfo
|
||||||
|
{
|
||||||
|
cl_platform_id platform_id;
|
||||||
|
cl_device_id device_id;
|
||||||
|
|
||||||
|
DeviceInfoImpl()
|
||||||
|
: platform_id(NULL), device_id(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void init(int id, PlatformInfoImpl& platformInfoImpl, cl_device_id device)
|
||||||
|
{
|
||||||
|
CV_Assert(device_id == NULL);
|
||||||
|
|
||||||
|
this->_id = id;
|
||||||
|
platform_id = platformInfoImpl.platform_id;
|
||||||
|
device_id = device;
|
||||||
|
|
||||||
|
this->platform = &platformInfoImpl;
|
||||||
|
|
||||||
|
cl_device_type type = cl_device_type(-1);
|
||||||
|
openCLSafeCall(getScalarInfo(clGetDeviceInfo, device, CL_DEVICE_TYPE, type));
|
||||||
|
this->deviceType = DeviceType(type);
|
||||||
|
|
||||||
|
openCLSafeCall(getStringInfo(clGetDeviceInfo, device, CL_DEVICE_PROFILE, this->deviceProfile));
|
||||||
|
openCLSafeCall(getStringInfo(clGetDeviceInfo, device, CL_DEVICE_VERSION, this->deviceVersion));
|
||||||
|
openCLSafeCall(getStringInfo(clGetDeviceInfo, device, CL_DEVICE_NAME, this->deviceName));
|
||||||
|
openCLSafeCall(getStringInfo(clGetDeviceInfo, device, CL_DEVICE_VENDOR, this->deviceVendor));
|
||||||
|
cl_uint vendorID = 0;
|
||||||
|
openCLSafeCall(getScalarInfo(clGetDeviceInfo, device, CL_DEVICE_VENDOR_ID, vendorID));
|
||||||
|
this->deviceVendorId = vendorID;
|
||||||
|
openCLSafeCall(getStringInfo(clGetDeviceInfo, device, CL_DRIVER_VERSION, this->deviceDriverVersion));
|
||||||
|
openCLSafeCall(getStringInfo(clGetDeviceInfo, device, CL_DEVICE_EXTENSIONS, this->deviceExtensions));
|
||||||
|
|
||||||
|
parseOpenCLVersion(this->deviceVersion,
|
||||||
|
this->deviceVersionMajor, this->deviceVersionMinor);
|
||||||
|
|
||||||
|
size_t maxWorkGroupSize = 0;
|
||||||
|
openCLSafeCall(getScalarInfo(clGetDeviceInfo, device, CL_DEVICE_MAX_WORK_GROUP_SIZE, maxWorkGroupSize));
|
||||||
|
this->maxWorkGroupSize = maxWorkGroupSize;
|
||||||
|
|
||||||
|
cl_uint maxDimensions = 0;
|
||||||
|
openCLSafeCall(getScalarInfo(clGetDeviceInfo, device, 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));
|
||||||
|
this->maxWorkItemSizes = maxWorkItemSizes;
|
||||||
|
|
||||||
|
cl_uint maxComputeUnits = 0;
|
||||||
|
openCLSafeCall(getScalarInfo(clGetDeviceInfo, device, CL_DEVICE_MAX_COMPUTE_UNITS, maxComputeUnits));
|
||||||
|
this->maxComputeUnits = maxComputeUnits;
|
||||||
|
|
||||||
|
cl_ulong localMemorySize = 0;
|
||||||
|
openCLSafeCall(getScalarInfo(clGetDeviceInfo, device, CL_DEVICE_LOCAL_MEM_SIZE, localMemorySize));
|
||||||
|
this->localMemorySize = (size_t)localMemorySize;
|
||||||
|
|
||||||
|
cl_ulong maxMemAllocSize = 0;
|
||||||
|
openCLSafeCall(getScalarInfo(clGetDeviceInfo, device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, maxMemAllocSize));
|
||||||
|
this->maxMemAllocSize = (size_t)maxMemAllocSize;
|
||||||
|
|
||||||
|
cl_bool unifiedMemory = false;
|
||||||
|
openCLSafeCall(getScalarInfo(clGetDeviceInfo, device, CL_DEVICE_HOST_UNIFIED_MEMORY, unifiedMemory));
|
||||||
|
this->isUnifiedMemory = unifiedMemory != 0;
|
||||||
|
|
||||||
|
//initialize extra options for compilation. Currently only fp64 is included.
|
||||||
|
//Assume 4KB is enough to store all possible extensions.
|
||||||
|
openCLSafeCall(getStringInfo(clGetDeviceInfo, device, CL_DEVICE_EXTENSIONS, this->deviceExtensions));
|
||||||
|
|
||||||
|
size_t fp64_khr = this->deviceExtensions.find("cl_khr_fp64");
|
||||||
|
if(fp64_khr != std::string::npos)
|
||||||
|
{
|
||||||
|
this->compilationExtraOptions += "-D DOUBLE_SUPPORT";
|
||||||
|
this->haveDoubleSupport = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->haveDoubleSupport = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t intel_platform = platformInfoImpl.platformVendor.find("Intel");
|
||||||
|
if(intel_platform != std::string::npos)
|
||||||
|
{
|
||||||
|
this->compilationExtraOptions += " -D INTEL_DEVICE";
|
||||||
|
this->isIntelDevice = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->isIntelDevice = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (id < 0)
|
||||||
|
{
|
||||||
|
#ifdef CL_VERSION_1_2
|
||||||
|
if (this->deviceVersionMajor > 1 || (this->deviceVersionMajor == 1 && this->deviceVersionMinor >= 2))
|
||||||
|
{
|
||||||
|
::clRetainDevice(device);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static std::vector<PlatformInfoImpl> global_platforms;
|
||||||
|
static std::vector<DeviceInfoImpl> global_devices;
|
||||||
|
|
||||||
static void split(const std::string &s, char delim, std::vector<std::string> &elems) {
|
static void split(const std::string &s, char delim, std::vector<std::string> &elems) {
|
||||||
std::stringstream ss(s);
|
std::stringstream ss(s);
|
||||||
std::string item;
|
std::string item;
|
||||||
@ -333,8 +444,6 @@ not_found:
|
|||||||
static bool __initialized = false;
|
static bool __initialized = false;
|
||||||
static int initializeOpenCLDevices()
|
static int initializeOpenCLDevices()
|
||||||
{
|
{
|
||||||
using namespace cl_utils;
|
|
||||||
|
|
||||||
assert(!__initialized);
|
assert(!__initialized);
|
||||||
__initialized = true;
|
__initialized = true;
|
||||||
|
|
||||||
@ -355,19 +464,9 @@ static int initializeOpenCLDevices()
|
|||||||
for (size_t i = 0; i < platforms.size(); ++i)
|
for (size_t i = 0; i < platforms.size(); ++i)
|
||||||
{
|
{
|
||||||
PlatformInfoImpl& platformInfo = global_platforms[i];
|
PlatformInfoImpl& platformInfo = global_platforms[i];
|
||||||
platformInfo.info._id = i;
|
|
||||||
|
|
||||||
cl_platform_id platform = platforms[i];
|
cl_platform_id platform = platforms[i];
|
||||||
|
platformInfo.init(i, platform);
|
||||||
platformInfo.platform_id = platform;
|
|
||||||
openCLSafeCall(getStringInfo(clGetPlatformInfo, platform, CL_PLATFORM_PROFILE, platformInfo.info.platformProfile));
|
|
||||||
openCLSafeCall(getStringInfo(clGetPlatformInfo, platform, CL_PLATFORM_VERSION, platformInfo.info.platformVersion));
|
|
||||||
openCLSafeCall(getStringInfo(clGetPlatformInfo, platform, CL_PLATFORM_NAME, platformInfo.info.platformName));
|
|
||||||
openCLSafeCall(getStringInfo(clGetPlatformInfo, platform, CL_PLATFORM_VENDOR, platformInfo.info.platformVendor));
|
|
||||||
openCLSafeCall(getStringInfo(clGetPlatformInfo, platform, CL_PLATFORM_EXTENSIONS, platformInfo.info.platformExtensons));
|
|
||||||
|
|
||||||
parseOpenCLVersion(platformInfo.info.platformVersion,
|
|
||||||
platformInfo.info.platformVersionMajor, platformInfo.info.platformVersionMinor);
|
|
||||||
|
|
||||||
std::vector<cl_device_id> devices;
|
std::vector<cl_device_id> devices;
|
||||||
cl_int status = getDevices(platform, CL_DEVICE_TYPE_ALL, devices);
|
cl_int status = getDevices(platform, CL_DEVICE_TYPE_ALL, devices);
|
||||||
@ -379,89 +478,15 @@ static int initializeOpenCLDevices()
|
|||||||
int baseIndx = global_devices.size();
|
int baseIndx = global_devices.size();
|
||||||
global_devices.resize(baseIndx + devices.size());
|
global_devices.resize(baseIndx + devices.size());
|
||||||
platformInfo.deviceIDs.resize(devices.size());
|
platformInfo.deviceIDs.resize(devices.size());
|
||||||
platformInfo.info.devices.resize(devices.size());
|
platformInfo.devices.resize(devices.size());
|
||||||
|
|
||||||
for(size_t j = 0; j < devices.size(); ++j)
|
for(size_t j = 0; j < devices.size(); ++j)
|
||||||
{
|
{
|
||||||
cl_device_id device = devices[j];
|
cl_device_id device = devices[j];
|
||||||
|
|
||||||
DeviceInfoImpl& deviceInfo = global_devices[baseIndx + j];
|
DeviceInfoImpl& deviceInfo = global_devices[baseIndx + j];
|
||||||
deviceInfo.info._id = baseIndx + j;
|
platformInfo.deviceIDs[j] = baseIndx + j;
|
||||||
deviceInfo.platform_id = platform;
|
deviceInfo.init(baseIndx + j, platformInfo, device);
|
||||||
deviceInfo.device_id = device;
|
|
||||||
|
|
||||||
deviceInfo.info.platform = &platformInfo.info;
|
|
||||||
platformInfo.deviceIDs[j] = deviceInfo.info._id;
|
|
||||||
|
|
||||||
cl_device_type type = cl_device_type(-1);
|
|
||||||
openCLSafeCall(getScalarInfo(clGetDeviceInfo, device, CL_DEVICE_TYPE, type));
|
|
||||||
deviceInfo.info.deviceType = DeviceType(type);
|
|
||||||
|
|
||||||
openCLSafeCall(getStringInfo(clGetDeviceInfo, device, CL_DEVICE_PROFILE, deviceInfo.info.deviceProfile));
|
|
||||||
openCLSafeCall(getStringInfo(clGetDeviceInfo, device, CL_DEVICE_VERSION, deviceInfo.info.deviceVersion));
|
|
||||||
openCLSafeCall(getStringInfo(clGetDeviceInfo, device, CL_DEVICE_NAME, deviceInfo.info.deviceName));
|
|
||||||
openCLSafeCall(getStringInfo(clGetDeviceInfo, device, CL_DEVICE_VENDOR, deviceInfo.info.deviceVendor));
|
|
||||||
cl_uint vendorID = 0;
|
|
||||||
openCLSafeCall(getScalarInfo(clGetDeviceInfo, device, CL_DEVICE_VENDOR_ID, vendorID));
|
|
||||||
deviceInfo.info.deviceVendorId = vendorID;
|
|
||||||
openCLSafeCall(getStringInfo(clGetDeviceInfo, device, CL_DRIVER_VERSION, deviceInfo.info.deviceDriverVersion));
|
|
||||||
openCLSafeCall(getStringInfo(clGetDeviceInfo, device, CL_DEVICE_EXTENSIONS, deviceInfo.info.deviceExtensions));
|
|
||||||
|
|
||||||
parseOpenCLVersion(deviceInfo.info.deviceVersion,
|
|
||||||
deviceInfo.info.deviceVersionMajor, deviceInfo.info.deviceVersionMinor);
|
|
||||||
|
|
||||||
size_t maxWorkGroupSize = 0;
|
|
||||||
openCLSafeCall(getScalarInfo(clGetDeviceInfo, device, CL_DEVICE_MAX_WORK_GROUP_SIZE, maxWorkGroupSize));
|
|
||||||
deviceInfo.info.maxWorkGroupSize = maxWorkGroupSize;
|
|
||||||
|
|
||||||
cl_uint maxDimensions = 0;
|
|
||||||
openCLSafeCall(getScalarInfo(clGetDeviceInfo, device, 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(getScalarInfo(clGetDeviceInfo, device, CL_DEVICE_MAX_COMPUTE_UNITS, maxComputeUnits));
|
|
||||||
deviceInfo.info.maxComputeUnits = maxComputeUnits;
|
|
||||||
|
|
||||||
cl_ulong localMemorySize = 0;
|
|
||||||
openCLSafeCall(getScalarInfo(clGetDeviceInfo, device, CL_DEVICE_LOCAL_MEM_SIZE, localMemorySize));
|
|
||||||
deviceInfo.info.localMemorySize = (size_t)localMemorySize;
|
|
||||||
|
|
||||||
cl_ulong maxMemAllocSize = 0;
|
|
||||||
openCLSafeCall(getScalarInfo(clGetDeviceInfo, device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, maxMemAllocSize));
|
|
||||||
deviceInfo.info.maxMemAllocSize = (size_t)maxMemAllocSize;
|
|
||||||
|
|
||||||
cl_bool unifiedMemory = false;
|
|
||||||
openCLSafeCall(getScalarInfo(clGetDeviceInfo, device, 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(getStringInfo(clGetDeviceInfo, device, 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t intel_platform = platformInfo.info.platformVendor.find("Intel");
|
|
||||||
if(intel_platform != std::string::npos)
|
|
||||||
{
|
|
||||||
deviceInfo.info.compilationExtraOptions += " -D INTEL_DEVICE";
|
|
||||||
deviceInfo.info.isIntelDevice = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
deviceInfo.info.isIntelDevice = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -472,7 +497,7 @@ static int initializeOpenCLDevices()
|
|||||||
for(size_t j = 0; j < platformInfo.deviceIDs.size(); ++j)
|
for(size_t j = 0; j < platformInfo.deviceIDs.size(); ++j)
|
||||||
{
|
{
|
||||||
DeviceInfoImpl& deviceInfo = global_devices[platformInfo.deviceIDs[j]];
|
DeviceInfoImpl& deviceInfo = global_devices[platformInfo.deviceIDs[j]];
|
||||||
platformInfo.info.devices[j] = &deviceInfo.info;
|
platformInfo.devices[j] = &deviceInfo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -491,6 +516,8 @@ DeviceInfo::DeviceInfo()
|
|||||||
// nothing
|
// nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DeviceInfo::~DeviceInfo() { }
|
||||||
|
|
||||||
PlatformInfo::PlatformInfo()
|
PlatformInfo::PlatformInfo()
|
||||||
: _id(-1),
|
: _id(-1),
|
||||||
platformVersionMajor(0), platformVersionMinor(0)
|
platformVersionMajor(0), platformVersionMinor(0)
|
||||||
@ -498,6 +525,8 @@ PlatformInfo::PlatformInfo()
|
|||||||
// nothing
|
// nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PlatformInfo::~PlatformInfo() { }
|
||||||
|
|
||||||
class ContextImpl;
|
class ContextImpl;
|
||||||
|
|
||||||
struct CommandQueue
|
struct CommandQueue
|
||||||
@ -535,34 +564,96 @@ cv::TLSData<CommandQueue> commandQueueTLSData;
|
|||||||
class ContextImpl : public Context
|
class ContextImpl : public Context
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
const cl_device_id clDeviceID;
|
cl_device_id clDeviceID;
|
||||||
cl_context clContext;
|
cl_context clContext;
|
||||||
const DeviceInfo& deviceInfo;
|
const DeviceInfoImpl& deviceInfoImpl;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ContextImpl(const DeviceInfo& deviceInfo, cl_device_id clDeviceID)
|
ContextImpl(const DeviceInfoImpl& _deviceInfoImpl, cl_context context)
|
||||||
: clDeviceID(clDeviceID), clContext(NULL), deviceInfo(deviceInfo)
|
: clDeviceID(_deviceInfoImpl.device_id), clContext(context), deviceInfoImpl(_deviceInfoImpl)
|
||||||
{
|
{
|
||||||
// nothing
|
#ifdef CL_VERSION_1_2
|
||||||
|
if (supportsFeature(FEATURE_CL_VER_1_2))
|
||||||
|
{
|
||||||
|
openCLSafeCall(clRetainDevice(clDeviceID));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
openCLSafeCall(clRetainContext(clContext));
|
||||||
|
|
||||||
|
ContextImpl* old = NULL;
|
||||||
|
{
|
||||||
|
cv::AutoLock lock(getCurrentContextMutex());
|
||||||
|
old = currentContext;
|
||||||
|
currentContext = this;
|
||||||
|
}
|
||||||
|
if (old != NULL)
|
||||||
|
{
|
||||||
|
delete old;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
~ContextImpl()
|
||||||
|
{
|
||||||
|
CV_Assert(this != currentContext);
|
||||||
|
|
||||||
|
#ifdef CL_VERSION_1_2
|
||||||
|
if (supportsFeature(FEATURE_CL_VER_1_2))
|
||||||
|
{
|
||||||
|
openCLSafeCall(clReleaseDevice(clDeviceID));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (deviceInfoImpl._id < 0) // not in the global registry, so we should cleanup it
|
||||||
|
{
|
||||||
|
#ifdef CL_VERSION_1_2
|
||||||
|
if (supportsFeature(FEATURE_CL_VER_1_2))
|
||||||
|
{
|
||||||
|
openCLSafeCall(clReleaseDevice(deviceInfoImpl.device_id));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
PlatformInfoImpl* platformImpl = (PlatformInfoImpl*)(deviceInfoImpl.platform);
|
||||||
|
delete platformImpl;
|
||||||
|
delete const_cast<DeviceInfoImpl*>(&deviceInfoImpl);
|
||||||
|
}
|
||||||
|
clDeviceID = NULL;
|
||||||
|
|
||||||
|
#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(clContext)
|
||||||
|
{
|
||||||
|
openCLSafeCall(clReleaseContext(clContext));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clContext = NULL;
|
||||||
}
|
}
|
||||||
~ContextImpl();
|
|
||||||
public:
|
public:
|
||||||
static void setContext(const DeviceInfo* deviceInfo);
|
static void setContext(const DeviceInfo* deviceInfo);
|
||||||
|
static void initializeContext(void* pClPlatform, void* pClContext, void* pClDevice);
|
||||||
|
|
||||||
bool supportsFeature(FEATURE_TYPE featureType) const;
|
bool supportsFeature(FEATURE_TYPE featureType) const;
|
||||||
|
|
||||||
static void cleanupContext(void);
|
static void cleanupContext(void);
|
||||||
|
|
||||||
|
static ContextImpl* getContext();
|
||||||
private:
|
private:
|
||||||
ContextImpl(const ContextImpl&); // disabled
|
ContextImpl(const ContextImpl&); // disabled
|
||||||
ContextImpl& operator=(const ContextImpl&); // disabled
|
ContextImpl& operator=(const ContextImpl&); // disabled
|
||||||
|
|
||||||
|
static ContextImpl* currentContext;
|
||||||
};
|
};
|
||||||
|
|
||||||
static ContextImpl* currentContext = NULL;
|
ContextImpl* ContextImpl::currentContext = NULL;
|
||||||
|
|
||||||
static bool __deviceSelected = false;
|
static bool __deviceSelected = false;
|
||||||
|
|
||||||
Context* Context::getContext()
|
Context* Context::getContext()
|
||||||
|
{
|
||||||
|
return ContextImpl::getContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
ContextImpl* ContextImpl::getContext()
|
||||||
{
|
{
|
||||||
if (currentContext == NULL)
|
if (currentContext == NULL)
|
||||||
{
|
{
|
||||||
@ -606,7 +697,7 @@ bool Context::supportsFeature(FEATURE_TYPE featureType) const
|
|||||||
|
|
||||||
const DeviceInfo& Context::getDeviceInfo() const
|
const DeviceInfo& Context::getDeviceInfo() const
|
||||||
{
|
{
|
||||||
return ((ContextImpl*)this)->deviceInfo;
|
return ((ContextImpl*)this)->deviceInfoImpl;
|
||||||
}
|
}
|
||||||
|
|
||||||
const void* Context::getOpenCLContextPtr() const
|
const void* Context::getOpenCLContextPtr() const
|
||||||
@ -636,34 +727,18 @@ bool ContextImpl::supportsFeature(FEATURE_TYPE featureType) const
|
|||||||
switch (featureType)
|
switch (featureType)
|
||||||
{
|
{
|
||||||
case FEATURE_CL_INTEL_DEVICE:
|
case FEATURE_CL_INTEL_DEVICE:
|
||||||
return deviceInfo.isIntelDevice;
|
return deviceInfoImpl.isIntelDevice;
|
||||||
case FEATURE_CL_DOUBLE:
|
case FEATURE_CL_DOUBLE:
|
||||||
return deviceInfo.haveDoubleSupport;
|
return deviceInfoImpl.haveDoubleSupport;
|
||||||
case FEATURE_CL_UNIFIED_MEM:
|
case FEATURE_CL_UNIFIED_MEM:
|
||||||
return deviceInfo.isUnifiedMemory;
|
return deviceInfoImpl.isUnifiedMemory;
|
||||||
case FEATURE_CL_VER_1_2:
|
case FEATURE_CL_VER_1_2:
|
||||||
return deviceInfo.deviceVersionMajor > 1 || (deviceInfo.deviceVersionMajor == 1 && deviceInfo.deviceVersionMinor >= 2);
|
return deviceInfoImpl.deviceVersionMajor > 1 || (deviceInfoImpl.deviceVersionMajor == 1 && deviceInfoImpl.deviceVersionMinor >= 2);
|
||||||
}
|
}
|
||||||
CV_Error(CV_StsBadArg, "Invalid feature type");
|
CV_Error(CV_StsBadArg, "Invalid feature type");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
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(clContext)
|
|
||||||
{
|
|
||||||
openCLSafeCall(clReleaseContext(clContext));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
clContext = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void fft_teardown();
|
void fft_teardown();
|
||||||
void clBlasTeardown();
|
void clBlasTeardown();
|
||||||
|
|
||||||
@ -672,46 +747,58 @@ void ContextImpl::cleanupContext(void)
|
|||||||
fft_teardown();
|
fft_teardown();
|
||||||
clBlasTeardown();
|
clBlasTeardown();
|
||||||
|
|
||||||
cv::AutoLock lock(__module.currentContextMutex);
|
cv::AutoLock lock(getCurrentContextMutex());
|
||||||
if (currentContext)
|
if (currentContext)
|
||||||
delete currentContext;
|
{
|
||||||
currentContext = NULL;
|
ContextImpl* ctx = currentContext;
|
||||||
|
currentContext = NULL;
|
||||||
|
delete ctx;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContextImpl::setContext(const DeviceInfo* deviceInfo)
|
void ContextImpl::setContext(const DeviceInfo* deviceInfo)
|
||||||
{
|
{
|
||||||
CV_Assert(deviceInfo->_id >= 0 && deviceInfo->_id < (int)global_devices.size());
|
CV_Assert(deviceInfo->_id >= 0); // we can't specify custom devices
|
||||||
|
CV_Assert(deviceInfo->_id < (int)global_devices.size());
|
||||||
|
|
||||||
{
|
{
|
||||||
cv::AutoLock lock(__module.currentContextMutex);
|
cv::AutoLock lock(getCurrentContextMutex());
|
||||||
if (currentContext)
|
if (currentContext)
|
||||||
{
|
{
|
||||||
if (currentContext->deviceInfo._id == deviceInfo->_id)
|
if (currentContext->deviceInfoImpl._id == deviceInfo->_id)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DeviceInfoImpl& infoImpl = global_devices[deviceInfo->_id];
|
DeviceInfoImpl& infoImpl = global_devices[deviceInfo->_id];
|
||||||
CV_Assert(deviceInfo == &infoImpl.info);
|
CV_Assert(deviceInfo == &infoImpl);
|
||||||
|
|
||||||
cl_int status = 0;
|
cl_int status = 0;
|
||||||
cl_context_properties cps[3] = { CL_CONTEXT_PLATFORM, (cl_context_properties)(infoImpl.platform_id), 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);
|
cl_context clContext = clCreateContext(cps, 1, &infoImpl.device_id, NULL, NULL, &status);
|
||||||
openCLVerifyCall(status);
|
openCLVerifyCall(status);
|
||||||
|
|
||||||
ContextImpl* ctx = new ContextImpl(infoImpl.info, infoImpl.device_id);
|
ContextImpl* ctx = new ContextImpl(infoImpl, clContext);
|
||||||
ctx->clContext = clContext;
|
clReleaseContext(clContext);
|
||||||
|
(void)ctx;
|
||||||
|
}
|
||||||
|
|
||||||
ContextImpl* old = NULL;
|
void ContextImpl::initializeContext(void* pClPlatform, void* pClContext, void* pClDevice)
|
||||||
{
|
{
|
||||||
cv::AutoLock lock(__module.currentContextMutex);
|
CV_Assert(pClPlatform != NULL);
|
||||||
old = currentContext;
|
CV_Assert(pClContext != NULL);
|
||||||
currentContext = ctx;
|
CV_Assert(pClDevice != NULL);
|
||||||
}
|
cl_platform_id platform = *(cl_platform_id*)pClPlatform;
|
||||||
if (old != NULL)
|
cl_context context = *(cl_context*)pClContext;
|
||||||
{
|
cl_device_id device = *(cl_device_id*)pClDevice;
|
||||||
delete old;
|
|
||||||
}
|
PlatformInfoImpl* platformInfoImpl = new PlatformInfoImpl();
|
||||||
|
platformInfoImpl->init(-1, platform);
|
||||||
|
DeviceInfoImpl* deviceInfoImpl = new DeviceInfoImpl();
|
||||||
|
deviceInfoImpl->init(-1, *platformInfoImpl, device);
|
||||||
|
|
||||||
|
ContextImpl* ctx = new ContextImpl(*deviceInfoImpl, context);
|
||||||
|
(void)ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandQueue::create(ContextImpl* context)
|
void CommandQueue::create(ContextImpl* context)
|
||||||
@ -735,7 +822,7 @@ int getOpenCLPlatforms(PlatformsInfo& platforms)
|
|||||||
for (size_t id = 0; id < global_platforms.size(); ++id)
|
for (size_t id = 0; id < global_platforms.size(); ++id)
|
||||||
{
|
{
|
||||||
PlatformInfoImpl& impl = global_platforms[id];
|
PlatformInfoImpl& impl = global_platforms[id];
|
||||||
platforms.push_back(&impl.info);
|
platforms.push_back(&impl);
|
||||||
}
|
}
|
||||||
|
|
||||||
return platforms.size();
|
return platforms.size();
|
||||||
@ -765,9 +852,9 @@ int getOpenCLDevices(std::vector<const DeviceInfo*> &devices, int deviceType, co
|
|||||||
for (size_t id = 0; id < global_devices.size(); ++id)
|
for (size_t id = 0; id < global_devices.size(); ++id)
|
||||||
{
|
{
|
||||||
DeviceInfoImpl& deviceInfo = global_devices[id];
|
DeviceInfoImpl& deviceInfo = global_devices[id];
|
||||||
if (((int)deviceInfo.info.deviceType & deviceType) != 0)
|
if (((int)deviceInfo.deviceType & deviceType) != 0)
|
||||||
{
|
{
|
||||||
devices.push_back(&deviceInfo.info);
|
devices.push_back(&deviceInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -800,6 +887,20 @@ void setDevice(const DeviceInfo* info)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void initializeContext(void* pClPlatform, void* pClContext, void* pClDevice)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ContextImpl::initializeContext(pClPlatform, pClContext, pClDevice);
|
||||||
|
__deviceSelected = true;
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
__deviceSelected = true;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool supportsFeature(FEATURE_TYPE featureType)
|
bool supportsFeature(FEATURE_TYPE featureType)
|
||||||
{
|
{
|
||||||
return Context::getContext()->supportsFeature(featureType);
|
return Context::getContext()->supportsFeature(featureType);
|
||||||
|
@ -40,7 +40,7 @@
|
|||||||
//M*/
|
//M*/
|
||||||
|
|
||||||
#include "test_precomp.hpp"
|
#include "test_precomp.hpp"
|
||||||
#include "opencv2/ocl/cl_runtime/cl_runtime.hpp" // for OpenCL types: cl_mem
|
#include "opencv2/ocl/cl_runtime/cl_runtime.hpp" // for OpenCL types & functions
|
||||||
|
|
||||||
TEST(TestAPI, openCLExecuteKernelInterop)
|
TEST(TestAPI, openCLExecuteKernelInterop)
|
||||||
{
|
{
|
||||||
@ -78,3 +78,87 @@ TEST(TestAPI, openCLExecuteKernelInterop)
|
|||||||
|
|
||||||
EXPECT_LE(checkNorm(cpuMat, dst), 1e-3);
|
EXPECT_LE(checkNorm(cpuMat, dst), 1e-3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This test must be DISABLED by default!
|
||||||
|
// (We can't restore original context for other tests)
|
||||||
|
TEST(TestAPI, DISABLED_InitializationFromHandles)
|
||||||
|
{
|
||||||
|
#define MAX_PLATFORMS 16
|
||||||
|
cl_platform_id platforms[MAX_PLATFORMS] = { NULL };
|
||||||
|
cl_uint numPlatforms = 0;
|
||||||
|
cl_int status = ::clGetPlatformIDs(MAX_PLATFORMS, &platforms[0], &numPlatforms);
|
||||||
|
ASSERT_EQ(CL_SUCCESS, status) << "clGetPlatformIDs";
|
||||||
|
ASSERT_NE(0, (int)numPlatforms);
|
||||||
|
|
||||||
|
int selectedPlatform = 0;
|
||||||
|
cl_platform_id platform = platforms[selectedPlatform];
|
||||||
|
|
||||||
|
ASSERT_NE((void*)NULL, platform);
|
||||||
|
|
||||||
|
cl_device_id device = NULL;
|
||||||
|
status = ::clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, 1, &device, NULL);
|
||||||
|
ASSERT_EQ(CL_SUCCESS, status) << "clGetDeviceIDs";
|
||||||
|
ASSERT_NE((void*)NULL, device);
|
||||||
|
|
||||||
|
cl_context_properties cps[3] = { CL_CONTEXT_PLATFORM, (cl_context_properties)(platform), 0 };
|
||||||
|
cl_context context = ::clCreateContext(cps, 1, &device, NULL, NULL, &status);
|
||||||
|
ASSERT_EQ(CL_SUCCESS, status) << "clCreateContext";
|
||||||
|
ASSERT_NE((void*)NULL, context);
|
||||||
|
|
||||||
|
ASSERT_NO_THROW(cv::ocl::initializeContext(&platform, &context, &device));
|
||||||
|
|
||||||
|
status = ::clReleaseContext(context);
|
||||||
|
ASSERT_EQ(CL_SUCCESS, status) << "clReleaseContext";
|
||||||
|
|
||||||
|
#ifdef CL_VERSION_1_2
|
||||||
|
#if 1
|
||||||
|
{
|
||||||
|
cv::ocl::Context* ctx = cv::ocl::Context::getContext();
|
||||||
|
ASSERT_NE((void*)NULL, ctx);
|
||||||
|
if (ctx->supportsFeature(cv::ocl::FEATURE_CL_VER_1_2)) // device supports OpenCL 1.2+
|
||||||
|
{
|
||||||
|
status = ::clReleaseDevice(device);
|
||||||
|
ASSERT_EQ(CL_SUCCESS, status) << "clReleaseDevice";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else // code below doesn't work on Linux (SEGFAULTs on 1.1- devices are not handled via exceptions)
|
||||||
|
try
|
||||||
|
{
|
||||||
|
status = ::clReleaseDevice(device); // NOTE This works only with !DEVICES! that supports OpenCL 1.2
|
||||||
|
(void)status; // no check
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
// nothing, there is no problem
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// print the name of current device
|
||||||
|
cv::ocl::Context* ctx = cv::ocl::Context::getContext();
|
||||||
|
ASSERT_NE((void*)NULL, ctx);
|
||||||
|
const cv::ocl::DeviceInfo& deviceInfo = ctx->getDeviceInfo();
|
||||||
|
std::cout << "Device name: " << deviceInfo.deviceName << std::endl;
|
||||||
|
std::cout << "Platform name: " << deviceInfo.platform->platformName << std::endl;
|
||||||
|
|
||||||
|
ASSERT_EQ(context, *(cl_context*)ctx->getOpenCLContextPtr());
|
||||||
|
ASSERT_EQ(device, *(cl_device_id*)ctx->getOpenCLDeviceIDPtr());
|
||||||
|
|
||||||
|
// do some calculations and check results
|
||||||
|
cv::RNG rng;
|
||||||
|
Size sz(100, 100);
|
||||||
|
cv::Mat srcMat = cvtest::randomMat(rng, sz, CV_32FC4, -10, 10, false);
|
||||||
|
cv::Mat dstMat;
|
||||||
|
|
||||||
|
cv::ocl::oclMat srcGpuMat(srcMat);
|
||||||
|
cv::ocl::oclMat dstGpuMat;
|
||||||
|
|
||||||
|
cv::Scalar v = cv::Scalar::all(1);
|
||||||
|
cv::add(srcMat, v, dstMat);
|
||||||
|
cv::ocl::add(srcGpuMat, v, dstGpuMat);
|
||||||
|
|
||||||
|
cv::Mat dstGpuMatMap;
|
||||||
|
dstGpuMat.download(dstGpuMatMap);
|
||||||
|
|
||||||
|
EXPECT_LE(checkNorm(dstMat, dstGpuMatMap), 1e-3);
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user