Fix #115043: Compositor crashes for huge render sizes #115299
|
@ -62,6 +62,7 @@
|
||||||
|
|
||||||
#include "UI_view2d.hh"
|
#include "UI_view2d.hh"
|
||||||
|
|
||||||
|
#include "GPU_capabilities.h"
|
||||||
#include "GPU_material.h"
|
#include "GPU_material.h"
|
||||||
|
|
||||||
#include "IMB_imbuf_types.h"
|
#include "IMB_imbuf_types.h"
|
||||||
|
@ -336,6 +337,33 @@ static void compo_completejob(void *cjv)
|
||||||
/** \name Composite Job C API
|
/** \name Composite Job C API
|
||||||
* \{ */
|
* \{ */
|
||||||
|
|
||||||
|
/* Identify if the compositor can run. Currently, this only checks if the compositor is set to GPU
|
||||||
|
* and the render size exceeds what can be allocated as a texture in it. */
|
||||||
|
static bool is_compositing_possible(const bContext *C)
|
||||||
|
{
|
||||||
|
Scene *scene = CTX_data_scene(C);
|
||||||
|
/* CPU compositor can always run. */
|
||||||
|
if (!U.experimental.use_full_frame_compositor ||
|
||||||
|
scene->nodetree->execution_mode != NTREE_EXECUTION_MODE_REALTIME)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int width, height;
|
||||||
|
BKE_render_resolution(&scene->r, false, &width, &height);
|
||||||
|
const int max_texture_size = GPU_max_texture_size();
|
||||||
|
|
||||||
|
/* There is no way to know if the render size is too large except if we actually allocate a test
|
||||||
|
* texture, which we want to avoid due its cost. So we employ a heuristic that so far has worked
|
||||||
|
* with all known GPU drivers. */
|
||||||
|
if (size_t(width) * height > (size_t(max_texture_size) * max_texture_size) / 4) {
|
||||||
|
WM_report(RPT_ERROR, "Render size too large for GPU, use CPU compositor instead");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void ED_node_composite_job(const bContext *C, bNodeTree *nodetree, Scene *scene_owner)
|
void ED_node_composite_job(const bContext *C, bNodeTree *nodetree, Scene *scene_owner)
|
||||||
{
|
{
|
||||||
using namespace blender::ed::space_node;
|
using namespace blender::ed::space_node;
|
||||||
|
@ -344,6 +372,10 @@ void ED_node_composite_job(const bContext *C, bNodeTree *nodetree, Scene *scene_
|
||||||
Scene *scene = CTX_data_scene(C);
|
Scene *scene = CTX_data_scene(C);
|
||||||
ViewLayer *view_layer = CTX_data_view_layer(C);
|
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||||
|
|
||||||
|
if (!is_compositing_possible(C)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* See #32272. */
|
/* See #32272. */
|
||||||
if (G.is_rendering) {
|
if (G.is_rendering) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -84,6 +84,7 @@
|
||||||
#include "SEQ_relations.hh"
|
#include "SEQ_relations.hh"
|
||||||
#include "SEQ_render.hh"
|
#include "SEQ_render.hh"
|
||||||
|
|
||||||
|
#include "GPU_capabilities.h"
|
||||||
#include "GPU_context.h"
|
#include "GPU_context.h"
|
||||||
#include "WM_api.hh"
|
#include "WM_api.hh"
|
||||||
#include "wm_window.hh"
|
#include "wm_window.hh"
|
||||||
|
@ -1628,6 +1629,32 @@ static int check_compositor_output(Scene *scene)
|
||||||
return node_tree_has_compositor_output(scene->nodetree);
|
return node_tree_has_compositor_output(scene->nodetree);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Identify if the compositor can run on the GPU. Currently, this only checks if the compositor is
|
||||||
|
* set to GPU and the render size exceeds what can be allocated as a texture in it. */
|
||||||
|
static bool is_compositing_possible_on_gpu(Scene *scene, ReportList *reports)
|
||||||
|
{
|
||||||
|
/* CPU compositor can always run. */
|
||||||
|
if (!U.experimental.use_full_frame_compositor ||
|
||||||
|
scene->nodetree->execution_mode != NTREE_EXECUTION_MODE_REALTIME)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int width, height;
|
||||||
|
BKE_render_resolution(&scene->r, false, &width, &height);
|
||||||
|
const int max_texture_size = GPU_max_texture_size();
|
||||||
|
|
||||||
|
/* There is no way to know if the render size is too large except if we actually allocate a test
|
||||||
|
* texture, which we want to avoid due its cost. So we employ a heuristic that so far has worked
|
||||||
|
* with all known GPU drivers. */
|
||||||
|
if (size_t(width) * height > (size_t(max_texture_size) * max_texture_size) / 4) {
|
||||||
|
BKE_report(reports, RPT_ERROR, "Render size too large for GPU, use CPU compositor instead");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool RE_is_rendering_allowed(Scene *scene,
|
bool RE_is_rendering_allowed(Scene *scene,
|
||||||
ViewLayer *single_layer,
|
ViewLayer *single_layer,
|
||||||
Object *camera_override,
|
Object *camera_override,
|
||||||
|
@ -1661,6 +1688,10 @@ bool RE_is_rendering_allowed(Scene *scene,
|
||||||
BKE_report(reports, RPT_ERROR, "No render output node in scene");
|
BKE_report(reports, RPT_ERROR, "No render output node in scene");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!is_compositing_possible_on_gpu(scene, reports)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* Regular Render */
|
/* Regular Render */
|
||||||
|
|
Loading…
Reference in New Issue