Fix T99706: Crash rendering with headless builds

When rendering with headless builds, show an error instead of crashing.

Previously GPU_backend_init was called indirectly from
DRW_opengl_context_create, a new function is now called from the window
manager (GPU_backend_init_once), so it's possible to check if the GPU
has a back-end.

This also disables the `bgl` Python module when building WITH_HEADLESS.

Reviewed By: fclem

Ref D15463
This commit is contained in:
Campbell Barton 2022-07-15 22:14:04 +10:00
parent 180db0f752
commit 00dc747702
Notes: blender-bot 2023-02-14 06:00:49 +01:00
Referenced by issue #99706, Null pointer Reference in blender_headless
8 changed files with 45 additions and 7 deletions

View File

@ -574,6 +574,10 @@ mark_as_advanced(
WITH_GPU_BUILDTIME_SHADER_BUILDER
)
if(WITH_HEADLESS)
set(WITH_OPENGL OFF)
endif()
# Metal
if (APPLE)

View File

@ -5,7 +5,7 @@
# to more easily highlight code-paths in other libraries that need to be refactored,
# bf_gpu is allowed to have opengl regardless of this option.
if(NOT WITH_OPENGL AND NOT WITH_METAL_BACKEND)
if(NOT WITH_OPENGL AND NOT WITH_METAL_BACKEND AND NOT WITH_HEADLESS)
add_definitions(-DWITH_OPENGL)
endif()

View File

@ -17,6 +17,7 @@
extern "C" {
#endif
bool GPU_backend_init_once(void);
void GPU_backend_init(eGPUBackendType backend);
void GPU_backend_exit(void);
bool GPU_backend_supported(eGPUBackendType type);

View File

@ -85,10 +85,7 @@ Context *Context::get()
GPUContext *GPU_context_create(void *ghost_window)
{
if (GPUBackend::get() == nullptr) {
/* TODO: move where it make sense. */
GPU_backend_init(GPU_BACKEND_OPENGL);
}
GPU_backend_init_once();
Context *ctx = GPUBackend::get()->context_alloc(ghost_window);
@ -214,6 +211,18 @@ bool GPU_backend_supported(eGPUBackendType type)
}
}
bool GPU_backend_init_once()
{
if (GPUBackend::get() == nullptr) {
if (!GPU_backend_supported(GPU_BACKEND_OPENGL)) {
return false;
}
/* TODO: move where it make sense. */
GPU_backend_init(GPU_BACKEND_OPENGL);
}
return true;
}
void GPU_backend_init(eGPUBackendType backend_type)
{
BLI_assert(g_backend == nullptr);

View File

@ -17,7 +17,6 @@ set(INC_SYS
)
set(SRC
bgl.c
bl_math_py_api.c
blf_py_api.c
bpy_threads.c
@ -27,7 +26,6 @@ set(SRC
py_capi_rna.c
py_capi_utils.c
bgl.h
bl_math_py_api.h
blf_py_api.h
idprop_py_api.h
@ -40,6 +38,14 @@ set(SRC
python_utildefines.h
)
if(WITH_OPENGL)
list(APPEND SRC
bgl.c
bgl.h
)
endif()
set(LIB
${GLEW_LIBRARY}
${PYTHON_LINKFLAGS}

View File

@ -259,7 +259,9 @@ static struct _inittab bpy_internal_modules[] = {
{"mathutils.kdtree", PyInit_mathutils_kdtree},
#endif
{"_bpy_path", BPyInit__bpy_path},
#ifdef WITH_OPENGL
{"bgl", BPyInit_bgl},
#endif
{"blf", BPyInit_blf},
{"bl_math", BPyInit_bl_math},
{"imbuf", BPyInit_imbuf},

View File

@ -46,6 +46,8 @@
#include "DRW_engine.h"
#include "GPU_context.h"
#include "pipeline.h"
#include "render_result.h"
#include "render_types.h"
@ -950,6 +952,16 @@ bool RE_engine_render(Render *re, bool do_all)
re->draw_lock(re->dlh, true);
}
if ((type->flag & RE_USE_GPU_CONTEXT) && (GPU_backend_get_type() == GPU_BACKEND_NONE)) {
/* Clear UI drawing locks. */
if (re->draw_lock) {
re->draw_lock(re->dlh, false);
}
BKE_report(re->reports, RPT_ERROR, "Can not initialize the GPU");
G.is_break = true;
return true;
}
/* update animation here so any render layer animation is applied before
* creating the render result */
if ((re->r.scemode & (R_NO_FRAME_UPDATE | R_BUTS_PREVIEW)) == 0) {

View File

@ -169,6 +169,10 @@ void WM_init_opengl(void)
wm_ghost_init(NULL);
}
if (!GPU_backend_init_once()) {
return;
}
/* Needs to be first to have an OpenGL context bound. */
DRW_opengl_context_create();