[Bf-blender-cvs] [eca92b3fb1c] temp-gpu-texture-partial-updates: WIP: partial update image.

Jeroen Bakker noreply at git.blender.org
Wed Nov 17 15:29:44 CET 2021


Commit: eca92b3fb1cb8cb17f21ace9b94ecdabe3b75b00
Author: Jeroen Bakker
Date:   Mon Nov 15 16:00:20 2021 +0100
Branches: temp-gpu-texture-partial-updates
https://developer.blender.org/rBeca92b3fb1cb8cb17f21ace9b94ecdabe3b75b00

WIP: partial update image.

Adding a basic mechanism that should be able to register tiles and find
changes. Not possible yet to loop over the updated tiles.
Next task would be to include reference to imbuf to get the width/height
of the images.

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

M	source/blender/blenkernel/BKE_image.h
M	source/blender/blenkernel/CMakeLists.txt
M	source/blender/blenkernel/intern/image.c
D	source/blender/blenkernel/intern/image_gpu_partial_update.cc
A	source/blender/blenkernel/intern/image_partial_update.cc
A	source/blender/blenkernel/intern/image_partial_update_test.cc
M	source/blender/makesdna/DNA_image_types.h

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

diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h
index 77f1d197844..bb600eb3f0c 100644
--- a/source/blender/blenkernel/BKE_image.h
+++ b/source/blender/blenkernel/BKE_image.h
@@ -24,6 +24,8 @@
 
 #include "BLI_utildefines.h"
 
+#include "BLI_rect.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -390,6 +392,89 @@ bool BKE_image_remove_renderslot(struct Image *ima, struct ImageUser *iuser, int
 struct RenderSlot *BKE_image_get_renderslot(struct Image *ima, int index);
 bool BKE_image_clear_renderslot(struct Image *ima, struct ImageUser *iuser, int slot);
 
+/* --- image_partial_update.cc --- */
+/** Image partial updates. */
+struct PartialUpdateUser;
+
+/**
+ * \brief Result codes of #BKE_image_partial_update_collect_tiles.
+ */
+typedef enum ePartialUpdateCollectResult {
+  /** \brief Unable to construct partial updates. Caller should perform a full update. */
+  PARTIAL_UPDATE_NEED_FULL_UPDATE,
+
+  /** \brief No changes detected since the last time requested. */
+  PARTIAL_UPDATE_NO_CHANGES,
+
+  /** \brief Changes detected sinve the last time requested. */
+  PARTIAL_UPDATE_CHANGES_AVAILABLE,
+} ePartialUpdateCollectResult;
+
+/**
+ * \brief A single tile to update.
+ *
+ * Data is organized in tiles. These tiles are in texel space (1 unit is a single texel). When
+ * tiles are requested they are merged with neighboring tiles.
+ */
+typedef struct PartialUpdateTile {
+  /** \brief area of the image that has been updated. */
+  struct rcti update_area;
+} PartialUpdateTile;
+
+/**
+ * \brief Return codes of #BKE_image_partial_update_next_tile.
+ */
+typedef enum ePartialUpdateIterResult {
+  /** \brief no tiles left when iterating over tiles. */
+  PARTIAL_UPDATE_ITER_NO_TILES_LEFT = 0,
+
+  /** \brief a tile was available and has been loaded. */
+  PARTIAL_UPDATE_ITER_NEW_TILE_LOADED = 1,
+} ePartialUpdateIterResult;
+
+/**
+ * \brief Create a new PartialUpdateUser. An Object that contains data to use partial updates.
+ */
+struct PartialUpdateUser *BKE_image_partial_update_create(struct Image *image);
+
+/**
+ * \brief free a partial update user.
+ */
+void BKE_image_partial_update_free(struct PartialUpdateUser *user);
+
+/**
+ * \brief collect the partial update since the last request.
+ *
+ * Invoke #BKE_image_partial_update_next_tile to iterate over the collected tiles.
+ *
+ * \returns PARTIAL_UPDATE_NEED_FULL_UPDATE: called should not use partial updates but
+ *              recalculate the full image. This result can be expected when called
+ *              for the first time for a user and when it isn't possible to reconstruct
+ *              the changes as the internal state doesn't have enough data stored.
+ *          PARTIAL_UPDATE_NO_CHANGES: The have been no changes detected since last
+ *              invoke for the same user.
+ *          PARTIAL_UPDATE_CHANGES_AVAILABLE: Parts of the image has been updated
+ *              since last invoke for the same user. The changes can be read by
+ *              using #BKE_image_partial_update_next_tile.
+ */
+ePartialUpdateCollectResult BKE_image_partial_update_collect_tiles(struct Image *image,
+                                                                   struct PartialUpdateUser *user);
+
+ePartialUpdateIterResult BKE_image_partial_update_next_tile(struct PartialUpdateUser *user,
+                                                            struct PartialUpdateTile *r_tile);
+
+/* --- partial updater (image side) --- */
+struct PartialUpdateRegister;
+
+struct PartialUpdateRegister *BKE_image_partial_update_register_ensure(struct Image *image,
+                                                                       struct ImBuf *image_buffer);
+void BKE_image_partial_update_register_free(struct Image *image);
+/** \brief Mark a region of the image to update. */
+void BKE_image_partial_update_register_mark_region(struct Image *image, rcti *updated_region);
+/** \brief Mark the whole image to be updated. */
+void BKE_image_partial_update_register_mark_full_update(struct Image *image,
+                                                        struct ImBuf *image_buffer);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index b2418d0539c..900a1d6f99c 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -163,6 +163,7 @@ set(SRC
   intern/idprop_utils.c
   intern/idtype.c
   intern/image.c
+  intern/image_partial_update.cc
   intern/image_gen.c
   intern/image_gpu.c
   intern/image_save.c
@@ -808,6 +809,7 @@ if(WITH_GTESTS)
     intern/asset_test.cc
     intern/cryptomatte_test.cc
     intern/fcurve_test.cc
+    intern/image_partial_update_test.cc
     intern/lattice_deform_test.cc
     intern/layer_test.cc
     intern/lib_id_test.cc
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index c0efc246567..e17d0f33d93 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -130,6 +130,8 @@ static void image_runtime_reset_on_copy(struct Image *image)
 {
   image->runtime.cache_mutex = MEM_mallocN(sizeof(ThreadMutex), "image runtime cache_mutex");
   BLI_mutex_init(image->runtime.cache_mutex);
+
+  image->runtime.partial_update_register = NULL;
 }
 
 static void image_init_data(ID *id)
diff --git a/source/blender/blenkernel/intern/image_gpu_partial_update.cc b/source/blender/blenkernel/intern/image_gpu_partial_update.cc
deleted file mode 100644
index cfbf01dc21e..00000000000
--- a/source/blender/blenkernel/intern/image_gpu_partial_update.cc
+++ /dev/null
@@ -1,149 +0,0 @@
-
-/**
- * \file image_gpu_partial_update.cc
- *
- * To reduce the overhead of uploading images to GPU only changed areas will be uploaded.
- * The areas are organized in tiles.
- *
- * Requirements:
- * - Independent how the actual GPU textures look like. The uploading, transforming are
- *   responsibility of the user of this API.
- *
- *
- * Usage:
- *
- * ```
- * Image *image = space_data->image;
- * PartialUpdateUser* partial_update_user = BKE_image_partial_update_create(image);
- *
- * if (BKE_image_partial_update_collect_tiles(image, partial_update_user) == DO_FULL_UPDATE {
- *   // Recreate full GPU texture.
- *   ...
- * } else {
- *   PartialUpdateTile tile;
- *  int index = 0;
- *   while(BKE_image_partial_update_get_tile(partial_update_user, index++, &tile) == TILE_VALID) {
- *     // Do something with the tile.
- *     ...
- *   }
- * }
- *
- * BKE_image_partial_update_free(partial_update_user);
- *
- * ```
- */
-
-#include "DNA_image_types.h"
-
-#include "BLI_vector.hh"
-
-namespace blender::bke::image {
-
-/**
- * \brief A single tile to update.
- *
- * Data is organized in tiles. These tiles are in texel space (1 unit is a single texel). When
- * tiles are requested they are merged with neighboring tiles.
- */
-struct PartialUpdateTile {
-  /** \brief area of the image that has been updated. */
-  rcti update_area;
-};
-
-using TransactionID = int;
-
-struct PartialUpdateUser {
- private:
-  TransactionID last_transaction_id;
-
-  /** \brief tiles that have been updated. */
-  Vector<PartialUpdateTile> changed_tiles;
-};
-
-struct PartialUpdateTransaction {
-  /* bitvec for each tile in the transaction. True means that this tile was changed during during
-   * this transaction. */
-  Vector<bool> tile_validity;
-  bool is_empty = true;
-
-  bool is_empty()
-  {
-    return is_empty;
-  }
-};
-
-/** \brief Partial update data that is stored inside the image. */
-struct PartialUpdateImage {
-  TransactionID first_transaction_id;
-  TransactionID current_transaction_id;
-  Vector<PartialUpdateTransaction> history;
-
-  PartialUpdateTransaction current_transaction;
-
-  void invalidate_tile(int tile_x, int tile_y)
-  {
-  }
-
-  void ensure_empty_transaction()
-  {
-    if (current_transaction.is_empty()) {
-      /* No need to create a new transaction when previous transaction does not contain any data.
-       */
-      return;
-    }
-    commit_current_transaction();
-  }
-
-  void commit_current_transaction()
-  {
-    history.append_as(std::move(current_transaction));
-    current_transaction_id++;
-  }
-}
-
-}  // namespace blender::bke::image
-
-extern "C" {
-struct PartialUpdateUser;
-using namespace blender::bke::image;
-
-PartialUpdateUser *BKE_image_partial_update_create(Image *image)
-{
-  return nullptr;
-}
-
-void BKE_image_partial_update_free(PartialUpdateUser *user)
-{
-}
-
-bool BKE_image_partial_update_collect_tiles(Image *image, PartialUpdateUser *user)
-{
-  user->clear_updated_tiles();
-  PartialUpdateImage *partial_updater = nullptr;  //*image->partial_updater;
-  partial_updater->ensure_empty_transaction();
-
-  if (user->last_transaction_id < partial_updater->first_transaction_id) {
-    user->last_transaction_id = partial_updater->current_transaction_id;
-    return NEED_FULL_UPDATE;
-  }
-
-  if (user->last_transaction_id == partial_updater->current_transaction_id) {
-    // No changes since last time.
-    return NO_CHANGES_SINCE_LAST_TIME;
-  }
-
-  // TODO: Collect changes between last_transaction_id and current_transaction_id.
-  // TODO: compress neighboring tiles and store in user.
-
-  user->last_transaction_id = partial_updated->current_transaction_id;
-  return CHANGES_DETECTED;
-}
-
-bool BKE_image_partial_update_get_tile(PartialUpdateUser *user,
-                                       int index,
-                                       PartialUpdateTile *r_tile)
-{
-  return NO_TILES_LEFT;
-}
-
-}
\ No newline at end of file
diff --git a/source/blender/blenkernel/intern/image_partial_update.cc b/source/blender/blenkernel/intern/image_partial_update.cc
new file mode 100644
index 00000000000..89fa5889c96
--- /dev/null
+++ b/source/blender/blenkernel/intern/image_partial_update.cc
@@ -0,0 +1,313 @@
+
+/**
+ * \file image_gpu_partial_update.cc
+ *
+ * To reduce the overhead of uploading images to GPU only changed areas will be uploaded.
+ * The areas are organized in tiles.
+ *
+ * Requirements:
+ * - Independent how the actual GPU textures look like. The uploading, transforming are
+ *   responsibility of the user

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list