Fix T52653: Render output of linked scenes conflicts with other scenes with the same name
The issue was caused by render result identifier only consist of scene name, which could indeed cause conflicts. On the one hand, there are quite some areas in Blender where we need identifier to be unique to properly address things. Usually this is required for sub-data of IDs, like bones. On another hand, it's not that hard to support this particular case and avoid possible frustration. The idea is, we add library name to render identifier for linked scenes. We use library name and not pointer so we preserve render results through undo stack. Reviewers: campbellbarton, mont29, brecht Reviewed By: mont29 Differential Revision: https://developer.blender.org/D2836
This commit is contained in:
parent
09c6c6c486
commit
ff79406404
Notes:
blender-bot
2023-02-14 06:55:40 +01:00
Referenced by issue #52653, Render output of linked scenes conflicts with other scenes with the same name
|
@ -1735,7 +1735,7 @@ static void stampdata(Scene *scene, Object *camera, StampData *stamp_data, int d
|
|||
}
|
||||
|
||||
{
|
||||
Render *re = RE_GetRender(scene->id.name);
|
||||
Render *re = RE_GetSceneRender(scene);
|
||||
RenderStats *stats = re ? RE_GetStats(re) : NULL;
|
||||
|
||||
if (stats && (scene->r.stamp & R_STAMP_RENDERTIME)) {
|
||||
|
@ -2929,7 +2929,7 @@ RenderResult *BKE_image_acquire_renderresult(Scene *scene, Image *ima)
|
|||
}
|
||||
else if (ima->type == IMA_TYPE_R_RESULT) {
|
||||
if (ima->render_slot == ima->last_render_slot)
|
||||
rr = RE_AcquireResultRead(RE_GetRender(scene->id.name));
|
||||
rr = RE_AcquireResultRead(RE_GetSceneRender(scene));
|
||||
else
|
||||
rr = ima->renders[ima->render_slot];
|
||||
|
||||
|
@ -2947,7 +2947,7 @@ void BKE_image_release_renderresult(Scene *scene, Image *ima)
|
|||
}
|
||||
else if (ima->type == IMA_TYPE_R_RESULT) {
|
||||
if (ima->render_slot == ima->last_render_slot)
|
||||
RE_ReleaseResult(RE_GetRender(scene->id.name));
|
||||
RE_ReleaseResult(RE_GetSceneRender(scene));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2967,7 +2967,7 @@ void BKE_image_backup_render(Scene *scene, Image *ima, bool free_current_slot)
|
|||
{
|
||||
/* called right before rendering, ima->renders contains render
|
||||
* result pointers for everything but the current render */
|
||||
Render *re = RE_GetRender(scene->id.name);
|
||||
Render *re = RE_GetSceneRender(scene);
|
||||
int slot = ima->render_slot, last = ima->last_render_slot;
|
||||
|
||||
if (slot != last) {
|
||||
|
@ -3692,7 +3692,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc
|
|||
if (!r_lock)
|
||||
return NULL;
|
||||
|
||||
re = RE_GetRender(iuser->scene->id.name);
|
||||
re = RE_GetSceneRender(iuser->scene);
|
||||
|
||||
channels = 4;
|
||||
layer = iuser->layer;
|
||||
|
|
|
@ -3320,7 +3320,7 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq
|
|||
}
|
||||
}
|
||||
else {
|
||||
Render *re = RE_GetRender(scene->id.name);
|
||||
Render *re = RE_GetSceneRender(scene);
|
||||
const int totviews = BKE_scene_multiview_num_views_get(&scene->r);
|
||||
int i;
|
||||
ImBuf **ibufs_arr;
|
||||
|
@ -3337,7 +3337,7 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq
|
|||
*/
|
||||
if (!is_thread_main || is_rendering == false || is_background || context->eval_ctx->mode == DAG_EVAL_RENDER) {
|
||||
if (re == NULL)
|
||||
re = RE_NewRender(scene->id.name);
|
||||
re = RE_NewSceneRender(scene);
|
||||
|
||||
BKE_scene_update_for_newframe(context->eval_ctx, context->bmain, scene, scene->lay);
|
||||
RE_BlenderFrame(re, context->bmain, scene, NULL, camera, scene->lay, frame, false);
|
||||
|
|
|
@ -41,6 +41,7 @@ void CompositorNode::convertToOperations(NodeConverter &converter, const Composi
|
|||
NodeInput *depthSocket = this->getInputSocket(2);
|
||||
|
||||
CompositorOperation *compositorOperation = new CompositorOperation();
|
||||
compositorOperation->setScene(context.getScene());
|
||||
compositorOperation->setSceneName(context.getScene()->id.name);
|
||||
compositorOperation->setRenderData(context.getRenderData());
|
||||
compositorOperation->setViewName(context.getViewName());
|
||||
|
|
|
@ -176,7 +176,7 @@ void RenderLayersNode::convertToOperations(NodeConverter &converter,
|
|||
const CompositorContext &context) const
|
||||
{
|
||||
Scene *scene = (Scene *)this->getbNode()->id;
|
||||
Render *re = (scene) ? RE_GetRender(scene->id.name) : NULL;
|
||||
Render *re = (scene) ? RE_GetSceneRender(scene) : NULL;
|
||||
|
||||
if (re != NULL) {
|
||||
testRenderLink(converter, context, re);
|
||||
|
|
|
@ -51,6 +51,7 @@ CompositorOperation::CompositorOperation() : NodeOperation()
|
|||
this->m_useAlphaInput = false;
|
||||
this->m_active = false;
|
||||
|
||||
this->m_scene = NULL;
|
||||
this->m_sceneName[0] = '\0';
|
||||
this->m_viewName = NULL;
|
||||
}
|
||||
|
@ -78,7 +79,7 @@ void CompositorOperation::deinitExecution()
|
|||
return;
|
||||
|
||||
if (!isBreaked()) {
|
||||
Render *re = RE_GetRender(this->m_sceneName);
|
||||
Render *re = RE_GetSceneRender(this->m_scene);
|
||||
RenderResult *rr = RE_AcquireResultWrite(re);
|
||||
|
||||
if (rr) {
|
||||
|
@ -217,7 +218,7 @@ void CompositorOperation::determineResolution(unsigned int resolution[2], unsign
|
|||
|
||||
// check actual render resolution with cropping it may differ with cropped border.rendering
|
||||
// FIX for: [31777] Border Crop gives black (easy)
|
||||
Render *re = RE_GetRender(this->m_sceneName);
|
||||
Render *re = RE_GetSceneRender(this->m_scene);
|
||||
if (re) {
|
||||
RenderResult *rr = RE_AcquireResultRead(re);
|
||||
if (rr) {
|
||||
|
|
|
@ -26,11 +26,14 @@
|
|||
#include "BLI_rect.h"
|
||||
#include "BLI_string.h"
|
||||
|
||||
struct Scene;
|
||||
|
||||
/**
|
||||
* @brief Compositor output operation
|
||||
*/
|
||||
class CompositorOperation : public NodeOperation {
|
||||
private:
|
||||
const struct Scene *m_scene;
|
||||
/**
|
||||
* @brief Scene name, used for getting the render output, includes 'SC' prefix.
|
||||
*/
|
||||
|
@ -84,6 +87,7 @@ public:
|
|||
CompositorOperation();
|
||||
const bool isActiveCompositorOutput() const { return this->m_active; }
|
||||
void executeRegion(rcti *rect, unsigned int tileNumber);
|
||||
void setScene(const struct Scene *scene) { m_scene = scene; }
|
||||
void setSceneName(const char *sceneName) { BLI_strncpy(this->m_sceneName, sceneName, sizeof(this->m_sceneName)); }
|
||||
void setViewName(const char *viewName) { this->m_viewName = viewName; }
|
||||
void setRenderData(const RenderData *rd) { this->m_rd = rd; }
|
||||
|
|
|
@ -48,7 +48,7 @@ RenderLayersProg::RenderLayersProg(const char *passName, DataType type, int elem
|
|||
void RenderLayersProg::initExecution()
|
||||
{
|
||||
Scene *scene = this->getScene();
|
||||
Render *re = (scene) ? RE_GetRender(scene->id.name) : NULL;
|
||||
Render *re = (scene) ? RE_GetSceneRender(scene) : NULL;
|
||||
RenderResult *rr = NULL;
|
||||
|
||||
if (re)
|
||||
|
@ -179,7 +179,7 @@ void RenderLayersProg::deinitExecution()
|
|||
void RenderLayersProg::determineResolution(unsigned int resolution[2], unsigned int /*preferredResolution*/[2])
|
||||
{
|
||||
Scene *sce = this->getScene();
|
||||
Render *re = (sce) ? RE_GetRender(sce->id.name) : NULL;
|
||||
Render *re = (sce) ? RE_GetSceneRender(sce) : NULL;
|
||||
RenderResult *rr = NULL;
|
||||
|
||||
resolution[0] = 0;
|
||||
|
|
|
@ -1161,7 +1161,7 @@ static void bake_init_api_data(wmOperator *op, bContext *C, BakeAPIRender *bkr)
|
|||
|
||||
bkr->result = OPERATOR_CANCELLED;
|
||||
|
||||
bkr->render = RE_NewRender(bkr->scene->id.name);
|
||||
bkr->render = RE_NewSceneRender(bkr->scene);
|
||||
|
||||
/* XXX hack to force saving to always be internal. Whether (and how) to support
|
||||
* external saving will be addressed later */
|
||||
|
|
|
@ -305,7 +305,7 @@ static int screen_render_exec(bContext *C, wmOperator *op)
|
|||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
re = RE_NewRender(scene->id.name);
|
||||
re = RE_NewSceneRender(scene);
|
||||
lay_override = (v3d && v3d->lay != scene->lay) ? v3d->lay : 0;
|
||||
|
||||
G.is_break = false;
|
||||
|
@ -964,7 +964,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
|
|||
rj->image = ima;
|
||||
|
||||
/* setup new render */
|
||||
re = RE_NewRender(scene->id.name);
|
||||
re = RE_NewSceneRender(scene);
|
||||
RE_test_break_cb(re, rj, render_breakjob);
|
||||
RE_draw_lock_cb(re, rj, render_drawlock);
|
||||
RE_display_update_cb(re, rj, image_rect_update);
|
||||
|
|
|
@ -681,7 +681,7 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op)
|
|||
}
|
||||
|
||||
/* create render */
|
||||
oglrender->re = RE_NewRender(scene->id.name);
|
||||
oglrender->re = RE_NewSceneRender(scene);
|
||||
|
||||
/* create image and image user */
|
||||
oglrender->ima = BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result");
|
||||
|
|
|
@ -88,7 +88,7 @@ static void draw_render_info(const bContext *C,
|
|||
float zoomy)
|
||||
{
|
||||
RenderResult *rr;
|
||||
Render *re = RE_GetRender(scene->id.name);
|
||||
Render *re = RE_GetSceneRender(scene);
|
||||
RenderData *rd = RE_engine_get_render_data(re);
|
||||
Scene *stats_scene = ED_render_job_get_scene(C);
|
||||
if (stats_scene == NULL) {
|
||||
|
|
|
@ -3632,7 +3632,7 @@ static int render_border_exec(bContext *C, wmOperator *op)
|
|||
{
|
||||
ARegion *ar = CTX_wm_region(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
Render *re = RE_GetRender(scene->id.name);
|
||||
Render *re = RE_GetSceneRender(scene);
|
||||
RenderData *rd;
|
||||
rctf border;
|
||||
|
||||
|
|
|
@ -1321,7 +1321,7 @@ static int node_read_fullsamplelayers_exec(bContext *C, wmOperator *UNUSED(op))
|
|||
Main *bmain = CTX_data_main(C);
|
||||
SpaceNode *snode = CTX_wm_space_node(C);
|
||||
Scene *curscene = CTX_data_scene(C);
|
||||
Render *re = RE_NewRender(curscene->id.name);
|
||||
Render *re = RE_NewSceneRender(curscene);
|
||||
|
||||
WM_cursor_wait(1);
|
||||
RE_MergeFullSample(re, bmain, curscene, snode->nodetree);
|
||||
|
|
|
@ -957,7 +957,7 @@ Render *BlenderStrokeRenderer::RenderScene(Render * /*re*/, bool render)
|
|||
}
|
||||
#endif
|
||||
|
||||
Render *freestyle_render = RE_NewRender(freestyle_scene->id.name);
|
||||
Render *freestyle_render = RE_NewSceneRender(freestyle_scene);
|
||||
|
||||
RE_RenderFreestyleStrokes(freestyle_render, freestyle_bmain, freestyle_scene,
|
||||
render && get_stroke_count() > 0);
|
||||
|
|
|
@ -194,6 +194,10 @@ typedef struct RenderStats {
|
|||
struct Render *RE_NewRender(const char *name);
|
||||
struct Render *RE_GetRender(const char *name);
|
||||
|
||||
struct Scene;
|
||||
struct Render *RE_NewSceneRender(const struct Scene *scene);
|
||||
struct Render *RE_GetSceneRender(const struct Scene *scene);
|
||||
|
||||
/* assign default dummy callbacks */
|
||||
void RE_InitRenderCB(struct Render *re);
|
||||
|
||||
|
|
|
@ -307,7 +307,6 @@ Render *RE_GetRender(const char *name)
|
|||
return re;
|
||||
}
|
||||
|
||||
|
||||
/* if you want to know exactly what has been done */
|
||||
RenderResult *RE_AcquireResultRead(Render *re)
|
||||
{
|
||||
|
@ -514,6 +513,36 @@ Render *RE_NewRender(const char *name)
|
|||
return re;
|
||||
}
|
||||
|
||||
/* MAX_ID_NAME + sizeof(Library->name) + space + null-terminator. */
|
||||
#define MAX_SCENE_RENDER_NAME (MAX_ID_NAME + 1024 + 2)
|
||||
|
||||
static void scene_render_name_get(const Scene *scene,
|
||||
const size_t max_size,
|
||||
char *render_name)
|
||||
{
|
||||
if (ID_IS_LINKED_DATABLOCK(scene)) {
|
||||
BLI_snprintf(render_name, max_size, "%s %s",
|
||||
scene->id.lib->id.name, scene->id.name);
|
||||
}
|
||||
else {
|
||||
BLI_snprintf(render_name, max_size, "%s", scene->id.name);
|
||||
}
|
||||
}
|
||||
|
||||
Render *RE_GetSceneRender(const Scene *scene)
|
||||
{
|
||||
char render_name[MAX_SCENE_RENDER_NAME];
|
||||
scene_render_name_get(scene, sizeof(render_name), render_name);
|
||||
return RE_GetRender(render_name);
|
||||
}
|
||||
|
||||
Render *RE_NewSceneRender(const Scene *scene)
|
||||
{
|
||||
char render_name[MAX_SCENE_RENDER_NAME];
|
||||
scene_render_name_get(scene, sizeof(render_name), render_name);
|
||||
return RE_NewRender(render_name);
|
||||
}
|
||||
|
||||
/* called for new renders and when finishing rendering so
|
||||
* we always have valid callbacks on a render */
|
||||
void RE_InitRenderCB(Render *re)
|
||||
|
@ -1913,7 +1942,7 @@ static void do_render_fields_blur_3d(Render *re)
|
|||
*/
|
||||
static void render_scene(Render *re, Scene *sce, int cfra)
|
||||
{
|
||||
Render *resc = RE_NewRender(sce->id.name);
|
||||
Render *resc = RE_NewSceneRender(sce);
|
||||
int winx = re->winx, winy = re->winy;
|
||||
|
||||
sce->r.cfra = cfra;
|
||||
|
@ -2348,7 +2377,7 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree)
|
|||
tag_scenes_for_render(re);
|
||||
for (sce = re->main->scene.first; sce; sce = sce->id.next) {
|
||||
if (sce->id.tag & LIB_TAG_DOIT) {
|
||||
re1 = RE_GetRender(sce->id.name);
|
||||
re1 = RE_GetSceneRender(sce);
|
||||
|
||||
if (re1 && (re1->r.scemode & R_FULL_SAMPLE)) {
|
||||
if (sample) {
|
||||
|
@ -3858,9 +3887,9 @@ bool RE_ReadRenderResult(Scene *scene, Scene *scenode)
|
|||
scene = scenode;
|
||||
|
||||
/* get render: it can be called from UI with draw callbacks */
|
||||
re = RE_GetRender(scene->id.name);
|
||||
re = RE_GetSceneRender(scene);
|
||||
if (re == NULL)
|
||||
re = RE_NewRender(scene->id.name);
|
||||
re = RE_NewSceneRender(scene);
|
||||
RE_InitState(re, NULL, &scene->r, NULL, winx, winy, &disprect);
|
||||
re->scene = scene;
|
||||
re->scene_color_manage = BKE_scene_check_color_management_enabled(scene);
|
||||
|
|
|
@ -271,6 +271,7 @@ void RE_sample_material_color(
|
|||
int tri_index, struct DerivedMesh *orcoDm, struct Object *ob) RET_NONE
|
||||
/* nodes */
|
||||
struct Render *RE_GetRender(const char *name) RET_NULL
|
||||
struct Render *RE_GetSceneRender(const struct Scene *scene) RET_NULL
|
||||
struct Object *RE_GetCamera(struct Render *re) RET_NULL
|
||||
float RE_lamp_get_data(struct ShadeInput *shi, struct Object *lamp_obj, float col[4], float lv[3], float *dist, float shadow[4]) RET_ZERO
|
||||
const float (*RE_object_instance_get_matrix(struct ObjectInstanceRen *obi, int matrix_id))[4] RET_NULL
|
||||
|
@ -296,6 +297,7 @@ float texture_value_blend(float tex, float out, float fact, float facg, int blen
|
|||
void texture_rgb_blend(float in[3], const float tex[3], const float out[3], float fact, float facg, int blendtype) RET_NONE
|
||||
double elbeemEstimateMemreq(int res, float sx, float sy, float sz, int refine, char *retstr) RET_ZERO
|
||||
struct Render *RE_NewRender(const char *name) RET_NULL
|
||||
struct Render *RE_NewSceneRender(const struct Scene *scene) RET_NULL
|
||||
void RE_SwapResult(struct Render *re, struct RenderResult **rr) RET_NONE
|
||||
void RE_BlenderFrame(struct Render *re, struct Main *bmain, struct Scene *scene, struct SceneRenderLayer *srl, struct Object *camera_override, unsigned int lay_override, int frame, const bool write_still) RET_NONE
|
||||
bool RE_WriteEnvmapResult(struct ReportList *reports, struct Scene *scene, struct EnvMap *env, const char *relpath, const char imtype, float layout[12]) RET_ZERO
|
||||
|
|
|
@ -1362,7 +1362,7 @@ static int arg_handle_render_frame(int argc, const char **argv, void *data)
|
|||
return 1;
|
||||
}
|
||||
|
||||
re = RE_NewRender(scene->id.name);
|
||||
re = RE_NewSceneRender(scene);
|
||||
BLI_begin_threaded_malloc();
|
||||
BKE_reports_init(&reports, RPT_STORE);
|
||||
|
||||
|
@ -1404,7 +1404,7 @@ static int arg_handle_render_animation(int UNUSED(argc), const char **UNUSED(arg
|
|||
Scene *scene = CTX_data_scene(C);
|
||||
if (scene) {
|
||||
Main *bmain = CTX_data_main(C);
|
||||
Render *re = RE_NewRender(scene->id.name);
|
||||
Render *re = RE_NewSceneRender(scene);
|
||||
ReportList reports;
|
||||
BLI_begin_threaded_malloc();
|
||||
BKE_reports_init(&reports, RPT_STORE);
|
||||
|
|
Loading…
Reference in New Issue