Home | History | Annotate | Download | only in a3xx
      1 /* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
      2 
      3 /*
      4  * Copyright (C) 2014 Rob Clark <robclark (at) freedesktop.org>
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the "Software"),
      8  * to deal in the Software without restriction, including without limitation
      9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     10  * and/or sell copies of the Software, and to permit persons to whom the
     11  * Software is furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice (including the next
     14  * paragraph) shall be included in all copies or substantial portions of the
     15  * Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     23  * SOFTWARE.
     24  *
     25  * Authors:
     26  *    Rob Clark <robclark (at) freedesktop.org>
     27  */
     28 
     29 #include "freedreno_query_hw.h"
     30 #include "freedreno_context.h"
     31 #include "freedreno_util.h"
     32 
     33 #include "fd3_query.h"
     34 #include "fd3_format.h"
     35 
     36 
     37 struct fd_rb_samp_ctrs {
     38 	uint64_t ctr[16];
     39 };
     40 
     41 /*
     42  * Occlusion Query:
     43  *
     44  * OCCLUSION_COUNTER and OCCLUSION_PREDICATE differ only in how they
     45  * interpret results
     46  */
     47 
     48 static struct fd_hw_sample *
     49 occlusion_get_sample(struct fd_batch *batch, struct fd_ringbuffer *ring)
     50 {
     51 	struct fd_hw_sample *samp =
     52 			fd_hw_sample_init(batch, sizeof(struct fd_rb_samp_ctrs));
     53 
     54 	/* Set RB_SAMPLE_COUNT_ADDR to samp->offset plus value of
     55 	 * HW_QUERY_BASE_REG register:
     56 	 */
     57 	OUT_PKT3(ring, CP_SET_CONSTANT, 3);
     58 	OUT_RING(ring, CP_REG(REG_A3XX_RB_SAMPLE_COUNT_ADDR) | 0x80000000);
     59 	OUT_RING(ring, HW_QUERY_BASE_REG);
     60 	OUT_RING(ring, samp->offset);
     61 
     62 	OUT_PKT0(ring, REG_A3XX_RB_SAMPLE_COUNT_CONTROL, 1);
     63 	OUT_RING(ring, A3XX_RB_SAMPLE_COUNT_CONTROL_COPY);
     64 
     65 	OUT_PKT3(ring, CP_DRAW_INDX, 3);
     66 	OUT_RING(ring, 0x00000000);
     67 	OUT_RING(ring, DRAW(DI_PT_POINTLIST_PSIZE, DI_SRC_SEL_AUTO_INDEX,
     68 						INDEX_SIZE_IGN, USE_VISIBILITY, 0));
     69 	OUT_RING(ring, 0);             /* NumIndices */
     70 
     71 	fd_event_write(batch, ring, ZPASS_DONE);
     72 
     73 	OUT_PKT0(ring, REG_A3XX_RBBM_PERFCTR_CTL, 1);
     74 	OUT_RING(ring, A3XX_RBBM_PERFCTR_CTL_ENABLE);
     75 
     76 	OUT_PKT0(ring, REG_A3XX_VBIF_PERF_CNT_EN, 1);
     77 	OUT_RING(ring, A3XX_VBIF_PERF_CNT_EN_CNT0 |
     78 			A3XX_VBIF_PERF_CNT_EN_CNT1 |
     79 			A3XX_VBIF_PERF_CNT_EN_PWRCNT0 |
     80 			A3XX_VBIF_PERF_CNT_EN_PWRCNT1 |
     81 			A3XX_VBIF_PERF_CNT_EN_PWRCNT2);
     82 
     83 	return samp;
     84 }
     85 
     86 static uint64_t
     87 count_samples(const struct fd_rb_samp_ctrs *start,
     88 		const struct fd_rb_samp_ctrs *end)
     89 {
     90 	uint64_t n = 0;
     91 	unsigned i;
     92 
     93 	/* not quite sure what all of these are, possibly different
     94 	 * counters for each MRT render target:
     95 	 */
     96 	for (i = 0; i < 16; i += 4)
     97 		n += end->ctr[i] - start->ctr[i];
     98 
     99 	return n;
    100 }
    101 
    102 static void
    103 occlusion_counter_accumulate_result(struct fd_context *ctx,
    104 		const void *start, const void *end,
    105 		union pipe_query_result *result)
    106 {
    107 	uint64_t n = count_samples(start, end);
    108 	result->u64 += n;
    109 }
    110 
    111 static void
    112 occlusion_predicate_accumulate_result(struct fd_context *ctx,
    113 		const void *start, const void *end,
    114 		union pipe_query_result *result)
    115 {
    116 	uint64_t n = count_samples(start, end);
    117 	result->b |= (n > 0);
    118 }
    119 
    120 static const struct fd_hw_sample_provider occlusion_counter = {
    121 		.query_type = PIPE_QUERY_OCCLUSION_COUNTER,
    122 		.active = FD_STAGE_DRAW,
    123 		.get_sample = occlusion_get_sample,
    124 		.accumulate_result = occlusion_counter_accumulate_result,
    125 };
    126 
    127 static const struct fd_hw_sample_provider occlusion_predicate = {
    128 		.query_type = PIPE_QUERY_OCCLUSION_PREDICATE,
    129 		.active = FD_STAGE_DRAW,
    130 		.get_sample = occlusion_get_sample,
    131 		.accumulate_result = occlusion_predicate_accumulate_result,
    132 };
    133 
    134 void fd3_query_context_init(struct pipe_context *pctx)
    135 {
    136 	fd_hw_query_register_provider(pctx, &occlusion_counter);
    137 	fd_hw_query_register_provider(pctx, &occlusion_predicate);
    138 }
    139