[Bf-blender-cvs] [7bd6a318e38] temp-gpu-texture-partial-updates: More tests and cleanups.
Jeroen Bakker
noreply at git.blender.org
Wed Nov 17 15:29:44 CET 2021
Commit: 7bd6a318e383c2cb22472fec1e3ffb9ae0015bd0
Author: Jeroen Bakker
Date: Tue Nov 16 12:35:57 2021 +0100
Branches: temp-gpu-texture-partial-updates
https://developer.blender.org/rB7bd6a318e383c2cb22472fec1e3ffb9ae0015bd0
More tests and cleanups.
===================================================================
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/intern/image_partial_update.cc b/source/blender/blenkernel/intern/image_partial_update.cc
index 12c251ed484..1eb054018b7 100644
--- a/source/blender/blenkernel/intern/image_partial_update.cc
+++ b/source/blender/blenkernel/intern/image_partial_update.cc
@@ -3,7 +3,7 @@
* \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.
+ * The areas are organized in tiles. Changed tiles over time are organized in changesets.
*
* Requirements:
* - Independent how the actual GPU textures look like. The uploading, transforming are
@@ -21,7 +21,6 @@
* ...
* } 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.
* ...
@@ -67,12 +66,12 @@ static PartialUpdateRegisterImpl *unwrap(struct PartialUpdateRegister *partial_u
return static_cast<PartialUpdateRegisterImpl *>(static_cast<void *>(partial_update_register));
}
-using TransactionID = int64_t;
-constexpr TransactionID UnknownTransactionID = -1;
+using ChangesetID = int64_t;
+constexpr ChangesetID UnknownChangesetID = -1;
struct PartialUpdateUserImpl {
- /** \brief last transaction id that was seen by this user. */
- TransactionID last_transaction_id = UnknownTransactionID;
+ /** \brief last changeset id that was seen by this user. */
+ ChangesetID last_changeset_id = UnknownChangesetID;
/** \brief tiles that have been updated. */
Vector<PartialUpdateTile> updated_tiles;
@@ -88,17 +87,28 @@ struct PartialUpdateUserImpl {
}
};
-struct PartialUpdateTransaction {
- /* bitvec for each tile in the transaction. True means that this tile was changed during during
- * this transaction. */
- Vector<bool> tile_validity;
+/**
+ * \brief Dirty tiles.
+ *
+ * Internally dirty tiles are grouped together in change sets to make sure that the correct answer
+ * can be built for different users reducing the amount of merges.
+ */
+struct TileChangeset {
+ private:
+ /** \brief Dirty flag for each tile. */
+ std::vector<bool> tile_dirty_flags_;
+ /** \brief are there dirty/ */
+ bool has_dirty_tiles_ = false;
+
+ public:
+ /** \brief Number of tiles along the x-axis. */
int tile_x_len_;
+ /** \brief Number of tiles along the y-axis. */
int tile_y_len_;
- bool is_empty_ = true;
- bool is_empty()
+ bool has_dirty_tiles() const
{
- return is_empty_;
+ return has_dirty_tiles();
}
void init_tiles(int tile_x_len, int tile_y_len)
@@ -106,15 +116,17 @@ struct PartialUpdateTransaction {
tile_x_len_ = tile_x_len;
tile_y_len_ = tile_y_len;
const int tile_len = tile_x_len * tile_y_len;
- tile_validity.resize(tile_len);
- /* Fast exit. When the transaction was already empty no need to re-init the tile_validity. */
- if (is_empty()) {
+ const int previous_tile_len = tile_dirty_flags_.size();
+
+ tile_dirty_flags_.resize(tile_len);
+ /* Fast exit. When the changeset was already empty no need to re-init the tile_validity. */
+ if (!has_dirty_tiles()) {
return;
}
- for (int index = 0; index < tile_len; index++) {
- tile_validity[index] = false;
+ for (int index = 0; index < min_ii(tile_len, previous_tile_len); index++) {
+ tile_dirty_flags_[index] = false;
}
- is_empty_ = true;
+ has_dirty_tiles_ = false;
}
void reset()
@@ -127,32 +139,31 @@ struct PartialUpdateTransaction {
for (int tile_y = start_y_tile; tile_y <= end_y_tile; tile_y++) {
for (int tile_x = start_x_tile; tile_x <= end_x_tile; tile_x++) {
int tile_index = tile_y * tile_x_len_ + tile_x;
- tile_validity[tile_index] = true;
+ tile_dirty_flags_[tile_index] = true;
}
}
- is_empty_ = false;
+ has_dirty_tiles_ = true;
}
- /** \brief Merge the given transaction into the receiver. */
- void merge(PartialUpdateTransaction &other)
+ /** \brief Merge the given changeset into the receiver. */
+ void merge(const TileChangeset &other)
{
BLI_assert(tile_x_len_ == other.tile_x_len_);
BLI_assert(tile_y_len_ == other.tile_y_len_);
const int tile_len = tile_x_len_ * tile_y_len_;
for (int tile_index = 0; tile_index < tile_len; tile_index++) {
- tile_validity[tile_index] |= other.tile_validity[tile_index];
- }
- if (!other.is_empty()) {
- is_empty_ = false;
+ tile_dirty_flags_[tile_index] = tile_dirty_flags_[tile_index] |
+ other.tile_dirty_flags_[tile_index];
}
+ has_dirty_tiles_ |= other.has_dirty_tiles_;
}
- /** \brief has a tile changed inside this transaction. */
- bool tile_changed(int tile_x, int tile_y)
+ /** \brief has a tile changed inside this changeset. */
+ bool is_tile_dirty(int tile_x, int tile_y) const
{
- int tile_index = tile_y * tile_x_len_ + tile_x;
- return tile_validity[tile_index];
+ const int tile_index = tile_y * tile_x_len_ + tile_x;
+ return tile_dirty_flags_[tile_index];
}
};
@@ -161,11 +172,11 @@ struct PartialUpdateRegisterImpl {
/* Changes are tracked in tiles. */
static constexpr int TILE_SIZE = 256;
- TransactionID first_transaction_id;
- TransactionID current_transaction_id;
- Vector<PartialUpdateTransaction> history;
+ ChangesetID first_changeset_id;
+ ChangesetID current_changeset_id;
+ Vector<TileChangeset> history;
- PartialUpdateTransaction current_transaction;
+ TileChangeset current_changeset;
int image_width;
int image_height;
@@ -178,7 +189,7 @@ struct PartialUpdateRegisterImpl {
int tile_x_len = image_width / TILE_SIZE;
int tile_y_len = image_height / TILE_SIZE;
- current_transaction.init_tiles(tile_x_len, tile_y_len);
+ current_changeset.init_tiles(tile_x_len, tile_y_len);
mark_full_update();
}
@@ -187,29 +198,43 @@ struct PartialUpdateRegisterImpl {
void mark_full_update()
{
history.clear();
- current_transaction_id++;
- current_transaction.reset();
- first_transaction_id = current_transaction_id;
+ current_changeset_id++;
+ current_changeset.reset();
+ first_changeset_id = current_changeset_id;
+ }
+
+ /**
+ * \brief get the tile number for the give pixel coordinate.
+ *
+ * As tiles are squares the this member can be used for both x and y axis.
+ */
+ static int tile_number_for_pixel(int pixel_offset)
+ {
+ int tile_offset = pixel_offset / TILE_SIZE;
+ if (pixel_offset < 0) {
+ tile_offset -= 1;
+ }
+ return tile_offset;
}
void mark_region(rcti *updated_region)
{
- int start_x_tile = updated_region->xmin / TILE_SIZE;
- int end_x_tile = updated_region->xmax / TILE_SIZE;
- int start_y_tile = updated_region->ymin / TILE_SIZE;
- int end_y_tile = updated_region->ymax / TILE_SIZE;
+ int start_x_tile = tile_number_for_pixel(updated_region->xmin);
+ int end_x_tile = tile_number_for_pixel(updated_region->xmax - 1);
+ int start_y_tile = tile_number_for_pixel(updated_region->ymin);
+ int end_y_tile = tile_number_for_pixel(updated_region->ymax - 1);
/* Clamp tiles to tiles in image. */
start_x_tile = max_ii(0, start_x_tile);
start_y_tile = max_ii(0, start_y_tile);
- end_x_tile = min_ii(current_transaction.tile_x_len_ - 1, end_x_tile);
- end_y_tile = min_ii(current_transaction.tile_y_len_ - 1, end_y_tile);
+ end_x_tile = min_ii(current_changeset.tile_x_len_ - 1, end_x_tile);
+ end_y_tile = min_ii(current_changeset.tile_y_len_ - 1, end_y_tile);
/* Early exit when no tiles need to be updated. */
- if (start_x_tile >= current_transaction.tile_x_len_) {
+ if (start_x_tile >= current_changeset.tile_x_len_) {
return;
}
- if (start_y_tile >= current_transaction.tile_y_len_) {
+ if (start_y_tile >= current_changeset.tile_y_len_) {
return;
}
if (end_x_tile < 0) {
@@ -219,47 +244,45 @@ struct PartialUpdateRegisterImpl {
return;
}
- current_transaction.add_region(start_x_tile, start_y_tile, end_x_tile, end_y_tile);
+ current_changeset.add_region(start_x_tile, start_y_tile, end_x_tile, end_y_tile);
}
- void ensure_empty_transaction()
+ void ensure_empty_changeset()
{
- if (current_transaction.is_empty()) {
- /* No need to create a new transaction when previous transaction does not contain any data.
- */
+ if (!current_changeset.has_dirty_tiles()) {
+ /* No need to create a new changeset when previous changeset does not contain any dirty
+ * tiles. */
return;
}
- commit_current_transaction();
+ commit_current_changeset();
}
- void commit_current_transaction()
+ void commit_current_changeset()
{
- history.append_as(std::move(current_transaction));
- current_transaction.reset();
- current_transaction_id++;
+ history.append_as(std::move(current_changeset));
+ current_changeset.reset();
+ current_changeset_id++;
}
/**
* /brief Check if data is available to construct the update tiles for the given
- * transaction_id.
+ * changeset_id.
*
- * The update tiles can be created when transaction id is between
+ * The update tiles can be created when changeset id is between
*/
- bool can_construct(TransactionID transaction_id)
+ bool can_construct(ChangesetID changeset_id)
{
- return transaction_id >= first_transaction_id;
+ return changeset_id >= first_changeset_id;
}
- std::unique_ptr<PartialUpdateTransaction> changed_tiles_since(
- const TransactionID from_transaction)
+ std::unique_ptr<TileChangeset> changed_tiles_since(const ChangesetID from_changeset)
{
- std::unique_ptr<PartialUpdateTransaction> changed_tiles =
- std::make_unique<PartialUpdateTransaction>();
+ std::unique_ptr<TileChangeset> changed_tiles = std::make_unique<TileChangeset>();
int tile_x_len = image_width / TILE_SIZE;
int tile_y_len = image_height / TILE_SIZE;
changed_tiles->init_tiles(tile_x_len, tile_y_len);
- for (int index = from_transaction - first_transaction_id; in
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list