[Bf-blender-cvs] [160720764d8] temp-gpu-image-engine: Regular texture partial update.

Jeroen Bakker noreply at git.blender.org
Tue Nov 30 12:54:02 CET 2021


Commit: 160720764d888d50e91bf658769f6eccdde4855d
Author: Jeroen Bakker
Date:   Tue Nov 30 12:53:42 2021 +0100
Branches: temp-gpu-image-engine
https://developer.blender.org/rB160720764d888d50e91bf658769f6eccdde4855d

Regular texture partial update.

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

M	source/blender/blenlib/BLI_math_matrix.h
M	source/blender/blenlib/intern/math_matrix.c
M	source/blender/draw/engines/image/image_drawing_mode_screen_space.hh
M	source/blender/draw/engines/image/image_private.hh

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

diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h
index 241acebffa3..78bd8371aa7 100644
--- a/source/blender/blenlib/BLI_math_matrix.h
+++ b/source/blender/blenlib/BLI_math_matrix.h
@@ -312,6 +312,7 @@ void invert_m4_m4_safe_ortho(float Ainv[4][4], const float A[4][4]);
 
 void scale_m3_fl(float R[3][3], float scale);
 void scale_m4_fl(float R[4][4], float scale);
+void scale_m4_v2(float R[4][4], const float scale[2]);
 
 float mat3_to_volume_scale(const float M[3][3]);
 float mat4_to_volume_scale(const float M[4][4]);
diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c
index b6d80d76be1..a4a5cdd7096 100644
--- a/source/blender/blenlib/intern/math_matrix.c
+++ b/source/blender/blenlib/intern/math_matrix.c
@@ -2360,6 +2360,17 @@ void scale_m4_fl(float R[4][4], float scale)
   R[3][0] = R[3][1] = R[3][2] = 0.0;
 }
 
+void scale_m4_v2(float R[4][4], const float scale[2])
+{
+  R[0][0] = scale[0];
+  R[1][1] = scale[1];
+  R[2][2] = R[3][3] = 1.0;
+  R[0][1] = R[0][2] = R[0][3] = 0.0;
+  R[1][0] = R[1][2] = R[1][3] = 0.0;
+  R[2][0] = R[2][1] = R[2][3] = 0.0;
+  R[3][0] = R[3][1] = R[3][2] = 0.0;
+}
+
 void translate_m4(float mat[4][4], float Tx, float Ty, float Tz)
 {
   mat[3][0] += (Tx * mat[0][0] + Ty * mat[1][0] + Tz * mat[2][0]);
diff --git a/source/blender/draw/engines/image/image_drawing_mode_screen_space.hh b/source/blender/draw/engines/image/image_drawing_mode_screen_space.hh
index 4b9d4fe04f6..bad319ba4b0 100644
--- a/source/blender/draw/engines/image/image_drawing_mode_screen_space.hh
+++ b/source/blender/draw/engines/image/image_drawing_mode_screen_space.hh
@@ -66,7 +66,6 @@ struct PrivateDataAccessor {
 
   void update_uv_bounds()
   {
-
     /* Calculate the uv coordinates of the screen space visible corners. */
     float inverse_mat[4][4];
     DRW_view_viewmat_get(NULL, inverse_mat, true);
@@ -85,6 +84,7 @@ struct PrivateDataAccessor {
             &pd->screen_space.texture_infos[0].uv_bounds, &new_uv_bounds, EPSILON_UV_BOUNDS)) {
       pd->screen_space.texture_infos[0].uv_bounds = new_uv_bounds;
       pd->screen_space.texture_infos[0].dirty = true;
+      update_uv_to_texture_matrix(&pd->screen_space.texture_infos[0]);
     }
 
     /* Mark the other textures as invalid. */
@@ -92,6 +92,40 @@ struct PrivateDataAccessor {
       BLI_rctf_init_minmax(&pd->screen_space.texture_infos[i].clipping_bounds);
     }
   }
+
+  void update_uv_to_texture_matrix(IMAGE_ScreenSpaceTextureInfo *info)
+  {
+    // TODO: I remember that there was a function for this somewhere.
+    unit_m4(info->uv_to_texture);
+    float scale_x = 1.0 / BLI_rctf_size_x(&info->uv_bounds);
+    float scale_y = 1.0 / BLI_rctf_size_y(&info->uv_bounds);
+    float translate_x = scale_x * -info->uv_bounds.xmin;
+    float translate_y = scale_y * -info->uv_bounds.ymin;
+
+    info->uv_to_texture[0][0] = scale_x;
+    info->uv_to_texture[1][1] = scale_y;
+    info->uv_to_texture[3][0] = translate_x;
+    info->uv_to_texture[3][1] = translate_y;
+  }
+};
+
+struct ImageTileAccessor {
+  ImageTile *image_tile;
+  ImageTileAccessor(ImageTile *image_tile) : image_tile(image_tile)
+  {
+  }
+
+  int get_tile_x_offset()
+  {
+    int tile_number = image_tile->tile_number;
+    return (tile_number - 1001) % 10;
+  }
+
+  int get_tile_y_offset()
+  {
+    int tile_number = image_tile->tile_number;
+    return (tile_number - 1001) / 10;
+  }
 };
 
 using namespace blender::bke::image::partial_update;
