[Bf-blender-cvs] [ae68c53b159] temp-T98375-share-gpu-textures: Base implementation to share textures between mutliple image data-blocks.

Jeroen Bakker noreply at git.blender.org
Fri May 27 15:09:13 CEST 2022


Commit: ae68c53b15912669f432b93bfd6edbe4d043a897
Author: Jeroen Bakker
Date:   Fri May 27 14:46:05 2022 +0200
Branches: temp-T98375-share-gpu-textures
https://developer.blender.org/rBae68c53b15912669f432b93bfd6edbe4d043a897

Base implementation to share textures between mutliple image data-blocks.

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

M	source/blender/blenkernel/BKE_image.h
M	source/blender/blenkernel/intern/image.cc
M	source/blender/blenkernel/intern/image_gpu.cc
M	source/blender/editors/sculpt_paint/paint_image.cc
M	source/blender/makesdna/DNA_image_types.h
M	source/blender/makesrna/intern/rna_image.c
M	source/blender/makesrna/intern/rna_image_api.c

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

diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h
index b6607a92c14..8f617cce7f7 100644
--- a/source/blender/blenkernel/BKE_image.h
+++ b/source/blender/blenkernel/BKE_image.h
@@ -325,11 +325,6 @@ bool BKE_image_scale(struct Image *image, int width, int height);
  */
 bool BKE_image_has_alpha(struct Image *image);
 
-/**
- * Check if texture has GPU texture code.
- */
-bool BKE_image_has_opengl_texture(struct Image *ima);
-
 /**
  * Get tile index for tiled images.
  */
