[Bf-blender-cvs] [a92413b0dbc] temp-pbvh-split: Revert "Gizmo: optimize intersection tests, fix selection bias"

Campbell Barton noreply at git.blender.org
Fri Jun 3 01:16:30 CEST 2022


Commit: a92413b0dbcb398f5477fb106f08711a1bd3675c
Author: Campbell Barton
Date:   Wed May 11 20:14:32 2022 +1000
Branches: temp-pbvh-split
https://developer.blender.org/rBa92413b0dbcb398f5477fb106f08711a1bd3675c

Revert "Gizmo: optimize intersection tests, fix selection bias"

Manually revert commit [0] as it caused problems macOS (reported T96435).

- Includes fixes from [1] & [2].
- T98037 TODO has been created to keep track of this feature.

Thanks to @jbakker & @sergey for investigating this issue as I wasn't
able to reproduce the bug.

[0]: 0cb5eae9d0617abedf745753c23061ddfcfd1416
[1]: cb986446e29a51b07bdb73b999a0339df5ecdeb4
[2]: cc8fe1a1cbc63db66c038773b070dca14e82cebb

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

M	source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c

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

diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c
index a61d73b9f0b..f481f19045d 100644
--- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c
+++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c
@@ -492,7 +492,8 @@ void WM_gizmomap_draw(wmGizmoMap *gzmap,
 
 static void gizmo_draw_select_3d_loop(const bContext *C,
                                       wmGizmo **visible_gizmos,
-                                      const int visible_gizmos_len)
+                                      const int visible_gizmos_len,
+                                      bool *r_use_select_bias)
 {
 
   /* TODO(campbell): this depends on depth buffer being written to,
@@ -528,6 +529,10 @@ static void gizmo_draw_select_3d_loop(const bContext *C,
       is_depth_skip_prev = is_depth_skip;
     }
 
+    if (gz->select_bias != 0.0) {
+      *r_use_select_bias = true;
+    }
+
     /* pass the selection id shifted by 8 bits. Last 8 bits are used for selected gizmo part id */
 
     gz->type->draw_select(C, gz, select_id << 8);
@@ -545,10 +550,7 @@ static int gizmo_find_intersected_3d_intern(wmGizmo **visible_gizmos,
                                             const int visible_gizmos_len,
                                             const bContext *C,
                                             const int co[2],
-                                            const int hotspot,
-                                            const bool use_depth_test,
-                                            const bool has_3d_select_bias,
-                                            int *r_hits)
+                                            const int hotspot)
 {
   const wmWindowManager *wm = CTX_wm_manager(C);
   ScrArea *area = CTX_wm_area(C);
@@ -562,76 +564,30 @@ static int gizmo_find_intersected_3d_intern(wmGizmo **visible_gizmos,
 
   BLI_rcti_init_pt_radius(&rect, co, hotspot);
 
-  /* The selection mode is assigned for the following reasons:
-   *
-   * - #GPU_SELECT_ALL: Use it to check if there is anything at the cursor location
-   *   (only ever runs once).
-   * - #GPU_SELECT_PICK_NEAREST: Use if there are more than 1 item at the cursor location,
-   *   pick the nearest one.
-   * - #GPU_SELECT_PICK_ALL: Use for the same purpose as #GPU_SELECT_PICK_NEAREST
-   *   when the selection depths need to re-ordered based on a bias.
-   * */
-  const eGPUSelectMode gpu_select_mode =
-      (use_depth_test ? (has_3d_select_bias ?
-                              /* Using select bias means the depths need to be
-                               * re-calculated based on the bias to pick the best. */
-                              GPU_SELECT_PICK_ALL :
-                              /* No bias, just pick the closest. */
-                              GPU_SELECT_PICK_NEAREST) :
-                        /* Fast-path (occlusion queries). */
-                        GPU_SELECT_ALL);
-
-  /* When switching between modes and the mouse pointer is over a gizmo, the highlight test is
-   * performed before the viewport is fully initialized (region->draw_buffer = NULL).
-   * When this is the case we should not use depth testing. */
-  GPUViewport *gpu_viewport = WM_draw_region_get_viewport(region);
-  if (use_depth_test && gpu_viewport == NULL) {
-    return -1;
-  }
+  ED_view3d_draw_setup_view(
+      wm, CTX_wm_window(C), depsgraph, CTX_data_scene(C), region, v3d, NULL, NULL, &rect);
 
-  if (GPU_select_is_cached()) {
-    GPU_select_begin(buffer, ARRAY_SIZE(buffer), &rect, gpu_select_mode, 0);
-    GPU_select_cache_load_id();
-    hits = GPU_select_end();
-  }
-  else {
-    /* TODO: waiting for the GPU in the middle of the event loop for every
-     * mouse move is bad for performance, we need to find a solution to not
-     * use the GPU or draw something once. (see T61474) */
+  bool use_select_bias = false;
 
-    ED_view3d_draw_setup_view(
-        wm, CTX_wm_window(C), depsgraph, CTX_data_scene(C), region, v3d, NULL, NULL, &rect);
+  /* TODO: waiting for the GPU in the middle of the event loop for every
+   * mouse move is bad for performance, we need to find a solution to not
+   * use the GPU or draw something once. (see T61474) */
+  GPU_select_begin(buffer, ARRAY_SIZE(buffer), &rect, GPU_SELECT_NEAREST_FIRST_PASS, 0);
+  /* do the drawing */
+  gizmo_draw_select_3d_loop(C, visible_gizmos, visible_gizmos_len, &use_select_bias);
 
-    /* There is no need to bind to the depth buffer outside this function
-     * because all future passes the will use the cached depths. */
-    GPUFrameBuffer *depth_read_fb = NULL;
-    if (use_depth_test) {
-      GPUTexture *depth_tx = GPU_viewport_depth_texture(gpu_viewport);
-      GPU_framebuffer_ensure_config(&depth_read_fb,
-                                    {
-                                        GPU_ATTACHMENT_TEXTURE(depth_tx),
-                                        GPU_ATTACHMENT_NONE,
-                                    });
-      GPU_framebuffer_bind(depth_read_fb);
-    }
+  hits = GPU_select_end();
 
-    GPU_select_begin(buffer, ARRAY_SIZE(buffer), &rect, gpu_select_mode, 0);
-    gizmo_draw_select_3d_loop(C, visible_gizmos, visible_gizmos_len);
-    hits = GPU_select_end();
-
-    if (use_depth_test) {
-      GPU_framebuffer_restore();
-      GPU_framebuffer_free(depth_read_fb);
-    }
-
-    ED_view3d_draw_setup_view(
-        wm, CTX_wm_window(C), depsgraph, CTX_data_scene(C), region, v3d, NULL, NULL, NULL);
+  if (hits > 0) {
+    GPU_select_begin(buffer, ARRAY_SIZE(buffer), &rect, GPU_SELECT_NEAREST_SECOND_PASS, hits);
+    gizmo_draw_select_3d_loop(C, visible_gizmos, visible_gizmos_len, &use_select_bias);
+    GPU_select_end();
   }
 
-  /* When selection bias is needed, this function will run again with `use_depth_test` enabled. */
-  int hit_found = -1;
+  ED_view3d_draw_setup_view(
+      wm, CTX_wm_window(C), depsgraph, CTX_data_scene(C), region, v3d, NULL, NULL, NULL);
 
-  if (has_3d_select_bias && use_depth_test && (hits > 1)) {
+  if (use_select_bias && (hits > 1)) {
     float co_direction[3];
     float co_screen[3] = {co[0], co[1], 0.0f};
     ED_view3d_win_to_vector(region, (float[2]){UNPACK2(co)}, co_direction);
@@ -643,6 +599,7 @@ static int gizmo_find_intersected_3d_intern(wmGizmo **visible_gizmos,
     GPU_matrix_unproject_3fv(co_screen, rv3d->viewinv, rv3d->winmat, viewport, co_3d_origin);
 
     GPUSelectResult *buf_iter = buffer;
+    int hit_found = -1;
     float dot_best = FLT_MAX;
 
     for (int i = 0; i < hits; i++, buf_iter++) {
@@ -662,16 +619,11 @@ static int gizmo_find_intersected_3d_intern(wmGizmo **visible_gizmos,
         hit_found = buf_iter->id;
       }
     }
-  }
-  else {
-    const GPUSelectResult *hit_near = GPU_select_buffer_near(buffer, hits);
-    if (hit_near) {
-      hit_found = hit_near->id;
-    }
+    return hit_found;
   }
 
-  *r_hits = hits;
-  return hit_found;
+  const GPUSelectResult *hit_near = GPU_select_buffer_near(buffer, hits);
+  return hit_near ? hit_near->id : -1;
 }
 
 /**
@@ -694,7 +646,6 @@ static wmGizmo *gizmo_find_intersected_3d(bContext *C,
 
   /* Search for 3D gizmo's that use the 2D callback for checking intersections. */
   bool has_3d = false;
-  bool has_3d_select_bias = false;
   {
     for (int select_id = 0; select_id < visible_gizmos_len; select_id++) {
       wmGizmo *gz = visible_gizmos[select_id];
@@ -710,9 +661,6 @@ static wmGizmo *gizmo_find_intersected_3d(bContext *C,
       }
       else if (gz->type->draw_select != NULL) {
         has_3d = true;
-        if (gz->select_bias != 0.0f) {
-          has_3d_select_bias = true;
-        }
       }
     }
   }
@@ -721,86 +669,39 @@ static wmGizmo *gizmo_find_intersected_3d(bContext *C,
    * This way we always use the first hit. */
   if (has_3d) {
 
-    /* NOTE(@campbellbarton): The selection logic here uses a fast-path that exits early
-     * where possible. This is important as this runs on cursor-motion in the 3D view-port.
-     *
-     * - First, don't use the depth buffer at all, use occlusion queries to detect any gizmos.
-     *   If there are no gizmos or only one - early exit, otherwise.
-     *
-     * - Bind the depth buffer and use selection picking logic.
-     *   This is much slower than occlusion queries (since it's reading depths while drawing).
-     *   When there is a single gizmo under the cursor (quite common), early exit, otherwise.
-     *
-     * - Perform another pass at a reduced size (see: `hotspot_radii`),
-     *   since the result depths are cached this pass is practically free.
-     *
-     * Other notes:
-     *
-     * - If any of these passes fail, use the nearest result from the previous pass.
-     *
-     * - Drawing is only ever done twice.
-     */
-
-    /* Order largest to smallest so the first pass can be used as cache for
-     * later passes (when `use_depth_test == true`). */
-    const int hotspot_radii[] = {
-        10 * U.pixelsize,
-        /* This runs on mouse move, careful doing too many tests! */
-        3 * U.pixelsize,
-    };
-
-    /* Narrowing may assign zero to `hit`, allow falling back to the previous test. */
-    int hit_prev = -1;
+    /* The depth buffer is needed for for gizmos to obscure eachother.  */
+    GPUViewport *viewport = WM_draw_region_get_viewport(CTX_wm_region(C));
 
-    bool use_depth_test = false;
-    bool use_depth_cache = false;
-
-    /* Workaround for MS-Windows & NVidia failing to detect any gizmo undo the cursor unless the
-     * depth test is enabled, see: T97124.
-     * NOTE(@campbellbarton): Ideally the exact cause of this could be tracked down,
-     * disable as I don't have a system to test this configuration. */
-    if (GPU_type_matches(GPU_DEVICE_NVIDIA | GPU_DEVICE_SOFTWARE, GPU_OS_WIN, GPU_DRIVER_ANY)) {
-      use_depth_test = true;
+    /* When switching between modes and the mouse pointer is over a gizmo, the highlight test is
+     * performed before the viewport is fully initialized (region->draw_buffer = NULL).
+     * When this is the case we should not use depth testing. */
+    if (viewport == NULL) {
+      return NULL;
     }
+    GPUTexture *depth_tx = GPU_viewport_depth_texture(

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list