Skip to content

Commit 44699c5

Browse files
committed
Merge pull request opencv#9799 from alalek:ocl_program
2 parents fee87ea + 6be2572 commit 44699c5

File tree

2 files changed

+171
-140
lines changed

2 files changed

+171
-140
lines changed

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -613,8 +613,10 @@ class CV_EXPORTS Program
613613
String getPrefix() const;
614614
static String getPrefix(const String& buildflags);
615615

616-
protected:
616+
617617
struct Impl;
618+
inline Impl* getImpl() const { return (Impl*)p; }
619+
protected:
618620
Impl* p;
619621
};
620622

@@ -635,8 +637,9 @@ class CV_EXPORTS ProgramSource
635637
const String& source() const;
636638
hash_t hash() const; // deprecated
637639

638-
protected:
639640
struct Impl;
641+
inline Impl* getImpl() const { return (Impl*)p; }
642+
protected:
640643
Impl* p;
641644
};
642645

modules/core/src/ocl.cpp

Lines changed: 166 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -2489,25 +2489,156 @@ size_t Kernel::localMemSize() const
24892489
sizeof(val), &val, &retsz) == CL_SUCCESS ? (size_t)val : 0;
24902490
}
24912491

2492+
2493+
2494+
///////////////////////////////////////// ProgramSource ///////////////////////////////////////////////
2495+
2496+
struct ProgramSource::Impl
2497+
{
2498+
Impl(const String& src)
2499+
{
2500+
init(cv::String(), cv::String(), src, cv::String());
2501+
}
2502+
Impl(const String& module, const String& name, const String& codeStr, const String& codeHash)
2503+
{
2504+
init(module, name, codeStr, codeHash);
2505+
}
2506+
void init(const String& module, const String& name, const String& codeStr, const String& codeHash)
2507+
{
2508+
refcount = 1;
2509+
module_ = module;
2510+
name_ = name;
2511+
codeStr_ = codeStr;
2512+
codeHash_ = codeHash;
2513+
2514+
isHashUpdated = false;
2515+
if (codeHash_.empty())
2516+
{
2517+
updateHash();
2518+
codeHash_ = cv::format("%08llx", hash_);
2519+
}
2520+
}
2521+
2522+
void updateHash()
2523+
{
2524+
hash_ = crc64((uchar*)codeStr_.c_str(), codeStr_.size());
2525+
isHashUpdated = true;
2526+
}
2527+
2528+
IMPLEMENT_REFCOUNTABLE();
2529+
2530+
String module_;
2531+
String name_;
2532+
String codeStr_;
2533+
String codeHash_;
2534+
// TODO std::vector<ProgramSource> includes_;
2535+
2536+
bool isHashUpdated;
2537+
ProgramSource::hash_t hash_;
2538+
};
2539+
2540+
2541+
ProgramSource::ProgramSource()
2542+
{
2543+
p = 0;
2544+
}
2545+
2546+
ProgramSource::ProgramSource(const String& module, const String& name, const String& codeStr, const String& codeHash)
2547+
{
2548+
p = new Impl(module, name, codeStr, codeHash);
2549+
}
2550+
2551+
ProgramSource::ProgramSource(const char* prog)
2552+
{
2553+
p = new Impl(prog);
2554+
}
2555+
2556+
ProgramSource::ProgramSource(const String& prog)
2557+
{
2558+
p = new Impl(prog);
2559+
}
2560+
2561+
ProgramSource::~ProgramSource()
2562+
{
2563+
if(p)
2564+
p->release();
2565+
}
2566+
2567+
ProgramSource::ProgramSource(const ProgramSource& prog)
2568+
{
2569+
p = prog.p;
2570+
if(p)
2571+
p->addref();
2572+
}
2573+
2574+
ProgramSource& ProgramSource::operator = (const ProgramSource& prog)
2575+
{
2576+
Impl* newp = (Impl*)prog.p;
2577+
if(newp)
2578+
newp->addref();
2579+
if(p)
2580+
p->release();
2581+
p = newp;
2582+
return *this;
2583+
}
2584+
2585+
const String& ProgramSource::source() const
2586+
{
2587+
CV_Assert(p);
2588+
return p->codeStr_;
2589+
}
2590+
2591+
ProgramSource::hash_t ProgramSource::hash() const
2592+
{
2593+
CV_Assert(p);
2594+
if (!p->isHashUpdated)
2595+
p->updateHash();
2596+
return p->hash_;
2597+
}
2598+
2599+
2600+
internal::ProgramEntry::operator ProgramSource&() const
2601+
{
2602+
if (this->pProgramSource == NULL)
2603+
{
2604+
cv::AutoLock lock(cv::getInitializationMutex());
2605+
if (this->pProgramSource == NULL)
2606+
{
2607+
ProgramSource* ps = new ProgramSource(this->module, this->name, this->programCode, this->programHash);
2608+
const_cast<ProgramEntry*>(this)->pProgramSource = ps;
2609+
}
2610+
}
2611+
return *this->pProgramSource;
2612+
}
2613+
2614+
2615+
24922616
/////////////////////////////////////////// Program /////////////////////////////////////////////
24932617

