[Bf-blender-cvs] [152ad1c2088] temp-gpu-texture-partial-updates: Clearing history.

Jeroen Bakker noreply at git.blender.org
Fri Nov 19 15:23:18 CET 2021


Commit: 152ad1c2088747aa18dc82683f351de8bdf2b00d
Author: Jeroen Bakker
Date:   Fri Nov 19 14:06:41 2021 +0100
Branches: temp-gpu-texture-partial-updates
https://developer.blender.org/rB152ad1c2088747aa18dc82683f351de8bdf2b00d

Clearing history.

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

M	source/blender/blenkernel/BKE_image.h
M	source/blender/blenkernel/intern/image_gpu.c
M	source/blender/blenkernel/intern/image_partial_update.cc
M	source/blender/blenkernel/intern/image_partial_update_test.cc
M	source/blender/imbuf/intern/moviecache.c

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

diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h
index 9b3bc89a0e7..5efc5e53ff2 100644
--- a/source/blender/blenkernel/BKE_image.h
+++ b/source/blender/blenkernel/BKE_image.h
@@ -483,9 +483,9 @@ struct PartialUpdateRegister;
 void BKE_image_partial_update_register_free(struct Image *image);
 /** \brief Mark a region of the image to update. */
 void BKE_image_partial_update_mark_region(struct Image *image,
-                                          struct ImageTile *image_tile,
-                                          struct ImBuf *image_buffer,
-                                          rcti *updated_region);
+                                          const struct ImageTile *image_tile,
+                                          const struct ImBuf *image_buffer,
+                                          const rcti *updated_region);
 /** \brief Mark the whole image to be updated. */
 void BKE_image_partial_update_mark_full_update(struct Image *image);
 
