Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2018-03-01 08:31:36 +0300
committerCampbell Barton <ideasman42@gmail.com>2018-03-01 08:37:39 +0300
commita459ef2827f1bb9e6ce92b0946a7463061c9ac55 (patch)
treef09abc5323903e5c879a96705534284891d903a8
parent68015f9d397124b66fd8b435b729fbc0daa6e9ad (diff)
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.
-rw-r--r--source/blender/draw/DRW_engine.h8
-rw-r--r--source/blender/draw/intern/draw_manager.c22
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c84
3 files changed, 83 insertions, 31 deletions
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);