Fix #133943: Unnecessary image full update mark on file open

This would be done when the frame, layer, pass or view changes compared to
the previous value. But for cases like old files without these members or
loading the image datablock into a different scene, this considered the image
to be always be changed on file load.

Now always reset this state on file load, and don't consider the initial
state as an image update.

This could also happen in the middle of GPU rendering, causing the GPU
texture to be freed while still in use.

Pull Request: https://projects.blender.org/blender/blender/pulls/134198
This commit is contained in:
Brecht Van Lommel
2025-02-07 21:23:48 +01:00
committed by Brecht Van Lommel
parent 78ff230257
commit cfca7ac952
4 changed files with 30 additions and 12 deletions

View File

@@ -49,6 +49,7 @@
#include "DNA_brush_types.h"
#include "DNA_camera_types.h"
#include "DNA_defaults.h"
#include "DNA_image_types.h"
#include "DNA_light_types.h"
#include "DNA_material_types.h"
#include "DNA_object_types.h"
@@ -156,6 +157,16 @@ static void image_runtime_free_data(Image *image)
BKE_image_partial_update_register_free(image);
}
static void image_gpu_runtime_reset(Image *ima)
{
ima->lastused = 0;
ima->gpuflag = 0;
ima->gpuframenr = IMAGE_GPU_FRAME_NONE;
ima->gpu_pass = IMAGE_GPU_PASS_NONE;
ima->gpu_layer = IMAGE_GPU_LAYER_NONE;
ima->gpu_view = IMAGE_GPU_VIEW_NONE;
}
static void image_init_data(ID *id)
{
Image *image = (Image *)id;
@@ -348,9 +359,8 @@ static void image_blend_write(BlendWriter *writer, ID *id, const void *id_addres
/* Clear all data that isn't read to reduce false detection of changed image during memfile undo.
*/
ima->lastused = 0;
ima->cache = nullptr;
ima->gpuflag = 0;
image_gpu_runtime_reset(ima);
BLI_listbase_clear(&ima->anims);
ima->runtime.partial_update_register = nullptr;
ima->runtime.partial_update_user = nullptr;
@@ -433,9 +443,7 @@ static void image_blend_read_data(BlendDataReader *reader, ID *id)
BKE_previewimg_blend_read(reader, ima->preview);
BLO_read_struct(reader, Stereo3dFormat, &ima->stereo3d_format);
ima->lastused = 0;
ima->gpuflag = 0;
image_gpu_runtime_reset(ima);
image_runtime_reset(ima);
}
@@ -5224,7 +5232,9 @@ void BKE_image_user_frame_calc(Image *ima, ImageUser *iuser, int cfra)
/* NOTE: a single texture and refresh doesn't really work when
* multiple image users may use different frames, this is to
* be improved with perhaps a GPU texture cache. */
BKE_image_partial_update_mark_full_update(ima);
if (ima->gpuframenr != IMAGE_GPU_FRAME_NONE) {
BKE_image_partial_update_mark_full_update(ima);
}
ima->gpuframenr = iuser->framenr;
}

View File

@@ -335,7 +335,7 @@ static void image_gpu_texture_try_partial_update(Image *image, ImageUser *iuser)
}
}
void BKE_image_ensure_gpu_texture(Image *image, ImageUser *image_user)
void BKE_image_ensure_gpu_texture(Image *image, ImageUser *iuser)
{
if (!image) {
return;
@@ -343,8 +343,9 @@ void BKE_image_ensure_gpu_texture(Image *image, ImageUser *image_user)
/* Note that the image can cache both stereo views, so we only invalidate the cache if the view
* index is more than 2. */
if (image->gpu_pass != image_user->pass || image->gpu_layer != image_user->layer ||
(image->gpu_view != image_user->multi_index && image_user->multi_index >= 2))
if (!ELEM(image->gpu_pass, IMAGE_GPU_PASS_NONE, iuser->pass) ||
!ELEM(image->gpu_layer, IMAGE_GPU_LAYER_NONE, iuser->layer) ||
(!ELEM(image->gpu_view, IMAGE_GPU_VIEW_NONE, iuser->multi_index) && iuser->multi_index >= 2))
{
BKE_image_partial_update_mark_full_update(image);
}

View File

@@ -22,9 +22,10 @@
.gen_y = 1024, \
.gen_type = IMA_GENTYPE_GRID, \
\
.gpuframenr = INT_MAX, \
.gpu_pass = SHRT_MAX, \
.gpu_layer = SHRT_MAX, \
.gpuframenr = IMAGE_GPU_FRAME_NONE, \
.gpu_pass = IMAGE_GPU_PASS_NONE, \
.gpu_layer = IMAGE_GPU_LAYER_NONE, \
.gpu_view = IMAGE_GPU_VIEW_NONE, \
.seam_margin = 8, \
}

View File

@@ -293,3 +293,9 @@ enum {
IMA_ALPHA_CHANNEL_PACKED = 2,
IMA_ALPHA_IGNORE = 3,
};
/* Image gpu runtime defaults */
#define IMAGE_GPU_FRAME_NONE INT_MAX
#define IMAGE_GPU_PASS_NONE SHRT_MAX
#define IMAGE_GPU_LAYER_NONE SHRT_MAX
#define IMAGE_GPU_VIEW_NONE SHRT_MAX