Blender  V2.93
blender_python.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2011-2013 Blender Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <Python.h>
18 
19 #include "blender/CCL_api.h"
20 
21 #include "blender/blender_device.h"
23 #include "blender/blender_sync.h"
24 #include "blender/blender_util.h"
25 
26 #include "render/denoising.h"
27 #include "render/merge.h"
28 
29 #include "util/util_debug.h"
30 #include "util/util_foreach.h"
31 #include "util/util_logging.h"
32 #include "util/util_md5.h"
33 #include "util/util_opengl.h"
35 #include "util/util_path.h"
36 #include "util/util_string.h"
37 #include "util/util_task.h"
38 #include "util/util_tbb.h"
39 #include "util/util_types.h"
40 
41 #ifdef WITH_OSL
42 # include "render/osl.h"
43 
44 # include <OSL/oslconfig.h>
45 # include <OSL/oslquery.h>
46 #endif
47 
48 #ifdef WITH_OPENCL
49 # include "device/device_intern.h"
50 #endif
51 
53 
54 namespace {
55 
56 /* Flag describing whether debug flags were synchronized from scene. */
57 bool debug_flags_set = false;
58 
59 void *pylong_as_voidptr_typesafe(PyObject *object)
60 {
61  if (object == Py_None)
62  return NULL;
63  return PyLong_AsVoidPtr(object);
64 }
65 
66 PyObject *pyunicode_from_string(const char *str)
67 {
68  /* Ignore errors if device API returns invalid UTF-8 strings. */
69  return PyUnicode_DecodeUTF8(str, strlen(str), "ignore");
70 }
71 
72 /* Synchronize debug flags from a given Blender scene.
73  * Return truth when device list needs invalidation.
74  */
76 {
77  DebugFlagsRef flags = DebugFlags();
78  PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
79  /* Backup some settings for comparison. */
80  DebugFlags::OpenCL::DeviceType opencl_device_type = flags.opencl.device_type;
81  /* Synchronize shared flags. */
82  flags.viewport_static_bvh = get_enum(cscene, "debug_bvh_type");
83  /* Synchronize CPU flags. */
84  flags.cpu.avx2 = get_boolean(cscene, "debug_use_cpu_avx2");
85  flags.cpu.avx = get_boolean(cscene, "debug_use_cpu_avx");
86  flags.cpu.sse41 = get_boolean(cscene, "debug_use_cpu_sse41");
87  flags.cpu.sse3 = get_boolean(cscene, "debug_use_cpu_sse3");
88  flags.cpu.sse2 = get_boolean(cscene, "debug_use_cpu_sse2");
89  flags.cpu.bvh_layout = (BVHLayout)get_enum(cscene, "debug_bvh_layout");
90  flags.cpu.split_kernel = get_boolean(cscene, "debug_use_cpu_split_kernel");
91  /* Synchronize CUDA flags. */
92  flags.cuda.adaptive_compile = get_boolean(cscene, "debug_use_cuda_adaptive_compile");
93  flags.cuda.split_kernel = get_boolean(cscene, "debug_use_cuda_split_kernel");
94  /* Synchronize OptiX flags. */
95  flags.optix.cuda_streams = get_int(cscene, "debug_optix_cuda_streams");
96  flags.optix.curves_api = get_boolean(cscene, "debug_optix_curves_api");
97  /* Synchronize OpenCL device type. */
98  switch (get_enum(cscene, "debug_opencl_device_type")) {
99  case 0:
101  break;
102  case 1:
104  break;
105  case 2:
107  break;
108  case 3:
110  break;
111  case 4:
113  break;
114  case 5:
116  break;
117  }
118  /* Synchronize other OpenCL flags. */
119  flags.opencl.debug = get_boolean(cscene, "debug_use_opencl_debug");
120  flags.opencl.mem_limit = ((size_t)get_int(cscene, "debug_opencl_mem_limit")) * 1024 * 1024;
121  return flags.opencl.device_type != opencl_device_type;
122 }
123 
124 /* Reset debug flags to default values.
125  * Return truth when device list needs invalidation.
126  */
128 {
129  DebugFlagsRef flags = DebugFlags();
130  /* Backup some settings for comparison. */
131  DebugFlags::OpenCL::DeviceType opencl_device_type = flags.opencl.device_type;
132  flags.reset();
133  return flags.opencl.device_type != opencl_device_type;
134 }
135 
136 } /* namespace */
137 
138 void python_thread_state_save(void **python_thread_state)
139 {
140  *python_thread_state = (void *)PyEval_SaveThread();
141 }
142 
143 void python_thread_state_restore(void **python_thread_state)
144 {
145  PyEval_RestoreThread((PyThreadState *)*python_thread_state);
146  *python_thread_state = NULL;
147 }
148 
149 static const char *PyC_UnicodeAsByte(PyObject *py_str, PyObject **coerce)
150 {
151  const char *result = PyUnicode_AsUTF8(py_str);
152  if (result) {
153  /* 99% of the time this is enough but we better support non unicode
154  * chars since blender doesn't limit this.
155  */
156  return result;
157  }
158  else {
159  PyErr_Clear();
160  if (PyBytes_Check(py_str)) {
161  return PyBytes_AS_STRING(py_str);
162  }
163  else if ((*coerce = PyUnicode_EncodeFSDefault(py_str))) {
164  return PyBytes_AS_STRING(*coerce);
165  }
166  else {
167  /* Clear the error, so Cycles can be at least used without
168  * GPU and OSL support,
169  */
170  PyErr_Clear();
171  return "";
172  }
173  }
174 }
175 
176 static PyObject *init_func(PyObject * /*self*/, PyObject *args)
177 {
178  PyObject *path, *user_path;
179  int headless;
180 
181  if (!PyArg_ParseTuple(args, "OOi", &path, &user_path, &headless)) {
182  return NULL;
183  }
184 
185  PyObject *path_coerce = NULL, *user_path_coerce = NULL;
186  path_init(PyC_UnicodeAsByte(path, &path_coerce),
187  PyC_UnicodeAsByte(user_path, &user_path_coerce));
188  Py_XDECREF(path_coerce);
189  Py_XDECREF(user_path_coerce);
190 
191  BlenderSession::headless = headless;
192 
194 
195  VLOG(2) << "Debug flags initialized to:\n" << DebugFlags();
196 
197  Py_RETURN_NONE;
198 }
199 
200 static PyObject *exit_func(PyObject * /*self*/, PyObject * /*args*/)
201 {
205  Py_RETURN_NONE;
206 }
207 
208 static PyObject *create_func(PyObject * /*self*/, PyObject *args)
209 {
210  PyObject *pyengine, *pypreferences, *pydata, *pyscreen, *pyregion, *pyv3d, *pyrv3d;
211  int preview_osl;
212 
213  if (!PyArg_ParseTuple(args,
214  "OOOOOOOi",
215  &pyengine,
216  &pypreferences,
217  &pydata,
218  &pyscreen,
219  &pyregion,
220  &pyv3d,
221  &pyrv3d,
222  &preview_osl)) {
223  return NULL;
224  }
225 
226  /* RNA */
227  ID *bScreen = (ID *)PyLong_AsVoidPtr(pyscreen);
228 
229  PointerRNA engineptr;
230  RNA_pointer_create(NULL, &RNA_RenderEngine, (void *)PyLong_AsVoidPtr(pyengine), &engineptr);
231  BL::RenderEngine engine(engineptr);
232 
233  PointerRNA preferencesptr;
235  NULL, &RNA_Preferences, (void *)PyLong_AsVoidPtr(pypreferences), &preferencesptr);
236  BL::Preferences preferences(preferencesptr);
237 
238  PointerRNA dataptr;
239  RNA_main_pointer_create((Main *)PyLong_AsVoidPtr(pydata), &dataptr);
240  BL::BlendData data(dataptr);
241 
242  PointerRNA regionptr;
244  BL::Region region(regionptr);
245 
246  PointerRNA v3dptr;
248  BL::SpaceView3D v3d(v3dptr);
249 
250  PointerRNA rv3dptr;
251  RNA_pointer_create(bScreen, &RNA_RegionView3D, pylong_as_voidptr_typesafe(pyrv3d), &rv3dptr);
252  BL::RegionView3D rv3d(rv3dptr);
253 
254  /* create session */
255  BlenderSession *session;
256 
257  if (rv3d) {
258  /* interactive viewport session */
259  int width = region.width();
260  int height = region.height();
261 
262  session = new BlenderSession(engine, preferences, data, v3d, rv3d, width, height);
263  }
264  else {
265  /* offline session or preview render */
266  session = new BlenderSession(engine, preferences, data, preview_osl);
267  }
268 
269  return PyLong_FromVoidPtr(session);
270 }
271 
272 static PyObject *free_func(PyObject * /*self*/, PyObject *value)
273 {
274  delete (BlenderSession *)PyLong_AsVoidPtr(value);
275 
276  Py_RETURN_NONE;
277 }
278 
279 static PyObject *render_func(PyObject * /*self*/, PyObject *args)
280 {
281  PyObject *pysession, *pydepsgraph;
282 
283  if (!PyArg_ParseTuple(args, "OO", &pysession, &pydepsgraph))
284  return NULL;
285 
286  BlenderSession *session = (BlenderSession *)PyLong_AsVoidPtr(pysession);
287 
288  PointerRNA depsgraphptr;
289  RNA_pointer_create(NULL, &RNA_Depsgraph, (ID *)PyLong_AsVoidPtr(pydepsgraph), &depsgraphptr);
290  BL::Depsgraph b_depsgraph(depsgraphptr);
291 
292  /* Allow Blender to execute other Python scripts, and isolate TBB tasks so we
293  * don't get deadlocks with Blender threads accessing shared data like images. */
295 
296  tbb::this_task_arena::isolate([&] { session->render(b_depsgraph); });
297 
299 
300  Py_RETURN_NONE;
301 }
302 
303 /* pixel_array and result passed as pointers */
304 static PyObject *bake_func(PyObject * /*self*/, PyObject *args)
305 {
306  PyObject *pysession, *pydepsgraph, *pyobject;
307  const char *pass_type;
308  int pass_filter, width, height;
309 
310  if (!PyArg_ParseTuple(args,
311  "OOOsiii",
312  &pysession,
313  &pydepsgraph,
314  &pyobject,
315  &pass_type,
316  &pass_filter,
317  &width,
318  &height))
319  return NULL;
320 
321  BlenderSession *session = (BlenderSession *)PyLong_AsVoidPtr(pysession);
322 
323  PointerRNA depsgraphptr;
324  RNA_pointer_create(NULL, &RNA_Depsgraph, PyLong_AsVoidPtr(pydepsgraph), &depsgraphptr);
325  BL::Depsgraph b_depsgraph(depsgraphptr);
326 
327  PointerRNA objectptr;
328  RNA_id_pointer_create((ID *)PyLong_AsVoidPtr(pyobject), &objectptr);
329  BL::Object b_object(objectptr);
330 
332 
333  tbb::this_task_arena::isolate(
334  [&] { session->bake(b_depsgraph, b_object, pass_type, pass_filter, width, height); });
335 
337 
338  Py_RETURN_NONE;
339 }
340 
341 static PyObject *draw_func(PyObject * /*self*/, PyObject *args)
342 {
343  PyObject *pysession, *pygraph, *pyv3d, *pyrv3d;
344 
345  if (!PyArg_ParseTuple(args, "OOOO", &pysession, &pygraph, &pyv3d, &pyrv3d))
346  return NULL;
347 
348  BlenderSession *session = (BlenderSession *)PyLong_AsVoidPtr(pysession);
349 
350  if (PyLong_AsVoidPtr(pyrv3d)) {
351  /* 3d view drawing */
352  int viewport[4];
353  glGetIntegerv(GL_VIEWPORT, viewport);
354 
355  session->draw(viewport[2], viewport[3]);
356  }
357 
358  Py_RETURN_NONE;
359 }
360 
361 static PyObject *reset_func(PyObject * /*self*/, PyObject *args)
362 {
363  PyObject *pysession, *pydata, *pydepsgraph;
364 
365  if (!PyArg_ParseTuple(args, "OOO", &pysession, &pydata, &pydepsgraph))
366  return NULL;
367 
368  BlenderSession *session = (BlenderSession *)PyLong_AsVoidPtr(pysession);
369 
370  PointerRNA dataptr;
371  RNA_main_pointer_create((Main *)PyLong_AsVoidPtr(pydata), &dataptr);
372  BL::BlendData b_data(dataptr);
373 
374  PointerRNA depsgraphptr;
375  RNA_pointer_create(NULL, &RNA_Depsgraph, PyLong_AsVoidPtr(pydepsgraph), &depsgraphptr);
376  BL::Depsgraph b_depsgraph(depsgraphptr);
377 
379 
380  tbb::this_task_arena::isolate([&] { session->reset_session(b_data, b_depsgraph); });
381 
383 
384  Py_RETURN_NONE;
385 }
386 
387 static PyObject *sync_func(PyObject * /*self*/, PyObject *args)
388 {
389  PyObject *pysession, *pydepsgraph;
390 
391  if (!PyArg_ParseTuple(args, "OO", &pysession, &pydepsgraph))
392  return NULL;
393 
394  BlenderSession *session = (BlenderSession *)PyLong_AsVoidPtr(pysession);
395 
396  PointerRNA depsgraphptr;
397  RNA_pointer_create(NULL, &RNA_Depsgraph, PyLong_AsVoidPtr(pydepsgraph), &depsgraphptr);
398  BL::Depsgraph b_depsgraph(depsgraphptr);
399 
401 
402  tbb::this_task_arena::isolate([&] { session->synchronize(b_depsgraph); });
403 
405 
406  Py_RETURN_NONE;
407 }
408 
409 static PyObject *available_devices_func(PyObject * /*self*/, PyObject *args)
410 {
411  const char *type_name;
412  if (!PyArg_ParseTuple(args, "s", &type_name)) {
413  return NULL;
414  }
415 
417  /* "NONE" is defined by the add-on, see: `CyclesPreferences.get_device_types`. */
418  if ((type == DEVICE_NONE) && (strcmp(type_name, "NONE") != 0)) {
419  PyErr_Format(PyExc_ValueError, "Device \"%s\" not known.", type_name);
420  return NULL;
421  }
422 
425 
427  PyObject *ret = PyTuple_New(devices.size());
428 
429  for (size_t i = 0; i < devices.size(); i++) {
430  DeviceInfo &device = devices[i];
431  string type_name = Device::string_from_type(device.type);
432  PyObject *device_tuple = PyTuple_New(4);
433  PyTuple_SET_ITEM(device_tuple, 0, pyunicode_from_string(device.description.c_str()));
434  PyTuple_SET_ITEM(device_tuple, 1, pyunicode_from_string(type_name.c_str()));
435  PyTuple_SET_ITEM(device_tuple, 2, pyunicode_from_string(device.id.c_str()));
436  PyTuple_SET_ITEM(device_tuple, 3, PyBool_FromLong(device.has_peer_memory));
437  PyTuple_SET_ITEM(ret, i, device_tuple);
438  }
439 
440  return ret;
441 }
442 
443 #ifdef WITH_OSL
444 
445 static PyObject *osl_update_node_func(PyObject * /*self*/, PyObject *args)
446 {
447  PyObject *pydata, *pynodegroup, *pynode;
448  const char *filepath = NULL;
449 
450  if (!PyArg_ParseTuple(args, "OOOs", &pydata, &pynodegroup, &pynode, &filepath))
451  return NULL;
452 
453  /* RNA */
454  PointerRNA dataptr;
455  RNA_main_pointer_create((Main *)PyLong_AsVoidPtr(pydata), &dataptr);
456  BL::BlendData b_data(dataptr);
457 
458  PointerRNA nodeptr;
459  RNA_pointer_create((ID *)PyLong_AsVoidPtr(pynodegroup),
461  (void *)PyLong_AsVoidPtr(pynode),
462  &nodeptr);
463  BL::ShaderNodeScript b_node(nodeptr);
464 
465  /* update bytecode hash */
466  string bytecode = b_node.bytecode();
467 
468  if (!bytecode.empty()) {
469  MD5Hash md5;
470  md5.append((const uint8_t *)bytecode.c_str(), bytecode.size());
471  b_node.bytecode_hash(md5.get_hex().c_str());
472  }
473  else
474  b_node.bytecode_hash("");
475 
476  /* query from file path */
477  OSL::OSLQuery query;
478 
479  if (!OSLShaderManager::osl_query(query, filepath))
480  Py_RETURN_FALSE;
481 
482  /* add new sockets from parameters */
483  set<void *> used_sockets;
484 
485  for (int i = 0; i < query.nparams(); i++) {
486  const OSL::OSLQuery::Parameter *param = query.getparam(i);
487 
488  /* skip unsupported types */
489  if (param->varlenarray || param->isstruct || param->type.arraylen > 1)
490  continue;
491 
492  /* determine socket type */
493  string socket_type;
494  BL::NodeSocket::type_enum data_type = BL::NodeSocket::type_VALUE;
495  float4 default_float4 = make_float4(0.0f, 0.0f, 0.0f, 1.0f);
496  float default_float = 0.0f;
497  int default_int = 0;
498  string default_string = "";
499 
500  if (param->isclosure) {
501  socket_type = "NodeSocketShader";
502  data_type = BL::NodeSocket::type_SHADER;
503  }
504  else if (param->type.vecsemantics == TypeDesc::COLOR) {
505  socket_type = "NodeSocketColor";
506  data_type = BL::NodeSocket::type_RGBA;
507 
508  if (param->validdefault) {
509  default_float4[0] = param->fdefault[0];
510  default_float4[1] = param->fdefault[1];
511  default_float4[2] = param->fdefault[2];
512  }
513  }
514  else if (param->type.vecsemantics == TypeDesc::POINT ||
515  param->type.vecsemantics == TypeDesc::VECTOR ||
516  param->type.vecsemantics == TypeDesc::NORMAL) {
517  socket_type = "NodeSocketVector";
518  data_type = BL::NodeSocket::type_VECTOR;
519 
520  if (param->validdefault) {
521  default_float4[0] = param->fdefault[0];
522  default_float4[1] = param->fdefault[1];
523  default_float4[2] = param->fdefault[2];
524  }
525  }
526  else if (param->type.aggregate == TypeDesc::SCALAR) {
527  if (param->type.basetype == TypeDesc::INT) {
528  socket_type = "NodeSocketInt";
529  data_type = BL::NodeSocket::type_INT;
530  if (param->validdefault)
531  default_int = param->idefault[0];
532  }
533  else if (param->type.basetype == TypeDesc::FLOAT) {
534  socket_type = "NodeSocketFloat";
535  data_type = BL::NodeSocket::type_VALUE;
536  if (param->validdefault)
537  default_float = param->fdefault[0];
538  }
539  else if (param->type.basetype == TypeDesc::STRING) {
540  socket_type = "NodeSocketString";
541  data_type = BL::NodeSocket::type_STRING;
542  if (param->validdefault)
543  default_string = param->sdefault[0].string();
544  }
545  else
546  continue;
547  }
548  else
549  continue;
550 
551  /* find socket socket */
552  BL::NodeSocket b_sock(PointerRNA_NULL);
553  if (param->isoutput) {
554  b_sock = b_node.outputs[param->name.string()];
555  /* remove if type no longer matches */
556  if (b_sock && b_sock.bl_idname() != socket_type) {
557  b_node.outputs.remove(b_data, b_sock);
558  b_sock = BL::NodeSocket(PointerRNA_NULL);
559  }
560  }
561  else {
562  b_sock = b_node.inputs[param->name.string()];
563  /* remove if type no longer matches */
564  if (b_sock && b_sock.bl_idname() != socket_type) {
565  b_node.inputs.remove(b_data, b_sock);
566  b_sock = BL::NodeSocket(PointerRNA_NULL);
567  }
568  }
569 
570  if (!b_sock) {
571  /* create new socket */
572  if (param->isoutput)
573  b_sock = b_node.outputs.create(
574  b_data, socket_type.c_str(), param->name.c_str(), param->name.c_str());
575  else
576  b_sock = b_node.inputs.create(
577  b_data, socket_type.c_str(), param->name.c_str(), param->name.c_str());
578 
579  /* set default value */
580  if (data_type == BL::NodeSocket::type_VALUE) {
581  set_float(b_sock.ptr, "default_value", default_float);
582  }
583  else if (data_type == BL::NodeSocket::type_INT) {
584  set_int(b_sock.ptr, "default_value", default_int);
585  }
586  else if (data_type == BL::NodeSocket::type_RGBA) {
587  set_float4(b_sock.ptr, "default_value", default_float4);
588  }
589  else if (data_type == BL::NodeSocket::type_VECTOR) {
590  set_float3(b_sock.ptr, "default_value", float4_to_float3(default_float4));
591  }
592  else if (data_type == BL::NodeSocket::type_STRING) {
593  set_string(b_sock.ptr, "default_value", default_string);
594  }
595  }
596 
597  used_sockets.insert(b_sock.ptr.data);
598  }
599 
600  /* remove unused parameters */
601  bool removed;
602 
603  do {
604  removed = false;
605 
606  for (BL::NodeSocket &b_input : b_node.inputs) {
607  if (used_sockets.find(b_input.ptr.data) == used_sockets.end()) {
608  b_node.inputs.remove(b_data, b_input);
609  removed = true;
610  break;
611  }
612  }
613 
614  for (BL::NodeSocket &b_output : b_node.outputs) {
615  if (used_sockets.find(b_output.ptr.data) == used_sockets.end()) {
616  b_node.outputs.remove(b_data, b_output);
617  removed = true;
618  break;
619  }
620  }
621  } while (removed);
622 
623  Py_RETURN_TRUE;
624 }
625 
626 static PyObject *osl_compile_func(PyObject * /*self*/, PyObject *args)
627 {
628  const char *inputfile = NULL, *outputfile = NULL;
629 
630  if (!PyArg_ParseTuple(args, "ss", &inputfile, &outputfile))
631  return NULL;
632 
633  /* return */
634  if (!OSLShaderManager::osl_compile(inputfile, outputfile))
635  Py_RETURN_FALSE;
636 
637  Py_RETURN_TRUE;
638 }
639 #endif
640 
641 static PyObject *system_info_func(PyObject * /*self*/, PyObject * /*value*/)
642 {
643  string system_info = Device::device_capabilities();
644  return pyunicode_from_string(system_info.c_str());
645 }
646 
647 #ifdef WITH_OPENCL
648 static PyObject *opencl_disable_func(PyObject * /*self*/, PyObject * /*value*/)
649 {
650  VLOG(2) << "Disabling OpenCL platform.";
652  Py_RETURN_NONE;
653 }
654 
655 static PyObject *opencl_compile_func(PyObject * /*self*/, PyObject *args)
656 {
657  PyObject *sequence = PySequence_Fast(args, "Arguments must be a sequence");
658  if (sequence == NULL) {
659  Py_RETURN_FALSE;
660  }
661 
663  for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(sequence); i++) {
664  PyObject *item = PySequence_Fast_GET_ITEM(sequence, i);
665  PyObject *item_as_string = PyObject_Str(item);
666  const char *parameter_string = PyUnicode_AsUTF8(item_as_string);
667  parameters.push_back(parameter_string);
668  Py_DECREF(item_as_string);
669  }
670  Py_DECREF(sequence);
671 
673  Py_RETURN_TRUE;
674  }
675  else {
676  Py_RETURN_FALSE;
677  }
678 }
679 #endif
680 
681 static bool image_parse_filepaths(PyObject *pyfilepaths, vector<string> &filepaths)
682 {
683  if (PyUnicode_Check(pyfilepaths)) {
684  const char *filepath = PyUnicode_AsUTF8(pyfilepaths);
685  filepaths.push_back(filepath);
686  return true;
687  }
688 
689  PyObject *sequence = PySequence_Fast(pyfilepaths,
690  "File paths must be a string or sequence of strings");
691  if (sequence == NULL) {
692  return false;
693  }
694 
695  for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(sequence); i++) {
696  PyObject *item = PySequence_Fast_GET_ITEM(sequence, i);
697  const char *filepath = PyUnicode_AsUTF8(item);
698  if (filepath == NULL) {
699  PyErr_SetString(PyExc_ValueError, "File paths must be a string or sequence of strings.");
700  Py_DECREF(sequence);
701  return false;
702  }
703  filepaths.push_back(filepath);
704  }
705  Py_DECREF(sequence);
706 
707  return true;
708 }
709 
710 static PyObject *denoise_func(PyObject * /*self*/, PyObject *args, PyObject *keywords)
711 {
712  static const char *keyword_list[] = {
713  "preferences", "scene", "view_layer", "input", "output", "tile_size", "samples", NULL};
714  PyObject *pypreferences, *pyscene, *pyviewlayer;
715  PyObject *pyinput, *pyoutput = NULL;
716  int tile_size = 0, samples = 0;
717 
718  if (!PyArg_ParseTupleAndKeywords(args,
719  keywords,
720  "OOOO|Oii",
721  (char **)keyword_list,
722  &pypreferences,
723  &pyscene,
724  &pyviewlayer,
725  &pyinput,
726  &pyoutput,
727  &tile_size,
728  &samples)) {
729  return NULL;
730  }
731 
732  /* Get device specification from preferences and scene. */
733  PointerRNA preferencesptr;
735  NULL, &RNA_Preferences, (void *)PyLong_AsVoidPtr(pypreferences), &preferencesptr);
736  BL::Preferences b_preferences(preferencesptr);
737 
738  PointerRNA sceneptr;
739  RNA_id_pointer_create((ID *)PyLong_AsVoidPtr(pyscene), &sceneptr);
740  BL::Scene b_scene(sceneptr);
741 
742  DeviceInfo device = blender_device_info(b_preferences, b_scene, true);
743 
744  /* Get denoising parameters from view layer. */
745  PointerRNA viewlayerptr;
746  RNA_pointer_create((ID *)PyLong_AsVoidPtr(pyscene),
747  &RNA_ViewLayer,
748  PyLong_AsVoidPtr(pyviewlayer),
749  &viewlayerptr);
750  PointerRNA cviewlayer = RNA_pointer_get(&viewlayerptr, "cycles");
751 
753  params.radius = get_int(cviewlayer, "denoising_radius");
754  params.strength = get_float(cviewlayer, "denoising_strength");
755  params.feature_strength = get_float(cviewlayer, "denoising_feature_strength");
756  params.relative_pca = get_boolean(cviewlayer, "denoising_relative_pca");
757  params.neighbor_frames = get_int(cviewlayer, "denoising_neighbor_frames");
758 
759  /* Parse file paths list. */
760  vector<string> input, output;
761 
762  if (!image_parse_filepaths(pyinput, input)) {
763  return NULL;
764  }
765 
766  if (pyoutput) {
767  if (!image_parse_filepaths(pyoutput, output)) {
768  return NULL;
769  }
770  }
771  else {
772  output = input;
773  }
774 
775  if (input.empty()) {
776  PyErr_SetString(PyExc_ValueError, "No input file paths specified.");
777  return NULL;
778  }
779  if (input.size() != output.size()) {
780  PyErr_SetString(PyExc_ValueError, "Number of input and output file paths does not match.");
781  return NULL;
782  }
783 
784  /* Create denoiser. */
785  Denoiser denoiser(device);
786  denoiser.params = params;
787  denoiser.input = input;
788  denoiser.output = output;
789 
790  if (tile_size > 0) {
791  denoiser.tile_size = make_int2(tile_size, tile_size);
792  }
793  if (samples > 0) {
794  denoiser.samples_override = samples;
795  }
796 
797  /* Run denoiser. */
798  if (!denoiser.run()) {
799  PyErr_SetString(PyExc_ValueError, denoiser.error.c_str());
800  return NULL;
801  }
802 
803  Py_RETURN_NONE;
804 }
805 
806 static PyObject *merge_func(PyObject * /*self*/, PyObject *args, PyObject *keywords)
807 {
808  static const char *keyword_list[] = {"input", "output", NULL};
809  PyObject *pyinput, *pyoutput = NULL;
810 
811  if (!PyArg_ParseTupleAndKeywords(
812  args, keywords, "OO", (char **)keyword_list, &pyinput, &pyoutput)) {
813  return NULL;
814  }
815 
816  /* Parse input list. */
817  vector<string> input;
818  if (!image_parse_filepaths(pyinput, input)) {
819  return NULL;
820  }
821 
822  /* Parse output string. */
823  if (!PyUnicode_Check(pyoutput)) {
824  PyErr_SetString(PyExc_ValueError, "Output must be a string.");
825  return NULL;
826  }
827  string output = PyUnicode_AsUTF8(pyoutput);
828 
829  /* Merge. */
830  ImageMerger merger;
831  merger.input = input;
832  merger.output = output;
833 
834  if (!merger.run()) {
835  PyErr_SetString(PyExc_ValueError, merger.error.c_str());
836  return NULL;
837  }
838 
839  Py_RETURN_NONE;
840 }
841 
842 static PyObject *debug_flags_update_func(PyObject * /*self*/, PyObject *args)
843 {
844  PyObject *pyscene;
845  if (!PyArg_ParseTuple(args, "O", &pyscene)) {
846  return NULL;
847  }
848 
849  PointerRNA sceneptr;
850  RNA_id_pointer_create((ID *)PyLong_AsVoidPtr(pyscene), &sceneptr);
851  BL::Scene b_scene(sceneptr);
852 
853  if (debug_flags_sync_from_scene(b_scene)) {
854  VLOG(2) << "Tagging device list for update.";
856  }
857 
858  VLOG(2) << "Debug flags set to:\n" << DebugFlags();
859 
860  debug_flags_set = true;
861 
862  Py_RETURN_NONE;
863 }
864 
865 static PyObject *debug_flags_reset_func(PyObject * /*self*/, PyObject * /*args*/)
866 {
867  if (debug_flags_reset()) {
868  VLOG(2) << "Tagging device list for update.";
870  }
871  if (debug_flags_set) {
872  VLOG(2) << "Debug flags reset to:\n" << DebugFlags();
873  debug_flags_set = false;
874  }
875  Py_RETURN_NONE;
876 }
877 
878 static PyObject *set_resumable_chunk_func(PyObject * /*self*/, PyObject *args)
879 {
880  int num_resumable_chunks, current_resumable_chunk;
881  if (!PyArg_ParseTuple(args, "ii", &num_resumable_chunks, &current_resumable_chunk)) {
882  Py_RETURN_NONE;
883  }
884 
885  if (num_resumable_chunks <= 0) {
886  fprintf(stderr, "Cycles: Bad value for number of resumable chunks.\n");
887  abort();
888  Py_RETURN_NONE;
889  }
890  if (current_resumable_chunk < 1 || current_resumable_chunk > num_resumable_chunks) {
891  fprintf(stderr, "Cycles: Bad value for current resumable chunk number.\n");
892  abort();
893  Py_RETURN_NONE;
894  }
895 
896  VLOG(1) << "Initialized resumable render: "
897  << "num_resumable_chunks=" << num_resumable_chunks << ", "
898  << "current_resumable_chunk=" << current_resumable_chunk;
899  BlenderSession::num_resumable_chunks = num_resumable_chunks;
900  BlenderSession::current_resumable_chunk = current_resumable_chunk;
901 
902  printf("Cycles: Will render chunk %d of %d\n", current_resumable_chunk, num_resumable_chunks);
903 
904  Py_RETURN_NONE;
905 }
906 
907 static PyObject *set_resumable_chunk_range_func(PyObject * /*self*/, PyObject *args)
908 {
909  int num_chunks, start_chunk, end_chunk;
910  if (!PyArg_ParseTuple(args, "iii", &num_chunks, &start_chunk, &end_chunk)) {
911  Py_RETURN_NONE;
912  }
913 
914  if (num_chunks <= 0) {
915  fprintf(stderr, "Cycles: Bad value for number of resumable chunks.\n");
916  abort();
917  Py_RETURN_NONE;
918  }
919  if (start_chunk < 1 || start_chunk > num_chunks) {
920  fprintf(stderr, "Cycles: Bad value for start chunk number.\n");
921  abort();
922  Py_RETURN_NONE;
923  }
924  if (end_chunk < 1 || end_chunk > num_chunks) {
925  fprintf(stderr, "Cycles: Bad value for start chunk number.\n");
926  abort();
927  Py_RETURN_NONE;
928  }
929  if (start_chunk > end_chunk) {
930  fprintf(stderr, "Cycles: End chunk should be higher than start one.\n");
931  abort();
932  Py_RETURN_NONE;
933  }
934 
935  VLOG(1) << "Initialized resumable render: "
936  << "num_resumable_chunks=" << num_chunks << ", "
937  << "start_resumable_chunk=" << start_chunk << "end_resumable_chunk=" << end_chunk;
941 
942  printf("Cycles: Will render chunks %d to %d of %d\n", start_chunk, end_chunk, num_chunks);
943 
944  Py_RETURN_NONE;
945 }
946 
947 static PyObject *clear_resumable_chunk_func(PyObject * /*self*/, PyObject * /*value*/)
948 {
949  VLOG(1) << "Clear resumable render";
952 
953  Py_RETURN_NONE;
954 }
955 
956 static PyObject *enable_print_stats_func(PyObject * /*self*/, PyObject * /*args*/)
957 {
959  Py_RETURN_NONE;
960 }
961 
962 static PyObject *get_device_types_func(PyObject * /*self*/, PyObject * /*args*/)
963 {
965  bool has_cuda = false, has_optix = false, has_opencl = false;
966  foreach (DeviceType device_type, device_types) {
967  has_cuda |= (device_type == DEVICE_CUDA);
968  has_optix |= (device_type == DEVICE_OPTIX);
969  has_opencl |= (device_type == DEVICE_OPENCL);
970  }
971  PyObject *list = PyTuple_New(3);
972  PyTuple_SET_ITEM(list, 0, PyBool_FromLong(has_cuda));
973  PyTuple_SET_ITEM(list, 1, PyBool_FromLong(has_optix));
974  PyTuple_SET_ITEM(list, 2, PyBool_FromLong(has_opencl));
975  return list;
976 }
977 
978 static PyObject *set_device_override_func(PyObject * /*self*/, PyObject *arg)
979 {
980  PyObject *override_string = PyObject_Str(arg);
981  string override = PyUnicode_AsUTF8(override_string);
982  Py_DECREF(override_string);
983 
984  bool include_cpu = false;
985  const string cpu_suffix = "+CPU";
986  if (string_endswith(override, cpu_suffix)) {
987  include_cpu = true;
988  override = override.substr(0, override.length() - cpu_suffix.length());
989  }
990 
991  if (override == "CPU") {
993  }
994  else if (override == "OPENCL") {
996  }
997  else if (override == "CUDA") {
999  }
1000  else if (override == "OPTIX") {
1002  }
1003  else {
1004  printf("\nError: %s is not a valid Cycles device.\n", override.c_str());
1005  Py_RETURN_FALSE;
1006  }
1007 
1008  if (include_cpu) {
1010  DEVICE_MASK_CPU);
1011  }
1012 
1013  Py_RETURN_TRUE;
1014 }
1015 
1016 static PyMethodDef methods[] = {
1017  {"init", init_func, METH_VARARGS, ""},
1018  {"exit", exit_func, METH_VARARGS, ""},
1019  {"create", create_func, METH_VARARGS, ""},
1020  {"free", free_func, METH_O, ""},
1021  {"render", render_func, METH_VARARGS, ""},
1022  {"bake", bake_func, METH_VARARGS, ""},
1023  {"draw", draw_func, METH_VARARGS, ""},
1024  {"sync", sync_func, METH_VARARGS, ""},
1025  {"reset", reset_func, METH_VARARGS, ""},
1026 #ifdef WITH_OSL
1027  {"osl_update_node", osl_update_node_func, METH_VARARGS, ""},
1028  {"osl_compile", osl_compile_func, METH_VARARGS, ""},
1029 #endif
1030  {"available_devices", available_devices_func, METH_VARARGS, ""},
1031  {"system_info", system_info_func, METH_NOARGS, ""},
1032 #ifdef WITH_OPENCL
1033  {"opencl_disable", opencl_disable_func, METH_NOARGS, ""},
1034  {"opencl_compile", opencl_compile_func, METH_VARARGS, ""},
1035 #endif
1036 
1037  /* Standalone denoising */
1038  {"denoise", (PyCFunction)denoise_func, METH_VARARGS | METH_KEYWORDS, ""},
1039  {"merge", (PyCFunction)merge_func, METH_VARARGS | METH_KEYWORDS, ""},
1040 
1041  /* Debugging routines */
1042  {"debug_flags_update", debug_flags_update_func, METH_VARARGS, ""},
1043  {"debug_flags_reset", debug_flags_reset_func, METH_NOARGS, ""},
1044 
1045  /* Statistics. */
1046  {"enable_print_stats", enable_print_stats_func, METH_NOARGS, ""},
1047 
1048  /* Resumable render */
1049  {"set_resumable_chunk", set_resumable_chunk_func, METH_VARARGS, ""},
1050  {"set_resumable_chunk_range", set_resumable_chunk_range_func, METH_VARARGS, ""},
1051  {"clear_resumable_chunk", clear_resumable_chunk_func, METH_NOARGS, ""},
1052 
1053  /* Compute Device selection */
1054  {"get_device_types", get_device_types_func, METH_VARARGS, ""},
1055  {"set_device_override", set_device_override_func, METH_O, ""},
1056 
1057  {NULL, NULL, 0, NULL},
1058 };
1059 
1060 static struct PyModuleDef module = {
1061  PyModuleDef_HEAD_INIT,
1062  "_cycles",
1063  "Blender cycles render integration",
1064  -1,
1065  methods,
1066  NULL,
1067  NULL,
1068  NULL,
1069  NULL,
1070 };
1071 
1073 
1075 {
1076  PyObject *mod = PyModule_Create(&ccl::module);
1077 
1078 #ifdef WITH_OSL
1079  /* TODO(sergey): This gives us library we've been linking against.
1080  * In theory with dynamic OSL library it might not be
1081  * accurate, but there's nothing in OSL API which we
1082  * might use to get version in runtime.
1083  */
1084  int curversion = OSL_LIBRARY_VERSION_CODE;
1085  PyModule_AddObject(mod, "with_osl", Py_True);
1086  Py_INCREF(Py_True);
1087  PyModule_AddObject(
1088  mod,
1089  "osl_version",
1090  Py_BuildValue("(iii)", curversion / 10000, (curversion / 100) % 100, curversion % 100));
1091  PyModule_AddObject(
1092  mod,
1093  "osl_version_string",
1094  PyUnicode_FromFormat(
1095  "%2d, %2d, %2d", curversion / 10000, (curversion / 100) % 100, curversion % 100));
1096 #else
1097  PyModule_AddObject(mod, "with_osl", Py_False);
1098  Py_INCREF(Py_False);
1099  PyModule_AddStringConstant(mod, "osl_version", "unknown");
1100  PyModule_AddStringConstant(mod, "osl_version_string", "unknown");
1101 #endif
1102 
1103 #ifdef WITH_CYCLES_DEBUG
1104  PyModule_AddObject(mod, "with_cycles_debug", Py_True);
1105  Py_INCREF(Py_True);
1106 #else
1107  PyModule_AddObject(mod, "with_cycles_debug", Py_False);
1108  Py_INCREF(Py_False);
1109 #endif
1110 
1111 #ifdef WITH_NETWORK
1112  PyModule_AddObject(mod, "with_network", Py_True);
1113  Py_INCREF(Py_True);
1114 #else /* WITH_NETWORK */
1115  PyModule_AddObject(mod, "with_network", Py_False);
1116  Py_INCREF(Py_False);
1117 #endif /* WITH_NETWORK */
1118 
1119 #ifdef WITH_EMBREE
1120  PyModule_AddObject(mod, "with_embree", Py_True);
1121  Py_INCREF(Py_True);
1122 #else /* WITH_EMBREE */
1123  PyModule_AddObject(mod, "with_embree", Py_False);
1124  Py_INCREF(Py_False);
1125 #endif /* WITH_EMBREE */
1126 
1128  PyModule_AddObject(mod, "with_openimagedenoise", Py_True);
1129  Py_INCREF(Py_True);
1130  }
1131  else {
1132  PyModule_AddObject(mod, "with_openimagedenoise", Py_False);
1133  Py_INCREF(Py_False);
1134  }
1135 
1136  return (void *)mod;
1137 }
unsigned int uint
Definition: BLI_sys_types.h:83
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:51
struct Object Object
struct Scene Scene
struct RegionView3D RegionView3D
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum query
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei width
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
Group RGB to NORMAL
struct RenderEngine RenderEngine
StructRNA RNA_Region
StructRNA RNA_SpaceView3D
StructRNA RNA_RenderEngine
StructRNA RNA_ViewLayer
StructRNA RNA_Depsgraph
StructRNA RNA_Preferences
StructRNA RNA_ShaderNodeScript
DeviceInfo blender_device_info(BL::Preferences &b_preferences, BL::Scene &b_scene, bool background)
static PyObject * available_devices_func(PyObject *, PyObject *args)
CCL_NAMESPACE_END void * CCL_python_module_init()
void python_thread_state_restore(void **python_thread_state)
static PyObject * draw_func(PyObject *, PyObject *args)
static PyObject * create_func(PyObject *, PyObject *args)
static PyObject * debug_flags_reset_func(PyObject *, PyObject *)
static PyObject * set_device_override_func(PyObject *, PyObject *arg)
static PyObject * sync_func(PyObject *, PyObject *args)
static struct PyModuleDef module
static PyObject * debug_flags_update_func(PyObject *, PyObject *args)
static bool image_parse_filepaths(PyObject *pyfilepaths, vector< string > &filepaths)
static PyMethodDef methods[]
static PyObject * clear_resumable_chunk_func(PyObject *, PyObject *)
static PyObject * merge_func(PyObject *, PyObject *args, PyObject *keywords)
static PyObject * set_resumable_chunk_func(PyObject *, PyObject *args)
static PyObject * render_func(PyObject *, PyObject *args)
static PyObject * enable_print_stats_func(PyObject *, PyObject *)
static PyObject * system_info_func(PyObject *, PyObject *)
static PyObject * exit_func(PyObject *, PyObject *)
static const char * PyC_UnicodeAsByte(PyObject *py_str, PyObject **coerce)
void python_thread_state_save(void **python_thread_state)
static PyObject * get_device_types_func(PyObject *, PyObject *)
static PyObject * denoise_func(PyObject *, PyObject *args, PyObject *keywords)
static PyObject * free_func(PyObject *, PyObject *value)
static PyObject * set_resumable_chunk_range_func(PyObject *, PyObject *args)
static PyObject * reset_func(PyObject *, PyObject *args)
static PyObject * bake_func(PyObject *, PyObject *args)
static PyObject * init_func(PyObject *, PyObject *args)
static float get_float(PointerRNA &ptr, const char *name)
Definition: blender_util.h:359
static bool get_boolean(PointerRNA &ptr, const char *name)
Definition: blender_util.h:349
static void set_float3(PointerRNA &ptr, const char *name, float3 value)
Definition: blender_util.h:332
static int get_int(PointerRNA &ptr, const char *name)
Definition: blender_util.h:369
static int get_enum(PointerRNA &ptr, const char *name, int num_values=-1, int default_value=-1)
Definition: blender_util.h:386
static void set_float4(PointerRNA &ptr, const char *name, float4 value)
Definition: blender_util.h:344
static void set_int(PointerRNA &ptr, const char *name, int value)
Definition: blender_util.h:374
static void set_float(PointerRNA &ptr, const char *name, float value)
Definition: blender_util.h:364
static void set_string(PointerRNA &ptr, const char *name, const string &value)
Definition: blender_util.h:431
#define output
SIMD_FORCE_INLINE btScalar length(const btQuaternion &q)
Return the length of a quaternion.
Definition: btQuaternion.h:895
CCL_NAMESPACE_BEGIN typedef KernelBVHLayout BVHLayout
Definition: bvh_params.h:32
static bool headless
static bool print_render_stats
void synchronize(BL::Depsgraph &b_depsgraph)
static int end_resumable_chunk
void * python_thread_state
static int start_resumable_chunk
static int current_resumable_chunk
void reset_session(BL::BlendData &b_data, BL::Depsgraph &b_depsgraph)
void bake(BL::Depsgraph &b_depsgrah, BL::Object &b_object, const string &pass_type, const int custom_flag, const int bake_width, const int bake_height)
bool draw(int w, int h)
void render(BL::Depsgraph &b_depsgraph)
static int num_resumable_chunks
static DeviceTypeMask device_override
OpenCL opencl
Definition: util_debug.h:186
void reset()
Definition: util_debug.cpp:128
OptiX optix
Definition: util_debug.h:183
bool running_inside_blender
Definition: util_debug.h:36
bool viewport_static_bvh
Definition: util_debug.h:34
int samples_override
Definition: denoising.h:55
string error
Definition: denoising.h:45
vector< string > output
Definition: denoising.h:52
bool run()
Definition: denoising.cpp:890
DenoiseParams params
Definition: denoising.h:60
vector< string > input
Definition: denoising.h:48
int2 tile_size
Definition: denoising.h:57
string id
Definition: device.h:76
bool has_peer_memory
Definition: device.h:87
DeviceType type
Definition: device.h:74
string description
Definition: device.h:75
static void free_memory()
Definition: device.cpp:687
static void tag_update()
Definition: device.cpp:682
static vector< DeviceInfo > available_devices(uint device_type_mask=DEVICE_MASK_ALL)
Definition: device.cpp:488
static DeviceType type_from_string(const char *name)
Definition: device.cpp:433
static string device_capabilities(uint device_type_mask=DEVICE_MASK_ALL)
Definition: device.cpp:573
static vector< DeviceType > available_types()
Definition: device.cpp:469
static string string_from_type(DeviceType type)
Definition: device.cpp:451
bool run()
Definition: merge.cpp:480
string output
Definition: merge.h:38
vector< string > input
Definition: merge.h:36
string error
Definition: merge.h:33
string get_hex()
Definition: util_md5.cpp:366
void append(const uint8_t *data, int size)
Definition: util_md5.cpp:274
static void free_memory()
Definition: shader.cpp:758
static void free_memory()
Definition: util_task.cpp:107
#define DEVICE_MASK(type)
Definition: device.h:70
DeviceTypeMask
Definition: device.h:54
@ DEVICE_MASK_OPTIX
Definition: device.h:58
@ DEVICE_MASK_CPU
Definition: device.h:55
@ DEVICE_MASK_OPENCL
Definition: device.h:56
@ DEVICE_MASK_ALL
Definition: device.h:60
@ DEVICE_MASK_CUDA
Definition: device.h:57
DeviceType
Definition: device.h:43
@ DEVICE_OPENCL
Definition: device.h:46
@ DEVICE_NONE
Definition: device.h:44
@ DEVICE_CUDA
Definition: device.h:47
@ DEVICE_OPTIX
Definition: device.h:50
bool device_opencl_compile_kernel(const vector< string > &parameters)
static KeywordTokenDef keyword_list[]
#define str(s)
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
#define CCL_NAMESPACE_END
#define make_float4(x, y, z, w)
#define make_int2(x, y)
double parameters[NUM_PARAMETERS]
bool debug_flags_sync_from_scene(BL::Scene b_scene)
void * pylong_as_voidptr_typesafe(PyObject *object)
PyObject * pyunicode_from_string(const char *str)
static const VertexNature POINT
Definition: Nature.h:34
Vector< CPUDevice > devices
list of all CPUDevices. for every hardware thread an instance of CPUDevice is created
return ret
void RNA_pointer_create(ID *id, StructRNA *type, void *data, PointerRNA *r_ptr)
Definition: rna_access.c:146
PointerRNA RNA_pointer_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6562
void RNA_id_pointer_create(ID *id, PointerRNA *r_ptr)
Definition: rna_access.c:122
const PointerRNA PointerRNA_NULL
Definition: rna_access.c:71
void RNA_main_pointer_create(struct Main *main, PointerRNA *r_ptr)
Definition: rna_access.c:115
unsigned char uint8_t
Definition: stdint.h:81
BVHLayout bvh_layout
Definition: util_debug.h:81
bool adaptive_compile
Definition: util_debug.h:96
DeviceType device_type
Definition: util_debug.h:155
Definition: DNA_ID.h:273
Definition: BKE_main.h:116
DebugFlags & DebugFlags()
Definition: util_debug.h:205
#define VLOG(severity)
Definition: util_logging.h:50
ccl_device_inline int mod(int x, int m)
Definition: util_math.h:405
ccl_device_inline float3 float4_to_float3(const float4 a)
Definition: util_math.h:415
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)
static CCL_NAMESPACE_BEGIN bool openimagedenoise_supported()
void path_init(const string &path, const string &user_path)
Definition: util_path.cpp:338
bool string_endswith(const string &s, const string &end)