device_opencl.cpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /*
  2. * Copyright 2011-2013 Blender Foundation
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #ifdef WITH_OPENCL
  17. # include "device/opencl/opencl.h"
  18. # include "device/device_intern.h"
  19. # include "util/util_foreach.h"
  20. # include "util/util_logging.h"
  21. # include "util/util_set.h"
  22. # include "util/util_string.h"
  23. CCL_NAMESPACE_BEGIN
  24. Device *device_opencl_create(DeviceInfo &info, Stats &stats, Profiler &profiler, bool background)
  25. {
  26. return opencl_create_split_device(info, stats, profiler, background);
  27. }
  28. bool device_opencl_init()
  29. {
  30. static bool initialized = false;
  31. static bool result = false;
  32. if (initialized)
  33. return result;
  34. initialized = true;
  35. if (OpenCLInfo::device_type() != 0) {
  36. int clew_result = clewInit();
  37. if (clew_result == CLEW_SUCCESS) {
  38. VLOG(1) << "CLEW initialization succeeded.";
  39. result = true;
  40. }
  41. else {
  42. VLOG(1) << "CLEW initialization failed: "
  43. << ((clew_result == CLEW_ERROR_ATEXIT_FAILED) ? "Error setting up atexit() handler" :
  44. "Error opening the library");
  45. }
  46. }
  47. else {
  48. VLOG(1) << "Skip initializing CLEW, platform is force disabled.";
  49. result = false;
  50. }
  51. return result;
  52. }
  53. static cl_int device_opencl_get_num_platforms_safe(cl_uint *num_platforms)
  54. {
  55. # ifdef _WIN32
  56. __try {
  57. return clGetPlatformIDs(0, NULL, num_platforms);
  58. }
  59. __except (EXCEPTION_EXECUTE_HANDLER) {
  60. /* Ignore crashes inside the OpenCL driver and hope we can
  61. * survive even with corrupted OpenCL installs. */
  62. fprintf(stderr, "Cycles OpenCL: driver crashed, continuing without OpenCL.\n");
  63. }
  64. *num_platforms = 0;
  65. return CL_DEVICE_NOT_FOUND;
  66. # else
  67. return clGetPlatformIDs(0, NULL, num_platforms);
  68. # endif
  69. }
  70. void device_opencl_info(vector<DeviceInfo> &devices)
  71. {
  72. cl_uint num_platforms = 0;
  73. device_opencl_get_num_platforms_safe(&num_platforms);
  74. if (num_platforms == 0) {
  75. return;
  76. }
  77. vector<OpenCLPlatformDevice> usable_devices;
  78. OpenCLInfo::get_usable_devices(&usable_devices);
  79. /* Devices are numbered consecutively across platforms. */
  80. int num_devices = 0;
  81. set<string> unique_ids;
  82. foreach (OpenCLPlatformDevice &platform_device, usable_devices) {
  83. /* Compute unique ID for persistent user preferences. */
  84. const string &platform_name = platform_device.platform_name;
  85. const string &device_name = platform_device.device_name;
  86. string hardware_id = platform_device.hardware_id;
  87. if (hardware_id == "") {
  88. hardware_id = string_printf("ID_%d", num_devices);
  89. }
  90. string id = string("OPENCL_") + platform_name + "_" + device_name + "_" + hardware_id;
  91. /* Hardware ID might not be unique, add device number in that case. */
  92. if (unique_ids.find(id) != unique_ids.end()) {
  93. id += string_printf("_ID_%d", num_devices);
  94. }
  95. unique_ids.insert(id);
  96. /* Create DeviceInfo. */
  97. DeviceInfo info;
  98. info.type = DEVICE_OPENCL;
  99. info.description = string_remove_trademark(string(device_name));
  100. info.num = num_devices;
  101. /* We don't know if it's used for display, but assume it is. */
  102. info.display_device = true;
  103. info.use_split_kernel = true;
  104. info.has_volume_decoupled = false;
  105. info.id = id;
  106. /* Check OpenCL extensions */
  107. info.has_half_images = platform_device.device_extensions.find("cl_khr_fp16") != string::npos;
  108. devices.push_back(info);
  109. num_devices++;
  110. }
  111. }
  112. string device_opencl_capabilities()
  113. {
  114. if (OpenCLInfo::device_type() == 0) {
  115. return "All OpenCL devices are forced to be OFF";
  116. }
  117. string result = "";
  118. string error_msg = ""; /* Only used by opencl_assert(), but in the future
  119. * it could also be nicely reported to the console.
  120. */
  121. cl_uint num_platforms = 0;
  122. opencl_assert(device_opencl_get_num_platforms_safe(&num_platforms));
  123. if (num_platforms == 0) {
  124. return "No OpenCL platforms found\n";
  125. }
  126. result += string_printf("Number of platforms: %u\n", num_platforms);
  127. vector<cl_platform_id> platform_ids;
  128. platform_ids.resize(num_platforms);
  129. opencl_assert(clGetPlatformIDs(num_platforms, &platform_ids[0], NULL));
  130. typedef char cl_string[1024];
  131. # define APPEND_INFO(func, id, name, what, type) \
  132. do { \
  133. type data; \
  134. memset(&data, 0, sizeof(data)); \
  135. opencl_assert(func(id, what, sizeof(data), &data, NULL)); \
  136. result += string_printf("%s: %s\n", name, to_string(data).c_str()); \
  137. } while (false)
  138. # define APPEND_STRING_EXTENSION_INFO(func, id, name, what) \
  139. do { \
  140. char data[1024] = "\0"; \
  141. size_t length = 0; \
  142. if (func(id, what, sizeof(data), &data, &length) == CL_SUCCESS) { \
  143. if (length != 0 && data[0] != '\0') { \
  144. result += string_printf("%s: %s\n", name, data); \
  145. } \
  146. } \
  147. } while (false)
  148. # define APPEND_PLATFORM_INFO(id, name, what, type) \
  149. APPEND_INFO(clGetPlatformInfo, id, "\tPlatform " name, what, type)
  150. # define APPEND_DEVICE_INFO(id, name, what, type) \
  151. APPEND_INFO(clGetDeviceInfo, id, "\t\t\tDevice " name, what, type)
  152. # define APPEND_DEVICE_STRING_EXTENSION_INFO(id, name, what) \
  153. APPEND_STRING_EXTENSION_INFO(clGetDeviceInfo, id, "\t\t\tDevice " name, what)
  154. vector<cl_device_id> device_ids;
  155. for (cl_uint platform = 0; platform < num_platforms; ++platform) {
  156. cl_platform_id platform_id = platform_ids[platform];
  157. result += string_printf("Platform #%u\n", platform);
  158. APPEND_PLATFORM_INFO(platform_id, "Name", CL_PLATFORM_NAME, cl_string);
  159. APPEND_PLATFORM_INFO(platform_id, "Vendor", CL_PLATFORM_VENDOR, cl_string);
  160. APPEND_PLATFORM_INFO(platform_id, "Version", CL_PLATFORM_VERSION, cl_string);
  161. APPEND_PLATFORM_INFO(platform_id, "Profile", CL_PLATFORM_PROFILE, cl_string);
  162. APPEND_PLATFORM_INFO(platform_id, "Extensions", CL_PLATFORM_EXTENSIONS, cl_string);
  163. cl_uint num_devices = 0;
  164. opencl_assert(
  165. clGetDeviceIDs(platform_ids[platform], CL_DEVICE_TYPE_ALL, 0, NULL, &num_devices));
  166. result += string_printf("\tNumber of devices: %u\n", num_devices);
  167. device_ids.resize(num_devices);
  168. opencl_assert(clGetDeviceIDs(
  169. platform_ids[platform], CL_DEVICE_TYPE_ALL, num_devices, &device_ids[0], NULL));
  170. for (cl_uint device = 0; device < num_devices; ++device) {
  171. cl_device_id device_id = device_ids[device];
  172. result += string_printf("\t\tDevice: #%u\n", device);
  173. APPEND_DEVICE_INFO(device_id, "Name", CL_DEVICE_NAME, cl_string);
  174. APPEND_DEVICE_STRING_EXTENSION_INFO(device_id, "Board Name", CL_DEVICE_BOARD_NAME_AMD);
  175. APPEND_DEVICE_INFO(device_id, "Vendor", CL_DEVICE_VENDOR, cl_string);
  176. APPEND_DEVICE_INFO(device_id, "OpenCL C Version", CL_DEVICE_OPENCL_C_VERSION, cl_string);
  177. APPEND_DEVICE_INFO(device_id, "Profile", CL_DEVICE_PROFILE, cl_string);
  178. APPEND_DEVICE_INFO(device_id, "Version", CL_DEVICE_VERSION, cl_string);
  179. APPEND_DEVICE_INFO(device_id, "Extensions", CL_DEVICE_EXTENSIONS, cl_string);
  180. APPEND_DEVICE_INFO(
  181. device_id, "Max clock frequency (MHz)", CL_DEVICE_MAX_CLOCK_FREQUENCY, cl_uint);
  182. APPEND_DEVICE_INFO(device_id, "Max compute units", CL_DEVICE_MAX_COMPUTE_UNITS, cl_uint);
  183. APPEND_DEVICE_INFO(device_id, "Max work group size", CL_DEVICE_MAX_WORK_GROUP_SIZE, size_t);
  184. }
  185. }
  186. # undef APPEND_STRING_INFO
  187. # undef APPEND_PLATFORM_STRING_INFO
  188. # undef APPEND_DEVICE_STRING_INFO
  189. return result;
  190. }
  191. CCL_NAMESPACE_END
  192. #endif /* WITH_OPENCL */