24942618
struct Program::Impl
24952619
{
24962620
Impl(const ProgramSource& _src,
2497-
const String& _buildflags, String& errmsg)
2621+
const String& _buildflags, String& errmsg) :
2622+
src(_src),
2623+
buildflags(_buildflags),
2624+
handle(NULL)
24982625
{
2499-
CV_INSTRUMENT_REGION_OPENCL_COMPILE(cv::format("Compile: %" PRIx64 " options: %s", _src.hash(), _buildflags.c_str()).c_str());
25002626
refcount = 1;
2501-
const Context& ctx = Context::getDefault();
2502-
src = _src;
2503-
buildflags = _buildflags;
2627+
compile(Context::getDefault(), errmsg);
2628+
}
2629+
2630+
bool compile(const Context& ctx, String& errmsg)
2631+
{
2632+
CV_Assert(handle == NULL);
2633+
CV_INSTRUMENT_REGION_OPENCL_COMPILE(cv::format("Compile: %" PRIx64 " options: %s", src.hash(), buildflags.c_str()).c_str());
25042634
const String& srcstr = src.source();
25052635
const char* srcptr = srcstr.c_str();
25062636
size_t srclen = srcstr.size();
25072637
cl_int retval = 0;
25082638

25092639
handle = clCreateProgramWithSource((cl_context)ctx.ptr(), 1, &srcptr, &srclen, &retval);
2510-
if( handle && retval == CL_SUCCESS )
2640+
CV_OclDbgAssert(handle && retval == CL_SUCCESS);
2641+
if (handle && retval == CL_SUCCESS)
25112642
{
25122643
int i, n = (int)ctx.ndevices();
25132644
AutoBuffer<void*> deviceListBuf(n+1);
@@ -2525,33 +2656,49 @@ struct Program::Impl
25252656
(const cl_device_id*)deviceList,
25262657
buildflags.c_str(), 0, 0);
25272658
#if !CV_OPENCL_ALWAYS_SHOW_BUILD_LOG
2528-
if( retval != CL_SUCCESS )
2659+
if (retval != CL_SUCCESS)
25292660
#endif
25302661
{
2662+
AutoBuffer<char, 4096> buffer; buffer[0] = 0;
2663+
25312664
size_t retsz = 0;
2532-
cl_int buildInfo_retval = clGetProgramBuildInfo(handle, (cl_device_id)deviceList[0],
2533-
CL_PROGRAM_BUILD_LOG, 0, 0, &retsz);
2534-
if (buildInfo_retval == CL_SUCCESS && retsz > 1)
2665+
cl_int log_retval = clGetProgramBuildInfo(handle, (cl_device_id)deviceList[0],
2666+
CL_PROGRAM_BUILD_LOG, 0, 0, &retsz);
2667+
if (log_retval == CL_SUCCESS && retsz > 1)
25352668
{
2536-
AutoBuffer<char> bufbuf(retsz + 16);
2537-
char* buf = bufbuf;
2538-
buildInfo_retval = clGetProgramBuildInfo(handle, (cl_device_id)deviceList[0],
2539-
CL_PROGRAM_BUILD_LOG, retsz+1, buf, &retsz);
2540-
if (buildInfo_retval == CL_SUCCESS)
2669+
buffer.resize(retsz + 16);
2670+
log_retval = clGetProgramBuildInfo(handle, (cl_device_id)deviceList[0],
2671+
CL_PROGRAM_BUILD_LOG, retsz+1, (char*)buffer, &retsz);
2672+
if (log_retval == CL_SUCCESS)
2673+
{
2674+
if (retsz < buffer.size())
2675+
buffer[retsz] = 0;
2676+
else
2677+
buffer[buffer.size() - 1] = 0;
2678+
}
2679+
else
25412680
{
2542-
// TODO It is useful to see kernel name & program file name also
2543-
errmsg = String(buf);
2544-
printf("OpenCL program build log: %s\n%s\n", buildflags.c_str(), errmsg.c_str());
2545-
fflush(stdout);
2681+
buffer[0] = 0;
25462682
}
25472683
}
2684+
2685+
errmsg = String(buffer);
2686+
printf("OpenCL program build log: %s (%s)\nStatus %d: %s\n%s\n%s\n",
2687+
src.getImpl()->name_.c_str(), src.getImpl()->module_.c_str(),
2688+
retval, getOpenCLErrorString(retval),
2689+
buildflags.c_str(), errmsg.c_str());
2690+
fflush(stdout);
2691+
2692+
// don't remove "retval != CL_SUCCESS" condition here:
2693+
// it would break CV_OPENCL_ALWAYS_SHOW_BUILD_LOG mode
25482694
if (retval != CL_SUCCESS && handle)
25492695
{
25502696
clReleaseProgram(handle);
25512697
handle = NULL;
25522698
}
25532699
}
25542700
}
2701+
return handle != NULL;
25552702
}
25562703

