From 001414fb2f7346d2ff332bf851373522d87659d7 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 29 Jan 2019 16:39:30 +0100 Subject: 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 --- intern/cycles/device/device.cpp | 132 +++++++++++++++++++++++++++------------- intern/cycles/device/device.h | 25 ++++++-- 2 files changed, 108 insertions(+), 49 deletions(-) (limited to 'intern/cycles/device') 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 Device::types; -vector Device::devices; +vector Device::opencl_devices; +vector Device::cuda_devices; +vector Device::cpu_devices; +vector 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& Device::available_types() +vector Device::available_types() { - thread_scoped_lock lock(device_mutex); - if(need_types_update) { - types.clear(); - types.push_back(DEVICE_CPU); + vector 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& Device::available_devices() +vector 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 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& 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& 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 diff --git a/intern/cycles/device/device.h b/intern/cycles/device/device.h index 55c39188210..082f9f758a8 100644 --- a/intern/cycles/device/device.h +++ b/intern/cycles/device/device.h @@ -40,7 +40,7 @@ class RenderTile; /* Device Types */ enum DeviceType { - DEVICE_NONE, + DEVICE_NONE = 0, DEVICE_CPU, DEVICE_OPENCL, DEVICE_CUDA, @@ -48,6 +48,16 @@ enum DeviceType { DEVICE_MULTI }; +enum DeviceTypeMask { + DEVICE_MASK_CPU = (1 << DEVICE_CPU), + DEVICE_MASK_OPENCL = (1 << DEVICE_OPENCL), + DEVICE_MASK_CUDA = (1 << DEVICE_CUDA), + DEVICE_MASK_NETWORK = (1 << DEVICE_NETWORK), + DEVICE_MASK_ALL = ~0 +}; + +#define DEVICE_MASK(type) (DeviceTypeMask)(1 << type) + class DeviceInfo { public: DeviceType type; @@ -328,9 +338,9 @@ public: static DeviceType type_from_string(const char *name); static string string_from_type(DeviceType type); - static vector& available_types(); - static vector& available_devices(); - static string device_capabilities(); + static vector available_types(); + static vector available_devices(uint device_type_mask = DEVICE_MASK_ALL); + static string device_capabilities(uint device_type_mask = DEVICE_MASK_ALL); static DeviceInfo get_multi_device(const vector& subdevices, int threads, bool background); @@ -357,8 +367,11 @@ private: /* Indicted whether device types and devices lists were initialized. */ static bool need_types_update, need_devices_update; static thread_mutex device_mutex; - static vector types; - static vector devices; + static vector cuda_devices; + static vector opencl_devices; + static vector cpu_devices; + static vector network_devices; + static uint devices_initialized_mask; }; CCL_NAMESPACE_END -- cgit v1.2.3