[Bf-blender-cvs] [dc9eb8234fe] master: Cycles: combined CPU + GPU rendering support.

Brecht Van Lommel noreply at git.blender.org
Sat Oct 21 20:15:44 CEST 2017


Commit: dc9eb8234fe4c9c561a3bfb9a8e3a3cefe77d5e3
Author: Brecht Van Lommel
Date:   Sat Oct 21 18:58:59 2017 +0200
Branches: master
https://developer.blender.org/rBdc9eb8234fe4c9c561a3bfb9a8e3a3cefe77d5e3

Cycles: combined CPU + GPU rendering support.

CPU rendering will be restricted to a BVH2, which is not ideal for raytracing
performance but can be shared with the GPU. Decoupled volume shading will be
disabled to match GPU volume sampling.

The number of CPU rendering threads is reduced to leave one core dedicated to
each GPU. Viewport rendering will also only use GPU rendering still. So along
with the BVH2 usage, perfect scaling should not be expected.

Go to User Preferences > System to enable the CPU to render alongside the GPU.

Differential Revision: https://developer.blender.org/D2873

===================================================================

M	intern/cycles/blender/addon/properties.py
M	intern/cycles/blender/blender_sync.cpp
M	intern/cycles/device/device.cpp
M	intern/cycles/device/device.h
M	intern/cycles/device/device_cpu.cpp
M	intern/cycles/device/opencl/opencl_util.cpp

===================================================================

diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py
index 7b16ef1d543..2e149527066 100644
--- a/intern/cycles/blender/addon/properties.py
+++ b/intern/cycles/blender/addon/properties.py
@@ -1351,8 +1351,9 @@ class CyclesPreferences(bpy.types.AddonPreferences):
 
         cuda_devices = []
         opencl_devices = []
+        cpu_devices = []
         for device in device_list:
-            if not device[1] in {'CUDA', 'OPENCL'}:
+            if not device[1] in {'CUDA', 'OPENCL', 'CPU'}:
                 continue
 
             entry = None
@@ -1361,18 +1362,28 @@ class CyclesPreferences(bpy.types.AddonPreferences):
                 if dev.id == device[2] and dev.type == device[1]:
                     entry = dev
                     break
-            # Create new entry if no existing one was found
             if not entry:
+                # Create new entry if no existing one was found
                 entry = self.devices.add()
                 entry.id   = device[2]
                 entry.name = device[0]
                 entry.type = device[1]
+                entry.use  = entry.type != 'CPU'
+            elif entry.name != device[0]:
+                # Update name in case it changed
+                entry.name = device[0]
 
             # Sort entries into lists
             if entry.type == 'CUDA':
                 cuda_devices.append(entry)
             elif entry.type == 'OPENCL':
                 opencl_devices.append(entry)
+            else:
+                cpu_devices.append(entry)
+
+        cuda_devices.extend(cpu_devices)
+        opencl_devices.extend(cpu_devices)
+
         return cuda_devices, opencl_devices
 
 
diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp
index 2e3301c4209..5eddf189468 100644
--- a/intern/cycles/blender/blender_sync.cpp
+++ b/intern/cycles/blender/blender_sync.cpp
@@ -675,6 +675,15 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine& b_engine,
 	/* feature set */
 	params.experimental = (get_enum(cscene, "feature_set") != 0);
 
+	/* threads */
+	if(b_scene.render().threads_mode() == BL::RenderSettings::threads_mode_FIXED)
+		params.threads = b_scene.render().threads();
+	else
+		params.threads = 0;
+
+	/* Background */
+	params.background = background;
+
 	/* device type */
 	vector<DeviceInfo>& devices = Device::available_devices();
 	
@@ -703,12 +712,28 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine& b_engine,
 			}
 		}
 
-		int compute_device = get_enum(b_preferences, "compute_device_type");
+		enum ComputeDevice {
+			COMPUTE_DEVICE_CPU = 0,
+			COMPUTE_DEVICE_CUDA = 1,
+			COMPUTE_DEVICE_OPENCL = 2,
+			COMPUTE_DEVICE_NUM = 3,
+		};
 
