[Bf-blender-cvs] [2b2d427bbac] master: Fix T90825: Performance texture painting with limited scale.

Jeroen Bakker noreply at git.blender.org
Wed Sep 8 09:56:38 CEST 2021


Commit: 2b2d427bbac6716092336f0d0f698706a390f4ad
Author: Jeroen Bakker
Date:   Wed Sep 8 09:52:06 2021 +0200
Branches: master
https://developer.blender.org/rB2b2d427bbac6716092336f0d0f698706a390f4ad

Fix T90825: Performance texture painting with limited scale.

Improve texture painting/uv editing performance when limited scale is active.
Cause of the slow down is that the image editor draws the image in maximum resolution,
but the 3d viewport uses the limited scale. The variation reuses the same GPU texture
and needed to be uploaded/scaled twice to the GPU.

This patch will adds texture slots that can hold the scaled down and the maximum
resolution image. This would allow better cache hits and reuse of existing caches.

Maximum resolution textures are reused for limited scale when they fit to reduce memory
and CPU footprint.

Reviewed By: fclem

Differential Revision: https://developer.blender.org/D12388

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

M	source/blender/blenkernel/intern/image.c
M	source/blender/blenkernel/intern/image_gpu.c
M	source/blender/makesdna/DNA_image_types.h
M	source/blender/makesrna/intern/rna_image.c

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

diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index d87290e1eb4..966dd0595da 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -155,7 +155,9 @@ static void image_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, c
 
   for (int eye = 0; eye < 2; eye++) {
     for (int i = 0; i < TEXTARGET_COUNT; i++) {
-      image_dst->gputexture[i][eye] = NULL;
+      for (int slot = 0; slot < IMA_TEXTURE_RESOLUTION_LEN; slot++) {
+        image_dst->gputexture[i][eye][slot] = NULL;
+      }
     }
   }
 