diff --git a/source/blender/blenkernel/intern/image_gpu.c b/source/blender/blenkernel/intern/image_gpu.c
index 15444dcf7c5..c980d945946 100644
--- a/source/blender/blenkernel/intern/image_gpu.c
+++ b/source/blender/blenkernel/intern/image_gpu.c
@@ -945,7 +945,8 @@ void BKE_image_update_gputexture_delayed(struct Image *ima,
                                          int h)
 {
   /* Check for full refresh. */
-  if (ibuf && image_tile->tile_number == 0 && x == 0 && y == 0 && w == ibuf->x && h == ibuf->y) {
+  if (ibuf != NULL && ima->source != IMA_SRC_TILED && x == 0 && y == 0 && w == ibuf->x &&
+      h == ibuf->y) {
     BKE_image_partial_update_mark_full_update(ima);
   }
   else {
diff --git a/source/blender/blenkernel/intern/image_partial_update.cc b/source/blender/blenkernel/intern/image_partial_update.cc
index b12b83bae9e..63e6ef7feb2 100644
--- a/source/blender/blenkernel/intern/image_partial_update.cc
+++ b/source/blender/blenkernel/intern/image_partial_update.cc
@@ -60,6 +60,18 @@ namespace blender::bke::image::partial_update {
 /** \brief Size of chunks to track changes. */
 constexpr int CHUNK_SIZE = 256;
 
+/**
+ * \brief Max number of changesets to keep in history.
+ *
+ * A higher number would need more memory and processing
+ * to calculate a changeset, but would lead to do partial updates for requests that don't happen
+ * every frame.
+ *
+ * A to small number would lead to more full updates when changes couldn't be reconstructed from
+ * the available history.
+ */
+constexpr int MAX_HISTORY_LEN = 4;
+
 /**
  * \brief get the chunk number for the give pixel coordinate.
  *
@@ -154,16 +166,18 @@ struct TileChangeset {
  public:
   /** \brief Width of the tile in pixels. */
   int tile_width;
-  /** \brief Hieght of the tile in pixels. */
+  /** \brief Height of the tile in pixels. */
   int tile_height;
   /** \brief Number of chunks along the x-axis. */
-  int chunk_x_len_;
+  int chunk_x_len;
   /** \brief Number of chunks along the y-axis. */
-  int chunk_y_len_;
+  int chunk_y_len;
+
+  TileNumber tile_number;
 
   void clear()
   {
-    init_chunks(chunk_x_len_, chunk_y_len_);
+    init_chunks(chunk_x_len, chunk_y_len);
   }
 
   /**
@@ -172,7 +186,7 @@ struct TileChangeset {
    * \returns true: resolution has been updated.
    *          false: resolution was unchanged.
    */
-  bool update_resolution(ImBuf *image_buffer)
+  bool update_resolution(const ImBuf *image_buffer)
   {
     if (tile_width == image_buffer->x && tile_height == image_buffer->y) {
       return false;
@@ -187,7 +201,7 @@ struct TileChangeset {
     return true;
   }
 
-  void mark_region(rcti *updated_region)
+  void mark_region(const rcti *updated_region)
   {
     int start_x_chunk = chunk_number_for_pixel(updated_region->xmin);
     int end_x_chunk = chunk_number_for_pixel(updated_region->xmax - 1);
@@ -197,14 +211,14 @@ struct TileChangeset {
     /* Clamp tiles to tiles in image. */
     start_x_chunk = max_ii(0, start_x_chunk);
     start_y_chunk = max_ii(0, start_y_chunk);
-    end_x_chunk = min_ii(chunk_x_len_ - 1, end_x_chunk);
-    end_y_chunk = min_ii(chunk_y_len_ - 1, end_y_chunk);
+    end_x_chunk = min_ii(chunk_x_len - 1, end_x_chunk);
+    end_y_chunk = min_ii(chunk_y_len - 1, end_y_chunk);
 
     /* Early exit when no tiles need to be updated. */
-    if (start_x_chunk >= chunk_x_len_) {
+    if (start_x_chunk >= chunk_x_len) {
       return;
     }
-    if (start_y_chunk >= chunk_y_len_) {
+    if (start_y_chunk >= chunk_y_len) {
       return;
     }
     if (end_x_chunk < 0) {
@@ -221,7 +235,7 @@ struct TileChangeset {
   {
     for (int chunk_y = start_y_chunk; chunk_y <= end_y_chunk; chunk_y++) {
       for (int chunk_x = start_x_chunk; chunk_x <= end_x_chunk; chunk_x++) {
-        int chunk_index = chunk_y * chunk_x_len_ + chunk_x;
+        int chunk_index = chunk_y * chunk_x_len + chunk_x;
         chunk_dirty_flags_[chunk_index] = true;
       }
     }
@@ -233,10 +247,10 @@ struct TileChangeset {
     return has_dirty_chunks_;
   }
 
-  void init_chunks(int chunk_x_len, int chunk_y_len)
+  void init_chunks(int chunk_x_len_, int chunk_y_len_)
   {
-    chunk_x_len_ = chunk_x_len;
-    chunk_y_len_ = chunk_y_len;
+    chunk_x_len = chunk_x_len_;
+    chunk_y_len = chunk_y_len_;
     const int chunk_len = chunk_x_len * chunk_y_len;
     const int previous_chunk_len = chunk_dirty_flags_.size();
 
@@ -254,9 +268,9 @@ struct TileChangeset {
   /** \brief Merge the given changeset into the receiver. */
   void merge(const TileChangeset &other)
   {
-    BLI_assert(chunk_x_len_ == other.chunk_x_len_);
-    BLI_assert(chunk_y_len_ == other.chunk_y_len_);
-    const int chunk_len = chunk_x_len_ * chunk_y_len_;
+    BLI_assert(chunk_x_len == other.chunk_x_len);
+    BLI_assert(chunk_y_len == other.chunk_y_len);
+    const int chunk_len = chunk_x_len * chunk_y_len;
 
     for (int chunk_index = 0; chunk_index < chunk_len; chunk_index++) {
       chunk_dirty_flags_[chunk_index] = chunk_dirty_flags_[chunk_index] |
@@ -268,27 +282,56 @@ struct TileChangeset {
   /** \brief has a chunk changed inside this changeset. */
   bool is_chunk_dirty(int chunk_x, int chunk_y) const
   {
-    const int chunk_index = chunk_y * chunk_x_len_ + chunk_x;
+    const int chunk_index = chunk_y * chunk_x_len + chunk_x;
     return chunk_dirty_flags_[chunk_index];
   }
 };
 
+/** \brief Changeset keeping track of changes for an image */
 struct Changeset {
  private:
-  TileChangeset tile_changeset;
+  Vector<TileChangeset> tiles;
 
  public:
+  /** \brief Keep track if any of the tiles have dirty chunks. */
   bool has_dirty_chunks;
 
  public:
-  TileChangeset &operator[](ImageTile *UNUSED(image_tile))
+  /**
+   * \brief Retrieve the TileChangeset for the given ImageTile.
+   *
+   * When the TileChangeset isn't found, it will be added.
+   */
+  TileChangeset &operator[](const ImageTile *image_tile)
+  {
+    for (TileChangeset &tile_changeset : tiles) {
+      if (tile_changeset.tile_number == image_tile->tile_number) {
+        return tile_changeset;
+      }
+    }
+
+    TileChangeset tile_changeset;
+    tile_changeset.tile_number = image_tile->tile_number;
+    tiles.append_as(tile_changeset);
+
+    return tiles.last();
+  }
+
+  /** \brief Does this changeset contain data for the given tile. */
+  bool has_tile(const ImageTile *image_tile)
   {
-    return tile_changeset;
+    for (TileChangeset &tile_changeset : tiles) {
+      if (tile_changeset.tile_number == image_tile->tile_number) {
+        return true;
+      }
+    }
+    return false;
   }
 
+  /** \brief Clear this changeset. */
   void clear()
   {
-    tile_changeset.clear();
+    tiles.clear();
     has_dirty_chunks = false;
   }
 };
@@ -307,10 +350,10 @@ struct PartialUpdateRegisterImpl {
 
   /** \brief history of changesets. */
   Vector<Changeset> history;
-  /** \brief The current changeset. New changes will be added to this changeset only. */
+  /** \brief The current changeset. New changes will be added to this changeset. */
   Changeset current_changeset;
 
-  void update_resolution(ImageTile *image_tile, ImBuf *image_buffer)
+  void update_resolution(const ImageTile *image_tile, const ImBuf *image_buffer)
   {
     TileChangeset &tile_changeset = current_changeset[image_tile];
     const bool has_dirty_chunks = tile_changeset.has_dirty_chunks();
@@ -329,7 +372,7 @@ struct PartialUpdateRegisterImpl {
     first_changeset_id = last_changeset_id;
   }
 
-  void mark_region(ImageTile *image_tile, rcti *updated_region)
+  void mark_region(const ImageTile *image_tile, const rcti *updated_region)
   {
     TileChangeset &tile_changeset = current_changeset[image_tile];
     tile_changeset.mark_region(updated_region);
@@ -344,9 +387,10 @@ struct PartialUpdateRegisterImpl {
       return;
     }
     commit_current_changeset();
+    limit_history();
   }
 
-  /** Move the current changeset to the history and resets the current changeset. */
+  /** \brief Move the current changeset to the history and resets the current changeset. */
   void commit_current_changeset()
   {
     history.append_as(std::move(current_changeset));
@@ -354,6 +398,16 @@ struct PartialUpdateRegisterImpl {
     last_changeset_id++;
   }
 
+  /** \brief Limit the number of items in the changeset. */
+  void limit_history()
+  {
+    const int num_items_to_remove = max_ii(history.size() - MAX_HISTORY_LEN, 0);
+    if (num_items_to_remove == 0) {
+      return;
+    }
+    history.remove(0, num_items_to_remove);
+  }
+
   /**
    * /brief Check if data is available to construct the update tiles for the given
    * changeset_id.
@@ -368,15 +422,9 @@ struct PartialUpdateRegisterImpl {
   /**
    * \brief collect all historic changes since a given changeset.
    */
-  // TODO(jbakker): add tile_number as parameter.
-  std::optional<TileChangeset> changed_tile_chunks_since(const TileNumber UNUSED(tile_number),
+  std::optional<TileChangeset> changed_tile_chunks_since(const ImageTile *image_tile,
                                                          const ChangesetID from_changeset)
   {
-    std::unique_ptr<TileChangeset> changed_tiles = std::make_unique<TileChangeset>();
-    int chunk_x_len = image_width / CHUNK_SIZE;
-   

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list