-		if(compute_device != 0) {
+		ComputeDevice compute_device = (ComputeDevice)get_enum(b_preferences,
+		                                                       "compute_device_type",
+		                                                       COMPUTE_DEVICE_NUM,
+		                                                       COMPUTE_DEVICE_CPU);
+
+		if(compute_device != COMPUTE_DEVICE_CPU) {
 			vector<DeviceInfo> used_devices;
 			RNA_BEGIN(&b_preferences, device, "devices") {
-				if(get_enum(device, "type") == compute_device && get_boolean(device, "use")) {
+				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)) {
 					string id = get_string(device, "id");
 					foreach(DeviceInfo& info, devices) {
 						if(info.id == id) {
@@ -723,15 +748,14 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine& b_engine,
 				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.background);
 			}
 			/* Else keep using the CPU device that was set before. */
 		}
 	}
 
-	/* Background */
-	params.background = background;
-
 	/* samples */
 	int samples = get_int(cscene, "samples");
 	int aa_samples = get_int(cscene, "aa_samples");
@@ -791,15 +815,10 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine& b_engine,
 		params.tile_order = TILE_BOTTOM_TO_TOP;
 	}
 
+	/* other parameters */
 	params.start_resolution = get_int(cscene, "preview_start_resolution");
 	params.pixel_size = b_engine.get_preview_pixel_size(b_scene);
 
-	/* other parameters */
-	if(b_scene.render().threads_mode() == BL::RenderSettings::threads_mode_FIXED)
-		params.threads = b_scene.render().threads();
-	else
-		params.threads = 0;
-
 	params.cancel_timeout = (double)get_float(cscene, "debug_cancel_timeout");
 	params.reset_timeout = (double)get_float(cscene, "debug_reset_timeout");
 	params.text_timeout = (double)get_float(cscene, "debug_text_timeout");
diff --git a/intern/cycles/device/device.cpp b/intern/cycles/device/device.cpp
index 7b0875965f8..f31cacd8ec1 100644
--- a/intern/cycles/device/device.cpp
+++ b/intern/cycles/device/device.cpp
@@ -23,9 +23,11 @@
 #include "util/util_debug.h"
 #include "util/util_foreach.h"
 #include "util/util_half.h"
+#include "util/util_logging.h"
 #include "util/util_math.h"
 #include "util/util_opengl.h"
 #include "util/util_time.h"
+#include "util/util_system.h"
 #include "util/util_types.h"
 #include "util/util_vector.h"
 #include "util/util_string.h"
@@ -365,7 +367,7 @@ string Device::device_capabilities()
 	return capabilities;
 }
 
