Fix #114982: Crash when rendering scene strips

Since b1526dd2c6, viewport renderer sets `G.is_rendering`, but VSE scene
rendering function used this to decide whether to do offscreen opengl
render or use render API. This logic was quite weak.

Use `SeqRenderData::for_render` instead of `G.is_rendering`, since it
explicitly defines whether strip rendering is invoked by F12 render job.

Since offscreen gl rendering rely on `BLI_thread_is_main()` being
true, use this to initialize `do_seq_gl` variable for clarity.

The use of render job path was further conditioned on `G.is_rendering`,
with exception of running headless, but this condition was incorrect.
This condition was reformulated as precondition, which if true, returns
`nullptr` instead of crashing.

Pull Request: https://projects.blender.org/blender/blender/pulls/115079
This commit is contained in:
Richard Antalik
2023-11-23 04:29:09 +01:00
committed by Richard Antalik
parent a13696a242
commit f4e28d4762

View File

@@ -1430,14 +1430,14 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context,
*/
const bool is_rendering = G.is_rendering;
const bool is_background = G.background;
const bool do_seq_gl = is_rendering ? false : (context->scene->r.seq_prev_type) != OB_RENDER;
bool do_seq_gl = !context->for_render && (context->scene->r.seq_prev_type) != OB_RENDER &&
BLI_thread_is_main();
bool have_comp = false;
bool use_gpencil = true;
/* do we need to re-evaluate the frame after rendering? */
bool is_frame_update = false;
Scene *scene;
int is_thread_main = BLI_thread_is_main();
/* don't refer to seq->scene above this point!, it can be nullptr */
if (seq->scene == nullptr) {
@@ -1498,7 +1498,7 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context,
is_frame_update = (orig_data.timeline_frame != scene->r.cfra) ||
(orig_data.subframe != scene->r.subframe);
if ((sequencer_view3d_fn && do_seq_gl && camera) && is_thread_main) {
if ((sequencer_view3d_fn && do_seq_gl && camera)) {
char err_out[256] = "unknown";
int width, height;
BKE_render_resolution(&scene->r, false, &width, &height);
@@ -1544,37 +1544,40 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context,
const int totviews = BKE_scene_multiview_num_views_get(&scene->r);
ImBuf **ibufs_arr;
ibufs_arr = static_cast<ImBuf **>(
MEM_callocN(sizeof(ImBuf *) * totviews, "Sequence Image Views Imbufs"));
/* XXX: this if can be removed when sequence preview rendering uses the job system
/*
* XXX: this if can be removed when sequence preview rendering uses the job system
*
* disable rendered preview for sequencer while rendering -- it's very much possible
* that preview render will went into conflict with final render
* Disable rendered preview for sequencer while rendering - invoked render job will
* conflict with already running render
*
* When rendering from command line renderer is called from main thread, in this
* case it's always safe to render scene here
*/
if (!is_thread_main || is_rendering == false || is_background || context->for_render) {
if (re == nullptr) {
re = RE_NewSceneRender(scene);
}
const float subframe = frame - floorf(frame);
RE_RenderFrame(re,
context->bmain,
scene,
have_comp ? nullptr : view_layer,
camera,
floorf(frame),
subframe,
false);
/* restore previous state after it was toggled on & off by RE_RenderFrame */
G.is_rendering = is_rendering;
if (!context->for_render && (is_rendering && !G.background)) {
goto finally;
}
ibufs_arr = static_cast<ImBuf **>(
MEM_callocN(sizeof(ImBuf *) * totviews, "Sequence Image Views Imbufs"));
if (re == nullptr) {
re = RE_NewSceneRender(scene);
}
const float subframe = frame - floorf(frame);
RE_RenderFrame(re,
context->bmain,
scene,
have_comp ? nullptr : view_layer,
camera,
floorf(frame),
subframe,
false);
/* restore previous state after it was toggled on & off by RE_RenderFrame */
G.is_rendering = is_rendering;
for (int view_id = 0; view_id < totviews; view_id++) {
SeqRenderData localcontext = *context;
RenderResult rres;