[Mesa-dev] [PATCH] gallium: add PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE

Marek Olšák maraeo at gmail.com
Thu Sep 14 00:56:57 UTC 2017


Reviewed-by: Marek Olšák <marek.olsak at amd.com>

Marek

On Wed, Sep 13, 2017 at 6:53 PM, Nicolai Hähnle <nhaehnle at gmail.com> wrote:
> From: Nicolai Hähnle <nicolai.haehnle at amd.com>
>
> To be able to properly distinguish between GL_ANY_SAMPLES_PASSED
> and GL_ANY_SAMPLES_PASSED_CONSERVATIVE.
>
> This patch goes through all drivers, having them treat the two
> query types identically, except:
>
> 1. radeon incorrectly enabled conservative mode on
>    PIPE_QUERY_OCCLUSION_PREDICATE. We now do it correctly, only
>    on PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE.
> 2. st/mesa uses the new query type.
>
> Fixes dEQP-GLES31.functional.fbo.no_attachments.*
> ---
>  src/gallium/auxiliary/util/u_dump_defines.c      |  1 +
>  src/gallium/auxiliary/util/u_inlines.h           |  1 +
>  src/gallium/docs/source/context.rst              |  6 ++++++
>  src/gallium/drivers/freedreno/a3xx/fd3_query.c   |  8 ++++++++
>  src/gallium/drivers/freedreno/a4xx/fd4_query.c   |  8 ++++++++
>  src/gallium/drivers/freedreno/a5xx/fd5_query.c   | 10 ++++++++++
>  src/gallium/drivers/freedreno/freedreno_query.h  |  1 +
>  src/gallium/drivers/llvmpipe/lp_query.c          |  3 +++
>  src/gallium/drivers/llvmpipe/lp_rast.c           |  2 ++
>  src/gallium/drivers/llvmpipe/lp_setup.c          |  3 +++
>  src/gallium/drivers/nouveau/nv30/nv30_query.c    |  4 +++-
>  src/gallium/drivers/nouveau/nv50/nv50_query.c    |  1 +
>  src/gallium/drivers/nouveau/nv50/nv50_query_hw.c |  4 ++++
>  src/gallium/drivers/nouveau/nvc0/nvc0_query.c    |  1 +
>  src/gallium/drivers/nouveau/nvc0/nvc0_query_hw.c |  7 ++++++-
>  src/gallium/drivers/r300/r300_query.c            |  7 +++++--
>  src/gallium/drivers/radeon/r600_pipe_common.c    |  3 ++-
>  src/gallium/drivers/radeon/r600_query.c          | 19 ++++++++++++++-----
>  src/gallium/drivers/softpipe/sp_query.c          |  4 ++++
>  src/gallium/drivers/svga/svga_pipe_query.c       |  7 ++++++-
>  src/gallium/drivers/swr/swr_query.cpp            |  1 +
>  src/gallium/drivers/trace/tr_dump_state.c        |  1 +
>  src/gallium/include/pipe/p_defines.h             |  2 ++
>  src/mesa/state_tracker/st_cb_queryobj.c          |  5 ++++-
>  24 files changed, 97 insertions(+), 12 deletions(-)
>
> diff --git a/src/gallium/auxiliary/util/u_dump_defines.c b/src/gallium/auxiliary/util/u_dump_defines.c
> index 5032974a880..e87e5301600 100644
> --- a/src/gallium/auxiliary/util/u_dump_defines.c
> +++ b/src/gallium/auxiliary/util/u_dump_defines.c
> @@ -358,20 +358,21 @@ util_tex_filter_short_names[] = {
>     "linear"
>  };
>
>  DEFINE_UTIL_STR_CONTINUOUS(tex_filter)
>
>
>  static const char *
>  util_query_type_names[] = {
>     "PIPE_QUERY_OCCLUSION_COUNTER",
>     "PIPE_QUERY_OCCLUSION_PREDICATE",
> +   "PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE",
>     "PIPE_QUERY_TIMESTAMP",
>     "PIPE_QUERY_TIMESTAMP_DISJOINT",
>     "PIPE_QUERY_TIME_ELAPSED",
>     "PIPE_QUERY_PRIMITIVES_GENERATED",
>     "PIPE_QUERY_PRIMITIVES_EMITTED",
>     "PIPE_QUERY_SO_STATISTICS",
>     "PIPE_QUERY_SO_OVERFLOW_PREDICATE",
>     "PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE",
>     "PIPE_QUERY_GPU_FINISHED",
>     "PIPE_QUERY_PIPELINE_STATISTICS",
> diff --git a/src/gallium/auxiliary/util/u_inlines.h b/src/gallium/auxiliary/util/u_inlines.h
> index e0ed594c9fe..79f62c32266 100644
> --- a/src/gallium/auxiliary/util/u_inlines.h
> +++ b/src/gallium/auxiliary/util/u_inlines.h
> @@ -529,20 +529,21 @@ util_get_min_point_size(const struct pipe_rasterizer_state *state)
>     return !state->point_quad_rasterization &&
>            !state->point_smooth &&
>            !state->multisample ? 1.0f : 0.0f;
>  }
>
>  static inline void
>  util_query_clear_result(union pipe_query_result *result, unsigned type)
>  {
>     switch (type) {
>     case PIPE_QUERY_OCCLUSION_PREDICATE:
> +   case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
>     case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
>     case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE:
>     case PIPE_QUERY_GPU_FINISHED:
>        result->b = FALSE;
>        break;
>     case PIPE_QUERY_OCCLUSION_COUNTER:
>     case PIPE_QUERY_TIMESTAMP:
>     case PIPE_QUERY_TIME_ELAPSED:
>     case PIPE_QUERY_PRIMITIVES_GENERATED:
>     case PIPE_QUERY_PRIMITIVES_EMITTED:
> diff --git a/src/gallium/docs/source/context.rst b/src/gallium/docs/source/context.rst
> index 6ac45819a66..ba7fef8301d 100644
> --- a/src/gallium/docs/source/context.rst
> +++ b/src/gallium/docs/source/context.rst
> @@ -387,20 +387,26 @@ are written to the framebuffer without being culled by
>  The result is an unsigned 64-bit integer.
>  This query can be used with ``render_condition``.
>
>  In cases where a boolean result of an occlusion query is enough,
>  ``PIPE_QUERY_OCCLUSION_PREDICATE`` should be used. It is just like
>  ``PIPE_QUERY_OCCLUSION_COUNTER`` except that the result is a boolean
>  value of FALSE for cases where COUNTER would result in 0 and TRUE
>  for all other cases.
>  This query can be used with ``render_condition``.
>
> +In cases where a conservative approximation of an occlusion query is enough,
> +``PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE`` should be used. It behaves
> +like ``PIPE_QUERY_OCCLUSION_PREDICATE``, except that it may return TRUE in
> +additional, implementation-dependent cases.
> +This query can be used with ``render_condition``.
> +
>  ``PIPE_QUERY_TIME_ELAPSED`` returns the amount of time, in nanoseconds,
>  the context takes to perform operations.
>  The result is an unsigned 64-bit integer.
>
>  ``PIPE_QUERY_TIMESTAMP`` returns a device/driver internal timestamp,
>  scaled to nanoseconds, recorded after all commands issued prior to
>  ``end_query`` have been processed.
>  This query does not require a call to ``begin_query``.
>  The result is an unsigned 64-bit integer.
>
> diff --git a/src/gallium/drivers/freedreno/a3xx/fd3_query.c b/src/gallium/drivers/freedreno/a3xx/fd3_query.c
> index cde42c37313..97a95b21546 100644
> --- a/src/gallium/drivers/freedreno/a3xx/fd3_query.c
> +++ b/src/gallium/drivers/freedreno/a3xx/fd3_query.c
> @@ -124,22 +124,30 @@ static const struct fd_hw_sample_provider occlusion_counter = {
>                 .accumulate_result = occlusion_counter_accumulate_result,
>  };
>
>  static const struct fd_hw_sample_provider occlusion_predicate = {
>                 .query_type = PIPE_QUERY_OCCLUSION_PREDICATE,
>                 .active = FD_STAGE_DRAW,
>                 .get_sample = occlusion_get_sample,
>                 .accumulate_result = occlusion_predicate_accumulate_result,
>  };
>
> +static const struct fd_hw_sample_provider occlusion_predicate_conservative = {
> +               .query_type = PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE,
> +               .active = FD_STAGE_DRAW,
> +               .get_sample = occlusion_get_sample,
> +               .accumulate_result = occlusion_predicate_accumulate_result,
> +};
> +
>  void fd3_query_context_init(struct pipe_context *pctx)
>  {
>         struct fd_context *ctx = fd_context(pctx);
>
>         ctx->create_query = fd_hw_create_query;
>         ctx->query_prepare = fd_hw_query_prepare;
>         ctx->query_prepare_tile = fd_hw_query_prepare_tile;
>         ctx->query_set_stage = fd_hw_query_set_stage;
>
>         fd_hw_query_register_provider(pctx, &occlusion_counter);
>         fd_hw_query_register_provider(pctx, &occlusion_predicate);
> +       fd_hw_query_register_provider(pctx, &occlusion_predicate_conservative);
>  }
> diff --git a/src/gallium/drivers/freedreno/a4xx/fd4_query.c b/src/gallium/drivers/freedreno/a4xx/fd4_query.c
> index f7b385d552d..809e7570b48 100644
> --- a/src/gallium/drivers/freedreno/a4xx/fd4_query.c
> +++ b/src/gallium/drivers/freedreno/a4xx/fd4_query.c
> @@ -244,20 +244,27 @@ static const struct fd_hw_sample_provider occlusion_counter = {
>                 .accumulate_result = occlusion_counter_accumulate_result,
>  };
>
>  static const struct fd_hw_sample_provider occlusion_predicate = {
>                 .query_type = PIPE_QUERY_OCCLUSION_PREDICATE,
>                 .active = FD_STAGE_DRAW,
>                 .get_sample = occlusion_get_sample,
>                 .accumulate_result = occlusion_predicate_accumulate_result,
>  };
>
> +static const struct fd_hw_sample_provider occlusion_predicate = {
> +               .query_type = PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE,
> +               .active = FD_STAGE_DRAW,
> +               .get_sample = occlusion_get_sample,
> +               .accumulate_result = occlusion_predicate_accumulate_result,
> +};
> +
>  static const struct fd_hw_sample_provider time_elapsed = {
>                 .query_type = PIPE_QUERY_TIME_ELAPSED,
>                 .active = FD_STAGE_DRAW | FD_STAGE_CLEAR,
>                 .enable = time_elapsed_enable,
>                 .get_sample = time_elapsed_get_sample,
>                 .accumulate_result = time_elapsed_accumulate_result,
>  };
>
>  /* NOTE: timestamp query isn't going to give terribly sensible results
>   * on a tiler.  But it is needed by qapitrace profile heatmap.  If you
> @@ -277,13 +284,14 @@ void fd4_query_context_init(struct pipe_context *pctx)
>  {
>         struct fd_context *ctx = fd_context(pctx);
>
>         ctx->create_query = fd_hw_create_query;
>         ctx->query_prepare = fd_hw_query_prepare;
>         ctx->query_prepare_tile = fd_hw_query_prepare_tile;
>         ctx->query_set_stage = fd_hw_query_set_stage;
>
>         fd_hw_query_register_provider(pctx, &occlusion_counter);
>         fd_hw_query_register_provider(pctx, &occlusion_predicate);
> +       fd_hw_query_register_provider(pctx, &occlusion_predicate_conservative);
>         fd_hw_query_register_provider(pctx, &time_elapsed);
>         fd_hw_query_register_provider(pctx, &timestamp);
>  }
> diff --git a/src/gallium/drivers/freedreno/a5xx/fd5_query.c b/src/gallium/drivers/freedreno/a5xx/fd5_query.c
> index 80b84ce54ba..87417f1f96e 100644
> --- a/src/gallium/drivers/freedreno/a5xx/fd5_query.c
> +++ b/src/gallium/drivers/freedreno/a5xx/fd5_query.c
> @@ -137,20 +137,29 @@ static const struct fd_acc_sample_provider occlusion_counter = {
>
>  static const struct fd_acc_sample_provider occlusion_predicate = {
>                 .query_type = PIPE_QUERY_OCCLUSION_PREDICATE,
>                 .active = FD_STAGE_DRAW,
>                 .size = sizeof(struct fd5_query_sample),
>                 .resume = occlusion_resume,
>                 .pause = occlusion_pause,
>                 .result = occlusion_predicate_result,
>  };
>
> +static const struct fd_acc_sample_provider occlusion_predicate_conservative = {
> +               .query_type = PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE,
> +               .active = FD_STAGE_DRAW,
> +               .size = sizeof(struct fd5_query_sample),
> +               .resume = occlusion_resume,
> +               .pause = occlusion_pause,
> +               .result = occlusion_predicate_result,
> +};
> +
>  /*
>   * Timestamp Queries:
>   */
>
>  static void
>  timestamp_resume(struct fd_acc_query *aq, struct fd_batch *batch)
>  {
>         struct fd_ringbuffer *ring = batch->draw;
>
>         OUT_PKT7(ring, CP_EVENT_WRITE, 4);
> @@ -240,14 +249,15 @@ static const struct fd_acc_sample_provider timestamp = {
>  void
>  fd5_query_context_init(struct pipe_context *pctx)
>  {
>         struct fd_context *ctx = fd_context(pctx);
>
>         ctx->create_query = fd_acc_create_query;
>         ctx->query_set_stage = fd_acc_query_set_stage;
>
>         fd_acc_query_register_provider(pctx, &occlusion_counter);
>         fd_acc_query_register_provider(pctx, &occlusion_predicate);
> +       fd_acc_query_register_provider(pctx, &occlusion_predicate_conservative);
>
>         fd_acc_query_register_provider(pctx, &time_elapsed);
>         fd_acc_query_register_provider(pctx, &timestamp);
>  }
> diff --git a/src/gallium/drivers/freedreno/freedreno_query.h b/src/gallium/drivers/freedreno/freedreno_query.h
> index 49a86803c4d..b8fa0951ded 100644
> --- a/src/gallium/drivers/freedreno/freedreno_query.h
> +++ b/src/gallium/drivers/freedreno/freedreno_query.h
> @@ -78,20 +78,21 @@ skip_begin_query(int type)
>  }
>
>  /* maps query_type to sample provider idx: */
>  static inline
>  int pidx(unsigned query_type)
>  {
>         switch (query_type) {
>         case PIPE_QUERY_OCCLUSION_COUNTER:
>                 return 0;
>         case PIPE_QUERY_OCCLUSION_PREDICATE:
> +       case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
>                 return 1;
>         /* TODO currently queries only emitted in main pass (not in binning pass)..
>          * which is fine for occlusion query, but pretty much not anything else.
>          */
>         case PIPE_QUERY_TIME_ELAPSED:
>                 return 2;
>         case PIPE_QUERY_TIMESTAMP:
>                 return 3;
>         default:
>                 return -1;
> diff --git a/src/gallium/drivers/llvmpipe/lp_query.c b/src/gallium/drivers/llvmpipe/lp_query.c
> index 6f8ce94e5d8..7b81903b413 100644
> --- a/src/gallium/drivers/llvmpipe/lp_query.c
> +++ b/src/gallium/drivers/llvmpipe/lp_query.c
> @@ -118,20 +118,21 @@ llvmpipe_get_query_result(struct pipe_context *pipe,
>      */
>     *result = 0;
>
>     switch (pq->type) {
>     case PIPE_QUERY_OCCLUSION_COUNTER:
>        for (i = 0; i < num_threads; i++) {
>           *result += pq->end[i];
>        }
>        break;
>     case PIPE_QUERY_OCCLUSION_PREDICATE:
> +   case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
>        for (i = 0; i < num_threads; i++) {
>           /* safer (still not guaranteed) when there's an overflow */
>           vresult->b = vresult->b || pq->end[i];
>        }
>        break;
>     case PIPE_QUERY_TIMESTAMP:
>        for (i = 0; i < num_threads; i++) {
>           if (pq->end[i] > *result) {
>              *result = pq->end[i];
>           }
> @@ -224,20 +225,21 @@ llvmpipe_begin_query(struct pipe_context *pipe, struct pipe_query *q)
>        /* reset our cache */
>        if (llvmpipe->active_statistics_queries == 0) {
>           memset(&llvmpipe->pipeline_statistics, 0,
>                  sizeof(llvmpipe->pipeline_statistics));
>        }
>        memcpy(&pq->stats, &llvmpipe->pipeline_statistics, sizeof(pq->stats));
>        llvmpipe->active_statistics_queries++;
>        break;
>     case PIPE_QUERY_OCCLUSION_COUNTER:
>     case PIPE_QUERY_OCCLUSION_PREDICATE:
> +   case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
>        llvmpipe->active_occlusion_queries++;
>        llvmpipe->dirty |= LP_NEW_OCCLUSION_QUERY;
>        break;
>     default:
>        break;
>     }
>     return true;
>  }
>
>
> @@ -287,20 +289,21 @@ llvmpipe_end_query(struct pipe_context *pipe, struct pipe_query *q)
>           llvmpipe->pipeline_statistics.c_invocations - pq->stats.c_invocations;
>        pq->stats.c_primitives =
>           llvmpipe->pipeline_statistics.c_primitives - pq->stats.c_primitives;
>        pq->stats.ps_invocations =
>           llvmpipe->pipeline_statistics.ps_invocations - pq->stats.ps_invocations;
>
>        llvmpipe->active_statistics_queries--;
>        break;
>     case PIPE_QUERY_OCCLUSION_COUNTER:
>     case PIPE_QUERY_OCCLUSION_PREDICATE:
> +   case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
>        assert(llvmpipe->active_occlusion_queries);
>        llvmpipe->active_occlusion_queries--;
>        llvmpipe->dirty |= LP_NEW_OCCLUSION_QUERY;
>        break;
>     default:
>        break;
>     }
>
>     return true;
>  }
> diff --git a/src/gallium/drivers/llvmpipe/lp_rast.c b/src/gallium/drivers/llvmpipe/lp_rast.c
> index b25ade3d2ec..0050655d9e3 100644
> --- a/src/gallium/drivers/llvmpipe/lp_rast.c
> +++ b/src/gallium/drivers/llvmpipe/lp_rast.c
> @@ -479,20 +479,21 @@ lp_rast_shade_quads_mask(struct lp_rasterizer_task *task,
>   */
>  static void
>  lp_rast_begin_query(struct lp_rasterizer_task *task,
>                      const union lp_rast_cmd_arg arg)
>  {
>     struct llvmpipe_query *pq = arg.query_obj;
>
>     switch (pq->type) {
>     case PIPE_QUERY_OCCLUSION_COUNTER:
>     case PIPE_QUERY_OCCLUSION_PREDICATE:
> +   case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
>        pq->start[task->thread_index] = task->thread_data.vis_counter;
>        break;
>     case PIPE_QUERY_PIPELINE_STATISTICS:
>        pq->start[task->thread_index] = task->ps_invocations;
>        break;
>     default:
>        assert(0);
>        break;
>     }
>  }
> @@ -505,20 +506,21 @@ lp_rast_begin_query(struct lp_rasterizer_task *task,
>   */
>  static void
>  lp_rast_end_query(struct lp_rasterizer_task *task,
>                    const union lp_rast_cmd_arg arg)
>  {
>     struct llvmpipe_query *pq = arg.query_obj;
>
>     switch (pq->type) {
>     case PIPE_QUERY_OCCLUSION_COUNTER:
>     case PIPE_QUERY_OCCLUSION_PREDICATE:
> +   case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
>        pq->end[task->thread_index] +=
>           task->thread_data.vis_counter - pq->start[task->thread_index];
>        pq->start[task->thread_index] = 0;
>        break;
>     case PIPE_QUERY_TIMESTAMP:
>        pq->end[task->thread_index] = os_time_get_nano();
>        break;
>     case PIPE_QUERY_PIPELINE_STATISTICS:
>        pq->end[task->thread_index] +=
>           task->ps_invocations - pq->start[task->thread_index];
> diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c
> index 32387ab5532..2be6fc033d1 100644
> --- a/src/gallium/drivers/llvmpipe/lp_setup.c
> +++ b/src/gallium/drivers/llvmpipe/lp_setup.c
> @@ -1373,20 +1373,21 @@ no_setup:
>   */
>  void
>  lp_setup_begin_query(struct lp_setup_context *setup,
>                       struct llvmpipe_query *pq)
>  {
>
>     set_scene_state(setup, SETUP_ACTIVE, "begin_query");
>
>     if (!(pq->type == PIPE_QUERY_OCCLUSION_COUNTER ||
>           pq->type == PIPE_QUERY_OCCLUSION_PREDICATE ||
> +         pq->type == PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE ||
>           pq->type == PIPE_QUERY_PIPELINE_STATISTICS))
>        return;
>
>     /* init the query to its beginning state */
>     assert(setup->active_binned_queries < LP_MAX_ACTIVE_BINNED_QUERIES);
>     /* exceeding list size so just ignore the query */
>     if (setup->active_binned_queries >= LP_MAX_ACTIVE_BINNED_QUERIES) {
>        return;
>     }
>     assert(setup->active_queries[setup->active_binned_queries] == NULL);
> @@ -1423,20 +1424,21 @@ lp_setup_end_query(struct lp_setup_context *setup, struct llvmpipe_query *pq)
>
>     assert(setup->scene);
>     if (setup->scene) {
>        /* pq->fence should be the fence of the *last* scene which
>         * contributed to the query result.
>         */
>        lp_fence_reference(&pq->fence, setup->scene->fence);
>
>        if (pq->type == PIPE_QUERY_OCCLUSION_COUNTER ||
>            pq->type == PIPE_QUERY_OCCLUSION_PREDICATE ||
> +          pq->type == PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE ||
>            pq->type == PIPE_QUERY_PIPELINE_STATISTICS ||
>            pq->type == PIPE_QUERY_TIMESTAMP) {
>           if (pq->type == PIPE_QUERY_TIMESTAMP &&
>                 !(setup->scene->tiles_x | setup->scene->tiles_y)) {
>              /*
>               * If there's a zero width/height framebuffer, there's no bins and
>               * hence no rast task is ever run. So fill in something here instead.
>               */
>              pq->end[0] = os_time_get_nano();
>           }
> @@ -1459,20 +1461,21 @@ lp_setup_end_query(struct lp_setup_context *setup, struct llvmpipe_query *pq)
>     else {
>        lp_fence_reference(&pq->fence, setup->last_fence);
>     }
>
>  fail:
>     /* Need to do this now not earlier since it still needs to be marked as
>      * active when binning it would cause a flush.
>      */
>     if (pq->type == PIPE_QUERY_OCCLUSION_COUNTER ||
>        pq->type == PIPE_QUERY_OCCLUSION_PREDICATE ||
> +      pq->type == PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE ||
>        pq->type == PIPE_QUERY_PIPELINE_STATISTICS) {
>        unsigned i;
>
>        /* remove from active binned query list */
>        for (i = 0; i < setup->active_binned_queries; i++) {
>           if (setup->active_queries[i] == pq)
>              break;
>        }
>        assert(i < setup->active_binned_queries);
>        if (i == setup->active_binned_queries)
> diff --git a/src/gallium/drivers/nouveau/nv30/nv30_query.c b/src/gallium/drivers/nouveau/nv30/nv30_query.c
> index 83ea3afec02..f26728868af 100644
> --- a/src/gallium/drivers/nouveau/nv30/nv30_query.c
> +++ b/src/gallium/drivers/nouveau/nv30/nv30_query.c
> @@ -114,20 +114,21 @@ nv30_query_create(struct pipe_context *pipe, unsigned type, unsigned index)
>     q->type = type;
>
>     switch (q->type) {
>     case PIPE_QUERY_TIMESTAMP:
>     case PIPE_QUERY_TIME_ELAPSED:
>        q->enable = 0x0000;
>        q->report = 1;
>        break;
>     case PIPE_QUERY_OCCLUSION_COUNTER:
>     case PIPE_QUERY_OCCLUSION_PREDICATE:
> +   case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
>        q->enable = NV30_3D_QUERY_ENABLE;
>        q->report = 1;
>        break;
>     case NV30_QUERY_ZCULL_0:
>     case NV30_QUERY_ZCULL_1:
>     case NV30_QUERY_ZCULL_2:
>     case NV30_QUERY_ZCULL_3:
>        q->enable = 0x1804;
>        q->report = 2 + (q->type - NV30_QUERY_ZCULL_0);
>        break;
> @@ -221,21 +222,22 @@ nv30_query_result(struct pipe_context *pipe, struct pipe_query *pq,
>           break;
>        default:
>           q->result = ntfy1[2];
>           break;
>        }
>
>        nv30_query_object_del(screen, &q->qo[0]);
>        nv30_query_object_del(screen, &q->qo[1]);
>     }
>
> -   if (q->type == PIPE_QUERY_OCCLUSION_PREDICATE)
> +   if (q->type == PIPE_QUERY_OCCLUSION_PREDICATE ||
> +       q->type == PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE)
>        result->b = !!q->result;
>     else
>        result->u64 = q->result;
>     return true;
>  }
>
>  static void
>  nv40_query_render_condition(struct pipe_context *pipe,
>                              struct pipe_query *pq,
>                              boolean condition, enum pipe_render_cond_flag mode)
> diff --git a/src/gallium/drivers/nouveau/nv50/nv50_query.c b/src/gallium/drivers/nouveau/nv50/nv50_query.c
> index ec6ee0f5eb3..e30380cd84d 100644
> --- a/src/gallium/drivers/nouveau/nv50/nv50_query.c
> +++ b/src/gallium/drivers/nouveau/nv50/nv50_query.c
> @@ -90,20 +90,21 @@ nv50_render_condition(struct pipe_context *pipe,
>     else {
>        /* NOTE: comparison of 2 queries only works if both have completed */
>        switch (q->type) {
>        case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
>           cond = condition ? NV50_3D_COND_MODE_EQUAL :
>                              NV50_3D_COND_MODE_NOT_EQUAL;
>           wait = true;
>           break;
>        case PIPE_QUERY_OCCLUSION_COUNTER:
>        case PIPE_QUERY_OCCLUSION_PREDICATE:
> +      case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
>           if (likely(!condition)) {
>              if (unlikely(hq->nesting))
>                 cond = wait ? NV50_3D_COND_MODE_NOT_EQUAL :
>                               NV50_3D_COND_MODE_ALWAYS;
>              else
>                 cond = NV50_3D_COND_MODE_RES_NON_ZERO;
>           } else {
>              cond = wait ? NV50_3D_COND_MODE_EQUAL : NV50_3D_COND_MODE_ALWAYS;
>           }
>           break;
> diff --git a/src/gallium/drivers/nouveau/nv50/nv50_query_hw.c b/src/gallium/drivers/nouveau/nv50/nv50_query_hw.c
> index 727b509372d..ac3e409b2d5 100644
> --- a/src/gallium/drivers/nouveau/nv50/nv50_query_hw.c
> +++ b/src/gallium/drivers/nouveau/nv50/nv50_query_hw.c
> @@ -150,20 +150,21 @@ nv50_hw_begin_query(struct nv50_context *nv50, struct nv50_query *q)
>        hq->data[1] = 1; /* initial render condition = true */
>        hq->data[4] = hq->sequence + 1; /* for comparison COND_MODE */
>        hq->data[5] = 0;
>     }
>     if (!hq->is64bit)
>        hq->data[0] = hq->sequence++; /* the previously used one */
>
>     switch (q->type) {
>     case PIPE_QUERY_OCCLUSION_COUNTER:
>     case PIPE_QUERY_OCCLUSION_PREDICATE:
> +   case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
>        hq->nesting = nv50->screen->num_occlusion_queries_active++;
>        if (hq->nesting) {
>           nv50_hw_query_get(push, q, 0x10, 0x0100f002);
>        } else {
>           PUSH_SPACE(push, 4);
>           BEGIN_NV04(push, NV50_3D(COUNTER_RESET), 1);
>           PUSH_DATA (push, NV50_3D_COUNTER_RESET_SAMPLECNT);
>           BEGIN_NV04(push, NV50_3D(SAMPLECNT_ENABLE), 1);
>           PUSH_DATA (push, 1);
>        }
> @@ -208,20 +209,21 @@ nv50_hw_end_query(struct nv50_context *nv50, struct nv50_query *q)
>     if (hq->funcs && hq->funcs->end_query) {
>        hq->funcs->end_query(nv50, hq);
>        return;
>     }
>
>     hq->state = NV50_HW_QUERY_STATE_ENDED;
>
>     switch (q->type) {
>     case PIPE_QUERY_OCCLUSION_COUNTER:
>     case PIPE_QUERY_OCCLUSION_PREDICATE:
> +   case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
>        nv50_hw_query_get(push, q, 0, 0x0100f002);
>        if (--nv50->screen->num_occlusion_queries_active == 0) {
>           PUSH_SPACE(push, 2);
>           BEGIN_NV04(push, NV50_3D(SAMPLECNT_ENABLE), 1);
>           PUSH_DATA (push, 0);
>        }
>        break;
>     case PIPE_QUERY_PRIMITIVES_GENERATED:
>        nv50_hw_query_get(push, q, 0, 0x06805002);
>        break;
> @@ -300,20 +302,21 @@ nv50_hw_get_query_result(struct nv50_context *nv50, struct nv50_query *q,
>     hq->state = NV50_HW_QUERY_STATE_READY;
>
>     switch (q->type) {
>     case PIPE_QUERY_GPU_FINISHED:
>        res8[0] = true;
>        break;
>     case PIPE_QUERY_OCCLUSION_COUNTER: /* u32 sequence, u32 count, u64 time */
>        res64[0] = hq->data[1] - hq->data[5];
>        break;
>     case PIPE_QUERY_OCCLUSION_PREDICATE:
> +   case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
>        res8[0] = hq->data[1] != hq->data[5];
>        break;
>     case PIPE_QUERY_PRIMITIVES_GENERATED: /* u64 count, u64 time */
>     case PIPE_QUERY_PRIMITIVES_EMITTED: /* u64 count, u64 time */
>        res64[0] = data64[0] - data64[2];
>        break;
>     case PIPE_QUERY_SO_STATISTICS:
>        res64[0] = data64[0] - data64[4];
>        res64[1] = data64[2] - data64[6];
>        break;
> @@ -371,20 +374,21 @@ nv50_hw_create_query(struct nv50_context *nv50, unsigned type, unsigned index)
>     if (!hq)
>        return NULL;
>
>     q = &hq->base;
>     q->funcs = &hw_query_funcs;
>     q->type = type;
>
>     switch (q->type) {
>     case PIPE_QUERY_OCCLUSION_COUNTER:
>     case PIPE_QUERY_OCCLUSION_PREDICATE:
> +   case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
>        hq->rotate = 32;
>        break;
>     case PIPE_QUERY_PRIMITIVES_GENERATED:
>     case PIPE_QUERY_PRIMITIVES_EMITTED:
>     case PIPE_QUERY_SO_STATISTICS:
>     case PIPE_QUERY_PIPELINE_STATISTICS:
>        hq->is64bit = true;
>        break;
>     case PIPE_QUERY_TIME_ELAPSED:
>     case PIPE_QUERY_TIMESTAMP:
> diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_query.c b/src/gallium/drivers/nouveau/nvc0/nvc0_query.c
> index e3090745e3b..d0a9e0c2c04 100644
> --- a/src/gallium/drivers/nouveau/nvc0/nvc0_query.c
> +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_query.c
> @@ -112,20 +112,21 @@ nvc0_render_condition(struct pipe_context *pipe,
>     else {
>        /* NOTE: comparison of 2 queries only works if both have completed */
>        switch (q->type) {
>        case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
>           cond = condition ? NVC0_3D_COND_MODE_EQUAL :
>                            NVC0_3D_COND_MODE_NOT_EQUAL;
>           wait = true;
>           break;
>        case PIPE_QUERY_OCCLUSION_COUNTER:
>        case PIPE_QUERY_OCCLUSION_PREDICATE:
> +      case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
>           if (likely(!condition)) {
>              if (unlikely(hq->nesting))
>                 cond = wait ? NVC0_3D_COND_MODE_NOT_EQUAL :
>                               NVC0_3D_COND_MODE_ALWAYS;
>              else
>                 cond = NVC0_3D_COND_MODE_RES_NON_ZERO;
>           } else {
>              cond = wait ? NVC0_3D_COND_MODE_EQUAL : NVC0_3D_COND_MODE_ALWAYS;
>           }
>           break;
> diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_query_hw.c b/src/gallium/drivers/nouveau/nvc0/nvc0_query_hw.c
> index d8d82de8650..f2fdb0cd999 100644
> --- a/src/gallium/drivers/nouveau/nvc0/nvc0_query_hw.c
> +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_query_hw.c
> @@ -150,20 +150,21 @@ nvc0_hw_begin_query(struct nvc0_context *nvc0, struct nvc0_query *q)
>        hq->data[0] = hq->sequence; /* initialize sequence */
>        hq->data[1] = 1; /* initial render condition = true */
>        hq->data[4] = hq->sequence + 1; /* for comparison COND_MODE */
>        hq->data[5] = 0;
>     }
>     hq->sequence++;
>
>     switch (q->type) {
>     case PIPE_QUERY_OCCLUSION_COUNTER:
>     case PIPE_QUERY_OCCLUSION_PREDICATE:
> +   case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
>        hq->nesting = nvc0->screen->num_occlusion_queries_active++;
>        if (hq->nesting) {
>           nvc0_hw_query_get(push, q, 0x10, 0x0100f002);
>        } else {
>           PUSH_SPACE(push, 3);
>           BEGIN_NVC0(push, NVC0_3D(COUNTER_RESET), 1);
>           PUSH_DATA (push, NVC0_3D_COUNTER_RESET_SAMPLECNT);
>           IMMED_NVC0(push, NVC0_3D(SAMPLECNT_ENABLE), 1);
>        }
>        break;
> @@ -217,20 +218,21 @@ nvc0_hw_end_query(struct nvc0_context *nvc0, struct nvc0_query *q)
>        /* some queries don't require 'begin' to be called (e.g. GPU_FINISHED) */
>        if (hq->rotate)
>           nvc0_hw_query_rotate(nvc0, q);
>        hq->sequence++;
>     }
>     hq->state = NVC0_HW_QUERY_STATE_ENDED;
>
>     switch (q->type) {
>     case PIPE_QUERY_OCCLUSION_COUNTER:
>     case PIPE_QUERY_OCCLUSION_PREDICATE:
> +   case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
>        nvc0_hw_query_get(push, q, 0, 0x0100f002);
>        if (--nvc0->screen->num_occlusion_queries_active == 0) {
>           PUSH_SPACE(push, 1);
>           IMMED_NVC0(push, NVC0_3D(SAMPLECNT_ENABLE), 0);
>        }
>        break;
>     case PIPE_QUERY_PRIMITIVES_GENERATED:
>        nvc0_hw_query_get(push, q, 0, 0x09005002 | (q->index << 5));
>        break;
>     case PIPE_QUERY_PRIMITIVES_EMITTED:
> @@ -313,20 +315,21 @@ nvc0_hw_get_query_result(struct nvc0_context *nvc0, struct nvc0_query *q,
>     hq->state = NVC0_HW_QUERY_STATE_READY;
>
>     switch (q->type) {
>     case PIPE_QUERY_GPU_FINISHED:
>        res8[0] = true;
>        break;
>     case PIPE_QUERY_OCCLUSION_COUNTER: /* u32 sequence, u32 count, u64 time */
>        res64[0] = hq->data[1] - hq->data[5];
>        break;
>     case PIPE_QUERY_OCCLUSION_PREDICATE:
> +   case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
>        res8[0] = hq->data[1] != hq->data[5];
>        break;
>     case PIPE_QUERY_PRIMITIVES_GENERATED: /* u64 count, u64 time */
>     case PIPE_QUERY_PRIMITIVES_EMITTED: /* u64 count, u64 time */
>        res64[0] = data64[0] - data64[2];
>        break;
>     case PIPE_QUERY_SO_STATISTICS:
>        res64[0] = data64[0] - data64[4];
>        res64[1] = data64[2] - data64[6];
>        break;
> @@ -401,21 +404,22 @@ nvc0_hw_get_query_result_resource(struct nvc0_context *nvc0,
>     if (hq->state != NVC0_HW_QUERY_STATE_READY)
>        nvc0_hw_query_update(nvc0->screen->base.client, q);
>
>     if (wait && hq->state != NVC0_HW_QUERY_STATE_READY)
>        nvc0_hw_query_fifo_wait(nvc0, q);
>
>     nouveau_pushbuf_space(push, 32, 2, 0);
>     PUSH_REFN (push, hq->bo, NOUVEAU_BO_GART | NOUVEAU_BO_RD);
>     PUSH_REFN (push, buf->bo, buf->domain | NOUVEAU_BO_WR);
>     BEGIN_1IC0(push, NVC0_3D(MACRO_QUERY_BUFFER_WRITE), 9);
> -   if (q->type == PIPE_QUERY_OCCLUSION_PREDICATE) /* XXX what if 64-bit? */
> +   if (q->type == PIPE_QUERY_OCCLUSION_PREDICATE ||
> +       q->type ++ PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE) /* XXX what if 64-bit? */
>        PUSH_DATA(push, 0x00000001);
>     else if (result_type == PIPE_QUERY_TYPE_I32)
>        PUSH_DATA(push, 0x7fffffff);
>     else if (result_type == PIPE_QUERY_TYPE_U32)
>        PUSH_DATA(push, 0xffffffff);
>     else
>        PUSH_DATA(push, 0x00000000);
>
>     switch (q->type) {
>     case PIPE_QUERY_SO_STATISTICS:
> @@ -506,20 +510,21 @@ nvc0_hw_create_query(struct nvc0_context *nvc0, unsigned type, unsigned index)
>     if (!hq)
>        return NULL;
>
>     q = &hq->base;
>     q->funcs = &hw_query_funcs;
>     q->type = type;
>
>     switch (q->type) {
>     case PIPE_QUERY_OCCLUSION_COUNTER:
>     case PIPE_QUERY_OCCLUSION_PREDICATE:
> +   case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
>        hq->rotate = 32;
>        space = NVC0_HW_QUERY_ALLOC_SPACE;
>        break;
>     case PIPE_QUERY_PIPELINE_STATISTICS:
>        hq->is64bit = true;
>        space = 512;
>        break;
>     case PIPE_QUERY_SO_STATISTICS:
>     case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
>        hq->is64bit = true;
> diff --git a/src/gallium/drivers/r300/r300_query.c b/src/gallium/drivers/r300/r300_query.c
> index d2dc7b73c05..a84c941768f 100644
> --- a/src/gallium/drivers/r300/r300_query.c
> +++ b/src/gallium/drivers/r300/r300_query.c
> @@ -32,20 +32,21 @@
>  static struct pipe_query *r300_create_query(struct pipe_context *pipe,
>                                              unsigned query_type,
>                                              unsigned index)
>  {
>      struct r300_context *r300 = r300_context(pipe);
>      struct r300_screen *r300screen = r300->screen;
>      struct r300_query *q;
>
>      if (query_type != PIPE_QUERY_OCCLUSION_COUNTER &&
>          query_type != PIPE_QUERY_OCCLUSION_PREDICATE &&
> +        query_type != PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE &&
>          query_type != PIPE_QUERY_GPU_FINISHED) {
>          return NULL;
>      }
>
>      q = CALLOC_STRUCT(r300_query);
>      if (!q)
>          return NULL;
>
>      q->type = query_type;
>
> @@ -164,21 +165,22 @@ static boolean r300_get_query_result(struct pipe_context* pipe,
>          return FALSE;
>
>      /* Sum up the results. */
>      temp = 0;
>      for (i = 0; i < q->num_results; i++) {
>          /* Convert little endian values written by GPU to CPU byte order */
>          temp += util_le32_to_cpu(*map);
>          map++;
>      }
>
> -    if (q->type == PIPE_QUERY_OCCLUSION_PREDICATE) {
> +    if (q->type == PIPE_QUERY_OCCLUSION_PREDICATE ||
> +        q->type == PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE) {
>          vresult->b = temp != 0;
>      } else {
>          vresult->u64 = temp;
>      }
>      return TRUE;
>  }
>
>  static void r300_render_condition(struct pipe_context *pipe,
>                                    struct pipe_query *query,
>                                    boolean condition,
> @@ -188,21 +190,22 @@ static void r300_render_condition(struct pipe_context *pipe,
>      union pipe_query_result result;
>      boolean wait;
>
>      r300->skip_rendering = FALSE;
>
>      if (query) {
>          wait = mode == PIPE_RENDER_COND_WAIT ||
>                 mode == PIPE_RENDER_COND_BY_REGION_WAIT;
>
>          if (r300_get_query_result(pipe, query, wait, &result)) {
> -            if (r300_query(query)->type == PIPE_QUERY_OCCLUSION_PREDICATE) {
> +            if (r300_query(query)->type == PIPE_QUERY_OCCLUSION_PREDICATE ||
> +                r300_query(query)->type == PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE) {
>                  r300->skip_rendering = condition == result.b;
>              } else {
>                  r300->skip_rendering = condition == !!result.u64;
>              }
>          }
>      }
>  }
>
>  static void
>  r300_set_active_query_state(struct pipe_context *pipe, boolean enable)
> diff --git a/src/gallium/drivers/radeon/r600_pipe_common.c b/src/gallium/drivers/radeon/r600_pipe_common.c
> index b283bc65b5b..1183e181a82 100644
> --- a/src/gallium/drivers/radeon/r600_pipe_common.c
> +++ b/src/gallium/drivers/radeon/r600_pipe_common.c
> @@ -119,21 +119,22 @@ void r600_gfx_write_event_eop(struct r600_common_context *ctx,
>         if (ctx->chip_class >= GFX9) {
>                 /* A ZPASS_DONE or PIXEL_STAT_DUMP_EVENT (of the DB occlusion
>                  * counters) must immediately precede every timestamp event to
>                  * prevent a GPU hang on GFX9.
>                  *
>                  * Occlusion queries don't need to do it here, because they
>                  * always do ZPASS_DONE before the timestamp.
>                  */
>                 if (ctx->chip_class == GFX9 &&
>                     query_type != PIPE_QUERY_OCCLUSION_COUNTER &&
> -                   query_type != PIPE_QUERY_OCCLUSION_PREDICATE) {
> +                   query_type != PIPE_QUERY_OCCLUSION_PREDICATE &&
> +                   query_type != PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE) {
>                         struct r600_resource *scratch = ctx->eop_bug_scratch;
>
>                         assert(16 * ctx->screen->info.num_render_backends <=
>                                scratch->b.b.width0);
>                         radeon_emit(cs, PKT3(PKT3_EVENT_WRITE, 2, 0));
>                         radeon_emit(cs, EVENT_TYPE(EVENT_TYPE_ZPASS_DONE) | EVENT_INDEX(1));
>                         radeon_emit(cs, scratch->gpu_address);
>                         radeon_emit(cs, scratch->gpu_address >> 32);
>
>                         radeon_add_to_buffer_list(ctx, &ctx->gfx, scratch,
> diff --git a/src/gallium/drivers/radeon/r600_query.c b/src/gallium/drivers/radeon/r600_query.c
> index 76307ca0662..e655bbdaa23 100644
> --- a/src/gallium/drivers/radeon/r600_query.c
> +++ b/src/gallium/drivers/radeon/r600_query.c
> @@ -544,21 +544,22 @@ static bool r600_query_hw_prepare_buffer(struct r600_common_screen *rscreen,
>         /* Callers ensure that the buffer is currently unused by the GPU. */
>         uint32_t *results = rscreen->ws->buffer_map(buffer->buf, NULL,
>                                                    PIPE_TRANSFER_WRITE |
>                                                    PIPE_TRANSFER_UNSYNCHRONIZED);
>         if (!results)
>                 return false;
>
>         memset(results, 0, buffer->b.b.width0);
>
>         if (query->b.type == PIPE_QUERY_OCCLUSION_COUNTER ||
> -           query->b.type == PIPE_QUERY_OCCLUSION_PREDICATE) {
> +           query->b.type == PIPE_QUERY_OCCLUSION_PREDICATE ||
> +           query->b.type == PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE) {
>                 unsigned max_rbs = rscreen->info.num_render_backends;
>                 unsigned enabled_rb_mask = rscreen->info.enabled_rb_mask;
>                 unsigned num_results;
>                 unsigned i, j;
>
>                 /* Set top bits for unused backends. */
>                 num_results = buffer->b.b.width0 / query->result_size;
>                 for (j = 0; j < num_results; j++) {
>                         for (i = 0; i < max_rbs; i++) {
>                                 if (!(enabled_rb_mask & (1<<i))) {
> @@ -629,20 +630,21 @@ static struct pipe_query *r600_query_hw_create(struct r600_common_screen *rscree
>         if (!query)
>                 return NULL;
>
>         query->b.type = query_type;
>         query->b.ops = &query_hw_ops;
>         query->ops = &query_hw_default_hw_ops;
>
>         switch (query_type) {
>         case PIPE_QUERY_OCCLUSION_COUNTER:
>         case PIPE_QUERY_OCCLUSION_PREDICATE:
> +       case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
>                 query->result_size = 16 * rscreen->info.num_render_backends;
>                 query->result_size += 16; /* for the fence + alignment */
>                 query->num_cs_dw_begin = 6;
>                 query->num_cs_dw_end = 6 + r600_gfx_write_fence_dwords(rscreen);
>                 break;
>         case PIPE_QUERY_TIME_ELAPSED:
>                 query->result_size = 24;
>                 query->num_cs_dw_begin = 8;
>                 query->num_cs_dw_end = 8 + r600_gfx_write_fence_dwords(rscreen);
>                 break;
> @@ -685,30 +687,31 @@ static struct pipe_query *r600_query_hw_create(struct r600_common_screen *rscree
>                 return NULL;
>         }
>
>         return (struct pipe_query *)query;
>  }
>
>  static void r600_update_occlusion_query_state(struct r600_common_context *rctx,
>                                               unsigned type, int diff)
>  {
>         if (type == PIPE_QUERY_OCCLUSION_COUNTER ||
> -           type == PIPE_QUERY_OCCLUSION_PREDICATE) {
> +           type == PIPE_QUERY_OCCLUSION_PREDICATE ||
> +           type == PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE) {
>                 bool old_enable = rctx->num_occlusion_queries != 0;
>                 bool old_perfect_enable =
>                         rctx->num_perfect_occlusion_queries != 0;
>                 bool enable, perfect_enable;
>
>                 rctx->num_occlusion_queries += diff;
>                 assert(rctx->num_occlusion_queries >= 0);
>
> -               if (type == PIPE_QUERY_OCCLUSION_COUNTER) {
> +               if (type != PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE) {
>                         rctx->num_perfect_occlusion_queries += diff;
>                         assert(rctx->num_perfect_occlusion_queries >= 0);
>                 }
>
>                 enable = rctx->num_occlusion_queries != 0;
>                 perfect_enable = rctx->num_perfect_occlusion_queries != 0;
>
>                 if (enable != old_enable || perfect_enable != old_perfect_enable) {
>                         rctx->set_occlusion_query_state(&rctx->b, enable);
>                 }
> @@ -738,20 +741,21 @@ static void emit_sample_streamout(struct radeon_winsys_cs *cs, uint64_t va,
>  static void r600_query_hw_do_emit_start(struct r600_common_context *ctx,
>                                         struct r600_query_hw *query,
>                                         struct r600_resource *buffer,
>                                         uint64_t va)
>  {
>         struct radeon_winsys_cs *cs = ctx->gfx.cs;
>
>         switch (query->b.type) {
>         case PIPE_QUERY_OCCLUSION_COUNTER:
>         case PIPE_QUERY_OCCLUSION_PREDICATE:
> +       case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
>                 radeon_emit(cs, PKT3(PKT3_EVENT_WRITE, 2, 0));
>                 radeon_emit(cs, EVENT_TYPE(EVENT_TYPE_ZPASS_DONE) | EVENT_INDEX(1));
>                 radeon_emit(cs, va);
>                 radeon_emit(cs, va >> 32);
>                 break;
>         case PIPE_QUERY_PRIMITIVES_EMITTED:
>         case PIPE_QUERY_PRIMITIVES_GENERATED:
>         case PIPE_QUERY_SO_STATISTICS:
>         case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
>                 emit_sample_streamout(cs, va, query->stream);
> @@ -832,20 +836,21 @@ static void r600_query_hw_do_emit_stop(struct r600_common_context *ctx,
>                                        struct r600_query_hw *query,
>                                        struct r600_resource *buffer,
>                                        uint64_t va)
>  {
>         struct radeon_winsys_cs *cs = ctx->gfx.cs;
>         uint64_t fence_va = 0;
>
>         switch (query->b.type) {
>         case PIPE_QUERY_OCCLUSION_COUNTER:
>         case PIPE_QUERY_OCCLUSION_PREDICATE:
> +       case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
>                 va += 8;
>                 radeon_emit(cs, PKT3(PKT3_EVENT_WRITE, 2, 0));
>                 radeon_emit(cs, EVENT_TYPE(EVENT_TYPE_ZPASS_DONE) | EVENT_INDEX(1));
>                 radeon_emit(cs, va);
>                 radeon_emit(cs, va >> 32);
>
>                 fence_va = va + ctx->screen->info.num_render_backends * 16 - 8;
>                 break;
>         case PIPE_QUERY_PRIMITIVES_EMITTED:
>         case PIPE_QUERY_PRIMITIVES_GENERATED:
> @@ -954,20 +959,21 @@ static void r600_emit_query_predication(struct r600_common_context *ctx,
>         invert = ctx->render_cond_invert;
>         flag_wait = ctx->render_cond_mode == PIPE_RENDER_COND_WAIT ||
>                     ctx->render_cond_mode == PIPE_RENDER_COND_BY_REGION_WAIT;
>
>         if (query->workaround_buf) {
>                 op = PRED_OP(PREDICATION_OP_BOOL64);
>         } else {
>                 switch (query->b.type) {
>                 case PIPE_QUERY_OCCLUSION_COUNTER:
>                 case PIPE_QUERY_OCCLUSION_PREDICATE:
> +               case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
>                         op = PRED_OP(PREDICATION_OP_ZPASS);
>                         break;
>                 case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
>                 case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE:
>                         op = PRED_OP(PREDICATION_OP_PRIMCOUNT);
>                         invert = !invert;
>                         break;
>                 default:
>                         assert(0);
>                         return;
> @@ -1132,20 +1138,21 @@ static void r600_get_hw_query_params(struct r600_common_context *rctx,
>                                      struct r600_hw_query_params *params)
>  {
>         unsigned max_rbs = rctx->screen->info.num_render_backends;
>
>         params->pair_stride = 0;
>         params->pair_count = 1;
>
>         switch (rquery->b.type) {
>         case PIPE_QUERY_OCCLUSION_COUNTER:
>         case PIPE_QUERY_OCCLUSION_PREDICATE:
> +       case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
>                 params->start_offset = 0;
>                 params->end_offset = 8;
>                 params->fence_offset = max_rbs * 16;
>                 params->pair_stride = 16;
>                 params->pair_count = max_rbs;
>                 break;
>         case PIPE_QUERY_TIME_ELAPSED:
>                 params->start_offset = 0;
>                 params->end_offset = 8;
>                 params->fence_offset = 16;
> @@ -1224,21 +1231,22 @@ static void r600_query_hw_add_result(struct r600_common_screen *rscreen,
>
>         switch (query->b.type) {
>         case PIPE_QUERY_OCCLUSION_COUNTER: {
>                 for (unsigned i = 0; i < max_rbs; ++i) {
>                         unsigned results_base = i * 16;
>                         result->u64 +=
>                                 r600_query_read_result(buffer + results_base, 0, 2, true);
>                 }
>                 break;
>         }
> -       case PIPE_QUERY_OCCLUSION_PREDICATE: {
> +       case PIPE_QUERY_OCCLUSION_PREDICATE:
> +       case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE: {
>                 for (unsigned i = 0; i < max_rbs; ++i) {
>                         unsigned results_base = i * 16;
>                         result->b = result->b ||
>                                 r600_query_read_result(buffer + results_base, 0, 2, true) != 0;
>                 }
>                 break;
>         }
>         case PIPE_QUERY_TIME_ELAPSED:
>                 result->u64 += r600_query_read_result(buffer, 0, 2, false);
>                 break;
> @@ -1704,21 +1712,22 @@ static void r600_query_hw_get_result_resource(struct r600_common_context *rctx,
>         grid.block[0] = 1;
>         grid.block[1] = 1;
>         grid.block[2] = 1;
>         grid.grid[0] = 1;
>         grid.grid[1] = 1;
>         grid.grid[2] = 1;
>
>         consts.config = 0;
>         if (index < 0)
>                 consts.config |= 4;
> -       if (query->b.type == PIPE_QUERY_OCCLUSION_PREDICATE)
> +       if (query->b.type == PIPE_QUERY_OCCLUSION_PREDICATE ||
> +           query->b.type == PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE)
>                 consts.config |= 8;
>         else if (query->b.type == PIPE_QUERY_SO_OVERFLOW_PREDICATE ||
>                  query->b.type == PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE)
>                 consts.config |= 8 | 256;
>         else if (query->b.type == PIPE_QUERY_TIMESTAMP ||
>                  query->b.type == PIPE_QUERY_TIME_ELAPSED)
>                 consts.config |= 32;
>
>         switch (result_type) {
>         case PIPE_QUERY_TYPE_U64:
> diff --git a/src/gallium/drivers/softpipe/sp_query.c b/src/gallium/drivers/softpipe/sp_query.c
> index 63f6c4be042..267c99977fe 100644
> --- a/src/gallium/drivers/softpipe/sp_query.c
> +++ b/src/gallium/drivers/softpipe/sp_query.c
> @@ -53,20 +53,21 @@ static struct softpipe_query *softpipe_query( struct pipe_query *p )
>
>  static struct pipe_query *
>  softpipe_create_query(struct pipe_context *pipe,
>                       unsigned type,
>                       unsigned index)
>  {
>     struct softpipe_query* sq;
>
>     assert(type == PIPE_QUERY_OCCLUSION_COUNTER ||
>            type == PIPE_QUERY_OCCLUSION_PREDICATE ||
> +          type == PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE ||
>            type == PIPE_QUERY_TIME_ELAPSED ||
>            type == PIPE_QUERY_SO_STATISTICS ||
>            type == PIPE_QUERY_SO_OVERFLOW_PREDICATE ||
>            type == PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE ||
>            type == PIPE_QUERY_PRIMITIVES_EMITTED ||
>            type == PIPE_QUERY_PRIMITIVES_GENERATED ||
>            type == PIPE_QUERY_PIPELINE_STATISTICS ||
>            type == PIPE_QUERY_GPU_FINISHED ||
>            type == PIPE_QUERY_TIMESTAMP ||
>            type == PIPE_QUERY_TIMESTAMP_DISJOINT);
> @@ -86,20 +87,21 @@ softpipe_destroy_query(struct pipe_context *pipe, struct pipe_query *q)
>
>  static boolean
>  softpipe_begin_query(struct pipe_context *pipe, struct pipe_query *q)
>  {
>     struct softpipe_context *softpipe = softpipe_context( pipe );
>     struct softpipe_query *sq = softpipe_query(q);
>
>     switch (sq->type) {
>     case PIPE_QUERY_OCCLUSION_COUNTER:
>     case PIPE_QUERY_OCCLUSION_PREDICATE:
> +   case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
>        sq->start = softpipe->occlusion_count;
>        break;
>     case PIPE_QUERY_TIME_ELAPSED:
>        sq->start = os_time_get_nano();
>        break;
>     case PIPE_QUERY_SO_STATISTICS:
>        sq->so.num_primitives_written = softpipe->so_stats.num_primitives_written;
>        sq->so.primitives_storage_needed = softpipe->so_stats.primitives_storage_needed;
>        break;
>     case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
> @@ -140,20 +142,21 @@ softpipe_begin_query(struct pipe_context *pipe, struct pipe_query *q)
>  static bool
>  softpipe_end_query(struct pipe_context *pipe, struct pipe_query *q)
>  {
>     struct softpipe_context *softpipe = softpipe_context( pipe );
>     struct softpipe_query *sq = softpipe_query(q);
>
>     softpipe->active_query_count--;
>     switch (sq->type) {
>     case PIPE_QUERY_OCCLUSION_COUNTER:
>     case PIPE_QUERY_OCCLUSION_PREDICATE:
> +   case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
>        sq->end = softpipe->occlusion_count;
>        break;
>     case PIPE_QUERY_TIMESTAMP:
>        sq->start = 0;
>        /* fall through */
>     case PIPE_QUERY_TIME_ELAPSED:
>        sq->end = os_time_get_nano();
>        break;
>     case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
>     case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE:
> @@ -245,20 +248,21 @@ softpipe_get_query_result(struct pipe_context *pipe,
>        td->disjoint = FALSE;
>     }
>        break;
>     case PIPE_QUERY_PRIMITIVES_EMITTED:
>        *result = sq->so.num_primitives_written;
>        break;
>     case PIPE_QUERY_PRIMITIVES_GENERATED:
>        *result = sq->so.primitives_storage_needed;
>        break;
>     case PIPE_QUERY_OCCLUSION_PREDICATE:
> +   case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
>        vresult->b = sq->end - sq->start != 0;
>        break;
>     default:
>        *result = sq->end - sq->start;
>        break;
>     }
>     return TRUE;
>  }
>
>
> diff --git a/src/gallium/drivers/svga/svga_pipe_query.c b/src/gallium/drivers/svga/svga_pipe_query.c
> index 0490a4ab5fc..26924524372 100644
> --- a/src/gallium/drivers/svga/svga_pipe_query.c
> +++ b/src/gallium/drivers/svga/svga_pipe_query.c
> @@ -700,20 +700,21 @@ svga_create_query(struct pipe_context *pipe,
>            * query of occlusion predicate type will be used
>            * in the SetPredication command.
>            */
>           sq->predicate = svga_create_query(pipe, PIPE_QUERY_OCCLUSION_PREDICATE, index);
>
>        } else {
>           define_query_vgpu9(svga, sq);
>        }
>        break;
>     case PIPE_QUERY_OCCLUSION_PREDICATE:
> +   case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
>        if (svga_have_vgpu10(svga)) {
>           sq->svga_type = SVGA3D_QUERYTYPE_OCCLUSIONPREDICATE;
>           define_query_vgpu10(svga, sq, sizeof(SVGADXOcclusionPredicateQueryResult));
>        } else {
>           sq->svga_type = SVGA3D_QUERYTYPE_OCCLUSION;
>           define_query_vgpu9(svga, sq);
>        }
>        break;
>     case PIPE_QUERY_PRIMITIVES_GENERATED:
>     case PIPE_QUERY_PRIMITIVES_EMITTED:
> @@ -782,20 +783,21 @@ svga_destroy_query(struct pipe_context *pipe, struct pipe_query *q)
>     }
>
>     sq = svga_query(q);
>
>     SVGA_DBG(DEBUG_QUERY, "%s sq=0x%x id=%d\n", __FUNCTION__,
>              sq, sq->id);
>
>     switch (sq->type) {
>     case PIPE_QUERY_OCCLUSION_COUNTER:
>     case PIPE_QUERY_OCCLUSION_PREDICATE:
> +   case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
>        if (svga_have_vgpu10(svga)) {
>           /* make sure to also destroy any associated predicate query */
>           if (sq->predicate)
>              svga_destroy_query(pipe, sq->predicate);
>           destroy_query_vgpu10(svga, sq);
>        } else {
>           sws->buffer_destroy(sws, sq->hwbuf);
>        }
>        sws->fence_reference(sws, &sq->fence, NULL);
>        break;
> @@ -857,20 +859,21 @@ svga_begin_query(struct pipe_context *pipe, struct pipe_query *q)
>              sq, sq->id);
>
>     /* Need to flush out buffered drawing commands so that they don't
>      * get counted in the query results.
>      */
>     svga_hwtnl_flush_retry(svga);
>
>     switch (sq->type) {
>     case PIPE_QUERY_OCCLUSION_COUNTER:
>     case PIPE_QUERY_OCCLUSION_PREDICATE:
> +   case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
>        if (svga_have_vgpu10(svga)) {
>           ret = begin_query_vgpu10(svga, sq);
>           /* also need to start the associated occlusion predicate query */
>           if (sq->predicate) {
>              enum pipe_error status;
>              status = begin_query_vgpu10(svga, svga_query(sq->predicate));
>              assert(status == PIPE_OK);
>              (void) status;
>           }
>        } else {
> @@ -970,20 +973,21 @@ svga_end_query(struct pipe_context *pipe, struct pipe_query *q)
>     if (sq->type == PIPE_QUERY_TIMESTAMP && svga->sq[sq->type] != sq)
>        svga_begin_query(pipe, q);
>
>     svga_hwtnl_flush_retry(svga);
>
>     assert(svga->sq[sq->type] == sq);
>
>     switch (sq->type) {
>     case PIPE_QUERY_OCCLUSION_COUNTER:
>     case PIPE_QUERY_OCCLUSION_PREDICATE:
> +   case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
>        if (svga_have_vgpu10(svga)) {
>           ret = end_query_vgpu10(svga, sq);
>           /* also need to end the associated occlusion predicate query */
>           if (sq->predicate) {
>              enum pipe_error status;
>              status = end_query_vgpu10(svga, svga_query(sq->predicate));
>              assert(status == PIPE_OK);
>              (void) status;
>           }
>        } else {
> @@ -1086,21 +1090,22 @@ svga_get_query_result(struct pipe_context *pipe,
>     case PIPE_QUERY_OCCLUSION_COUNTER:
>        if (svga_have_vgpu10(svga)) {
>           SVGADXOcclusionQueryResult occResult;
>           ret = get_query_result_vgpu10(svga, sq, wait,
>                                         (void *)&occResult, sizeof(occResult));
>           *result = (uint64_t)occResult.samplesRendered;
>        } else {
>           ret = get_query_result_vgpu9(svga, sq, wait, result);
>        }
>        break;
> -   case PIPE_QUERY_OCCLUSION_PREDICATE: {
> +   case PIPE_QUERY_OCCLUSION_PREDICATE:
> +   case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE: {
>        if (svga_have_vgpu10(svga)) {
>           SVGADXOcclusionPredicateQueryResult occResult;
>           ret = get_query_result_vgpu10(svga, sq, wait,
>                                         (void *)&occResult, sizeof(occResult));
>           vresult->b = occResult.anySamplesRendered != 0;
>        } else {
>           uint64_t count = 0;
>           ret = get_query_result_vgpu9(svga, sq, wait, &count);
>           vresult->b = count != 0;
>        }
> diff --git a/src/gallium/drivers/swr/swr_query.cpp b/src/gallium/drivers/swr/swr_query.cpp
> index 4c14c5206b0..e3697304e05 100644
> --- a/src/gallium/drivers/swr/swr_query.cpp
> +++ b/src/gallium/drivers/swr/swr_query.cpp
> @@ -87,20 +87,21 @@ swr_get_query_result(struct pipe_context *pipe,
>
>        swr_fence_finish(pipe->screen, NULL, pq->fence, 0);
>        swr_fence_reference(pipe->screen, &pq->fence, NULL);
>     }
>
>     /* All values are reset to 0 at swr_begin_query, except starting timestamp.
>      * Counters become simply end values.  */
>     switch (pq->type) {
>     /* Booleans */
>     case PIPE_QUERY_OCCLUSION_PREDICATE:
> +   case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
>        result->b = pq->result.core.DepthPassCount != 0;
>        break;
>     case PIPE_QUERY_GPU_FINISHED:
>        result->b = TRUE;
>        break;
>     /* Counters */
>     case PIPE_QUERY_OCCLUSION_COUNTER:
>        result->u64 = pq->result.core.DepthPassCount;
>        break;
>     case PIPE_QUERY_TIMESTAMP:
> diff --git a/src/gallium/drivers/trace/tr_dump_state.c b/src/gallium/drivers/trace/tr_dump_state.c
> index 0650f63d266..e7e32237c4c 100644
> --- a/src/gallium/drivers/trace/tr_dump_state.c
> +++ b/src/gallium/drivers/trace/tr_dump_state.c
> @@ -871,20 +871,21 @@ trace_dump_query_result(unsigned query_type,
>     if (!trace_dumping_enabled_locked())
>        return;
>
>     if (!result) {
>        trace_dump_null();
>        return;
>     }
>
>     switch (query_type) {
>     case PIPE_QUERY_OCCLUSION_PREDICATE:
> +   case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
>     case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
>     case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE:
>     case PIPE_QUERY_GPU_FINISHED:
>        trace_dump_bool(result->b);
>        break;
>
>     case PIPE_QUERY_OCCLUSION_COUNTER:
>     case PIPE_QUERY_TIMESTAMP:
>     case PIPE_QUERY_TIME_ELAPSED:
>     case PIPE_QUERY_PRIMITIVES_GENERATED:
> diff --git a/src/gallium/include/pipe/p_defines.h b/src/gallium/include/pipe/p_defines.h
> index da7d5da7347..9b428a6ad76 100644
> --- a/src/gallium/include/pipe/p_defines.h
> +++ b/src/gallium/include/pipe/p_defines.h
> @@ -523,20 +523,21 @@ enum pipe_tess_spacing {
>     PIPE_TESS_SPACING_FRACTIONAL_EVEN,
>     PIPE_TESS_SPACING_EQUAL,
>  };
>
>  /**
>   * Query object types
>   */
>  enum pipe_query_type {
>     PIPE_QUERY_OCCLUSION_COUNTER,
>     PIPE_QUERY_OCCLUSION_PREDICATE,
> +   PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE,
>     PIPE_QUERY_TIMESTAMP,
>     PIPE_QUERY_TIMESTAMP_DISJOINT,
>     PIPE_QUERY_TIME_ELAPSED,
>     PIPE_QUERY_PRIMITIVES_GENERATED,
>     PIPE_QUERY_PRIMITIVES_EMITTED,
>     PIPE_QUERY_SO_STATISTICS,
>     PIPE_QUERY_SO_OVERFLOW_PREDICATE,
>     PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE,
>     PIPE_QUERY_GPU_FINISHED,
>     PIPE_QUERY_PIPELINE_STATISTICS,
> @@ -938,20 +939,21 @@ union pipe_numeric_type_union
>     uint32_t u32;
>     float f;
>  };
>
>  /**
>   * Query result (returned by pipe_context::get_query_result).
>   */
>  union pipe_query_result
>  {
>     /* PIPE_QUERY_OCCLUSION_PREDICATE */
> +   /* PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE */
>     /* PIPE_QUERY_SO_OVERFLOW_PREDICATE */
>     /* PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE */
>     /* PIPE_QUERY_GPU_FINISHED */
>     boolean b;
>
>     /* PIPE_QUERY_OCCLUSION_COUNTER */
>     /* PIPE_QUERY_TIMESTAMP */
>     /* PIPE_QUERY_TIME_ELAPSED */
>     /* PIPE_QUERY_PRIMITIVES_GENERATED */
>     /* PIPE_QUERY_PRIMITIVES_EMITTED */
> diff --git a/src/mesa/state_tracker/st_cb_queryobj.c b/src/mesa/state_tracker/st_cb_queryobj.c
> index 4c25724b5dc..a470ff6b8b5 100644
> --- a/src/mesa/state_tracker/st_cb_queryobj.c
> +++ b/src/mesa/state_tracker/st_cb_queryobj.c
> @@ -95,23 +95,25 @@ st_BeginQuery(struct gl_context *ctx, struct gl_query_object *q)
>     struct pipe_context *pipe = st->pipe;
>     struct st_query_object *stq = st_query_object(q);
>     unsigned type;
>     bool ret = false;
>
>     st_flush_bitmap_cache(st_context(ctx));
>
>     /* convert GL query type to Gallium query type */
>     switch (q->Target) {
>     case GL_ANY_SAMPLES_PASSED:
> -   case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
>        type = PIPE_QUERY_OCCLUSION_PREDICATE;
>        break;
> +   case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
> +      type = PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE;
> +      break;
>     case GL_SAMPLES_PASSED_ARB:
>        type = PIPE_QUERY_OCCLUSION_COUNTER;
>        break;
>     case GL_PRIMITIVES_GENERATED:
>        type = PIPE_QUERY_PRIMITIVES_GENERATED;
>        break;
>     case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
>        type = PIPE_QUERY_PRIMITIVES_EMITTED;
>        break;
>     case GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB:
> @@ -253,20 +255,21 @@ get_query_result(struct pipe_context *pipe,
>        break;
>     case GL_CLIPPING_INPUT_PRIMITIVES_ARB:
>        stq->base.Result = data.pipeline_statistics.c_invocations;
>        break;
>     case GL_CLIPPING_OUTPUT_PRIMITIVES_ARB:
>        stq->base.Result = data.pipeline_statistics.c_primitives;
>        break;
>     default:
>        switch (stq->type) {
>        case PIPE_QUERY_OCCLUSION_PREDICATE:
> +      case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
>        case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
>        case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE:
>           stq->base.Result = !!data.b;
>           break;
>        default:
>           stq->base.Result = data.u64;
>           break;
>        }
>        break;
>     }
> --
> 2.11.0
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev


More information about the mesa-dev mailing list