From: Rob Clark Date: Thu, 2 Jul 2015 22:07:27 +0000 (-0400) Subject: freedreno/a4xx: occlusion query support X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=15d3524ad24a698095cc542cf9a527c8a8615f78;p=mesa.git freedreno/a4xx: occlusion query support Signed-off-by: Rob Clark --- diff --git a/src/gallium/drivers/freedreno/a4xx/fd4_query.c b/src/gallium/drivers/freedreno/a4xx/fd4_query.c index 6db1c11b94b..4f69e0c1694 100644 --- a/src/gallium/drivers/freedreno/a4xx/fd4_query.c +++ b/src/gallium/drivers/freedreno/a4xx/fd4_query.c @@ -31,9 +31,93 @@ #include "freedreno_util.h" #include "fd4_query.h" +#include "fd4_draw.h" #include "fd4_format.h" + +struct fd_rb_samp_ctrs { + uint64_t ctr[16]; +}; + +/* + * Occlusion Query: + * + * OCCLUSION_COUNTER and OCCLUSION_PREDICATE differ only in how they + * interpret results + */ + +static struct fd_hw_sample * +occlusion_get_sample(struct fd_context *ctx, struct fd_ringbuffer *ring) +{ + struct fd_hw_sample *samp = + fd_hw_sample_init(ctx, sizeof(struct fd_rb_samp_ctrs)); + + /* low bits of sample addr should be zero (since they are control + * flags in RB_SAMPLE_COUNT_CONTROL): + */ + debug_assert((samp->offset & 0x3) == 0); + + /* Set RB_SAMPLE_COUNT_ADDR to samp->offset plus value of + * HW_QUERY_BASE_REG register: + */ + OUT_PKT3(ring, CP_SET_CONSTANT, 3); + OUT_RING(ring, CP_REG(REG_A4XX_RB_SAMPLE_COUNT_CONTROL) | 0x80000000); + OUT_RING(ring, HW_QUERY_BASE_REG); + OUT_RING(ring, A4XX_RB_SAMPLE_COUNT_CONTROL_COPY | + samp->offset); + + OUT_PKT3(ring, CP_DRAW_INDX_OFFSET, 3); + OUT_RING(ring, DRAW4(DI_PT_POINTLIST_PSIZE, DI_SRC_SEL_AUTO_INDEX, + INDEX4_SIZE_32_BIT, USE_VISIBILITY)); + OUT_RING(ring, 1); /* NumInstances */ + OUT_RING(ring, 0); /* NumIndices */ + + fd_event_write(ctx, ring, ZPASS_DONE); + + return samp; +} + +static uint64_t +count_samples(const struct fd_rb_samp_ctrs *start, + const struct fd_rb_samp_ctrs *end) +{ + return end->ctr[0] - start->ctr[0]; +} + +static void +occlusion_counter_accumulate_result(struct fd_context *ctx, + const void *start, const void *end, + union pipe_query_result *result) +{ + uint64_t n = count_samples(start, end); + result->u64 += n; +} + +static void +occlusion_predicate_accumulate_result(struct fd_context *ctx, + const void *start, const void *end, + union pipe_query_result *result) +{ + uint64_t n = count_samples(start, end); + result->b |= (n > 0); +} + +static const struct fd_hw_sample_provider occlusion_counter = { + .query_type = PIPE_QUERY_OCCLUSION_COUNTER, + .active = FD_STAGE_DRAW, + .get_sample = occlusion_get_sample, + .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, +}; + void fd4_query_context_init(struct pipe_context *pctx) { - /* TODO */ + fd_hw_query_register_provider(pctx, &occlusion_counter); + fd_hw_query_register_provider(pctx, &occlusion_predicate); }