43#include "magick/studio.h"
44#include "magick/accelerate-kernels-private.h"
45#include "magick/artifact.h"
46#include "magick/cache.h"
47#include "magick/cache-private.h"
48#include "magick/color.h"
49#include "magick/compare.h"
50#include "magick/constitute.h"
51#include "magick/distort.h"
52#include "magick/draw.h"
53#include "magick/effect.h"
54#include "magick/exception.h"
55#include "magick/exception-private.h"
57#include "magick/gem.h"
58#include "magick/geometry.h"
59#include "magick/image.h"
60#include "magick/image-private.h"
61#include "magick/layer.h"
62#include "magick/locale_.h"
63#include "magick/mime-private.h"
64#include "magick/memory_.h"
65#include "magick/memory-private.h"
66#include "magick/monitor.h"
67#include "magick/montage.h"
68#include "magick/morphology.h"
69#include "magick/nt-base.h"
70#include "magick/nt-base-private.h"
71#include "magick/opencl.h"
72#include "magick/opencl-private.h"
73#include "magick/option.h"
74#include "magick/policy.h"
75#include "magick/property.h"
76#include "magick/quantize.h"
77#include "magick/quantum.h"
78#include "magick/random_.h"
79#include "magick/random-private.h"
80#include "magick/resample.h"
81#include "magick/resource_.h"
82#include "magick/splay-tree.h"
83#include "magick/semaphore.h"
84#include "magick/statistic.h"
85#include "magick/string_.h"
86#include "magick/token.h"
87#include "magick/utility.h"
88#include "magick/utility-private.h"
90#ifdef MAGICKCORE_CLPERFMARKER
91#include "CLPerfMarker.h"
94#if defined(MAGICKCORE_OPENCL_SUPPORT)
96#if defined(MAGICKCORE_LTDL_DELEGATE)
100#define NUM_CL_RAND_GENERATORS 1024
101#define PROFILE_OCL_KERNELS 0
109} KernelProfileRecord;
111static const char *kernelNames[] = {
125 "LocalContrastBlurRow",
126 "LocalContrastBlurApplyColumn",
130 "RandomNumberGenerator",
133 "UnsharpMaskBlurColumn",
139 profileRecords[KERNEL_COUNT];
141typedef struct _AccelerateTimer {
147void startAccelerateTimer(AccelerateTimer* timer) {
149 QueryPerformanceCounter((LARGE_INTEGER*)&timer->_start);
155 timer->_start = (
long long)s.tv_sec * (
long long)1.0E3 + (
long long)s.tv_usec / (
long long)1.0E3;
159void stopAccelerateTimer(AccelerateTimer* timer) {
162 QueryPerformanceCounter((LARGE_INTEGER*)&(n));
166 n = (
long long)s.tv_sec * (
long long)1.0E3+ (
long long)s.tv_usec / (
long long)1.0E3;
173void resetAccelerateTimer(AccelerateTimer* timer) {
178void initAccelerateTimer(AccelerateTimer* timer) {
180 QueryPerformanceFrequency((LARGE_INTEGER*)&timer->_freq);
182 timer->_freq = (
long long)1.0E3;
184 resetAccelerateTimer(timer);
187double readAccelerateTimer(AccelerateTimer* timer) {
188 return (
double)timer->_clocks/(double)timer->_freq;
191MagickPrivate MagickBooleanType RecordProfileData(MagickCLEnv clEnv, ProfiledKernels kernel, cl_event event)
193#if PROFILE_OCL_KERNELS
197 cl_ulong elapsed = 0;
198 clEnv->library->clWaitForEvents(1, &event);
199 status = clEnv->library->clGetEventProfilingInfo(event, CL_PROFILING_COMMAND_START,
sizeof(cl_ulong), &start, NULL);
200 status &= clEnv->library->clGetEventProfilingInfo(event, CL_PROFILING_COMMAND_END,
sizeof(cl_ulong), &end, NULL);
201 if (status == CL_SUCCESS) {
204 elapsed = end - start;
206 LockSemaphoreInfo(clEnv->commandQueuesLock);
207 if ((elapsed < profileRecords[kernel].min) || (profileRecords[kernel].count == 0))
208 profileRecords[kernel].min = elapsed;
209 if (elapsed > profileRecords[kernel].max)
210 profileRecords[kernel].max = elapsed;
211 profileRecords[kernel].total += elapsed;
212 profileRecords[kernel].count += 1;
213 UnlockSemaphoreInfo(clEnv->commandQueuesLock);
217 magick_unreferenced(clEnv);
218 magick_unreferenced(kernel);
219 magick_unreferenced(event);
224void DumpProfileData()
226#if PROFILE_OCL_KERNELS
229 OpenCLLog(
"====================================================");
240 clEnv = GetDefaultOpenCLEnv();
242 status = clEnv->library->clGetDeviceInfo(clEnv->device, CL_DEVICE_VENDOR, 2048, buff, NULL);
245 status = clEnv->library->clGetDeviceInfo(clEnv->device, CL_DEVICE_NAME, 2048, buff, NULL);
248 status = clEnv->library->clGetDeviceInfo(clEnv->device, CL_DRIVER_VERSION, 2048, buff, NULL);
252 OpenCLLog(
"====================================================");
253 OpenCLLog(
" ave\tcalls \tmin -> max");
254 OpenCLLog(
" ---\t----- \t----------");
255 for (i = 0; i < KERNEL_COUNT; ++i) {
258 (void) CopyMagickString(indent,
" ",
260 strncpy(indent, kernelNames[i], min(strlen(kernelNames[i]), strlen(indent) - 1));
261 (void) FormatLocaleString(buf,
sizeof(buf),
"%s%d\t(%d calls) \t%d -> %d",
262 indent, profileRecords[i].count > 0 ? (profileRecords[i].total /
263 profileRecords[i].count) : 0, profileRecords[i].count,
264 profileRecords[i].min, profileRecords[i].max);
270 OpenCLLog(
"====================================================");
279#ifdef MAGICKCORE_WINDOWS_SUPPORT
285void *OsLibraryLoad(
const char *libraryName)
287#ifdef MAGICKCORE_WINDOWS_SUPPORT
288 return (
void *)LoadLibraryA(libraryName);
290 return (
void *)dlopen(libraryName, RTLD_NOW);
295void *OsLibraryGetFunctionAddress(
void *library,
const char *functionName)
297#ifdef MAGICKCORE_WINDOWS_SUPPORT
298 if (!library || !functionName)
302 return (
void *) GetProcAddress( (HMODULE)library, functionName);
304 if (!library || !functionName)
308 return (
void *)dlsym(library, functionName);
328MagickPrivate MagickCLEnv AcquireMagickOpenCLEnv()
331 clEnv = (MagickCLEnv) AcquireMagickMemory(
sizeof(
struct _MagickCLEnv));
335 clEnv->commandQueuesPos=-1;
336 ActivateSemaphoreInfo(&clEnv->lock);
337 ActivateSemaphoreInfo(&clEnv->commandQueuesLock);
366MagickPrivate MagickBooleanType RelinquishMagickOpenCLEnv(MagickCLEnv clEnv)
368 if (clEnv != (MagickCLEnv) NULL)
370 while (clEnv->commandQueuesPos >= 0)
372 clEnv->library->clReleaseCommandQueue(
373 clEnv->commandQueues[clEnv->commandQueuesPos--]);
375 if (clEnv->programs[0] != (cl_program) NULL)
376 (void) clEnv->library->clReleaseProgram(clEnv->programs[0]);
377 if (clEnv->context != (cl_context) NULL)
378 clEnv->library->clReleaseContext(clEnv->context);
379 DestroySemaphoreInfo(&clEnv->lock);
380 DestroySemaphoreInfo(&clEnv->commandQueuesLock);
381 RelinquishMagickMemory(clEnv);
391MagickCLEnv defaultCLEnv;
397MagickLibrary * OpenCLLib;
401static MagickBooleanType bindOpenCLFunctions(
void* library)
403#ifdef MAGICKCORE_HAVE_OPENCL_CL_H
404#define BIND(X) OpenCLLib->X= &X;
407 if ((OpenCLLib->X=(MAGICKpfn_##X)OsLibraryGetFunctionAddress(library,#X)) == NULL)\
411 BIND(clGetPlatformIDs);
412 BIND(clGetPlatformInfo);
414 BIND(clGetDeviceIDs);
415 BIND(clGetDeviceInfo);
417 BIND(clCreateContext);
418 BIND(clReleaseContext);
420 BIND(clCreateBuffer);
421 BIND(clRetainMemObject);
422 BIND(clReleaseMemObject);
424 BIND(clCreateProgramWithSource);
425 BIND(clCreateProgramWithBinary);
426 BIND(clBuildProgram);
427 BIND(clReleaseProgram);
428 BIND(clGetProgramInfo);
429 BIND(clGetProgramBuildInfo);
431 BIND(clCreateKernel);
432 BIND(clReleaseKernel);
433 BIND(clSetKernelArg);
438 BIND(clEnqueueNDRangeKernel);
439 BIND(clEnqueueReadBuffer);
440 BIND(clEnqueueMapBuffer);
441 BIND(clEnqueueUnmapMemObject);
443 BIND(clCreateCommandQueue);
444 BIND(clReleaseCommandQueue);
446 BIND(clGetEventProfilingInfo);
447 BIND(clGetEventInfo);
448 BIND(clWaitForEvents);
449 BIND(clReleaseEvent);
451 BIND(clSetEventCallback);
456MagickLibrary * GetOpenCLLib()
458 if (OpenCLLib == NULL)
460 if (OpenCLLibLock == NULL)
462 ActivateSemaphoreInfo(&OpenCLLibLock);
465 LockSemaphoreInfo(OpenCLLibLock);
467 OpenCLLib = (MagickLibrary *) AcquireMagickMemory (
sizeof (MagickLibrary));
469 if (OpenCLLib != NULL)
471 MagickBooleanType status = MagickFalse;
472 void * library = NULL;
474#ifdef MAGICKCORE_OPENCL_MACOSX
475 status = bindOpenCLFunctions(library);
478 memset(OpenCLLib, 0,
sizeof(MagickLibrary));
479#ifdef MAGICKCORE_WINDOWS_SUPPORT
480 library = OsLibraryLoad(
"OpenCL.dll");
482 library = OsLibraryLoad(
"libOpenCL.so");
485 status = bindOpenCLFunctions(library);
487 if (status==MagickTrue)
488 OpenCLLib->base=library;
490 OpenCLLib=(MagickLibrary *)RelinquishMagickMemory(OpenCLLib);
494 UnlockSemaphoreInfo(OpenCLLibLock);
525MagickExport MagickCLEnv GetDefaultOpenCLEnv()
527 if (defaultCLEnv == NULL)
529 if (defaultCLEnvLock == NULL)
531 ActivateSemaphoreInfo(&defaultCLEnvLock);
533 LockSemaphoreInfo(defaultCLEnvLock);
534 if (defaultCLEnv == NULL)
535 defaultCLEnv = AcquireMagickOpenCLEnv();
536 UnlockSemaphoreInfo(defaultCLEnvLock);
541static void LockDefaultOpenCLEnv() {
542 if (defaultCLEnvLock == NULL)
544 ActivateSemaphoreInfo(&defaultCLEnvLock);
546 LockSemaphoreInfo(defaultCLEnvLock);
549static void UnlockDefaultOpenCLEnv() {
550 if (defaultCLEnvLock == NULL)
552 ActivateSemaphoreInfo(&defaultCLEnvLock);
555 UnlockSemaphoreInfo(defaultCLEnvLock);
582MagickPrivate MagickCLEnv SetDefaultOpenCLEnv(MagickCLEnv clEnv)
585 LockDefaultOpenCLEnv();
586 oldEnv = defaultCLEnv;
587 defaultCLEnv = clEnv;
588 UnlockDefaultOpenCLEnv();
625static MagickBooleanType SetMagickOpenCLEnvParamInternal(MagickCLEnv clEnv, MagickOpenCLEnvParam param
626 ,
size_t dataSize,
void* data, ExceptionInfo* exception)
628 MagickBooleanType status = MagickFalse;
636 case MAGICK_OPENCL_ENV_PARAM_DEVICE:
637 if (dataSize !=
sizeof(clEnv->device))
639 clEnv->device = *((cl_device_id*)data);
640 clEnv->OpenCLInitialized = MagickFalse;
644 case MAGICK_OPENCL_ENV_PARAM_OPENCL_DISABLED:
645 if (dataSize !=
sizeof(clEnv->OpenCLDisabled))
647 clEnv->OpenCLDisabled = *((MagickBooleanType*)data);
648 clEnv->OpenCLInitialized = MagickFalse;
652 case MAGICK_OPENCL_ENV_PARAM_OPENCL_INITIALIZED:
653 (void) ThrowMagickException(exception, GetMagickModule(), ModuleWarning,
"SetMagickOpenCLEnvParm cannot modify the OpenCL initialization state.",
"'%s'",
".");
656 case MAGICK_OPENCL_ENV_PARAM_PROGRAM_CACHE_DISABLED:
657 if (dataSize !=
sizeof(clEnv->disableProgramCache))
659 clEnv->disableProgramCache = *((MagickBooleanType*)data);
660 clEnv->OpenCLInitialized = MagickFalse;
664 case MAGICK_OPENCL_ENV_PARAM_REGENERATE_PROFILE:
665 if (dataSize !=
sizeof(clEnv->regenerateProfile))
667 clEnv->regenerateProfile = *((MagickBooleanType*)data);
668 clEnv->OpenCLInitialized = MagickFalse;
681 MagickBooleanType SetMagickOpenCLEnvParam(MagickCLEnv clEnv, MagickOpenCLEnvParam param
682 ,
size_t dataSize,
void* data, ExceptionInfo* exception) {
683 MagickBooleanType status = MagickFalse;
685 LockSemaphoreInfo(clEnv->lock);
686 status = SetMagickOpenCLEnvParamInternal(clEnv,param,dataSize,data,exception);
687 UnlockSemaphoreInfo(clEnv->lock);
726 MagickBooleanType GetMagickOpenCLEnvParam(MagickCLEnv clEnv, MagickOpenCLEnvParam param
727 ,
size_t dataSize,
void* data, ExceptionInfo* exception)
735 magick_unreferenced(exception);
737 status = MagickFalse;
745 case MAGICK_OPENCL_ENV_PARAM_DEVICE:
746 if (dataSize !=
sizeof(cl_device_id))
748 *((cl_device_id*)data) = clEnv->device;
752 case MAGICK_OPENCL_ENV_PARAM_OPENCL_DISABLED:
753 if (dataSize !=
sizeof(clEnv->OpenCLDisabled))
755 *((MagickBooleanType*)data) = clEnv->OpenCLDisabled;
759 case MAGICK_OPENCL_ENV_PARAM_OPENCL_INITIALIZED:
760 if (dataSize !=
sizeof(clEnv->OpenCLDisabled))
762 *((MagickBooleanType*)data) = clEnv->OpenCLInitialized;
766 case MAGICK_OPENCL_ENV_PARAM_PROGRAM_CACHE_DISABLED:
767 if (dataSize !=
sizeof(clEnv->disableProgramCache))
769 *((MagickBooleanType*)data) = clEnv->disableProgramCache;
773 case MAGICK_OPENCL_ENV_PARAM_REGENERATE_PROFILE:
774 if (dataSize !=
sizeof(clEnv->regenerateProfile))
776 *((MagickBooleanType*)data) = clEnv->regenerateProfile;
780 case MAGICK_OPENCL_ENV_PARAM_PLATFORM_VENDOR:
781 if (dataSize !=
sizeof(
char *))
783 clEnv->library->clGetPlatformInfo(clEnv->platform,CL_PLATFORM_VENDOR,0,
785 *((
char **) data)=(
char *) AcquireQuantumMemory(length,
sizeof(
char));
786 clEnv->library->clGetPlatformInfo(clEnv->platform,CL_PLATFORM_VENDOR,
787 length,*((
char **) data),NULL);
791 case MAGICK_OPENCL_ENV_PARAM_DEVICE_NAME:
792 if (dataSize !=
sizeof(
char *))
794 clEnv->library->clGetDeviceInfo(clEnv->device,CL_DEVICE_NAME,0,NULL,
796 *((
char **) data)=(
char *) AcquireQuantumMemory(length,
sizeof(
char));
797 clEnv->library->clGetDeviceInfo(clEnv->device,CL_DEVICE_NAME,length,
798 *((
char **) data),NULL);
835cl_context GetOpenCLContext(MagickCLEnv clEnv) {
839 return clEnv->context;
842static char* getBinaryCLProgramName(MagickCLEnv clEnv, MagickOpenCLProgram prog,
unsigned int signature)
846 char path[MaxTextExtent];
847 char deviceName[MaxTextExtent];
848 const char* prefix =
"magick_opencl";
849 clEnv->library->clGetDeviceInfo(clEnv->device, CL_DEVICE_NAME, MaxTextExtent, deviceName, NULL);
854 if ( *ptr ==
' ' || *ptr ==
'\\' || *ptr ==
'/' || *ptr ==
':' || *ptr ==
'*'
855 || *ptr ==
'?' || *ptr ==
'"' || *ptr ==
'<' || *ptr ==
'>' || *ptr ==
'|')
861 (void) FormatLocaleString(path,MaxTextExtent,
"%s%s%s_%s_%02d_%08x_%.20g.bin",
862 GetOpenCLCachedFilesDirectory(),DirectorySeparator,prefix,deviceName,
863 (
unsigned int) prog,signature,(
double)
sizeof(
char*)*8);
864 name = (
char*)AcquireMagickMemory(strlen(path)+1);
865 CopyMagickString(name,path,strlen(path)+1);
869static void saveBinaryCLProgram(MagickCLEnv clEnv,MagickOpenCLProgram prog,
870 unsigned int signature,ExceptionInfo* exception)
886 filename=getBinaryCLProgramName(clEnv,prog,signature);
887 status=clEnv->library->clGetProgramInfo(clEnv->programs[prog],
888 CL_PROGRAM_NUM_DEVICES,
sizeof(cl_uint),&num_devices,NULL);
889 if (status != CL_SUCCESS)
891 size=num_devices*
sizeof(*program_sizes);
892 program_sizes=(
size_t*) AcquireQuantumMemory(1,size);
893 if (program_sizes == (
size_t*) NULL)
895 status=clEnv->library->clGetProgramInfo(clEnv->programs[prog],
896 CL_PROGRAM_BINARY_SIZES,size,program_sizes,NULL);
897 if (status == CL_SUCCESS)
905 binary_program_size=num_devices*
sizeof(*binary_program);
906 binary_program=(
unsigned char **) AcquireQuantumMemory(1,
907 binary_program_size);
908 if (binary_program == (
unsigned char **) NULL)
910 program_sizes=(
size_t *) RelinquishMagickMemory(program_sizes);
913 memset(binary_program,0,binary_program_size);
914 for (i = 0; i < num_devices; i++)
916 binary_program[i]=(
unsigned char *) AcquireQuantumMemory(
917 MagickMax(*(program_sizes+i),1),
sizeof(**binary_program));
918 if (binary_program[i] == (
unsigned char *) NULL)
920 status=CL_OUT_OF_HOST_MEMORY;
924 if (status == CL_SUCCESS)
925 status=clEnv->library->clGetProgramInfo(clEnv->programs[prog],
926 CL_PROGRAM_BINARIES,binary_program_size,binary_program,NULL);
927 if (status == CL_SUCCESS)
929 for (i = 0; i < num_devices; i++)
937 program_size=*(program_sizes+i);
938 if (program_size < 1)
940 file=open_utf8(filename,O_WRONLY | O_CREAT | O_BINARY,S_MODE);
943 write(file,binary_program[i],program_size);
947 (
void) ThrowMagickException(exception,GetMagickModule(),
948 DelegateWarning,
"Saving kernel failed.",
"`%s'",filename);
952 for (i = 0; i < num_devices; i++)
953 binary_program[i]=(
unsigned char *) RelinquishMagickMemory(
955 binary_program=(
unsigned char **) RelinquishMagickMemory(binary_program);
957 program_sizes=(
size_t *) RelinquishMagickMemory(program_sizes);
960static MagickBooleanType loadBinaryCLProgram(MagickCLEnv clEnv, MagickOpenCLProgram prog,
unsigned int signature)
962 MagickBooleanType loadSuccessful;
963 unsigned char* binaryProgram;
964 char* binaryFileName;
967#ifdef MAGICKCORE_CLPERFMARKER
968 clBeginPerfMarkerAMD(__FUNCTION__,
"");
971 binaryProgram = NULL;
972 binaryFileName = NULL;
974 loadSuccessful = MagickFalse;
976 binaryFileName = getBinaryCLProgramName(clEnv, prog, signature);
977 fileHandle = fopen(binaryFileName,
"rb");
978 if (fileHandle != NULL)
983 cl_int clBinaryStatus;
987 b_error |= fseek( fileHandle, 0, SEEK_END ) < 0;
988 b_error |= ( length = ftell( fileHandle ) ) <= 0;
989 b_error |= fseek( fileHandle, 0, SEEK_SET ) < 0;
993 binaryProgram = (
unsigned char*)AcquireMagickMemory(length);
994 if (binaryProgram == NULL)
997 memset(binaryProgram, 0, length);
998 b_error |= fread(binaryProgram, 1, length, fileHandle) != length;
1000 clEnv->programs[prog] = clEnv->library->clCreateProgramWithBinary(clEnv->context, 1, &clEnv->device, &length, (
const unsigned char**)&binaryProgram, &clBinaryStatus, &clStatus);
1001 if (clStatus != CL_SUCCESS
1002 || clBinaryStatus != CL_SUCCESS)
1005 loadSuccessful = MagickTrue;
1009 if (fileHandle != NULL)
1011 if (binaryFileName != NULL)
1012 RelinquishMagickMemory(binaryFileName);
1013 if (binaryProgram != NULL)
1014 RelinquishMagickMemory(binaryProgram);
1016#ifdef MAGICKCORE_CLPERFMARKER
1017 clEndPerfMarkerAMD();
1020 return loadSuccessful;
1023static unsigned int stringSignature(
const char*
string)
1025 unsigned int stringLength;
1027 unsigned int signature;
1031 const unsigned int* u;
1034#ifdef MAGICKCORE_CLPERFMARKER
1035 clBeginPerfMarkerAMD(__FUNCTION__,
"");
1038 stringLength = (
unsigned int) strlen(
string);
1039 signature = stringLength;
1040 n = stringLength/
sizeof(
unsigned int);
1042 for (i = 0; i < n; i++)
1046 if (n *
sizeof(
unsigned int) != stringLength)
1049 j = n *
sizeof(
unsigned int);
1050 for (i = 0; i < 4; i++,j++)
1052 if (j < stringLength)
1061#ifdef MAGICKCORE_CLPERFMARKER
1062 clEndPerfMarkerAMD();
1069extern const char *accelerateKernels, *accelerateKernels2;
1071static MagickBooleanType CompileOpenCLKernels(MagickCLEnv clEnv, ExceptionInfo* exception)
1073 MagickBooleanType status = MagickFalse;
1076 char* accelerateKernelsBuffer = NULL;
1079 const char* MagickOpenCLProgramStrings[MAGICK_OPENCL_NUM_PROGRAMS];
1081 char options[MaxTextExtent];
1082 unsigned int optionsSignature;
1084#ifdef MAGICKCORE_CLPERFMARKER
1085 clBeginPerfMarkerAMD(__FUNCTION__,
"");
1089 (void) FormatLocaleString(options, MaxTextExtent, CLOptions, (
float)QuantumRange,
1090 (
float)QuantumScale, (
float)CLCharQuantumScale, (
float)MagickEpsilon, (
float)MagickPI, (
unsigned int)MaxMap, (
unsigned int)MAGICKCORE_QUANTUM_DEPTH);
1105 optionsSignature = stringSignature(options);
1108 accelerateKernelsBuffer = (
char*) AcquireQuantumMemory(1,strlen(accelerateKernels)+strlen(accelerateKernels2)+1);
1109 FormatLocaleString(accelerateKernelsBuffer,strlen(accelerateKernels)+
1110 strlen(accelerateKernels2)+1,
"%s%s",accelerateKernels,accelerateKernels2);
1111 MagickOpenCLProgramStrings[MAGICK_OPENCL_ACCELERATE] = accelerateKernelsBuffer;
1113 for (i = 0; i < MAGICK_OPENCL_NUM_PROGRAMS; i++)
1115 MagickBooleanType loadSuccessful = MagickFalse;
1116 unsigned int programSignature = stringSignature(MagickOpenCLProgramStrings[i]) ^ optionsSignature;
1119 if (clEnv->disableProgramCache != MagickTrue
1120 && !getenv(
"MAGICK_OCL_REC"))
1121 loadSuccessful = loadBinaryCLProgram(clEnv, (MagickOpenCLProgram)i, programSignature);
1123 if (loadSuccessful == MagickFalse)
1126 size_t programLength = strlen(MagickOpenCLProgramStrings[i]);
1127 clEnv->programs[i] = clEnv->library->clCreateProgramWithSource(clEnv->context, 1, &(MagickOpenCLProgramStrings[i]), &programLength, &clStatus);
1128 if (clStatus!=CL_SUCCESS)
1130 (void) ThrowMagickException(exception, GetMagickModule(), DelegateWarning,
1131 "clCreateProgramWithSource failed.",
"(%d)", (
int)clStatus);
1137 clStatus = clEnv->library->clBuildProgram(clEnv->programs[i], 1, &clEnv->device, options, NULL, NULL);
1138 if (clStatus!=CL_SUCCESS)
1140 (void) ThrowMagickException(exception, GetMagickModule(), DelegateWarning,
1141 "clBuildProgram failed.",
"(%d)", (
int)clStatus);
1143 if (loadSuccessful == MagickFalse)
1145 char path[MaxTextExtent];
1149 (void) FormatLocaleString(path,MaxTextExtent,
"%s%s%s"
1150 ,GetOpenCLCachedFilesDirectory()
1151 ,DirectorySeparator,
"magick_badcl.cl");
1152 fileHandle = fopen(path,
"wb");
1153 if (fileHandle != NULL)
1155 fwrite(MagickOpenCLProgramStrings[i],
sizeof(
char), strlen(MagickOpenCLProgramStrings[i]), fileHandle);
1163 clEnv->library->clGetProgramBuildInfo(clEnv->programs[i], clEnv->device, CL_PROGRAM_BUILD_LOG, 0, NULL, &logSize);
1164 log = (
char*)AcquireCriticalMemory(logSize);
1165 clEnv->library->clGetProgramBuildInfo(clEnv->programs[i], clEnv->device, CL_PROGRAM_BUILD_LOG, logSize, log, &logSize);
1167 (void) FormatLocaleString(path,MaxTextExtent,
"%s%s%s"
1168 ,GetOpenCLCachedFilesDirectory()
1169 ,DirectorySeparator,
"magick_badcl_build.log");
1170 fileHandle = fopen(path,
"wb");
1171 if (fileHandle != NULL)
1173 const char* buildOptionsTitle =
"build options: ";
1174 fwrite(buildOptionsTitle,
sizeof(
char), strlen(buildOptionsTitle), fileHandle);
1175 fwrite(options,
sizeof(
char), strlen(options), fileHandle);
1176 fwrite(
"\n",
sizeof(
char), 1, fileHandle);
1177 fwrite(log,
sizeof(
char), logSize, fileHandle);
1180 RelinquishMagickMemory(log);
1186 if (loadSuccessful == MagickFalse)
1189 saveBinaryCLProgram(clEnv, (MagickOpenCLProgram)i, programSignature, exception);
1193 status = MagickTrue;
1197 if (accelerateKernelsBuffer!=NULL) RelinquishMagickMemory(accelerateKernelsBuffer);
1199#ifdef MAGICKCORE_CLPERFMARKER
1200 clEndPerfMarkerAMD();
1206static MagickBooleanType InitOpenCLPlatformDevice(MagickCLEnv clEnv, ExceptionInfo* exception) {
1209 cl_uint numPlatforms = 0;
1210 cl_platform_id *platforms = NULL;
1211 char* MAGICK_OCL_DEVICE = NULL;
1212 MagickBooleanType OpenCLAvailable = MagickFalse;
1214#ifdef MAGICKCORE_CLPERFMARKER
1215 clBeginPerfMarkerAMD(__FUNCTION__,
"");
1219 MAGICK_OCL_DEVICE = getenv(
"MAGICK_OCL_DEVICE");
1220 if (MAGICK_OCL_DEVICE == (
char *) NULL)
1221 return(MagickFalse);
1222 if (strcmp(MAGICK_OCL_DEVICE,
"CPU") == 0)
1223 clEnv->deviceType = CL_DEVICE_TYPE_CPU;
1224 else if (strcmp(MAGICK_OCL_DEVICE,
"GPU") == 0)
1225 clEnv->deviceType = CL_DEVICE_TYPE_GPU;
1226 else if (IsStringTrue(MAGICK_OCL_DEVICE) != MagickFalse)
1228 if (clEnv->deviceType == 0)
1229 clEnv->deviceType = CL_DEVICE_TYPE_ALL;
1232 return(MagickFalse);
1234 if (clEnv->device != NULL)
1236 status = clEnv->library->clGetDeviceInfo(clEnv->device, CL_DEVICE_PLATFORM,
sizeof(cl_platform_id), &clEnv->platform, NULL);
1237 if (status != CL_SUCCESS) {
1238 (void) ThrowMagickException(exception, GetMagickModule(), DelegateWarning,
1239 "Failed to get OpenCL platform from the selected device.",
"(%d)", status);
1243 else if (clEnv->platform != NULL)
1246 platforms = (cl_platform_id *) AcquireQuantumMemory(1,numPlatforms *
sizeof(cl_platform_id));
1247 if (platforms == (cl_platform_id *) NULL)
1249 (void) ThrowMagickException(exception, GetMagickModule(), ResourceLimitError,
1250 "AcquireMagickMemory failed.",
".");
1253 platforms[0] = clEnv->platform;
1257 clEnv->device = NULL;
1260 status = clEnv->library->clGetPlatformIDs(0, NULL, &numPlatforms);
1261 if (status != CL_SUCCESS)
1263 (void) ThrowMagickException(exception, GetMagickModule(), DelegateWarning,
1264 "clGetplatformIDs failed.",
"(%d)", status);
1269 if (numPlatforms == 0) {
1273 platforms = (cl_platform_id *) AcquireQuantumMemory(1,numPlatforms *
sizeof(cl_platform_id));
1274 if (platforms == (cl_platform_id *) NULL)
1276 (void) ThrowMagickException(exception, GetMagickModule(), ResourceLimitError,
1277 "AcquireMagickMemory failed.",
".");
1281 status = clEnv->library->clGetPlatformIDs(numPlatforms, platforms, NULL);
1282 if (status != CL_SUCCESS)
1284 (void) ThrowMagickException(exception, GetMagickModule(), DelegateWarning,
1285 "clGetPlatformIDs failed.",
"(%d)", status);
1291 clEnv->device = NULL;
1292 for (j = 0; j < 2; j++)
1295 cl_device_type deviceType;
1296 if (clEnv->deviceType == CL_DEVICE_TYPE_ALL)
1299 deviceType = CL_DEVICE_TYPE_GPU;
1301 deviceType = CL_DEVICE_TYPE_CPU;
1308 deviceType = clEnv->deviceType;
1310 for (i = 0; i < numPlatforms; i++)
1312 char version[MaxTextExtent];
1314 status = clEnv->library->clGetPlatformInfo(clEnv->platform, CL_PLATFORM_VERSION, MaxTextExtent, version, NULL);
1315 if (status != CL_SUCCESS)
1317 (void) ThrowMagickException(exception, GetMagickModule(), DelegateWarning,
1318 "clGetPlatformInfo failed.",
"(%d)", status);
1321 if (strncmp(version,
"OpenCL 1.0 ",11) == 0)
1323 status = clEnv->library->clGetDeviceIDs(platforms[i], deviceType, 1, &(clEnv->device), &numDevices);
1324 if (status != CL_SUCCESS)
1326 (void) ThrowMagickException(exception, GetMagickModule(), DelegateWarning,
1327 "clGetDeviceIDs failed.",
"(%d)", status);
1330 if (clEnv->device != NULL)
1332 clEnv->platform = platforms[i];
1339 if (platforms!=NULL)
1340 RelinquishMagickMemory(platforms);
1342 OpenCLAvailable = (clEnv->platform!=NULL
1343 && clEnv->device!=NULL)?MagickTrue:MagickFalse;
1345#ifdef MAGICKCORE_CLPERFMARKER
1346 clEndPerfMarkerAMD();
1349 return OpenCLAvailable;
1352static MagickBooleanType EnableOpenCLInternal(MagickCLEnv clEnv) {
1353 if (clEnv->OpenCLInitialized != MagickFalse
1354 && clEnv->platform != NULL
1355 && clEnv->device != NULL) {
1356 clEnv->OpenCLDisabled = MagickFalse;
1359 clEnv->OpenCLDisabled = MagickTrue;
1364static MagickBooleanType autoSelectDevice(MagickCLEnv clEnv, ExceptionInfo* exception);
1390static void RelinquishCommandQueues(MagickCLEnv clEnv)
1392 if (clEnv == (MagickCLEnv) NULL)
1395 LockSemaphoreInfo(clEnv->commandQueuesLock);
1396 while (clEnv->commandQueuesPos >= 0)
1397 clEnv->library->clReleaseCommandQueue(
1398 clEnv->commandQueues[clEnv->commandQueuesPos--]);
1399 UnlockSemaphoreInfo(clEnv->commandQueuesLock);
1403MagickBooleanType InitOpenCLEnvInternal(MagickCLEnv clEnv, ExceptionInfo* exception) {
1404 MagickBooleanType status = MagickTrue;
1406 cl_context_properties cps[3];
1408#ifdef MAGICKCORE_CLPERFMARKER
1410 int status = clInitializePerfMarkerAMD();
1411 if (status == AP_SUCCESS) {
1416 clEnv->OpenCLInitialized = MagickTrue;
1419 OpenCLLib=GetOpenCLLib();
1422 clEnv->library=OpenCLLib;
1427 MagickBooleanType flag;
1429 SetMagickOpenCLEnvParamInternal(clEnv, MAGICK_OPENCL_ENV_PARAM_OPENCL_DISABLED
1430 ,
sizeof(MagickBooleanType), &flag, exception);
1433 if (clEnv->OpenCLDisabled != MagickFalse)
1436 clEnv->OpenCLDisabled = MagickTrue;
1438 status = InitOpenCLPlatformDevice(clEnv, exception);
1439 if (status == MagickFalse) {
1445 cps[0] = CL_CONTEXT_PLATFORM;
1446 cps[1] = (cl_context_properties)clEnv->platform;
1448 clEnv->context = clEnv->library->clCreateContext(cps, 1, &(clEnv->device), NULL, NULL, &clStatus);
1449 if (clStatus != CL_SUCCESS)
1451 (void) ThrowMagickException(exception, GetMagickModule(), DelegateWarning,
1452 "clCreateContext failed.",
"(%d)", clStatus);
1453 status = MagickFalse;
1457 RelinquishCommandQueues(clEnv);
1459 status = CompileOpenCLKernels(clEnv, exception);
1460 if (status == MagickFalse) {
1461 (void) ThrowMagickException(exception, GetMagickModule(), DelegateWarning,
1462 "clCreateCommandQueue failed.",
"(%d)", status);
1467 status = EnableOpenCLInternal(clEnv);
1475MagickBooleanType InitOpenCLEnv(MagickCLEnv clEnv, ExceptionInfo* exception) {
1476 MagickBooleanType status = MagickFalse;
1478 if ((clEnv == NULL) || (getenv(
"MAGICK_OCL_DEVICE") == (
const char *) NULL))
1481#ifdef MAGICKCORE_CLPERFMARKER
1482 clBeginPerfMarkerAMD(__FUNCTION__,
"");
1485 LockSemaphoreInfo(clEnv->lock);
1486 if (clEnv->OpenCLInitialized == MagickFalse) {
1487 if (clEnv->device==NULL && clEnv->OpenCLDisabled == MagickFalse)
1488 status = autoSelectDevice(clEnv, exception);
1490 status = InitOpenCLEnvInternal(clEnv, exception);
1492 UnlockSemaphoreInfo(clEnv->lock);
1494#ifdef MAGICKCORE_CLPERFMARKER
1495 clEndPerfMarkerAMD();
1524MagickPrivate cl_command_queue AcquireOpenCLCommandQueue(MagickCLEnv clEnv)
1529 cl_command_queue_properties
1532 if (clEnv == (MagickCLEnv) NULL)
1533 return (cl_command_queue) NULL;
1534 LockSemaphoreInfo(clEnv->commandQueuesLock);
1535 if (clEnv->commandQueuesPos >= 0) {
1536 queue=clEnv->commandQueues[clEnv->commandQueuesPos--];
1537 UnlockSemaphoreInfo(clEnv->commandQueuesLock);
1540 UnlockSemaphoreInfo(clEnv->commandQueuesLock);
1542#if PROFILE_OCL_KERNELS
1543 properties=CL_QUEUE_PROFILING_ENABLE;
1545 queue=clEnv->library->clCreateCommandQueue(clEnv->context,clEnv->device,
1578MagickPrivate MagickBooleanType RelinquishOpenCLCommandQueue(MagickCLEnv clEnv,
1579 cl_command_queue queue)
1585 return(MagickFalse);
1587 LockSemaphoreInfo(clEnv->commandQueuesLock);
1589 if (clEnv->commandQueuesPos >= MAX_COMMAND_QUEUES-1)
1591 clEnv->library->clFinish(queue);
1592 status=(clEnv->library->clReleaseCommandQueue(queue) == CL_SUCCESS) ?
1593 MagickTrue : MagickFalse;
1597 clEnv->library->clFlush(queue);
1598 clEnv->commandQueues[++clEnv->commandQueuesPos]=queue;
1602 UnlockSemaphoreInfo(clEnv->commandQueuesLock);
1636 cl_kernel AcquireOpenCLKernel(MagickCLEnv clEnv, MagickOpenCLProgram program,
const char* kernelName)
1639 cl_kernel kernel = NULL;
1640 if (clEnv != NULL && kernelName!=NULL)
1642 kernel = clEnv->library->clCreateKernel(clEnv->programs[program], kernelName, &clStatus);
1676 MagickBooleanType RelinquishOpenCLKernel(MagickCLEnv clEnv, cl_kernel kernel)
1678 MagickBooleanType status = MagickFalse;
1679 if (clEnv != NULL && kernel != NULL)
1681 status = ((clEnv->library->clReleaseKernel(kernel) == CL_SUCCESS)?MagickTrue:MagickFalse);
1711 unsigned long GetOpenCLDeviceLocalMemorySize(MagickCLEnv clEnv)
1713 cl_ulong localMemorySize;
1714 clEnv->library->clGetDeviceInfo(clEnv->device, CL_DEVICE_LOCAL_MEM_SIZE,
sizeof(cl_ulong), &localMemorySize, NULL);
1715 return (
unsigned long)localMemorySize;
1719 unsigned long GetOpenCLDeviceMaxMemAllocSize(MagickCLEnv clEnv)
1721 cl_ulong maxMemAllocSize;
1722 clEnv->library->clGetDeviceInfo(clEnv->device, CL_DEVICE_MAX_MEM_ALLOC_SIZE,
sizeof(cl_ulong), &maxMemAllocSize, NULL);
1723 return (
unsigned long)maxMemAllocSize;
1734 ,DS_INVALID_PROFILE = 1000
1736 ,DS_INVALID_PERF_EVALUATOR_TYPE
1737 ,DS_INVALID_PERF_EVALUATOR
1738 ,DS_PERF_EVALUATOR_ERROR
1740 ,DS_UNKNOWN_DEVICE_TYPE
1741 ,DS_PROFILE_FILE_ERROR
1742 ,DS_SCORE_SERIALIZER_ERROR
1743 ,DS_SCORE_DESERIALIZER_ERROR
1748 DS_DEVICE_NATIVE_CPU = 0
1749 ,DS_DEVICE_OPENCL_DEVICE
1754 ds_device_type type;
1755 cl_device_type oclDeviceType;
1756 cl_device_id oclDeviceID;
1757 char* oclDeviceName;
1758 char* oclDriverVersion;
1759 cl_uint oclMaxClockFrequency;
1760 cl_uint oclMaxComputeUnits;
1765 unsigned int numDevices;
1767 const char* version;
1771typedef ds_status (*ds_score_release)(
void* score);
1773static ds_status releaseDeviceResource(ds_device* device, ds_score_release sr) {
1774 ds_status status = DS_SUCCESS;
1776 if (device->oclDeviceName) RelinquishMagickMemory(device->oclDeviceName);
1777 if (device->oclDriverVersion) RelinquishMagickMemory(device->oclDriverVersion);
1778 if (device->score) status = sr(device->score);
1783static ds_status releaseDSProfile(ds_profile* profile, ds_score_release sr) {
1784 ds_status status = DS_SUCCESS;
1785 if (profile!=NULL) {
1786 if (profile->devices!=NULL && sr!=NULL) {
1788 for (i = 0; i < profile->numDevices; i++) {
1789 status = releaseDeviceResource(profile->devices+i,sr);
1790 if (status != DS_SUCCESS)
1793 RelinquishMagickMemory(profile->devices);
1795 RelinquishMagickMemory(profile);
1801static ds_status initDSProfile(ds_profile** p,
const char* version) {
1803 cl_uint numPlatforms = 0;
1804 cl_platform_id* platforms = NULL;
1805 cl_device_id* devices = NULL;
1806 ds_status status = DS_SUCCESS;
1807 ds_profile* profile = NULL;
1808 unsigned int next = 0;
1812 return DS_INVALID_PROFILE;
1814 profile = (ds_profile*) AcquireMagickMemory(
sizeof(ds_profile));
1815 if (profile == NULL)
1816 return DS_MEMORY_ERROR;
1818 memset(profile, 0,
sizeof(ds_profile));
1820 OpenCLLib->clGetPlatformIDs(0, NULL, &numPlatforms);
1821 if (numPlatforms > 0) {
1822 platforms = (cl_platform_id*) AcquireQuantumMemory(numPlatforms,
sizeof(cl_platform_id));
1823 if (platforms == NULL) {
1824 status = DS_MEMORY_ERROR;
1827 OpenCLLib->clGetPlatformIDs(numPlatforms, platforms, NULL);
1828 for (i = 0; i < (
unsigned int)numPlatforms; i++) {
1830 if (OpenCLLib->clGetDeviceIDs(platforms[i], CL_DEVICE_TYPE_CPU | CL_DEVICE_TYPE_GPU, 0, NULL, &num) == CL_SUCCESS)
1835 profile->numDevices = numDevices+1;
1837 profile->devices = (ds_device*) AcquireQuantumMemory(profile->numDevices,
sizeof(ds_device));
1838 if (profile->devices == NULL) {
1839 profile->numDevices = 0;
1840 status = DS_MEMORY_ERROR;
1843 memset(profile->devices, 0, profile->numDevices*
sizeof(ds_device));
1845 if (numDevices > 0) {
1846 devices = (cl_device_id*) AcquireQuantumMemory(numDevices,
sizeof(cl_device_id));
1847 if (devices == NULL) {
1848 status = DS_MEMORY_ERROR;
1851 for (i = 0; i < (
unsigned int)numPlatforms; i++) {
1855 for (d = 0; d < 2; d++) {
1857 cl_device_type deviceType;
1860 deviceType = CL_DEVICE_TYPE_GPU;
1863 deviceType = CL_DEVICE_TYPE_CPU;
1869 if (OpenCLLib->clGetDeviceIDs(platforms[i], deviceType, numDevices, devices, &num) != CL_SUCCESS)
1871 for (j = 0; j < num; j++, next++) {
1874 profile->devices[next].type = DS_DEVICE_OPENCL_DEVICE;
1875 profile->devices[next].oclDeviceID = devices[j];
1877 OpenCLLib->clGetDeviceInfo(profile->devices[next].oclDeviceID, CL_DEVICE_NAME
1878 , 0, NULL, &length);
1879 profile->devices[next].oclDeviceName = (
char*) AcquireQuantumMemory(length,
sizeof(
char));
1880 OpenCLLib->clGetDeviceInfo(profile->devices[next].oclDeviceID, CL_DEVICE_NAME
1881 , length, profile->devices[next].oclDeviceName, NULL);
1883 OpenCLLib->clGetDeviceInfo(profile->devices[next].oclDeviceID, CL_DRIVER_VERSION
1884 , 0, NULL, &length);
1885 profile->devices[next].oclDriverVersion = (
char*) AcquireQuantumMemory(length,
sizeof(
char));
1886 OpenCLLib->clGetDeviceInfo(profile->devices[next].oclDeviceID, CL_DRIVER_VERSION
1887 , length, profile->devices[next].oclDriverVersion, NULL);
1889 OpenCLLib->clGetDeviceInfo(profile->devices[next].oclDeviceID, CL_DEVICE_MAX_CLOCK_FREQUENCY
1890 ,
sizeof(cl_uint), &profile->devices[next].oclMaxClockFrequency, NULL);
1892 OpenCLLib->clGetDeviceInfo(profile->devices[next].oclDeviceID, CL_DEVICE_MAX_COMPUTE_UNITS
1893 ,
sizeof(cl_uint), &profile->devices[next].oclMaxComputeUnits, NULL);
1895 OpenCLLib->clGetDeviceInfo(profile->devices[next].oclDeviceID, CL_DEVICE_TYPE
1896 ,
sizeof(cl_device_type), &profile->devices[next].oclDeviceType, NULL);
1902 profile->devices[next].type = DS_DEVICE_NATIVE_CPU;
1903 profile->version = version;
1906 if (platforms) RelinquishMagickMemory(platforms);
1907 if (devices) RelinquishMagickMemory(devices);
1908 if (status == DS_SUCCESS) {
1913 if (profile->devices)
1914 RelinquishMagickMemory(profile->devices);
1915 RelinquishMagickMemory(profile);
1925typedef ds_status (*ds_perf_evaluator)(ds_device* device,
void* data);
1929 ,DS_EVALUATE_NEW_ONLY
1930} ds_evaluation_type;
1932static ds_status profileDevices(ds_profile* profile,
const ds_evaluation_type type
1933 ,ds_perf_evaluator evaluator,
void* evaluatorData,
unsigned int* numUpdates) {
1934 ds_status status = DS_SUCCESS;
1936 unsigned int updates = 0;
1938 if (profile == NULL) {
1939 return DS_INVALID_PROFILE;
1941 if (evaluator == NULL) {
1942 return DS_INVALID_PERF_EVALUATOR;
1945 for (i = 0; i < profile->numDevices; i++) {
1946 ds_status evaluatorStatus;
1949 case DS_EVALUATE_NEW_ONLY:
1950 if (profile->devices[i].score != NULL)
1953 case DS_EVALUATE_ALL:
1954 evaluatorStatus = evaluator(profile->devices+i,evaluatorData);
1955 if (evaluatorStatus != DS_SUCCESS) {
1956 status = evaluatorStatus;
1962 return DS_INVALID_PERF_EVALUATOR_TYPE;
1967 *numUpdates = updates;
1972#define DS_TAG_VERSION "<version>"
1973#define DS_TAG_VERSION_END "</version>"
1974#define DS_TAG_DEVICE "<device>"
1975#define DS_TAG_DEVICE_END "</device>"
1976#define DS_TAG_SCORE "<score>"
1977#define DS_TAG_SCORE_END "</score>"
1978#define DS_TAG_DEVICE_TYPE "<type>"
1979#define DS_TAG_DEVICE_TYPE_END "</type>"
1980#define DS_TAG_DEVICE_NAME "<name>"
1981#define DS_TAG_DEVICE_NAME_END "</name>"
1982#define DS_TAG_DEVICE_DRIVER_VERSION "<driver>"
1983#define DS_TAG_DEVICE_DRIVER_VERSION_END "</driver>"
1984#define DS_TAG_DEVICE_MAX_COMPUTE_UNITS "<max cu>"
1985#define DS_TAG_DEVICE_MAX_COMPUTE_UNITS_END "</max cu>"
1986#define DS_TAG_DEVICE_MAX_CLOCK_FREQ "<max clock>"
1987#define DS_TAG_DEVICE_MAX_CLOCK_FREQ_END "</max clock>"
1989#define DS_DEVICE_NATIVE_CPU_STRING "native_cpu"
1993typedef ds_status (*ds_score_serializer)(ds_device* device,
void** serializedScore,
unsigned int* serializedScoreSize);
1994static ds_status writeProfileToFile(ds_profile* profile, ds_score_serializer serializer,
const char* file) {
1995 ds_status status = DS_SUCCESS;
1996 FILE* profileFile = NULL;
1999 if (profile == NULL)
2000 return DS_INVALID_PROFILE;
2002 profileFile = fopen(file,
"wb");
2003 if (profileFile==NULL) {
2004 status = DS_FILE_ERROR;
2010 fwrite(DS_TAG_VERSION,
sizeof(
char), strlen(DS_TAG_VERSION), profileFile);
2011 fwrite(profile->version,
sizeof(
char), strlen(profile->version), profileFile);
2012 fwrite(DS_TAG_VERSION_END,
sizeof(
char), strlen(DS_TAG_VERSION_END), profileFile);
2013 fwrite(
"\n",
sizeof(
char), 1, profileFile);
2015 for (i = 0; i < profile->numDevices && status == DS_SUCCESS; i++) {
2016 void* serializedScore;
2017 unsigned int serializedScoreSize;
2019 fwrite(DS_TAG_DEVICE,
sizeof(
char), strlen(DS_TAG_DEVICE), profileFile);
2021 fwrite(DS_TAG_DEVICE_TYPE,
sizeof(
char), strlen(DS_TAG_DEVICE_TYPE), profileFile);
2022 fwrite(&profile->devices[i].type,
sizeof(ds_device_type),1, profileFile);
2023 fwrite(DS_TAG_DEVICE_TYPE_END,
sizeof(
char), strlen(DS_TAG_DEVICE_TYPE_END), profileFile);
2025 switch(profile->devices[i].type) {
2026 case DS_DEVICE_NATIVE_CPU:
2036 case DS_DEVICE_OPENCL_DEVICE:
2040 fwrite(DS_TAG_DEVICE_NAME,
sizeof(
char), strlen(DS_TAG_DEVICE_NAME), profileFile);
2041 fwrite(profile->devices[i].oclDeviceName,
sizeof(
char),strlen(profile->devices[i].oclDeviceName), profileFile);
2042 fwrite(DS_TAG_DEVICE_NAME_END,
sizeof(
char), strlen(DS_TAG_DEVICE_NAME_END), profileFile);
2044 fwrite(DS_TAG_DEVICE_DRIVER_VERSION,
sizeof(
char), strlen(DS_TAG_DEVICE_DRIVER_VERSION), profileFile);
2045 fwrite(profile->devices[i].oclDriverVersion,
sizeof(
char),strlen(profile->devices[i].oclDriverVersion), profileFile);
2046 fwrite(DS_TAG_DEVICE_DRIVER_VERSION_END,
sizeof(
char), strlen(DS_TAG_DEVICE_DRIVER_VERSION_END), profileFile);
2048 fwrite(DS_TAG_DEVICE_MAX_COMPUTE_UNITS,
sizeof(
char), strlen(DS_TAG_DEVICE_MAX_COMPUTE_UNITS), profileFile);
2049 (void) FormatLocaleString(tmp,
sizeof(tmp),
"%d",
2050 profile->devices[i].oclMaxComputeUnits);
2051 fwrite(tmp,
sizeof(
char),strlen(tmp), profileFile);
2052 fwrite(DS_TAG_DEVICE_MAX_COMPUTE_UNITS_END,
sizeof(
char), strlen(DS_TAG_DEVICE_MAX_COMPUTE_UNITS_END), profileFile);
2054 fwrite(DS_TAG_DEVICE_MAX_CLOCK_FREQ,
sizeof(
char), strlen(DS_TAG_DEVICE_MAX_CLOCK_FREQ), profileFile);
2055 (void) FormatLocaleString(tmp,
sizeof(tmp),
"%d",
2056 profile->devices[i].oclMaxClockFrequency);
2057 fwrite(tmp,
sizeof(
char),strlen(tmp), profileFile);
2058 fwrite(DS_TAG_DEVICE_MAX_CLOCK_FREQ_END,
sizeof(
char), strlen(DS_TAG_DEVICE_MAX_CLOCK_FREQ_END), profileFile);
2062 status = DS_UNKNOWN_DEVICE_TYPE;
2066 fwrite(DS_TAG_SCORE,
sizeof(
char), strlen(DS_TAG_SCORE), profileFile);
2067 status = serializer(profile->devices+i, &serializedScore, &serializedScoreSize);
2068 if (status == DS_SUCCESS && serializedScore!=NULL && serializedScoreSize > 0) {
2069 fwrite(serializedScore,
sizeof(
char), serializedScoreSize, profileFile);
2070 RelinquishMagickMemory(serializedScore);
2072 fwrite(DS_TAG_SCORE_END,
sizeof(
char), strlen(DS_TAG_SCORE_END), profileFile);
2073 fwrite(DS_TAG_DEVICE_END,
sizeof(
char), strlen(DS_TAG_DEVICE_END), profileFile);
2074 fwrite(
"\n",
sizeof(
char),1,profileFile);
2076 fclose(profileFile);
2082static ds_status readProFile(
const char* fileName,
char** content,
size_t* contentSize) {
2083 ds_status status = DS_SUCCESS;
2084 FILE * input = NULL;
2087 char* binary = NULL;
2092 input = fopen(fileName,
"rb");
2094 return DS_FILE_ERROR;
2097 fseek(input, 0L, SEEK_END);
2098 size = ftell(input);
2100 binary = (
char*) AcquireQuantumMemory(1,size);
2101 if(binary == NULL) {
2102 status = DS_FILE_ERROR;
2105 rsize = fread(binary,
sizeof(
char), size, input);
2108 status = DS_FILE_ERROR;
2111 *contentSize = size;
2115 if (input != NULL) fclose(input);
2116 if (status != DS_SUCCESS
2117 && binary != NULL) {
2118 RelinquishMagickMemory(binary);
2126static const char* findString(
const char* contentStart,
const char* contentEnd,
const char*
string) {
2127 size_t stringLength;
2128 const char* currentPosition;
2131 stringLength = strlen(
string);
2132 currentPosition = contentStart;
2133 for(currentPosition = contentStart; currentPosition < contentEnd; currentPosition++) {
2134 if (*currentPosition ==
string[0]) {
2135 if (currentPosition+stringLength < contentEnd) {
2136 if (strncmp(currentPosition,
string, stringLength) == 0) {
2137 found = currentPosition;
2147typedef ds_status (*ds_score_deserializer)(ds_device* device,
const unsigned char* serializedScore,
unsigned int serializedScoreSize);
2148static ds_status readProfileFromFile(ds_profile* profile, ds_score_deserializer deserializer,
const char* file) {
2150 ds_status status = DS_SUCCESS;
2151 char* contentStart = NULL;
2152 const char* contentEnd = NULL;
2156 return DS_INVALID_PROFILE;
2158 status = readProFile(file, &contentStart, &contentSize);
2159 if (status == DS_SUCCESS) {
2160 const char* currentPosition;
2161 const char* dataStart;
2162 const char* dataEnd;
2163 size_t versionStringLength;
2165 contentEnd = contentStart + contentSize;
2166 currentPosition = contentStart;
2170 dataStart = findString(currentPosition, contentEnd, DS_TAG_VERSION);
2171 if (dataStart == NULL) {
2172 status = DS_PROFILE_FILE_ERROR;
2175 dataStart += strlen(DS_TAG_VERSION);
2177 dataEnd = findString(dataStart, contentEnd, DS_TAG_VERSION_END);
2178 if (dataEnd==NULL) {
2179 status = DS_PROFILE_FILE_ERROR;
2183 versionStringLength = strlen(profile->version);
2184 if (versionStringLength!=(
size_t)(dataEnd-dataStart)
2185 || strncmp(profile->version, dataStart, versionStringLength)!=(
int)0) {
2187 status = DS_PROFILE_FILE_ERROR;
2190 currentPosition = dataEnd+strlen(DS_TAG_VERSION_END);
2193DisableMSCWarning(4127)
2198 const char* deviceTypeStart;
2199 const char* deviceTypeEnd;
2200 ds_device_type deviceType;
2202 const char* deviceNameStart;
2203 const char* deviceNameEnd;
2205 const char* deviceScoreStart;
2206 const char* deviceScoreEnd;
2208 const char* deviceDriverStart;
2209 const char* deviceDriverEnd;
2211 const char* tmpStart;
2215 cl_uint maxClockFrequency;
2216 cl_uint maxComputeUnits;
2218 dataStart = findString(currentPosition, contentEnd, DS_TAG_DEVICE);
2219 if (dataStart==NULL) {
2223 dataStart+=strlen(DS_TAG_DEVICE);
2224 dataEnd = findString(dataStart, contentEnd, DS_TAG_DEVICE_END);
2225 if (dataEnd==NULL) {
2226 status = DS_PROFILE_FILE_ERROR;
2231 deviceTypeStart = findString(dataStart, contentEnd, DS_TAG_DEVICE_TYPE);
2232 if (deviceTypeStart==NULL) {
2233 status = DS_PROFILE_FILE_ERROR;
2236 deviceTypeStart+=strlen(DS_TAG_DEVICE_TYPE);
2237 deviceTypeEnd = findString(deviceTypeStart, contentEnd, DS_TAG_DEVICE_TYPE_END);
2238 if (deviceTypeEnd==NULL) {
2239 status = DS_PROFILE_FILE_ERROR;
2242 memcpy(&deviceType, deviceTypeStart,
sizeof(ds_device_type));
2246 if (deviceType == DS_DEVICE_OPENCL_DEVICE) {
2248 deviceNameStart = findString(dataStart, contentEnd, DS_TAG_DEVICE_NAME);
2249 if (deviceNameStart==NULL) {
2250 status = DS_PROFILE_FILE_ERROR;
2253 deviceNameStart+=strlen(DS_TAG_DEVICE_NAME);
2254 deviceNameEnd = findString(deviceNameStart, contentEnd, DS_TAG_DEVICE_NAME_END);
2255 if (deviceNameEnd==NULL) {
2256 status = DS_PROFILE_FILE_ERROR;
2261 deviceDriverStart = findString(dataStart, contentEnd, DS_TAG_DEVICE_DRIVER_VERSION);
2262 if (deviceDriverStart==NULL) {
2263 status = DS_PROFILE_FILE_ERROR;
2266 deviceDriverStart+=strlen(DS_TAG_DEVICE_DRIVER_VERSION);
2267 deviceDriverEnd = findString(deviceDriverStart, contentEnd, DS_TAG_DEVICE_DRIVER_VERSION_END);
2268 if (deviceDriverEnd ==NULL) {
2269 status = DS_PROFILE_FILE_ERROR;
2274 tmpStart = findString(dataStart, contentEnd, DS_TAG_DEVICE_MAX_COMPUTE_UNITS);
2275 if (tmpStart==NULL) {
2276 status = DS_PROFILE_FILE_ERROR;
2279 tmpStart+=strlen(DS_TAG_DEVICE_MAX_COMPUTE_UNITS);
2280 tmpEnd = findString(tmpStart, contentEnd, DS_TAG_DEVICE_MAX_COMPUTE_UNITS_END);
2281 if (tmpEnd ==NULL) {
2282 status = DS_PROFILE_FILE_ERROR;
2285 memcpy(tmp,tmpStart,tmpEnd-tmpStart);
2286 tmp[tmpEnd-tmpStart] =
'\0';
2287 maxComputeUnits = strtol(tmp,(
char **) NULL,10);
2290 tmpStart = findString(dataStart, contentEnd, DS_TAG_DEVICE_MAX_CLOCK_FREQ);
2291 if (tmpStart==NULL) {
2292 status = DS_PROFILE_FILE_ERROR;
2295 tmpStart+=strlen(DS_TAG_DEVICE_MAX_CLOCK_FREQ);
2296 tmpEnd = findString(tmpStart, contentEnd, DS_TAG_DEVICE_MAX_CLOCK_FREQ_END);
2297 if (tmpEnd ==NULL) {
2298 status = DS_PROFILE_FILE_ERROR;
2301 memcpy(tmp,tmpStart,tmpEnd-tmpStart);
2302 tmp[tmpEnd-tmpStart] =
'\0';
2303 maxClockFrequency = strtol(tmp,(
char **) NULL,10);
2307 for (i = 0; i < profile->numDevices; i++) {
2308 if (profile->devices[i].type == DS_DEVICE_OPENCL_DEVICE) {
2309 size_t actualDeviceNameLength;
2310 size_t driverVersionLength;
2312 actualDeviceNameLength = strlen(profile->devices[i].oclDeviceName);
2313 driverVersionLength = strlen(profile->devices[i].oclDriverVersion);
2314 if (actualDeviceNameLength == (
size_t)(deviceNameEnd - deviceNameStart)
2315 && driverVersionLength == (
size_t)(deviceDriverEnd - deviceDriverStart)
2316 && maxComputeUnits == profile->devices[i].oclMaxComputeUnits
2317 && maxClockFrequency == profile->devices[i].oclMaxClockFrequency
2318 && strncmp(profile->devices[i].oclDeviceName, deviceNameStart, actualDeviceNameLength)==(
int)0
2319 && strncmp(profile->devices[i].oclDriverVersion, deviceDriverStart, driverVersionLength)==(
int)0) {
2321 deviceScoreStart = findString(dataStart, contentEnd, DS_TAG_SCORE);
2322 if (deviceNameStart==NULL) {
2323 status = DS_PROFILE_FILE_ERROR;
2326 deviceScoreStart+=strlen(DS_TAG_SCORE);
2327 deviceScoreEnd = findString(deviceScoreStart, contentEnd, DS_TAG_SCORE_END);
2328 status = deserializer(profile->devices+i, (
const unsigned char*)deviceScoreStart, deviceScoreEnd-deviceScoreStart);
2329 if (status != DS_SUCCESS) {
2337 else if (deviceType == DS_DEVICE_NATIVE_CPU) {
2338 for (i = 0; i < profile->numDevices; i++) {
2339 if (profile->devices[i].type == DS_DEVICE_NATIVE_CPU) {
2340 deviceScoreStart = findString(dataStart, contentEnd, DS_TAG_SCORE);
2341 if (deviceScoreStart==NULL) {
2342 status = DS_PROFILE_FILE_ERROR;
2345 deviceScoreStart+=strlen(DS_TAG_SCORE);
2346 deviceScoreEnd = findString(deviceScoreStart, contentEnd, DS_TAG_SCORE_END);
2347 status = deserializer(profile->devices+i, (
const unsigned char*)deviceScoreStart, deviceScoreEnd-deviceScoreStart);
2348 if (status != DS_SUCCESS) {
2356 currentPosition = dataEnd+strlen(DS_TAG_DEVICE_END);
2360 if (contentStart!=NULL) RelinquishMagickMemory(contentStart);
2366static ds_status getNumDeviceWithEmptyScore(ds_profile* profile,
unsigned int* num) {
2368 if (profile == NULL || num==NULL)
2369 return DS_MEMORY_ERROR;
2371 for (i = 0; i < profile->numDevices; i++) {
2372 if (profile->devices[i].score == NULL) {
2385typedef double AccelerateScoreType;
2387static ds_status AcceleratePerfEvaluator(ds_device *device,
2388 void *magick_unused(data))
2390#define ACCELERATE_PERF_DIMEN "2048x1536"
2392#define ReturnStatus(status) \
2394 if (oldClEnv != (MagickCLEnv) NULL) \
2395 defaultCLEnv=oldClEnv; \
2396 if (clEnv != (MagickCLEnv) NULL) \
2397 (void) RelinquishMagickOpenCLEnv(clEnv); \
2414 magick_unreferenced(data);
2417 ReturnStatus(DS_PERF_EVALUATOR_ERROR);
2419 clEnv=AcquireMagickOpenCLEnv();
2420 exception=AcquireExceptionInfo();
2422 if (device->type == DS_DEVICE_NATIVE_CPU)
2425 MagickBooleanType flag=MagickTrue;
2426 SetMagickOpenCLEnvParamInternal(clEnv,
2427 MAGICK_OPENCL_ENV_PARAM_OPENCL_DISABLED,
sizeof(MagickBooleanType),
2430 else if (device->type == DS_DEVICE_OPENCL_DEVICE)
2433 SetMagickOpenCLEnvParamInternal(clEnv,MAGICK_OPENCL_ENV_PARAM_DEVICE,
2434 sizeof(cl_device_id),&device->oclDeviceID,exception);
2437 ReturnStatus(DS_PERF_EVALUATOR_ERROR);
2440 clEnv->disableProgramCache = defaultCLEnv->disableProgramCache;
2442 status=InitOpenCLEnvInternal(clEnv,exception);
2443 oldClEnv=defaultCLEnv;
2447 if (status != MagickFalse)
2458 imageInfo=AcquireImageInfo();
2459 CloneString(&imageInfo->size,ACCELERATE_PERF_DIMEN);
2460 CopyMagickString(imageInfo->filename,
"xc:none",MaxTextExtent);
2461 inputImage=ReadImage(imageInfo,exception);
2462 if (inputImage == (Image *) NULL)
2463 ReturnStatus(DS_PERF_EVALUATOR_ERROR);
2465 initAccelerateTimer(&timer);
2467 for (i=0; i<=NUM_ITER; i++)
2481 startAccelerateTimer(&timer);
2483#ifdef MAGICKCORE_CLPERFMARKER
2484 clBeginPerfMarkerAMD(
"PerfEvaluatorRegion",
"");
2487 bluredImage=BlurImage(inputImage,10.0f,3.5f,exception);
2488 unsharpedImage=UnsharpMaskImage(bluredImage,2.0f,2.0f,50.0f,10.0f,
2490 resizedImage=ResizeImage(unsharpedImage,640,480,LanczosFilter,1.0,
2497 if (device->type != DS_DEVICE_NATIVE_CPU)
2499 events=GetOpenCLEvents(resizedImage,&event_count);
2500 if (event_count > 0)
2501 clEnv->library->clWaitForEvents(event_count,events);
2502 events=(cl_event *) RelinquishMagickMemory(events);
2505#ifdef MAGICKCORE_CLPERFMARKER
2506 clEndPerfMarkerAMD();
2510 stopAccelerateTimer(&timer);
2513 DestroyImage(bluredImage);
2515 DestroyImage(unsharpedImage);
2517 DestroyImage(resizedImage);
2519 DestroyImage(inputImage);
2523 if (device->score == NULL)
2524 device->score= AcquireMagickMemory(
sizeof(AccelerateScoreType));
2526 if (status != MagickFalse)
2527 *(AccelerateScoreType*) device->score=readAccelerateTimer(&timer);
2529 *(AccelerateScoreType*) device->score=42;
2531 ReturnStatus(DS_SUCCESS);
2534ds_status AccelerateScoreSerializer(ds_device* device,
void** serializedScore,
unsigned int* serializedScoreSize) {
2538 char* s = (
char*) AcquireQuantumMemory(256,
sizeof(
char));
2539 (void) FormatLocaleString(s,256,
"%.4f",*((AccelerateScoreType*)
2541 *serializedScore = (
void*)s;
2542 *serializedScoreSize = (
unsigned int) strlen(s);
2546 return DS_SCORE_SERIALIZER_ERROR;
2550ds_status AccelerateScoreDeserializer(ds_device* device,
const unsigned char* serializedScore,
unsigned int serializedScoreSize) {
2553 char* s = (
char*) AcquireQuantumMemory(1,serializedScoreSize+1);
2554 memcpy(s, serializedScore, serializedScoreSize);
2555 s[serializedScoreSize] = (char)
'\0';
2556 device->score = AcquireMagickMemory(
sizeof(AccelerateScoreType));
2557 *((AccelerateScoreType*)device->score) = (AccelerateScoreType)
2558 strtod(s, (
char **) NULL);
2559 RelinquishMagickMemory(s);
2563 return DS_SCORE_DESERIALIZER_ERROR;
2567ds_status AccelerateScoreRelease(
void* score) {
2569 RelinquishMagickMemory(score);
2574ds_status canWriteProfileToFile(
const char *path)
2576 FILE* profileFile = fopen(path,
"ab");
2578 if (profileFile==NULL)
2579 return DS_FILE_ERROR;
2581 fclose(profileFile);
2586#define IMAGEMAGICK_PROFILE_VERSION "ImageMagick Device Selection v0.9"
2587#define IMAGEMAGICK_PROFILE_FILE "ImagemagickOpenCLDeviceProfile"
2588static MagickBooleanType autoSelectDevice(MagickCLEnv clEnv, ExceptionInfo* exception) {
2590 MagickBooleanType mStatus = MagickFalse;
2592 ds_profile* profile;
2593 unsigned int numDeviceProfiled = 0;
2595 unsigned int bestDeviceIndex;
2596 AccelerateScoreType bestScore;
2597 char path[MaxTextExtent];
2598 MagickBooleanType flag;
2599 ds_evaluation_type profileType;
2601 LockDefaultOpenCLEnv();
2605 SetMagickOpenCLEnvParamInternal(clEnv, MAGICK_OPENCL_ENV_PARAM_OPENCL_DISABLED
2606 ,
sizeof(MagickBooleanType), &flag, exception);
2609 OpenCLLib=GetOpenCLLib();
2610 if (OpenCLLib==NULL)
2612 mStatus=InitOpenCLEnvInternal(clEnv, exception);
2616 clEnv->library=OpenCLLib;
2618 status = initDSProfile(&profile, IMAGEMAGICK_PROFILE_VERSION);
2619 if (status!=DS_SUCCESS) {
2620 (void) ThrowMagickException(exception, GetMagickModule(), ModuleFatalError,
"Error when initializing the profile",
"'%s'",
".");
2624 (void) FormatLocaleString(path,MaxTextExtent,
"%s%s%s"
2625 ,GetOpenCLCachedFilesDirectory()
2626 ,DirectorySeparator,IMAGEMAGICK_PROFILE_FILE);
2628 if (canWriteProfileToFile(path) != DS_SUCCESS) {
2632 bestDeviceIndex = 0;
2633 for (i = 1; i < profile->numDevices; i++) {
2634 if ((profile->devices[i].type == DS_DEVICE_OPENCL_DEVICE) && (profile->devices[i].oclDeviceType == CL_DEVICE_TYPE_GPU)) {
2635 bestDeviceIndex = i;
2641 if (clEnv->regenerateProfile != MagickFalse) {
2642 profileType = DS_EVALUATE_ALL;
2645 readProfileFromFile(profile, AccelerateScoreDeserializer, path);
2646 profileType = DS_EVALUATE_NEW_ONLY;
2648 status = profileDevices(profile, profileType, AcceleratePerfEvaluator, NULL, &numDeviceProfiled);
2650 if (status!=DS_SUCCESS) {
2651 (void) ThrowMagickException(exception, GetMagickModule(), ModuleFatalError,
"Error when initializing the profile",
"'%s'",
".");
2654 if (numDeviceProfiled > 0) {
2655 status = writeProfileToFile(profile, AccelerateScoreSerializer, path);
2656 if (status!=DS_SUCCESS) {
2657 (void) ThrowMagickException(exception, GetMagickModule(), ModuleWarning,
"Error when saving the profile into a file",
"'%s'",
".");
2662 bestDeviceIndex = 0;
2663 bestScore = *(AccelerateScoreType*)profile->devices[bestDeviceIndex].score;
2664 for (i = 1; i < profile->numDevices; i++) {
2665 AccelerateScoreType score = *(AccelerateScoreType*)profile->devices[i].score;
2666 if (score < bestScore) {
2667 bestDeviceIndex = i;
2674 if (profile->devices[bestDeviceIndex].type == DS_DEVICE_NATIVE_CPU) {
2677 SetMagickOpenCLEnvParamInternal(clEnv, MAGICK_OPENCL_ENV_PARAM_OPENCL_DISABLED
2678 ,
sizeof(MagickBooleanType), &flag, exception);
2680 else if (profile->devices[bestDeviceIndex].type == DS_DEVICE_OPENCL_DEVICE) {
2683 SetMagickOpenCLEnvParamInternal(clEnv, MAGICK_OPENCL_ENV_PARAM_OPENCL_DISABLED
2684 ,
sizeof(MagickBooleanType), &flag, exception);
2685 SetMagickOpenCLEnvParamInternal(clEnv, MAGICK_OPENCL_ENV_PARAM_DEVICE
2686 ,
sizeof(cl_device_id), &profile->devices[bestDeviceIndex].oclDeviceID,exception);
2689 status = DS_PERF_EVALUATOR_ERROR;
2692 mStatus=InitOpenCLEnvInternal(clEnv, exception);
2694 status = releaseDSProfile(profile, AccelerateScoreRelease);
2695 if (status!=DS_SUCCESS) {
2696 (void) ThrowMagickException(exception, GetMagickModule(), ModuleWarning,
"Error when releasing the profile",
"'%s'",
".");
2701 UnlockDefaultOpenCLEnv();
2739MagickExport MagickBooleanType InitImageMagickOpenCL(
2740 ImageMagickOpenCLMode mode,
void *userSelectedDevice,
void *selectedDevice,
2741 ExceptionInfo *exception)
2743 MagickBooleanType status = MagickFalse;
2744 MagickCLEnv clEnv = NULL;
2745 MagickBooleanType flag;
2747 clEnv = GetDefaultOpenCLEnv();
2751 case MAGICK_OPENCL_OFF:
2753 SetMagickOpenCLEnvParam(clEnv, MAGICK_OPENCL_ENV_PARAM_OPENCL_DISABLED
2754 ,
sizeof(MagickBooleanType), &flag, exception);
2755 status = InitOpenCLEnv(clEnv, exception);
2758 *(cl_device_id*)selectedDevice = NULL;
2761 case MAGICK_OPENCL_DEVICE_SELECT_USER:
2763 if (userSelectedDevice == NULL)
2767 SetMagickOpenCLEnvParam(clEnv, MAGICK_OPENCL_ENV_PARAM_OPENCL_DISABLED
2768 ,
sizeof(MagickBooleanType), &flag, exception);
2770 SetMagickOpenCLEnvParam(clEnv, MAGICK_OPENCL_ENV_PARAM_DEVICE
2771 ,
sizeof(cl_device_id), userSelectedDevice,exception);
2773 status = InitOpenCLEnv(clEnv, exception);
2774 if (selectedDevice) {
2775 GetMagickOpenCLEnvParam(clEnv, MAGICK_OPENCL_ENV_PARAM_DEVICE
2776 ,
sizeof(cl_device_id), selectedDevice, exception);
2780 case MAGICK_OPENCL_DEVICE_SELECT_AUTO_CLEAR_CACHE:
2782 SetMagickOpenCLEnvParam(clEnv, MAGICK_OPENCL_ENV_PARAM_PROGRAM_CACHE_DISABLED
2783 ,
sizeof(MagickBooleanType), &flag, exception);
2785 SetMagickOpenCLEnvParam(clEnv, MAGICK_OPENCL_ENV_PARAM_REGENERATE_PROFILE
2786 ,
sizeof(MagickBooleanType), &flag, exception);
2789 case MAGICK_OPENCL_DEVICE_SELECT_AUTO:
2792 cl_device_id d = NULL;
2794 SetMagickOpenCLEnvParam(clEnv, MAGICK_OPENCL_ENV_PARAM_OPENCL_DISABLED
2795 ,
sizeof(MagickBooleanType), &flag, exception);
2796 SetMagickOpenCLEnvParam(clEnv, MAGICK_OPENCL_ENV_PARAM_DEVICE
2797 ,
sizeof(cl_device_id), &d,exception);
2798 status = InitOpenCLEnv(clEnv, exception);
2799 if (selectedDevice) {
2800 GetMagickOpenCLEnvParam(clEnv, MAGICK_OPENCL_ENV_PARAM_DEVICE
2801 ,
sizeof(cl_device_id), selectedDevice, exception);
2812MagickBooleanType OpenCLThrowMagickException(ExceptionInfo *exception,
2813 const char *module,
const char *function,
const size_t line,
2814 const ExceptionType severity,
const char *tag,
const char *format,...) {
2820 status = MagickTrue;
2822 clEnv = GetDefaultOpenCLEnv();
2824 assert(exception != (ExceptionInfo *) NULL);
2825 assert(exception->signature == MagickCoreSignature);
2828 cl_device_type dType;
2829 clEnv->library->clGetDeviceInfo(clEnv->device,CL_DEVICE_TYPE ,
sizeof(cl_device_type),&dType,NULL);
2830 if (dType == CL_DEVICE_TYPE_CPU) {
2831 char buffer[MaxTextExtent];
2832 clEnv->library->clGetPlatformInfo(clEnv->platform, CL_PLATFORM_NAME, MaxTextExtent, buffer, NULL);
2836 if (strncmp(buffer,
"Intel",5) == 0) {
2838 InitImageMagickOpenCL(MAGICK_OPENCL_OFF, NULL, NULL, exception);
2843#ifdef OPENCLLOG_ENABLED
2847 va_start(operands,format);
2848 status=ThrowMagickExceptionList(exception,module,function,line,severity,tag, format,operands);
2852 magick_unreferenced(module);
2853 magick_unreferenced(function);
2854 magick_unreferenced(line);
2855 magick_unreferenced(tag);
2856 magick_unreferenced(format);
2862char* openclCachedFilesDirectory;
2866const char* GetOpenCLCachedFilesDirectory() {
2867 if (openclCachedFilesDirectory == NULL) {
2868 if (openclCachedFilesDirectoryLock == NULL)
2870 ActivateSemaphoreInfo(&openclCachedFilesDirectoryLock);
2872 LockSemaphoreInfo(openclCachedFilesDirectoryLock);
2873 if (openclCachedFilesDirectory == NULL) {
2874 char path[MaxTextExtent];
2877 struct stat attributes;
2878 MagickBooleanType status;
2879 int mkdirStatus = 0;
2883 home=GetEnvironmentValue(
"MAGICK_OPENCL_CACHE_DIR");
2884 if (home == (
char *) NULL)
2886 home=GetEnvironmentValue(
"XDG_CACHE_HOME");
2887#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__MINGW32__)
2888 if (home == (
char *) NULL)
2889 home=GetEnvironmentValue(
"LOCALAPPDATA");
2890 if (home == (
char *) NULL)
2891 home=GetEnvironmentValue(
"APPDATA");
2892 if (home == (
char *) NULL)
2893 home=GetEnvironmentValue(
"USERPROFILE");
2897 if (home != (
char *) NULL)
2900 (void) FormatLocaleString(path,MaxTextExtent,
"%s",home);
2901 status=GetPathAttributes(path,&attributes);
2902 if (status == MagickFalse)
2905#ifdef MAGICKCORE_WINDOWS_SUPPORT
2906 mkdirStatus = mkdir(path);
2908 mkdirStatus = mkdir(path, 0777);
2915 (void) FormatLocaleString(path,MaxTextExtent,
2916 "%s%sImageMagick",home,DirectorySeparator);
2918 status=GetPathAttributes(path,&attributes);
2919 if (status == MagickFalse)
2921#ifdef MAGICKCORE_WINDOWS_SUPPORT
2922 mkdirStatus = mkdir(path);
2924 mkdirStatus = mkdir(path, 0777);
2931 temp = (
char*)AcquireCriticalMemory(strlen(path)+1);
2932 CopyMagickString(temp,path,strlen(path)+1);
2934 home=DestroyString(home);
2936 home=GetEnvironmentValue(
"HOME");
2937 if (home != (
char *) NULL)
2943 (void) FormatLocaleString(path,MaxTextExtent,
"%s%s.cache",
2944 home,DirectorySeparator);
2945 status=GetPathAttributes(path,&attributes);
2946 if (status == MagickFalse)
2949#ifdef MAGICKCORE_WINDOWS_SUPPORT
2950 mkdirStatus = mkdir(path);
2952 mkdirStatus = mkdir(path, 0777);
2959 (void) FormatLocaleString(path,MaxTextExtent,
2960 "%s%s.cache%sImageMagick",home,DirectorySeparator,
2961 DirectorySeparator);
2963 status=GetPathAttributes(path,&attributes);
2964 if (status == MagickFalse)
2966#ifdef MAGICKCORE_WINDOWS_SUPPORT
2967 mkdirStatus = mkdir(path);
2969 mkdirStatus = mkdir(path, 0777);
2976 temp = (
char*)AcquireCriticalMemory(strlen(path)+1);
2977 CopyMagickString(temp,path,strlen(path)+1);
2979 home=DestroyString(home);
2982 openclCachedFilesDirectory = temp;
2984 UnlockSemaphoreInfo(openclCachedFilesDirectoryLock);
2986 return openclCachedFilesDirectory;
2991void OpenCLLog(
const char* message) {
2993#ifdef OPENCLLOG_ENABLED
2994#define OPENCL_LOG_FILE "ImageMagickOpenCL.log"
2997 if (getenv(
"MAGICK_OCL_LOG"))
3000 char path[MaxTextExtent];
3001 unsigned long allocSize;
3005 clEnv = GetDefaultOpenCLEnv();
3008 (void) FormatLocaleString(path,MaxTextExtent,
"%s%s%s"
3009 ,GetOpenCLCachedFilesDirectory()
3010 ,DirectorySeparator,OPENCL_LOG_FILE);
3013 log = fopen(path,
"ab");
3014 if (log == (FILE *) NULL)
3016 fwrite(message,
sizeof(
char), strlen(message), log);
3017 fwrite(
"\n",
sizeof(
char), 1, log);
3019 if (clEnv->OpenCLInitialized && !clEnv->OpenCLDisabled)
3021 allocSize = GetOpenCLDeviceMaxMemAllocSize(clEnv);
3022 fprintf(log,
"Devic Max Memory Alloc Size: %lu\n", allocSize);
3029 magick_unreferenced(message);
3033MagickPrivate
void OpenCLTerminus()
3036 if (openclCachedFilesDirectory != (
char *) NULL)
3037 openclCachedFilesDirectory=DestroyString(openclCachedFilesDirectory);
3039 DestroySemaphoreInfo(&openclCachedFilesDirectoryLock);
3040 if (defaultCLEnv != (MagickCLEnv) NULL)
3042 (void) RelinquishMagickOpenCLEnv(defaultCLEnv);
3043 defaultCLEnv=(MagickCLEnv)NULL;
3046 DestroySemaphoreInfo(&defaultCLEnvLock);
3047 if (OpenCLLib != (MagickLibrary *)NULL)
3049 if (OpenCLLib->base != (
void *) NULL)
3050 (void) lt_dlclose(OpenCLLib->base);
3051 OpenCLLib=(MagickLibrary *)RelinquishMagickMemory(OpenCLLib);
3054 DestroySemaphoreInfo(&OpenCLLibLock);
3060 MagickBooleanType OpenCLInitialized;
3066MagickExport MagickCLEnv GetDefaultOpenCLEnv()
3068 return (MagickCLEnv) NULL;
3071MagickExport MagickBooleanType SetMagickOpenCLEnvParam(
3072 MagickCLEnv magick_unused(clEnv),MagickOpenCLEnvParam magick_unused(param),
3073 size_t magick_unused(dataSize),
void *magick_unused(data),
3074 ExceptionInfo *magick_unused(exception))
3076 magick_unreferenced(clEnv);
3077 magick_unreferenced(param);
3078 magick_unreferenced(dataSize);
3079 magick_unreferenced(data);
3080 magick_unreferenced(exception);
3081 return(MagickFalse);
3084MagickExport MagickBooleanType GetMagickOpenCLEnvParam(
3085 MagickCLEnv magick_unused(clEnv),MagickOpenCLEnvParam magick_unused(param),
3086 size_t magick_unused(dataSize),
void *magick_unused(data),
3087 ExceptionInfo *magick_unused(exception))
3089 magick_unreferenced(clEnv);
3090 magick_unreferenced(param);
3091 magick_unreferenced(dataSize);
3092 magick_unreferenced(data);
3093 magick_unreferenced(exception);
3094 return(MagickFalse);
3097MagickExport MagickBooleanType InitOpenCLEnv(MagickCLEnv magick_unused(clEnv),
3098 ExceptionInfo *magick_unused(exception))
3100 magick_unreferenced(clEnv);
3101 magick_unreferenced(exception);
3102 return(MagickFalse);
3105MagickExport MagickBooleanType InitImageMagickOpenCL(
3106 ImageMagickOpenCLMode magick_unused(mode),
3107 void *magick_unused(userSelectedDevice),
void *magick_unused(selectedDevice),
3108 ExceptionInfo *magick_unused(exception))
3110 magick_unreferenced(mode);
3111 magick_unreferenced(userSelectedDevice);
3112 magick_unreferenced(selectedDevice);
3113 magick_unreferenced(exception);
3114 return(MagickFalse);