diff options
author | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2019-01-29 18:39:30 +0300 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2019-01-29 19:00:02 +0300 |
commit | 001414fb2f7346d2ff332bf851373522d87659d7 (patch) | |
tree | 366112462b869a31767d7439b04b900ba21044c1 /intern/cycles/device/device.cpp | |
parent | e37b9b5d0d2664697de8f1c7614e88073dd8ff49 (diff) |
Cycles: delay CUDA and OpenCL initialization to avoid driver crashes.
We've had many reported crashes on Windows where we suspect there is a
corrupted OpenCL driver. The purpose here is to keep Blender generally
usable in such cases.
Now it always shows None / CUDA / OpenCL in the preferences, and only when
selecting one will it reveal if there are any GPUs available. This should
avoid crashes when opening the preferences or on startup.
Differential Revision: https://developer.blender.org/D4265
Diffstat (limited to 'intern/cycles/device/device.cpp')
-rw-r--r-- | intern/cycles/device/device.cpp | 132 |
1 files changed, 89 insertions, 43 deletions
diff --git a/intern/cycles/device/device.cpp b/intern/cycles/device/device.cpp index c2d1512492c..317e62b2f69 100644 --- a/intern/cycles/device/device.cpp +++ b/intern/cycles/device/device.cpp @@ -36,8 +36,11 @@ CCL_NAMESPACE_BEGIN bool Device::need_types_update = true; bool Device::need_devices_update = true; thread_mutex Device::device_mutex; -vector<DeviceType> Device::types; -vector<DeviceInfo> Device::devices; +vector<DeviceInfo> Device::opencl_devices; +vector<DeviceInfo> Device::cuda_devices; +vector<DeviceInfo> Device::cpu_devices; +vector<DeviceInfo> Device::network_devices; +uint Device::devices_initialized_mask = 0; /* Device Requested Features */ @@ -279,70 +282,108 @@ string Device::string_from_type(DeviceType type) return ""; } -vector<DeviceType>& Device::available_types() +vector<DeviceType> Device::available_types() { - thread_scoped_lock lock(device_mutex); - if(need_types_update) { - types.clear(); - types.push_back(DEVICE_CPU); + vector<DeviceType> types; + types.push_back(DEVICE_CPU); #ifdef WITH_CUDA - if(device_cuda_init()) { - types.push_back(DEVICE_CUDA); - } + types.push_back(DEVICE_CUDA); #endif #ifdef WITH_OPENCL - if(device_opencl_init()) { - types.push_back(DEVICE_OPENCL); - } + types.push_back(DEVICE_OPENCL); #endif #ifdef WITH_NETWORK - types.push_back(DEVICE_NETWORK); + types.push_back(DEVICE_NETWORK); #endif - need_types_update = false; - } return types; } -vector<DeviceInfo>& Device::available_devices() +vector<DeviceInfo> Device::available_devices(uint mask) { + /* Lazy initialize devices. On some platforms OpenCL or CUDA drivers can + * be broken and cause crashes when only trying to get device info, so + * we don't want to do any initialization until the user chooses to. */ thread_scoped_lock lock(device_mutex); - if(need_devices_update) { - devices.clear(); + vector<DeviceInfo> devices; + #ifdef WITH_OPENCL - if(device_opencl_init()) { - device_opencl_info(devices); + if(mask & DEVICE_MASK_OPENCL) { + if(!(devices_initialized_mask & DEVICE_MASK_OPENCL)) { + if(device_opencl_init()) { + device_opencl_info(opencl_devices); + } + devices_initialized_mask |= DEVICE_MASK_OPENCL; } + foreach(DeviceInfo& info, opencl_devices) { + devices.push_back(info); + } + } #endif + #ifdef WITH_CUDA - if(device_cuda_init()) { - device_cuda_info(devices); + if(mask & DEVICE_MASK_CUDA) { + if(!(devices_initialized_mask & DEVICE_MASK_CUDA)) { + if(device_cuda_init()) { + device_cuda_info(cuda_devices); + } + devices_initialized_mask |= DEVICE_MASK_CUDA; } + foreach(DeviceInfo& info, cuda_devices) { + devices.push_back(info); + } + } #endif - device_cpu_info(devices); + + if(mask & DEVICE_MASK_CPU) { + if(!(devices_initialized_mask & DEVICE_MASK_CPU)) { + device_cpu_info(cpu_devices); + devices_initialized_mask |= DEVICE_MASK_CPU; + } + foreach(DeviceInfo& info, cpu_devices) { + devices.push_back(info); + } + } + #ifdef WITH_NETWORK - device_network_info(devices); -#endif - need_devices_update = false; + if(mask & DEVICE_MASK_NETWORK) { + if(!(devices_initialized_mask & DEVICE_MASK_NETWORK)) { + device_network_info(network_devices); + devices_initialized_mask |= DEVICE_MASK_NETWORK; + } + foreach(DeviceInfo& info, network_devices) { + devices.push_back(info); + } } +#endif + return devices; } -string Device::device_capabilities() +string Device::device_capabilities(uint mask) { - string capabilities = "CPU device capabilities: "; - capabilities += device_cpu_capabilities() + "\n"; + thread_scoped_lock lock(device_mutex); + string capabilities = ""; + + if(mask & DEVICE_MASK_CPU) { + capabilities += "\nCPU device capabilities: "; + capabilities += device_cpu_capabilities() + "\n"; + } #ifdef WITH_OPENCL - if(device_opencl_init()) { - capabilities += "\nOpenCL device capabilities:\n"; - capabilities += device_opencl_capabilities(); + if(mask & DEVICE_MASK_OPENCL) { + if(device_opencl_init()) { + capabilities += "\nOpenCL device capabilities:\n"; + capabilities += device_opencl_capabilities(); + } } #endif #ifdef WITH_CUDA - if(device_cuda_init()) { - capabilities += "\nCUDA device capabilities:\n"; - capabilities += device_cuda_capabilities(); + if(mask & DEVICE_MASK_CUDA) { + if(device_cuda_init()) { + capabilities += "\nCUDA device capabilities:\n"; + capabilities += device_cuda_capabilities(); + } } #endif @@ -351,7 +392,12 @@ string Device::device_capabilities() DeviceInfo Device::get_multi_device(const vector<DeviceInfo>& subdevices, int threads, bool background) { - assert(subdevices.size() > 1); + assert(subdevices.size() > 0); + + if(subdevices.size() == 1) { + /* No multi device needed. */ + return subdevices.front(); + } DeviceInfo info; info.type = DEVICE_MULTI; @@ -405,16 +451,16 @@ DeviceInfo Device::get_multi_device(const vector<DeviceInfo>& subdevices, int th void Device::tag_update() { - need_types_update = true; - need_devices_update = true; + free_memory(); } void Device::free_memory() { - need_types_update = true; - need_devices_update = true; - types.free_memory(); - devices.free_memory(); + devices_initialized_mask = 0; + cuda_devices.clear(); + opencl_devices.clear(); + cpu_devices.clear(); + network_devices.clear(); } CCL_NAMESPACE_END |