[Bf-blender-cvs] [ed7d12e7113] temp-gpu-texture-partial-updates: WIP adding tiles between chunks and images.

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


Commit: ed7d12e7113c2c0cac1eba08e5cf95be2d3d9d3f
Author: Jeroen Bakker
Date:   Fri Nov 19 09:54:01 2021 +0100
Branches: temp-gpu-texture-partial-updates
https://developer.blender.org/rBed7d12e7113c2c0cac1eba08e5cf95be2d3d9d3f

WIP adding tiles between chunks and images.

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

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/editors/render/render_internal.c

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

diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h
index 301f4f0f440..9b3bc89a0e7 100644
--- a/source/blender/blenkernel/BKE_image.h
+++ b/source/blender/blenkernel/BKE_image.h
@@ -380,8 +380,13 @@ struct GPUTexture *BKE_image_get_gpu_tilemap(struct Image *image,
 bool BKE_image_has_gpu_texture_premultiplied_alpha(struct Image *image, struct ImBuf *ibuf);
 void BKE_image_update_gputexture(
     struct Image *ima, struct ImageUser *iuser, int x, int y, int w, int h);
-void BKE_image_update_gputexture_delayed(
-    struct Image *ima, struct ImBuf *ibuf, int x, int y, int w, int h);
+void BKE_image_update_gputexture_delayed(struct Image *ima,
+                                         struct ImageTile *image_tile,
+                                         struct ImBuf *ibuf,
+                                         int x,
+                                         int y,
+                                         int w,
+                                         int h);
 void BKE_image_paint_set_mipmap(struct Main *bmain, bool mipmap);
 
 /* Delayed free of OpenGL buffers by main thread */
@@ -423,7 +428,7 @@ typedef struct PartialUpdateRegion {
 
   /**
    * \brief Tile number that this region belongs to.
-   * 
+   *
    * For tiled images it contains the UDIM tile number (1001, 1010).
    * For non tiled images this is set to 0.
    */
@@ -478,6 +483,7 @@ 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);
 /** \brief Mark the whole image to be updated. */
diff --git a/source/blender/blenkernel/intern/image_gpu.c b/source/blender/blenkernel/intern/image_gpu.c
index 17ecc82809a..15444dcf7c5 100644
--- a/source/blender/blenkernel/intern/image_gpu.c
+++ b/source/blender/blenkernel/intern/image_gpu.c
@@ -926,8 +926,9 @@ static void image_update_gputexture_ex(
  * texture user is decentralized. */
 void BKE_image_update_gputexture(Image *ima, ImageUser *iuser, int x, int y, int w, int h)
 {
+  ImageTile *image_tile = BKE_image_get_tile_from_iuser(ima, iuser);
   ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
-  BKE_image_update_gputexture_delayed(ima, ibuf, x, y, w, h);
+  BKE_image_update_gputexture_delayed(ima, image_tile, ibuf, x, y, w, h);
   BKE_image_release_ibuf(ima, ibuf, NULL);
 }
 
@@ -935,17 +936,22 @@ void BKE_image_update_gputexture(Image *ima, ImageUser *iuser, int x, int y, int
  * The next time the GPUTexture is used these tiles will be refreshes. This saves time
  * when writing to the same place multiple times This happens for during foreground
  * rendering. */
-void BKE_image_update_gputexture_delayed(
-    struct Image *ima, struct ImBuf *ibuf, int x, int y, int w, int h)
+void BKE_image_update_gputexture_delayed(struct Image *ima,
+                                         struct ImageTile *image_tile,
+                                         struct ImBuf *ibuf,
+                                         int x,
+                                         int y,
+                                         int w,
+                                         int h)
 {
   /* Check for full refresh. */
-  if (ibuf && x == 0 && y == 0 && w == ibuf->x && h == ibuf->y) {
+  if (ibuf && image_tile->tile_number == 0 && x == 0 && y == 0 && w == ibuf->x && h == ibuf->y) {
     BKE_image_partial_update_mark_full_update(ima);
   }
   else {
     rcti dirty_region;
     BLI_rcti_init(&dirty_region, x, x + w, y, y + h);
-    BKE_image_partial_update_mark_region(ima, ibuf, &dirty_region);
+    BKE_image_partial_update_mark_region(ima, image_tile, ibuf, &dirty_region);
   }
 }
 
diff --git a/source/blender/blenkernel/intern/image_partial_update.cc b/source/blender/blenkernel/intern/image_partial_update.cc
index 4520d9c645d..b12b83bae9e 100644
--- a/source/blender/blenkernel/intern/image_partial_update.cc
+++ b/source/blender/blenkernel/intern/image_partial_update.cc
@@ -14,7 +14,7 @@
  * Image *image = ...;
  * ImBuf *image_buffer = ...;
  *
- * // partial_update_user should be kept for the whole session where the changes needs to be
+ * // Partial_update_user should be kept for the whole session where the changes needs to be
  * // tracked. Keep this instance alive as long as you need to track image changes.
  *
  * PartialUpdateUser *partial_update_user = BKE_image_partial_update_create(image);
@@ -44,6 +44,8 @@
  * ```
  */
 
+#include <optional>
+
 #include "BKE_image.h"
 
 #include "DNA_image_types.h"
@@ -55,6 +57,23 @@
 
 namespace blender::bke::image::partial_update {
 
+/** \brief Size of chunks to track changes. */
+constexpr int CHUNK_SIZE = 256;
+
+/**
+ * \brief get the chunk number for the give pixel coordinate.
+ *
+ * As chunks are squares the this member can be used for both x and y axis.
+ */
+static int chunk_number_for_pixel(int pixel_offset)
+{
+  int chunk_offset = pixel_offset / CHUNK_SIZE;
+  if (pixel_offset < 0) {
+    chunk_offset -= 1;
+  }
+  return chunk_offset;
+}
+
 struct PartialUpdateUserImpl;
 struct PartialUpdateRegisterImpl;
 
@@ -133,11 +152,82 @@ struct TileChangeset {
   bool has_dirty_chunks_ = false;
 
  public:
+  /** \brief Width of the tile in pixels. */
+  int tile_width;
+  /** \brief Hieght of the tile in pixels. */
+  int tile_height;
   /** \brief Number of chunks along the x-axis. */
   int chunk_x_len_;
   /** \brief Number of chunks along the y-axis. */
   int chunk_y_len_;
 
+  void clear()
+  {
+    init_chunks(chunk_x_len_, chunk_y_len_);
+  }
+
+  /**
+   * \brief Update the resolution of the tile.
+   *
+   * \returns true: resolution has been updated.
+   *          false: resolution was unchanged.
+   */
+  bool update_resolution(ImBuf *image_buffer)
+  {
+    if (tile_width == image_buffer->x && tile_height == image_buffer->y) {
+      return false;
+    }
+
+    tile_width = image_buffer->x;
+    tile_height = image_buffer->y;
+
+    int chunk_x_len = tile_width / CHUNK_SIZE;
+    int chunk_y_len = tile_height / CHUNK_SIZE;
+    init_chunks(chunk_x_len, chunk_y_len);
+    return true;
+  }
+
+  void mark_region(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);
+    int start_y_chunk = chunk_number_for_pixel(updated_region->ymin);
+    int end_y_chunk = chunk_number_for_pixel(updated_region->ymax - 1);
+
+    /* 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);
+
+    /* Early exit when no tiles need to be updated. */
+    if (start_x_chunk >= chunk_x_len_) {
+      return;
+    }
+    if (start_y_chunk >= chunk_y_len_) {
+      return;
+    }
+    if (end_x_chunk < 0) {
+      return;
+    }
+    if (end_y_chunk < 0) {
+      return;
+    }
+
+    mark_chunks_dirty(start_x_chunk, start_y_chunk, end_x_chunk, end_y_chunk);
+  }
+
+  void mark_chunks_dirty(int start_x_chunk, int start_y_chunk, int end_x_chunk, int end_y_chunk)
+  {
+    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;
+        chunk_dirty_flags_[chunk_index] = true;
+      }
+    }
+    has_dirty_chunks_ = true;
+  }
+
   bool has_dirty_chunks() const
   {
     return has_dirty_chunks_;
@@ -161,22 +251,6 @@ struct TileChangeset {
     has_dirty_chunks_ = false;
   }
 
-  void reset()
-  {
-    init_chunks(chunk_x_len_, chunk_y_len_);
-  }
-
-  void mark_chunks_dirty(int start_x_chunk, int start_y_chunk, int end_x_chunk, int end_y_chunk)
-  {
-    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;
-        chunk_dirty_flags_[chunk_index] = true;
-      }
-    }
-    has_dirty_chunks_ = true;
-  }
-
   /** \brief Merge the given changeset into the receiver. */
   void merge(const TileChangeset &other)
   {
@@ -200,7 +274,23 @@ struct TileChangeset {
 };
 
 struct Changeset {
+ private:
   TileChangeset tile_changeset;
+
+ public:
+  bool has_dirty_chunks;
+
+ public:
+  TileChangeset &operator[](ImageTile *UNUSED(image_tile))
+  {
+    return tile_changeset;
+  }
+
+  void clear()
+  {
+    tile_changeset.clear();
+    has_dirty_chunks = false;
+  }
 };
 
 /**
@@ -210,9 +300,6 @@ struct Changeset {
  * TileChangesets.
  */
 struct PartialUpdateRegisterImpl {
-  /* Changes are tracked in chunks. */
-  static constexpr int CHUNK_SIZE = 256;
-
   /** \brief changeset id of the first changeset kept in #history. */
   ChangesetID first_changeset_id;
   /** \brief changeset id of the top changeset kept in #history. */
@@ -223,23 +310,14 @@ struct PartialUpdateRegisterImpl {
   /** \brief The current changeset. New changes will be added to this changeset only. */
   Changeset current_changeset;
 
-  int image_width;
-  int image_height;
-
-  void update_resolution(ImBuf *image_buffer)
+  void update_resolution(ImageTile *image_tile, ImBuf *image_buffer)
   {
-    if (image_width != image_buffer->x || image_height != image_buffer->y) {
-      image_width = image_buffer->x;
-      image_height = image_buffer->y;
+    TileChangeset &tile_changeset = current_changeset[image_tile];
+    const bool has_dirty_chunks = tile_changeset.has_dirty_chunks();
+    const bool resolution_changed = tile_changeset.update_resolution(image_buffer);
 
-      int chunk_x_len = image_width / CHUNK_SIZE;
-      int chunk_y_len = image_height / CHUNK_SIZE;
-      current_changeset.tile_changeset.init_chunks(chunk_x_len, chunk_y_len);
-
-      /* Only perform a full update when the cache contains data. */
-      if (current_change

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list