-DeviceInfo Device::get_multi_device(vector<DeviceInfo> subdevices)
+DeviceInfo Device::get_multi_device(const vector<DeviceInfo>& subdevices, int threads, bool background)
 {
 	assert(subdevices.size() > 1);
 
@@ -373,18 +375,38 @@ DeviceInfo Device::get_multi_device(vector<DeviceInfo> subdevices)
 	info.type = DEVICE_MULTI;
 	info.id = "MULTI";
 	info.description = "Multi Device";
-	info.multi_devices = subdevices;
 	info.num = 0;
 
 	info.has_bindless_textures = true;
 	info.has_volume_decoupled = true;
 	info.has_qbvh = true;
-	foreach(DeviceInfo &device, subdevices) {
-		assert(device.type == info.multi_devices[0].type);
-
+	foreach(const DeviceInfo &device, subdevices) {
 		info.has_bindless_textures &= device.has_bindless_textures;
 		info.has_volume_decoupled &= device.has_volume_decoupled;
 		info.has_qbvh &= device.has_qbvh;
+
+		if(device.type == DEVICE_CPU && subdevices.size() > 1) {
+			if(background) {
+				int orig_cpu_threads = (threads)? threads: system_cpu_thread_count();
+				int cpu_threads = max(orig_cpu_threads - (subdevices.size() - 1), 0);
+
+				if(cpu_threads >= 1) {
+					DeviceInfo cpu_device = device;
+					cpu_device.cpu_threads = cpu_threads;
+					info.multi_devices.push_back(cpu_device);
+				}
+
+				VLOG(1) << "CPU render threads reduced from "
+						<< orig_cpu_threads << " to " << cpu_threads
+						<< ", to dedicate to GPU.";
+			}
+			else {
+				VLOG(1) << "CPU render threads disabled for interactive render.";
+			}
+		}
+		else {
+			info.multi_devices.push_back(device);
+		}
 	}
 
 	return info;
diff --git a/intern/cycles/device/device.h b/intern/cycles/device/device.h
index 5cd9cf46769..f400eeb3e6b 100644
--- a/intern/cycles/device/device.h
+++ b/intern/cycles/device/device.h
@@ -58,6 +58,7 @@ public:
 	bool has_volume_decoupled;
 	bool has_qbvh;
 	bool use_split_kernel; /* Denotes if the device is going to run cycles using split-kernel */
+	int cpu_threads;
 	vector<DeviceInfo> multi_devices;
 
 	DeviceInfo()
@@ -65,6 +66,7 @@ public:
 		type = DEVICE_CPU;
 		id = "CPU";
 		num = 0;
+		cpu_threads = 0;
 		display_device = false;
 		advanced_shading = true;
 		has_bindless_textures = false;
@@ -345,7 +347,9 @@ public:
 	static vector<DeviceType>& available_types();
 	static vector<DeviceInfo>& available_devices();
 	static string device_capabilities();
-	static DeviceInfo get_multi_device(vector<DeviceInfo> subdevices);
+	static DeviceInfo get_multi_device(const vector<DeviceInfo>& subdevices,
+	                                   int threads,
+	                                   bool background);
 
 	/* Tag devices lists for update. */
 	static void tag_update();
diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp
index a17caabc850..af1bbc0db18 100644
--- a/intern/cycles/device/device_cpu.cpp
+++ b/intern/cycles/device/device_cpu.cpp
@@ -207,8 +207,8 @@ public:
 	      KERNEL_NAME_EVAL(cpu_avx, name), \
 	      KERNEL_NAME_EVAL(cpu_avx2, name)
 
-	CPUDevice(DeviceInfo& info, Stats &stats, bool background)
-	: Device(info, stats, background),
+	CPUDevice(DeviceInfo& info_, Stats &stats_, bool background_)
+	: Device(info_, stats_, background_),
 #define REGISTER_KERNEL(name) name ## _kernel(KERNEL_FUNCTIONS(name))
 	  REGISTER_KERNEL(path_trace),
 	  REGISTER_KERNEL(convert_to_half_float),
@@ -229,6 +229,9 @@ public:
 	  REGISTER_KERNEL(data_init)
 #undef REGISTER_KERNEL
 	{
+		if(info.cpu_threads == 0) {
+			info.cpu_threads = TaskScheduler::num_threads();
+		}
 
 #ifdef WITH_OSL
 		kernel_globals.osl = &osl_globals;
@@ -237,7 +240,6 @@ public:
 		if(use_split_kernel) {
 			VLOG(1) << "Will be using split kernel.";
 		}
-
 		need_texture_info = false;
 
 #define REGISTER_SPLIT_KERNEL(name) split_kernels[#name] = KernelFunctions<void(*)(KernelGlobals*, KernelData*)>(KERNEL_FUNCTIONS(name))
@@ -271,7 +273,7 @@ public:
 
 	virtual bool show_samples() const
 	{
-		return (TaskScheduler::num_threads() == 1);
+		return (info.cpu_threads == 1);
 	}
 
 	void load_texture_info()
@@ -826,9 +828,9 @@ public:
 	int get_split_task_count(DeviceTask& task)
 	{
 		if(task.type == DeviceTask::SHADER)
-			return task.get_subtask_count(TaskScheduler::num_threads(), 256);
+			return task.get_subtask_count(info.cpu_threads, 256);
 		else
-			return task.get_subtask_count(TaskScheduler::num_threads());
+			return task.get_subtask_count(info.cpu

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list