[Bf-blender-cvs] [cfa101c2287] master: Cycles: Add command line option for overriding the compute device

Lukas Stockner noreply at git.blender.org
Fri Oct 2 19:32:16 CEST 2020


Commit: cfa101c22871c3d115f854e23f8b656b1c58a304
Author: Lukas Stockner
Date:   Fri Oct 2 00:48:01 2020 +0200
Branches: master
https://developer.blender.org/rBcfa101c22871c3d115f854e23f8b656b1c58a304

Cycles: Add command line option for overriding the compute device

The current way of setting the compute device makes sense for local
use, but for headless rendering it it a massive pain to get Cycles
to use the correct device, usually involving entire Python scripts.

Therefore, this patch adds a simple command-line option to Blender
for specifying the type of device that should be used. If the option
is present, the settings in the user preferences and the scene are
ignored, and instead all devices matching the specified type are used.

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

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

M	intern/cycles/blender/addon/engine.py
M	intern/cycles/blender/blender_device.cpp
M	intern/cycles/blender/blender_python.cpp
M	intern/cycles/blender/blender_session.cpp
M	intern/cycles/blender/blender_session.h
M	intern/cycles/util/util_string.cpp
M	intern/cycles/util/util_string.h

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

diff --git a/intern/cycles/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py
index 54221d3f1e0..807dcaf7f43 100644
--- a/intern/cycles/blender/addon/engine.py
+++ b/intern/cycles/blender/addon/engine.py
@@ -70,6 +70,11 @@ def _configure_argument_parser():
     parser.add_argument("--cycles-print-stats",
                         help="Print rendering statistics to stderr",
                         action='store_true')
+    parser.add_argument("--cycles-device",
+                        help="Set the device to use for Cycles, overriding user preferences and the scene setting."
+                             "Valid options are 'CPU', 'CUDA', 'OPTIX' or 'OPENCL'."
+                             "Additionally, you can append '+CPU' to any GPU type for hybrid rendering.",
+                        default=None)
     return parser
 
 
@@ -102,6 +107,10 @@ def _parse_command_line():
         import _cycles
         _cycles.enable_print_stats()
 
+    if args.cycles_device:
+        import _cycles
+        _cycles.set_device_override(args.cycles_device)
+
 
 def init():
     import bpy
diff --git a/intern/cycles/blender/blender_device.cpp b/intern/cycles/blender/blender_device.cpp
index fb9ab9e8c97..0293223864d 100644
--- a/intern/cycles/blender/blender_device.cpp
+++ b/intern/cycles/blender/blender_device.cpp
@@ -15,6 +15,7 @@
  */
 
 #include "blender/blender_device.h"
+#include "blender/blender_session.h"
 #include "blender/blender_util.h"
 
 #include "util/util_foreach.h"
@@ -42,6 +43,18 @@ int blender_device_threads(BL::Scene &b_scene)
 
 DeviceInfo blender_device_info(BL::Preferences &b_preferences, BL::Scene &b_scene, bool background)
 {
+  if (BlenderSession::device_override != DEVICE_MASK_ALL) {
+    vector<DeviceInfo> devices = Device::available_devices(BlenderSession::device_override);
+
+    if (devices.empty()) {
+      printf("Found no Cycles device of the specified type, falling back to CPU...\n");
+      return Device::available_devices(DEVICE_MASK_CPU).front();
+    }
+
+    int threads = blender_device_threads(b_scene);
+    return Device::get_multi_device(devices, threads, background);
+  }
+
   PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
 
   /* Default to CPU device. */
diff --git a/intern/cycles/blender/blender_python.cpp b/intern/cycles/blender/blender_python.cpp
index 25c77b74ce3..65337d1ba4f 100644
--- a/intern/cycles/blender/blender_python.cpp
+++ b/intern/cycles/blender/blender_python.cpp
@@ -968,6 +968,44 @@ static PyObject *get_device_types_func(PyObject * /*self*/, PyObject * /*args*/)
   return list;
 }
 
