3 Copyright (c) 2003-2015 HandBrake Team
4 This file is part of the HandBrake source code
5 Homepage: <http://handbrake.fr/>.
6 It may be used under the terms of the GNU General Public License v2.
7 For full terms see the file COPYING file or visit http://www.gnu.org/licenses/gpl-2.0.html
12 #define HB_OCL_DLOPEN LoadLibraryW(L"OpenCL")
13 #define HB_OCL_DLSYM GetProcAddress
14 #define HB_OCL_DLCLOSE FreeLibrary
18 #define HB_OCL_DLOPEN dlopen("/System/Library/Frameworks/OpenCL.framework/OpenCL", RTLD_NOW)
20 #define HB_OCL_DLOPEN dlopen("libOpenCL.so", RTLD_NOW)
22 #define HB_OCL_DLSYM dlsym
23 #define HB_OCL_DLCLOSE dlclose
29 hb_opencl_library_t
*hb_ocl
= NULL
;
35 if ((hb_ocl
= hb_opencl_library_init()) == NULL
)
45 hb_opencl_library_close(&hb_ocl
);
48 hb_opencl_library_t
* hb_opencl_library_init()
50 hb_opencl_library_t
*opencl
;
51 if ((opencl
= calloc(1, sizeof(hb_opencl_library_t
))) == NULL
)
53 hb_error("hb_opencl_library_init: memory allocation failure");
57 opencl
->library
= HB_OCL_DLOPEN
;
58 if (opencl
->library
== NULL
)
63 #define HB_OCL_LOAD(func) \
65 if ((opencl->func = (void*)HB_OCL_DLSYM(opencl->library, #func)) == NULL) \
67 hb_log("hb_opencl_library_init: failed to load function '%s'", #func); \
71 HB_OCL_LOAD(clBuildProgram
);
72 HB_OCL_LOAD(clCreateBuffer
);
73 HB_OCL_LOAD(clCreateCommandQueue
);
74 HB_OCL_LOAD(clCreateContextFromType
);
75 HB_OCL_LOAD(clCreateKernel
);
76 HB_OCL_LOAD(clCreateProgramWithBinary
);
77 HB_OCL_LOAD(clCreateProgramWithSource
);
78 HB_OCL_LOAD(clEnqueueCopyBuffer
);
79 HB_OCL_LOAD(clEnqueueMapBuffer
);
80 HB_OCL_LOAD(clEnqueueNDRangeKernel
);
81 HB_OCL_LOAD(clEnqueueReadBuffer
);
82 HB_OCL_LOAD(clEnqueueUnmapMemObject
);
83 HB_OCL_LOAD(clEnqueueWriteBuffer
);
85 HB_OCL_LOAD(clGetCommandQueueInfo
);
86 HB_OCL_LOAD(clGetContextInfo
);
87 HB_OCL_LOAD(clGetDeviceIDs
);
88 HB_OCL_LOAD(clGetDeviceInfo
);
89 HB_OCL_LOAD(clGetPlatformIDs
);
90 HB_OCL_LOAD(clGetPlatformInfo
);
91 HB_OCL_LOAD(clGetProgramBuildInfo
);
92 HB_OCL_LOAD(clGetProgramInfo
);
93 HB_OCL_LOAD(clReleaseCommandQueue
);
94 HB_OCL_LOAD(clReleaseContext
);
95 HB_OCL_LOAD(clReleaseEvent
);
96 HB_OCL_LOAD(clReleaseKernel
);
97 HB_OCL_LOAD(clReleaseMemObject
);
98 HB_OCL_LOAD(clReleaseProgram
);
99 HB_OCL_LOAD(clSetKernelArg
);
100 HB_OCL_LOAD(clWaitForEvents
);
106 hb_opencl_library_close(&opencl
);
110 void hb_opencl_library_close(hb_opencl_library_t
**_opencl
)
116 hb_opencl_library_t
*opencl
= *_opencl
;
120 if (opencl
->library
!= NULL
)
122 HB_OCL_DLCLOSE(opencl
->library
);
129 static int hb_opencl_device_is_supported(hb_opencl_device_t
* device
)
131 // we only support OpenCL on GPUs for now
132 // Ivy Bridge supports OpenCL on GPU, but it's too slow to be usable
133 // FIXME: disable on NVIDIA to to a bug
134 if ((device
!= NULL
) &&
135 (device
->type
& CL_DEVICE_TYPE_GPU
) &&
136 (device
->ocl_vendor
!= HB_OCL_VENDOR_NVIDIA
) &&
137 (device
->ocl_vendor
!= HB_OCL_VENDOR_INTEL
||
138 hb_get_cpu_platform() != HB_CPU_PLATFORM_INTEL_IVB
))
141 // check OpenCL version:
142 // OpenCL<space><major_version.minor_version><space><vendor-specific information>
143 if (sscanf(device
->version
, "OpenCL %d.%d", &major
, &minor
) != 2)
147 return (major
> HB_OCL_MINVERSION_MAJOR
) || (major
== HB_OCL_MINVERSION_MAJOR
&&
148 minor
>= HB_OCL_MINVERSION_MINOR
);
153 static hb_opencl_device_t
* hb_opencl_device_get(hb_opencl_library_t
*opencl
,
154 cl_device_id device_id
)
156 if (opencl
== NULL
|| opencl
->clGetDeviceInfo
== NULL
)
158 hb_error("hb_opencl_device_get: OpenCL support not available");
161 else if (device_id
== NULL
)
163 hb_error("hb_opencl_device_get: invalid device ID");
167 hb_opencl_device_t
*device
= calloc(1, sizeof(hb_opencl_device_t
));
170 hb_error("hb_opencl_device_get: memory allocation failure");
174 cl_int status
= CL_SUCCESS
;
175 device
->id
= device_id
;
177 status
|= opencl
->clGetDeviceInfo(device
->id
, CL_DEVICE_VENDOR
, sizeof(device
->vendor
),
178 device
->vendor
, NULL
);
179 status
|= opencl
->clGetDeviceInfo(device
->id
, CL_DEVICE_NAME
, sizeof(device
->name
),
181 status
|= opencl
->clGetDeviceInfo(device
->id
, CL_DEVICE_VERSION
, sizeof(device
->version
),
182 device
->version
, NULL
);
183 status
|= opencl
->clGetDeviceInfo(device
->id
, CL_DEVICE_TYPE
, sizeof(device
->type
),
184 &device
->type
, NULL
);
185 status
|= opencl
->clGetDeviceInfo(device
->id
, CL_DEVICE_PLATFORM
, sizeof(device
->platform
),
186 &device
->platform
, NULL
);
187 status
|= opencl
->clGetDeviceInfo(device
->id
, CL_DRIVER_VERSION
, sizeof(device
->driver
),
188 device
->driver
, NULL
);
189 if (status
!= CL_SUCCESS
)
195 if (!strcmp(device
->vendor
, "Advanced Micro Devices, Inc.") ||
196 !strcmp(device
->vendor
, "AMD"))
198 device
->ocl_vendor
= HB_OCL_VENDOR_AMD
;
200 else if (!strncmp(device
->vendor
, "NVIDIA", 6 /* strlen("NVIDIA") */))
202 device
->ocl_vendor
= HB_OCL_VENDOR_NVIDIA
;
204 else if (!strncmp(device
->vendor
, "Intel", 5 /* strlen("Intel") */))
206 device
->ocl_vendor
= HB_OCL_VENDOR_INTEL
;
210 device
->ocl_vendor
= HB_OCL_VENDOR_OTHER
;
216 static void hb_opencl_devices_list_close(hb_list_t
**_list
)
220 hb_list_t
*list
= *_list
;
221 hb_opencl_device_t
*device
;
222 while (list
!= NULL
&& hb_list_count(list
) > 0)
224 if ((device
= hb_list_item(list
, 0)) != NULL
)
226 hb_list_rem(list
, device
);
231 hb_list_close(_list
);
234 static hb_list_t
* hb_opencl_devices_list_get(hb_opencl_library_t
*opencl
,
235 cl_device_type device_type
)
237 if (opencl
== NULL
||
238 opencl
->library
== NULL
||
239 opencl
->clGetDeviceIDs
== NULL
||
240 opencl
->clGetDeviceInfo
== NULL
||
241 opencl
->clGetPlatformIDs
== NULL
)
243 hb_error("hb_opencl_devices_list_get: OpenCL support not available");
247 hb_list_t
*list
= hb_list_init();
250 hb_error("hb_opencl_devices_list_get: memory allocation failure");
254 cl_device_id
*device_ids
= NULL
;
255 hb_opencl_device_t
*device
= NULL
;
256 cl_platform_id
*platform_ids
= NULL
;
257 cl_uint i
, j
, num_platforms
, num_devices
;
259 if (opencl
->clGetPlatformIDs(0, NULL
, &num_platforms
) != CL_SUCCESS
|| !num_platforms
)
263 if ((platform_ids
= malloc(sizeof(cl_platform_id
) * num_platforms
)) == NULL
)
265 hb_error("hb_opencl_devices_list_get: memory allocation failure");
268 if (opencl
->clGetPlatformIDs(num_platforms
, platform_ids
, NULL
) != CL_SUCCESS
)
272 for (i
= 0; i
< num_platforms
; i
++)
274 if (opencl
->clGetDeviceIDs(platform_ids
[i
], device_type
, 0, NULL
, &num_devices
) != CL_SUCCESS
|| !num_devices
)
279 if ((device_ids
= malloc(sizeof(cl_device_id
) * num_devices
)) == NULL
)
281 hb_error("hb_opencl_devices_list_get: memory allocation failure");
284 if (opencl
->clGetDeviceIDs(platform_ids
[i
], device_type
, num_devices
, device_ids
, NULL
) != CL_SUCCESS
)
289 for (j
= 0; j
< num_devices
; j
++)
291 if ((device
= hb_opencl_device_get(opencl
, device_ids
[j
])) != NULL
)
293 hb_list_add(list
, device
);
301 hb_opencl_devices_list_close(&list
);
309 int hb_opencl_available()
311 static int opencl_available
= -1;
312 if (opencl_available
>= 0)
314 return opencl_available
;
316 opencl_available
= 0;
319 * Check whether we can load the OpenCL library, then check devices and make
320 * sure we support running OpenCL code on at least one of them.
322 hb_opencl_library_t
*opencl
;
323 if ((opencl
= hb_opencl_library_init()) != NULL
)
326 hb_list_t
*device_list
;
327 hb_opencl_device_t
*device
;
328 if ((device_list
= hb_opencl_devices_list_get(opencl
, CL_DEVICE_TYPE_ALL
)) != NULL
)
330 for (i
= 0; i
< hb_list_count(device_list
); i
++)
332 if ((device
= hb_list_item(device_list
, i
)) != NULL
&&
333 (hb_opencl_device_is_supported(device
)))
335 opencl_available
= 1;
339 hb_opencl_devices_list_close(&device_list
);
341 hb_opencl_library_close(&opencl
);
343 return opencl_available
;
346 void hb_opencl_info_print()
349 * Note: this function should not log any warnings or errors.
350 * Its only purpose is to list OpenCL-capable devices, so let's initialize
351 * only what we absolutely need here, rather than calling library_open().
353 hb_opencl_library_t ocl
, *opencl
= &ocl
;
354 if ((opencl
->library
= (void*)HB_OCL_DLOPEN
) == NULL
||
355 (opencl
->clGetDeviceIDs
= (void*)HB_OCL_DLSYM(opencl
->library
, "clGetDeviceIDs" )) == NULL
||
356 (opencl
->clGetDeviceInfo
= (void*)HB_OCL_DLSYM(opencl
->library
, "clGetDeviceInfo" )) == NULL
||
357 (opencl
->clGetPlatformIDs
= (void*)HB_OCL_DLSYM(opencl
->library
, "clGetPlatformIDs")) == NULL
)
359 // zero or insufficient OpenCL support
360 hb_log("OpenCL: library not available");
365 hb_list_t
*device_list
;
366 hb_opencl_device_t
*device
;
367 if ((device_list
= hb_opencl_devices_list_get(opencl
, CL_DEVICE_TYPE_ALL
)) != NULL
)
369 for (i
= 0, idx
= 1; i
< hb_list_count(device_list
); i
++)
371 if ((device
= hb_list_item(device_list
, i
)) != NULL
)
373 // don't list CPU devices (always unsupported)
374 if (!(device
->type
& CL_DEVICE_TYPE_CPU
))
376 hb_log("OpenCL device #%d: %s %s", idx
++, device
->vendor
, device
->name
);
377 hb_log(" - OpenCL version: %s", device
->version
+ 7 /* strlen("OpenCL ") */);
378 hb_log(" - driver version: %s", device
->driver
);
379 hb_log(" - device type: %s%s",
380 device
->type
& CL_DEVICE_TYPE_CPU
? "CPU" :
381 device
->type
& CL_DEVICE_TYPE_GPU
? "GPU" :
382 device
->type
& CL_DEVICE_TYPE_CUSTOM
? "Custom" :
383 device
->type
& CL_DEVICE_TYPE_ACCELERATOR
? "Accelerator" : "Unknown",
384 device
->type
& CL_DEVICE_TYPE_DEFAULT
? " (default)" : "");
385 hb_log(" - supported: %s",
386 hb_opencl_device_is_supported(device
) ? "YES" : "no");
390 hb_opencl_devices_list_close(&device_list
);
395 * Close only the initialized part
397 if (opencl
->library
!= NULL
)
399 HB_OCL_DLCLOSE(opencl
->library
);