Path: blob/master/samples/android/tutorial-4-opencl/jni/CLprocessor.cpp
16348 views
#define __CL_ENABLE_EXCEPTIONS1#define CL_USE_DEPRECATED_OPENCL_1_1_APIS /*let's give a chance for OpenCL 1.1 devices*/2#include <CL/cl.hpp>34#include <GLES2/gl2.h>5#include <EGL/egl.h>67#include <opencv2/core.hpp>8#include <opencv2/imgproc.hpp>9#include <opencv2/core/ocl.hpp>1011#include "common.hpp"1213const char oclProgB2B[] = "// clBuffer to clBuffer";14const char oclProgI2B[] = "// clImage to clBuffer";15const char oclProgI2I[] = \16"__constant sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_NEAREST; \n" \17"\n" \18"__kernel void Laplacian( \n" \19" __read_only image2d_t imgIn, \n" \20" __write_only image2d_t imgOut \n" \21" ) { \n" \22" \n" \23" const int2 pos = {get_global_id(0), get_global_id(1)}; \n" \24" \n" \25" float4 sum = (float4) 0.0f; \n" \26" sum += read_imagef(imgIn, sampler, pos + (int2)(-1,0)); \n" \27" sum += read_imagef(imgIn, sampler, pos + (int2)(+1,0)); \n" \28" sum += read_imagef(imgIn, sampler, pos + (int2)(0,-1)); \n" \29" sum += read_imagef(imgIn, sampler, pos + (int2)(0,+1)); \n" \30" sum -= read_imagef(imgIn, sampler, pos) * 4; \n" \31" \n" \32" write_imagef(imgOut, pos, sum*10); \n" \33"} \n";3435void dumpCLinfo()36{37LOGD("*** OpenCL info ***");38try39{40std::vector<cl::Platform> platforms;41cl::Platform::get(&platforms);42LOGD("OpenCL info: Found %d OpenCL platforms", platforms.size());43for (int i = 0; i < platforms.size(); ++i)44{45std::string name = platforms[i].getInfo<CL_PLATFORM_NAME>();46std::string version = platforms[i].getInfo<CL_PLATFORM_VERSION>();47std::string profile = platforms[i].getInfo<CL_PLATFORM_PROFILE>();48std::string extensions = platforms[i].getInfo<CL_PLATFORM_EXTENSIONS>();49LOGD( "OpenCL info: Platform[%d] = %s, ver = %s, prof = %s, ext = %s",50i, name.c_str(), version.c_str(), profile.c_str(), extensions.c_str() );51}5253std::vector<cl::Device> devices;54platforms[0].getDevices(CL_DEVICE_TYPE_ALL, &devices);5556for (int i = 0; i < devices.size(); ++i)57{58std::string name = devices[i].getInfo<CL_DEVICE_NAME>();59std::string extensions = devices[i].getInfo<CL_DEVICE_EXTENSIONS>();60cl_ulong type = devices[i].getInfo<CL_DEVICE_TYPE>();61LOGD( "OpenCL info: Device[%d] = %s (%s), ext = %s",62i, name.c_str(), (type==CL_DEVICE_TYPE_GPU ? "GPU" : "CPU"), extensions.c_str() );63}64}65catch(cl::Error& e)66{67LOGE( "OpenCL info: error while gathering OpenCL info: %s (%d)", e.what(), e.err() );68}69catch(std::exception& e)70{71LOGE( "OpenCL info: error while gathering OpenCL info: %s", e.what() );72}73catch(...)74{75LOGE( "OpenCL info: unknown error while gathering OpenCL info" );76}77LOGD("*******************");78}7980cl::Context theContext;81cl::CommandQueue theQueue;82cl::Program theProgB2B, theProgI2B, theProgI2I;83bool haveOpenCL = false;8485extern "C" void initCL()86{87dumpCLinfo();8889EGLDisplay mEglDisplay = eglGetCurrentDisplay();90if (mEglDisplay == EGL_NO_DISPLAY)91LOGE("initCL: eglGetCurrentDisplay() returned 'EGL_NO_DISPLAY', error = %x", eglGetError());9293EGLContext mEglContext = eglGetCurrentContext();94if (mEglContext == EGL_NO_CONTEXT)95LOGE("initCL: eglGetCurrentContext() returned 'EGL_NO_CONTEXT', error = %x", eglGetError());9697cl_context_properties props[] =98{ CL_GL_CONTEXT_KHR, (cl_context_properties) mEglContext,99CL_EGL_DISPLAY_KHR, (cl_context_properties) mEglDisplay,100CL_CONTEXT_PLATFORM, 0,1010 };102103try104{105haveOpenCL = false;106cl::Platform p = cl::Platform::getDefault();107std::string ext = p.getInfo<CL_PLATFORM_EXTENSIONS>();108if(ext.find("cl_khr_gl_sharing") == std::string::npos)109LOGE("Warning: CL-GL sharing isn't supported by PLATFORM");110props[5] = (cl_context_properties) p();111112theContext = cl::Context(CL_DEVICE_TYPE_GPU, props);113std::vector<cl::Device> devs = theContext.getInfo<CL_CONTEXT_DEVICES>();114LOGD("Context returned %d devices, taking the 1st one", devs.size());115ext = devs[0].getInfo<CL_DEVICE_EXTENSIONS>();116if(ext.find("cl_khr_gl_sharing") == std::string::npos)117LOGE("Warning: CL-GL sharing isn't supported by DEVICE");118119theQueue = cl::CommandQueue(theContext, devs[0]);120121cl::Program::Sources src(1, std::make_pair(oclProgI2I, sizeof(oclProgI2I)));122theProgI2I = cl::Program(theContext, src);123theProgI2I.build(devs);124125cv::ocl::attachContext(p.getInfo<CL_PLATFORM_NAME>(), p(), theContext(), devs[0]());126if( cv::ocl::useOpenCL() )127LOGD("OpenCV+OpenCL works OK!");128else129LOGE("Can't init OpenCV with OpenCL TAPI");130haveOpenCL = true;131}132catch(cl::Error& e)133{134LOGE("cl::Error: %s (%d)", e.what(), e.err());135}136catch(std::exception& e)137{138LOGE("std::exception: %s", e.what());139}140catch(...)141{142LOGE( "OpenCL info: unknown error while initializing OpenCL stuff" );143}144LOGD("initCL completed");145}146147extern "C" void closeCL()148{149}150151#define GL_TEXTURE_2D 0x0DE1152void procOCL_I2I(int texIn, int texOut, int w, int h)153{154LOGD("Processing OpenCL Direct (image2d)");155if(!haveOpenCL)156{157LOGE("OpenCL isn't initialized");158return;159}160161LOGD("procOCL_I2I(%d, %d, %d, %d)", texIn, texOut, w, h);162cl::ImageGL imgIn (theContext, CL_MEM_READ_ONLY, GL_TEXTURE_2D, 0, texIn);163cl::ImageGL imgOut(theContext, CL_MEM_WRITE_ONLY, GL_TEXTURE_2D, 0, texOut);164std::vector < cl::Memory > images;165images.push_back(imgIn);166images.push_back(imgOut);167168int64_t t = getTimeMs();169theQueue.enqueueAcquireGLObjects(&images);170theQueue.finish();171LOGD("enqueueAcquireGLObjects() costs %d ms", getTimeInterval(t));172173t = getTimeMs();174cl::Kernel Laplacian(theProgI2I, "Laplacian"); //TODO: may be done once175Laplacian.setArg(0, imgIn);176Laplacian.setArg(1, imgOut);177theQueue.finish();178LOGD("Kernel() costs %d ms", getTimeInterval(t));179180t = getTimeMs();181theQueue.enqueueNDRangeKernel(Laplacian, cl::NullRange, cl::NDRange(w, h), cl::NullRange);182theQueue.finish();183LOGD("enqueueNDRangeKernel() costs %d ms", getTimeInterval(t));184185t = getTimeMs();186theQueue.enqueueReleaseGLObjects(&images);187theQueue.finish();188LOGD("enqueueReleaseGLObjects() costs %d ms", getTimeInterval(t));189}190191void procOCL_OCV(int texIn, int texOut, int w, int h)192{193LOGD("Processing OpenCL via OpenCV");194if(!haveOpenCL)195{196LOGE("OpenCL isn't initialized");197return;198}199200int64_t t = getTimeMs();201cl::ImageGL imgIn (theContext, CL_MEM_READ_ONLY, GL_TEXTURE_2D, 0, texIn);202std::vector < cl::Memory > images(1, imgIn);203theQueue.enqueueAcquireGLObjects(&images);204theQueue.finish();205cv::UMat uIn, uOut, uTmp;206cv::ocl::convertFromImage(imgIn(), uIn);207LOGD("loading texture data to OpenCV UMat costs %d ms", getTimeInterval(t));208theQueue.enqueueReleaseGLObjects(&images);209210t = getTimeMs();211//cv::blur(uIn, uOut, cv::Size(5, 5));212cv::Laplacian(uIn, uTmp, CV_8U);213cv:multiply(uTmp, 10, uOut);214cv::ocl::finish();215LOGD("OpenCV processing costs %d ms", getTimeInterval(t));216217t = getTimeMs();218cl::ImageGL imgOut(theContext, CL_MEM_WRITE_ONLY, GL_TEXTURE_2D, 0, texOut);219images.clear();220images.push_back(imgOut);221theQueue.enqueueAcquireGLObjects(&images);222cl_mem clBuffer = (cl_mem)uOut.handle(cv::ACCESS_READ);223cl_command_queue q = (cl_command_queue)cv::ocl::Queue::getDefault().ptr();224size_t offset = 0;225size_t origin[3] = { 0, 0, 0 };226size_t region[3] = { w, h, 1 };227CV_Assert(clEnqueueCopyBufferToImage (q, clBuffer, imgOut(), offset, origin, region, 0, NULL, NULL) == CL_SUCCESS);228theQueue.enqueueReleaseGLObjects(&images);229cv::ocl::finish();230LOGD("uploading results to texture costs %d ms", getTimeInterval(t));231}232233void drawFrameProcCPU(int w, int h, int texOut)234{235LOGD("Processing on CPU");236int64_t t;237238// let's modify pixels in FBO texture in C++ code (on CPU)239static cv::Mat m;240m.create(h, w, CV_8UC4);241242// read243t = getTimeMs();244// expecting FBO to be bound245glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, m.data);246LOGD("glReadPixels() costs %d ms", getTimeInterval(t));247248// modify249t = getTimeMs();250cv::Laplacian(m, m, CV_8U);251m *= 10;252LOGD("Laplacian() costs %d ms", getTimeInterval(t));253254// write back255glActiveTexture(GL_TEXTURE0);256glBindTexture(GL_TEXTURE_2D, texOut);257t = getTimeMs();258glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, m.data);259LOGD("glTexSubImage2D() costs %d ms", getTimeInterval(t));260}261262263enum ProcMode {PROC_MODE_NO_PROC=0, PROC_MODE_CPU=1, PROC_MODE_OCL_DIRECT=2, PROC_MODE_OCL_OCV=3};264265extern "C" void processFrame(int tex1, int tex2, int w, int h, int mode)266{267switch(mode)268{269//case PROC_MODE_NO_PROC:270case PROC_MODE_CPU:271drawFrameProcCPU(w, h, tex2);272break;273case PROC_MODE_OCL_DIRECT:274procOCL_I2I(tex1, tex2, w, h);275break;276case PROC_MODE_OCL_OCV:277procOCL_OCV(tex1, tex2, w, h);278break;279default:280LOGE("Unexpected processing mode: %d", mode);281}282}283284285