diff --git a/api/Makefile.am b/api/Makefile.am index 04fcf7898f..20a3b48806 100644 --- a/api/Makefile.am +++ b/api/Makefile.am @@ -8,8 +8,9 @@ if ENABLE_LIBRARIES # stuff linked into both main app and graphics app api_files= \ boinc_api.cpp \ - reduce_main.cpp \ - graphics2_util.cpp + boinc_opencl.cpp \ + graphics2_util.cpp \ + reduce_main.cpp # stuff linked into graphics app graphics2_files = \ diff --git a/api/boinc_opencl.cpp b/api/boinc_opencl.cpp new file mode 100644 index 0000000000..0208354bea --- /dev/null +++ b/api/boinc_opencl.cpp @@ -0,0 +1,208 @@ +// This file is part of BOINC. +// http://boinc.berkeley.edu +// Copyright (C) 2011 University of California +// +// BOINC is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// BOINC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with BOINC. If not, see . + +// BOINC API for OpenCL + +#ifdef _WIN32 +#include "win_util.h" +#else +#ifdef __APPLE__ +// Suppress obsolete warning when building for OS 10.3.9 +#define DLOPEN_NO_WARN +#include +#endif +#include "config.h" +#include +#include +#include +#endif + +#include "error_numbers.h" +#include "str_replace.h" + +#include "coproc.h" + +#include "boinc_opencl.h" + +#ifdef _WIN32 +static HMODULE opencl_lib = NULL; + +typedef cl_int (__stdcall *CL_PLATFORMIDS) (cl_uint, cl_platform_id*, cl_uint*); +typedef cl_int (__stdcall *CL_DEVICEIDS)(cl_platform_id, cl_device_type, cl_uint, cl_device_id*, cl_uint*); +typedef cl_int (__stdcall *CL_INFO) (cl_device_id, cl_device_info, size_t, void*, size_t*); + +static CL_PLATFORMIDS __clGetPlatformIDs = NULL; +static CL_DEVICEIDS __clGetDeviceIDs = NULL; +static CL_INFO __clGetDeviceInfo = NULL; + +#else + +static jmp_buf resume; + +static void segv_handler(int) { + longjmp(resume, 1); +} + +static void* opencl_lib = NULL; + +static cl_int (*__clGetPlatformIDs)(cl_uint /* num_entries */, + cl_platform_id * /* platforms */, + cl_uint * /* num_platforms */); +static cl_int (*__clGetDeviceIDs)(cl_platform_id /* platform */, + cl_device_type /* device_type */, + cl_uint /* num_entries */, + cl_device_id * /* devices */, + cl_uint * /* num_devices */); +static cl_int (*__clGetDeviceInfo)(cl_device_id /* device */, + cl_device_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */); +#endif + +void boinc_get_opencl_ids(char *type, int device_num, OPENCL_REFERENCE *ref) { + cl_int errnum; + cl_platform_id platforms[MAX_OPENCL_PLATFORMS]; + cl_uint num_platforms, platform_index, num_devices; + cl_device_id devices[MAX_COPROC_INSTANCES]; + char vendor[256]; // Device vendor (NVIDIA, ATI, AMD, etc.) + +#ifdef _WIN32 + opencl_lib = LoadLibrary("OpenCL.dll"); + if (!opencl_lib) { + ref->retval = ERR_NOT_IMPLEMENTED; + return; + } + __clGetPlatformIDs = (CL_PLATFORMIDS)GetProcAddress( opencl_lib, "clGetPlatformIDs" ); + __clGetDeviceIDs = (CL_DEVICEIDS)GetProcAddress( opencl_lib, "clGetDeviceIDs" ); + __clGetDeviceInfo = (CL_INFO)GetProcAddress( opencl_lib, "clGetDeviceInfo" ); +#else +#ifdef __APPLE__ + opencl_lib = dlopen("/System/Library/Frameworks/OpenCL.framework/Versions/Current/OpenCL", RTLD_NOW); +#else +//TODO: Is this correct? + opencl_lib = dlopen("libOpenCL.so", RTLD_NOW); +#endif + + if (!opencl_lib) { + ref->retval = ERR_NOT_IMPLEMENTED; + return; + } + + __clGetPlatformIDs = (cl_int(*)(cl_uint, cl_platform_id*, cl_uint*)) dlsym( opencl_lib, "clGetPlatformIDs" ); + __clGetDeviceIDs = (cl_int(*)(cl_platform_id, cl_device_type, cl_uint, cl_device_id*, cl_uint*)) dlsym( opencl_lib, "clGetDeviceIDs" ); + __clGetDeviceInfo = (cl_int(*)(cl_device_id, cl_device_info, size_t, void*, size_t*)) dlsym( opencl_lib, "clGetDeviceInfo" ); +#endif + if ((!__clGetPlatformIDs) || (!__clGetDeviceIDs) || (!__clGetDeviceInfo)) { + ref->retval = ERR_NOT_IMPLEMENTED; + goto bail; + } + + errnum = (*__clGetPlatformIDs)(MAX_OPENCL_PLATFORMS, platforms, &num_platforms); + if (num_platforms == 0) errnum = CL_DEVICE_NOT_FOUND; + if (errnum != CL_SUCCESS) { + ref->retval = errnum; + goto bail; + } + + for (platform_index=0; platform_index (cl_uint)(device_num + 1)) continue; + + cl_device_id device_id = devices[device_num]; + + errnum = (*__clGetDeviceInfo)(device_id, CL_DEVICE_VENDOR, sizeof(vendor), vendor, NULL); + if ((errnum != CL_SUCCESS) || (vendor[0] == 0)) continue; + + if ((strstr(vendor, "AMD")) || + (strstr(vendor, "Advanced Micro Devices, Inc.")) + ) { + strcpy(vendor, GPU_TYPE_ATI); + } + + if (!strcmp(vendor, type)) { + ref->device_id = device_id; + ref->platform_id = platforms[platform_index]; + break; + } + } + +bail: +#ifndef _WIN32 + dlclose(opencl_lib); +#endif + + if ((ref->retval == CL_SUCCESS) && (ref->device_id == NULL)) { + ref->retval = CL_DEVICE_NOT_FOUND; + } +} + +OPENCL_REFERENCE boinc_get_opencl_ids(int argc, char** argv) { + OPENCL_REFERENCE ref; + char type[256]; + int device_num; + + memset(&ref, 0, sizeof(struct OPENCL_REFERENCE)); + type[0] = '\0'; + device_num = -1; + + for (int i = 1; i < argc; i++) { + if (!strcmp(argv[i], "--gpu_type")) { + strlcpy(type, argv[++i], sizeof(type)); + } + if (!strcmp(argv[i], "--device")) { + device_num = atoi(argv[++i]); + } + } + + if (type[0] == '\0'){ + ref.retval = CL_INVALID_DEVICE_TYPE; + return ref; + } + + if (device_num < 0) { + ref.retval = CL_INVALID_DEVICE; + return ref; + } + +#ifdef _WIN32 + try { + boinc_get_opencl_ids(type, device_num, &ref); + } + catch (...) { + ref.retval = ERR_SIGNAL_CATCH; + } +#else + void (*old_sig)(int) = signal(SIGSEGV, segv_handler); + if (setjmp(resume)) { + ref.retval = ERR_SIGNAL_CATCH; + } else { + boinc_get_opencl_ids(type, device_num, &ref); + } + + signal(SIGSEGV, old_sig); +#endif + + if ((ref.retval == CL_SUCCESS) && (ref.device_id == NULL)) { + ref.retval = CL_DEVICE_NOT_FOUND; + } + + return ref; +} diff --git a/api/boinc_opencl.h b/api/boinc_opencl.h new file mode 100644 index 0000000000..9067d3cd77 --- /dev/null +++ b/api/boinc_opencl.h @@ -0,0 +1,26 @@ +// This file is part of BOINC. +// http://boinc.berkeley.edu +// Copyright (C) 2011 University of California +// +// BOINC is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// BOINC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with BOINC. If not, see . + +// BOINC API for OpenCL apps + +struct OPENCL_REFERENCE { + cl_device_id device_id; + cl_platform_id platform_id; + cl_int retval; +}; + +OPENCL_REFERENCE boinc_get_opencl_ids(int argc, char** argv); diff --git a/checkin_notes b/checkin_notes index e023244b12..886043417d 100644 --- a/checkin_notes +++ b/checkin_notes @@ -5353,3 +5353,13 @@ Charlie 31 Aug 2011 lib/ coproc.cpp, .h + +David 31 Aug 2011 + - move boinc_get_opencl_ids() from lib/ to api/. + lib/ is for code that's used by >1 part of BOINC + + lib/ + coproc.cpp,h + api/ + boinc_opencl.cpp,h (new) + Makefile.am diff --git a/lib/coproc.cpp b/lib/coproc.cpp index 455fbc8e99..93869bab70 100644 --- a/lib/coproc.cpp +++ b/lib/coproc.cpp @@ -669,175 +669,3 @@ void COPROC_ATI::description(char* buf) { name, version, attribs.localRAM/1024.*1024., peak_flops/1.e9 ); } - -#ifndef __WXWINDOWS__ /* Exclude from Manager */ - -#ifdef _WIN32 -static HMODULE opencl_lib = NULL; - -typedef cl_int (__stdcall *CL_PLATFORMIDS) (cl_uint, cl_platform_id*, cl_uint*); -typedef cl_int (__stdcall *CL_DEVICEIDS)(cl_platform_id, cl_device_type, cl_uint, cl_device_id*, cl_uint*); -typedef cl_int (__stdcall *CL_INFO) (cl_device_id, cl_device_info, size_t, void*, size_t*); - -static CL_PLATFORMIDS __clGetPlatformIDs = NULL; -static CL_DEVICEIDS __clGetDeviceIDs = NULL; -static CL_INFO __clGetDeviceInfo = NULL; - -#else - -static jmp_buf resume; - -static void segv_handler(int) { - longjmp(resume, 1); -} - -static void* opencl_lib = NULL; - -static cl_int (*__clGetPlatformIDs)(cl_uint /* num_entries */, - cl_platform_id * /* platforms */, - cl_uint * /* num_platforms */); -static cl_int (*__clGetDeviceIDs)(cl_platform_id /* platform */, - cl_device_type /* device_type */, - cl_uint /* num_entries */, - cl_device_id * /* devices */, - cl_uint * /* num_devices */); -static cl_int (*__clGetDeviceInfo)(cl_device_id /* device */, - cl_device_info /* param_name */, - size_t /* param_value_size */, - void * /* param_value */, - size_t * /* param_value_size_ret */); -#endif - -void boinc_get_opencl_ids(char *type, int device_num, OPENCL_REFERENCE *ref) { - cl_int errnum; - cl_platform_id platforms[MAX_OPENCL_PLATFORMS]; - cl_uint num_platforms, platform_index, num_devices; - cl_device_id devices[MAX_COPROC_INSTANCES]; - char vendor[256]; // Device vendor (NVIDIA, ATI, AMD, etc.) - -#ifdef _WIN32 - opencl_lib = LoadLibrary("OpenCL.dll"); - if (!opencl_lib) { - ref->retval = ERR_NOT_IMPLEMENTED; - return; - } - __clGetPlatformIDs = (CL_PLATFORMIDS)GetProcAddress( opencl_lib, "clGetPlatformIDs" ); - __clGetDeviceIDs = (CL_DEVICEIDS)GetProcAddress( opencl_lib, "clGetDeviceIDs" ); - __clGetDeviceInfo = (CL_INFO)GetProcAddress( opencl_lib, "clGetDeviceInfo" ); -#else -#ifdef __APPLE__ - opencl_lib = dlopen("/System/Library/Frameworks/OpenCL.framework/Versions/Current/OpenCL", RTLD_NOW); -#else -//TODO: Is this correct? - opencl_lib = dlopen("libOpenCL.so", RTLD_NOW); -#endif - - if (!opencl_lib) { - ref->retval = ERR_NOT_IMPLEMENTED; - return; - } - - __clGetPlatformIDs = (cl_int(*)(cl_uint, cl_platform_id*, cl_uint*)) dlsym( opencl_lib, "clGetPlatformIDs" ); - __clGetDeviceIDs = (cl_int(*)(cl_platform_id, cl_device_type, cl_uint, cl_device_id*, cl_uint*)) dlsym( opencl_lib, "clGetDeviceIDs" ); - __clGetDeviceInfo = (cl_int(*)(cl_device_id, cl_device_info, size_t, void*, size_t*)) dlsym( opencl_lib, "clGetDeviceInfo" ); -#endif - if ((!__clGetPlatformIDs) || (!__clGetDeviceIDs) || (!__clGetDeviceInfo)) { - ref->retval = ERR_NOT_IMPLEMENTED; - goto bail; - } - - errnum = (*__clGetPlatformIDs)(MAX_OPENCL_PLATFORMS, platforms, &num_platforms); - if (num_platforms == 0) errnum = CL_DEVICE_NOT_FOUND; - if (errnum != CL_SUCCESS) { - ref->retval = errnum; - goto bail; - } - - for (platform_index=0; platform_index (cl_uint)(device_num + 1)) continue; - - cl_device_id device_id = devices[device_num]; - - errnum = (*__clGetDeviceInfo)(device_id, CL_DEVICE_VENDOR, sizeof(vendor), vendor, NULL); - if ((errnum != CL_SUCCESS) || (vendor[0] == 0)) continue; - - if ((strstr(vendor, "AMD")) || - (strstr(vendor, "Advanced Micro Devices, Inc.")) - ) { - strcpy(vendor, GPU_TYPE_ATI); - } - - if (!strcmp(vendor, type)) { - ref->device_id = device_id; - ref->platform_id = platforms[platform_index]; - break; - } - } - -bail: -#ifndef _WIN32 - dlclose(opencl_lib); -#endif - - if ((ref->retval == CL_SUCCESS) && (ref->device_id == NULL)) { - ref->retval = CL_DEVICE_NOT_FOUND; - } -} - -OPENCL_REFERENCE boinc_get_opencl_ids(int argc, char** argv) { - OPENCL_REFERENCE ref; - char type[256]; - int device_num; - - memset(&ref, 0, sizeof(struct OPENCL_REFERENCE)); - type[0] = '\0'; - device_num = -1; - - for (int i = 1; i < argc; i++) { - if (!strcmp(argv[i], "--gpu_type")) { - strlcpy(type, argv[++i], sizeof(type)); - } - if (!strcmp(argv[i], "--device")) { - device_num = atoi(argv[++i]); - } - } - - if (type[0] == '\0'){ - ref.retval = CL_INVALID_DEVICE_TYPE; - return ref; - } - - if (device_num < 0) { - ref.retval = CL_INVALID_DEVICE; - return ref; - } - -#ifdef _WIN32 - try { - boinc_get_opencl_ids(type, device_num, &ref); - } - catch (...) { - ref.retval = ERR_SIGNAL_CATCH; - } -#else - void (*old_sig)(int) = signal(SIGSEGV, segv_handler); - if (setjmp(resume)) { - ref.retval = ERR_SIGNAL_CATCH; - } else { - boinc_get_opencl_ids(type, device_num, &ref); - } - - signal(SIGSEGV, old_sig); -#endif - - if ((ref.retval == CL_SUCCESS) && (ref.device_id == NULL)) { - ref.retval = CL_DEVICE_NOT_FOUND; - } - - return ref; -} -#endif // __WXWINDOWS \ No newline at end of file diff --git a/lib/coproc.h b/lib/coproc.h index a98b965f16..636e8a8217 100644 --- a/lib/coproc.h +++ b/lib/coproc.h @@ -83,13 +83,6 @@ #define GPU_TYPE_NVIDIA "NVIDIA" #define GPU_TYPE_ATI "ATI" -#define GPU_TYPE_AMD GPU_TYPE_ATI - -struct OPENCL_REFERENCE { - cl_device_id device_id; - cl_platform_id platform_id; - cl_int retval; -}; // represents a requirement for a coproc. // This is a parsed version of the elements in an @@ -411,6 +404,4 @@ struct COPROCS { } }; -OPENCL_REFERENCE boinc_get_opencl_ids(int argc, char** argv); - #endif