Merge remote-tracking branch 'mesa-public/master' into vulkan
[mesa.git] / src / gallium / drivers / freedreno / a4xx / fd4_query.c
1 /* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
2
3 /*
4 * Copyright (C) 2014 Rob Clark <robclark@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@freedesktop.org>
27 */
28
29 #include "freedreno_query_hw.h"
30 #include "freedreno_context.h"
31 #include "freedreno_util.h"
32
33 #include "fd4_query.h"
34 #include "fd4_draw.h"
35 #include "fd4_format.h"
36
37
38 struct fd_rb_samp_ctrs {
39 uint64_t ctr[16];
40 };
41
42 /*
43 * Occlusion Query:
44 *
45 * OCCLUSION_COUNTER and OCCLUSION_PREDICATE differ only in how they
46 * interpret results
47 */
48
49 static struct fd_hw_sample *
50 occlusion_get_sample(struct fd_context *ctx, struct fd_ringbuffer *ring)
51 {
52 struct fd_hw_sample *samp =
53 fd_hw_sample_init(ctx, sizeof(struct fd_rb_samp_ctrs));
54
55 /* low bits of sample addr should be zero (since they are control
56 * flags in RB_SAMPLE_COUNT_CONTROL):
57 */
58 debug_assert((samp->offset & 0x3) == 0);
59
60 /* Set RB_SAMPLE_COUNT_ADDR to samp->offset plus value of
61 * HW_QUERY_BASE_REG register:
62 */
63 OUT_PKT3(ring, CP_SET_CONSTANT, 3);
64 OUT_RING(ring, CP_REG(REG_A4XX_RB_SAMPLE_COUNT_CONTROL) | 0x80000000);
65 OUT_RING(ring, HW_QUERY_BASE_REG);
66 OUT_RING(ring, A4XX_RB_SAMPLE_COUNT_CONTROL_COPY |
67 samp->offset);
68
69 OUT_PKT3(ring, CP_DRAW_INDX_OFFSET, 3);
70 OUT_RING(ring, DRAW4(DI_PT_POINTLIST_PSIZE, DI_SRC_SEL_AUTO_INDEX,
71 INDEX4_SIZE_32_BIT, USE_VISIBILITY));
72 OUT_RING(ring, 1); /* NumInstances */
73 OUT_RING(ring, 0); /* NumIndices */
74
75 fd_event_write(ctx, ring, ZPASS_DONE);
76
77 return samp;
78 }
79
80 static uint64_t
81 count_samples(const struct fd_rb_samp_ctrs *start,
82 const struct fd_rb_samp_ctrs *end)
83 {
84 return end->ctr[0] - start->ctr[0];
85 }
86
87 static void
88 occlusion_counter_accumulate_result(struct fd_context *ctx,
89 const void *start, const void *end,
90 union pipe_query_result *result)
91 {
92 uint64_t n = count_samples(start, end);
93 result->u64 += n;
94 }
95
96 static void
97 occlusion_predicate_accumulate_result(struct fd_context *ctx,
98 const void *start, const void *end,
99 union pipe_query_result *result)
100 {
101 uint64_t n = count_samples(start, end);
102 result->b |= (n > 0);
103 }
104
105 static const struct fd_hw_sample_provider occlusion_counter = {
106 .query_type = PIPE_QUERY_OCCLUSION_COUNTER,
107 .active = FD_STAGE_DRAW,
108 .get_sample = occlusion_get_sample,
109 .accumulate_result = occlusion_counter_accumulate_result,
110 };
111
112 static const struct fd_hw_sample_provider occlusion_predicate = {
113 .query_type = PIPE_QUERY_OCCLUSION_PREDICATE,
114 .active = FD_STAGE_DRAW,
115 .get_sample = occlusion_get_sample,
116 .accumulate_result = occlusion_predicate_accumulate_result,
117 };
118
119 void fd4_query_context_init(struct pipe_context *pctx)
120 {
121 fd_hw_query_register_provider(pctx, &occlusion_counter);
122 fd_hw_query_register_provider(pctx, &occlusion_predicate);
123 }