[Bf-blender-cvs] [bdd74e1e933] master: DrawManager: Image engine support huge images.

Jeroen Bakker noreply at git.blender.org
Fri Jan 28 08:38:28 CET 2022


Commit: bdd74e1e9338b18e4f80458f284d0c6a4d100f30
Author: Jeroen Bakker
Date:   Fri Jan 28 08:37:12 2022 +0100
Branches: master
https://developer.blender.org/rBbdd74e1e9338b18e4f80458f284d0c6a4d100f30

DrawManager: Image engine support huge images.

Adding better support for drawing huge images in the image/uv editor. Also solved tearing artifacts.
The approach is that for each image/uv editor a screen space gpu texture is created that only contains
the visible pixels. When zooming or panning the gpu texture is rebuild.

Although the solution isn't memory intensive other parts of blender memory usage scales together with
the image size.

* Due to complexity we didn't implement partial updates when drawing images tiled (wrap repeat).
  This could be added, but is complicated as a change in the source could mean many different
  changes on the GPU texture. The work around for now is to tag all gpu textures to be dirty when
  changes are detected.

Original plan was to have 4 screen space images to support panning without gpu texture creation.
For now we don't see the need to implement it as the solution is already fast. Especially when
GPU memory is shared with CPU ram.

Reviewed By: fclem

Maniphest Tasks: T92525, T92903

Differential Revision: https://developer.blender.org/D13424

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

M	source/blender/blenkernel/BKE_image_partial_update.hh
M	source/blender/blenkernel/intern/image_gpu.cc
M	source/blender/blenlib/BLI_math_matrix.h
M	source/blender/blenlib/intern/math_matrix.c
M	source/blender/draw/CMakeLists.txt
A	source/blender/draw/engines/image/image_batches.hh
A	source/blender/draw/engines/image/image_drawing_mode.hh
D	source/blender/draw/engines/image/image_drawing_mode_image_space.hh
M	source/blender/draw/engines/image/image_engine.cc
A	source/blender/draw/engines/image/image_instance_data.hh
A	source/blender/draw/engines/image/image_partial_updater.hh
M	source/blender/draw/engines/image/image_private.hh
A	source/blender/draw/engines/image/image_shader_params.hh
A	source/blender/draw/engines/image/image_space.hh
M	source/blender/draw/engines/image/image_space_image.hh
M	source/blender/draw/engines/image/image_space_node.hh
A	source/blender/draw/engines/image/image_texture_info.hh
A	source/blender/draw/engines/image/image_wrappers.hh
M	source/blender/draw/engines/image/shaders/engine_image_frag.glsl
M	source/blender/draw/engines/image/shaders/engine_image_vert.glsl

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

diff --git a/source/blender/blenkernel/BKE_image_partial_update.hh b/source/blender/blenkernel/BKE_image_partial_update.hh
index 6af44b2c3c9..ca7c4f40593 100644
--- a/source/blender/blenkernel/BKE_image_partial_update.hh
+++ b/source/blender/blenkernel/BKE_image_partial_update.hh
@@ -295,4 +295,4 @@ template<typename TileData = NoTileData> struct PartialUpdateChecker {
 };
 
 }  // namespace partial_update
-}  // namespace blender::bke::image
\ No newline at end of file
+}  // namespace blender::bke::image
diff --git a/source/blender/blenkernel/intern/image_gpu.cc b/source/blender/blenkernel/intern/image_gpu.cc
index 91937e709da..eaee1fd2c30 100644
--- a/source/blender/blenkernel/intern/image_gpu.cc
+++ b/source/blender/blenkernel/intern/image_gpu.cc
@@ -58,14 +58,6 @@ static void image_free_gpu_limited_scale(Image *ima);
 static void image_update_gputexture_ex(
     Image *ima, ImageTile *tile, ImBuf *ibuf, int x, int y, int w, int h);
 
