Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Stockner <lukas.stockner@freenet.de>2016-11-07 04:33:53 +0300
committerLukas Stockner <lukas.stockner@freenet.de>2016-11-07 05:19:29 +0300
commitdd921238d9223f550d3043313c9c38d07620de5d (patch)
tree762c114b9ccda879a2826be6c2205cb5a20665d3 /intern/cycles/device
parentf89fbf580eae6202cef9da08756fd415ca34a8f3 (diff)
Cycles: Refactor Device selection to allow individual GPU compute device selection
Previously, it was only possible to choose a single GPU or all of that type (CUDA or OpenCL). Now, a toggle button is displayed for every device. These settings are tied to the PCI Bus ID of the devices, so they're consistent across hardware addition and removal (but not when swapping/moving cards). From the code perspective, the more important change is that now, the compute device properties are stored in the Addon preferences of the Cycles addon, instead of directly in the User Preferences. This allows for a cleaner implementation, removing the Cycles C API functions that were called by the RNA code to specify the enum items. Note that this change is neither backwards- nor forwards-compatible, but since it's only a User Preference no existing files are broken. Reviewers: #cycles, brecht Reviewed By: #cycles, brecht Subscribers: brecht, juicyfruit, mib2berlin, Blendify Differential Revision: https://developer.blender.org/D2338
Diffstat (limited to 'intern/cycles/device')
-rw-r--r--intern/cycles/device/device.cpp54
-rw-r--r--intern/cycles/device/device.h9
-rw-r--r--intern/cycles/device/device_cuda.cpp7
-rw-r--r--intern/cycles/device/device_intern.h1
-rw-r--r--intern/cycles/device/device_multi.cpp115
-rw-r--r--intern/cycles/device/device_opencl.cpp7
-rw-r--r--intern/cycles/device/opencl/opencl.h9
-rw-r--r--intern/cycles/device/opencl/opencl_util.cpp25
8 files changed, 86 insertions, 141 deletions
diff --git a/intern/cycles/device/device.cpp b/intern/cycles/device/device.cpp
index 909ec7a6d60..ff9387b0a8a 100644
--- a/intern/cycles/device/device.cpp
+++ b/intern/cycles/device/device.cpp
@@ -258,33 +258,33 @@ Device *Device::create(DeviceInfo& info, Stats &stats, bool background)
DeviceType Device::type_from_string(const char *name)
{
- if(strcmp(name, "cpu") == 0)
+ if(strcmp(name, "CPU") == 0)
return DEVICE_CPU;
- else if(strcmp(name, "cuda") == 0)
+ else if(strcmp(name, "CUDA") == 0)
return DEVICE_CUDA;
- else if(strcmp(name, "opencl") == 0)
+ else if(strcmp(name, "OPENCL") == 0)
return DEVICE_OPENCL;
- else if(strcmp(name, "network") == 0)
+ else if(strcmp(name, "NETWORK") == 0)
return DEVICE_NETWORK;
- else if(strcmp(name, "multi") == 0)
+ else if(strcmp(name, "MULTI") == 0)
return DEVICE_MULTI;
-
+
return DEVICE_NONE;
}
string Device::string_from_type(DeviceType type)
{
if(type == DEVICE_CPU)
- return "cpu";
+ return "CPU";
else if(type == DEVICE_CUDA)
- return "cuda";
+ return "CUDA";
else if(type == DEVICE_OPENCL)
- return "opencl";
+ return "OPENCL";
else if(type == DEVICE_NETWORK)
- return "network";
+ return "NETWORK";
else if(type == DEVICE_MULTI)
- return "multi";
-
+ return "MULTI";
+
return "";
}
@@ -307,9 +307,6 @@ vector<DeviceType>& Device::available_types()
#ifdef WITH_NETWORK
types.push_back(DEVICE_NETWORK);
#endif
-#ifdef WITH_MULTI
- types.push_back(DEVICE_MULTI);
-#endif
need_types_update = false;
}
@@ -331,10 +328,6 @@ vector<DeviceInfo>& Device::available_devices()
device_opencl_info(devices);
#endif
-#ifdef WITH_MULTI
- device_multi_info(devices);
-#endif
-
device_cpu_info(devices);
#ifdef WITH_NETWORK
@@ -368,6 +361,29 @@ string Device::device_capabilities()
return capabilities;
}
+DeviceInfo Device::get_multi_device(vector<DeviceInfo> subdevices)
+{
+ assert(subdevices.size() > 1);
+
+ DeviceInfo info;
+ info.type = DEVICE_MULTI;
+ info.id = "MULTI";
+ info.description = "Multi Device";
+ info.multi_devices = subdevices;
+ info.num = 0;
+
+ info.has_bindless_textures = true;
+ info.pack_images = false;
+ foreach(DeviceInfo &device, subdevices) {
+ assert(device.type == info.multi_devices[0].type);
+
+ info.pack_images |= device.pack_images;
+ info.has_bindless_textures &= device.has_bindless_textures;
+ }
+
+ return info;
+}
+
void Device::tag_update()
{
need_types_update = true;
diff --git a/intern/cycles/device/device.h b/intern/cycles/device/device.h
index 77dc1fa9713..b9bdffa2618 100644
--- a/intern/cycles/device/device.h
+++ b/intern/cycles/device/device.h
@@ -49,7 +49,7 @@ class DeviceInfo {
public:
DeviceType type;
string description;
- string id;
+ string id; /* used for user preferences, should stay fixed with changing hardware config */
int num;
bool display_device;
bool advanced_shading;
@@ -69,6 +69,12 @@ public:
has_bindless_textures = false;
use_split_kernel = false;
}
+
+ bool operator==(const DeviceInfo &info) {
+ /* Multiple Devices with the same ID would be very bad. */
+ assert(id != info.id || (type == info.type && num == info.num && description == info.description));
+ return id == info.id;
+ }
};
class DeviceRequestedFeatures {
@@ -282,6 +288,7 @@ public:
static vector<DeviceType>& available_types();
static vector<DeviceInfo>& available_devices();
static string device_capabilities();
+ static DeviceInfo get_multi_device(vector<DeviceInfo> subdevices);
/* Tag devices lists for update. */
static void tag_update();
diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp
index 73c9221e6a2..a4818aa3b8d 100644
--- a/intern/cycles/device/device_cuda.cpp
+++ b/intern/cycles/device/device_cuda.cpp
@@ -1408,13 +1408,18 @@ void device_cuda_info(vector<DeviceInfo>& devices)
info.type = DEVICE_CUDA;
info.description = string(name);
- info.id = string_printf("CUDA_%d", num);
info.num = num;
info.advanced_shading = (major >= 2);
info.has_bindless_textures = (major >= 3);
info.pack_images = false;
+ int pci_location[3] = {0, 0, 0};
+ cuDeviceGetAttribute(&pci_location[0], CU_DEVICE_ATTRIBUTE_PCI_DOMAIN_ID, num);
+ cuDeviceGetAttribute(&pci_location[1], CU_DEVICE_ATTRIBUTE_PCI_BUS_ID, num);
+ cuDeviceGetAttribute(&pci_location[2], CU_DEVICE_ATTRIBUTE_PCI_DEVICE_ID, num);
+ info.id = string_printf("CUDA_%s_%04x:%02x:%02x", name, pci_location[0], pci_location[1], pci_location[2]);
+
/* if device has a kernel timeout, assume it is used for display */
if(cuDeviceGetAttribute(&attr, CU_DEVICE_ATTRIBUTE_KERNEL_EXEC_TIMEOUT, num) == CUDA_SUCCESS && attr == 1) {
info.description += " (Display)";
diff --git a/intern/cycles/device/device_intern.h b/intern/cycles/device/device_intern.h
index 47584ae6d22..de487649045 100644
--- a/intern/cycles/device/device_intern.h
+++ b/intern/cycles/device/device_intern.h
@@ -33,7 +33,6 @@ void device_cpu_info(vector<DeviceInfo>& devices);
void device_opencl_info(vector<DeviceInfo>& devices);
void device_cuda_info(vector<DeviceInfo>& devices);
void device_network_info(vector<DeviceInfo>& devices);
-void device_multi_info(vector<DeviceInfo>& devices);
string device_cpu_capabilities(void);
string device_opencl_capabilities(void);
diff --git a/intern/cycles/device/device_multi.cpp b/intern/cycles/device/device_multi.cpp
index ef257358b22..48fd159d508 100644
--- a/intern/cycles/device/device_multi.cpp
+++ b/intern/cycles/device/device_multi.cpp
@@ -350,120 +350,5 @@ Device *device_multi_create(DeviceInfo& info, Stats &stats, bool background)
return new MultiDevice(info, stats, background);
}
-static bool device_multi_add(vector<DeviceInfo>& devices, DeviceType type, bool with_display, bool with_advanced_shading, const char *id_fmt, int num)
-{
- DeviceInfo info;
-
- /* create map to find duplicate descriptions */
- map<string, int> dupli_map;
- map<string, int>::iterator dt;
- int num_added = 0, num_display = 0;
-
- info.advanced_shading = with_advanced_shading;
- info.pack_images = false;
- info.has_bindless_textures = true;
-
- foreach(DeviceInfo& subinfo, devices) {
- if(subinfo.type == type) {
- if(subinfo.advanced_shading != info.advanced_shading)
- continue;
- if(subinfo.display_device) {
- if(with_display)
- num_display++;
- else
- continue;
- }
-
- string key = subinfo.description;
-
- if(dupli_map.find(key) == dupli_map.end())
- dupli_map[key] = 1;
- else
- dupli_map[key]++;
-
- info.multi_devices.push_back(subinfo);
- if(subinfo.display_device)
- info.display_device = true;
- info.pack_images = info.pack_images || subinfo.pack_images;
- info.has_bindless_textures = info.has_bindless_textures && subinfo.has_bindless_textures;
- num_added++;
- }
- }
-
- if(num_added <= 1 || (with_display && num_display == 0))
- return false;
-
- /* generate string */
- stringstream desc;
- vector<string> last_tokens;
- bool first = true;
-
- for(dt = dupli_map.begin(); dt != dupli_map.end(); dt++) {
- if(!first) desc << " + ";
- first = false;
-
- /* get name and count */
- string name = dt->first;
- int count = dt->second;
-
- /* strip common prefixes */
- vector<string> tokens;
- string_split(tokens, dt->first);
-
- if(tokens.size() > 1) {
- int i;
-
- for(i = 0; i < tokens.size() && i < last_tokens.size(); i++)
- if(tokens[i] != last_tokens[i])
- break;
-
- name = "";
- for(; i < tokens.size(); i++) {
- name += tokens[i];
- if(i != tokens.size() - 1)
- name += " ";
- }
- }
-
- last_tokens = tokens;
-
- /* add */
- if(count > 1)
- desc << name << " (" << count << "x)";
- else
- desc << name;
- }
-
- /* add info */
- info.type = DEVICE_MULTI;
- info.description = desc.str();
- info.id = string_printf(id_fmt, num);
- info.display_device = with_display;
- info.num = 0;
-
- if(with_display)
- devices.push_back(info);
- else
- devices.insert(devices.begin(), info);
-
- return true;
-}
-
-void device_multi_info(vector<DeviceInfo>& devices)
-{
- int num = 0;
-
- if(!device_multi_add(devices, DEVICE_CUDA, false, true, "CUDA_MULTI_%d", num++))
- device_multi_add(devices, DEVICE_CUDA, false, false, "CUDA_MULTI_%d", num++);
- if(!device_multi_add(devices, DEVICE_CUDA, true, true, "CUDA_MULTI_%d", num++))
- device_multi_add(devices, DEVICE_CUDA, true, false, "CUDA_MULTI_%d", num++);
-
- num = 0;
- if(!device_multi_add(devices, DEVICE_OPENCL, false, true, "OPENCL_MULTI_%d", num++))
- device_multi_add(devices, DEVICE_OPENCL, false, false, "OPENCL_MULTI_%d", num++);
- if(!device_multi_add(devices, DEVICE_OPENCL, true, true, "OPENCL_MULTI_%d", num++))
- device_multi_add(devices, DEVICE_OPENCL, true, false, "OPENCL_MULTI_%d", num++);
-}
-
CCL_NAMESPACE_END
diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp
index 45cf6b074e9..ba94c592a5f 100644
--- a/intern/cycles/device/device_opencl.cpp
+++ b/intern/cycles/device/device_opencl.cpp
@@ -83,17 +83,22 @@ void device_opencl_info(vector<DeviceInfo>& devices)
const string& platform_name = platform_device.platform_name;
const cl_device_type device_type = platform_device.device_type;
const string& device_name = platform_device.device_name;
+ string hardware_id = platform_device.hardware_id;
+ if(hardware_id == "") {
+ hardware_id = string_printf("ID_%d", num_devices);
+ }
+
DeviceInfo info;
info.type = DEVICE_OPENCL;
info.description = string_remove_trademark(string(device_name));
info.num = num_devices;
- info.id = string_printf("OPENCL_%d", info.num);
/* We don't know if it's used for display, but assume it is. */
info.display_device = true;
info.advanced_shading = OpenCLInfo::kernel_use_advanced_shading(platform_name);
info.pack_images = true;
info.use_split_kernel = OpenCLInfo::kernel_use_split(platform_name,
device_type);
+ info.id = string("OPENCL_") + platform_name + "_" + device_name + "_" + hardware_id;
devices.push_back(info);
num_devices++;
}
diff --git a/intern/cycles/device/opencl/opencl.h b/intern/cycles/device/opencl/opencl.h
index 30a35acbb2a..054ac9014f0 100644
--- a/intern/cycles/device/opencl/opencl.h
+++ b/intern/cycles/device/opencl/opencl.h
@@ -55,17 +55,20 @@ struct OpenCLPlatformDevice {
const string& platform_name,
cl_device_id device_id,
cl_device_type device_type,
- const string& device_name)
+ const string& device_name,
+ const string& hardware_id)
: platform_id(platform_id),
platform_name(platform_name),
device_id(device_id),
device_type(device_type),
- device_name(device_name) {}
+ device_name(device_name),
+ hardware_id(hardware_id) {}
cl_platform_id platform_id;
string platform_name;
cl_device_id device_id;
cl_device_type device_type;
string device_name;
+ string hardware_id;
};
/* Contains all static OpenCL helper functions. */
@@ -83,6 +86,8 @@ public:
string *error = NULL);
static bool device_version_check(cl_device_id device,
string *error = NULL);
+ static string get_hardware_id(string platform_name,
+ cl_device_id device_id);
static void get_usable_devices(vector<OpenCLPlatformDevice> *usable_devices,
bool force_all = false);
};
diff --git a/intern/cycles/device/opencl/opencl_util.cpp b/intern/cycles/device/opencl/opencl_util.cpp
index e425ae8e2e8..36eb70b8c85 100644
--- a/intern/cycles/device/opencl/opencl_util.cpp
+++ b/intern/cycles/device/opencl/opencl_util.cpp
@@ -661,6 +661,27 @@ bool OpenCLInfo::device_version_check(cl_device_id device,
return true;
}
+string OpenCLInfo::get_hardware_id(string platform_name, cl_device_id device_id)
+{
+ if(platform_name == "AMD Accelerated Parallel Processing" || platform_name == "Apple") {
+ /* Use cl_amd_device_topology extension. */
+ cl_char topology[24];
+ if(clGetDeviceInfo(device_id, 0x4037, sizeof(topology), topology, NULL) == CL_SUCCESS && topology[0] == 1) {
+ return string_printf("%02x:%02x.%01x", topology[21], topology[22], topology[23]);
+ }
+ }
+ else if(platform_name == "NVIDIA CUDA") {
+ /* Use two undocumented options of the cl_nv_device_attribute_query extension. */
+ cl_int bus_id, slot_id;
+ if(clGetDeviceInfo(device_id, 0x4008, sizeof(cl_int), &bus_id, NULL) == CL_SUCCESS &&
+ clGetDeviceInfo(device_id, 0x4009, sizeof(cl_int), &slot_id, NULL) == CL_SUCCESS) {
+ return string_printf("%02x:%02x.%01x", bus_id, slot_id>>3, slot_id & 0x7);
+ }
+ }
+ /* No general way to get a hardware ID from OpenCL => give up. */
+ return "";
+}
+
void OpenCLInfo::get_usable_devices(vector<OpenCLPlatformDevice> *usable_devices,
bool force_all)
{
@@ -773,11 +794,13 @@ void OpenCLInfo::get_usable_devices(vector<OpenCLPlatformDevice> *usable_devices
continue;
}
FIRST_VLOG(2) << "Adding new device " << device_name << ".";
+ string hardware_id = get_hardware_id(platform_name, device_id);
usable_devices->push_back(OpenCLPlatformDevice(platform_id,
platform_name,
device_id,
device_type,
- device_name));
+ device_name,
+ hardware_id));
}
else {
FIRST_VLOG(2) << "Ignoring device " << device_name