[Bf-blender-cvs] [6cda987f592] temp-gpu-texture-partial-updates: Added API documentation.

Jeroen Bakker noreply at git.blender.org
Fri Nov 26 13:29:43 CET 2021


Commit: 6cda987f592409689a384226b03a49fc32648530
Author: Jeroen Bakker
Date:   Fri Nov 26 13:29:18 2021 +0100
Branches: temp-gpu-texture-partial-updates
https://developer.blender.org/rB6cda987f592409689a384226b03a49fc32648530

Added API documentation.

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

M	source/blender/blenkernel/BKE_image_partial_update.hh
M	source/blender/blenkernel/intern/image_gpu.cc
M	source/blender/blenkernel/intern/image_partial_update.cc
M	source/blender/blenkernel/intern/image_partial_update_test.cc

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

diff --git a/source/blender/blenkernel/BKE_image_partial_update.hh b/source/blender/blenkernel/BKE_image_partial_update.hh
index 107e54c9351..dfc02fea742 100644
--- a/source/blender/blenkernel/BKE_image_partial_update.hh
+++ b/source/blender/blenkernel/BKE_image_partial_update.hh
@@ -18,6 +18,13 @@
 
 /** \file
  * \ingroup bke
+ *
+ * To reduce the overhead of image processing this file contains a mechanism to detect areas of the
+ * image that are changed. These areas are organized in chunks. Changes that happen over time are
+ * organized in changesets.
+ *
+ * A common usecase is to update GPUTexture for drawing where only that part is uploaded that only
+ * changed.
  */
 
 #pragma once
