2 * Copyright (c) 2017 Etnaviv Project
3 * Copyright (C) 2017 Zodiac Inflight Innovations
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:
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
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.
25 * Rob Clark <robclark@freedesktop.org>
26 * Christian Gmeiner <christian.gmeiner@gmail.com>
29 #include "util/u_inlines.h"
30 #include "util/u_memory.h"
32 #include "etnaviv_context.h"
33 #include "etnaviv_debug.h"
34 #include "etnaviv_emit.h"
35 #include "etnaviv_query_acc.h"
36 #include "etnaviv_screen.h"
39 extern const struct etna_acc_sample_provider occlusion_provider
;
40 extern const struct etna_acc_sample_provider perfmon_provider
;
42 static const struct etna_acc_sample_provider
*acc_sample_provider
[] =
49 etna_acc_destroy_query(struct etna_context
*ctx
, struct etna_query
*q
)
51 struct etna_acc_query
*aq
= etna_acc_query(q
);
53 pipe_resource_reference(&aq
->prsc
, NULL
);
60 realloc_query_bo(struct etna_context
*ctx
, struct etna_acc_query
*aq
)
62 struct etna_resource
*rsc
;
65 pipe_resource_reference(&aq
->prsc
, NULL
);
67 /* allocate resource with space for 64 * 64bit values */
68 aq
->prsc
= pipe_buffer_create(&ctx
->screen
->base
, PIPE_BIND_QUERY_BUFFER
,
71 /* don't assume the buffer is zero-initialized */
72 rsc
= etna_resource(aq
->prsc
);
74 etna_bo_cpu_prep(rsc
->bo
, DRM_ETNA_PREP_WRITE
);
76 map
= etna_bo_map(rsc
->bo
);
77 memset(map
, 0, 0x1000);
78 etna_bo_cpu_fini(rsc
->bo
);
82 etna_acc_begin_query(struct etna_context
*ctx
, struct etna_query
*q
)
84 struct etna_acc_query
*aq
= etna_acc_query(q
);
85 const struct etna_acc_sample_provider
*p
= aq
->provider
;
87 /* ->begin_query() discards previous results, so realloc bo */
88 realloc_query_bo(ctx
, aq
);
93 /* add to active list */
94 assert(list_is_empty(&aq
->node
));
95 list_addtail(&aq
->node
, &ctx
->active_acc_queries
);
101 etna_acc_end_query(struct etna_context
*ctx
, struct etna_query
*q
)
103 struct etna_acc_query
*aq
= etna_acc_query(q
);
104 const struct etna_acc_sample_provider
*p
= aq
->provider
;
109 /* remove from active list */
110 list_delinit(&aq
->node
);
114 etna_acc_get_query_result(struct etna_context
*ctx
, struct etna_query
*q
,
115 bool wait
, union pipe_query_result
*result
)
117 struct etna_acc_query
*aq
= etna_acc_query(q
);
118 struct etna_resource
*rsc
= etna_resource(aq
->prsc
);
119 const struct etna_acc_sample_provider
*p
= aq
->provider
;
121 assert(list_is_empty(&aq
->node
));
123 if (rsc
->status
& ETNA_PENDING_WRITE
) {
125 /* piglit spec@arb_occlusion_query@occlusion_query_conform
126 * test, and silly apps perhaps, get stuck in a loop trying
127 * to get query result forever with wait==false.. we don't
128 * wait to flush unnecessarily but we also don't want to
131 if (aq
->no_wait_cnt
++ > 5) {
132 ctx
->base
.flush(&ctx
->base
, NULL
, 0);
138 /* flush that GPU executes all query related actions */
139 ctx
->base
.flush(&ctx
->base
, NULL
, 0);
144 int ret
= etna_bo_cpu_prep(rsc
->bo
, DRM_ETNA_PREP_READ
);
148 void *ptr
= etna_bo_map(rsc
->bo
);
149 bool success
= p
->result(aq
, ptr
, result
);
154 etna_bo_cpu_fini(rsc
->bo
);
159 static const struct etna_query_funcs acc_query_funcs
= {
160 .destroy_query
= etna_acc_destroy_query
,
161 .begin_query
= etna_acc_begin_query
,
162 .end_query
= etna_acc_end_query
,
163 .get_query_result
= etna_acc_get_query_result
,
167 etna_acc_create_query(struct etna_context
*ctx
, unsigned query_type
)
169 const struct etna_acc_sample_provider
*p
= NULL
;
170 struct etna_acc_query
*aq
;
171 struct etna_query
*q
;
173 /* find a sample provide for the requested query type */
174 for (unsigned i
= 0; i
< ARRAY_SIZE(acc_sample_provider
); i
++) {
175 p
= acc_sample_provider
[i
];
177 if (p
->supports(query_type
))
186 aq
= p
->allocate(ctx
, query_type
);
192 list_inithead(&aq
->node
);
195 q
->funcs
= &acc_query_funcs
;
196 q
->type
= query_type
;