@@ -525,7 +520,7 @@ void BKE_image_update_gputexture_delayed(struct Image *ima,
  * temporary disabling/enabling mipmapping on all images for quick texture
  * updates with glTexSubImage2D. images that didn't change don't have to be re-uploaded to OpenGL.
  */
-void BKE_image_paint_set_mipmap(struct Main *bmain, bool mipmap);
+void BKE_image_paint_set_mipmap(bool mipmap);
 
 /**
  * Delayed free of OpenGL buffers by main thread.
diff --git a/source/blender/blenkernel/intern/image.cc b/source/blender/blenkernel/intern/image.cc
index bc21e706d1e..bf00eb7ab7a 100644
--- a/source/blender/blenkernel/intern/image.cc
+++ b/source/blender/blenkernel/intern/image.cc
@@ -180,12 +180,6 @@ static void image_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, c
 
   BLI_duplicatelist(&image_dst->tiles, &image_src->tiles);
 
-  for (int eye = 0; eye < 2; eye++) {
-    for (int i = 0; i < TEXTARGET_COUNT; i++) {
-      image_dst->gputexture[i][eye] = nullptr;
-    }
-  }
-
   if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0) {
     BKE_previewimg_id_copy(&image_dst->id, &image_src->id);
   }
@@ -234,6 +228,7 @@ static void image_foreach_cache(ID *id,
   key.offset_in_ID = offsetof(Image, cache);
   function_callback(id, &key, (void **)&image->cache, 0, user_data);
 
+#if 0
   auto gputexture_offset = [image](int target, int eye) {
     constexpr size_t base_offset = offsetof(Image, gputexture);
     struct GPUTexture **first = &image->gputexture[0][0];
@@ -241,6 +236,7 @@ static void image_foreach_cache(ID *id,
     return base_offset + array_offset;
   };
 
+// TODO(jbakker): need to check how this is actually used not the GPU textures are shared we might need to reinvalidate this.
   for (int eye = 0; eye < 2; eye++) {
     for (int a = 0; a < TEXTARGET_COUNT; a++) {
       GPUTexture *texture = image->gputexture[a][eye];
@@ -251,6 +247,7 @@ static void image_foreach_cache(ID *id,
       function_callback(id, &key, (void **)&image->gputexture[a][eye], 0, user_data);
     }
   }
+#endif
 
   key.offset_in_ID = offsetof(Image, rr);
   function_callback(id, &key, (void **)&image->rr, 0, user_data);
@@ -328,11 +325,6 @@ static void image_blend_write(BlendWriter *writer, ID *id, const void *id_addres
   BLI_listbase_clear(&ima->anims);
   ima->runtime.partial_update_register = nullptr;
   ima->runtime.partial_update_user = nullptr;
-  for (int i = 0; i < 3; i++) {
-    for (int j = 0; j < 2; j++) {
-      ima->gputexture[i][j] = nullptr;
-    }
-  }
 
   ImagePackedFile *imapf;
 
@@ -773,18 +765,6 @@ bool BKE_image_scale(Image *image, int width, int height)
   return (ibuf != nullptr);
 }
 
-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] != nullptr) {
-        return true;
-      }
-    }
-  }
-  return false;
-}
-
 static int image_get_tile_number_from_iuser(Image *ima, const ImageUser *iuser)
 {
   BLI_assert(ima != nullptr && ima->tiles.first);
@@ -2847,20 +2827,6 @@ void BKE_image_init_imageuser(Image *ima, ImageUser *iuser)
 
 static void image_free_tile(Image *ima, ImageTile *tile)
 {
-  for (int i = 0; i < TEXTARGET_COUNT; i++) {
-    /* Only two textures depends on all tiles, so if this is a secondary tile we can keep the other
-     * two. */
-    if (tile != ima->tiles.first && !(ELEM(i, TEXTARGET_2D_ARRAY, TEXTARGET_TILE_MAPPING))) {
-      continue;
-    }
-
-    for (int eye = 0; eye < 2; eye++) {
-      if (ima->gputexture[i][eye] != nullptr) {
-        GPU_texture_free(ima->gputexture[i][eye]);
-        ima->gputexture[i][eye] = nullptr;
-      }
-    }
-  }
   BKE_image_partial_update_mark_full_update(ima);
 
   if (BKE_image_is_multiview(ima)) {
@@ -3196,17 +3162,6 @@ ImageTile *BKE_image_add_tile(struct Image *ima, int tile_number, const char *la
     BLI_strncpy(tile->label, label, sizeof(tile->label));
   }
 
-  for (int eye = 0; eye < 2; eye++) {
-    /* Reallocate GPU tile array. */
-    if (ima->gputexture[TEXTARGET_2D_ARRAY][eye] != nullptr) {
-      GPU_texture_free(ima->gputexture[TEXTARGET_2D_ARRAY][eye]);
-      ima->gputexture[TEXTARGET_2D_ARRAY][eye] = nullptr;
-    }
-    if (ima->gputexture[TEXTARGET_TILE_MAPPING][eye] != nullptr) {
-      GPU_texture_free(ima->gputexture[TEXTARGET_TILE_MAPPING][eye]);
-      ima->gputexture[TEXTARGET_TILE_MAPPING][eye] = nullptr;
-    }
-  }
   BKE_image_partial_update_mark_full_update(ima);
 
   return tile;
@@ -3259,17 +3214,6 @@ void BKE_image_reassign_tile(struct Image *ima, ImageTile *tile, int new_tile_nu
     IMB_freeImBuf(ibuf);
   }
 
-  for (int eye = 0; eye < 2; eye++) {
-    /* Reallocate GPU tile array. */
-    if (ima->gputexture[TEXTARGET_2D_ARRAY][eye] != nullptr) {
-      GPU_texture_free(ima->gputexture[TEXTARGET_2D_ARRAY][eye]);
-      ima->gputexture[TEXTARGET_2D_ARRAY][eye] = nullptr;
-    }
-    if (ima->gputexture[TEXTARGET_TILE_MAPPING][eye] != nullptr) {
-      GPU_texture_free(ima->gputexture[TEXTARGET_TILE_MAPPING][eye]);
-      ima->gputexture[TEXTARGET_TILE_MAPPING][eye] = nullptr;
-    }
-  }
   BKE_image_partial_update_mark_full_update(ima);
 }
 
diff --git a/source/blender/blenkernel/intern/image_gpu.cc b/source/blender/blenkernel/intern/image_gpu.cc
index bed79a318e8..3e0e0414afa 100644
--- a/source/blender/blenkernel/intern/image_gpu.cc
+++ b/source/blender/blenkernel/intern/image_gpu.cc
@@ -11,7 +11,9 @@
 #include "BLI_boxpack_2d.h"
 #include "BLI_linklist.h"
 #include "BLI_listbase.h"
+#include "BLI_map.hh"
 #include "BLI_threads.h"
+#include "BLI_utility_mixins.hh"
 
 #include "DNA_image_types.h"
 #include "DNA_userdef_types.h"
@@ -33,13 +35,133 @@
 
 using namespace blender::bke::image::partial_update;
 
