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 /source/blender
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.
Diffstat (limited to 'source/blender')
-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);