25572704
Impl(const String& _buf, const String& _buildflags)
@@ -2717,125 +2864,6 @@ String Program::getPrefix(const String& buildflags)
27172864
dev.name().c_str(), dev.driverVersion().c_str(), buildflags.c_str());
27182865
}
27192866

2720-
///////////////////////////////////////// ProgramSource ///////////////////////////////////////////////
2721-
2722-
struct ProgramSource::Impl
2723-
{
2724-
Impl(const String& src)
2725-
{
2726-
init(cv::String(), cv::String(), src, cv::String());
2727-
}
2728-
Impl(const String& module, const String& name, const String& codeStr, const String& codeHash)
2729-
{
2730-
init(module, name, codeStr, codeHash);
2731-
}
2732-
void init(const String& module, const String& name, const String& codeStr, const String& codeHash)
2733-
{
2734-
refcount = 1;
2735-
module_ = module;
2736-
name_ = name;
2737-
codeStr_ = codeStr;
2738-
codeHash_ = codeHash;
2739-
2740-
isHashUpdated = false;
2741-
if (codeHash_.empty())
2742-
{
2743-
updateHash();
2744-
codeHash_ = cv::format("%08llx", hash_);
2745-
}
2746-
}
2747-
2748-
void updateHash()
2749-
{
2750-
hash_ = crc64((uchar*)codeStr_.c_str(), codeStr_.size());
2751-
isHashUpdated = true;
2752-
}
2753-
2754-
IMPLEMENT_REFCOUNTABLE();
2755-
2756-
String module_;
2757-
String name_;
2758-
String codeStr_;
2759-
String codeHash_;
2760-
// TODO std::vector<ProgramSource> includes_;
2761-
2762-
bool isHashUpdated;
2763-
ProgramSource::hash_t hash_;
2764-
};
2765-
2766-
2767-
ProgramSource::ProgramSource()
2768-
{
2769-
p = 0;
2770-
}
2771-
2772-
ProgramSource::ProgramSource(const String& module, const String& name, const String& codeStr, const String& codeHash)
2773-
{
2774-
p = new Impl(module, name, codeStr, codeHash);
2775-
}
2776-
2777-
ProgramSource::ProgramSource(const char* prog)
2778-
{
2779-
p = new Impl(prog);
2780-
}
2781-
2782-
ProgramSource::ProgramSource(const String& prog)
2783-
{
2784-
p = new Impl(prog);
2785-
}
2786-
2787-
ProgramSource::~ProgramSource()
2788-
{
2789-
if(p)
2790-
p->release();
2791-
}
2792-
2793-
ProgramSource::ProgramSource(const ProgramSource& prog)
2794-
{
2795-
p = prog.p;
2796-
if(p)
2797-
p->addref();
2798-
}
2799-
2800-
ProgramSource& ProgramSource::operator = (const ProgramSource& prog)
2801-
{
2802-
Impl* newp = (Impl*)prog.p;
2803-
if(newp)
2804-
newp->addref();
2805-
if(p)
2806-
p->release();
2807-
p = newp;
2808-
return *this;
2809-
}
2810-
2811-
const String& ProgramSource::source() const
2812-
{
2813-
CV_Assert(p);
2814-
return p->codeStr_;
2815-
}
2816-
2817-
ProgramSource::hash_t ProgramSource::hash() const
2818-
{
2819-
CV_Assert(p);
2820-
if (!p->isHashUpdated)
2821-
p->updateHash();
2822-
return p->hash_;
2823-
}
2824-
2825-
2826-
internal::ProgramEntry::operator ProgramSource&() const
2827-
{
2828-
if (this->pProgramSource == NULL)
2829-
{
2830-
cv::AutoLock lock(cv::getInitializationMutex());
2831-
if (this->pProgramSource == NULL)
2832-
{
2833-
ProgramSource* ps = new ProgramSource(this->module, this->name, this->programCode, this->programHash);
2834-
const_cast<ProgramEntry*>(this)->pProgramSource = ps;
2835-
}
2836-
}
2837-
return *this->pProgramSource;
2838-
}
28392867

28402868

28412869
//////////////////////////////////////////// OpenCLAllocator //////////////////////////////////////////////////

0 commit comments

Comments
 (0)