44 if (
object == Py_None) {
47 return PyLong_AsVoidPtr(
object);
53 return PyUnicode_DecodeUTF8(
str, strlen(
str),
"ignore");
88 *python_thread_state = (
void *)PyEval_SaveThread();
93 PyEval_RestoreThread((PyThreadState *)*python_thread_state);
94 *python_thread_state =
nullptr;
99 const char *
result = PyUnicode_AsUTF8(py_str);
107 if (PyBytes_Check(py_str)) {
108 return PyBytes_AS_STRING(py_str);
111 *coerce = PyUnicode_EncodeFSDefault(py_str);
113 return PyBytes_AS_STRING(*coerce);
128 if (!PyArg_ParseTuple(args,
"OOi", &path, &user_path, &headless)) {
132 PyObject *path_coerce =
nullptr;
133 PyObject *user_path_coerce =
nullptr;
136 Py_XDECREF(path_coerce);
137 Py_XDECREF(user_path_coerce);
160 PyObject *pypreferences;
168 if (!PyArg_ParseTuple(args,
186 nullptr, &RNA_RenderEngine, PyLong_AsVoidPtr(pyengine));
187 BL::RenderEngine engine(engineptr);
190 nullptr, &RNA_Preferences, PyLong_AsVoidPtr(pypreferences));
191 BL::Preferences preferences(preferencesptr);
194 BL::BlendData
data(dataptr);
197 bScreen, &RNA_Region, pylong_as_voidptr_typesafe(pyregion));
198 BL::Region region(regionptr);
201 bScreen, &RNA_SpaceView3D, pylong_as_voidptr_typesafe(pyv3d));
202 BL::SpaceView3D v3d(v3dptr);
205 bScreen, &RNA_RegionView3D, pylong_as_voidptr_typesafe(pyrv3d));
206 BL::RegionView3D rv3d(rv3dptr);
213 const int width = region.width();
214 const int height = region.height();
223 return PyLong_FromVoidPtr(session);
236 PyObject *pydepsgraph;
238 if (!PyArg_ParseTuple(args,
"OO", &pysession, &pydepsgraph)) {
245 nullptr, &RNA_Depsgraph, (
ID *)PyLong_AsVoidPtr(pydepsgraph));
246 BL::Depsgraph b_depsgraph(depsgraphptr);
251 session->
render(b_depsgraph);
262 if (!PyArg_ParseTuple(args,
"O", &pysession)) {
280 PyObject *py_session;
283 PyObject *py_space_image;
285 if (!PyArg_ParseTuple(args,
"OOOO", &py_session, &py_graph, &py_screen, &py_space_image)) {
291 ID *b_screen = (
ID *)PyLong_AsVoidPtr(py_screen);
294 b_screen, &RNA_SpaceImageEditor, pylong_as_voidptr_typesafe(py_space_image));
295 BL::SpaceImageEditor b_space_image(b_space_image_ptr);
297 session->
draw(b_space_image);
306 PyObject *pydepsgraph;
308 const char *pass_type;
313 if (!PyArg_ParseTuple(args,
329 nullptr, &RNA_Depsgraph, PyLong_AsVoidPtr(pydepsgraph));
330 BL::Depsgraph b_depsgraph(depsgraphptr);
333 BL::Object b_object(objectptr);
337 session->
bake(b_depsgraph, b_object, pass_type, pass_filter, width, height);
351 if (!PyArg_ParseTuple(args,
"OOOO", &pysession, &pygraph, &pyv3d, &pyrv3d)) {
357 if (PyLong_AsVoidPtr(pyrv3d)) {
362 session->
view_draw(viewport[2], viewport[3]);
372 PyObject *pydepsgraph;
374 if (!PyArg_ParseTuple(args,
"OOO", &pysession, &pydata, &pydepsgraph)) {
381 BL::BlendData b_data(dataptr);
384 nullptr, &RNA_Depsgraph, PyLong_AsVoidPtr(pydepsgraph));
385 BL::Depsgraph b_depsgraph(depsgraphptr);
399 PyObject *pydepsgraph;
401 if (!PyArg_ParseTuple(args,
"OO", &pysession, &pydepsgraph)) {
408 nullptr, &RNA_Depsgraph, PyLong_AsVoidPtr(pydepsgraph));
409 BL::Depsgraph b_depsgraph(depsgraphptr);
422 const char *type_name;
423 if (!PyArg_ParseTuple(args,
"s", &type_name)) {
429 if ((type ==
DEVICE_NONE) && (strcmp(type_name,
"NONE") != 0)) {
430 PyErr_Format(PyExc_ValueError,
"Device \"%s\" not known.", type_name);
438 PyObject *
ret = PyTuple_New(devices.size());
440 for (
size_t i = 0;
i < devices.size();
i++) {
443 PyObject *device_tuple = PyTuple_New(8);
444 PyTuple_SET_ITEM(device_tuple, 0, pyunicode_from_string(device.
description.c_str()));
445 PyTuple_SET_ITEM(device_tuple, 1, pyunicode_from_string(type_name.c_str()));
446 PyTuple_SET_ITEM(device_tuple, 2, pyunicode_from_string(device.
id.c_str()));
447 PyTuple_SET_ITEM(device_tuple, 3, PyBool_FromLong(device.
has_peer_memory));
453 PyTuple_SET_ITEM(
ret,
i, device_tuple);
461static PyObject *osl_compile_func(PyObject * , PyObject *args)
463 const char *inputfile =
nullptr;
464 const char *outputfile =
nullptr;
466 if (!PyArg_ParseTuple(args,
"ss", &inputfile, &outputfile)) {
471 if (!OSLManager::osl_compile(inputfile, outputfile)) {
482 return pyunicode_from_string(system_info.c_str());
487 if (PyUnicode_Check(pyfilepaths)) {
488 const char *filepath = PyUnicode_AsUTF8(pyfilepaths);
489 filepaths.push_back(filepath);
493 PyObject *sequence = PySequence_Fast(pyfilepaths,
494 "File paths must be a string or sequence of strings");
495 if (sequence ==
nullptr) {
499 for (Py_ssize_t
i = 0;
i < PySequence_Fast_GET_SIZE(sequence);
i++) {
500 PyObject *item = PySequence_Fast_GET_ITEM(sequence,
i);
501 const char *filepath = PyUnicode_AsUTF8(item);
502 if (filepath ==
nullptr) {
503 PyErr_SetString(PyExc_ValueError,
"File paths must be a string or sequence of strings.");
507 filepaths.push_back(filepath);
514static PyObject *
denoise_func(PyObject * , PyObject *args, PyObject *keywords)
517 "preferences",
"scene",
"view_layer",
"input",
"output",
nullptr};
518 PyObject *pypreferences;
520 PyObject *pyviewlayer;
522 PyObject *pyoutput =
nullptr;
524 if (!PyArg_ParseTupleAndKeywords(args,
539 nullptr, &RNA_Preferences, PyLong_AsVoidPtr(pypreferences));
540 BL::Preferences b_preferences(preferencesptr);
543 BL::Scene b_scene(sceneptr);
547 b_preferences, b_scene,
true,
true, preferences_device);
551 (
ID *)PyLong_AsVoidPtr(pyscene), &RNA_ViewLayer, PyLong_AsVoidPtr(pyviewlayer));
552 BL::ViewLayer b_view_layer(viewlayerptr);
555 b_scene, b_view_layer,
true, preferences_device);
576 PyErr_SetString(PyExc_ValueError,
"No input file paths specified.");
580 PyErr_SetString(PyExc_ValueError,
"Number of input and output file paths does not match.");
593 if (!denoiser.
run()) {
594 PyErr_SetString(PyExc_ValueError, denoiser.
error.c_str());
601static PyObject *
merge_func(PyObject * , PyObject *args, PyObject *keywords)
603 static const char *
keyword_list[] = {
"input",
"output",
nullptr};
605 PyObject *pyoutput =
nullptr;
607 if (!PyArg_ParseTupleAndKeywords(
608 args, keywords,
"OO", (
char **)
keyword_list, &pyinput, &pyoutput))
620 if (!PyUnicode_Check(pyoutput)) {
621 PyErr_SetString(PyExc_ValueError,
"Output must be a string.");
624 const string output = PyUnicode_AsUTF8(pyoutput);
632 PyErr_SetString(PyExc_ValueError, merger.
error.c_str());
642 if (!PyArg_ParseTuple(args,
"O", &pyscene)) {
647 const BL::Scene b_scene(sceneptr);
649 debug_flags_sync_from_scene(b_scene);
651 debug_flags_set =
true;
659 if (debug_flags_set) {
660 debug_flags_set =
false;
674 bool has_cuda =
false;
675 bool has_optix =
false;
676 bool has_hip =
false;
677 bool has_metal =
false;
678 bool has_oneapi =
false;
679 bool has_hiprt =
false;
680 for (
const DeviceType device_type : device_types) {
688 PyObject *list = PyTuple_New(6);
689 PyTuple_SET_ITEM(list, 0, PyBool_FromLong(has_cuda));
690 PyTuple_SET_ITEM(list, 1, PyBool_FromLong(has_optix));
691 PyTuple_SET_ITEM(list, 2, PyBool_FromLong(has_hip));
692 PyTuple_SET_ITEM(list, 3, PyBool_FromLong(has_metal));
693 PyTuple_SET_ITEM(list, 4, PyBool_FromLong(has_oneapi));
694 PyTuple_SET_ITEM(list, 5, PyBool_FromLong(has_hiprt));
700 PyObject *override_string = PyObject_Str(arg);
701 string override = PyUnicode_AsUTF8(override_string);
704 bool include_cpu =
false;
705 const string cpu_suffix =
"+CPU";
708 override =
override.substr(0,
override.
length() - cpu_suffix.length());
711 if (
override ==
"CPU") {
714 else if (
override ==
"CUDA") {
717 else if (
override ==
"OPTIX") {
720 else if (
override ==
"HIP") {
723 else if (
override ==
"METAL") {
726 else if (
override ==
"ONEAPI") {
730 LOG_ERROR <<
override <<
" is not a valid Cycles device.";
744# pragma clang diagnostic push
745# pragma clang diagnostic ignored "-Wcast-function-type"
747# pragma GCC diagnostic push
748# pragma GCC diagnostic ignored "-Wcast-function-type"
765 {
"osl_compile", osl_compile_func, METH_VARARGS,
""},
771 {
"denoise", (PyCFunction)
denoise_func, METH_VARARGS | METH_KEYWORDS,
""},
772 {
"merge", (PyCFunction)
merge_func, METH_VARARGS | METH_KEYWORDS,
""},
785 {
nullptr,
nullptr, 0,
nullptr},
790# pragma clang diagnostic pop
792# pragma GCC diagnostic pop
799 "Blender cycles render integration",
812 PyObject *
mod = PyModule_Create(&ccl::module);
820 const int curversion = OSL_LIBRARY_VERSION_CODE;
821 PyModule_AddObjectRef(
mod,
"with_osl", Py_True);
825 Py_BuildValue(
"(iii)", curversion / 10000, (curversion / 100) % 100, curversion % 100));
828 "osl_version_string",
829 PyUnicode_FromFormat(
830 "%2d, %2d, %2d", curversion / 10000, (curversion / 100) % 100, curversion % 100));
832 PyModule_AddObjectRef(
mod,
"with_osl", Py_False);
833 PyModule_AddStringConstant(
mod,
"osl_version",
"unknown");
834 PyModule_AddStringConstant(
mod,
"osl_version_string",
"unknown");
837 if (ccl::guiding_supported()) {
838 PyModule_AddObjectRef(
mod,
"with_path_guiding", Py_True);
841 PyModule_AddObjectRef(
mod,
"with_path_guiding", Py_False);
845 PyModule_AddObjectRef(
mod,
"with_embree", Py_True);
847 PyModule_AddObjectRef(
mod,
"with_embree", Py_False);
850#ifdef WITH_EMBREE_GPU
851 PyModule_AddObjectRef(
mod,
"with_embree_gpu", Py_True);
853 PyModule_AddObjectRef(
mod,
"with_embree_gpu", Py_False);
856 if (ccl::openimagedenoise_supported()) {
857 PyModule_AddObjectRef(
mod,
"with_openimagedenoise", Py_True);
860 PyModule_AddObjectRef(
mod,
"with_openimagedenoise", Py_False);
863#ifdef WITH_CYCLES_DEBUG
864 PyModule_AddObjectRef(
mod,
"with_debug", Py_True);
866 PyModule_AddObjectRef(
mod,
"with_debug", Py_False);
void GPU_viewport_size_get_i(int coords[4])
DeviceInfo blender_device_info(BL::Preferences &b_preferences, BL::Scene &b_scene, bool background, bool preview, DeviceInfo &preferences_device)
BMesh const char void * data
SIMD_FORCE_INLINE btScalar length() const
Return the length of the vector.
static bool print_render_stats
void synchronize(BL::Depsgraph &b_depsgraph)
void * python_thread_state
void bake(BL::Depsgraph &b_depsgraph_, BL::Object &b_object, const string &bake_type, const int bake_filter, const int bake_width, const int bake_height)
void reset_session(BL::BlendData &b_data, BL::Depsgraph &b_depsgraph)
void render(BL::Depsgraph &b_depsgraph)
void draw(BL::SpaceImageEditor &space_image)
void view_draw(const int w, const int h)
void render_frame_finish()
static DeviceTypeMask device_override
static DenoiseParams get_denoise_params(BL::Scene &b_scene, BL::ViewLayer &b_view_layer, bool background, const DeviceInfo &denoise_device)
static void free_memory()
bool has_execution_optimization
DenoiserTypeMask denoisers
bool use_hardware_raytracing
static void free_memory()
static DeviceType type_from_string(const char *name)
static string device_capabilities(const uint device_type_mask=DEVICE_MASK_ALL)
static vector< DeviceType > available_types()
static string string_from_type(DeviceType type)
static vector< DeviceInfo > available_devices(const uint device_type_mask=DEVICE_MASK_ALL)
static void free_memory()
static void free_memory()
static bool get_boolean(PointerRNA &ptr, const char *name)
static int get_enum(PointerRNA &ptr, const char *name, int num_values=-1, int default_value=-1)
DebugFlags & DebugFlagsRef
DebugFlags & DebugFlags()
@ DENOISER_OPENIMAGEDENOISE
#define CCL_NAMESPACE_END
#define DEVICE_MASK(type)
static KeywordTokenDef keyword_list[]
VecBase< float, D > constexpr mod(VecOp< float, D >, VecOp< float, D >) RET
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
void debug_flags_sync_from_scene(BL::Scene b_scene)
void * pylong_as_voidptr_typesafe(PyObject *object)
PyObject * pyunicode_from_string(const char *str)
KernelBVHLayout BVHLayout
void path_init(const string &path, const string &user_path)
static PyObject * init_func(PyObject *, PyObject *args)
static PyObject * merge_func(PyObject *, PyObject *args, PyObject *keywords)
static PyObject * sync_func(PyObject *, PyObject *args)
static PyObject * denoise_func(PyObject *, PyObject *args, PyObject *keywords)
void python_thread_state_restore(void **python_thread_state)
static PyObject * system_info_func(PyObject *, PyObject *)
static PyObject * set_device_override_func(PyObject *, PyObject *arg)
static PyObject * free_func(PyObject *, PyObject *value)
CCL_NAMESPACE_END void * CCL_python_module_init()
static struct PyModuleDef module
static bool image_parse_filepaths(PyObject *pyfilepaths, vector< string > &filepaths)
static PyMethodDef methods[]
static PyObject * available_devices_func(PyObject *, PyObject *args)
static PyObject * bake_func(PyObject *, PyObject *args)
static PyObject * reset_func(PyObject *, PyObject *args)
static PyObject * view_draw_func(PyObject *, PyObject *args)
static PyObject * enable_print_stats_func(PyObject *, PyObject *)
static PyObject * debug_flags_reset_func(PyObject *, PyObject *)
static PyObject * render_func(PyObject *, PyObject *args)
static PyObject * debug_flags_update_func(PyObject *, PyObject *args)
void python_thread_state_save(void **python_thread_state)
static PyObject * draw_func(PyObject *, PyObject *args)
static PyObject * get_device_types_func(PyObject *, PyObject *)
static const char * PyC_UnicodeAsBytes(PyObject *py_str, PyObject **coerce)
static PyObject * render_frame_finish_func(PyObject *, PyObject *args)
static PyObject * create_func(PyObject *, PyObject *args)
static PyObject * exit_func(PyObject *, PyObject *)
PointerRNA RNA_pointer_get(PointerRNA *ptr, const char *name)
PointerRNA RNA_main_pointer_create(Main *main)
PointerRNA RNA_pointer_create_discrete(ID *id, StructRNA *type, void *data)
PointerRNA RNA_id_pointer_create(ID *id)
bool string_endswith(const string_view s, const string_view end)