1/*
2Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization
3dedicated to making software imaging solutions freely available.
4
5You may not use this file except in compliance with the License.
6obtain a copy of the License at
7
8http://www.imagemagick.org/script/license.php
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15
16MagickCore OpenCL private methods.
17*/
18#ifndef MAGICKCORE_OPENCL_PRIVATE_H
19#define MAGICKCORE_OPENCL_PRIVATE_H
20
21/*
22Include declarations.
23*/
24#include "MagickCore/studio.h"
25#include "MagickCore/opencl.h"
26#include "MagickCore/thread_.h"
27
28#if defined(__cplusplus) || defined(c_plusplus)
29extern "C" {
30#endif
31
32#if !defined(MAGICKCORE_OPENCL_SUPPORT)
33typedef void* MagickCLCacheInfo;
34#else
35typedef struct _MagickCLCacheInfo
36{
37  cl_event
38    *events;
39
40  cl_mem
41    buffer;
42
43  cl_uint
44    event_count;
45
46  MagickCLDevice
47    device;
48
49  MagickSizeType
50    length;
51
52  Quantum
53    *pixels;
54}* MagickCLCacheInfo;
55
56/*
57  Define declarations.
58*/
59#define MAGICKCORE_OPENCL_UNDEFINED_SCORE -1.0
60#define MAGICKCORE_OPENCL_COMMAND_QUEUES 16
61
62/* Platform APIs */
63typedef CL_API_ENTRY cl_int
64  (CL_API_CALL *MAGICKpfn_clGetPlatformIDs)(cl_uint num_entries,
65    cl_platform_id *platforms,cl_uint *num_platforms) CL_API_SUFFIX__VERSION_1_0;
66
67typedef CL_API_ENTRY cl_int
68  (CL_API_CALL *MAGICKpfn_clGetPlatformInfo)(cl_platform_id platform,
69    cl_platform_info param_name,size_t param_value_size,void *param_value,
70    size_t *param_value_size_ret) CL_API_SUFFIX__VERSION_1_0;
71
72
73/* Device APIs */
74typedef CL_API_ENTRY cl_int
75  (CL_API_CALL *MAGICKpfn_clGetDeviceIDs)(cl_platform_id platform,
76    cl_device_type device_type,cl_uint num_entries,cl_device_id *devices,
77    cl_uint *num_devices) CL_API_SUFFIX__VERSION_1_0;
78
79typedef CL_API_ENTRY cl_int
80  (CL_API_CALL *MAGICKpfn_clGetDeviceInfo)(cl_device_id device,
81    cl_device_info param_name,size_t param_value_size,void *param_value,
82    size_t *param_value_size_ret) CL_API_SUFFIX__VERSION_1_0;
83
84
85/* Context APIs */
86typedef CL_API_ENTRY cl_context
87  (CL_API_CALL *MAGICKpfn_clCreateContext)(
88    const cl_context_properties *properties,cl_uint num_devices,
89    const cl_device_id *devices,void (CL_CALLBACK *pfn_notify)(const char *,
90    const void *,size_t,void *),void *user_data,cl_int *errcode_ret)
91    CL_API_SUFFIX__VERSION_1_0;
92
93typedef CL_API_ENTRY cl_int
94  (CL_API_CALL *MAGICKpfn_clReleaseContext)(cl_context context)
95    CL_API_SUFFIX__VERSION_1_0;
96
97
98/* Command Queue APIs */
99typedef CL_API_ENTRY cl_command_queue
100  (CL_API_CALL *MAGICKpfn_clCreateCommandQueue)(cl_context context,
101    cl_device_id device,cl_command_queue_properties properties,
102    cl_int *errcode_ret) CL_API_SUFFIX__VERSION_1_0;
103
104typedef CL_API_ENTRY cl_int
105  (CL_API_CALL *MAGICKpfn_clReleaseCommandQueue)(
106    cl_command_queue command_queue) CL_API_SUFFIX__VERSION_1_0;
107
108typedef CL_API_ENTRY cl_int
109  (CL_API_CALL *MAGICKpfn_clFlush)(cl_command_queue command_queue)
110    CL_API_SUFFIX__VERSION_1_0;
111
112typedef CL_API_ENTRY cl_int
113  (CL_API_CALL *MAGICKpfn_clFinish)(cl_command_queue command_queue)
114    CL_API_SUFFIX__VERSION_1_0;
115
116
117/* Memory Object APIs */
118typedef CL_API_ENTRY cl_mem
119  (CL_API_CALL *MAGICKpfn_clCreateBuffer)(cl_context context,
120    cl_mem_flags flags,size_t size,void *host_ptr,cl_int *errcode_ret)
121    CL_API_SUFFIX__VERSION_1_0;
122
123typedef CL_API_ENTRY cl_int
124  (CL_API_CALL *MAGICKpfn_clReleaseMemObject)(cl_mem memobj)
125    CL_API_SUFFIX__VERSION_1_0;
126
127
128/* Program Object APIs */
129typedef CL_API_ENTRY cl_program
130  (CL_API_CALL *MAGICKpfn_clCreateProgramWithSource)(cl_context context,
131    cl_uint count,const char **strings,const size_t *lengths,
132    cl_int *errcode_ret) CL_API_SUFFIX__VERSION_1_0;
133
134typedef CL_API_ENTRY cl_program
135  (CL_API_CALL *MAGICKpfn_clCreateProgramWithBinary)(cl_context context,
136    cl_uint num_devices,const cl_device_id *device_list,const size_t *lengths,
137    const unsigned char **binaries,cl_int *binary_status,cl_int *errcode_ret)
138    CL_API_SUFFIX__VERSION_1_0;
139
140typedef CL_API_ENTRY cl_int
141  (CL_API_CALL *MAGICKpfn_clReleaseProgram)(cl_program program)
142    CL_API_SUFFIX__VERSION_1_0;
143
144typedef CL_API_ENTRY cl_int
145  (CL_API_CALL *MAGICKpfn_clBuildProgram)(cl_program program,
146    cl_uint num_devices,const cl_device_id *device_list,const char *options,
147    void (CL_CALLBACK *pfn_notify)(cl_program program,void * user_data),
148    void *user_data) CL_API_SUFFIX__VERSION_1_0;
149
150typedef CL_API_ENTRY cl_int
151  (CL_API_CALL *MAGICKpfn_clGetProgramBuildInfo)(cl_program program,
152    cl_device_id device,cl_program_build_info param_name,size_t param_value_size,
153    void *param_value,size_t *param_value_size_ret) CL_API_SUFFIX__VERSION_1_0;
154
155typedef CL_API_ENTRY cl_int
156  (CL_API_CALL *MAGICKpfn_clGetProgramInfo)(cl_program program,
157    cl_program_info param_name,size_t param_value_size,void *param_value,
158    size_t *param_value_size_ret) CL_API_SUFFIX__VERSION_1_0;
159
160
161/* Kernel Object APIs */
162typedef CL_API_ENTRY cl_kernel
163  (CL_API_CALL *MAGICKpfn_clCreateKernel)(cl_program program,
164    const char *kernel_name,cl_int *errcode_ret) CL_API_SUFFIX__VERSION_1_0;
165
166typedef CL_API_ENTRY cl_int
167  (CL_API_CALL *MAGICKpfn_clReleaseKernel)(cl_kernel kernel)
168    CL_API_SUFFIX__VERSION_1_0;
169
170typedef CL_API_ENTRY cl_int
171  (CL_API_CALL *MAGICKpfn_clSetKernelArg)(cl_kernel kernel,cl_uint arg_index,
172  size_t arg_size,const void * arg_value) CL_API_SUFFIX__VERSION_1_0;
173
174typedef CL_API_ENTRY cl_int
175  (CL_API_CALL *MAGICKpfn_clGetKernelInfo)(cl_kernel kernel,
176    cl_kernel_info param_name,size_t param_value_size,void *param_value,
177    size_t *param_value_size_ret) CL_API_SUFFIX__VERSION_1_0;
178
179
180/* Enqueued Commands APIs */
181typedef CL_API_ENTRY cl_int
182  (CL_API_CALL *MAGICKpfn_clEnqueueReadBuffer)(cl_command_queue command_queue,
183    cl_mem buffer,cl_bool blocking_read,size_t offset,size_t cb,void *ptr,
184    cl_uint num_events_in_wait_list,const cl_event *event_wait_list,
185    cl_event *event) CL_API_SUFFIX__VERSION_1_0;
186
187typedef CL_API_ENTRY void
188  *(CL_API_CALL *MAGICKpfn_clEnqueueMapBuffer)(cl_command_queue command_queue,
189    cl_mem buffer,cl_bool blocking_map,cl_map_flags map_flags,size_t offset,
190    size_t cb,cl_uint num_events_in_wait_list,const cl_event *event_wait_list,
191    cl_event *event,cl_int *errcode_ret) CL_API_SUFFIX__VERSION_1_0;
192
193typedef CL_API_ENTRY cl_int
194  (CL_API_CALL *MAGICKpfn_clEnqueueUnmapMemObject)(
195    cl_command_queue command_queue,cl_mem memobj,void *mapped_ptr,
196    cl_uint num_events_in_wait_list,const cl_event *event_wait_list,
197    cl_event *event) CL_API_SUFFIX__VERSION_1_0;
198
199typedef CL_API_ENTRY cl_int
200  (CL_API_CALL *MAGICKpfn_clEnqueueNDRangeKernel)(
201    cl_command_queue command_queue,cl_kernel kernel,cl_uint work_dim,
202    const size_t *global_work_offset,const size_t *global_work_size,
203    const size_t *local_work_size,cl_uint num_events_in_wait_list,
204    const cl_event * event_wait_list,cl_event *event)
205    CL_API_SUFFIX__VERSION_1_0;
206
207
208/* Events APIs */
209typedef CL_API_ENTRY cl_int
210  (CL_API_CALL *MAGICKpfn_clWaitForEvents)(cl_uint num_events,
211    const cl_event *event_list) CL_API_SUFFIX__VERSION_1_0;
212
213typedef CL_API_ENTRY cl_int
214  (CL_API_CALL *MAGICKpfn_clReleaseEvent)(cl_event event)
215    CL_API_SUFFIX__VERSION_1_0;
216
217typedef CL_API_ENTRY cl_int
218  (CL_API_CALL *MAGICKpfn_clRetainEvent)(cl_event event)
219    CL_API_SUFFIX__VERSION_1_0;
220
221typedef CL_API_ENTRY cl_int
222  (CL_API_CALL *MAGICKpfn_clSetEventCallback)(cl_event event,
223    cl_int command_exec_callback_type,void (CL_CALLBACK *MAGICKpfn_notify)(
224      cl_event,cl_int,void *),void *user_data) CL_API_SUFFIX__VERSION_1_1;
225
226
227/* Profiling APIs */
228typedef CL_API_ENTRY cl_int
229  (CL_API_CALL *MAGICKpfn_clGetEventProfilingInfo)(cl_event event,
230    cl_profiling_info param_name,size_t param_value_size,void *param_value,
231    size_t *param_value_size_ret) CL_API_SUFFIX__VERSION_1_0;
232
233typedef struct MagickLibraryRec MagickLibrary;
234
235struct MagickLibraryRec
236{
237  MAGICKpfn_clGetPlatformIDs          clGetPlatformIDs;
238  MAGICKpfn_clGetPlatformInfo         clGetPlatformInfo;
239
240  MAGICKpfn_clGetDeviceIDs            clGetDeviceIDs;
241  MAGICKpfn_clGetDeviceInfo           clGetDeviceInfo;
242
243  MAGICKpfn_clCreateContext           clCreateContext;
244  MAGICKpfn_clReleaseContext          clReleaseContext;
245
246  MAGICKpfn_clCreateCommandQueue      clCreateCommandQueue;
247  MAGICKpfn_clReleaseCommandQueue     clReleaseCommandQueue;
248  MAGICKpfn_clFlush                   clFlush;
249  MAGICKpfn_clFinish                  clFinish;
250
251  MAGICKpfn_clCreateBuffer            clCreateBuffer;
252  MAGICKpfn_clReleaseMemObject        clReleaseMemObject;
253
254  MAGICKpfn_clCreateProgramWithSource clCreateProgramWithSource;
255  MAGICKpfn_clCreateProgramWithBinary clCreateProgramWithBinary;
256  MAGICKpfn_clReleaseProgram          clReleaseProgram;
257  MAGICKpfn_clBuildProgram            clBuildProgram;
258  MAGICKpfn_clGetProgramBuildInfo     clGetProgramBuildInfo;
259  MAGICKpfn_clGetProgramInfo          clGetProgramInfo;
260
261  MAGICKpfn_clCreateKernel            clCreateKernel;
262  MAGICKpfn_clReleaseKernel           clReleaseKernel;
263  MAGICKpfn_clSetKernelArg            clSetKernelArg;
264  MAGICKpfn_clGetKernelInfo           clGetKernelInfo;
265
266  MAGICKpfn_clEnqueueReadBuffer       clEnqueueReadBuffer;
267  MAGICKpfn_clEnqueueMapBuffer        clEnqueueMapBuffer;
268  MAGICKpfn_clEnqueueUnmapMemObject   clEnqueueUnmapMemObject;
269  MAGICKpfn_clEnqueueNDRangeKernel    clEnqueueNDRangeKernel;
270
271  MAGICKpfn_clWaitForEvents           clWaitForEvents;
272  MAGICKpfn_clReleaseEvent            clReleaseEvent;
273  MAGICKpfn_clRetainEvent             clRetainEvent;
274  MAGICKpfn_clSetEventCallback        clSetEventCallback;
275
276  MAGICKpfn_clGetEventProfilingInfo   clGetEventProfilingInfo;
277};
278
279struct _MagickCLDevice
280{
281  char
282    *name,
283    *platform_name,
284    *version;
285
286  cl_command_queue
287    command_queues[MAGICKCORE_OPENCL_COMMAND_QUEUES];
288
289  cl_context
290    context;
291
292  cl_device_id
293    deviceID;
294
295  cl_device_type
296    type;
297
298  cl_program
299    program;
300
301  cl_uint
302    max_clock_frequency,
303    max_compute_units;
304
305  cl_ulong
306    local_memory_size;
307
308  double
309    score;
310
311  KernelProfileRecord
312    *profile_records;
313
314  MagickBooleanType
315    enabled,
316    profile_kernels;
317
318  SemaphoreInfo
319    *lock;
320
321  size_t
322    requested;
323
324  ssize_t
325    command_queues_index;
326};
327
328typedef struct _MagickCLEnv
329{
330  cl_context
331    *contexts;
332
333  double
334    cpu_score;
335
336  MagickBooleanType
337    enabled,
338    initialized;
339
340  MagickCLDevice
341    *devices;
342
343  MagickLibrary
344    *library;
345
346  MagickThreadType
347    benchmark_thread_id;
348
349  SemaphoreInfo
350    *lock;
351
352  size_t
353    number_contexts,
354    number_devices;
355} *MagickCLEnv;
356
357#if defined(MAGICKCORE_HDRI_SUPPORT)
358#define CLOptions "-cl-single-precision-constant -cl-mad-enable -DMAGICKCORE_HDRI_SUPPORT=1 "\
359  "-DCLQuantum=float -DCLSignedQuantum=float -DCLPixelType=float4 -DQuantumRange=%ff " \
360  "-DQuantumScale=%f -DCharQuantumScale=%f -DMagickEpsilon=%f -DMagickPI=%f "\
361  "-DMaxMap=%u -DMAGICKCORE_QUANTUM_DEPTH=%u"
362#define CLQuantum  cl_float
363#define CLPixelPacket  cl_float4
364#define CLCharQuantumScale 1.0f
365#elif (MAGICKCORE_QUANTUM_DEPTH == 8)
366#define CLOptions "-cl-single-precision-constant -cl-mad-enable " \
367  "-DCLQuantum=uchar -DCLSignedQuantum=char -DCLPixelType=uchar4 -DQuantumRange=%ff " \
368  "-DQuantumScale=%ff -DCharQuantumScale=%ff -DMagickEpsilon=%ff -DMagickPI=%ff "\
369  "-DMaxMap=%u -DMAGICKCORE_QUANTUM_DEPTH=%u"
370#define CLQuantum  cl_uchar
371#define CLPixelPacket  cl_uchar4
372#define CLCharQuantumScale 1.0f
373#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
374#define CLOptions "-cl-single-precision-constant -cl-mad-enable " \
375  "-DCLQuantum=ushort -DCLSignedQuantum=short -DCLPixelType=ushort4 -DQuantumRange=%ff "\
376  "-DQuantumScale=%f -DCharQuantumScale=%f -DMagickEpsilon=%f -DMagickPI=%f "\
377  "-DMaxMap=%u -DMAGICKCORE_QUANTUM_DEPTH=%u"
378#define CLQuantum  cl_ushort
379#define CLPixelPacket  cl_ushort4
380#define CLCharQuantumScale 257.0f
381#elif (MAGICKCORE_QUANTUM_DEPTH == 32)
382#define CLOptions "-cl-single-precision-constant -cl-mad-enable " \
383  "-DCLQuantum=uint -DCLSignedQuantum=int -DCLPixelType=uint4 -DQuantumRange=%ff "\
384  "-DQuantumScale=%f -DCharQuantumScale=%f -DMagickEpsilon=%f -DMagickPI=%f "\
385  "-DMaxMap=%u -DMAGICKCORE_QUANTUM_DEPTH=%u"
386#define CLQuantum  cl_uint
387#define CLPixelPacket  cl_uint4
388#define CLCharQuantumScale 16843009.0f
389#elif (MAGICKCORE_QUANTUM_DEPTH == 64)
390#define CLOptions "-cl-single-precision-constant -cl-mad-enable " \
391  "-DCLQuantum=ulong -DCLSignedQuantum=long -DCLPixelType=ulong4 -DQuantumRange=%ff "\
392  "-DQuantumScale=%f -DCharQuantumScale=%f -DMagickEpsilon=%f -DMagickPI=%f "\
393  "-DMaxMap=%u -DMAGICKCORE_QUANTUM_DEPTH=%u"
394#define CLQuantum  cl_ulong
395#define CLPixelPacket  cl_ulong4
396#define CLCharQuantumScale 72340172838076673.0f
397#endif
398
399extern MagickPrivate cl_command_queue
400  AcquireOpenCLCommandQueue(MagickCLDevice);
401
402extern MagickPrivate cl_int
403  SetOpenCLKernelArg(cl_kernel,cl_uint,size_t,const void *);
404
405extern MagickPrivate cl_kernel
406  AcquireOpenCLKernel(MagickCLDevice,const char *);
407
408extern MagickPrivate cl_mem
409  CreateOpenCLBuffer(MagickCLDevice,cl_mem_flags,size_t,void *);
410
411extern MagickPrivate MagickBooleanType
412  EnqueueOpenCLKernel(cl_command_queue,cl_kernel,cl_uint,const size_t *,
413    const size_t *,const size_t *,const Image *,const Image *,ExceptionInfo *),
414  InitializeOpenCL(MagickCLEnv,ExceptionInfo *),
415  OpenCLThrowMagickException(MagickCLDevice,ExceptionInfo *,
416    const char *,const char *,const size_t,const ExceptionType,const char *,
417    const char *,...),
418  RecordProfileData(MagickCLDevice,cl_kernel,cl_event);
419
420extern MagickPrivate MagickCLCacheInfo
421  AcquireMagickCLCacheInfo(MagickCLDevice,Quantum *,const MagickSizeType),
422  CopyMagickCLCacheInfo(MagickCLCacheInfo),
423  RelinquishMagickCLCacheInfo(MagickCLCacheInfo,const MagickBooleanType);
424
425extern MagickPrivate MagickCLDevice
426  RequestOpenCLDevice(MagickCLEnv);
427
428extern MagickPrivate MagickCLEnv
429  GetCurrentOpenCLEnv(void);
430
431extern MagickPrivate unsigned long
432  GetOpenCLDeviceLocalMemorySize(const MagickCLDevice);
433
434extern MagickPrivate void
435  DumpOpenCLProfileData(),
436  OpenCLTerminus(),
437  ReleaseOpenCLCommandQueue(MagickCLDevice,cl_command_queue),
438  ReleaseOpenCLDevice(MagickCLDevice),
439  ReleaseOpenCLKernel(cl_kernel),
440  ReleaseOpenCLMemObject(cl_mem),
441  RetainOpenCLEvent(cl_event);
442
443#endif
444
445#if defined(__cplusplus) || defined(c_plusplus)
446}
447#endif
448
449#endif
450