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
This commit is contained in:
@@ -363,13 +363,8 @@ static void options_parse(int argc, const char **argv)
|
|||||||
string devicename = "CPU";
|
string devicename = "CPU";
|
||||||
bool list = false;
|
bool list = false;
|
||||||
|
|
||||||
vector<DeviceType>& types = Device::available_types();
|
/* List devices for which support is compiled in. */
|
||||||
|
vector<DeviceType> types = Device::available_types();
|
||||||
/* TODO(sergey): Here's a feedback loop happens: on the one hand we want
|
|
||||||
* the device list to be printed in help message, on the other hand logging
|
|
||||||
* is not initialized yet so we wouldn't have debug log happening in the
|
|
||||||
* device initialization.
|
|
||||||
*/
|
|
||||||
foreach(DeviceType type, types) {
|
foreach(DeviceType type, types) {
|
||||||
if(device_names != "")
|
if(device_names != "")
|
||||||
device_names += ", ";
|
device_names += ", ";
|
||||||
@@ -421,7 +416,7 @@ static void options_parse(int argc, const char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(list) {
|
if(list) {
|
||||||
vector<DeviceInfo>& devices = Device::available_devices();
|
vector<DeviceInfo> devices = Device::available_devices();
|
||||||
printf("Devices:\n");
|
printf("Devices:\n");
|
||||||
|
|
||||||
foreach(DeviceInfo& info, devices) {
|
foreach(DeviceInfo& info, devices) {
|
||||||
@@ -456,15 +451,12 @@ static void options_parse(int argc, const char **argv)
|
|||||||
|
|
||||||
/* find matching device */
|
/* find matching device */
|
||||||
DeviceType device_type = Device::type_from_string(devicename.c_str());
|
DeviceType device_type = Device::type_from_string(devicename.c_str());
|
||||||
vector<DeviceInfo>& devices = Device::available_devices();
|
vector<DeviceInfo> devices = Device::available_devices(DEVICE_MASK(device_type));
|
||||||
bool device_available = false;
|
|
||||||
|
|
||||||
foreach(DeviceInfo& device, devices) {
|
bool device_available = false;
|
||||||
if(device_type == device.type) {
|
if (!devices.empty()) {
|
||||||
options.session_params.device = device;
|
options.session_params.device = devices.front();
|
||||||
device_available = true;
|
device_available = true;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* handle invalid configurations */
|
/* handle invalid configurations */
|
||||||
|
|||||||
@@ -1478,7 +1478,7 @@ class CyclesPreferences(bpy.types.AddonPreferences):
|
|||||||
def get_devices(self):
|
def get_devices(self):
|
||||||
import _cycles
|
import _cycles
|
||||||
# Layout of the device tuples: (Name, Type, Persistent ID)
|
# 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
|
# 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
|
# we know we don't add new devices. This way we guarantee to not
|
||||||
# hold pointers to a resized array.
|
# hold pointers to a resized array.
|
||||||
@@ -1502,7 +1502,7 @@ class CyclesPreferences(bpy.types.AddonPreferences):
|
|||||||
|
|
||||||
def get_num_gpu_devices(self):
|
def get_num_gpu_devices(self):
|
||||||
import _cycles
|
import _cycles
|
||||||
device_list = _cycles.available_devices()
|
device_list = _cycles.available_devices(self.compute_device_type)
|
||||||
num = 0
|
num = 0
|
||||||
for device in device_list:
|
for device in device_list:
|
||||||
if device[1] != self.compute_device_type:
|
if device[1] != self.compute_device_type:
|
||||||
@@ -1515,26 +1515,32 @@ class CyclesPreferences(bpy.types.AddonPreferences):
|
|||||||
def has_active_device(self):
|
def has_active_device(self):
|
||||||
return self.get_num_gpu_devices() > 0
|
return self.get_num_gpu_devices() > 0
|
||||||
|
|
||||||
def draw_impl(self, layout, context):
|
def _draw_devices(self, layout, device_type, devices):
|
||||||
available_device_types = self.get_device_types(context)
|
box = layout.box()
|
||||||
layout.label(text="Cycles Compute Device:")
|
|
||||||
if len(available_device_types) == 1:
|
found_device = False
|
||||||
layout.label(text="No compatible GPUs found", icon='INFO')
|
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
|
return
|
||||||
layout.row().prop(self, "compute_device_type", expand=True)
|
|
||||||
|
for device in 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)
|
||||||
|
|
||||||
cuda_devices, opencl_devices = self.get_devices()
|
cuda_devices, opencl_devices = self.get_devices()
|
||||||
row = layout.row()
|
row = layout.row()
|
||||||
|
if self.compute_device_type == 'CUDA':
|
||||||
if self.compute_device_type == 'CUDA' and cuda_devices:
|
self._draw_devices(row, 'CUDA', cuda_devices)
|
||||||
box = row.box()
|
elif self.compute_device_type == 'OPENCL':
|
||||||
for device in cuda_devices:
|
self._draw_devices(row, 'OPENCL', opencl_devices)
|
||||||
box.prop(device, "use", text=device.name)
|
|
||||||
|
|
||||||
if self.compute_device_type == 'OPENCL' and opencl_devices:
|
|
||||||
box = row.box()
|
|
||||||
for device in opencl_devices:
|
|
||||||
box.prop(device, "use", text=device.name)
|
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
self.draw_impl(self.layout, context)
|
self.draw_impl(self.layout, context)
|
||||||
|
|||||||
@@ -384,9 +384,18 @@ static PyObject *sync_func(PyObject * /*self*/, PyObject *value)
|
|||||||
Py_RETURN_NONE;
|
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());
|
PyObject *ret = PyTuple_New(devices.size());
|
||||||
|
|
||||||
for(size_t i = 0; i < devices.size(); i++) {
|
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*/)
|
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;
|
bool has_cuda = false, has_opencl = false;
|
||||||
for(int i = 0; i < devices.size(); i++) {
|
foreach(DeviceType device_type, device_types) {
|
||||||
has_cuda |= (devices[i].type == DEVICE_CUDA);
|
has_cuda |= (device_type == DEVICE_CUDA);
|
||||||
has_opencl |= (devices[i].type == DEVICE_OPENCL);
|
has_opencl |= (device_type == DEVICE_OPENCL);
|
||||||
}
|
}
|
||||||
PyObject *list = PyTuple_New(2);
|
PyObject *list = PyTuple_New(2);
|
||||||
PyTuple_SET_ITEM(list, 0, PyBool_FromLong(has_cuda));
|
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_update_node", osl_update_node_func, METH_VARARGS, ""},
|
||||||
{"osl_compile", osl_compile_func, METH_VARARGS, ""},
|
{"osl_compile", osl_compile_func, METH_VARARGS, ""},
|
||||||
#endif
|
#endif
|
||||||
{"available_devices", available_devices_func, METH_NOARGS, ""},
|
{"available_devices", available_devices_func, METH_VARARGS, ""},
|
||||||
{"system_info", system_info_func, METH_NOARGS, ""},
|
{"system_info", system_info_func, METH_NOARGS, ""},
|
||||||
#ifdef WITH_OPENCL
|
#ifdef WITH_OPENCL
|
||||||
{"opencl_disable", opencl_disable_func, METH_NOARGS, ""},
|
{"opencl_disable", opencl_disable_func, METH_NOARGS, ""},
|
||||||
|
|||||||
@@ -766,24 +766,18 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine& b_engine,
|
|||||||
/* Background */
|
/* Background */
|
||||||
params.background = background;
|
params.background = background;
|
||||||
|
|
||||||
/* device type */
|
/* Default to CPU device. */
|
||||||
vector<DeviceInfo>& devices = Device::available_devices();
|
params.device = Device::available_devices(DEVICE_MASK_CPU).front();
|
||||||
|
|
||||||
/* device default CPU */
|
|
||||||
foreach(DeviceInfo& device, devices) {
|
|
||||||
if(device.type == DEVICE_CPU) {
|
|
||||||
params.device = device;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(get_enum(cscene, "device") == 2) {
|
if(get_enum(cscene, "device") == 2) {
|
||||||
/* find network device */
|
/* Find network device. */
|
||||||
foreach(DeviceInfo& info, devices)
|
vector<DeviceInfo> devices = Device::available_devices(DEVICE_MASK_NETWORK);
|
||||||
if(info.type == DEVICE_NETWORK)
|
if(!devices.empty()) {
|
||||||
params.device = info;
|
params.device = devices.front();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if(get_enum(cscene, "device") == 1) {
|
else if(get_enum(cscene, "device") == 1) {
|
||||||
|
/* Find cycles preferences. */
|
||||||
PointerRNA b_preferences;
|
PointerRNA b_preferences;
|
||||||
|
|
||||||
BL::UserPreferences::addons_iterator b_addon_iter;
|
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 {
|
enum ComputeDevice {
|
||||||
COMPUTE_DEVICE_CPU = 0,
|
COMPUTE_DEVICE_CPU = 0,
|
||||||
COMPUTE_DEVICE_CUDA = 1,
|
COMPUTE_DEVICE_CUDA = 1,
|
||||||
@@ -807,15 +802,20 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine& b_engine,
|
|||||||
COMPUTE_DEVICE_CPU);
|
COMPUTE_DEVICE_CPU);
|
||||||
|
|
||||||
if(compute_device != 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;
|
vector<DeviceInfo> used_devices;
|
||||||
RNA_BEGIN(&b_preferences, device, "devices") {
|
RNA_BEGIN(&b_preferences, device, "devices") {
|
||||||
ComputeDevice device_type = (ComputeDevice)get_enum(device,
|
if(get_boolean(device, "use")) {
|
||||||
"type",
|
|
||||||
COMPUTE_DEVICE_NUM,
|
|
||||||
COMPUTE_DEVICE_CPU);
|
|
||||||
|
|
||||||
if(get_boolean(device, "use") &&
|
|
||||||
(device_type == compute_device || device_type == COMPUTE_DEVICE_CPU)) {
|
|
||||||
string id = get_string(device, "id");
|
string id = get_string(device, "id");
|
||||||
foreach(DeviceInfo& info, devices) {
|
foreach(DeviceInfo& info, devices) {
|
||||||
if(info.id == id) {
|
if(info.id == id) {
|
||||||
@@ -826,10 +826,7 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine& b_engine,
|
|||||||
}
|
}
|
||||||
} RNA_END;
|
} RNA_END;
|
||||||
|
|
||||||
if(used_devices.size() == 1) {
|
if(!used_devices.empty()) {
|
||||||
params.device = used_devices[0];
|
|
||||||
}
|
|
||||||
else if(used_devices.size() > 1) {
|
|
||||||
params.device = Device::get_multi_device(used_devices,
|
params.device = Device::get_multi_device(used_devices,
|
||||||
params.threads,
|
params.threads,
|
||||||
params.background);
|
params.background);
|
||||||
|
|||||||
@@ -36,8 +36,11 @@ CCL_NAMESPACE_BEGIN
|
|||||||
bool Device::need_types_update = true;
|
bool Device::need_types_update = true;
|
||||||
bool Device::need_devices_update = true;
|
bool Device::need_devices_update = true;
|
||||||
thread_mutex Device::device_mutex;
|
thread_mutex Device::device_mutex;
|
||||||
vector<DeviceType> Device::types;
|
vector<DeviceInfo> Device::opencl_devices;
|
||||||
vector<DeviceInfo> Device::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 */
|
/* Device Requested Features */
|
||||||
|
|
||||||
@@ -279,70 +282,108 @@ string Device::string_from_type(DeviceType type)
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<DeviceType>& Device::available_types()
|
vector<DeviceType> Device::available_types()
|
||||||
{
|
{
|
||||||
thread_scoped_lock lock(device_mutex);
|
vector<DeviceType> types;
|
||||||
if(need_types_update) {
|
types.push_back(DEVICE_CPU);
|
||||||
types.clear();
|
|
||||||
types.push_back(DEVICE_CPU);
|
|
||||||
#ifdef WITH_CUDA
|
#ifdef WITH_CUDA
|
||||||
if(device_cuda_init()) {
|
types.push_back(DEVICE_CUDA);
|
||||||
types.push_back(DEVICE_CUDA);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef WITH_OPENCL
|
#ifdef WITH_OPENCL
|
||||||
if(device_opencl_init()) {
|
types.push_back(DEVICE_OPENCL);
|
||||||
types.push_back(DEVICE_OPENCL);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef WITH_NETWORK
|
#ifdef WITH_NETWORK
|
||||||
types.push_back(DEVICE_NETWORK);
|
types.push_back(DEVICE_NETWORK);
|
||||||
#endif
|
#endif
|
||||||
need_types_update = false;
|
|
||||||
}
|
|
||||||
return types;
|
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);
|
thread_scoped_lock lock(device_mutex);
|
||||||
if(need_devices_update) {
|
vector<DeviceInfo> devices;
|
||||||
devices.clear();
|
|
||||||
#ifdef WITH_OPENCL
|
#ifdef WITH_OPENCL
|
||||||
if(device_opencl_init()) {
|
if(mask & DEVICE_MASK_OPENCL) {
|
||||||
device_opencl_info(devices);
|
if(!(devices_initialized_mask & DEVICE_MASK_OPENCL)) {
|
||||||
|
if(device_opencl_init()) {
|
||||||
|
device_opencl_info(opencl_devices);
|
||||||
|
}
|
||||||
|
devices_initialized_mask |= DEVICE_MASK_OPENCL;
|
||||||
}
|
}
|
||||||
#endif
|
foreach(DeviceInfo& info, opencl_devices) {
|
||||||
#ifdef WITH_CUDA
|
devices.push_back(info);
|
||||||
if(device_cuda_init()) {
|
|
||||||
device_cuda_info(devices);
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
device_cpu_info(devices);
|
|
||||||
#ifdef WITH_NETWORK
|
|
||||||
device_network_info(devices);
|
|
||||||
#endif
|
|
||||||
need_devices_update = false;
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WITH_CUDA
|
||||||
|
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
|
||||||
|
|
||||||
|
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
|
||||||
|
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;
|
return devices;
|
||||||
}
|
}
|
||||||
|
|
||||||
string Device::device_capabilities()
|
string Device::device_capabilities(uint mask)
|
||||||
{
|
{
|
||||||
string capabilities = "CPU device capabilities: ";
|
thread_scoped_lock lock(device_mutex);
|
||||||
capabilities += device_cpu_capabilities() + "\n";
|
string capabilities = "";
|
||||||
|
|
||||||
|
if(mask & DEVICE_MASK_CPU) {
|
||||||
|
capabilities += "\nCPU device capabilities: ";
|
||||||
|
capabilities += device_cpu_capabilities() + "\n";
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef WITH_OPENCL
|
#ifdef WITH_OPENCL
|
||||||
if(device_opencl_init()) {
|
if(mask & DEVICE_MASK_OPENCL) {
|
||||||
capabilities += "\nOpenCL device capabilities:\n";
|
if(device_opencl_init()) {
|
||||||
capabilities += device_opencl_capabilities();
|
capabilities += "\nOpenCL device capabilities:\n";
|
||||||
|
capabilities += device_opencl_capabilities();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WITH_CUDA
|
#ifdef WITH_CUDA
|
||||||
if(device_cuda_init()) {
|
if(mask & DEVICE_MASK_CUDA) {
|
||||||
capabilities += "\nCUDA device capabilities:\n";
|
if(device_cuda_init()) {
|
||||||
capabilities += device_cuda_capabilities();
|
capabilities += "\nCUDA device capabilities:\n";
|
||||||
|
capabilities += device_cuda_capabilities();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -351,7 +392,12 @@ string Device::device_capabilities()
|
|||||||
|
|
||||||
DeviceInfo Device::get_multi_device(const vector<DeviceInfo>& subdevices, int threads, bool background)
|
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;
|
DeviceInfo info;
|
||||||
info.type = DEVICE_MULTI;
|
info.type = DEVICE_MULTI;
|
||||||
@@ -405,16 +451,16 @@ DeviceInfo Device::get_multi_device(const vector<DeviceInfo>& subdevices, int th
|
|||||||
|
|
||||||
void Device::tag_update()
|
void Device::tag_update()
|
||||||
{
|
{
|
||||||
need_types_update = true;
|
free_memory();
|
||||||
need_devices_update = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Device::free_memory()
|
void Device::free_memory()
|
||||||
{
|
{
|
||||||
need_types_update = true;
|
devices_initialized_mask = 0;
|
||||||
need_devices_update = true;
|
cuda_devices.clear();
|
||||||
types.free_memory();
|
opencl_devices.clear();
|
||||||
devices.free_memory();
|
cpu_devices.clear();
|
||||||
|
network_devices.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
CCL_NAMESPACE_END
|
CCL_NAMESPACE_END
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ class RenderTile;
|
|||||||
/* Device Types */
|
/* Device Types */
|
||||||
|
|
||||||
enum DeviceType {
|
enum DeviceType {
|
||||||
DEVICE_NONE,
|
DEVICE_NONE = 0,
|
||||||
DEVICE_CPU,
|
DEVICE_CPU,
|
||||||
DEVICE_OPENCL,
|
DEVICE_OPENCL,
|
||||||
DEVICE_CUDA,
|
DEVICE_CUDA,
|
||||||
@@ -48,6 +48,16 @@ enum DeviceType {
|
|||||||
DEVICE_MULTI
|
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 {
|
class DeviceInfo {
|
||||||
public:
|
public:
|
||||||
DeviceType type;
|
DeviceType type;
|
||||||
@@ -328,9 +338,9 @@ public:
|
|||||||
|
|
||||||
static DeviceType type_from_string(const char *name);
|
static DeviceType type_from_string(const char *name);
|
||||||
static string string_from_type(DeviceType type);
|
static string string_from_type(DeviceType type);
|
||||||
static vector<DeviceType>& available_types();
|
static vector<DeviceType> available_types();
|
||||||
static vector<DeviceInfo>& available_devices();
|
static vector<DeviceInfo> available_devices(uint device_type_mask = DEVICE_MASK_ALL);
|
||||||
static string device_capabilities();
|
static string device_capabilities(uint device_type_mask = DEVICE_MASK_ALL);
|
||||||
static DeviceInfo get_multi_device(const vector<DeviceInfo>& subdevices,
|
static DeviceInfo get_multi_device(const vector<DeviceInfo>& subdevices,
|
||||||
int threads,
|
int threads,
|
||||||
bool background);
|
bool background);
|
||||||
@@ -357,8 +367,11 @@ private:
|
|||||||
/* Indicted whether device types and devices lists were initialized. */
|
/* Indicted whether device types and devices lists were initialized. */
|
||||||
static bool need_types_update, need_devices_update;
|
static bool need_types_update, need_devices_update;
|
||||||
static thread_mutex device_mutex;
|
static thread_mutex device_mutex;
|
||||||
static vector<DeviceType> types;
|
static vector<DeviceInfo> cuda_devices;
|
||||||
static vector<DeviceInfo> devices;
|
static vector<DeviceInfo> opencl_devices;
|
||||||
|
static vector<DeviceInfo> cpu_devices;
|
||||||
|
static vector<DeviceInfo> network_devices;
|
||||||
|
static uint devices_initialized_mask;
|
||||||
};
|
};
|
||||||
|
|
||||||
CCL_NAMESPACE_END
|
CCL_NAMESPACE_END
|
||||||
|
|||||||
Reference in New Issue
Block a user