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/blender | |
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/blender')
-rw-r--r-- | intern/cycles/blender/addon/properties.py | 42 | ||||
-rw-r--r-- | intern/cycles/blender/blender_python.cpp | 23 | ||||
-rw-r--r-- | intern/cycles/blender/blender_sync.cpp | 47 |
3 files changed, 62 insertions, 50 deletions
diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index 9d00a3f75b8..23ab1cf6a30 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -1478,7 +1478,7 @@ class CyclesPreferences(bpy.types.AddonPreferences): def get_devices(self): import _cycles # Layout of the device tuples: (Name, Type, Persistent ID) - device_list = _cycles.available_devices() + device_list = _cycles.available_devices(self.compute_device_type) # Make sure device entries are up to date and not referenced before # we know we don't add new devices. This way we guarantee to not # hold pointers to a resized array. @@ -1502,7 +1502,7 @@ class CyclesPreferences(bpy.types.AddonPreferences): def get_num_gpu_devices(self): import _cycles - device_list = _cycles.available_devices() + device_list = _cycles.available_devices(self.compute_device_type) num = 0 for device in device_list: if device[1] != self.compute_device_type: @@ -1515,26 +1515,32 @@ class CyclesPreferences(bpy.types.AddonPreferences): def has_active_device(self): return self.get_num_gpu_devices() > 0 - def draw_impl(self, layout, context): - available_device_types = self.get_device_types(context) - layout.label(text="Cycles Compute Device:") - if len(available_device_types) == 1: - layout.label(text="No compatible GPUs found", icon='INFO') + def _draw_devices(self, layout, device_type, devices): + box = layout.box() + + found_device = False + for device in devices: + if device.type == device_type: + found_device = True + break + + if not found_device: + box.label(text="No compatible GPUs found", icon='INFO') return - layout.row().prop(self, "compute_device_type", expand=True) - cuda_devices, opencl_devices = self.get_devices() - row = layout.row() + for device in devices: + box.prop(device, "use", text=device.name) - if self.compute_device_type == 'CUDA' and cuda_devices: - box = row.box() - for device in cuda_devices: - box.prop(device, "use", text=device.name) + def draw_impl(self, layout, context): + row = layout.row() + row.prop(self, "compute_device_type", expand=True) - if self.compute_device_type == 'OPENCL' and opencl_devices: - box = row.box() - for device in opencl_devices: - box.prop(device, "use", text=device.name) + cuda_devices, opencl_devices = self.get_devices() + row = layout.row() + if self.compute_device_type == 'CUDA': + self._draw_devices(row, 'CUDA', cuda_devices) + elif self.compute_device_type == 'OPENCL': + self._draw_devices(row, 'OPENCL', opencl_devices) def draw(self, context): self.draw_impl(self.layout, context) diff --git a/intern/cycles/blender/blender_python.cpp b/intern/cycles/blender/blender_python.cpp index d9ff95b2578..9dd0cd4c0bc 100644 --- a/intern/cycles/blender/blender_python.cpp +++ b/intern/cycles/blender/blender_python.cpp @@ -384,9 +384,18 @@ static PyObject *sync_func(PyObject * /*self*/, PyObject *value) Py_RETURN_NONE; } -static PyObject *available_devices_func(PyObject * /*self*/, PyObject * /*args*/) +static PyObject *available_devices_func(PyObject * /*self*/, PyObject * args) { - vector<DeviceInfo>& devices = Device::available_devices(); + const char *type_name; + if(!PyArg_ParseTuple(args, "s", &type_name)) { + return NULL; + } + + DeviceType type = Device::type_from_string(type_name); + uint mask = (type == DEVICE_NONE) ? DEVICE_MASK_ALL : DEVICE_MASK(type); + mask |= DEVICE_MASK_CPU; + + vector<DeviceInfo> devices = Device::available_devices(mask); PyObject *ret = PyTuple_New(devices.size()); for(size_t i = 0; i < devices.size(); i++) { @@ -742,11 +751,11 @@ static PyObject *enable_print_stats_func(PyObject * /*self*/, PyObject * /*args* static PyObject *get_device_types_func(PyObject * /*self*/, PyObject * /*args*/) { - vector<DeviceInfo>& devices = Device::available_devices(); + vector<DeviceType> device_types = Device::available_types(); bool has_cuda = false, has_opencl = false; - for(int i = 0; i < devices.size(); i++) { - has_cuda |= (devices[i].type == DEVICE_CUDA); - has_opencl |= (devices[i].type == DEVICE_OPENCL); + foreach(DeviceType device_type, device_types) { + has_cuda |= (device_type == DEVICE_CUDA); + has_opencl |= (device_type == DEVICE_OPENCL); } PyObject *list = PyTuple_New(2); PyTuple_SET_ITEM(list, 0, PyBool_FromLong(has_cuda)); @@ -768,7 +777,7 @@ static PyMethodDef methods[] = { {"osl_update_node", osl_update_node_func, METH_VARARGS, ""}, {"osl_compile", osl_compile_func, METH_VARARGS, ""}, #endif - {"available_devices", available_devices_func, METH_NOARGS, ""}, + {"available_devices", available_devices_func, METH_VARARGS, ""}, {"system_info", system_info_func, METH_NOARGS, ""}, #ifdef WITH_OPENCL {"opencl_disable", opencl_disable_func, METH_NOARGS, ""}, diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index 2b73c41fb19..703fcc2078b 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -766,24 +766,18 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine& b_engine, /* Background */ params.background = background; - /* device type */ - vector<DeviceInfo>& devices = Device::available_devices(); - - /* device default CPU */ - foreach(DeviceInfo& device, devices) { - if(device.type == DEVICE_CPU) { - params.device = device; - break; - } - } + /* Default to CPU device. */ + params.device = Device::available_devices(DEVICE_MASK_CPU).front(); if(get_enum(cscene, "device") == 2) { - /* find network device */ - foreach(DeviceInfo& info, devices) - if(info.type == DEVICE_NETWORK) - params.device = info; + /* Find network device. */ + vector<DeviceInfo> devices = Device::available_devices(DEVICE_MASK_NETWORK); + if(!devices.empty()) { + params.device = devices.front(); + } } else if(get_enum(cscene, "device") == 1) { + /* Find cycles preferences. */ PointerRNA b_preferences; BL::UserPreferences::addons_iterator b_addon_iter; @@ -794,6 +788,7 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine& b_engine, } } + /* Test if we are using GPU devices. */ enum ComputeDevice { COMPUTE_DEVICE_CPU = 0, COMPUTE_DEVICE_CUDA = 1, @@ -807,15 +802,20 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine& b_engine, COMPUTE_DEVICE_CPU); if(compute_device != COMPUTE_DEVICE_CPU) { + /* Query GPU devices with matching types. */ + uint mask = DEVICE_MASK_CPU; + if(compute_device == COMPUTE_DEVICE_CUDA) { + mask |= DEVICE_MASK_CUDA; + } + else if(compute_device == COMPUTE_DEVICE_OPENCL) { + mask |= DEVICE_MASK_OPENCL; + } + vector<DeviceInfo> devices = Device::available_devices(mask); + + /* Match device preferences and available devices. */ vector<DeviceInfo> used_devices; RNA_BEGIN(&b_preferences, device, "devices") { - ComputeDevice device_type = (ComputeDevice)get_enum(device, - "type", - COMPUTE_DEVICE_NUM, - COMPUTE_DEVICE_CPU); - - if(get_boolean(device, "use") && - (device_type == compute_device || device_type == COMPUTE_DEVICE_CPU)) { + if(get_boolean(device, "use")) { string id = get_string(device, "id"); foreach(DeviceInfo& info, devices) { if(info.id == id) { @@ -826,10 +826,7 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine& b_engine, } } RNA_END; - if(used_devices.size() == 1) { - params.device = used_devices[0]; - } - else if(used_devices.size() > 1) { + if(!used_devices.empty()) { params.device = Device::get_multi_device(used_devices, params.threads, params.background); |