From b1eaf58aa4fc777e175ea0c6ad20969d9a5b21b9 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Thu, 20 Feb 2025 11:18:26 +0100 Subject: [PATCH] Fix #134586: EEVEE: Crash when rendering large resolutions EEVEE crashes when it is not able to allocate buffers. Previously we had a message showing to the user that it tries to allocate a texture larger than supported by the GPU. But was not implemented for EEVEE-next. This fix will add back this error message. ![image.png](/attachments/723c10a4-2b44-49c4-a30f-6e8178055d8a) Pull Request: https://projects.blender.org/blender/blender/pulls/134725 --- .../draw/engines/eevee_next/eevee_film.cc | 15 +++++++++ .../draw/engines/eevee_next/eevee_film.hh | 5 +++ .../draw/engines/eevee_next/eevee_instance.cc | 31 ++++++++++++++----- .../draw/engines/eevee_next/eevee_instance.hh | 2 +- 4 files changed, 45 insertions(+), 8 deletions(-) diff --git a/source/blender/draw/engines/eevee_next/eevee_film.cc b/source/blender/draw/engines/eevee_next/eevee_film.cc index 74b73cd5baa..889ab6c6f49 100644 --- a/source/blender/draw/engines/eevee_next/eevee_film.cc +++ b/source/blender/draw/engines/eevee_next/eevee_film.cc @@ -331,6 +331,21 @@ void Film::init(const int2 &extent, const rcti *output_rect) data_.overscan = overscan_pixels_get(inst_.camera.overscan(), data_.render_extent); data_.render_extent += data_.overscan * 2; + is_valid_render_extent_ = data_.render_extent.x <= GPU_max_texture_size() && + data_.render_extent.y <= GPU_max_texture_size(); + if (!is_valid_render_extent_) { + inst_.info_append_i18n( + "Required render size ({}px) is larger than reported texture size limit ({}px).", + max_ii(data_.render_extent.x, data_.render_extent.y), + GPU_max_texture_size()); + + data_.extent = int2(4, 4); + data_.render_extent = int2(4, 4); + data_.extent_inv = 1.0f / float2(data_.extent); + data_.offset = int2(0, 0); + data_.overscan = 0; + } + data_.filter_radius = clamp_f(scene.r.gauss, 0.0f, 100.0f); if (sampling.sample_count() == 1) { /* Disable filtering if sample count is 1. */ diff --git a/source/blender/draw/engines/eevee_next/eevee_film.hh b/source/blender/draw/engines/eevee_next/eevee_film.hh index 57b0c966091..3e3305db952 100644 --- a/source/blender/draw/engines/eevee_next/eevee_film.hh +++ b/source/blender/draw/engines/eevee_next/eevee_film.hh @@ -91,6 +91,7 @@ class Film { eViewLayerEEVEEPassType viewport_compositor_enabled_passes_ = eViewLayerEEVEEPassType(0); PassCategory enabled_categories_ = PassCategory(0); bool use_reprojection_ = false; + bool is_valid_render_extent_ = true; public: Film(Instance &inst, FilmData &data) : inst_(inst), data_(data){}; @@ -130,6 +131,10 @@ class Film { { return data_.render_extent; } + inline bool is_valid_render_extent() const + { + return is_valid_render_extent_; + } /** Size and offset of the film (taking into account render region). */ int2 film_extent_get() const diff --git a/source/blender/draw/engines/eevee_next/eevee_instance.cc b/source/blender/draw/engines/eevee_next/eevee_instance.cc index 8a568c1e8c9..7a5abe3c59e 100644 --- a/source/blender/draw/engines/eevee_next/eevee_instance.cc +++ b/source/blender/draw/engines/eevee_next/eevee_instance.cc @@ -75,6 +75,7 @@ void Instance::init(const int2 &output_res, shaders_are_ready_ = shaders.is_ready(is_image_render()); if (!shaders_are_ready_) { + skip_render_ = true; return; } @@ -125,7 +126,8 @@ void Instance::init(const int2 &output_res, /* Pre-compile specialization constants in parallel (if supported). */ shaders.precompile_specializations( render_buffers.data.shadow_id, shadows.get_data().ray_count, shadows.get_data().step_count); - shaders_are_ready_ = shaders.is_ready(is_image_render()); + shaders_are_ready_ = shaders.is_ready(is_image_render()) || !film.is_valid_render_extent(); + skip_render_ = !shaders_are_ready_ || !film.is_valid_render_extent(); } void Instance::init_light_bake(Depsgraph *depsgraph, draw::Manager *manager) @@ -200,7 +202,7 @@ void Instance::view_update() void Instance::begin_sync() { - if (!shaders_are_ready_) { + if (skip_render_) { return; } @@ -244,7 +246,7 @@ void Instance::begin_sync() void Instance::object_sync(ObjectRef &ob_ref) { - if (!shaders_are_ready_) { + if (skip_render_) { return; } @@ -320,7 +322,7 @@ void Instance::object_sync_render(void *instance_, void Instance::end_sync() { - if (!shaders_are_ready_) { + if (skip_render_) { return; } @@ -507,6 +509,13 @@ void Instance::render_read_result(RenderLayer *render_layer, const char *view_na void Instance::render_frame(RenderEngine *engine, RenderLayer *render_layer, const char *view_name) { + if (skip_render_) { + if (!info_.empty()) { + RE_engine_set_error_message(engine, info_.c_str()); + info_ = ""; + } + return; + } /* TODO: Break on RE_engine_test_break(engine) */ while (!sampling.finished()) { this->render_sample(); @@ -558,11 +567,13 @@ void Instance::render_frame(RenderEngine *engine, RenderLayer *render_layer, con void Instance::draw_viewport() { - if (!shaders_are_ready_) { + if (skip_render_) { DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); GPU_framebuffer_clear_color_depth(dfbl->default_fb, float4(0.0f), 1.0f); - info_append_i18n("Compiling EEVEE engine shaders"); - DRW_viewport_request_redraw(); + if (!shaders_are_ready_) { + info_append_i18n("Compiling EEVEE engine shaders"); + DRW_viewport_request_redraw(); + } return; } @@ -599,6 +610,9 @@ void Instance::draw_viewport() void Instance::draw_viewport_image_render() { + if (skip_render_) { + return; + } while (!sampling.finished_viewport()) { this->render_sample(); } @@ -611,6 +625,9 @@ void Instance::draw_viewport_image_render() void Instance::store_metadata(RenderResult *render_result) { + if (skip_render_) { + return; + } cryptomatte.store_metadata(render_result); } diff --git a/source/blender/draw/engines/eevee_next/eevee_instance.hh b/source/blender/draw/engines/eevee_next/eevee_instance.hh index 4c870c74ba3..41dad1d9a92 100644 --- a/source/blender/draw/engines/eevee_next/eevee_instance.hh +++ b/source/blender/draw/engines/eevee_next/eevee_instance.hh @@ -83,8 +83,8 @@ class Instance { uint64_t depsgraph_last_update_ = 0; bool overlays_enabled_ = false; - bool shaders_are_ready_ = true; + bool skip_render_ = false; /** Info string displayed at the top of the render / viewport, or the console when baking. */ std::string info_ = "";