@@ -104,23 +111,76 @@ ePartialUpdateCollectResult BKE_image_partial_update_collect_changes(
 ePartialUpdateIterResult BKE_image_partial_update_get_next_change(
     struct PartialUpdateUser *user, struct PartialUpdateRegion *r_region);
 
+/** \brief Abstract class to load tile data when using the PartialUpdateChecker. */
 class AbstractTileData {
  protected:
   virtual ~AbstractTileData() = default;
 
  public:
+  /**
+   * \brief Load the data for the given tile_number.
+   *
+   * Invoked when changes are on a different tile compared to the previous tile..
+   */
   virtual void init_data(TileNumber tile_number) = 0;
+  /**
+   * \brief Unload the data that has been loaded.
+   *
+   * Invoked when changes are on a different tile compared to the previous tile or when finished
+   * iterating over the changes.
+   */
   virtual void free_data() = 0;
 };
 
-class ImageTileData : AbstractTileData {
+/**
+ * \brief Class to not load any tile specific data when iterating over changes.
+ */
+class NoTileData : AbstractTileData {
  public:
-  ImageTile *tile = nullptr;
-  ImBuf *tile_buffer = nullptr;
+  NoTileData(Image *UNUSED(image), ImageUser &UNUSED(image_user))
+  {
+  }
+
+  void init_data(TileNumber UNUSED(new_tile_number)) override
+  {
+  }
 
+  void free_data() override
+  {
+  }
+};
+
+/**
+ * \brief Load the ImageTile and ImBuf associated with the partial change.
+ */
+class ImageTileData : AbstractTileData {
+ public:
+  /**
+   * \brief Not owned Image that is being iterated over.
+   */
   Image *image;
+
+  /**
+   * \brief Local copy of the image user.
+   *
+   * The local copy is required so we don't change the image user of the caller.
+   * We need to change it in order to request data for a specific tile.
+   */
   ImageUser image_user;
 
+  /**
+   * \brief ImageTile associated with the loaded tile.
+   * Data is not owned by this instance but by the `image`.
+   */
+  ImageTile *tile = nullptr;
+
+  /**
+   * \brief ImBuf of the loaded tile.
+   *
+   * Can be nullptr when the file doesn't exist or when the tile hasn't been initialized.
+   */
+  ImBuf *tile_buffer = nullptr;
+
   ImageTileData(Image *image, ImageUser image_user) : image(image), image_user(image_user)
   {
   }
@@ -128,7 +188,6 @@ class ImageTileData : AbstractTileData {
   void init_data(TileNumber new_tile_number) override
   {
     image_user.tile = new_tile_number;
-
     tile = BKE_image_get_tile(image, new_tile_number);
     tile_buffer = BKE_image_acquire_ibuf(image, &image_user, NULL);
   }
@@ -141,77 +200,79 @@ class ImageTileData : AbstractTileData {
   }
 };
 
-class NoTileData : AbstractTileData {
- public:
-  NoTileData(Image *UNUSED(image), ImageUser &UNUSED(image_user))
-  {
-  }
+template<typename TileData = NoTileData> struct PartialUpdateChecker {
 
-  void init_data(TileNumber UNUSED(new_tile_number)) override
-  {
-  }
-
-  void free_data() override
-  {
-  }
-};
-
-template<typename TileData = NoTileData> struct PartialUpdateCollectResult {
+  /**
+   * \brief Not owned Image that is being iterated over.
+   */
   Image *image;
-  PartialUpdateUser *user;
-  TileData tile_data;
-  TileNumber last_tile_number;
-  PartialUpdateRegion changed_region;
+  ImageUser *image_user;
 
- private:
-  ePartialUpdateCollectResult collect_result;
+  /**
+   * \brief the collected changes are stored inside the PartialUpdateUser.
+   */
+  PartialUpdateUser *user;
 
- public:
-  PartialUpdateCollectResult(Image *image,
-                             ImageUser image_user,
-                             PartialUpdateUser *user,
-                             ePartialUpdateCollectResult collect_result)
-      : image(image), user(user), tile_data(image, image_user), collect_result(collect_result)
-  {
-  }
+  struct CollectResult {
+    PartialUpdateChecker<TileData> *checker;
+
+    /**
+     * \brief Tile specific data.
+     */
+    TileData tile_data;
+    PartialUpdateRegion changed_region;
+    ePartialUpdateCollectResult result_code;
+
+   private:
+    TileNumber last_tile_number;
+
+   public:
+    CollectResult(PartialUpdateChecker<TileData> *checker, ePartialUpdateCollectResult result_code)
+        : checker(checker),
+          tile_data(checker->image, *checker->image_user),
+          result_code(result_code)
+    {
+    }
 
-  const ePartialUpdateCollectResult get_collect_result() const
-  {
-    return collect_result;
-  }
+    const ePartialUpdateCollectResult get_result_code() const
+    {
+      return result_code;
+    }
 
-  ePartialUpdateIterResult get_next_change()
-  {
-    BLI_assert(collect_result == ePartialUpdateCollectResult::PartialChangesDetected);
-    ePartialUpdateIterResult result = BKE_image_partial_update_get_next_change(user,
-                                                                               &changed_region);
-    switch (result) {
-      case ePartialUpdateIterResult::Finished:
-        tile_data.free_data();
-        return result;
-
-      case ePartialUpdateIterResult::ChangeAvailable:
-        if (last_tile_number == changed_region.tile_number) {
+    /**
+     * \brief Load the next changed region.
+     *
+     * This member function can only be called when partial changes are detected.
+     * (`get_result_code()` returns `ePartialUpdateCollectResult::PartialChangesDetected`).
+     *
+     * When changes for another tile than the previous tile is loaded the #tile_data will be
+     * updated.
+     */
+    ePartialUpdateIterResult get_next_change()
+    {
+      BLI_assert(result_code == ePartialUpdateCollectResult::PartialChangesDetected);
+      ePartialUpdateIterResult result = BKE_image_partial_update_get_next_change(checker->user,
+                                                                                 &changed_region);
+      switch (result) {
+        case ePartialUpdateIterResult::Finished:
+          tile_data.free_data();
           return result;
-        }
-        tile_data.free_data();
-        tile_data.init_data(changed_region.tile_number);
-        last_tile_number = changed_region.tile_number;
-        return result;
-
-        ;
-      default:
-        BLI_assert_unreachable();
-        return result;
-    }
-  }
-};
 
-template<typename TileData = NoTileData> class PartialUpdateChecker {
+        case ePartialUpdateIterResult::ChangeAvailable:
+          if (last_tile_number == changed_region.tile_number) {
+            return result;
+          }
+          tile_data.free_data();
+          tile_data.init_data(changed_region.tile_number);
+          last_tile_number = changed_region.tile_number;
+          return result;
 
-  Image *image;
-  ImageUser *image_user;
-  PartialUpdateUser *user;
+        default:
+          BLI_assert_unreachable();
+          return result;
+      }
+    }
+  };
 
  public:
   PartialUpdateChecker(Image *image, ImageUser *image_user, PartialUpdateUser *user)
@@ -219,11 +280,14 @@ template<typename TileData = NoTileData> class PartialUpdateChecker {
   {
   }
 
-  PartialUpdateCollectResult<TileData> collect_changes()
+  /**
+   * \brief Check for new changes since the last time this method was invoked for this #user.
+   */
+  CollectResult collect_changes()
   {
     ePartialUpdateCollectResult collect_result = BKE_image_partial_update_collect_changes(image,
                                                                                           user);
-    return PartialUpdateCollectResult<TileData>(image, *image_user, user, collect_result);
+    return CollectResult(this, collect_result);
   }
 };
 
diff --git a/source/blender/blenkernel/intern/image_gpu.cc b/source/blender/blenkernel/intern/image_gpu.cc
index 14ea935bb36..070b6eb2a89 100644
--- a/source/blender/blenkernel/intern/image_gpu.cc
+++ b/source/blender/blenkernel/intern/image_gpu.cc
@@ -335,7 +335,7 @@ static void image_update_reusable_textures(Image *ima,
 }
 
 static void image_gpu_texture_partial_update_changes_available(
-    PartialUpdateCollectResult<ImageTileData> &changes)
+    Image *image, PartialUpdateChecker<ImageTileData>::CollectResult &changes)
 {
   while (changes.get_next_change() == ePartialUpdateIterResult::ChangeAvailable) {
     const int tile_offset_x = changes.changed_region.region.xmin;
@@ -344,7 +344,7 @@ static void image_gpu_texture_partial_update_changes_available(
                                   BLI_rcti_size_x(&changes.changed_region.region));
     const int tile_height = min_ii(changes.tile_data.tile_buffer->y,
                                    BLI_rcti_size_y(&changes.changed_region.region));
-    image_update_gputexture_ex(changes.image,
+    image_update_gputexture_ex(image,
                                changes.tile_data.tile,
                                changes.tile_data.tile_buffer,
                                tile_offset_x,
@@ -357,15 +357,15 @@ static void image_gpu_texture_partial_update_changes_available(
 static void image_gpu_texture_try_partial_update(Image *image, ImageUser *iuser)
 {
   PartialUpdateChecker<ImageTileData> checker(image, iuser, image->runtime.partial_update_user);
-  PartialUpdateCollectResult<ImageTileData> changes = checker.collect_changes();
-  switch (changes.get_collect_result()) {
+  PartialUpdateChecker<ImageTileData>::CollectResult changes = checker.collect_changes();
+  switch (changes.get_result_code()) {
     case ePartialUpdateCollectResult::FullUpdateNeeded: {
       image_free_gpu(image, true);
       break;
     }
 
     case ePartialUpdateCollectResult::PartialChangesDetected: {
-      image_g

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list