Skip to content

Commit a82d236

Browse files
committed
ocl: refactor Program API
- don't store ProgramSource in compiled Programs (resolved problem with "source" buffers lifetime) - completelly remove Program::read/write methods implementation: - replaced with method to query RAW OpenCL binary without any "custom" data - deprecate Program::getPrefix() methods
1 parent 13c4a02 commit a82d236

File tree

2 files changed

+56
-114
lines changed

2 files changed

+56
-114
lines changed

modules/core/include/opencv2/core/ocl.hpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -606,19 +606,14 @@ class CV_EXPORTS Program
606606

607607
bool create(const ProgramSource& src,
608608
const String& buildflags, String& errmsg);
609-
bool read(const String& buf, const String& buildflags); // deprecated
610-
bool write(String& buf) const; // deprecated
611609

612-
const ProgramSource& source() const; // deprecated
613610
void* ptr() const;
614611

615-
String getPrefix() const; // deprecated
616-
static String getPrefix(const String& buildflags); // deprecated
617-
618-
619612
/**
620613
* @brief Query device-specific program binary.
621614
*
615+
* Returns RAW OpenCL executable binary without additional attachments.
616+
*
622617
* @sa ProgramSource::fromBinary
623618
*
624619
* @param[out] binary output buffer
@@ -629,6 +624,15 @@ class CV_EXPORTS Program
629624
inline Impl* getImpl() const { return (Impl*)p; }
630625
protected:
631626
Impl* p;
627+
public:
628+
#ifndef OPENCV_REMOVE_DEPRECATED_API
629+
// TODO Remove this
630+
CV_DEPRECATED bool read(const String& buf, const String& buildflags); // removed, use ProgramSource instead
631+
CV_DEPRECATED bool write(String& buf) const; // removed, use getBinary() method instead (RAW OpenCL binary)
632+
CV_DEPRECATED const ProgramSource& source() const; // implementation removed
633+
CV_DEPRECATED String getPrefix() const; // deprecated, implementation replaced
634+
CV_DEPRECATED static String getPrefix(const String& buildflags); // deprecated, implementation replaced
635+
#endif
632636
};
633637

634638

modules/core/src/ocl.cpp

Lines changed: 45 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -2252,6 +2252,8 @@ struct Context::Impl
22522252
return;
22532253
}
22542254
#endif
2255+
2256+
friend class Program;
22552257
};
22562258

22572259

@@ -3463,19 +3465,20 @@ struct Program::Impl
34633465
{
34643466
IMPLEMENT_REFCOUNTABLE();
34653467

3466-
Impl(const ProgramSource& _src,
3468+
Impl(const ProgramSource& src,
34673469
const String& _buildflags, String& errmsg) :
3468-
src(_src),
3469-
buildflags(_buildflags),
3470-
handle(NULL)
3470+
refcount(1),
3471+
handle(NULL),
3472+
buildflags(_buildflags)
34713473
{
3472-
refcount = 1;
3474+
const ProgramSource::Impl* src_ = src.getImpl();
3475+
CV_Assert(src_);
3476+
sourceModule_ = src_->module_;
3477+
sourceName_ = src_->name_;
34733478
const Context ctx = Context::getDefault();
34743479
Device device = ctx.device(0);
34753480
if (ctx.ptr() == NULL || device.ptr() == NULL)
34763481
return;
3477-
const ProgramSource::Impl* src_ = src.getImpl();
3478-
CV_Assert(src_);
34793482
buildflags = joinBuildOptions(buildflags, src_->buildOptions_);
34803483
if (src.getImpl()->kind_ == ProgramSource::Impl::PROGRAM_SOURCE_CODE)
34813484
{
@@ -3484,13 +3487,12 @@ struct Program::Impl
34843487
else if (device.isIntel())
34853488
buildflags = joinBuildOptions(buildflags, " -D INTEL_DEVICE");
34863489
}
3487-
compile(ctx, errmsg);
3490+
compile(ctx, src_, errmsg);
34883491
}
34893492

3490-
bool compile(const Context& ctx, String& errmsg)
3493+
bool compile(const Context& ctx, const ProgramSource::Impl* src_, String& errmsg)
34913494
{
34923495
CV_Assert(ctx.getImpl());
3493-
const ProgramSource::Impl* src_ = src.getImpl();
34943496
CV_Assert(src_);
34953497

34963498
// We don't cache OpenCL binaries
@@ -3499,13 +3501,12 @@ struct Program::Impl
34993501
bool isLoaded = createFromBinary(ctx, src_->sourceAddr_, src_->sourceSize_, errmsg);
35003502
return isLoaded;
35013503
}
3502-
return compileWithCache(ctx, errmsg);
3504+
return compileWithCache(ctx, src_, errmsg);
35033505
}
35043506

3505-
bool compileWithCache(const Context& ctx, String& errmsg)
3507+
bool compileWithCache(const Context& ctx, const ProgramSource::Impl* src_, String& errmsg)
35063508
{
35073509
CV_Assert(ctx.getImpl());
3508-
const ProgramSource::Impl* src_ = src.getImpl();
35093510
CV_Assert(src_);
35103511
CV_Assert(src_->kind_ != ProgramSource::Impl::PROGRAM_BINARIES);
35113512

@@ -3557,7 +3558,7 @@ struct Program::Impl
35573558
CV_Assert(handle == NULL);
35583559
if (src_->kind_ == ProgramSource::Impl::PROGRAM_SOURCE_CODE)
35593560
{
3560-
if (!buildFromSources(ctx, errmsg))
3561+
if (!buildFromSources(ctx, src_, errmsg))
35613562
{
35623563
return false;
35633564
}
@@ -3648,23 +3649,22 @@ struct Program::Impl
36483649

36493650
errmsg = String(buffer);
36503651
printf("OpenCL program build log: %s/%s\nStatus %d: %s\n%s\n%s\n",
3651-
src.getImpl()->module_.c_str(), src.getImpl()->name_.c_str(),
3652+
sourceModule_.c_str(), sourceName_.c_str(),
36523653
result, getOpenCLErrorString(result),
36533654
buildflags.c_str(), errmsg.c_str());
36543655
fflush(stdout);
36553656
}
36563657

3657-
bool buildFromSources(const Context& ctx, String& errmsg)
3658+
bool buildFromSources(const Context& ctx, const ProgramSource::Impl* src_, String& errmsg)
36583659
{
3659-
const ProgramSource::Impl* src_ = src.getImpl();
36603660
CV_Assert(src_);
36613661
CV_Assert(src_->kind_ == ProgramSource::Impl::PROGRAM_SOURCE_CODE);
36623662
CV_Assert(handle == NULL);
36633663
CV_INSTRUMENT_REGION_OPENCL_COMPILE(cv::format("Build OpenCL program: %s/%s %" PRIx64 " options: %s",
3664-
src_->module_.c_str(), src_->name_.c_str(),
3664+
sourceModule_.c_str(), sourceName_.c_str(),
36653665
src.hash(), buildflags.c_str()).c_str());
36663666

3667-
CV_LOG_VERBOSE(NULL, 0, "Compile... " << src_->module_.c_str() << "/" << src_->name_.c_str());
3667+
CV_LOG_VERBOSE(NULL, 0, "Compile... " << sourceModule_.c_str() << "/" << sourceName_.c_str());
36683668

36693669
const char* srcptr = src_->sourceAddr_ ? ((const char*)src_->sourceAddr_) : src_->codeStr_.c_str();
36703670
size_t srclen = src_->sourceAddr_ ? src_->sourceSize_ : src_->codeStr_.size();
@@ -3721,58 +3721,6 @@ struct Program::Impl
37213721
return handle != NULL;
37223722
}
37233723

3724-
Impl(const String& _buf, const String& _buildflags)
3725-
{
3726-
refcount = 1;
3727-
handle = 0;
3728-
buildflags = _buildflags;
3729-
if(_buf.empty())
3730-
return;
3731-
String prefix0 = Program::getPrefix(buildflags);
3732-
const Context& ctx = Context::getDefault();
3733-
const Device& dev = Device::getDefault();
3734-
const char* pos0 = _buf.c_str();
3735-
const char* pos1 = strchr(pos0, '\n');
3736-
if(!pos1)
3737-
return;
3738-
const char* pos2 = strchr(pos1+1, '\n');
3739-
if(!pos2)
3740-
return;
3741-
const char* pos3 = strchr(pos2+1, '\n');
3742-
if(!pos3)
3743-
return;
3744-
size_t prefixlen = (pos3 - pos0)+1;
3745-
String prefix(pos0, prefixlen);
3746-
if( prefix != prefix0 )
3747-
return;
3748-
const uchar* bin = (uchar*)(pos3+1);
3749-
void* devid = dev.ptr();
3750-
size_t codelen = _buf.length() - prefixlen;
3751-
cl_int binstatus = 0, retval = 0;
3752-
handle = clCreateProgramWithBinary((cl_context)ctx.ptr(), 1, (cl_device_id*)&devid,
3753-
&codelen, &bin, &binstatus, &retval);
3754-
CV_OCL_DBG_CHECK_RESULT(retval, "clCreateProgramWithBinary");
3755-
}
3756-
3757-
String store()
3758-
{
3759-
if(!handle)
3760-
return String();
3761-
size_t progsz = 0, retsz = 0;
3762-
String prefix = Program::getPrefix(buildflags);
3763-
size_t prefixlen = prefix.length();
3764-
if(clGetProgramInfo(handle, CL_PROGRAM_BINARY_SIZES, sizeof(progsz), &progsz, &retsz) != CL_SUCCESS)
3765-
return String();
3766-
AutoBuffer<uchar> bufbuf(prefixlen + progsz + 16);
3767-
uchar* buf = bufbuf;
3768-
memcpy(buf, prefix.c_str(), prefixlen);
3769-
buf += prefixlen;
3770-
if(clGetProgramInfo(handle, CL_PROGRAM_BINARIES, sizeof(buf), &buf, &retsz) != CL_SUCCESS)
3771-
return String();
3772-
buf[progsz] = (uchar)'\0';
3773-
return String((const char*)(uchar*)bufbuf, prefixlen + progsz);
3774-
}
3775-
37763724
void getProgramBinary(std::vector<char>& buf)
37773725
{
37783726
CV_Assert(handle);
@@ -3836,7 +3784,7 @@ struct Program::Impl
38363784
else
38373785
{
38383786
result = clBuildProgram(handle, (cl_uint)ndevices, (cl_device_id*)devices_, buildflags.c_str(), 0, 0);
3839-
CV_OCL_DBG_CHECK_RESULT(result, cv::format("clBuildProgram(binary: %s/%s)", src.getImpl()->module_.c_str(), src.getImpl()->name_.c_str()).c_str());
3787+
CV_OCL_DBG_CHECK_RESULT(result, cv::format("clBuildProgram(binary: %s/%s)", sourceModule_.c_str(), sourceName_.c_str()).c_str());
38403788
if (result != CL_SUCCESS)
38413789
{
38423790
dumpBuildLog_(result, devices, errmsg);
@@ -3905,9 +3853,11 @@ struct Program::Impl
39053853
}
39063854
}
39073855

3908-
ProgramSource src;
3909-
String buildflags;
39103856
cl_program handle;
3857+
3858+
String buildflags;
3859+
String sourceModule_;
3860+
String sourceName_;
39113861
};
39123862

39133863
#else // HAVE_OPENCL
@@ -3969,55 +3919,41 @@ bool Program::create(const ProgramSource& src,
39693919
#endif
39703920
}
39713921

3972-
const ProgramSource& Program::source() const
3922+
void* Program::ptr() const
39733923
{
39743924
#ifdef HAVE_OPENCL
3975-
static ProgramSource dummy;
3976-
return p ? p->src : dummy;
3925+
return p ? p->handle : 0;
39773926
#else
39783927
CV_OPENCL_NO_SUPPORT();
39793928
#endif
39803929
}
39813930

3982-
void* Program::ptr() const
3931+
#ifndef OPENCV_REMOVE_DEPRECATED_API
3932+
const ProgramSource& Program::source() const
39833933
{
3984-
#ifdef HAVE_OPENCL
3985-
return p ? p->handle : 0;
3986-
#else
3987-
CV_OPENCL_NO_SUPPORT();
3988-
#endif
3934+
CV_ErrorNoReturn(Error::StsNotImplemented, "Removed API");
39893935
}
39903936

39913937
bool Program::read(const String& bin, const String& buildflags)
39923938
{
3993-
#ifdef HAVE_OPENCL
3994-
if(p)
3995-
p->release();
3996-
p = new Impl(bin, buildflags);
3997-
return p->handle != 0;
3998-
#else
3999-
CV_OPENCL_NO_SUPPORT();
4000-
#endif
3939+
CV_UNUSED(bin); CV_UNUSED(buildflags);
3940+
CV_ErrorNoReturn(Error::StsNotImplemented, "Removed API");
40013941
}
40023942

40033943
bool Program::write(String& bin) const
40043944
{
4005-
#ifdef HAVE_OPENCL
4006-
if(!p)
4007-
return false;
4008-
bin = p->store();
4009-
return !bin.empty();
4010-
#else
4011-
CV_OPENCL_NO_SUPPORT();
4012-
#endif
3945+
CV_UNUSED(bin);
3946+
CV_ErrorNoReturn(Error::StsNotImplemented, "Removed API");
40133947
}
40143948

40153949
String Program::getPrefix() const
40163950
{
40173951
#ifdef HAVE_OPENCL
40183952
if(!p)
40193953
return String();
4020-
return getPrefix(p->buildflags);
3954+
Context::Impl* ctx_ = Context::getDefault().getImpl();
3955+
CV_Assert(ctx_);
3956+
return cv::format("opencl=%s\nbuildflags=%s", ctx_->getPrefixString().c_str(), p->buildflags.c_str());
40213957
#else
40223958
CV_OPENCL_NO_SUPPORT();
40233959
#endif
@@ -4026,20 +3962,19 @@ String Program::getPrefix() const
40263962
String Program::getPrefix(const String& buildflags)
40273963
{
40283964
#ifdef HAVE_OPENCL
4029-
const Context& ctx = Context::getDefault();
4030-
const Device& dev = ctx.device(0);
4031-
return format("name=%s\ndriver=%s\nbuildflags=%s\n",
4032-
dev.name().c_str(), dev.driverVersion().c_str(), buildflags.c_str());
3965+
Context::Impl* ctx_ = Context::getDefault().getImpl();
3966+
CV_Assert(ctx_);
3967+
return cv::format("opencl=%s\nbuildflags=%s", ctx_->getPrefixString().c_str(), buildflags.c_str());
40333968
#else
4034-
CV_UNUSED(buildflags);
40353969
CV_OPENCL_NO_SUPPORT();
40363970
#endif
40373971
}
3972+
#endif
40383973

40393974
void Program::getBinary(std::vector<char>& binary) const
40403975
{
40413976
#ifdef HAVE_OPENCL
4042-
CV_Assert(p);
3977+
CV_Assert(p && "Empty program");
40433978
p->getProgramBinary(binary);
40443979
#else
40453980
binary.clear();
@@ -4054,7 +3989,10 @@ Program Context::Impl::getProg(const ProgramSource& src,
40543989
size_t limit = getProgramCountLimit();
40553990
const ProgramSource::Impl* src_ = src.getImpl();
40563991
CV_Assert(src_);
4057-
String key = cv::format("module=%s name=%s codehash=%s ", src_->module_.c_str(), src_->name_.c_str(), src_->sourceHash_.c_str()) + Program::getPrefix(buildflags);
3992+
String key = cv::format("module=%s name=%s codehash=%s\nopencl=%s\nbuildflags=%s",
3993+
src_->module_.c_str(), src_->name_.c_str(), src_->sourceHash_.c_str(),
3994+
getPrefixString().c_str(),
3995+
buildflags.c_str());
40583996
{
40593997
cv::AutoLock lock(program_cache_mutex);
40603998
phash_t::iterator it = phash.find(key);

0 commit comments

Comments
 (0)