[Bf-blender-cvs] [d7f124f06f3] master: Fix T102845: GPU python crash in background mode

Germano Cavalcante noreply at git.blender.org
Tue Nov 29 17:55:54 CET 2022


Commit: d7f124f06f3fda59523ed05f12d1f4af6a523ba6
Author: Germano Cavalcante
Date:   Tue Nov 29 13:55:37 2022 -0300
Branches: master
https://developer.blender.org/rBd7f124f06f3fda59523ed05f12d1f4af6a523ba6

Fix T102845: GPU python crash in background mode

`BPYGPU_IS_INIT_OR_ERROR_OBJ` is not implemented in all pygpu functions.

Instead of copying and pasting that call across the API when it has no
gpu context, override the methods with one that always reports error.

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

M	source/blender/python/gpu/gpu_py.c
M	source/blender/python/gpu/gpu_py.h
M	source/blender/python/gpu/gpu_py_api.c
M	source/blender/python/gpu/gpu_py_batch.c
M	source/blender/python/gpu/gpu_py_capabilities.c
M	source/blender/python/gpu/gpu_py_element.c
M	source/blender/python/gpu/gpu_py_framebuffer.c
M	source/blender/python/gpu/gpu_py_matrix.c
M	source/blender/python/gpu/gpu_py_offscreen.c
M	source/blender/python/gpu/gpu_py_platform.c
M	source/blender/python/gpu/gpu_py_select.c
M	source/blender/python/gpu/gpu_py_shader.c
M	source/blender/python/gpu/gpu_py_state.c
M	source/blender/python/gpu/gpu_py_texture.c
M	source/blender/python/gpu/gpu_py_types.c
M	source/blender/python/gpu/gpu_py_uniformbuffer.c

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