+static PyObject *set_device_override_func(PyObject * /*self*/, PyObject *arg)
+{
+  PyObject *override_string = PyObject_Str(arg);
+  string override = PyUnicode_AsUTF8(override_string);
+  Py_DECREF(override_string);
+
+  bool include_cpu = false;
+  const string cpu_suffix = "+CPU";
+  if (string_endswith(override, cpu_suffix)) {
+    include_cpu = true;
+    override = override.substr(0, override.length() - cpu_suffix.length());
+  }
+
+  if (override == "CPU") {
+    BlenderSession::device_override = DEVICE_MASK_CPU;
+  }
+  else if (override == "OPENCL") {
+    BlenderSession::device_override = DEVICE_MASK_OPENCL;
+  }
+  else if (override == "CUDA") {
+    BlenderSession::device_override = DEVICE_MASK_CUDA;
+  }
+  else if (override == "OPTIX") {
+    BlenderSession::device_override = DEVICE_MASK_OPTIX;
+  }
+  else {
+    printf("\nError: %s is not a valid Cycles device.\n", override.c_str());
+    Py_RETURN_FALSE;
+  }
+
+  if (include_cpu) {
+    BlenderSession::device_override = (DeviceTypeMask)(BlenderSession::device_override |
+                                                       DEVICE_MASK_CPU);
+  }
+
+  Py_RETURN_TRUE;
+}
+
 static PyMethodDef methods[] = {
     {"init", init_func, METH_VARARGS, ""},
     {"exit", exit_func, METH_VARARGS, ""},
@@ -1007,6 +1045,7 @@ static PyMethodDef methods[] = {
 
     /* Compute Device selection */
     {"get_device_types", get_device_types_func, METH_VARARGS, ""},
+    {"set_device_override", set_device_override_func, METH_O, ""},
 
     {NULL, NULL, 0, NULL},
 };
diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp
index 8e962f17f56..c2bdec0e53d 100644
--- a/intern/cycles/blender/blender_session.cpp
+++ b/intern/cycles/blender/blender_session.cpp
@@ -47,6 +47,7 @@
 
 CCL_NAMESPACE_BEGIN
 
+DeviceTypeMask BlenderSession::device_override = DEVICE_MASK_ALL;
 bool BlenderSession::headless = false;
 int BlenderSession::num_resumable_chunks = 0;
 int BlenderSession::current_resumable_chunk = 0;
diff --git a/intern/cycles/blender/blender_session.h b/intern/cycles/blender/blender_session.h
index 34e952e312b..68db8a2fb58 100644
--- a/intern/cycles/blender/blender_session.h
+++ b/intern/cycles/blender/blender_session.h
@@ -126,6 +126,7 @@ class BlenderSession {
   /* Global state which is common for all render sessions created from Blender.
    * Usually denotes command line arguments.
    */
+  static DeviceTypeMask device_override;
 
   /* Blender is running from the command line, no windows are shown and some
    * extra render optimization is possible (possible to free draw-only data and
diff --git a/intern/cycles/util/util_string.cpp b/intern/cycles/util/util_string.cpp
index afcca7e0411..4dfebf14923 100644
--- a/intern/cycles/util/util_string.cpp
+++ b/intern/cycles/util/util_string.cpp
@@ -117,14 +117,14 @@ bool string_startswith(const string &s, const char *start)
     return strncmp(s.c_str(), start, len) == 0;
 }
 
-bool string_endswith(const string &s, const char *end)
+bool string_endswith(const string &s, const string &end)
 {
-  size_t len = strlen(end);
+  size_t len = end.length();
 
   if (len > s.size())
     return 0;
   else
-    return strncmp(s.c_str() + s.size() - len, end, len) == 0;
+    return s.compare(s.length() - len, len, end) == 0;
 }
 
 string string_strip(const string &s)
diff --git a/intern/cycles/util/util_string.h b/intern/cycles/util/util_string.h
index ce2d4acdde4..f51aa7111e8 100644
--- a/intern/cycles/util/util_string.h
+++ b/intern/cycles/util/util_string.h
@@ -46,7 +46,7 @@ void string_split(vector<string> &tokens,
                   bool skip_empty_tokens = true);
 void string_replace(string &haystack, const string &needle, const string &other);
 bool string_startswith(const string &s, const char *start);
-bool string_endswith(const string &s, const char *end);
+bool string_endswith(const string &s, const string &end);
 string string_strip(const string &s);
 string string_remove_trademark(const string &s);
 string string_from_bool(const bool var);



More information about the Bf-blender-cvs mailing list