+namespace blender::bke::image::gpu {
+struct ImageGPUTextureStore {
+  class Entry : NonCopyable {
+   public:
+    GPUTexture *gputextures[TEXTARGET_COUNT][2];
+    struct {
+      bool in_use : 1;
+    } flags;
+
+    Entry()
+    {
+      for (int target = 0; target < TEXTARGET_COUNT; target++) {
+        for (int eye = 0; eye < 2; eye++) {
+          gputextures[target][eye] = nullptr;
+        }
+      }
+    }
+
+    Entry(Entry &&other)
+    {
+      for (int target = 0; target < TEXTARGET_COUNT; target++) {
+        for (int eye = 0; eye < 2; eye++) {
+          gputextures[target][eye] = other.gputextures[target][eye];
+          other.gputextures[target][eye] = nullptr;
+        }
+      }
+      flags.in_use = other.flags.in_use;
+    };
+
+    virtual ~Entry()
+    {
+      clear();
+    }
+
+    void set_mipmap(const bool mipmap)
+    {
+      for (int eye = 0; eye < 2; eye++) {
+        if (gputextures[TEXTARGET_2D][eye]) {
+          GPU_texture_mipmap_mode(gputextures[TEXTARGET_2D][eye], mipmap, true);
+        }
+        if (gputextures[TEXTARGET_2D_ARRAY][eye]) {
+          GPU_texture_mipmap_mode(gputextures[TEXTARGET_2D_ARRAY][eye], mipmap, true);
+        }
+      }
+    }
+
+    void tag_used()
+    {
+      flags.in_use = true;
+    }
+
+    void clear()
+    {
+      for (int target = 0; target < TEXTARGET_COUNT; target++) {
+        for (int eye = 0; eye < 2; eye++) {
+          GPU_TEXTURE_FREE_SAFE(gputextures[target][eye]);
+        }
+      }
+    }
+  };
+
+  using Entries = Map<std::string, Entry>;
+
+  Entries entries;
+
+  void reset_usage()
+  {
+    for (Entry &entry : entries.values()) {
+      entry.flags.in_use = false;
+    }
+  }
+
+  void remove_unused()
+  {
+    for (auto it : entries.items()) {
+      if (it.value.flags.in_use) {
+        continue;
+      }
+      entries.remove(it.key);
+    }
+  }
+
+  void set_mipmap(const bool mipmap)
+  {
+    for (Entry &entry : entries.values()) {
+      entry.set_mipmap(mipmap);
+    }
+  }
+
+  void clear()
+  {
+    entries.clear();
+  }
+
+  std::string create_key(const Image &image) const
+  {
+    std::stringstream result;
+    result << "ID:" << image.id.name;
+    return result.str();
+  }
+
+  Entry &operator[](Image &image)
+  {
+    std::string key = create_key(image);
+    return entries.lookup_or_add_default(key);
+  }
+};
+
+static ImageGPUTextureStore g_texture_store;
+
+}  // namespace blender::bke::image::gpu
+
 extern "C" {
 
+using namespace blender::bke::image::gpu;
+
 /* Prototypes. */
 static void gpu_free_unused_buffers();
 static void image_free_gpu(Image *ima, const bool immediate);
-static void image_update_gputexture_ex(
-    Image *ima, ImageTile *tile, ImBuf *ibuf, int x, int y, int w, int h);
+static void image_update_gputexture_ex(Image *ima,
+                                       ImageGPUTextureStore::Entry &entry,
+                                       ImageTile *tile,
+                                       ImBuf *ibuf,
+                                       int x,
+                                       int y,
+                                       int w,
+                                       int h);
 
 bool BKE_image_has_gpu_texture_premultiplied_alpha(Image *image, ImBuf *ibuf)
 {
@@ -77,9 +199,11 @@ static int smaller_power_of_2_limit(int num)
   return power_of_2_min_i(GPU_texture_size_with_limit(num));
 }
 
-static GPUTexture *gpu_texture_create_tile_mapping(Image *ima, const int multiview_eye)
+static GPUTexture *gpu_texture_create_tile_mapping(Image *ima,
+                                                   ImageGPUTextureStore::Entry &entry,
+                                                   const int multiview_eye)
 {
-  GPUTexture *tilearray = ima->gputexture[TEXTARGET_2D_ARRAY][multiview_eye];
+  GPUTexture *tilearray = entry.gputextures[TEXTARGET_2D_ARRAY][multiview_eye];
 
   if (tilearray == nullptr) {
     return nullptr;
@@ -249,7 +373,7 @@ static GPUTexture *gpu_texture_create_tile_array(

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list