From 740b1f235e6832e15be2061df5411e318945d6b4 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Wed, 11 Dec 2013 18:49:50 +0400 Subject: [PATCH] ocl: implemented per-thread OpenCL command queue --- modules/ocl/src/cl_context.cpp | 72 ++++++++++++++++++++++++++++++++---------- 1 file changed, 55 insertions(+), 17 deletions(-) diff --git a/modules/ocl/src/cl_context.cpp b/modules/ocl/src/cl_context.cpp index ef9611d..7ab39cb 100644 --- a/modules/ocl/src/cl_context.cpp +++ b/modules/ocl/src/cl_context.cpp @@ -57,6 +57,10 @@ namespace cv { namespace ocl { +#if defined(WIN32) +static bool __termination = false; +#endif + struct __Module { __Module(); @@ -494,6 +498,38 @@ PlatformInfo::PlatformInfo() // nothing } +class ContextImpl; + +struct CommandQueue +{ + ContextImpl* context_; + cl_command_queue clQueue_; + + CommandQueue() : context_(NULL), clQueue_(NULL) { } + ~CommandQueue() { release(); } + + void create(ContextImpl* context_); + void release() + { +#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(clQueue_) + { + openCLSafeCall(clReleaseCommandQueue(clQueue_)); // some cleanup problems are here + } + + } + clQueue_ = NULL; + context_ = NULL; + } +}; + +cv::TLSData commandQueueTLSData; + //////////////////////////////// OpenCL context //////////////////////// //This is a global singleton class used to represent a OpenCL context. class ContextImpl : public Context @@ -501,12 +537,11 @@ 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) + : clDeviceID(clDeviceID), clContext(NULL), deviceInfo(deviceInfo) { // nothing } @@ -581,7 +616,13 @@ const void* Context::getOpenCLContextPtr() const const void* Context::getOpenCLCommandQueuePtr() const { - return &(((ContextImpl*)this)->clCmdQueue); + ContextImpl* pThis = (ContextImpl*)this; + CommandQueue* commandQueue = commandQueueTLSData.get(); + if (commandQueue->context_ != pThis) + { + commandQueue->create(pThis); + } + return &commandQueue->clQueue_; } const void* Context::getOpenCLDeviceIDPtr() const @@ -607,10 +648,6 @@ bool ContextImpl::supportsFeature(FEATURE_TYPE featureType) const return false; } -#if defined(WIN32) -static bool __termination = false; -#endif - ContextImpl::~ContextImpl() { #ifdef WIN32 @@ -619,17 +656,11 @@ ContextImpl::~ContextImpl() if (!__termination) #endif { - if(clCmdQueue) - { - openCLSafeCall(clReleaseCommandQueue(clCmdQueue)); // some cleanup problems are here - } - if(clContext) { openCLSafeCall(clReleaseContext(clContext)); } } - clCmdQueue = NULL; clContext = NULL; } @@ -667,12 +698,8 @@ void ContextImpl::setContext(const DeviceInfo* deviceInfo) 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; @@ -687,6 +714,17 @@ void ContextImpl::setContext(const DeviceInfo* deviceInfo) } } +void CommandQueue::create(ContextImpl* context) +{ + release(); + cl_int status = 0; + // TODO add CL_QUEUE_PROFILING_ENABLE + cl_command_queue clCmdQueue = clCreateCommandQueue(context->clContext, context->clDeviceID, 0, &status); + openCLVerifyCall(status); + context_ = context; + clQueue_ = clCmdQueue; +} + int getOpenCLPlatforms(PlatformsInfo& platforms) { if (!__initialized) -- 2.7.4