@@ -229,7 +263,7 @@ class ScreenSpaceDrawingMode : public AbstractDrawingMode {
         do_partial_update(changes, txl, pd, image);
         break;
     }
-    update_dirty_textures(txl, pd);
+    do_full_update_for_dirty_textures(txl, pd);
   }
 
   void do_partial_update(PartialUpdateChecker<ImageTileData>::CollectResult &iterator,
@@ -238,70 +272,171 @@ class ScreenSpaceDrawingMode : public AbstractDrawingMode {
                          Image *image) const
   {
     while (iterator.get_next_change() == ePartialUpdateIterResult::ChangeAvailable) {
+      const float tile_width = static_cast<float>(iterator.tile_data.tile_buffer->x);
+      const float tile_height = static_cast<float>(iterator.tile_data.tile_buffer->y);
+
       for (int i = 0; i < SCREEN_SPACE_DRAWING_MODE_TEXTURE_LEN; i++) {
+        const IMAGE_ScreenSpaceTextureInfo *info = &pd->screen_space.texture_infos[i];
         /* Dirty images will receive a full update. No need to do a partial one now. */
-        if (pd->screen_space.texture_infos[i].dirty) {
+        if (info->dirty) {
+          continue;
+        }
+        if (!info->visible) {
           continue;
         }
+        GPUTexture *texture = txl->screen_space.textures[i];
+        const float texture_width = GPU_texture_width(texture);
+        const float texture_height = GPU_texture_height(texture);
         // TODO
+        // early bound check.
+        ImageTileAccessor tile_accessor(iterator.tile_data.tile);
+        float tile_offset_x = static_cast<float>(tile_accessor.get_tile_x_offset());
+        float tile_offset_y = static_cast<float>(tile_accessor.get_tile_y_offset());
+        rcti *changed_region_in_texel_space = &iterator.changed_region.region;
+        rctf changed_region_in_uv_space;
+        BLI_rctf_init(&changed_region_in_uv_space,
+                      static_cast<float>(changed_region_in_texel_space->xmin) /
+                              static_cast<float>(iterator.tile_data.tile_buffer->x) +
+                          tile_offset_x,
+                      static_cast<float>(changed_region_in_texel_space->xmax) /
+                              static_cast<float>(iterator.tile_data.tile_buffer->x) +
+                          tile_offset_x,
+                      static_cast<float>(changed_region_in_texel_space->ymin) /
+                              static_cast<float>(iterator.tile_data.tile_buffer->y) +
+                          tile_offset_y,
+                      static_cast<float>(changed_region_in_texel_space->ymax) /
+                              static_cast<float>(iterator.tile_data.tile_buffer->y) +
+                          tile_offset_y);
+        rctf changed_overlapping_region_in_uv_space;
+        const bool region_overlap = BLI_rctf_isect(&info->uv_bounds,
+                                                   &changed_region_in_uv_space,
+                                                   &changed_overlapping_region_in_uv_space);
+        if (!region_overlap) {
+          continue;
+        }
+        // convert the overlapping region to texel space and to ss_pixel space...
+        // TODO: first convert to ss_pixel space as integer based. and from there go back to texel
+        // space. But perhaps this isn't needed and we could use an extraction offset somehow.
+        rcti gpu_texture_region_to_update;
+        BLI_rcti_init(&gpu_texture_region_to_update,
+                      floor((changed_overlapping_region_in_uv_space.xmin - info->uv_bounds.xmin) *
+                            texture_width / BLI_rctf_size_x(&info->uv_bounds)),
+                      floor((changed_overlapping_region_in_uv_space.xmax - info->uv_bounds.xmin) *
+                            texture_width / BLI_rctf_size_x(&info->uv_bounds)),
+                      ceil((changed_overlapping_region_in_uv_space.ymin - info->uv_bounds.ymin) *
+                           texture_height / BLI_rctf_size_y(&info->uv_bounds)),
+                      ceil((changed_overlapping_region_in_uv_space.ymax - info->uv_bounds.ymin) *
+                           texture_height / BLI_rctf_size_y(&info->uv_bounds)));
+
+        rcti tile_region_to_extract;
+        BLI_rcti_init(
+            &tile_region_to_extract,
+            floor((changed_overlapping_region_in_uv_space.xmin - tile_offset_x) * tile_width),
+            floor((changed_overlapping_region_in_uv_space.xmax - tile_offset_x) * tile_width),
+            ceil((changed_overlapping_region_in_uv_space.ymin - tile_offset_y) * tile_height),
+            ceil((changed_overlapping_region_in_uv_space.ymax - tile_offset_y) * tile_height));
+
+        // Create an image buffer with a size
+        // extract and scale into an imbuf
+        const int texture_region_width = BLI_rcti_size_x(&gpu_texture_region_to_update);
+        const int texture_region_height = BLI_rcti_size_y(&gpu_texture_region_to_update);
+
+        ImBuf extracted_buffer;
+        IMB_initImBuf(
+            &extracted_buffer, texture_region_width, texture_region_height, 32, IB_rectfloat);
+
+        int offset = 0;
+        ImBuf *tile_buffer = iterator.tile_data.tile_buffer;
+        for (int y = gpu_texture_region_to_update.ymin; y < gpu_texture_region_to_update.ymax;
+             y++) {
+          float yf = y / (float)texture_height;
+          float v = info->uv_bounds.ymax * yf + info->uv_bounds.ymin * (1.0 - yf);
+          for (int x = gpu_texture_region_to_update.xmin; x < gpu_texture_region_to_update.xmax;
+               x++) {
+            float xf = x / (float)texture_width;
+            float u = info->uv_bounds.xmax * xf + info->uv_bounds.xmin * (1.0 - xf);
+            nearest_interpolation_color(tile_buffer,
+                                        nullptr,
+                                        &extracted_buffer.rect_float[offset * 4],
+                                        u * tile_buffer->x,
+                                        v * tile_buffer->y);
+            offset++;
+          }
+        }
+
+        GPU_texture_update_sub(texture,
+                               GPU_DATA_FLOAT,
+                               extracted_buffer.rect_float,
+                               gpu_texture_region_to_update.xmin,
+                               gpu_texture_region_to_update.ymin,
+                               0,
+                               extracted_buffer.x,
+                               extracted_buffer.y,
+                               0);
+        imb_freerectImbuf_all(&extracted_buffer);
       }
     }
   }
 
-  void update_dirty_textures(IMAGE_TextureList *txl, IMAGE_PrivateData *pd) const
+  void do_partial_update()
+  {
+  }
+
+  void do_full_update_for_dirty_textures(IMAGE_TextureList *t

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list