Cleanup: Render: Restructure compositor render code
This patch cleanup and refactors the render pipeline compositor render code to deduplicate code and clarify usage. The unused this_scene arguemenet was removed, per-node functions were introduced to simplify loops, C++ Set was used instead of GSet, and scene change is now detected by any rendered scene in the set. Pull Request: https://projects.blender.org/blender/blender/pulls/124028
This commit is contained in:
parent
9f91ca66bc
commit
29451489ae
@ -34,6 +34,7 @@
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_map.hh"
|
||||
#include "BLI_rect.h"
|
||||
#include "BLI_set.hh"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_threads.h"
|
||||
#include "BLI_time.h"
|
||||
@ -1171,39 +1172,50 @@ static void do_render_compositor_scene(Render *re, Scene *sce, int cfra)
|
||||
do_render_engine(resc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper call to detect if this scene needs a render,
|
||||
* or if there's a any render layer to render.
|
||||
*/
|
||||
static bool compositor_needs_render(Scene *sce, const bool this_scene)
|
||||
/* Get the scene referenced by the given node if the node uses its render. Returns nullptr
|
||||
* otherwise. */
|
||||
static Scene *get_scene_referenced_by_node(const bNode *node)
|
||||
{
|
||||
bNodeTree *ntree = sce->nodetree;
|
||||
if (node->flag & NODE_MUTED) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (node->type == CMP_NODE_R_LAYERS) {
|
||||
return reinterpret_cast<Scene *>(node->id);
|
||||
}
|
||||
else if (node->type == CMP_NODE_CRYPTOMATTE &&
|
||||
node->custom1 == CMP_NODE_CRYPTOMATTE_SOURCE_RENDER)
|
||||
{
|
||||
return reinterpret_cast<Scene *>(node->id);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* Returns true if the given scene needs a render, either because it doesn't use the compositor
|
||||
* pipeline and thus needs a simple render, or that its compositor node tree requires the scene to
|
||||
* be rendered. */
|
||||
static bool compositor_needs_render(Scene *scene)
|
||||
{
|
||||
bNodeTree *ntree = scene->nodetree;
|
||||
|
||||
if (ntree == nullptr) {
|
||||
return true;
|
||||
}
|
||||
if (sce->use_nodes == false) {
|
||||
if (scene->use_nodes == false) {
|
||||
return true;
|
||||
}
|
||||
if ((sce->r.scemode & R_DOCOMP) == 0) {
|
||||
if ((scene->r.scemode & R_DOCOMP) == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (const bNode *node : ntree->all_nodes()) {
|
||||
if (node->type == CMP_NODE_R_LAYERS && (node->flag & NODE_MUTED) == 0) {
|
||||
if (this_scene == 0 || node->id == nullptr || node->id == &sce->id) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (node->type == CMP_NODE_CRYPTOMATTE &&
|
||||
node->custom1 == CMP_NODE_CRYPTOMATTE_SOURCE_RENDER && (node->flag & NODE_MUTED) == 0)
|
||||
{
|
||||
if (this_scene == 0 || node->id == nullptr || node->id == &sce->id) {
|
||||
return true;
|
||||
}
|
||||
Scene *node_scene = get_scene_referenced_by_node(node);
|
||||
if (node_scene && node_scene == scene) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1230,62 +1242,43 @@ static bool node_tree_has_composite_output(const bNodeTree *node_tree)
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Render all scenes within a compositor node tree. */
|
||||
/* Render all scenes references by the compositor of the given render's scene. */
|
||||
static void do_render_compositor_scenes(Render *re)
|
||||
{
|
||||
int cfra = re->scene->r.cfra;
|
||||
Scene *restore_scene = re->scene;
|
||||
|
||||
if (re->scene->nodetree == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool changed_scene = false;
|
||||
|
||||
/* now foreach render-result node we do a full render */
|
||||
/* results are stored in a way compositor will find it */
|
||||
GSet *scenes_rendered = BLI_gset_ptr_new(__func__);
|
||||
/* For each node that requires a scene we do a full render. Results are stored in a way
|
||||
* compositor will find it. */
|
||||
blender::Set<Scene *> scenes_rendered;
|
||||
for (bNode *node : re->scene->nodetree->all_nodes()) {
|
||||
if (node->type == CMP_NODE_R_LAYERS && (node->flag & NODE_MUTED) == 0) {
|
||||
if (node->id && node->id != (ID *)re->scene) {
|
||||
Scene *scene = (Scene *)node->id;
|
||||
if (!BLI_gset_haskey(scenes_rendered, scene) &&
|
||||
render_scene_has_layers_to_render(scene, nullptr))
|
||||
{
|
||||
do_render_compositor_scene(re, scene, cfra);
|
||||
BLI_gset_add(scenes_rendered, scene);
|
||||
node->typeinfo->updatefunc(restore_scene->nodetree, node);
|
||||
|
||||
if (scene != re->scene) {
|
||||
changed_scene = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Scene *node_scene = get_scene_referenced_by_node(node);
|
||||
if (!node_scene) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (node->type == CMP_NODE_CRYPTOMATTE &&
|
||||
node->custom1 == CMP_NODE_CRYPTOMATTE_SOURCE_RENDER && (node->flag & NODE_MUTED) == 0)
|
||||
{
|
||||
if (node->id && node->id != (ID *)re->scene) {
|
||||
Scene *scene = (Scene *)node->id;
|
||||
if (!BLI_gset_haskey(scenes_rendered, scene) &&
|
||||
render_scene_has_layers_to_render(scene, nullptr))
|
||||
{
|
||||
do_render_compositor_scene(re, scene, cfra);
|
||||
BLI_gset_add(scenes_rendered, scene);
|
||||
node->typeinfo->updatefunc(restore_scene->nodetree, node);
|
||||
|
||||
if (scene != re->scene) {
|
||||
changed_scene = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* References the current scene, which was already rendered. */
|
||||
if (node_scene == re->scene) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Scene already rendered as required by another node. */
|
||||
if (scenes_rendered.contains(node_scene)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!render_scene_has_layers_to_render(node_scene, nullptr)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
scenes_rendered.add_new(node_scene);
|
||||
do_render_compositor_scene(re, node_scene, re->scene->r.cfra);
|
||||
node->typeinfo->updatefunc(re->scene->nodetree, node);
|
||||
}
|
||||
BLI_gset_free(scenes_rendered, nullptr);
|
||||
|
||||
if (changed_scene) {
|
||||
/* If rendered another scene, switch back to the current scene with compositing nodes. */
|
||||
/* If another scene was rendered, switch back to the current scene. */
|
||||
if (!scenes_rendered.is_empty()) {
|
||||
re->current_scene_update(re->scene);
|
||||
}
|
||||
}
|
||||
@ -1308,7 +1301,7 @@ static void do_render_compositor(Render *re)
|
||||
bNodeTree *ntree = re->pipeline_scene_eval->nodetree;
|
||||
bool update_newframe = false;
|
||||
|
||||
if (compositor_needs_render(re->pipeline_scene_eval, true)) {
|
||||
if (compositor_needs_render(re->pipeline_scene_eval)) {
|
||||
/* render the frames
|
||||
* it could be optimized to render only the needed view
|
||||
* but what if a scene has a different number of views
|
||||
|
Loading…
Reference in New Issue
Block a user