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_query_hw.h"
34 #include "etnaviv_screen.h"
37 etna_hw_destroy_query(struct etna_context
*ctx
, struct etna_query
*q
)
39 struct etna_hw_query
*hq
= etna_hw_query(q
);
41 pipe_resource_reference(&hq
->prsc
, NULL
);
48 realloc_query_bo(struct etna_context
*ctx
, struct etna_hw_query
*hq
)
50 struct etna_resource
*rsc
;
53 pipe_resource_reference(&hq
->prsc
, NULL
);
55 /* allocate resource with space for 64 * 64bit values */
56 hq
->prsc
= pipe_buffer_create(&ctx
->screen
->base
, PIPE_BIND_QUERY_BUFFER
,
59 /* don't assume the buffer is zero-initialized */
60 rsc
= etna_resource(hq
->prsc
);
62 etna_bo_cpu_prep(rsc
->bo
, DRM_ETNA_PREP_WRITE
);
64 map
= etna_bo_map(rsc
->bo
);
65 memset(map
, 0, 0x1000);
66 etna_bo_cpu_fini(rsc
->bo
);
70 etna_hw_begin_query(struct etna_context
*ctx
, struct etna_query
*q
)
72 struct etna_hw_query
*hq
= etna_hw_query(q
);
73 const struct etna_hw_sample_provider
*p
= hq
->provider
;
75 /* ->begin_query() discards previous results, so realloc bo */
76 realloc_query_bo(ctx
, hq
);
80 /* add to active list */
81 assert(list_empty(&hq
->node
));
82 list_addtail(&hq
->node
, &ctx
->active_hw_queries
);
88 etna_hw_end_query(struct etna_context
*ctx
, struct etna_query
*q
)
90 struct etna_hw_query
*hq
= etna_hw_query(q
);
91 const struct etna_hw_sample_provider
*p
= hq
->provider
;
95 /* remove from active list */
96 list_delinit(&hq
->node
);
100 etna_hw_get_query_result(struct etna_context
*ctx
, struct etna_query
*q
,
101 boolean wait
, union pipe_query_result
*result
)
103 struct etna_hw_query
*hq
= etna_hw_query(q
);
104 struct etna_resource
*rsc
= etna_resource(hq
->prsc
);
105 const struct etna_hw_sample_provider
*p
= hq
->provider
;
107 assert(LIST_IS_EMPTY(&hq
->node
));
112 if (rsc
->status
& ETNA_PENDING_WRITE
) {
113 /* piglit spec@arb_occlusion_query@occlusion_query_conform
114 * test, and silly apps perhaps, get stuck in a loop trying
115 * to get query result forever with wait==false.. we don't
116 * wait to flush unnecessarily but we also don't want to
119 if (hq
->no_wait_cnt
++ > 5)
120 ctx
->base
.flush(&ctx
->base
, NULL
, 0);
124 ret
= etna_bo_cpu_prep(rsc
->bo
, DRM_ETNA_PREP_READ
| DRM_ETNA_PREP_NOSYNC
);
128 etna_bo_cpu_fini(rsc
->bo
);
131 /* flush that GPU executes all query related actions */
132 ctx
->base
.flush(&ctx
->base
, NULL
, 0);
135 etna_bo_cpu_prep(rsc
->bo
, DRM_ETNA_PREP_READ
);
137 void *ptr
= etna_bo_map(rsc
->bo
);
138 p
->result(hq
, ptr
, result
);
140 etna_bo_cpu_fini(rsc
->bo
);
145 static const struct etna_query_funcs hw_query_funcs
= {
146 .destroy_query
= etna_hw_destroy_query
,
147 .begin_query
= etna_hw_begin_query
,
148 .end_query
= etna_hw_end_query
,
149 .get_query_result
= etna_hw_get_query_result
,
152 static inline const struct etna_hw_sample_provider
*
153 query_sample_provider(unsigned query_type
)
155 switch (query_type
) {
162 etna_hw_create_query(struct etna_context
*ctx
, unsigned query_type
)
164 struct etna_hw_query
*hq
;
165 struct etna_query
*q
;
166 const struct etna_hw_sample_provider
*p
;
168 p
= query_sample_provider(query_type
);
172 hq
= CALLOC_STRUCT(etna_hw_query
);
178 list_inithead(&hq
->node
);
181 q
->funcs
= &hw_query_funcs
;
182 q
->type
= query_type
;