Blender  V2.93
device_opencl.cpp
Go to the documentation of this file.
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 
17 #ifdef WITH_OPENCL
18 
20 # include "device/device.h"
21 # include "device/device_intern.h"
22 
23 # include "util/util_foreach.h"
24 # include "util/util_logging.h"
25 # include "util/util_set.h"
26 # include "util/util_string.h"
27 
29 
30 Device *device_opencl_create(DeviceInfo &info, Stats &stats, Profiler &profiler, bool background)
31 {
32  return opencl_create_split_device(info, stats, profiler, background);
33 }
34 
35 bool device_opencl_init()
36 {
37  static bool initialized = false;
38  static bool result = false;
39 
40  if (initialized)
41  return result;
42 
43  initialized = true;
44 
45  if (OpenCLInfo::device_type() != 0) {
46  int clew_result = clewInit();
47  if (clew_result == CLEW_SUCCESS) {
48  VLOG(1) << "CLEW initialization succeeded.";
49  result = true;
50  }
51  else {
52  VLOG(1) << "CLEW initialization failed: "
53  << ((clew_result == CLEW_ERROR_ATEXIT_FAILED) ? "Error setting up atexit() handler" :
54  "Error opening the library");
55  }
56  }
57  else {
58  VLOG(1) << "Skip initializing CLEW, platform is force disabled.";
59  result = false;
60  }
61 
62  return result;
63 }
64 
65 static cl_int device_opencl_get_num_platforms_safe(cl_uint *num_platforms)
66 {
67 # ifdef _WIN32
68  __try {
69  return clGetPlatformIDs(0, NULL, num_platforms);
70  }
71  __except (EXCEPTION_EXECUTE_HANDLER) {
72  /* Ignore crashes inside the OpenCL driver and hope we can
73  * survive even with corrupted OpenCL installs. */
74  fprintf(stderr, "Cycles OpenCL: driver crashed, continuing without OpenCL.\n");
75  }
76 
77  *num_platforms = 0;
78  return CL_DEVICE_NOT_FOUND;
79 # else
80  return clGetPlatformIDs(0, NULL, num_platforms);
81 # endif
82 }
83 
85 {
86  cl_uint num_platforms = 0;
87  device_opencl_get_num_platforms_safe(&num_platforms);
88  if (num_platforms == 0) {
89  return;
90  }
91 
92  vector<OpenCLPlatformDevice> usable_devices;
93  OpenCLInfo::get_usable_devices(&usable_devices);
94  /* Devices are numbered consecutively across platforms. */
95  int num_devices = 0;
96  set<string> unique_ids;
97  foreach (OpenCLPlatformDevice &platform_device, usable_devices) {
98  /* Compute unique ID for persistent user preferences. */
99  const string &platform_name = platform_device.platform_name;
100  const string &device_name = platform_device.device_name;
101  string hardware_id = platform_device.hardware_id;
102  if (hardware_id == "") {
103  hardware_id = string_printf("ID_%d", num_devices);
104  }
105  string id = string("OPENCL_") + platform_name + "_" + device_name + "_" + hardware_id;
106 
107  /* Hardware ID might not be unique, add device number in that case. */
108  if (unique_ids.find(id) != unique_ids.end()) {
109  id += string_printf("_ID_%d", num_devices);
110  }
111  unique_ids.insert(id);
112 
113  /* Create DeviceInfo. */
114  DeviceInfo info;
115  info.type = DEVICE_OPENCL;
116  info.description = string_remove_trademark(string(device_name));
117  info.num = num_devices;
118  /* We don't know if it's used for display, but assume it is. */
119  info.display_device = true;
120  info.use_split_kernel = true;
121  info.has_volume_decoupled = false;
122  info.has_adaptive_stop_per_sample = false;
123  info.denoisers = DENOISER_NLM;
124  info.id = id;
125 
126  /* Check OpenCL extensions */
127  info.has_half_images = platform_device.device_extensions.find("cl_khr_fp16") != string::npos;
128 
129  /* Disabled for now due to apparent AMD driver bug. */
130  info.has_nanovdb = platform_name != "AMD Accelerated Parallel Processing";
131 
132  devices.push_back(info);
133  num_devices++;
134  }
135 }
136 
138 {
139  if (OpenCLInfo::device_type() == 0) {
140  return "All OpenCL devices are forced to be OFF";
141  }
142  string result = "";
143  string error_msg = ""; /* Only used by opencl_assert(), but in the future
144  * it could also be nicely reported to the console.
145  */
146  cl_uint num_platforms = 0;
147  opencl_assert(device_opencl_get_num_platforms_safe(&num_platforms));
148  if (num_platforms == 0) {
149  return "No OpenCL platforms found\n";
150  }
151  result += string_printf("Number of platforms: %u\n", num_platforms);
152 
153  vector<cl_platform_id> platform_ids;
154  platform_ids.resize(num_platforms);
155  opencl_assert(clGetPlatformIDs(num_platforms, &platform_ids[0], NULL));
156 
157 # define APPEND_INFO(func, id, name, what, type) \
158  do { \
159  type data; \
160  memset(&data, 0, sizeof(data)); \
161  opencl_assert(func(id, what, sizeof(data), &data, NULL)); \
162  result += string_printf("%s: %s\n", name, to_string(data).c_str()); \
163  } while (false)
164 # define APPEND_STRING_INFO_IMPL(func, id, name, what, is_optional) \
165  do { \
166  string value; \
167  size_t length = 0; \
168  if (func(id, what, 0, NULL, &length) == CL_SUCCESS) { \
169  vector<char> buffer(length + 1); \
170  if (func(id, what, buffer.size(), buffer.data(), NULL) == CL_SUCCESS) { \
171  value = string(buffer.data()); \
172  } \
173  } \
174  if (is_optional && !(length != 0 && value[0] != '\0')) { \
175  break; \
176  } \
177  result += string_printf("%s: %s\n", name, value.c_str()); \
178  } while (false)
179 # define APPEND_PLATFORM_STRING_INFO(id, name, what) \
180  APPEND_STRING_INFO_IMPL(clGetPlatformInfo, id, "\tPlatform " name, what, false)
181 # define APPEND_STRING_EXTENSION_INFO(func, id, name, what) \
182  APPEND_STRING_INFO_IMPL(clGetPlatformInfo, id, "\tPlatform " name, what, true)
183 # define APPEND_PLATFORM_INFO(id, name, what, type) \
184  APPEND_INFO(clGetPlatformInfo, id, "\tPlatform " name, what, type)
185 # define APPEND_DEVICE_INFO(id, name, what, type) \
186  APPEND_INFO(clGetDeviceInfo, id, "\t\t\tDevice " name, what, type)
187 # define APPEND_DEVICE_STRING_INFO(id, name, what) \
188  APPEND_STRING_INFO_IMPL(clGetDeviceInfo, id, "\t\t\tDevice " name, what, false)
189 # define APPEND_DEVICE_STRING_EXTENSION_INFO(id, name, what) \
190  APPEND_STRING_INFO_IMPL(clGetDeviceInfo, id, "\t\t\tDevice " name, what, true)
191 
192  vector<cl_device_id> device_ids;
193  for (cl_uint platform = 0; platform < num_platforms; ++platform) {
194  cl_platform_id platform_id = platform_ids[platform];
195 
196  result += string_printf("Platform #%u\n", platform);
197 
198  APPEND_PLATFORM_STRING_INFO(platform_id, "Name", CL_PLATFORM_NAME);
199  APPEND_PLATFORM_STRING_INFO(platform_id, "Vendor", CL_PLATFORM_VENDOR);
200  APPEND_PLATFORM_STRING_INFO(platform_id, "Version", CL_PLATFORM_VERSION);
201  APPEND_PLATFORM_STRING_INFO(platform_id, "Profile", CL_PLATFORM_PROFILE);
202  APPEND_PLATFORM_STRING_INFO(platform_id, "Extensions", CL_PLATFORM_EXTENSIONS);
203 
204  cl_uint num_devices = 0;
205  opencl_assert(
206  clGetDeviceIDs(platform_ids[platform], CL_DEVICE_TYPE_ALL, 0, NULL, &num_devices));
207  result += string_printf("\tNumber of devices: %u\n", num_devices);
208 
209  device_ids.resize(num_devices);
210  opencl_assert(clGetDeviceIDs(
211  platform_ids[platform], CL_DEVICE_TYPE_ALL, num_devices, &device_ids[0], NULL));
212  for (cl_uint device = 0; device < num_devices; ++device) {
213  cl_device_id device_id = device_ids[device];
214 
215  result += string_printf("\t\tDevice: #%u\n", device);
216 
217  APPEND_DEVICE_STRING_INFO(device_id, "Name", CL_DEVICE_NAME);
218  APPEND_DEVICE_STRING_EXTENSION_INFO(device_id, "Board Name", CL_DEVICE_BOARD_NAME_AMD);
219  APPEND_DEVICE_STRING_INFO(device_id, "Vendor", CL_DEVICE_VENDOR);
220  APPEND_DEVICE_STRING_INFO(device_id, "OpenCL C Version", CL_DEVICE_OPENCL_C_VERSION);
221  APPEND_DEVICE_STRING_INFO(device_id, "Profile", CL_DEVICE_PROFILE);
222  APPEND_DEVICE_STRING_INFO(device_id, "Version", CL_DEVICE_VERSION);
223  APPEND_DEVICE_STRING_INFO(device_id, "Extensions", CL_DEVICE_EXTENSIONS);
224  APPEND_DEVICE_INFO(
225  device_id, "Max clock frequency (MHz)", CL_DEVICE_MAX_CLOCK_FREQUENCY, cl_uint);
226  APPEND_DEVICE_INFO(device_id, "Max compute units", CL_DEVICE_MAX_COMPUTE_UNITS, cl_uint);
227  APPEND_DEVICE_INFO(device_id, "Max work group size", CL_DEVICE_MAX_WORK_GROUP_SIZE, size_t);
228  }
229  }
230 
231 # undef APPEND_INFO
232 # undef APPEND_STRING_INFO_IMPL
233 # undef APPEND_PLATFORM_STRING_INFO
234 # undef APPEND_STRING_EXTENSION_INFO
235 # undef APPEND_PLATFORM_INFO
236 # undef APPEND_DEVICE_INFO
237 # undef APPEND_DEVICE_STRING_INFO
238 # undef APPEND_DEVICE_STRING_EXTENSION_INFO
239 
240  return result;
241 }
242 
244 
245 #endif /* WITH_OPENCL */
bool has_half_images
Definition: device.h:79
int num
Definition: device.h:77
string id
Definition: device.h:76
bool use_split_kernel
Definition: device.h:85
DenoiserTypeMask denoisers
Definition: device.h:88
bool display_device
Definition: device.h:78
bool has_nanovdb
Definition: device.h:80
bool has_adaptive_stop_per_sample
Definition: device.h:83
DeviceType type
Definition: device.h:74
string description
Definition: device.h:75
bool has_volume_decoupled
Definition: device.h:81
Definition: device.h:293
@ DEVICE_OPENCL
Definition: device.h:46
bool device_opencl_init()
void device_opencl_info(vector< DeviceInfo > &devices)
Device * device_opencl_create(DeviceInfo &info, Stats &stats, Profiler &profiler, bool background)
string device_opencl_capabilities()
@ DENOISER_NLM
Definition: device_task.h:36
static bool initialized
Definition: gpu_init_exit.c:41
#define CCL_NAMESPACE_END
Vector< CPUDevice > devices
list of all CPUDevices. for every hardware thread an instance of CPUDevice is created
#define VLOG(severity)
Definition: util_logging.h:50
string string_remove_trademark(const string &s)
CCL_NAMESPACE_BEGIN string string_printf(const char *format,...)
Definition: util_string.cpp:32