@@ -208,9 +210,11 @@ static void image_foreach_cache(ID *id,
 
   for (int eye = 0; eye < 2; eye++) {
     for (int a = 0; a < TEXTARGET_COUNT; a++) {
-      key.offset_in_ID = offsetof(Image, gputexture[a][eye]);
-      key.cache_v = image->gputexture[a][eye];
-      function_callback(id, &key, (void **)&image->gputexture[a][eye], 0, user_data);
+      for (int slot = 0; slot < IMA_TEXTURE_RESOLUTION_LEN; slot++) {
+        key.offset_in_ID = offsetof(Image, gputexture[a][eye][slot]);
+        key.cache_v = image->gputexture[a][eye];
+        function_callback(id, &key, (void **)&image->gputexture[a][eye][slot], 0, user_data);
+      }
     }
   }
 
@@ -239,7 +243,9 @@ static void image_blend_write(BlendWriter *writer, ID *id, const void *id_addres
   BLI_listbase_clear(&ima->gpu_refresh_areas);
   for (int i = 0; i < 3; i++) {
     for (int j = 0; j < 2; j++) {
-      ima->gputexture[i][j] = NULL;
+      for (int slot = 0; slot < IMA_TEXTURE_RESOLUTION_LEN; slot++) {
+        ima->gputexture[i][j][slot] = NULL;
+      }
     }
   }
 
@@ -677,8 +683,10 @@ bool BKE_image_has_opengl_texture(Image *ima)
 {
   for (int eye = 0; eye < 2; eye++) {
     for (int i = 0; i < TEXTARGET_COUNT; i++) {
-      if (ima->gputexture[i][eye] != NULL) {
-        return true;
+      for (int slot = 0; slot < IMA_TEXTURE_RESOLUTION_LEN; slot++) {
+        if (ima->gputexture[i][eye][slot] != NULL) {
+          return true;
+        }
       }
     }
   }
@@ -3531,9 +3539,11 @@ static void image_free_tile(Image *ima, ImageTile *tile)
     }
 
     for (int eye = 0; eye < 2; eye++) {
-      if (ima->gputexture[i][eye] != NULL) {
-        GPU_texture_free(ima->gputexture[i][eye]);
-        ima->gputexture[i][eye] = NULL;
+      for (int slot = 0; slot < IMA_TEXTURE_RESOLUTION_LEN; slot++) {
+        if (ima->gputexture[i][eye][slot] != NULL) {
+          GPU_texture_free(ima->gputexture[i][eye][slot]);
+          ima->gputexture[i][eye][slot] = NULL;
+        }
       }
     }
   }
@@ -3801,14 +3811,16 @@ ImageTile *BKE_image_add_tile(struct Image *ima, int tile_number, const char *la
   }
 
   for (int eye = 0; eye < 2; eye++) {
-    /* Reallocate GPU tile array. */
-    if (ima->gputexture[TEXTARGET_2D_ARRAY][eye] != NULL) {
-      GPU_texture_free(ima->gputexture[TEXTARGET_2D_ARRAY][eye]);
-      ima->gputexture[TEXTARGET_2D_ARRAY][eye] = NULL;
-    }
-    if (ima->gputexture[TEXTARGET_TILE_MAPPING][eye] != NULL) {
-      GPU_texture_free(ima->gputexture[TEXTARGET_TILE_MAPPING][eye]);
-      ima->gputexture[TEXTARGET_TILE_MAPPING][eye] = NULL;
+    for (int slot = 0; slot < IMA_TEXTURE_RESOLUTION_LEN; slot++) {
+      /* Reallocate GPU tile array. */
+      if (ima->gputexture[TEXTARGET_2D_ARRAY][eye][slot] != NULL) {
+        GPU_texture_free(ima->gputexture[TEXTARGET_2D_ARRAY][eye][slot]);
+        ima->gputexture[TEXTARGET_2D_ARRAY][eye][slot] = NULL;
+      }
+      if (ima->gputexture[TEXTARGET_TILE_MAPPING][eye][slot] != NULL) {
+        GPU_texture_free(ima->gputexture[TEXTARGET_TILE_MAPPING][eye][slot]);
+        ima->gputexture[TEXTARGET_TILE_MAPPING][eye][slot] = NULL;
+      }
     }
   }
 
@@ -3863,14 +3875,17 @@ void BKE_image_reassign_tile(struct Image *ima, ImageTile *tile, int new_tile_nu
   }
 
   for (int eye = 0; eye < 2; eye++) {
-    /* Reallocate GPU tile array. */
-    if (ima->gputexture[TEXTARGET_2D_ARRAY][eye] != NULL) {
-      GPU_texture_free(ima->gputexture[TEXTARGET_2D_ARRAY][eye]);
-      ima->gputexture[TEXTARGET_2D_ARRAY][eye] = NULL;
-    }
-    if (ima->gputexture[TEXTARGET_TILE_MAPPING][eye] != NULL) {
-      GPU_texture_free(ima->gputexture[TEXTARGET_TILE_MAPPING][eye]);
-      ima->gputexture[TEXTARGET_TILE_MAPPING][eye] = NULL;
+    for (int slot = 0; slot < IMA_TEXTURE_RESOLUTION_LEN; slot++) {
+
+      /* Reallocate GPU tile array. */
+      if (ima->gputexture[TEXTARGET_2D_ARRAY][eye][slot] != NULL) {
+        GPU_texture_free(ima->gputexture[TEXTARGET_2D_ARRAY][eye][slot]);
+        ima->gputexture[TEXTARGET_2D_ARRAY][eye][slot] = NULL;
+      }
+      if (ima->gputexture[TEXTARGET_TILE_MAPPING][eye][slot] != NULL) {
+        GPU_texture_free(ima->gputexture[TEXTARGET_TILE_MAPPING][eye][slot]);
+        ima->gputexture[TEXTARGET_TILE_MAPPING][eye][slot] = NULL;
+      }
     }
   }
 }
diff --git a/source/blender/blenkernel/intern/image_gpu.c b/source/blender/blenkernel/intern/image_gpu.c
index d179dd40c33..9712e912bed 100644
--- a/source/blender/blenkernel/intern/image_gpu.c
+++ b/source/blender/blenkernel/intern/image_gpu.c
@@ -49,6 +49,7 @@
 /* Prototypes. */
 static void gpu_free_unused_buffers(void);
 static void image_free_gpu(Image *ima, const bool immediate);
+static void image_free_gpu_limited_scale(Image *ima);
 static void image_update_gputexture_ex(
     Image *ima, ImageTile *tile, ImBuf *ibuf, int x, int y, int w, int h);
 
@@ -97,9 +98,11 @@ static int smaller_power_of_2_limit(int num, bool limit_gl_texture_size)
   return power_of_2_min_i(GPU_texture_size_with_limit(num, limit_gl_texture_size));
 }
 
-static GPUTexture *gpu_texture_create_tile_mapping(Image *ima, const int multiview_eye)
+static GPUTexture *gpu_texture_create_tile_mapping(
+    Image *ima, const int multiview_eye, const eImageTextureResolution texture_resolution)
 {
-  GPUTexture *tilearray = ima->gputexture[TEXTARGET_2D_ARRAY][multiview_eye];
+  const int resolution = (texture_resolution == IMA_TEXTURE_RESOLUTION_LIMITED) ? 1 : 0;
+  GPUTexture *tilearray = ima->gputexture[TEXTARGET_2D_ARRAY][multiview_eye][resolution];
 
   if (tilearray == NULL) {
     return 0;
@@ -121,13 +124,14 @@ static GPUTexture *gpu_texture_create_tile_mapping(Image *ima, const int multivi
   }
   LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) {
     int i = tile->tile_number - 1001;
-    data[4 * i] = tile->runtime.tilearray_layer;
+    ImageTile_RuntimeTextureSlot *tile_runtime = &tile->runtime.slots[resolution];
+    data[4 * i] = tile_runtime->tilearray_layer;
 
     float *tile_info = &data[4 * width + 4 * i];
-    tile_info[0] = tile->runtime.tilearray_offset[0] / array_w;
-    tile_info[1] = tile->runtime.tilearray_offset[1] / array_h;
-    tile_info[2] = tile->runtime.tilearray_size[0] / array_w;
-    tile_info[3] = tile->runtime.tilearray_size[1] / array_h;
+    tile_info[0] = tile_runtime->tilearray_offset[0] / array_w;
+    tile_info[1] = tile_runtime->tilearray_offset[1] / array_h;
+    tile_info[2] = tile_runtime->tilearray_size[0] / array_w;
+    tile_info[3] = tile_runtime->tilearray_size[1] / array_h;
   }
 
   GPUTexture *tex = GPU_texture_create_1d_array(ima->id.name + 2, width, 2, 1, GPU_RGBA32F, data);
@@ -152,9 +156,12 @@ static int compare_packtile(const void *a, const void *b)
   return tile_a->pack_score < tile_b->pack_score;
 }
 
-static GPUTexture *gpu_texture_create_tile_array(Image *ima, ImBuf *main_ibuf)
+static GPUTexture *gpu_texture_create_tile_array(Image *ima,
+                                                 ImBuf *main_ibuf,
+                                                 const eImageTextureResolution texture_resolution)
 {
-  const bool limit_gl_texture_size = (ima->gpuflag & IMA_GPU_MAX_RESOLUTION) == 0;
+  const bool limit_gl_texture_size = texture_resolution == IMA_TEXTURE_RESOLUTION_LIMITED;
+  const int resolution = texture_resolution == IMA_TEXTURE_RESOLUTION_LIMITED ? 1 : 0;
   int arraywidth = 0, arrayheight = 0;
   ListBase boxes = {NULL};
 
@@ -200,14 +207,15 @@ static GPUTexture *gpu_texture_create_tile_array(Image *ima, ImBuf *main_ibuf)
 
     LISTBASE_FOREACH (PackTile *, packtile, &packed) {
       ImageTile *tile = packtile->tile;
-      int *tileoffset = tile->runtime.tilearray_offset;
-      int *tilesize = tile->runtime.tilearray_size;
+      ImageTile_RuntimeTextureSlot *tile_runtime = &tile->runtime.slots[resolution];
+      int *tileoffset = tile_runtime->tilearray_offset;
+      int *tilesize = tile_runtime->tilearray_size;
 
       tileoffset[0] = packtile->boxpack.x;
       tileoffset[1] = packtile->boxpack.y;
       tilesize[0] = packtile->boxpack.w;
       tilesize[1] = packtile->boxpack.h;
-      tile->runtime.tilearray_layer = arraylayers;
+      tile_runtime->tilearray_layer = arraylayers;
     }
 
     BLI_freelistN(&packed);
@@ -221,9 +229,10 @@ static GPUTexture *gpu_texture_create_tile_array(Image *ima, ImBuf *main_ibuf)
 
   /* Upload each tile one by one. */
   LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) {
-    int tilelayer = tile->runtime.tilearray_layer;
-    int *tileoffset = tile->runtime.tilearray_offset;
-    int *tilesize = tile->runtime.tilearray_size;
+    ImageTile_RuntimeTextureSlot *tile_runtime = &tile->runtime.slots[resolution];
+    int tilelayer = tile_runtime->tilearray_layer;
+    int *tileoffset = tile_runtime->tilearray_offset;
+    int *tilesize = tile_runtime->tilearray_size;
 
     if (tilesize[0] == 0 || tilesize[1] == 0) {
       continue;
@@ -268,16 +277,33 @@ static GPUTexture *gpu_texture_create_tile_array(Image *ima, ImBuf *main_ibuf)
 /** \name Regular gpu texture
  * \{ */
 
+static bool image_max_resolution_texture_fits_in_limited_scale(Image *ima,
+                                                               eGPUTextureTarget textarget,
+                                                               const int multiview_eye)
+{
+  BLI_assert_msg(U.glreslimit != 0,
+                 "limited scale function called without limited scale being set.");
+  GPUTexture *max_resolution_texture =
+      ima->gputexture[textarget][multiview_eye][IMA_TEXTURE_RESOLUTION_FULL];
+  if (max_resolution_texture && GPU_texture_width(max_resolution_texture) <= U.glre

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list