tesseract/opencl/openclwrapper.h
2017-05-05 20:14:45 +02:00

298 lines
11 KiB
C++

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef TESSERACT_OPENCL_OPENCLWRAPPER_H_
#define TESSERACT_OPENCL_OPENCLWRAPPER_H_
#include <stdio.h>
#include "allheaders.h"
#include "pix.h"
#ifdef USE_OPENCL
#include "tiff.h"
#include "tiffio.h"
#endif
#include "tprintf.h"
// including CL/cl.h doesn't occur until USE_OPENCL defined below
// platform preprocessor commands
#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || \
defined(__CYGWIN__) || defined(__MINGW32__)
#define ON_WINDOWS 1
#define ON_LINUX 0
#define ON_APPLE 0
#define ON_OTHER 0
#define IF_WINDOWS(X) X
#define IF_LINUX(X)
#define IF_APPLE(X)
#define IF_OTHER(X)
#define NOT_WINDOWS(X)
#elif defined( __linux__ )
#define ON_WINDOWS 0
#define ON_LINUX 1
#define ON_APPLE 0
#define ON_OTHER 0
#define IF_WINDOWS(X)
#define IF_LINUX(X) X
#define IF_APPLE(X)
#define IF_OTHER(X)
#define NOT_WINDOWS(X) X
#elif defined( __APPLE__ )
#define ON_WINDOWS 0
#define ON_LINUX 0
#define ON_APPLE 1
#define ON_OTHER 0
#define IF_WINDOWS(X)
#define IF_LINUX(X)
#define IF_APPLE(X) X
#define IF_OTHER(X)
#define NOT_WINDOWS(X) X
#else
#define ON_WINDOWS 0
#define ON_LINUX 0
#define ON_APPLE 0
#define ON_OTHER 1
#define IF_WINDOWS(X)
#define IF_LINUX(X)
#define IF_APPLE(X)
#define IF_OTHER(X) X
#define NOT_WINDOWS(X) X
#endif
#if ON_LINUX
#include <time.h>
#endif
/************************************************************************************
* enable/disable reporting of performance
* PERF_REPORT_LEVEL
* 0 - no reporting
* 1 - no reporting
* 2 - report total function call time for functions we're tracking
* 3 - optionally report breakdown of function calls (kernel launch, kernel time, data copies)
************************************************************************************/
#define PERF_COUNT_VERBOSE 1
#define PERF_COUNT_REPORT_STR "[%36s], %24s, %11.6f\n"
#if ON_WINDOWS
#if PERF_COUNT_VERBOSE >= 2
#define PERF_COUNT_START(FUNCT_NAME) \
char *funct_name = FUNCT_NAME; \
double elapsed_time_sec; \
LARGE_INTEGER freq, time_funct_start, time_funct_end, time_sub_start, time_sub_end; \
QueryPerformanceFrequency(&freq); \
QueryPerformanceCounter(&time_funct_start); \
time_sub_start = time_funct_start; \
time_sub_end = time_funct_start;
#define PERF_COUNT_END \
QueryPerformanceCounter(&time_funct_end); \
elapsed_time_sec = (time_funct_end.QuadPart - time_funct_start.QuadPart) / \
(double)(freq.QuadPart); \
printf(PERF_COUNT_REPORT_STR, funct_name, "total", elapsed_time_sec);
#else
#define PERF_COUNT_START(FUNCT_NAME)
#define PERF_COUNT_END
#endif
#if PERF_COUNT_VERBOSE >= 3
#define PERF_COUNT_SUB(SUB) \
QueryPerformanceCounter(&time_sub_end); \
elapsed_time_sec = (time_sub_end.QuadPart - time_sub_start.QuadPart) / \
(double)(freq.QuadPart); \
printf(PERF_COUNT_REPORT_STR, funct_name, SUB, elapsed_time_sec); \
time_sub_start = time_sub_end;
#else
#define PERF_COUNT_SUB(SUB)
#endif
// not on windows
#else
#if PERF_COUNT_VERBOSE >= 2
#define PERF_COUNT_START(FUNCT_NAME) \
char *funct_name = FUNCT_NAME; \
double elapsed_time_sec; \
timespec time_funct_start, time_funct_end, time_sub_start, time_sub_end; \
clock_gettime( CLOCK_MONOTONIC, &time_funct_start ); \
time_sub_start = time_funct_start; \
time_sub_end = time_funct_start;
#define PERF_COUNT_END \
clock_gettime(CLOCK_MONOTONIC, &time_funct_end); \
elapsed_time_sec = \
(time_funct_end.tv_sec - time_funct_start.tv_sec) * 1.0 + \
(time_funct_end.tv_nsec - time_funct_start.tv_nsec) / 1000000000.0; \
printf(PERF_COUNT_REPORT_STR, funct_name, "total", elapsed_time_sec);
#else
#define PERF_COUNT_START(FUNCT_NAME)
#define PERF_COUNT_END
#endif
#if PERF_COUNT_VERBOSE >= 3
#define PERF_COUNT_SUB(SUB) \
clock_gettime(CLOCK_MONOTONIC, &time_sub_end); \
elapsed_time_sec = \
(time_sub_end.tv_sec - time_sub_start.tv_sec) * 1.0 + \
(time_sub_end.tv_nsec - time_sub_start.tv_nsec) / 1000000000.0; \
printf(PERF_COUNT_REPORT_STR, funct_name, SUB, elapsed_time_sec); \
time_sub_start = time_sub_end;
#else
#define PERF_COUNT_SUB(SUB)
#endif
#endif
/**************************************************************************
* enable/disable use of OpenCL
**************************************************************************/
#ifdef USE_OPENCL
#include "opencl_device_selection.h"
#ifndef strcasecmp
#define strcasecmp strcmp
#endif
#define MAX_KERNEL_STRING_LEN 64
#define MAX_CLFILE_NUM 50
#define MAX_CLKERNEL_NUM 200
#define MAX_KERNEL_NAME_LEN 64
#define CL_QUEUE_THREAD_HANDLE_AMD 0x403E
#define GROUPSIZE_X 16
#define GROUPSIZE_Y 16
#define GROUPSIZE_HMORX 256
#define GROUPSIZE_HMORY 1
typedef struct _KernelEnv
{
cl_context mpkContext;
cl_command_queue mpkCmdQueue;
cl_program mpkProgram;
cl_kernel mpkKernel;
char mckKernelName[150];
} KernelEnv;
typedef struct _OpenCLEnv
{
cl_platform_id mpOclPlatformID;
cl_context mpOclContext;
cl_device_id mpOclDevsID;
cl_command_queue mpOclCmdQueue;
} OpenCLEnv;
typedef int ( *cl_kernel_function )( void **userdata, KernelEnv *kenv );
#define CHECK_OPENCL(status,name) \
if( status != CL_SUCCESS ) \
{ \
printf ("OpenCL error code is %d at when %s .\n", status, name); \
}
typedef struct _GPUEnv
{
//share vb in all modules in hb library
cl_platform_id mpPlatformID;
cl_device_type mDevType;
cl_context mpContext;
cl_device_id *mpArryDevsID;
cl_device_id mpDevID;
cl_command_queue mpCmdQueue;
cl_kernel mpArryKernels[MAX_CLFILE_NUM];
cl_program mpArryPrograms[MAX_CLFILE_NUM]; //one program object maps one kernel source file
char mArryKnelSrcFile[MAX_CLFILE_NUM][256], //the max len of kernel file name is 256
mArrykernelNames[MAX_CLKERNEL_NUM][MAX_KERNEL_STRING_LEN + 1];
cl_kernel_function mpArryKnelFuncs[MAX_CLKERNEL_NUM];
int mnKernelCount, mnFileCount, // only one kernel file
mnIsUserCreated; // 1: created , 0:no create and needed to create by opencl wrapper
int mnKhrFp64Flag;
int mnAmdFp64Flag;
} GPUEnv;
class OpenclDevice
{
public:
static GPUEnv gpuEnv;
static int isInited;
OpenclDevice();
~OpenclDevice();
static int InitEnv(); // load dll, call InitOpenclRunEnv(0)
static int InitOpenclRunEnv( int argc ); // RegistOpenclKernel, double flags, compile kernels
static int InitOpenclRunEnv_DeviceSelection( int argc ); // RegistOpenclKernel, double flags, compile kernels
static int RegistOpenclKernel();
static int ReleaseOpenclRunEnv();
static int ReleaseOpenclEnv( GPUEnv *gpuInfo );
static int CompileKernelFile( GPUEnv *gpuInfo, const char *buildOption );
static int CachedOfKernerPrg( const GPUEnv *gpuEnvCached, const char * clFileName );
static int GeneratBinFromKernelSource( cl_program program, const char * clFileName );
static int WriteBinaryToFile( const char* fileName, const char* birary, size_t numBytes );
static int BinaryGenerated( const char * clFileName, FILE ** fhandle );
//static int CompileKernelFile( const char *filename, GPUEnv *gpuInfo, const char *buildOption );
static l_uint32* pixReadFromTiffKernel(l_uint32 *tiffdata,l_int32 w,l_int32 h,l_int32 wpl, l_uint32 *line);
static int composeRGBPixelCl(int *tiffdata,int *line,int h,int w);
/* OpenCL implementations of Morphological operations*/
//Initialiation of OCL buffers used in Morph operations
static int initMorphCLAllocations(l_int32 wpl, l_int32 h, Pix* pixs);
static void releaseMorphCLBuffers();
static void pixGetLinesCL(Pix *pixd, Pix *pixs, Pix **pix_vline,
Pix **pix_hline, Pix **pixClosed,
bool getpixClosed, l_int32 close_hsize,
l_int32 close_vsize, l_int32 open_hsize,
l_int32 open_vsize, l_int32 line_hsize,
l_int32 line_vsize);
//int InitOpenclAttr( OpenCLEnv * env );
//int ReleaseKernel( KernelEnv * env );
static int SetKernelEnv( KernelEnv *envInfo );
//int CreateKernel( char * kernelname, KernelEnv * env );
//int RunKernel( const char *kernelName, void **userdata );
//int ConvertToString( const char *filename, char **source );
//int CheckKernelName( KernelEnv *envInfo, const char *kernelName );
//int RegisterKernelWrapper( const char *kernelName, cl_kernel_function function );
//int RunKernelWrapper( cl_kernel_function function, const char * kernelName, void **usrdata );
//int GetKernelEnvAndFunc( const char *kernelName, KernelEnv *env, cl_kernel_function *function );
static int LoadOpencl();
#ifdef WIN32
//static int OpenclInite();
static void FreeOpenclDll();
#endif
inline static int AddKernelConfig( int kCount, const char *kName );
/* for binarization */
static int HistogramRectOCL(unsigned char *imagedata, int bytes_per_pixel,
int bytes_per_line, int left, int top,
int width, int height, int kHistogramSize,
int *histogramAllChannels);
static int ThresholdRectToPixOCL(unsigned char *imagedata,
int bytes_per_pixel, int bytes_per_line,
int *thresholds, int *hi_values, Pix **pix,
int rect_height, int rect_width,
int rect_top, int rect_left);
static ds_device getDeviceSelection();
static ds_device selectedDevice;
static bool deviceIsSelected;
static bool selectedDeviceIsOpenCL();
};
#endif // USE_OPENCL
#endif // TESSERACT_OPENCL_OPENCLWRAPPER_H_