[Bf-blender-cvs] [a459ef2827f] blender2.8: Fix T54190: Occlusion query select failed

Campbell Barton noreply at git.blender.org
Thu Mar 1 06:32:37 CET 2018


Commit: a459ef2827f1bb9e6ce92b0946a7463061c9ac55
Author: Campbell Barton
Date:   Thu Mar 1 16:31:36 2018 +1100
Branches: blender2.8
https://developer.blender.org/rBa459ef2827f1bb9e6ce92b0946a7463061c9ac55

Fix T54190: Occlusion query select failed

By default select wasn't picking the nearest object,
this could have been fixed by not clearing the depth buffer,
but calling GPU_select_(begin/end) without the binded frame-buffer
caused issues for depth-picking. So move GPU_select begin/end to a
callback.

This also has the advantage that only needs to populate the engines once
to draw two passes.

Note that cycling through objects fails with occlusion queries still,
will fix shortly.

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

M	source/blender/draw/DRW_engine.h
M	source/blender/draw/intern/draw_manager.c
M	source/blender/editors/space_view3d/view3d_view.c

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

diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h
index 9ed8f776f34..4043f39b46d 100644
--- a/source/blender/draw/DRW_engine.h
+++ b/source/blender/draw/DRW_engine.h
@@ -88,6 +88,11 @@ typedef struct DRWUpdateContext {
 void DRW_notify_view_update(const DRWUpdateContext *update_ctx);
 void DRW_notify_id_update(const DRWUpdateContext *update_ctx, struct ID *id);
 
+
+typedef enum eDRWSelectStage { DRW_SELECT_PASS_PRE = 1, DRW_SELECT_PASS_POST, } eDRWSelectStage;
+typedef bool (*DRW_SelectPassFn)(
+        eDRWSelectStage stage, void *user_data);
+
 void DRW_draw_view(const struct bContext *C);
 
 void DRW_draw_render_loop_ex(
@@ -108,7 +113,8 @@ void DRW_draw_render_loop_offscreen(
 void DRW_draw_select_loop(
         struct Depsgraph *depsgraph,
         struct ARegion *ar, struct View3D *v3d, const eObjectMode object_mode,
-        bool use_obedit_skip, bool use_nearest, const struct rcti *rect);
+        bool use_obedit_skip, bool use_nearest, const struct rcti *rect,
+        DRW_SelectPassFn select_pass_fn, void *select_pass_user_data);
 void DRW_draw_depth_loop(
         struct Depsgraph *depsgraph,
         struct ARegion *ar, struct View3D *v3d, const eObjectMode object_mode);
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index 62042a44434..037053399c7 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -1384,7 +1384,8 @@ void DRW_render_instance_buffer_finish(void)
 void DRW_draw_select_loop(
         struct Depsgraph *depsgraph,
         ARegion *ar, View3D *v3d, const eObjectMode object_mode,
-        bool UNUSED(use_obedit_skip), bool UNUSED(use_nearest), const rcti *rect)
+        bool UNUSED(use_obedit_skip), bool UNUSED(use_nearest), const rcti *rect,
+        DRW_SelectPassFn select_pass_fn, void *select_pass_user_data)
 {
 	Scene *scene = DEG_get_evaluated_scene(depsgraph);
 	RenderEngineType *engine_type = RE_engines_find(scene->view_render.engine_id);
@@ -1484,12 +1485,21 @@ void DRW_draw_select_loop(
 	/* Start Drawing */
 	DRW_state_reset();
 	DRW_draw_callbacks_pre_scene();
-	drw_engines_draw_scene();
-	DRW_draw_callbacks_post_scene();
 
-#ifdef USE_GPU_SELECT
-	GPU_select_finalize();
-#endif
+	/* Only 1-2 passes. */
+	while (true) {
+		if (!select_pass_fn(DRW_SELECT_PASS_PRE, select_pass_user_data)) {
+			break;
+		}
+
+		drw_engines_draw_scene();
+
+		if (!select_pass_fn(DRW_SELECT_PASS_POST, select_pass_user_data)) {
+			break;
+		}
+	}
+
+	DRW_draw_callbacks_post_scene();
 
 	DRW_state_reset();
 	drw_engines_disable();
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index cb329e62e96..0afef34194c 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -861,6 +861,45 @@ void view3d_opengl_select_cache_end(void)
 	GPU_select_cache_end();
 }
 
+#ifndef WITH_OPENGL_LEGACY
+struct DrawSelectLoopUserData {
+	uint  pass;
+	uint  hits;
+	uint *buffer;
+	uint  buffer_len;
+	const rcti *rect;
+	char gpu_select_mode;
+};
+
+static bool drw_select_loop_pass(eDRWSelectStage stage, void *user_data)
+{
+	bool continue_pass = false;
+	struct DrawSelectLoopUserData *data = user_data;
+	if (stage == DRW_SELECT_PASS_PRE) {
+		GPU_select_begin(data->buffer, data->buffer_len, data->rect, data->gpu_select_mode, data->hits);
+		/* always run POST after PRE. */
+		continue_pass = true;
+	}
+	else if (stage == DRW_SELECT_PASS_POST) {
+		int hits = GPU_select_end();
+		if (data->pass == 0) {
+			/* quirk of GPU_select_end, only take hits value from first call. */
+			data->hits = hits;
+		}
+		if (data->gpu_select_mode == GPU_SELECT_NEAREST_FIRST_PASS) {
+			data->gpu_select_mode = GPU_SELECT_NEAREST_SECOND_PASS;
+			continue_pass = true;
+		}
+		data->pass += 1;
+	}
+	else {
+		BLI_assert(0);
+	}
+	return continue_pass;
+
+}
+#endif /* WITH_OPENGL_LEGACY */
+
 /**
  * \warning be sure to account for a negative return value
  * This is an error, "Too many objects in select buffer"
@@ -950,43 +989,40 @@ int view3d_opengl_select(
 	if (vc->rv3d->rflag & RV3D_CLIPPING)
 		ED_view3d_clipping_set(vc->rv3d);
 	
-	GPU_select_begin(buffer, bufsize, &rect, gpu_select_mode, 0);
 
 #ifdef WITH_OPENGL_LEGACY
 	if (IS_VIEWPORT_LEGACY(vc->v3d)) {
+		GPU_select_begin(buffer, bufsize, &rect, gpu_select_mode, 0);
 		ED_view3d_draw_select_loop(vc, scene, sl, v3d, ar, use_obedit_skip, use_nearest);
+		hits = GPU_select_end();
+
+		if (do_passes && (hits > 0)) {
+			GPU_select_begin(buffer, bufsize, &rect, GPU_SELECT_NEAREST_SECOND_PASS, hits);
+			ED_view3d_draw_select_loop(vc, scene, sl, v3d, ar, use_obedit_skip, use_nearest);
+			GPU_select_end();
+		}
 	}
 	else
 #else
 	{
+		/* We need to call "GPU_select_*" API's inside DRW_draw_select_loop
+		 * because the OpenGL context created & destroyed inside this function. */
+		struct DrawSelectLoopUserData drw_select_loop_user_data = {
+			.pass = 0,
+			.hits = 0,
+			.buffer = buffer,
+			.buffer_len = bufsize,
+			.rect = &rect,
+			.gpu_select_mode = gpu_select_mode,
+		};
 		DRW_draw_select_loop(
 		        graph, ar, v3d, eval_ctx->object_mode,
-		        use_obedit_skip, use_nearest, &rect);
+		        use_obedit_skip, use_nearest, &rect,
+		        drw_select_loop_pass, &drw_select_loop_user_data);
+		hits = drw_select_loop_user_data.hits;
 	}
 #endif /* WITH_OPENGL_LEGACY */
 
-	hits = GPU_select_end();
-	
-	/* second pass, to get the closest object to camera */
-	if (do_passes && (hits > 0)) {
-		GPU_select_begin(buffer, bufsize, &rect, GPU_SELECT_NEAREST_SECOND_PASS, hits);
-
-#ifdef WITH_OPENGL_LEGACY
-		if (IS_VIEWPORT_LEGACY(vc->v3d)) {
-			ED_view3d_draw_select_loop(vc, scene, sl, v3d, ar, use_obedit_skip, use_nearest);
-		}
-		else
-#else
-		{
-			DRW_draw_select_loop(
-			        graph, ar, v3d, eval_ctx->object_mode,
-			        use_obedit_skip, use_nearest, &rect);
-		}
-#endif /* WITH_OPENGL_LEGACY */
-
-		GPU_select_end();
-	}
-
 	G.f &= ~G_PICKSEL;
 	ED_view3d_draw_setup_view(vc->win, eval_ctx, scene, ar, v3d, vc->rv3d->viewmat, NULL, NULL);



More information about the Bf-blender-cvs mailing list