diff --git a/source/blender/python/gpu/gpu_py.c b/source/blender/python/gpu/gpu_py.c
index 987d2fbd627..34557f0115b 100644
--- a/source/blender/python/gpu/gpu_py.c
+++ b/source/blender/python/gpu/gpu_py.c
@@ -51,16 +51,72 @@ struct PyC_StringEnumItems bpygpu_dataformat_items[] = {
 /** \name Utilities
  * \{ */
 
-bool bpygpu_is_init_or_error(void)
+static const char g_error[] = "GPU API is not available in background mode";
+
+static PyObject *py_error__ml_meth(PyObject *UNUSED(self), PyObject *UNUSED(args))
 {
-  if (!GPU_is_init()) {
-    PyErr_SetString(PyExc_SystemError,
-                    "GPU functions for drawing are not available in background mode");
+  PyErr_SetString(PyExc_SystemError, g_error);
+  Py_RETURN_NONE;
+}
+
+static PyObject *py_error__getter(PyObject *UNUSED(self), void *UNUSED(type))
+{
+  PyErr_SetString(PyExc_SystemError, g_error);
+  Py_RETURN_NONE;
+}
+
+static int py_error__setter(PyObject *UNUSED(self), PyObject *value, void *UNUSED(type))
+{
+  PyErr_SetString(PyExc_SystemError, g_error);
+  return -1;
+}
+
+static PyObject *py_error__tp_new(PyTypeObject *UNUSED(type),
+                                  PyObject *UNUSED(args),
+                                  PyObject *UNUSED(kwds))
+{
+  PyErr_SetString(PyExc_SystemError, g_error);
+  return NULL;
+}
+
+PyObject *bpygpu_create_module(PyModuleDef *module_type)
+{
+  if (!GPU_is_init() && module_type->m_methods) {
+    /* Replace all methods with an error method.
+     * That way when the method is called, an error will appear instead. */
+    for (PyMethodDef *meth = module_type->m_methods; meth->ml_name; meth++) {
+      meth->ml_meth = py_error__ml_meth;
+    }
+  }
 
-    return false;
+  PyObject *module = PyModule_Create(module_type);
+
+  return module;
+}
+
+int bpygpu_finalize_type(PyTypeObject *py_type)
+{
+  if (!GPU_is_init()) {
+    if (py_type->tp_methods) {
+      /* Replace all methods with an error method. */
+      for (PyMethodDef *meth = py_type->tp_methods; meth->ml_name; meth++) {
+        meth->ml_meth = py_error__ml_meth;
+      }
+    }
+    if (py_type->tp_getset) {
+      /* Replace all getters and setter with a functions that always returns error. */
+      for (PyGetSetDef *getset = py_type->tp_getset; getset->name; getset++) {
+        getset->get = py_error__getter;
+        getset->set = py_error__setter;
+      }
+    }
+    if (py_type->tp_new) {
+      /* If initialized, return error. */
+      py_type->tp_new = py_error__tp_new;
+    }
   }
 
-  return true;
+  return PyType_Ready(py_type);
 }
 
 /** \} */
diff --git a/source/blender/python/gpu/gpu_py.h b/source/blender/python/gpu/gpu_py.h
index 2914e370cdc..c0abb60d419 100644
--- a/source/blender/python/gpu/gpu_py.h
+++ b/source/blender/python/gpu/gpu_py.h
@@ -9,15 +9,5 @@
 extern struct PyC_StringEnumItems bpygpu_primtype_items[];
 extern struct PyC_StringEnumItems bpygpu_dataformat_items[];
 
-bool bpygpu_is_init_or_error(void);
-
-#define BPYGPU_IS_INIT_OR_ERROR_OBJ \
-  if (UNLIKELY(!bpygpu_is_init_or_error())) { \
-    return NULL; \
-  } \
-  ((void)0)
-#define BPYGPU_IS_INIT_OR_ERROR_INT \
-  if (UNLIKELY(!bpygpu_is_init_or_error())) { \
-    return -1; \
-  } \
-  ((void)0)
+PyObject *bpygpu_create_module(PyModuleDef *module_type);
+int bpygpu_finalize_type(PyTypeObject *py_type);
diff --git a/source/blender/python/gpu/gpu_py_api.c b/source/blender/python/gpu/gpu_py_api.c
index 8f5897be649..abba2e83cd6 100644
--- a/source/blender/python/gpu/gpu_py_api.c
+++ b/source/blender/python/gpu/gpu_py_api.c
@@ -21,6 +21,7 @@
 #include "gpu_py_state.h"
 #include "gpu_py_types.h"
 
+#include "gpu_py.h"
 #include "gpu_py_api.h" /* Own include. */
 
 /* -------------------------------------------------------------------- */
@@ -48,7 +49,7 @@ PyObject *BPyInit_gpu(void)
   PyObject *submodule;
   PyObject *mod;
 
-  mod = PyModule_Create(&pygpu_module_def);
+  mod = bpygpu_create_module(&pygpu_module_def);
 
   PyModule_AddObject(mod, "types", (submodule = bpygpu_types_init()));
   PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
diff --git a/source/blender/python/gpu/gpu_py_batch.c b/source/blender/python/gpu/gpu_py_batch.c
index a36b1dfd1b5..25fe31322b1 100644
--- a/source/blender/python/gpu/gpu_py_batch.c
+++ b/source/blender/python/gpu/gpu_py_batch.c
@@ -47,8 +47,6 @@ static bool pygpu_batch_is_program_or_error(BPyGPUBatch *self)
 
 static PyObject *pygpu_batch__tp_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *kwds)
 {
-  BPYGPU_IS_INIT_OR_ERROR_OBJ;
-
   const char *exc_str_missing_arg = "GPUBatch.__new__() missing required argument '%s' (pos %d)";
 
   struct PyC_StringEnum prim_type = {bpygpu_primtype_items, GPU_PRIM_NONE};
diff --git a/source/blender/python/gpu/gpu_py_capabilities.c b/source/blender/python/gpu/gpu_py_capabilities.c
index 2345982eb42..80f7df81e9f 100644
--- a/source/blender/python/gpu/gpu_py_capabilities.c
+++ b/source/blender/python/gpu/gpu_py_capabilities.c
@@ -13,6 +13,7 @@
 
 #include "GPU_capabilities.h"
 
+#include "gpu_py.h"
 #include "gpu_py_capabilities.h" /* own include */
 
 /* -------------------------------------------------------------------- */
@@ -315,7 +316,7 @@ PyObject *bpygpu_capabilities_init(void)
 {
   PyObject *submodule;
 
-  submodule = PyModule_Create(&pygpu_capabilities_module_def);
+  submodule = bpygpu_create_module(&pygpu_capabilities_module_def);
 
   return submodule;
 }
diff --git a/source/blender/python/gpu/gpu_py_element.c b/source/blender/python/gpu/gpu_py_element.c
index 46f1d4d49eb..d150a51ba04 100644
--- a/source/blender/python/gpu/gpu_py_element.c
+++ b/source/blender/python/gpu/gpu_py_element.c
@@ -26,8 +26,6 @@
 
 static PyObject *pygpu_IndexBuf__tp_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *kwds)
 {
-  BPYGPU_IS_INIT_OR_ERROR_OBJ;
-
   const char *error_prefix = "IndexBuf.__new__";
   bool ok = true;
 
diff --git a/source/blender/python/gpu/gpu_py_framebuffer.c b/source/blender/python/gpu/gpu_py_framebuffer.c
index 2de8c680b23..acbf15b604d 100644
--- a/source/blender/python/gpu/gpu_py_framebuffer.c
+++ b/source/blender/python/gpu/gpu_py_framebuffer.c
@@ -267,7 +267,6 @@ static PyObject *pygpu_framebuffer__tp_new(PyTypeObject *UNUSED(self),
                                            PyObject *args,
                                            PyObject *kwds)
 {
-  BPYGPU_IS_INIT_OR_ERROR_OBJ;
   if (!GPU_context_active_get()) {
     PyErr_SetString(PyExc_RuntimeError, "No active GPU context found");
     return NULL;
diff --git a/source/blender/python/gpu/gpu_py_matrix.c b/source/blender/python/gpu/gpu_py_matrix.c
index 7d80f763162..414c7751926 100644
--- a/source/blender/python/gpu/gpu_py_matrix.c
+++ b/source/blender/python/gpu/gpu_py_matrix.c
@@ -24,6 +24,7 @@
 #include "GPU_matrix.h"
 #undef USE_GPU_PY_MATRIX_API
 
+#include "gpu_py.h"
 #include "gpu_py_matrix.h" /* own include */
 
 /* -------------------------------------------------------------------- */
@@ -542,9 +543,9 @@ PyObject *bpygpu_matrix_init(void)
 {
   PyObject *submodule;
 
-  submodule = PyModule_Create(&pygpu_matrix_module_def);
+  submodule = bpygpu_create_module(&pygpu_matrix_module_def);
 
-  if (PyType_Ready(&PyGPUMatrixStackContext_Type) < 0) {
+  if (bpygpu_finalize_type(&PyGPUMatrixStackContext_Type) < 0) {
     return NULL;
   }
 
diff --git a/source/blender/python/gpu/gpu_py_offscreen.c b/source/blender/python/gpu/gpu_py_offscreen.c
index 621c6647cb9..2738a4e4784 100644
--- a/source/blender/python/gpu/gpu_py_offscreen.c
+++ b/source/blender/python/gpu/gpu_py_offscreen.c
@@ -211,8 +211,6 @@ static PyObject *pygpu_offscreen__tp_new(PyTypeObject *UNUSED(self),
                                          PyObject *args,
                                          PyObject *kwds)
 {
-  BPYGPU_IS_INIT_OR_ERROR_OBJ;
-
   GPUOffScreen *ofs = NULL;
   int width, height;
   struct PyC_StringEnum pygpu_textureformat = {pygpu_framebuffer_color_texture_formats, GPU_RGBA8};
diff --git a/source/blender/python/gpu/gpu_py_platform.c b/source/blender/python/gpu/gpu_py_platform.c
index 5f9f653a3c4..e908447e02c 100644
--- a/source/blender/python/gpu/gpu_py_platform.c
+++ b/source/blender/python/gpu/gpu_py_platform.c
@@ -14,6 +14,7 @@
 #include "GPU_context.h"
 #include "GPU_platform.h"
 
+#include "gpu_py.h"
 #include "gpu_py_platform.h" /* Own include. */
 
 /* -------------------------------------------------------------------- */
@@ -155,7 +156,7 @@ PyObject *bpygpu_platform_init(void)
 {
   PyObject *submodule;
 
-  submodule = PyModule_Create(&pygpu_platform_module_def);
+  submodule = bpygpu_create_module(&pygpu_platform_module_def);
 
   return submodule;
 }
diff --git a/source/blender/python/gpu/gpu_py_select.c b/source/blender/python/gpu/gpu_py_select.c
index 02e06e0ffd5..dde703fa52d 100644
--- a/source/blender/python/gpu/gpu_py_select.c
+++ b/source/blender/python/gpu/gpu_py_select.c
@@ -20,6 +20,7 @@
 
 #include "GPU_select.h"
 
+#include "gpu_py.h"
 #include "gpu_py_select.h" /* Own include. */
 
 /* -------------------------------------------------------------------- */
@@ -72,7 +73,7 @@ PyObject *bpygpu_select_init(void)
 {
   PyObject *submodule;
 
-  submodule = PyModule_Create(&pygpu_select_module_def);
+  submodule = bpygpu_create_module(&pygpu_select_module_def);
 
   return submodule;
 }
diff --git a/source/blender/python/gpu/gpu_py_shader.c b/source/blender/python/gpu/gpu_py_shader.c
index 7222cb1696a..87f09098d46 100644
--- a/source/blender/python/gpu/gpu_py_shader.c
+++ b/source/blender/python/gpu/gpu_py_shader.c
@@ -95,8 +95,6 @@ static int pygpu_shader_uniform_location_get(GPUShader *shader,
 
 static PyObject *pygpu_shader__tp_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *kwds)
 {
-  BPYGPU_IS_INIT_OR_ERROR_OBJ;
-
   struct {
     const char *vertexcode;
     const char *fragcode;
@@ -835,8 +833,6 @@ PyDoc_STRVAR(
     "   :rtype: :class:`bpy.types.GPUShader`\n");
 static PyObject *pygpu_shader_from_builtin(PyObject *UNUSED(self), PyObject *args, PyObject *kwds)
 {
-  BPYGPU_IS_INIT_OR_ERROR_OBJ;
-
   struct PyC_StringEnum pygpu_bultinshader = {pygpu_shader_builtin_items};
   struct PyC_StringEnum pygpu_config = {pygpu_shader_config_items, GPU_SHADER_CFG_DEFAULT};
 
@@

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list