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:
authorCampbell Barton <campbell@blender.org>2022-03-08 14:07:59 +0300
committerCampbell Barton <campbell@blender.org>2022-03-08 14:15:12 +0300
commit73dc8c24e44ba8b462f88c1c629a84c98979ef41 (patch)
tree4b3cb93544a04a319ac79b8bf91e94cb76c201af
parentf76f48be23e04dbbbe313e428636cfcbcf2be59c (diff)
PyAPI: optimize depsgraph use in PyDrivers
Avoid re-creating & freeing the depsgraph for every driver evaluation. Now the depsgraph is kept in the name-space (matching self), only re-created when the value changes. In a contrived test-case with many drivers this gave ~15% overall speedup for animation playback.
-rw-r--r--source/blender/python/intern/bpy_driver.c74
-rw-r--r--source/blender/python/intern/bpy_intern_string.c4
-rw-r--r--source/blender/python/intern/bpy_intern_string.h1
3 files changed, 41 insertions, 38 deletions
diff --git a/source/blender/python/intern/bpy_driver.c b/source/blender/python/intern/bpy_driver.c
index e2b6b2bec29..68018d22753 100644
--- a/source/blender/python/intern/bpy_driver.c
+++ b/source/blender/python/intern/bpy_driver.c
@@ -162,9 +162,11 @@ static struct {
/* borrowed reference to the 'self' in 'bpy_pydriver_Dict'
* keep for as long as the same self is used. */
PyObject *self;
+ BPy_StructRNA *depsgraph;
} g_pydriver_state_prev = {
.evaltime = FLT_MAX,
.self = NULL,
+ .depsgraph = NULL,
};
static void bpy_pydriver_namespace_update_frame(const float evaltime)
@@ -199,6 +201,38 @@ static void bpy_pydriver_namespace_clear_self(void)
}
}
+static PyObject *bpy_pydriver_depsgraph_as_pyobject(struct Depsgraph *depsgraph)
+{
+ struct PointerRNA depsgraph_ptr;
+ RNA_pointer_create(NULL, &RNA_Depsgraph, depsgraph, &depsgraph_ptr);
+ return pyrna_struct_CreatePyObject(&depsgraph_ptr);
+}
+
+/**
+ * Adds a variable 'depsgraph' to the name-space. This can then be used to obtain evaluated
+ * data-blocks, and the current view layer and scene. See T75553.
+ */
+static void bpy_pydriver_namespace_update_depsgraph(struct Depsgraph *depsgraph)
+{
+ /* This should never happen, but it's probably better to have None in Python
+ * than a NULL-wrapping Depsgraph Python struct. */
+ BLI_assert(depsgraph != NULL);
+ if (UNLIKELY(depsgraph == NULL)) {
+ PyDict_SetItem(bpy_pydriver_Dict, bpy_intern_str_depsgraph, Py_None);
+ g_pydriver_state_prev.depsgraph = NULL;
+ return;
+ }
+
+ if ((g_pydriver_state_prev.depsgraph == NULL) ||
+ ((depsgraph != g_pydriver_state_prev.depsgraph->ptr.data))) {
+ PyObject *item = bpy_pydriver_depsgraph_as_pyobject(depsgraph);
+ PyDict_SetItem(bpy_pydriver_Dict, bpy_intern_str_depsgraph, item);
+ Py_DECREF(item);
+
+ g_pydriver_state_prev.depsgraph = (BPy_StructRNA *)item;
+ }
+}
+
void BPY_driver_reset(void)
{
PyGILState_STATE gilstate;
@@ -226,6 +260,7 @@ void BPY_driver_reset(void)
/* freed when clearing driver dict */
g_pydriver_state_prev.self = NULL;
+ g_pydriver_state_prev.depsgraph = NULL;
if (use_gil) {
PyGILState_Release(gilstate);
@@ -369,41 +404,6 @@ static bool bpy_driver_secure_bytecode_validate(PyObject *expr_code, PyObject *d
}
#endif /* USE_BYTECODE_WHITELIST */
-
-static PyObject *bpy_pydriver_depsgraph_as_pyobject(struct Depsgraph *depsgraph)
-{
- /* This should never happen, but it's probably better to have None in Python
- * than a NULL-wrapping Depsgraph py struct. */
- BLI_assert(depsgraph != NULL);
- if (depsgraph == NULL) {
- Py_RETURN_NONE;
- }
-
- struct PointerRNA depsgraph_ptr;
- RNA_pointer_create(NULL, &RNA_Depsgraph, depsgraph, &depsgraph_ptr);
- return pyrna_struct_CreatePyObject(&depsgraph_ptr);
-}
-
-/**
- * Adds a variable 'depsgraph' to the driver variables. This can then be used to obtain evaluated
- * data-blocks, and the current view layer and scene. See T75553.
- */
-static void bpy_pydriver_namespace_add_depsgraph(PyObject *driver_vars,
- struct Depsgraph *depsgraph)
-{
- PyObject *py_depsgraph = bpy_pydriver_depsgraph_as_pyobject(depsgraph);
- const char *depsgraph_variable_name = "depsgraph";
-
- if (PyDict_SetItemString(driver_vars, depsgraph_variable_name, py_depsgraph) == -1) {
- fprintf(stderr,
- "\tBPY_driver_eval() - couldn't add variable '%s' to namespace\n",
- depsgraph_variable_name);
- PyErr_Print();
- PyErr_Clear();
- }
- Py_DECREF(py_depsgraph);
-}
-
float BPY_driver_exec(struct PathResolvedRNA *anim_rna,
ChannelDriver *driver,
ChannelDriver *driver_orig,
@@ -489,6 +489,8 @@ float BPY_driver_exec(struct PathResolvedRNA *anim_rna,
bpy_pydriver_namespace_clear_self();
}
+ bpy_pydriver_namespace_update_depsgraph(anim_eval_context->depsgraph);
+
if (driver_orig->expr_comp == NULL) {
driver_orig->flag |= DRIVER_FLAG_RECOMPILE;
}
@@ -613,8 +615,6 @@ float BPY_driver_exec(struct PathResolvedRNA *anim_rna,
}
#endif /* USE_BYTECODE_WHITELIST */
- bpy_pydriver_namespace_add_depsgraph(driver_vars, anim_eval_context->depsgraph);
-
#if 0 /* slow, with this can avoid all Py_CompileString above. */
/* execute expression to get a value */
retval = PyRun_String(expr, Py_eval_input, bpy_pydriver_Dict, driver_vars);
diff --git a/source/blender/python/intern/bpy_intern_string.c b/source/blender/python/intern/bpy_intern_string.c
index 1cf8f3b65a0..817494cb70a 100644
--- a/source/blender/python/intern/bpy_intern_string.c
+++ b/source/blender/python/intern/bpy_intern_string.c
@@ -14,7 +14,7 @@
#include "BLI_utildefines.h"
-static PyObject *bpy_intern_str_arr[16];
+static PyObject *bpy_intern_str_arr[17];
PyObject *bpy_intern_str___annotations__;
PyObject *bpy_intern_str___doc__;
@@ -31,6 +31,7 @@ PyObject *bpy_intern_str_frame;
PyObject *bpy_intern_str_properties;
PyObject *bpy_intern_str_register;
PyObject *bpy_intern_str_self;
+PyObject *bpy_intern_str_depsgraph;
PyObject *bpy_intern_str_unregister;
void bpy_intern_string_init(void)
@@ -58,6 +59,7 @@ void bpy_intern_string_init(void)
BPY_INTERN_STR(bpy_intern_str_properties, "properties");
BPY_INTERN_STR(bpy_intern_str_register, "register");
BPY_INTERN_STR(bpy_intern_str_self, "self");
+ BPY_INTERN_STR(bpy_intern_str_depsgraph, "depsgraph");
BPY_INTERN_STR(bpy_intern_str_unregister, "unregister");
#undef BPY_INTERN_STR
diff --git a/source/blender/python/intern/bpy_intern_string.h b/source/blender/python/intern/bpy_intern_string.h
index 1d74e8c31c5..cc8bf8a6f3b 100644
--- a/source/blender/python/intern/bpy_intern_string.h
+++ b/source/blender/python/intern/bpy_intern_string.h
@@ -28,6 +28,7 @@ extern PyObject *bpy_intern_str_frame;
extern PyObject *bpy_intern_str_properties;
extern PyObject *bpy_intern_str_register;
extern PyObject *bpy_intern_str_self;
+extern PyObject *bpy_intern_str_depsgraph;
extern PyObject *bpy_intern_str_unregister;
#ifdef __cplusplus