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.
This commit is contained in:
parent
d1b3da697d
commit
6be8b6af40
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue