[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