-/* Internal structs. */
-#define IMA_PARTIAL_REFRESH_TILE_SIZE 256
-struct ImagePartialRefresh {
-  struct ImagePartialRefresh *next, *prev;
-  int tile_x;
-  int tile_y;
-};
-
 bool BKE_image_has_gpu_texture_premultiplied_alpha(Image *image, ImBuf *ibuf)
 {
   if (image) {
diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h
index 65d654bc930..03b6ff25a4f 100644
--- a/source/blender/blenlib/BLI_math_matrix.h
+++ b/source/blender/blenlib/BLI_math_matrix.h
@@ -404,6 +404,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]);
 
 /**
  * This computes the overall volume scale factor of a transformation matrix.
diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c
index eaf76696a0a..f307672361b 100644
--- a/source/blender/blenlib/intern/math_matrix.c
+++ b/source/blender/blenlib/intern/math_matrix.c
@@ -2296,6 +2296,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/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index 0c5b158ac80..b40fc88a076 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -227,11 +227,17 @@ set(SRC
   engines/eevee/eevee_lut.h
   engines/eevee/eevee_private.h
   engines/external/external_engine.h
-  engines/image/image_drawing_mode_image_space.hh
+  engines/image/image_batches.hh
+  engines/image/image_drawing_mode.hh
   engines/image/image_engine.h
+  engines/image/image_instance_data.hh
+  engines/image/image_partial_updater.hh
   engines/image/image_private.hh
+  engines/image/image_shader_params.hh
   engines/image/image_space_image.hh
   engines/image/image_space_node.hh
+  engines/image/image_space.hh
+  engines/image/image_wrappers.hh
   engines/workbench/workbench_engine.h
   engines/workbench/workbench_private.h
   engines/workbench/workbench_shader_shared.h
diff --git a/source/blender/draw/engines/image/image_batches.hh b/source/blender/draw/engines/image/image_batches.hh
new file mode 100644
index 00000000000..489785d5d12
--- /dev/null
+++ b/source/blender/draw/engines/image/image_batches.hh
@@ -0,0 +1,106 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2021, Blender Foundation.
+ */
+
+/** \file
+ * \ingroup draw_engine
+ */
+
+#pragma once
+
+#include "image_texture_info.hh"
+
+/** \brief Create GPUBatch for a IMAGE_ScreenSpaceTextureInfo. */
+class BatchUpdater {
+  TextureInfo &info;
+
+  GPUVertFormat format = {0};
+  int pos_id;
+  int uv_id;
+
+ public:
+  BatchUpdater(TextureInfo &info) : info(info)
+  {
+  }
+
+  void update_batch()
+  {
+    ensure_clear_batch();
+    ensure_format();
+    init_batch();
+  }
+
+  void discard_batch()
+  {
+    GPU_BATCH_DISCARD_SAFE(info.batch);
+  }
+
+ private:
+  void ensure_clear_batch()
+  {
+    GPU_BATCH_CLEAR_SAFE(info.batch);
+    if (info.batch == nullptr) {
+      info.batch = GPU_batch_calloc();
+    }
+  }
+
+  void init_batch()
+  {
+    GPUVertBuf *vbo = create_vbo();
+    GPU_batch_init_ex(info.batch, GPU_PRIM_TRI_FAN, vbo, nullptr, GPU_BATCH_OWNS_VBO);
+  }
+
+  GPUVertBuf *create_vbo()
+  {
+    GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+    GPU_vertbuf_data_alloc(vbo, 4);
+    float pos[4][2];
+    fill_tri_fan_from_rctf(pos, info.clipping_bounds);
+    float uv[4][2];
+    fill_tri_fan_from_rctf(uv, info.uv_bounds);
+
+    for (int i = 0; i < 4; i++) {
+      GPU_vertbuf_attr_set(vbo, pos_id, i, pos[i]);
+      GPU_vertbuf_attr_set(vbo, uv_id, i, uv[i]);
+    }
+
+    return vbo;
+  }
+
+  static void fill_tri_fan_from_rctf(float result[4][2], rctf &rect)
+  {
+    result[0][0] = rect.xmin;
+    result[0][1] = rect.ymin;
+    result[1][0] = rect.xmax;
+    result[1][1] = rect.ymin;
+    result[2][0] = rect.xmax;
+    result[2][1] = rect.ymax;
+    result[3][0] = rect.xmin;
+    result[3][1] = rect.ymax;
+  }
+
+  void ensure_format()
+  {
+    if (format.attr_len == 0) {
+      GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+      GPU_vertformat_attr_add(&format, "uv", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
+      pos_id = GPU_vertformat_attr_id_get(&format, "pos");
+      uv_id = GPU_vertformat_attr_id_get(&format, "uv");
+    }
+  }
+};
diff --git a/source/blender/draw/engines/image/image_drawing_mode.hh b/source/blender/draw/engines/image/image_drawing_mode.hh
new file mode 100644
index 00000000000..8762a02458f
--- /dev/null
+++ b/source/blender/draw/engines/image/image_drawing_mode.hh
@@ -0,0 +1,417 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2021, Blender Foundation.
+ */
+
+/** \file
+ * \ingroup draw_engine
+ */
+
+#pragma once
+
+#include "BKE_image_partial_update.hh"
+
+#include "IMB_imbuf_types.h"
+
+#include "image_batches.hh"
+#include "image_private.hh"
+#include "image_wrappers.hh"
+
+namespace blender::draw::image_engine {
+
+constexpr float EPSILON_UV_BOUNDS = 0.00001f;
+
+/**
+ * \brief Screen space method using a single texture spawning the whole screen.
+ */
+struct OneTextureMethod {
+  IMAGE_InstanceData *instance_data;
+
+  OneTextureMethod(IMAGE_InstanceData *instance_data) : instance_data(instance_data)
+  {
+  }
+
+  /** \brief Update the texture slot uv and screen space bounds. */
+  void update_screen_space_bounds(const ARegion *region)
+  {
+    /* Create a single texture that covers the visible screen space. */
+    BLI_rctf_init(
+        &instance_data->texture_infos[0].clipping_bounds, 0, region->winx, 0, region->winy);
+    instance_data->texture_infos[0].visible = true;
+
+    /* Mark the other textures as invalid. */
+    for (int i = 1; i < SCREEN_SPACE_DRAWING_MODE_TEXTURE_LEN; i++) {
+      BLI_rctf_init_minmax(&instance_data->texture_infos[i].clipping_bounds);
+      instance_data->texture_infos[i].visible = false;
+    }
+  }
+
+  void update_uv_bounds(const ARegion *region)
+  {
+    TextureInfo &info = instance_data->texture_infos[0];
+    if (!BLI_rctf_compare(&info.uv_bounds, &region->v2d.cur, EPSILON_UV_BOUNDS)) {
+      info.uv_bounds = region->v2d.cur;
+      info.dirty = true;
+    }
+
+    /* Mark the other textures as invalid. */
+    for (int i = 1; i < SCREEN_SPACE_DRAWING_MODE_TEXTURE_LEN; i++) {
+      BLI_rctf_init_minmax(&instance_data->texture_infos[i].clipping_bounds);
+    }
+  }
+};
+
+using namespace blender::bke::image::partial_update;
+
+template<typename TextureMethod> class ScreenSpaceDrawingMode : public AbstractDrawingMode {
+ private:
+  DRWPass *create_image_pass() const
+  {
+    /* Write depth is needed for background overlay rendering. Near depth is used for
+     * transparency checker and Far depth is used for indicating the image size. */
+    DRWState state = static_cast<DRWState>(DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH |
+                                           DRW_STATE_DEPTH_ALWAYS | DRW_STATE_BLEND_ALPHA_PREMUL);
+    return DRW_pass_create("Image", state);
+  }
+
+  void add_shgroups(const IMAGE_InstanceData *instance_data) const
+  {
+    const ShaderParameters &sh_params = instance_data->sh_params;
+    GPUShader *shader = IMAGE_shader_image_get(false);
+
+    DRWShadingGroup *shgrp = DRW_shgroup_create(shader, instance_data->passes.image_pass);
+    DRW_shgroup_uniform_vec2_copy(shgrp, "farNearDis

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list