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
This commit is contained in:
Jeroen Bakker
2025-02-20 11:18:26 +01:00
parent 0bb750ee84
commit b1eaf58aa4
4 changed files with 45 additions and 8 deletions

View File

@@ -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_.overscan = overscan_pixels_get(inst_.camera.overscan(), data_.render_extent);
data_.render_extent += data_.overscan * 2; 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); data_.filter_radius = clamp_f(scene.r.gauss, 0.0f, 100.0f);
if (sampling.sample_count() == 1) { if (sampling.sample_count() == 1) {
/* Disable filtering if sample count is 1. */ /* Disable filtering if sample count is 1. */

View File

@@ -91,6 +91,7 @@ class Film {
eViewLayerEEVEEPassType viewport_compositor_enabled_passes_ = eViewLayerEEVEEPassType(0); eViewLayerEEVEEPassType viewport_compositor_enabled_passes_ = eViewLayerEEVEEPassType(0);
PassCategory enabled_categories_ = PassCategory(0); PassCategory enabled_categories_ = PassCategory(0);
bool use_reprojection_ = false; bool use_reprojection_ = false;
bool is_valid_render_extent_ = true;
public: public:
Film(Instance &inst, FilmData &data) : inst_(inst), data_(data){}; Film(Instance &inst, FilmData &data) : inst_(inst), data_(data){};
@@ -130,6 +131,10 @@ class Film {
{ {
return data_.render_extent; 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). */ /** Size and offset of the film (taking into account render region). */
int2 film_extent_get() const int2 film_extent_get() const

View File

@@ -75,6 +75,7 @@ void Instance::init(const int2 &output_res,
shaders_are_ready_ = shaders.is_ready(is_image_render()); shaders_are_ready_ = shaders.is_ready(is_image_render());
if (!shaders_are_ready_) { if (!shaders_are_ready_) {
skip_render_ = true;
return; return;
} }
@@ -125,7 +126,8 @@ void Instance::init(const int2 &output_res,
/* Pre-compile specialization constants in parallel (if supported). */ /* Pre-compile specialization constants in parallel (if supported). */
shaders.precompile_specializations( shaders.precompile_specializations(
render_buffers.data.shadow_id, shadows.get_data().ray_count, shadows.get_data().step_count); 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) void Instance::init_light_bake(Depsgraph *depsgraph, draw::Manager *manager)
@@ -200,7 +202,7 @@ void Instance::view_update()
void Instance::begin_sync() void Instance::begin_sync()
{ {
if (!shaders_are_ready_) { if (skip_render_) {
return; return;
} }
@@ -244,7 +246,7 @@ void Instance::begin_sync()
void Instance::object_sync(ObjectRef &ob_ref) void Instance::object_sync(ObjectRef &ob_ref)
{ {
if (!shaders_are_ready_) { if (skip_render_) {
return; return;
} }
@@ -320,7 +322,7 @@ void Instance::object_sync_render(void *instance_,
void Instance::end_sync() void Instance::end_sync()
{ {
if (!shaders_are_ready_) { if (skip_render_) {
return; 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) 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) */ /* TODO: Break on RE_engine_test_break(engine) */
while (!sampling.finished()) { while (!sampling.finished()) {
this->render_sample(); this->render_sample();
@@ -558,11 +567,13 @@ void Instance::render_frame(RenderEngine *engine, RenderLayer *render_layer, con
void Instance::draw_viewport() void Instance::draw_viewport()
{ {
if (!shaders_are_ready_) { if (skip_render_) {
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
GPU_framebuffer_clear_color_depth(dfbl->default_fb, float4(0.0f), 1.0f); GPU_framebuffer_clear_color_depth(dfbl->default_fb, float4(0.0f), 1.0f);
info_append_i18n("Compiling EEVEE engine shaders"); if (!shaders_are_ready_) {
DRW_viewport_request_redraw(); info_append_i18n("Compiling EEVEE engine shaders");
DRW_viewport_request_redraw();
}
return; return;
} }
@@ -599,6 +610,9 @@ void Instance::draw_viewport()
void Instance::draw_viewport_image_render() void Instance::draw_viewport_image_render()
{ {
if (skip_render_) {
return;
}
while (!sampling.finished_viewport()) { while (!sampling.finished_viewport()) {
this->render_sample(); this->render_sample();
} }
@@ -611,6 +625,9 @@ void Instance::draw_viewport_image_render()
void Instance::store_metadata(RenderResult *render_result) void Instance::store_metadata(RenderResult *render_result)
{ {
if (skip_render_) {
return;
}
cryptomatte.store_metadata(render_result); cryptomatte.store_metadata(render_result);
} }

View File

@@ -83,8 +83,8 @@ class Instance {
uint64_t depsgraph_last_update_ = 0; uint64_t depsgraph_last_update_ = 0;
bool overlays_enabled_ = false; bool overlays_enabled_ = false;
bool shaders_are_ready_ = true; bool shaders_are_ready_ = true;
bool skip_render_ = false;
/** Info string displayed at the top of the render / viewport, or the console when baking. */ /** Info string displayed at the top of the render / viewport, or the console when baking. */
std::string info_ = ""; std::string info_ = "";