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);
335 clEnv->commandQueuesPos=-1;
336 ActivateSemaphoreInfo(&clEnv->lock);
337 ActivateSemaphoreInfo(&clEnv->commandQueuesLock);
366MagickPrivate MagickBooleanType RelinquishMagickOpenCLEnv(
MagickCLEnv clEnv)
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);
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);
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);
585 LockDefaultOpenCLEnv();
586 oldEnv = defaultCLEnv;
587 defaultCLEnv = clEnv;
588 UnlockDefaultOpenCLEnv();
625static MagickBooleanType SetMagickOpenCLEnvParamInternal(
MagickCLEnv clEnv, MagickOpenCLEnvParam param
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
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
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);
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,
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 for (i = 0; i < num_devices; i++)
915 binary_program[i]=(
unsigned char *) AcquireQuantumMemory(
916 MagickMax(*(program_sizes+i),1),
sizeof(**binary_program));
917 if (binary_program[i] == (
unsigned char *) NULL)
919 status=CL_OUT_OF_HOST_MEMORY;
923 if (status == CL_SUCCESS)
924 status=clEnv->library->clGetProgramInfo(clEnv->programs[prog],
925 CL_PROGRAM_BINARIES,binary_program_size,binary_program,NULL);
926 if (status == CL_SUCCESS)
928 for (i = 0; i < num_devices; i++)
936 program_size=*(program_sizes+i);
937 if (program_size < 1)
939 file=open_utf8(filename,O_WRONLY | O_CREAT | O_BINARY,S_MODE);
942 write(file,binary_program[i],program_size);
946 (
void) ThrowMagickException(exception,GetMagickModule(),
947 DelegateWarning,
"Saving kernel failed.",
"`%s'",filename);
951 for (i = 0; i < num_devices; i++)
952 binary_program[i]=(
unsigned char *) RelinquishMagickMemory(
954 binary_program=(
unsigned char **) RelinquishMagickMemory(binary_program);
956 program_sizes=(
size_t *) RelinquishMagickMemory(program_sizes);
959static MagickBooleanType loadBinaryCLProgram(
MagickCLEnv clEnv, MagickOpenCLProgram prog,
unsigned int signature)
961 MagickBooleanType loadSuccessful;
962 unsigned char* binaryProgram;
963 char* binaryFileName;
966#ifdef MAGICKCORE_CLPERFMARKER
967 clBeginPerfMarkerAMD(__FUNCTION__,
"");
970 binaryProgram = NULL;
971 binaryFileName = NULL;
973 loadSuccessful = MagickFalse;
975 binaryFileName = getBinaryCLProgramName(clEnv, prog, signature);
976 fileHandle = fopen(binaryFileName,
"rb");
977 if (fileHandle != NULL)
982 cl_int clBinaryStatus;
986 b_error |= fseek( fileHandle, 0, SEEK_END ) < 0;
987 b_error |= ( length = ftell( fileHandle ) ) <= 0;
988 b_error |= fseek( fileHandle, 0, SEEK_SET ) < 0;
992 binaryProgram = (
unsigned char*)AcquireMagickMemory(length);
993 if (binaryProgram == NULL)
996 memset(binaryProgram, 0, length);
997 b_error |= fread(binaryProgram, 1, length, fileHandle) != length;
999 clEnv->programs[prog] = clEnv->library->clCreateProgramWithBinary(clEnv->context, 1, &clEnv->device, &length, (
const unsigned char**)&binaryProgram, &clBinaryStatus, &clStatus);
1000 if (clStatus != CL_SUCCESS
1001 || clBinaryStatus != CL_SUCCESS)
1004 loadSuccessful = MagickTrue;
1008 if (fileHandle != NULL)
1010 if (binaryFileName != NULL)
1011 RelinquishMagickMemory(binaryFileName);
1012 if (binaryProgram != NULL)
1013 RelinquishMagickMemory(binaryProgram);
1015#ifdef MAGICKCORE_CLPERFMARKER
1016 clEndPerfMarkerAMD();
1019 return loadSuccessful;
1022static unsigned int stringSignature(
const char*
string)
1024 unsigned int stringLength;
1026 unsigned int signature;
1030 const unsigned int* u;
1033#ifdef MAGICKCORE_CLPERFMARKER
1034 clBeginPerfMarkerAMD(__FUNCTION__,
"");
1037 stringLength = (
unsigned int) strlen(
string);
1038 signature = stringLength;
1039 n = stringLength/
sizeof(
unsigned int);
1041 for (i = 0; i < n; i++)
1045 if (n *
sizeof(
unsigned int) != stringLength)
1048 j = n *
sizeof(
unsigned int);
1049 for (i = 0; i < 4; i++,j++)
1051 if (j < stringLength)
1060#ifdef MAGICKCORE_CLPERFMARKER
1061 clEndPerfMarkerAMD();
1068extern const char *accelerateKernels, *accelerateKernels2;
1072 MagickBooleanType status = MagickFalse;
1075 char* accelerateKernelsBuffer = NULL;
1078 const char* MagickOpenCLProgramStrings[MAGICK_OPENCL_NUM_PROGRAMS];
1080 char options[MaxTextExtent];
1081 unsigned int optionsSignature;
1083#ifdef MAGICKCORE_CLPERFMARKER
1084 clBeginPerfMarkerAMD(__FUNCTION__,
"");
1088 (void) FormatLocaleString(options, MaxTextExtent, CLOptions, (
float)QuantumRange,
1089 (
float)QuantumScale, (
float)CLCharQuantumScale, (
float)MagickEpsilon, (
float)MagickPI, (
unsigned int)MaxMap, (
unsigned int)MAGICKCORE_QUANTUM_DEPTH);
1104 optionsSignature = stringSignature(options);
1107 accelerateKernelsBuffer = (
char*) AcquireQuantumMemory(1,strlen(accelerateKernels)+strlen(accelerateKernels2)+1);
1108 FormatLocaleString(accelerateKernelsBuffer,strlen(accelerateKernels)+
1109 strlen(accelerateKernels2)+1,
"%s%s",accelerateKernels,accelerateKernels2);
1110 MagickOpenCLProgramStrings[MAGICK_OPENCL_ACCELERATE] = accelerateKernelsBuffer;
1112 for (i = 0; i < MAGICK_OPENCL_NUM_PROGRAMS; i++)
1114 MagickBooleanType loadSuccessful = MagickFalse;
1115 unsigned int programSignature = stringSignature(MagickOpenCLProgramStrings[i]) ^ optionsSignature;
1118 if (clEnv->disableProgramCache != MagickTrue
1119 && !getenv(
"MAGICK_OCL_REC"))
1120 loadSuccessful = loadBinaryCLProgram(clEnv, (MagickOpenCLProgram)i, programSignature);
1122 if (loadSuccessful == MagickFalse)
1125 size_t programLength = strlen(MagickOpenCLProgramStrings[i]);
1126 clEnv->programs[i] = clEnv->library->clCreateProgramWithSource(clEnv->context, 1, &(MagickOpenCLProgramStrings[i]), &programLength, &clStatus);
1127 if (clStatus!=CL_SUCCESS)
1129 (void) ThrowMagickException(exception, GetMagickModule(), DelegateWarning,
1130 "clCreateProgramWithSource failed.",
"(%d)", (
int)clStatus);
1136 clStatus = clEnv->library->clBuildProgram(clEnv->programs[i], 1, &clEnv->device, options, NULL, NULL);
1137 if (clStatus!=CL_SUCCESS)
1139 (void) ThrowMagickException(exception, GetMagickModule(), DelegateWarning,
1140 "clBuildProgram failed.",
"(%d)", (
int)clStatus);
1142 if (loadSuccessful == MagickFalse)
1144 char path[MaxTextExtent];
1148 (void) FormatLocaleString(path,MaxTextExtent,
"%s%s%s"
1149 ,GetOpenCLCachedFilesDirectory()
1150 ,DirectorySeparator,
"magick_badcl.cl");
1151 fileHandle = fopen(path,
"wb");
1152 if (fileHandle != NULL)
1154 fwrite(MagickOpenCLProgramStrings[i],
sizeof(
char), strlen(MagickOpenCLProgramStrings[i]), fileHandle);
1162 clEnv->library->clGetProgramBuildInfo(clEnv->programs[i], clEnv->device, CL_PROGRAM_BUILD_LOG, 0, NULL, &logSize);
1163 log = (
char*)AcquireCriticalMemory(logSize);
1164 clEnv->library->clGetProgramBuildInfo(clEnv->programs[i], clEnv->device, CL_PROGRAM_BUILD_LOG, logSize, log, &logSize);
1166 (void) FormatLocaleString(path,MaxTextExtent,
"%s%s%s"
1167 ,GetOpenCLCachedFilesDirectory()
1168 ,DirectorySeparator,
"magick_badcl_build.log");
1169 fileHandle = fopen(path,
"wb");
1170 if (fileHandle != NULL)
1172 const char* buildOptionsTitle =
"build options: ";
1173 fwrite(buildOptionsTitle,
sizeof(
char), strlen(buildOptionsTitle), fileHandle);
1174 fwrite(options,
sizeof(
char), strlen(options), fileHandle);
1175 fwrite(
"\n",
sizeof(
char), 1, fileHandle);
1176 fwrite(log,
sizeof(
char), logSize, fileHandle);
1179 RelinquishMagickMemory(log);
1185 if (loadSuccessful == MagickFalse)
1188 saveBinaryCLProgram(clEnv, (MagickOpenCLProgram)i, programSignature, exception);
1192 status = MagickTrue;
1196 if (accelerateKernelsBuffer!=NULL) RelinquishMagickMemory(accelerateKernelsBuffer);
1198#ifdef MAGICKCORE_CLPERFMARKER
1199 clEndPerfMarkerAMD();
1208 cl_uint numPlatforms = 0;
1209 cl_platform_id *platforms = NULL;
1210 char* MAGICK_OCL_DEVICE = NULL;
1211 MagickBooleanType OpenCLAvailable = MagickFalse;
1213#ifdef MAGICKCORE_CLPERFMARKER
1214 clBeginPerfMarkerAMD(__FUNCTION__,
"");
1218 MAGICK_OCL_DEVICE = getenv(
"MAGICK_OCL_DEVICE");
1219 if (MAGICK_OCL_DEVICE == (
char *) NULL)
1220 return(MagickFalse);
1221 if (strcmp(MAGICK_OCL_DEVICE,
"CPU") == 0)
1222 clEnv->deviceType = CL_DEVICE_TYPE_CPU;
1223 else if (strcmp(MAGICK_OCL_DEVICE,
"GPU") == 0)
1224 clEnv->deviceType = CL_DEVICE_TYPE_GPU;
1225 else if (IsStringTrue(MAGICK_OCL_DEVICE) != MagickFalse)
1227 if (clEnv->deviceType == 0)
1228 clEnv->deviceType = CL_DEVICE_TYPE_ALL;
1231 return(MagickFalse);
1233 if (clEnv->device != NULL)
1235 status = clEnv->library->clGetDeviceInfo(clEnv->device, CL_DEVICE_PLATFORM,
sizeof(cl_platform_id), &clEnv->platform, NULL);
1236 if (status != CL_SUCCESS) {
1237 (void) ThrowMagickException(exception, GetMagickModule(), DelegateWarning,
1238 "Failed to get OpenCL platform from the selected device.",
"(%d)", status);
1242 else if (clEnv->platform != NULL)
1245 platforms = (cl_platform_id *) AcquireQuantumMemory(1,numPlatforms *
sizeof(cl_platform_id));
1246 if (platforms == (cl_platform_id *) NULL)
1248 (void) ThrowMagickException(exception, GetMagickModule(), ResourceLimitError,
1249 "AcquireMagickMemory failed.",
".");
1252 platforms[0] = clEnv->platform;
1256 clEnv->device = NULL;
1259 status = clEnv->library->clGetPlatformIDs(0, NULL, &numPlatforms);
1260 if (status != CL_SUCCESS)
1262 (void) ThrowMagickException(exception, GetMagickModule(), DelegateWarning,
1263 "clGetplatformIDs failed.",
"(%d)", status);
1268 if (numPlatforms == 0) {
1272 platforms = (cl_platform_id *) AcquireQuantumMemory(1,numPlatforms *
sizeof(cl_platform_id));
1273 if (platforms == (cl_platform_id *) NULL)
1275 (void) ThrowMagickException(exception, GetMagickModule(), ResourceLimitError,
1276 "AcquireMagickMemory failed.",
".");
1280 status = clEnv->library->clGetPlatformIDs(numPlatforms, platforms, NULL);
1281 if (status != CL_SUCCESS)
1283 (void) ThrowMagickException(exception, GetMagickModule(), DelegateWarning,
1284 "clGetPlatformIDs failed.",
"(%d)", status);
1290 clEnv->device = NULL;
1291 for (j = 0; j < 2; j++)
1294 cl_device_type deviceType;
1295 if (clEnv->deviceType == CL_DEVICE_TYPE_ALL)
1298 deviceType = CL_DEVICE_TYPE_GPU;
1300 deviceType = CL_DEVICE_TYPE_CPU;
1307 deviceType = clEnv->deviceType;
1309 for (i = 0; i < numPlatforms; i++)
1311 char version[MaxTextExtent];
1313 status = clEnv->library->clGetPlatformInfo(clEnv->platform, CL_PLATFORM_VERSION, MaxTextExtent, version, NULL);
1314 if (status != CL_SUCCESS)
1316 (void) ThrowMagickException(exception, GetMagickModule(), DelegateWarning,
1317 "clGetPlatformInfo failed.",
"(%d)", status);
1320 if (strncmp(version,
"OpenCL 1.0 ",11) == 0)
1322 status = clEnv->library->clGetDeviceIDs(platforms[i], deviceType, 1, &(clEnv->device), &numDevices);
1323 if (status != CL_SUCCESS)
1325 (void) ThrowMagickException(exception, GetMagickModule(), DelegateWarning,
1326 "clGetDeviceIDs failed.",
"(%d)", status);
1329 if (clEnv->device != NULL)
1331 clEnv->platform = platforms[i];
1338 if (platforms!=NULL)
1339 RelinquishMagickMemory(platforms);
1341 OpenCLAvailable = (clEnv->platform!=NULL
1342 && clEnv->device!=NULL)?MagickTrue:MagickFalse;
1344#ifdef MAGICKCORE_CLPERFMARKER
1345 clEndPerfMarkerAMD();
1348 return OpenCLAvailable;
1351static MagickBooleanType EnableOpenCLInternal(
MagickCLEnv clEnv) {
1352 if (clEnv->OpenCLInitialized != MagickFalse
1353 && clEnv->platform != NULL
1354 && clEnv->device != NULL) {
1355 clEnv->OpenCLDisabled = MagickFalse;
1358 clEnv->OpenCLDisabled = MagickTrue;
1389static void RelinquishCommandQueues(
MagickCLEnv clEnv)
1394 LockSemaphoreInfo(clEnv->commandQueuesLock);
1395 while (clEnv->commandQueuesPos >= 0)
1396 clEnv->library->clReleaseCommandQueue(
1397 clEnv->commandQueues[clEnv->commandQueuesPos--]);
1398 UnlockSemaphoreInfo(clEnv->commandQueuesLock);
1403 MagickBooleanType status = MagickTrue;
1405 cl_context_properties cps[3];
1407#ifdef MAGICKCORE_CLPERFMARKER
1409 int status = clInitializePerfMarkerAMD();
1410 if (status == AP_SUCCESS) {
1415 clEnv->OpenCLInitialized = MagickTrue;
1418 OpenCLLib=GetOpenCLLib();
1421 clEnv->library=OpenCLLib;
1426 MagickBooleanType flag;
1428 SetMagickOpenCLEnvParamInternal(clEnv, MAGICK_OPENCL_ENV_PARAM_OPENCL_DISABLED
1429 ,
sizeof(MagickBooleanType), &flag, exception);
1432 if (clEnv->OpenCLDisabled != MagickFalse)
1435 clEnv->OpenCLDisabled = MagickTrue;
1437 status = InitOpenCLPlatformDevice(clEnv, exception);
1438 if (status == MagickFalse) {
1444 cps[0] = CL_CONTEXT_PLATFORM;
1445 cps[1] = (cl_context_properties)clEnv->platform;
1447 clEnv->context = clEnv->library->clCreateContext(cps, 1, &(clEnv->device), NULL, NULL, &clStatus);
1448 if (clStatus != CL_SUCCESS)
1450 (void) ThrowMagickException(exception, GetMagickModule(), DelegateWarning,
1451 "clCreateContext failed.",
"(%d)", clStatus);
1452 status = MagickFalse;
1456 RelinquishCommandQueues(clEnv);
1458 status = CompileOpenCLKernels(clEnv, exception);
1459 if (status == MagickFalse) {
1460 (void) ThrowMagickException(exception, GetMagickModule(), DelegateWarning,
1461 "clCreateCommandQueue failed.",
"(%d)", status);
1466 status = EnableOpenCLInternal(clEnv);
1475 MagickBooleanType status = MagickFalse;
1477 if ((clEnv == NULL) || (getenv(
"MAGICK_OCL_DEVICE") == (
const char *) NULL))
1480#ifdef MAGICKCORE_CLPERFMARKER
1481 clBeginPerfMarkerAMD(__FUNCTION__,
"");
1484 LockSemaphoreInfo(clEnv->lock);
1485 if (clEnv->OpenCLInitialized == MagickFalse) {
1486 if (clEnv->device==NULL && clEnv->OpenCLDisabled == MagickFalse)
1487 status = autoSelectDevice(clEnv, exception);
1489 status = InitOpenCLEnvInternal(clEnv, exception);
1491 UnlockSemaphoreInfo(clEnv->lock);
1493#ifdef MAGICKCORE_CLPERFMARKER
1494 clEndPerfMarkerAMD();
1523MagickPrivate cl_command_queue AcquireOpenCLCommandQueue(
MagickCLEnv clEnv)
1528 cl_command_queue_properties
1532 return (cl_command_queue) NULL;
1533 LockSemaphoreInfo(clEnv->commandQueuesLock);
1534 if (clEnv->commandQueuesPos >= 0) {
1535 queue=clEnv->commandQueues[clEnv->commandQueuesPos--];
1536 UnlockSemaphoreInfo(clEnv->commandQueuesLock);
1539 UnlockSemaphoreInfo(clEnv->commandQueuesLock);
1541#if PROFILE_OCL_KERNELS
1542 properties=CL_QUEUE_PROFILING_ENABLE;
1544 queue=clEnv->library->clCreateCommandQueue(clEnv->context,clEnv->device,
1577MagickPrivate MagickBooleanType RelinquishOpenCLCommandQueue(
MagickCLEnv clEnv,
1578 cl_command_queue queue)
1584 return(MagickFalse);
1586 LockSemaphoreInfo(clEnv->commandQueuesLock);
1588 if (clEnv->commandQueuesPos >= MAX_COMMAND_QUEUES-1)
1590 clEnv->library->clFinish(queue);
1591 status=(clEnv->library->clReleaseCommandQueue(queue) == CL_SUCCESS) ?
1592 MagickTrue : MagickFalse;
1596 clEnv->library->clFlush(queue);
1597 clEnv->commandQueues[++clEnv->commandQueuesPos]=queue;
1601 UnlockSemaphoreInfo(clEnv->commandQueuesLock);
1635 cl_kernel AcquireOpenCLKernel(
MagickCLEnv clEnv, MagickOpenCLProgram program,
const char* kernelName)
1638 cl_kernel kernel = NULL;
1639 if (clEnv != NULL && kernelName!=NULL)
1641 kernel = clEnv->library->clCreateKernel(clEnv->programs[program], kernelName, &clStatus);
1675 MagickBooleanType RelinquishOpenCLKernel(
MagickCLEnv clEnv, cl_kernel kernel)
1677 MagickBooleanType status = MagickFalse;
1678 if (clEnv != NULL && kernel != NULL)
1680 status = ((clEnv->library->clReleaseKernel(kernel) == CL_SUCCESS)?MagickTrue:MagickFalse);
1710 unsigned long GetOpenCLDeviceLocalMemorySize(
MagickCLEnv clEnv)
1712 cl_ulong localMemorySize;
1713 clEnv->library->clGetDeviceInfo(clEnv->device, CL_DEVICE_LOCAL_MEM_SIZE,
sizeof(cl_ulong), &localMemorySize, NULL);
1714 return (
unsigned long)localMemorySize;
1718 unsigned long GetOpenCLDeviceMaxMemAllocSize(
MagickCLEnv clEnv)
1720 cl_ulong maxMemAllocSize;
1721 clEnv->library->clGetDeviceInfo(clEnv->device, CL_DEVICE_MAX_MEM_ALLOC_SIZE,
sizeof(cl_ulong), &maxMemAllocSize, NULL);
1722 return (
unsigned long)maxMemAllocSize;
1733 ,DS_INVALID_PROFILE = 1000
1735 ,DS_INVALID_PERF_EVALUATOR_TYPE
1736 ,DS_INVALID_PERF_EVALUATOR
1737 ,DS_PERF_EVALUATOR_ERROR
1739 ,DS_UNKNOWN_DEVICE_TYPE
1740 ,DS_PROFILE_FILE_ERROR
1741 ,DS_SCORE_SERIALIZER_ERROR
1742 ,DS_SCORE_DESERIALIZER_ERROR
1747 DS_DEVICE_NATIVE_CPU = 0
1748 ,DS_DEVICE_OPENCL_DEVICE
1753 ds_device_type type;
1754 cl_device_type oclDeviceType;
1755 cl_device_id oclDeviceID;
1756 char* oclDeviceName;
1757 char* oclDriverVersion;
1758 cl_uint oclMaxClockFrequency;
1759 cl_uint oclMaxComputeUnits;
1764 unsigned int numDevices;
1766 const char* version;
1770typedef ds_status (*ds_score_release)(
void* score);
1772static ds_status releaseDeviceResource(ds_device* device, ds_score_release sr) {
1773 ds_status status = DS_SUCCESS;
1775 if (device->oclDeviceName) RelinquishMagickMemory(device->oclDeviceName);
1776 if (device->oclDriverVersion) RelinquishMagickMemory(device->oclDriverVersion);
1777 if (device->score) status = sr(device->score);
1782static ds_status releaseDSProfile(ds_profile* profile, ds_score_release sr) {
1783 ds_status status = DS_SUCCESS;
1784 if (profile!=NULL) {
1785 if (profile->devices!=NULL && sr!=NULL) {
1787 for (i = 0; i < profile->numDevices; i++) {
1788 status = releaseDeviceResource(profile->devices+i,sr);
1789 if (status != DS_SUCCESS)
1792 RelinquishMagickMemory(profile->devices);
1794 RelinquishMagickMemory(profile);
1800static ds_status initDSProfile(ds_profile** p,
const char* version) {
1802 cl_uint numPlatforms = 0;
1803 cl_platform_id* platforms = NULL;
1804 cl_device_id* devices = NULL;
1805 ds_status status = DS_SUCCESS;
1806 ds_profile* profile = NULL;
1807 unsigned int next = 0;
1811 return DS_INVALID_PROFILE;
1813 profile = (ds_profile*) AcquireMagickMemory(
sizeof(ds_profile));
1814 if (profile == NULL)
1815 return DS_MEMORY_ERROR;
1817 memset(profile, 0,
sizeof(ds_profile));
1819 OpenCLLib->clGetPlatformIDs(0, NULL, &numPlatforms);
1820 if (numPlatforms > 0) {
1821 platforms = (cl_platform_id*) AcquireQuantumMemory(numPlatforms,
sizeof(cl_platform_id));
1822 if (platforms == NULL) {
1823 status = DS_MEMORY_ERROR;
1826 OpenCLLib->clGetPlatformIDs(numPlatforms, platforms, NULL);
1827 for (i = 0; i < (
unsigned int)numPlatforms; i++) {
1829 if (OpenCLLib->clGetDeviceIDs(platforms[i], CL_DEVICE_TYPE_CPU | CL_DEVICE_TYPE_GPU, 0, NULL, &num) == CL_SUCCESS)
1834 profile->numDevices = numDevices+1;
1836 profile->devices = (ds_device*) AcquireQuantumMemory(profile->numDevices,
sizeof(ds_device));
1837 if (profile->devices == NULL) {
1838 profile->numDevices = 0;
1839 status = DS_MEMORY_ERROR;
1842 memset(profile->devices, 0, profile->numDevices*
sizeof(ds_device));
1844 if (numDevices > 0) {
1845 devices = (cl_device_id*) AcquireQuantumMemory(numDevices,
sizeof(cl_device_id));
1846 if (devices == NULL) {
1847 status = DS_MEMORY_ERROR;
1850 for (i = 0; i < (
unsigned int)numPlatforms; i++) {
1854 for (d = 0; d < 2; d++) {
1856 cl_device_type deviceType;
1859 deviceType = CL_DEVICE_TYPE_GPU;
1862 deviceType = CL_DEVICE_TYPE_CPU;
1868 if (OpenCLLib->clGetDeviceIDs(platforms[i], deviceType, numDevices, devices, &num) != CL_SUCCESS)
1870 for (j = 0; j < num; j++, next++) {
1873 profile->devices[next].type = DS_DEVICE_OPENCL_DEVICE;
1874 profile->devices[next].oclDeviceID = devices[j];
1876 OpenCLLib->clGetDeviceInfo(profile->devices[next].oclDeviceID, CL_DEVICE_NAME
1877 , 0, NULL, &length);
1878 profile->devices[next].oclDeviceName = (
char*) AcquireQuantumMemory(length,
sizeof(
char));
1879 OpenCLLib->clGetDeviceInfo(profile->devices[next].oclDeviceID, CL_DEVICE_NAME
1880 , length, profile->devices[next].oclDeviceName, NULL);
1882 OpenCLLib->clGetDeviceInfo(profile->devices[next].oclDeviceID, CL_DRIVER_VERSION
1883 , 0, NULL, &length);
1884 profile->devices[next].oclDriverVersion = (
char*) AcquireQuantumMemory(length,
sizeof(
char));
1885 OpenCLLib->clGetDeviceInfo(profile->devices[next].oclDeviceID, CL_DRIVER_VERSION
1886 , length, profile->devices[next].oclDriverVersion, NULL);
1888 OpenCLLib->clGetDeviceInfo(profile->devices[next].oclDeviceID, CL_DEVICE_MAX_CLOCK_FREQUENCY
1889 ,
sizeof(cl_uint), &profile->devices[next].oclMaxClockFrequency, NULL);
1891 OpenCLLib->clGetDeviceInfo(profile->devices[next].oclDeviceID, CL_DEVICE_MAX_COMPUTE_UNITS
1892 ,
sizeof(cl_uint), &profile->devices[next].oclMaxComputeUnits, NULL);
1894 OpenCLLib->clGetDeviceInfo(profile->devices[next].oclDeviceID, CL_DEVICE_TYPE
1895 ,
sizeof(cl_device_type), &profile->devices[next].oclDeviceType, NULL);
1901 profile->devices[next].type = DS_DEVICE_NATIVE_CPU;
1902 profile->version = version;
1905 if (platforms) RelinquishMagickMemory(platforms);
1906 if (devices) RelinquishMagickMemory(devices);
1907 if (status == DS_SUCCESS) {
1912 if (profile->devices)
1913 RelinquishMagickMemory(profile->devices);
1914 RelinquishMagickMemory(profile);
1924typedef ds_status (*ds_perf_evaluator)(ds_device* device,
void* data);
1928 ,DS_EVALUATE_NEW_ONLY
1929} ds_evaluation_type;
1931static ds_status profileDevices(ds_profile* profile,
const ds_evaluation_type type
1932 ,ds_perf_evaluator evaluator,
void* evaluatorData,
unsigned int* numUpdates) {
1933 ds_status status = DS_SUCCESS;
1935 unsigned int updates = 0;
1937 if (profile == NULL) {
1938 return DS_INVALID_PROFILE;
1940 if (evaluator == NULL) {
1941 return DS_INVALID_PERF_EVALUATOR;
1944 for (i = 0; i < profile->numDevices; i++) {
1945 ds_status evaluatorStatus;
1948 case DS_EVALUATE_NEW_ONLY:
1949 if (profile->devices[i].score != NULL)
1952 case DS_EVALUATE_ALL:
1953 evaluatorStatus = evaluator(profile->devices+i,evaluatorData);
1954 if (evaluatorStatus != DS_SUCCESS) {
1955 status = evaluatorStatus;
1961 return DS_INVALID_PERF_EVALUATOR_TYPE;
1966 *numUpdates = updates;
1971#define DS_TAG_VERSION "<version>"
1972#define DS_TAG_VERSION_END "</version>"
1973#define DS_TAG_DEVICE "<device>"
1974#define DS_TAG_DEVICE_END "</device>"
1975#define DS_TAG_SCORE "<score>"
1976#define DS_TAG_SCORE_END "</score>"
1977#define DS_TAG_DEVICE_TYPE "<type>"
1978#define DS_TAG_DEVICE_TYPE_END "</type>"
1979#define DS_TAG_DEVICE_NAME "<name>"
1980#define DS_TAG_DEVICE_NAME_END "</name>"
1981#define DS_TAG_DEVICE_DRIVER_VERSION "<driver>"
1982#define DS_TAG_DEVICE_DRIVER_VERSION_END "</driver>"
1983#define DS_TAG_DEVICE_MAX_COMPUTE_UNITS "<max cu>"
1984#define DS_TAG_DEVICE_MAX_COMPUTE_UNITS_END "</max cu>"
1985#define DS_TAG_DEVICE_MAX_CLOCK_FREQ "<max clock>"
1986#define DS_TAG_DEVICE_MAX_CLOCK_FREQ_END "</max clock>"
1988#define DS_DEVICE_NATIVE_CPU_STRING "native_cpu"
1992typedef ds_status (*ds_score_serializer)(ds_device* device,
void** serializedScore,
unsigned int* serializedScoreSize);
1993static ds_status writeProfileToFile(ds_profile* profile, ds_score_serializer serializer,
const char* file) {
1994 ds_status status = DS_SUCCESS;
1995 FILE* profileFile = NULL;
1998 if (profile == NULL)
1999 return DS_INVALID_PROFILE;
2001 profileFile = fopen(file,
"wb");
2002 if (profileFile==NULL) {
2003 status = DS_FILE_ERROR;
2009 fwrite(DS_TAG_VERSION,
sizeof(
char), strlen(DS_TAG_VERSION), profileFile);
2010 fwrite(profile->version,
sizeof(
char), strlen(profile->version), profileFile);
2011 fwrite(DS_TAG_VERSION_END,
sizeof(
char), strlen(DS_TAG_VERSION_END), profileFile);
2012 fwrite(
"\n",
sizeof(
char), 1, profileFile);
2014 for (i = 0; i < profile->numDevices && status == DS_SUCCESS; i++) {
2015 void* serializedScore;
2016 unsigned int serializedScoreSize;
2018 fwrite(DS_TAG_DEVICE,
sizeof(
char), strlen(DS_TAG_DEVICE), profileFile);
2020 fwrite(DS_TAG_DEVICE_TYPE,
sizeof(
char), strlen(DS_TAG_DEVICE_TYPE), profileFile);
2021 fwrite(&profile->devices[i].type,
sizeof(ds_device_type),1, profileFile);
2022 fwrite(DS_TAG_DEVICE_TYPE_END,
sizeof(
char), strlen(DS_TAG_DEVICE_TYPE_END), profileFile);
2024 switch(profile->devices[i].type) {
2025 case DS_DEVICE_NATIVE_CPU:
2035 case DS_DEVICE_OPENCL_DEVICE:
2039 fwrite(DS_TAG_DEVICE_NAME,
sizeof(
char), strlen(DS_TAG_DEVICE_NAME), profileFile);
2040 fwrite(profile->devices[i].oclDeviceName,
sizeof(
char),strlen(profile->devices[i].oclDeviceName), profileFile);
2041 fwrite(DS_TAG_DEVICE_NAME_END,
sizeof(
char), strlen(DS_TAG_DEVICE_NAME_END), profileFile);
2043 fwrite(DS_TAG_DEVICE_DRIVER_VERSION,
sizeof(
char), strlen(DS_TAG_DEVICE_DRIVER_VERSION), profileFile);
2044 fwrite(profile->devices[i].oclDriverVersion,
sizeof(
char),strlen(profile->devices[i].oclDriverVersion), profileFile);
2045 fwrite(DS_TAG_DEVICE_DRIVER_VERSION_END,
sizeof(
char), strlen(DS_TAG_DEVICE_DRIVER_VERSION_END), profileFile);
2047 fwrite(DS_TAG_DEVICE_MAX_COMPUTE_UNITS,
sizeof(
char), strlen(DS_TAG_DEVICE_MAX_COMPUTE_UNITS), profileFile);
2048 (void) FormatLocaleString(tmp,
sizeof(tmp),
"%d",
2049 profile->devices[i].oclMaxComputeUnits);
2050 fwrite(tmp,
sizeof(
char),strlen(tmp), profileFile);
2051 fwrite(DS_TAG_DEVICE_MAX_COMPUTE_UNITS_END,
sizeof(
char), strlen(DS_TAG_DEVICE_MAX_COMPUTE_UNITS_END), profileFile);
2053 fwrite(DS_TAG_DEVICE_MAX_CLOCK_FREQ,
sizeof(
char), strlen(DS_TAG_DEVICE_MAX_CLOCK_FREQ), profileFile);
2054 (void) FormatLocaleString(tmp,
sizeof(tmp),
"%d",
2055 profile->devices[i].oclMaxClockFrequency);
2056 fwrite(tmp,
sizeof(
char),strlen(tmp), profileFile);
2057 fwrite(DS_TAG_DEVICE_MAX_CLOCK_FREQ_END,
sizeof(
char), strlen(DS_TAG_DEVICE_MAX_CLOCK_FREQ_END), profileFile);
2061 status = DS_UNKNOWN_DEVICE_TYPE;
2065 fwrite(DS_TAG_SCORE,
sizeof(
char), strlen(DS_TAG_SCORE), profileFile);
2066 status = serializer(profile->devices+i, &serializedScore, &serializedScoreSize);
2067 if (status == DS_SUCCESS && serializedScore!=NULL && serializedScoreSize > 0) {
2068 fwrite(serializedScore,
sizeof(
char), serializedScoreSize, profileFile);
2069 RelinquishMagickMemory(serializedScore);
2071 fwrite(DS_TAG_SCORE_END,
sizeof(
char), strlen(DS_TAG_SCORE_END), profileFile);
2072 fwrite(DS_TAG_DEVICE_END,
sizeof(
char), strlen(DS_TAG_DEVICE_END), profileFile);
2073 fwrite(
"\n",
sizeof(
char),1,profileFile);
2075 fclose(profileFile);
2081static ds_status readProFile(
const char* fileName,
char** content,
size_t* contentSize) {
2082 ds_status status = DS_SUCCESS;
2083 FILE * input = NULL;
2086 char* binary = NULL;
2091 input = fopen(fileName,
"rb");
2093 return DS_FILE_ERROR;
2096 fseek(input, 0L, SEEK_END);
2097 size = ftell(input);
2099 binary = (
char*) AcquireQuantumMemory(1,size);
2100 if(binary == NULL) {
2101 status = DS_FILE_ERROR;
2104 rsize = fread(binary,
sizeof(
char), size, input);
2107 status = DS_FILE_ERROR;
2110 *contentSize = size;
2114 if (input != NULL) fclose(input);
2115 if (status != DS_SUCCESS
2116 && binary != NULL) {
2117 RelinquishMagickMemory(binary);
2125static const char* findString(
const char* contentStart,
const char* contentEnd,
const char*
string) {
2126 size_t stringLength;
2127 const char* currentPosition;
2130 stringLength = strlen(
string);
2131 currentPosition = contentStart;
2132 for(currentPosition = contentStart; currentPosition < contentEnd; currentPosition++) {
2133 if (*currentPosition ==
string[0]) {
2134 if (currentPosition+stringLength < contentEnd) {
2135 if (strncmp(currentPosition,
string, stringLength) == 0) {
2136 found = currentPosition;
2146typedef ds_status (*ds_score_deserializer)(ds_device* device,
const unsigned char* serializedScore,
unsigned int serializedScoreSize);
2147static ds_status readProfileFromFile(ds_profile* profile, ds_score_deserializer deserializer,
const char* file) {
2149 ds_status status = DS_SUCCESS;
2150 char* contentStart = NULL;
2151 const char* contentEnd = NULL;
2155 return DS_INVALID_PROFILE;
2157 status = readProFile(file, &contentStart, &contentSize);
2158 if (status == DS_SUCCESS) {
2159 const char* currentPosition;
2160 const char* dataStart;
2161 const char* dataEnd;
2162 size_t versionStringLength;
2164 contentEnd = contentStart + contentSize;
2165 currentPosition = contentStart;
2169 dataStart = findString(currentPosition, contentEnd, DS_TAG_VERSION);
2170 if (dataStart == NULL) {
2171 status = DS_PROFILE_FILE_ERROR;
2174 dataStart += strlen(DS_TAG_VERSION);
2176 dataEnd = findString(dataStart, contentEnd, DS_TAG_VERSION_END);
2177 if (dataEnd==NULL) {
2178 status = DS_PROFILE_FILE_ERROR;
2182 versionStringLength = strlen(profile->version);
2183 if (versionStringLength!=(
size_t)(dataEnd-dataStart)
2184 || strncmp(profile->version, dataStart, versionStringLength)!=(
int)0) {
2186 status = DS_PROFILE_FILE_ERROR;
2189 currentPosition = dataEnd+strlen(DS_TAG_VERSION_END);
2192DisableMSCWarning(4127)
2197 const char* deviceTypeStart;
2198 const char* deviceTypeEnd;
2199 ds_device_type deviceType;
2201 const char* deviceNameStart;
2202 const char* deviceNameEnd;
2204 const char* deviceScoreStart;
2205 const char* deviceScoreEnd;
2207 const char* deviceDriverStart;
2208 const char* deviceDriverEnd;
2210 const char* tmpStart;
2214 cl_uint maxClockFrequency;
2215 cl_uint maxComputeUnits;
2217 dataStart = findString(currentPosition, contentEnd, DS_TAG_DEVICE);
2218 if (dataStart==NULL) {
2222 dataStart+=strlen(DS_TAG_DEVICE);
2223 dataEnd = findString(dataStart, contentEnd, DS_TAG_DEVICE_END);
2224 if (dataEnd==NULL) {
2225 status = DS_PROFILE_FILE_ERROR;
2230 deviceTypeStart = findString(dataStart, contentEnd, DS_TAG_DEVICE_TYPE);
2231 if (deviceTypeStart==NULL) {
2232 status = DS_PROFILE_FILE_ERROR;
2235 deviceTypeStart+=strlen(DS_TAG_DEVICE_TYPE);
2236 deviceTypeEnd = findString(deviceTypeStart, contentEnd, DS_TAG_DEVICE_TYPE_END);
2237 if (deviceTypeEnd==NULL) {
2238 status = DS_PROFILE_FILE_ERROR;
2241 memcpy(&deviceType, deviceTypeStart,
sizeof(ds_device_type));
2245 if (deviceType == DS_DEVICE_OPENCL_DEVICE) {
2247 deviceNameStart = findString(dataStart, contentEnd, DS_TAG_DEVICE_NAME);
2248 if (deviceNameStart==NULL) {
2249 status = DS_PROFILE_FILE_ERROR;
2252 deviceNameStart+=strlen(DS_TAG_DEVICE_NAME);
2253 deviceNameEnd = findString(deviceNameStart, contentEnd, DS_TAG_DEVICE_NAME_END);
2254 if (deviceNameEnd==NULL) {
2255 status = DS_PROFILE_FILE_ERROR;
2260 deviceDriverStart = findString(dataStart, contentEnd, DS_TAG_DEVICE_DRIVER_VERSION);
2261 if (deviceDriverStart==NULL) {
2262 status = DS_PROFILE_FILE_ERROR;
2265 deviceDriverStart+=strlen(DS_TAG_DEVICE_DRIVER_VERSION);
2266 deviceDriverEnd = findString(deviceDriverStart, contentEnd, DS_TAG_DEVICE_DRIVER_VERSION_END);
2267 if (deviceDriverEnd ==NULL) {
2268 status = DS_PROFILE_FILE_ERROR;
2273 tmpStart = findString(dataStart, contentEnd, DS_TAG_DEVICE_MAX_COMPUTE_UNITS);
2274 if (tmpStart==NULL) {
2275 status = DS_PROFILE_FILE_ERROR;
2278 tmpStart+=strlen(DS_TAG_DEVICE_MAX_COMPUTE_UNITS);
2279 tmpEnd = findString(tmpStart, contentEnd, DS_TAG_DEVICE_MAX_COMPUTE_UNITS_END);
2280 if (tmpEnd ==NULL) {
2281 status = DS_PROFILE_FILE_ERROR;
2284 memcpy(tmp,tmpStart,tmpEnd-tmpStart);
2285 tmp[tmpEnd-tmpStart] =
'\0';
2286 maxComputeUnits = strtol(tmp,(
char **) NULL,10);
2289 tmpStart = findString(dataStart, contentEnd, DS_TAG_DEVICE_MAX_CLOCK_FREQ);
2290 if (tmpStart==NULL) {
2291 status = DS_PROFILE_FILE_ERROR;
2294 tmpStart+=strlen(DS_TAG_DEVICE_MAX_CLOCK_FREQ);
2295 tmpEnd = findString(tmpStart, contentEnd, DS_TAG_DEVICE_MAX_CLOCK_FREQ_END);
2296 if (tmpEnd ==NULL) {
2297 status = DS_PROFILE_FILE_ERROR;
2300 memcpy(tmp,tmpStart,tmpEnd-tmpStart);
2301 tmp[tmpEnd-tmpStart] =
'\0';
2302 maxClockFrequency = strtol(tmp,(
char **) NULL,10);
2306 for (i = 0; i < profile->numDevices; i++) {
2307 if (profile->devices[i].type == DS_DEVICE_OPENCL_DEVICE) {
2308 size_t actualDeviceNameLength;
2309 size_t driverVersionLength;
2311 actualDeviceNameLength = strlen(profile->devices[i].oclDeviceName);
2312 driverVersionLength = strlen(profile->devices[i].oclDriverVersion);
2313 if (actualDeviceNameLength == (
size_t)(deviceNameEnd - deviceNameStart)
2314 && driverVersionLength == (
size_t)(deviceDriverEnd - deviceDriverStart)
2315 && maxComputeUnits == profile->devices[i].oclMaxComputeUnits
2316 && maxClockFrequency == profile->devices[i].oclMaxClockFrequency
2317 && strncmp(profile->devices[i].oclDeviceName, deviceNameStart, actualDeviceNameLength)==(
int)0
2318 && strncmp(profile->devices[i].oclDriverVersion, deviceDriverStart, driverVersionLength)==(
int)0) {
2320 deviceScoreStart = findString(dataStart, contentEnd, DS_TAG_SCORE);
2321 if (deviceNameStart==NULL) {
2322 status = DS_PROFILE_FILE_ERROR;
2325 deviceScoreStart+=strlen(DS_TAG_SCORE);
2326 deviceScoreEnd = findString(deviceScoreStart, contentEnd, DS_TAG_SCORE_END);
2327 status = deserializer(profile->devices+i, (
const unsigned char*)deviceScoreStart, deviceScoreEnd-deviceScoreStart);
2328 if (status != DS_SUCCESS) {
2336 else if (deviceType == DS_DEVICE_NATIVE_CPU) {
2337 for (i = 0; i < profile->numDevices; i++) {
2338 if (profile->devices[i].type == DS_DEVICE_NATIVE_CPU) {
2339 deviceScoreStart = findString(dataStart, contentEnd, DS_TAG_SCORE);
2340 if (deviceScoreStart==NULL) {
2341 status = DS_PROFILE_FILE_ERROR;
2344 deviceScoreStart+=strlen(DS_TAG_SCORE);
2345 deviceScoreEnd = findString(deviceScoreStart, contentEnd, DS_TAG_SCORE_END);
2346 status = deserializer(profile->devices+i, (
const unsigned char*)deviceScoreStart, deviceScoreEnd-deviceScoreStart);
2347 if (status != DS_SUCCESS) {
2355 currentPosition = dataEnd+strlen(DS_TAG_DEVICE_END);
2359 if (contentStart!=NULL) RelinquishMagickMemory(contentStart);
2365static ds_status getNumDeviceWithEmptyScore(ds_profile* profile,
unsigned int* num) {
2367 if (profile == NULL || num==NULL)
2368 return DS_MEMORY_ERROR;
2370 for (i = 0; i < profile->numDevices; i++) {
2371 if (profile->devices[i].score == NULL) {
2384typedef double AccelerateScoreType;
2386static ds_status AcceleratePerfEvaluator(ds_device *device,
2387 void *magick_unused(data))
2389#define ACCELERATE_PERF_DIMEN "2048x1536"
2391#define ReturnStatus(status) \
2393 if (oldClEnv != (MagickCLEnv) NULL) \
2394 defaultCLEnv=oldClEnv; \
2395 if (clEnv != (MagickCLEnv) NULL) \
2396 (void) RelinquishMagickOpenCLEnv(clEnv); \
2413 magick_unreferenced(data);
2416 ReturnStatus(DS_PERF_EVALUATOR_ERROR);
2418 clEnv=AcquireMagickOpenCLEnv();
2419 exception=AcquireExceptionInfo();
2421 if (device->type == DS_DEVICE_NATIVE_CPU)
2424 MagickBooleanType flag=MagickTrue;
2425 SetMagickOpenCLEnvParamInternal(clEnv,
2426 MAGICK_OPENCL_ENV_PARAM_OPENCL_DISABLED,
sizeof(MagickBooleanType),
2429 else if (device->type == DS_DEVICE_OPENCL_DEVICE)
2432 SetMagickOpenCLEnvParamInternal(clEnv,MAGICK_OPENCL_ENV_PARAM_DEVICE,
2433 sizeof(cl_device_id),&device->oclDeviceID,exception);
2436 ReturnStatus(DS_PERF_EVALUATOR_ERROR);
2439 clEnv->disableProgramCache = defaultCLEnv->disableProgramCache;
2441 status=InitOpenCLEnvInternal(clEnv,exception);
2442 oldClEnv=defaultCLEnv;
2446 if (status != MagickFalse)
2457 imageInfo=AcquireImageInfo();
2458 CloneString(&imageInfo->size,ACCELERATE_PERF_DIMEN);
2459 CopyMagickString(imageInfo->filename,
"xc:none",MaxTextExtent);
2460 inputImage=ReadImage(imageInfo,exception);
2461 if (inputImage == (
Image *) NULL)
2462 ReturnStatus(DS_PERF_EVALUATOR_ERROR);
2464 initAccelerateTimer(&timer);
2466 for (i=0; i<=NUM_ITER; i++)
2480 startAccelerateTimer(&timer);
2482#ifdef MAGICKCORE_CLPERFMARKER
2483 clBeginPerfMarkerAMD(
"PerfEvaluatorRegion",
"");
2486 bluredImage=BlurImage(inputImage,10.0f,3.5f,exception);
2487 unsharpedImage=UnsharpMaskImage(bluredImage,2.0f,2.0f,50.0f,10.0f,
2489 resizedImage=ResizeImage(unsharpedImage,640,480,LanczosFilter,1.0,
2496 if (device->type != DS_DEVICE_NATIVE_CPU)
2498 events=GetOpenCLEvents(resizedImage,&event_count);
2499 if (event_count > 0)
2500 clEnv->library->clWaitForEvents(event_count,events);
2501 events=(cl_event *) RelinquishMagickMemory(events);
2504#ifdef MAGICKCORE_CLPERFMARKER
2505 clEndPerfMarkerAMD();
2509 stopAccelerateTimer(&timer);
2512 DestroyImage(bluredImage);
2514 DestroyImage(unsharpedImage);
2516 DestroyImage(resizedImage);
2518 DestroyImage(inputImage);
2522 if (device->score == NULL)
2523 device->score= AcquireMagickMemory(
sizeof(AccelerateScoreType));
2525 if (status != MagickFalse)
2526 *(AccelerateScoreType*) device->score=readAccelerateTimer(&timer);
2528 *(AccelerateScoreType*) device->score=42;
2530 ReturnStatus(DS_SUCCESS);
2533ds_status AccelerateScoreSerializer(ds_device* device,
void** serializedScore,
unsigned int* serializedScoreSize) {
2537 char* s = (
char*) AcquireQuantumMemory(256,
sizeof(
char));
2538 (void) FormatLocaleString(s,256,
"%.4f",*((AccelerateScoreType*)
2540 *serializedScore = (
void*)s;
2541 *serializedScoreSize = (
unsigned int) strlen(s);
2545 return DS_SCORE_SERIALIZER_ERROR;
2549ds_status AccelerateScoreDeserializer(ds_device* device,
const unsigned char* serializedScore,
unsigned int serializedScoreSize) {
2552 char* s = (
char*) AcquireQuantumMemory(1,serializedScoreSize+1);
2553 memcpy(s, serializedScore, serializedScoreSize);
2554 s[serializedScoreSize] = (char)
'\0';
2555 device->score = AcquireMagickMemory(
sizeof(AccelerateScoreType));
2556 *((AccelerateScoreType*)device->score) = (AccelerateScoreType)
2557 strtod(s, (
char **) NULL);
2558 RelinquishMagickMemory(s);
2562 return DS_SCORE_DESERIALIZER_ERROR;
2566ds_status AccelerateScoreRelease(
void* score) {
2568 RelinquishMagickMemory(score);
2573ds_status canWriteProfileToFile(
const char *path)
2575 FILE* profileFile = fopen(path,
"ab");
2577 if (profileFile==NULL)
2578 return DS_FILE_ERROR;
2580 fclose(profileFile);
2585#define IMAGEMAGICK_PROFILE_VERSION "ImageMagick Device Selection v0.9"
2586#define IMAGEMAGICK_PROFILE_FILE "ImagemagickOpenCLDeviceProfile"
2589 MagickBooleanType mStatus = MagickFalse;
2591 ds_profile* profile;
2592 unsigned int numDeviceProfiled = 0;
2594 unsigned int bestDeviceIndex;
2595 AccelerateScoreType bestScore;
2596 char path[MaxTextExtent];
2597 MagickBooleanType flag;
2598 ds_evaluation_type profileType;
2600 LockDefaultOpenCLEnv();
2604 SetMagickOpenCLEnvParamInternal(clEnv, MAGICK_OPENCL_ENV_PARAM_OPENCL_DISABLED
2605 ,
sizeof(MagickBooleanType), &flag, exception);
2608 OpenCLLib=GetOpenCLLib();
2609 if (OpenCLLib==NULL)
2611 mStatus=InitOpenCLEnvInternal(clEnv, exception);
2615 clEnv->library=OpenCLLib;
2617 status = initDSProfile(&profile, IMAGEMAGICK_PROFILE_VERSION);
2618 if (status!=DS_SUCCESS) {
2619 (void) ThrowMagickException(exception, GetMagickModule(), ModuleFatalError,
"Error when initializing the profile",
"'%s'",
".");
2623 (void) FormatLocaleString(path,MaxTextExtent,
"%s%s%s"
2624 ,GetOpenCLCachedFilesDirectory()
2625 ,DirectorySeparator,IMAGEMAGICK_PROFILE_FILE);
2627 if (canWriteProfileToFile(path) != DS_SUCCESS) {
2631 bestDeviceIndex = 0;
2632 for (i = 1; i < profile->numDevices; i++) {
2633 if ((profile->devices[i].type == DS_DEVICE_OPENCL_DEVICE) && (profile->devices[i].oclDeviceType == CL_DEVICE_TYPE_GPU)) {
2634 bestDeviceIndex = i;
2640 if (clEnv->regenerateProfile != MagickFalse) {
2641 profileType = DS_EVALUATE_ALL;
2644 readProfileFromFile(profile, AccelerateScoreDeserializer, path);
2645 profileType = DS_EVALUATE_NEW_ONLY;
2647 status = profileDevices(profile, profileType, AcceleratePerfEvaluator, NULL, &numDeviceProfiled);
2649 if (status!=DS_SUCCESS) {
2650 (void) ThrowMagickException(exception, GetMagickModule(), ModuleFatalError,
"Error when initializing the profile",
"'%s'",
".");
2653 if (numDeviceProfiled > 0) {
2654 status = writeProfileToFile(profile, AccelerateScoreSerializer, path);
2655 if (status!=DS_SUCCESS) {
2656 (void) ThrowMagickException(exception, GetMagickModule(), ModuleWarning,
"Error when saving the profile into a file",
"'%s'",
".");
2661 bestDeviceIndex = 0;
2662 bestScore = *(AccelerateScoreType*)profile->devices[bestDeviceIndex].score;
2663 for (i = 1; i < profile->numDevices; i++) {
2664 AccelerateScoreType score = *(AccelerateScoreType*)profile->devices[i].score;
2665 if (score < bestScore) {
2666 bestDeviceIndex = i;
2673 if (profile->devices[bestDeviceIndex].type == DS_DEVICE_NATIVE_CPU) {
2676 SetMagickOpenCLEnvParamInternal(clEnv, MAGICK_OPENCL_ENV_PARAM_OPENCL_DISABLED
2677 ,
sizeof(MagickBooleanType), &flag, exception);
2679 else if (profile->devices[bestDeviceIndex].type == DS_DEVICE_OPENCL_DEVICE) {
2682 SetMagickOpenCLEnvParamInternal(clEnv, MAGICK_OPENCL_ENV_PARAM_OPENCL_DISABLED
2683 ,
sizeof(MagickBooleanType), &flag, exception);
2684 SetMagickOpenCLEnvParamInternal(clEnv, MAGICK_OPENCL_ENV_PARAM_DEVICE
2685 ,
sizeof(cl_device_id), &profile->devices[bestDeviceIndex].oclDeviceID,exception);
2688 status = DS_PERF_EVALUATOR_ERROR;
2691 mStatus=InitOpenCLEnvInternal(clEnv, exception);
2693 status = releaseDSProfile(profile, AccelerateScoreRelease);
2694 if (status!=DS_SUCCESS) {
2695 (void) ThrowMagickException(exception, GetMagickModule(), ModuleWarning,
"Error when releasing the profile",
"'%s'",
".");
2700 UnlockDefaultOpenCLEnv();
2738MagickExport MagickBooleanType InitImageMagickOpenCL(
2739 ImageMagickOpenCLMode mode,
void *userSelectedDevice,
void *selectedDevice,
2742 MagickBooleanType status = MagickFalse;
2744 MagickBooleanType flag;
2746 clEnv = GetDefaultOpenCLEnv();
2750 case MAGICK_OPENCL_OFF:
2752 SetMagickOpenCLEnvParam(clEnv, MAGICK_OPENCL_ENV_PARAM_OPENCL_DISABLED
2753 ,
sizeof(MagickBooleanType), &flag, exception);
2754 status = InitOpenCLEnv(clEnv, exception);
2757 *(cl_device_id*)selectedDevice = NULL;
2760 case MAGICK_OPENCL_DEVICE_SELECT_USER:
2762 if (userSelectedDevice == NULL)
2766 SetMagickOpenCLEnvParam(clEnv, MAGICK_OPENCL_ENV_PARAM_OPENCL_DISABLED
2767 ,
sizeof(MagickBooleanType), &flag, exception);
2769 SetMagickOpenCLEnvParam(clEnv, MAGICK_OPENCL_ENV_PARAM_DEVICE
2770 ,
sizeof(cl_device_id), userSelectedDevice,exception);
2772 status = InitOpenCLEnv(clEnv, exception);
2773 if (selectedDevice) {
2774 GetMagickOpenCLEnvParam(clEnv, MAGICK_OPENCL_ENV_PARAM_DEVICE
2775 ,
sizeof(cl_device_id), selectedDevice, exception);
2779 case MAGICK_OPENCL_DEVICE_SELECT_AUTO_CLEAR_CACHE:
2781 SetMagickOpenCLEnvParam(clEnv, MAGICK_OPENCL_ENV_PARAM_PROGRAM_CACHE_DISABLED
2782 ,
sizeof(MagickBooleanType), &flag, exception);
2784 SetMagickOpenCLEnvParam(clEnv, MAGICK_OPENCL_ENV_PARAM_REGENERATE_PROFILE
2785 ,
sizeof(MagickBooleanType), &flag, exception);
2788 case MAGICK_OPENCL_DEVICE_SELECT_AUTO:
2791 cl_device_id d = NULL;
2793 SetMagickOpenCLEnvParam(clEnv, MAGICK_OPENCL_ENV_PARAM_OPENCL_DISABLED
2794 ,
sizeof(MagickBooleanType), &flag, exception);
2795 SetMagickOpenCLEnvParam(clEnv, MAGICK_OPENCL_ENV_PARAM_DEVICE
2796 ,
sizeof(cl_device_id), &d,exception);
2797 status = InitOpenCLEnv(clEnv, exception);
2798 if (selectedDevice) {
2799 GetMagickOpenCLEnvParam(clEnv, MAGICK_OPENCL_ENV_PARAM_DEVICE
2800 ,
sizeof(cl_device_id), selectedDevice, exception);
2811MagickBooleanType OpenCLThrowMagickException(
ExceptionInfo *exception,
2812 const char *module,
const char *function,
const size_t line,
2813 const ExceptionType severity,
const char *tag,
const char *format,...) {
2819 status = MagickTrue;
2821 clEnv = GetDefaultOpenCLEnv();
2824 assert(exception->signature == MagickCoreSignature);
2827 cl_device_type dType;
2828 clEnv->library->clGetDeviceInfo(clEnv->device,CL_DEVICE_TYPE ,
sizeof(cl_device_type),&dType,NULL);
2829 if (dType == CL_DEVICE_TYPE_CPU) {
2830 char buffer[MaxTextExtent];
2831 clEnv->library->clGetPlatformInfo(clEnv->platform, CL_PLATFORM_NAME, MaxTextExtent, buffer, NULL);
2835 if (strncmp(buffer,
"Intel",5) == 0) {
2837 InitImageMagickOpenCL(MAGICK_OPENCL_OFF, NULL, NULL, exception);
2842#ifdef OPENCLLOG_ENABLED
2846 va_start(operands,format);
2847 status=ThrowMagickExceptionList(exception,module,function,line,severity,tag, format,operands);
2851 magick_unreferenced(module);
2852 magick_unreferenced(function);
2853 magick_unreferenced(line);
2854 magick_unreferenced(tag);
2855 magick_unreferenced(format);
2861char* openclCachedFilesDirectory;
2865const char* GetOpenCLCachedFilesDirectory() {
2866 if (openclCachedFilesDirectory == NULL) {
2867 if (openclCachedFilesDirectoryLock == NULL)
2869 ActivateSemaphoreInfo(&openclCachedFilesDirectoryLock);
2871 LockSemaphoreInfo(openclCachedFilesDirectoryLock);
2872 if (openclCachedFilesDirectory == NULL) {
2873 char path[MaxTextExtent];
2876 struct stat attributes;
2877 MagickBooleanType status;
2878 int mkdirStatus = 0;
2882 home=GetEnvironmentValue(
"MAGICK_OPENCL_CACHE_DIR");
2883 if (home == (
char *) NULL)
2885 home=GetEnvironmentValue(
"XDG_CACHE_HOME");
2886#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__MINGW32__)
2887 if (home == (
char *) NULL)
2888 home=GetEnvironmentValue(
"LOCALAPPDATA");
2889 if (home == (
char *) NULL)
2890 home=GetEnvironmentValue(
"APPDATA");
2891 if (home == (
char *) NULL)
2892 home=GetEnvironmentValue(
"USERPROFILE");
2896 if (home != (
char *) NULL)
2899 (void) FormatLocaleString(path,MaxTextExtent,
"%s",home);
2900 status=GetPathAttributes(path,&attributes);
2901 if (status == MagickFalse)
2904#ifdef MAGICKCORE_WINDOWS_SUPPORT
2905 mkdirStatus = mkdir(path);
2907 mkdirStatus = mkdir(path, 0777);
2914 (void) FormatLocaleString(path,MaxTextExtent,
2915 "%s%sImageMagick",home,DirectorySeparator);
2917 status=GetPathAttributes(path,&attributes);
2918 if (status == MagickFalse)
2920#ifdef MAGICKCORE_WINDOWS_SUPPORT
2921 mkdirStatus = mkdir(path);
2923 mkdirStatus = mkdir(path, 0777);
2930 temp = (
char*)AcquireCriticalMemory(strlen(path)+1);
2931 CopyMagickString(temp,path,strlen(path)+1);
2933 home=DestroyString(home);
2935 home=GetEnvironmentValue(
"HOME");
2936 if (home != (
char *) NULL)
2942 (void) FormatLocaleString(path,MaxTextExtent,
"%s%s.cache",
2943 home,DirectorySeparator);
2944 status=GetPathAttributes(path,&attributes);
2945 if (status == MagickFalse)
2948#ifdef MAGICKCORE_WINDOWS_SUPPORT
2949 mkdirStatus = mkdir(path);
2951 mkdirStatus = mkdir(path, 0777);
2958 (void) FormatLocaleString(path,MaxTextExtent,
2959 "%s%s.cache%sImageMagick",home,DirectorySeparator,
2960 DirectorySeparator);
2962 status=GetPathAttributes(path,&attributes);
2963 if (status == MagickFalse)
2965#ifdef MAGICKCORE_WINDOWS_SUPPORT
2966 mkdirStatus = mkdir(path);
2968 mkdirStatus = mkdir(path, 0777);
2975 temp = (
char*)AcquireCriticalMemory(strlen(path)+1);
2976 CopyMagickString(temp,path,strlen(path)+1);
2978 home=DestroyString(home);
2981 openclCachedFilesDirectory = temp;
2983 UnlockSemaphoreInfo(openclCachedFilesDirectoryLock);
2985 return openclCachedFilesDirectory;
2990void OpenCLLog(
const char* message) {
2992#ifdef OPENCLLOG_ENABLED
2993#define OPENCL_LOG_FILE "ImageMagickOpenCL.log"
2996 if (getenv(
"MAGICK_OCL_LOG"))
2999 char path[MaxTextExtent];
3000 unsigned long allocSize;
3004 clEnv = GetDefaultOpenCLEnv();
3007 (void) FormatLocaleString(path,MaxTextExtent,
"%s%s%s"
3008 ,GetOpenCLCachedFilesDirectory()
3009 ,DirectorySeparator,OPENCL_LOG_FILE);
3012 log = fopen(path,
"ab");
3013 if (log == (FILE *) NULL)
3015 fwrite(message,
sizeof(
char), strlen(message), log);
3016 fwrite(
"\n",
sizeof(
char), 1, log);
3018 if (clEnv->OpenCLInitialized && !clEnv->OpenCLDisabled)
3020 allocSize = GetOpenCLDeviceMaxMemAllocSize(clEnv);
3021 fprintf(log,
"Devic Max Memory Alloc Size: %lu\n", allocSize);
3028 magick_unreferenced(message);
3032MagickPrivate
void OpenCLTerminus()
3035 if (openclCachedFilesDirectory != (
char *) NULL)
3036 openclCachedFilesDirectory=DestroyString(openclCachedFilesDirectory);
3038 DestroySemaphoreInfo(&openclCachedFilesDirectoryLock);
3041 (void) RelinquishMagickOpenCLEnv(defaultCLEnv);
3045 DestroySemaphoreInfo(&defaultCLEnvLock);
3046 if (OpenCLLib != (MagickLibrary *)NULL)
3048 if (OpenCLLib->base != (
void *) NULL)
3049 (void) lt_dlclose(OpenCLLib->base);
3050 OpenCLLib=(MagickLibrary *)RelinquishMagickMemory(OpenCLLib);
3053 DestroySemaphoreInfo(&OpenCLLibLock);
3059 MagickBooleanType OpenCLInitialized;
3070MagickExport MagickBooleanType SetMagickOpenCLEnvParam(
3071 MagickCLEnv magick_unused(clEnv),MagickOpenCLEnvParam magick_unused(param),
3072 size_t magick_unused(dataSize),
void *magick_unused(data),
3075 magick_unreferenced(clEnv);
3076 magick_unreferenced(param);
3077 magick_unreferenced(dataSize);
3078 magick_unreferenced(data);
3079 magick_unreferenced(exception);
3080 return(MagickFalse);
3083MagickExport MagickBooleanType GetMagickOpenCLEnvParam(
3084 MagickCLEnv magick_unused(clEnv),MagickOpenCLEnvParam magick_unused(param),
3085 size_t magick_unused(dataSize),
void *magick_unused(data),
3088 magick_unreferenced(clEnv);
3089 magick_unreferenced(param);
3090 magick_unreferenced(dataSize);
3091 magick_unreferenced(data);
3092 magick_unreferenced(exception);
3093 return(MagickFalse);
3096MagickExport MagickBooleanType InitOpenCLEnv(
MagickCLEnv magick_unused(clEnv),
3099 magick_unreferenced(clEnv);
3100 magick_unreferenced(exception);
3101 return(MagickFalse);
3104MagickExport MagickBooleanType InitImageMagickOpenCL(
3105 ImageMagickOpenCLMode magick_unused(mode),
3106 void *magick_unused(userSelectedDevice),
void *magick_unused(selectedDevice),
3109 magick_unreferenced(mode);
3110 magick_unreferenced(userSelectedDevice);
3111 magick_unreferenced(selectedDevice);
3112 magick_unreferenced(exception);
3113 return(MagickFalse);