[Bf-blender-cvs] [6be8b6af400] blender-v2.90-release: EEVEE: LightCache: Prevent crash when using a lightcache too big

Clément Foucault noreply at git.blender.org
Wed Aug 5 02:34:57 CEST 2020


Commit: 6be8b6af4006e088ac4a2cd8c1adc8f18c04035b
Author: Clément Foucault
Date:   Tue Aug 4 19:52:18 2020 +0200
Branches: blender-v2.90-release
https://developer.blender.org/rB6be8b6af4006e088ac4a2cd8c1adc8f18c04035b

EEVEE: LightCache: Prevent crash when using a lightcache too big

Some implementation have different maximum texture size.
This patch avoid crash when texture allocation fails when:
- trying to bake a lightcache too big for the OpenGL imeplementaion.
- loading a cache from file that is too big for the OpenGL imeplementation.

===================================================================

M	source/blender/blenloader/intern/readfile.c
M	source/blender/draw/engines/eevee/eevee_lightcache.c
M	source/blender/draw/engines/eevee/eevee_lightprobes.c
M	source/blender/draw/engines/eevee/eevee_private.h
M	source/blender/draw/intern/draw_manager_texture.c
M	source/blender/editors/render/render_shading.c
M	source/blender/makesdna/DNA_lightprobe_types.h

===================================================================

diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 9f5e474e479..4abf37e66bc 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -6048,6 +6048,7 @@ static void direct_link_lightcache_texture(BlendDataReader *reader, LightCacheTe
 
 static void direct_link_lightcache(BlendDataReader *reader, LightCache *cache)
 {
+  cache->flag &= ~LIGHTCACHE_NOT_USABLE;
   direct_link_lightcache_texture(reader, &cache->cube_tx);
   direct_link_lightcache_texture(reader, &cache->grid_tx);
 
diff --git a/source/blender/draw/engines/eevee/eevee_lightcache.c b/source/blender/draw/engines/eevee/eevee_lightcache.c
index 78fcd28eb5d..92bb9227e13 100644
--- a/source/blender/draw/engines/eevee/eevee_lightcache.c
+++ b/source/blender/draw/engines/eevee/eevee_lightcache.c
@@ -228,7 +228,14 @@ void EEVEE_lightcache_info_update(SceneEEVEE *eevee)
 
     if (lcache->cube_tx.tex_size[2] > GPU_max_texture_layers()) {
       BLI_strncpy(eevee->light_cache_info,
-                  TIP_("Error: Light cache is too big for your GPU to be loaded"),
+                  TIP_("Error: Light cache is too big for the GPU to be loaded"),
+                  sizeof(eevee->light_cache_info));
+      return;
+    }
+
+    if (lcache->flag & LIGHTCACHE_INVALID) {
+      BLI_strncpy(eevee->light_cache_info,
+                  TIP_("Error: Light cache dimensions not supported by the GPU"),
                   sizeof(eevee->light_cache_info));
       return;
     }
@@ -281,7 +288,7 @@ static bool EEVEE_lightcache_validate(const LightCache *light_cache,
                                       const int grid_len,
                                       const int irr_size[3])
 {
-  if (light_cache) {
+  if (light_cache && !(light_cache->flag & LIGHTCACHE_INVALID)) {
     /* See if we need the same amount of texture space. */
     if ((irr_size[0] == light_cache->grid_tx.tex_size[0]) &&
         (irr_size[1] == light_cache->grid_tx.tex_size[1]) &&
@@ -343,12 +350,18 @@ LightCache *EEVEE_lightcache_create(const int grid_len,
   light_cache->cube_mips = MEM_callocN(sizeof(LightCacheTexture) * light_cache->mips_len,
                                        "LightCacheTexture");
 
-  for (int mip = 0; mip < light_cache->mips_len; mip++) {
-    GPU_texture_get_mipmap_size(
-        light_cache->cube_tx.tex, mip + 1, light_cache->cube_mips[mip].tex_size);
+  if (light_cache->grid_tx.tex == NULL || light_cache->cube_tx.tex == NULL) {
+    /* We could not create the requested textures size. Stop baking and do not use the cache. */
+    light_cache->flag = LIGHTCACHE_INVALID;
   }
+  else {
+    light_cache->flag = LIGHTCACHE_UPDATE_WORLD | LIGHTCACHE_UPDATE_CUBE | LIGHTCACHE_UPDATE_GRID;
 
-  light_cache->flag = LIGHTCACHE_UPDATE_WORLD | LIGHTCACHE_UPDATE_CUBE | LIGHTCACHE_UPDATE_GRID;
+    for (int mip = 0; mip < light_cache->mips_len; mip++) {
+      GPU_texture_get_mipmap_size(
+          light_cache->cube_tx.tex, mip + 1, light_cache->cube_mips[mip].tex_size);
+    }
+  }
 
   return light_cache;
 }
@@ -376,6 +389,12 @@ static bool eevee_lightcache_static_load(LightCache *lcache)
                                                 0,
                                                 false,
                                                 NULL);
+
+    if (lcache->grid_tx.tex == NULL) {
+      lcache->flag |= LIGHTCACHE_NOT_USABLE;
+      return false;
+    }
+
     GPU_texture_filter_mode(lcache->grid_tx.tex, true);
   }
 
@@ -401,6 +420,11 @@ static bool eevee_lightcache_static_load(LightCache *lcache)
                                                   NULL);
     }
 
+    if (lcache->cube_tx.tex == NULL) {
+      lcache->flag |= LIGHTCACHE_NOT_USABLE;
+      return false;
+    }
+
     for (int mip = 0; mip < lcache->mips_len; mip++) {
       GPU_texture_add_mipmap(
           lcache->cube_tx.tex, GPU_DATA_10_11_11_REV, mip + 1, lcache->cube_mips[mip].data);
@@ -420,6 +444,10 @@ bool EEVEE_lightcache_load(LightCache *lcache)
     return false;
   }
 
+  if (lcache->flag & (LIGHTCACHE_INVALID | LIGHTCACHE_NOT_USABLE)) {
+    return false;
+  }
+
   switch (lcache->type) {
     case LIGHTCACHE_TYPE_STATIC:
       return eevee_lightcache_static_load(lcache);
@@ -590,9 +618,7 @@ static void eevee_lightbake_create_resources(EEVEE_LightBake *lbake)
   if (lbake->lcache == NULL) {
     lbake->lcache = EEVEE_lightcache_create(
         lbake->grid_len, lbake->cube_len, lbake->ref_cube_res, lbake->vis_res, lbake->irr_size);
-    lbake->lcache->flag = LIGHTCACHE_UPDATE_WORLD | LIGHTCACHE_UPDATE_CUBE |
-                          LIGHTCACHE_UPDATE_GRID;
-    lbake->lcache->vis_res = lbake->vis_res;
+
     lbake->own_light_cache = true;
 
     eevee->light_cache_data = lbake->lcache;
@@ -1269,6 +1295,17 @@ void EEVEE_lightbake_job(void *custom_data, short *stop, short *do_update, float
    * We cannot do it in the main thread. */
   eevee_lightbake_context_enable(lbake);
   eevee_lightbake_create_resources(lbake);
+
+  /* Resource allocation can fail. Early exit in this case. */
+  if (lbake->lcache->flag & LIGHTCACHE_INVALID) {
+    *lbake->stop = 1;
+    *lbake->do_update = 1;
+    lbake->lcache->flag &= ~LIGHTCACHE_BAKING;
+    eevee_lightbake_context_disable(lbake);
+    eevee_lightbake_delete_resources(lbake);
+    return;
+  }
+
   eevee_lightbake_create_render_target(lbake, lbake->rt_res);
   eevee_lightbake_context_disable(lbake);
 
diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c
index 72187dc29eb..a2f7686619f 100644
--- a/source/blender/draw/engines/eevee/eevee_lightprobes.c
+++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c
@@ -23,6 +23,7 @@
 #include "DRW_render.h"
 
 #include "BLI_rand.h"
+#include "BLI_string_utils.h"
 #include "BLI_utildefines.h"
 
 #include "DNA_image_types.h"
@@ -161,6 +162,7 @@ void EEVEE_lightprobes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
 
   const DRWContextState *draw_ctx = DRW_context_state_get();
   const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph);
+  vedata->info[0] = '\0';
 
   if (!e_data.hammersley) {
     EEVEE_shaders_lightprobe_shaders_init();
@@ -176,6 +178,13 @@ void EEVEE_lightprobes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
     stl->g_data->light_cache = scene_eval->eevee.light_cache_data;
   }
   else {
+    if (scene_eval->eevee.light_cache_data &&
+        (scene_eval->eevee.light_cache_data->flag & LIGHTCACHE_NOT_USABLE)) {
+      /* Error message info. */
+      BLI_snprintf(
+          vedata->info, sizeof(vedata->info), "Error: LightCache cannot be loaded on this GPU");
+    }
+
     if (!sldata->fallback_lightcache) {
 #if defined(IRRADIANCE_SH_L2)
       int grid_res = 4;
diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h
index 81a50d36e17..51831e5506d 100644
--- a/source/blender/draw/engines/eevee/eevee_private.h
+++ b/source/blender/draw/engines/eevee/eevee_private.h
@@ -29,6 +29,8 @@
 
 #include "DNA_lightprobe_types.h"
 
+#include "GPU_viewport.h"
+
 #include "BKE_camera.h"
 
 struct EEVEE_ShadowCasterBuffer;
@@ -891,6 +893,7 @@ typedef struct EEVEE_Data {
   EEVEE_TextureList *txl;
   EEVEE_PassList *psl;
   EEVEE_StorageList *stl;
+  char info[GPU_INFO_SIZE];
 } EEVEE_Data;
 
 typedef struct EEVEE_PrivateData {
diff --git a/source/blender/draw/intern/draw_manager_texture.c b/source/blender/draw/intern/draw_manager_texture.c
index 77b0462303d..b94a6db3bad 100644
--- a/source/blender/draw/intern/draw_manager_texture.c
+++ b/source/blender/draw/intern/draw_manager_texture.c
@@ -61,6 +61,10 @@ static bool drw_texture_format_supports_framebuffer(eGPUTextureFormat format)
 
 void drw_texture_set_parameters(GPUTexture *tex, DRWTextureFlag flags)
 {
+  if (tex == NULL) {
+    return;
+  }
+
   if (flags & DRW_TEX_MIPMAP) {
     GPU_texture_mipmap_mode(tex, true, flags & DRW_TEX_FILTER);
     GPU_texture_bind(tex, 0);
@@ -119,7 +123,6 @@ GPUTexture *DRW_texture_create_cube(int w,
 {
   GPUTexture *tex = GPU_texture_create_cube(w, format, fpixels, NULL);
   drw_texture_set_parameters(tex, flags);
-
   return tex;
 }
 
@@ -128,7 +131,6 @@ GPUTexture *DRW_texture_create_cube_array(
 {
   GPUTexture *tex = GPU_texture_create_cube_array(w, d, format, fpixels, NULL);
   drw_texture_set_parameters(tex, flags);
-
   return tex;
 }
 
diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c
index 536252f5003..711f89b9fda 100644
--- a/source/blender/editors/render/render_shading.c
+++ b/source/blender/editors/render/render_shading.c
@@ -945,6 +945,11 @@ static int light_cache_bake_modal(bContext *C, wmOperator *op, const wmEvent *ev
 
   /* no running blender, remove handler and pass through */
   if (0 == WM_jobs_test(CTX_wm_manager(C), scene, WM_JOB_TYPE_RENDER)) {
+    LightCache *lcache = scene->eevee.light_cache_data;
+    if (lcache && (lcache->flag & LIGHTCACHE_INVALID)) {
+      BKE_report(op->reports, RPT_ERROR, "Lightcache cannot allocate resources");
+      return OPERATOR_CANCELLED;
+    }
     return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
   }
 
diff --git a/source/blender/makesdna/DNA_lightprobe_types.h b/source/blender/makesdna/DNA_lightprobe_types.h
index 5ddfedfed2d..c8d091bd074 100644
--- a/source/blender/makesdna/DNA_lightprobe_types.h
+++ b/source/blender/makesdna/DNA_lightprobe_types.h
@@ -150,7 +150,7 @@ BLI_STATIC_ASSERT_ALIGN(LightGridCache, 16)
 
 typedef struct LightCacheTexture {
   struct GPUTexture *tex;
-  /* Copy of GPU datas to create GPUTextures on file read. */
+  /** Copy of GPU datas to create GPUTextures on file read. */
   char *data;
   int tex_size[3];
   char data_type;
@@ -204,6 +204,10 @@ enum {
   LIGHTCACHE_UPDATE_GRID = (1 << 5),
   LIGHTCACHE_UPDATE_WORLD = (1 << 6),
   LIGHTCACHE_UPDATE_AUTO = (1 << 7),
+  /** Invalid means we tried to alloc it but failed. */
+  LIGHTCACHE_INVALID = (1 << 8),
+  /** The data present in the cache is valid but unusable on this GPU. */
+  LIGHTCACHE_NOT_USABLE = (1 << 9),
 };
 
 /* EEVEE_LightCacheTexture->data_type */



More information about the Bf-blender-cvs mailing list