1 /*
2 * Copyright (c) 2017 Etnaviv Project
3 * Copyright (C) 2017 Zodiac Inflight Innovations
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sub license,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
14 * of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
25 * Rob Clark <[email protected]>
26 * Christian Gmeiner <[email protected]>
27 */
28
29 #include "util/compiler.h"
30 #include "util/u_inlines.h"
31 #include "util/u_memory.h"
32
33 #include "etnaviv_context.h"
34 #include "etnaviv_debug.h"
35 #include "etnaviv_emit.h"
36 #include "etnaviv_query_acc.h"
37 #include "etnaviv_screen.h"
38
39 #define MAX_OQ_SAMPLES 511 /* 4KB / 8Bytes/sample */
40
41 /*
42 * Occlusion Query:
43 *
44 * OCCLUSION_COUNTER and OCCLUSION_PREDICATE differ only in how they
45 * interpret results
46 */
47
48 static bool
occlusion_supports(unsigned query_type)49 occlusion_supports(unsigned query_type)
50 {
51 switch (query_type) {
52 case PIPE_QUERY_OCCLUSION_COUNTER:
53 FALLTHROUGH;
54 case PIPE_QUERY_OCCLUSION_PREDICATE:
55 FALLTHROUGH;
56 case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
57 return true;
58 default:
59 return false;
60 }
61 }
62
63 static struct etna_acc_query *
occlusion_allocate(struct etna_context * ctx,ASSERTED unsigned query_type)64 occlusion_allocate(struct etna_context *ctx, ASSERTED unsigned query_type)
65 {
66 return CALLOC_STRUCT(etna_acc_query);
67 }
68
69 static void
occlusion_resume(struct etna_acc_query * aq,struct etna_context * ctx)70 occlusion_resume(struct etna_acc_query *aq, struct etna_context *ctx)
71 {
72 struct etna_resource *rsc = etna_resource(aq->prsc);
73 struct etna_reloc r = {
74 .bo = rsc->bo,
75 .flags = ETNA_RELOC_WRITE
76 };
77
78 if (aq->samples > MAX_OQ_SAMPLES) {
79 aq->samples = MAX_OQ_SAMPLES;
80 BUG("samples overflow");
81 }
82
83 r.offset = aq->samples * 8; /* 64bit value */
84
85 etna_set_state_reloc(ctx->stream, VIVS_GL_OCCLUSION_QUERY_ADDR, &r);
86 resource_written(ctx, aq->prsc);
87 }
88
89 static void
occlusion_suspend(struct etna_acc_query * aq,struct etna_context * ctx)90 occlusion_suspend(struct etna_acc_query *aq, struct etna_context *ctx)
91 {
92 /* 0x1DF5E76 is the value used by blob - but any random value will work */
93 etna_set_state(ctx->stream, VIVS_GL_OCCLUSION_QUERY_CONTROL, 0x1DF5E76);
94 resource_written(ctx, aq->prsc);
95 aq->samples++;
96 }
97
98 static bool
occlusion_result(struct etna_acc_query * aq,void * buf,union pipe_query_result * result)99 occlusion_result(struct etna_acc_query *aq, void *buf,
100 union pipe_query_result *result)
101 {
102 uint64_t sum = 0;
103 uint64_t *ptr = (uint64_t *)buf;
104
105 for (unsigned i = 0; i < aq->samples; i++)
106 sum += *(ptr + i);
107
108 if (aq->base.type == PIPE_QUERY_OCCLUSION_COUNTER)
109 result->u64 = sum;
110 else
111 result->b = !!sum;
112
113 return true;
114 }
115
116 const struct etna_acc_sample_provider occlusion_provider = {
117 .supports = occlusion_supports,
118 .allocate = occlusion_allocate,
119 .suspend = occlusion_suspend,
120 .resume = occlusion_resume,
121 .result = occlusion_result,
122 };
123