From: Nicolai Hähnle <nicolai.haeh...@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, ×tamp); } 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, ×tamp); } 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@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev