1 #include "zink_query.h"
3 #include "zink_context.h"
4 #include "zink_screen.h"
6 #include "util/u_dump.h"
7 #include "util/u_inlines.h"
8 #include "util/u_memory.h"
11 enum pipe_query_type type
;
13 VkQueryPool query_pool
;
14 unsigned curr_query
, num_queries
;
20 struct list_head active_list
;
24 convert_query_type(unsigned query_type
, bool *use_64bit
, bool *precise
)
29 case PIPE_QUERY_OCCLUSION_COUNTER
:
32 case PIPE_QUERY_OCCLUSION_PREDICATE
:
33 case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE
:
34 return VK_QUERY_TYPE_OCCLUSION
;
35 case PIPE_QUERY_TIMESTAMP
:
37 return VK_QUERY_TYPE_TIMESTAMP
;
38 case PIPE_QUERY_PIPELINE_STATISTICS
:
39 return VK_QUERY_TYPE_PIPELINE_STATISTICS
;
41 debug_printf("unknown query: %s\n",
42 util_str_query_type(query_type
, true));
43 unreachable("zink: unknown query type");
47 static struct pipe_query
*
48 zink_create_query(struct pipe_context
*pctx
,
49 unsigned query_type
, unsigned index
)
51 struct zink_screen
*screen
= zink_screen(pctx
->screen
);
52 struct zink_query
*query
= CALLOC_STRUCT(zink_query
);
53 VkQueryPoolCreateInfo pool_create
= {};
58 query
->type
= query_type
;
59 query
->vkqtype
= convert_query_type(query_type
, &query
->use_64bit
, &query
->precise
);
60 if (query
->vkqtype
== -1)
63 query
->num_queries
= query_type
== PIPE_QUERY_TIMESTAMP
? 1 : 100;
64 query
->curr_query
= 0;
66 pool_create
.sType
= VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO
;
67 pool_create
.queryType
= query
->vkqtype
;
68 pool_create
.queryCount
= query
->num_queries
;
70 VkResult status
= vkCreateQueryPool(screen
->dev
, &pool_create
, NULL
, &query
->query_pool
);
71 if (status
!= VK_SUCCESS
) {
75 return (struct pipe_query
*)query
;
79 zink_destroy_query(struct pipe_context
*pctx
,
82 struct zink_screen
*screen
= zink_screen(pctx
->screen
);
83 struct zink_query
*query
= (struct zink_query
*)q
;
85 vkDestroyQueryPool(screen
->dev
, query
->query_pool
, NULL
);
89 begin_query(struct zink_context
*ctx
, struct zink_query
*q
)
91 VkQueryControlFlags flags
= 0;
93 flags
|= VK_QUERY_CONTROL_PRECISE_BIT
;
95 struct zink_batch
*batch
= zink_curr_batch(ctx
);
96 vkCmdBeginQuery(batch
->cmdbuf
, q
->query_pool
, q
->curr_query
, flags
);
100 zink_begin_query(struct pipe_context
*pctx
,
101 struct pipe_query
*q
)
103 struct zink_context
*ctx
= zink_context(pctx
);
104 struct zink_query
*query
= (struct zink_query
*)q
;
106 /* ignore begin_query for timestamps */
107 if (query
->type
== PIPE_QUERY_TIMESTAMP
)
110 /* TODO: resetting on begin isn't ideal, as it forces render-pass exit...
111 * should instead reset on creation (if possible?)... Or perhaps maintain
112 * the pool in the batch instead?
114 struct zink_batch
*batch
= zink_batch_no_rp(zink_context(pctx
));
115 vkCmdResetQueryPool(batch
->cmdbuf
, query
->query_pool
, 0, query
->curr_query
);
116 query
->curr_query
= 0;
118 begin_query(ctx
, query
);
119 list_addtail(&query
->active_list
, &ctx
->active_queries
);
125 end_query(struct zink_context
*ctx
, struct zink_query
*q
)
127 struct zink_batch
*batch
= zink_curr_batch(ctx
);
128 assert(q
->type
!= PIPE_QUERY_TIMESTAMP
);
129 vkCmdEndQuery(batch
->cmdbuf
, q
->query_pool
, q
->curr_query
);
130 if (++q
->curr_query
== q
->num_queries
) {
132 /* need to reset pool! */
137 zink_end_query(struct pipe_context
*pctx
,
138 struct pipe_query
*q
)
140 struct zink_context
*ctx
= zink_context(pctx
);
141 struct zink_query
*query
= (struct zink_query
*)q
;
143 if (query
->type
== PIPE_QUERY_TIMESTAMP
) {
144 assert(query
->curr_query
== 0);
145 struct zink_batch
*batch
= zink_curr_batch(ctx
);
146 vkCmdWriteTimestamp(batch
->cmdbuf
, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT
,
147 query
->query_pool
, 0);
149 end_query(ctx
, query
);
150 list_delinit(&query
->active_list
);
157 zink_get_query_result(struct pipe_context
*pctx
,
158 struct pipe_query
*q
,
160 union pipe_query_result
*result
)
162 struct zink_screen
*screen
= zink_screen(pctx
->screen
);
163 struct zink_query
*query
= (struct zink_query
*)q
;
164 VkQueryResultFlagBits flags
= 0;
167 struct pipe_fence_handle
*fence
= NULL
;
168 pctx
->flush(pctx
, &fence
, PIPE_FLUSH_HINT_FINISH
);
170 pctx
->screen
->fence_finish(pctx
->screen
, NULL
, fence
,
171 PIPE_TIMEOUT_INFINITE
);
172 pctx
->screen
->fence_reference(pctx
->screen
, &fence
, NULL
);
174 flags
|= VK_QUERY_RESULT_WAIT_BIT
;
176 pctx
->flush(pctx
, NULL
, 0);
178 if (query
->use_64bit
)
179 flags
|= VK_QUERY_RESULT_64_BIT
;
181 // TODO: handle curr_query > 100
182 // union pipe_query_result results[100];
183 uint64_t results
[100];
184 memset(results
, 0, sizeof(results
));
185 assert(query
->curr_query
<= ARRAY_SIZE(results
));
186 if (vkGetQueryPoolResults(screen
->dev
, query
->query_pool
,
187 0, query
->curr_query
,
191 flags
) != VK_SUCCESS
)
194 util_query_clear_result(result
, query
->type
);
195 for (int i
= 0; i
< query
->curr_query
; ++i
) {
196 switch (query
->type
) {
197 case PIPE_QUERY_OCCLUSION_PREDICATE
:
198 case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE
:
199 case PIPE_QUERY_SO_OVERFLOW_PREDICATE
:
200 case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE
:
201 case PIPE_QUERY_GPU_FINISHED
:
202 result
->b
|= results
[i
] != 0;
205 case PIPE_QUERY_OCCLUSION_COUNTER
:
206 result
->u64
+= results
[i
];
210 debug_printf("unhangled query type: %s\n",
211 util_str_query_type(query
->type
, true));
212 unreachable("unexpected query type");
220 zink_suspend_queries(struct zink_context
*ctx
, struct zink_batch
*batch
)
222 struct zink_query
*query
;
223 LIST_FOR_EACH_ENTRY(query
, &ctx
->active_queries
, active_list
) {
224 end_query(ctx
, query
);
229 zink_resume_queries(struct zink_context
*ctx
, struct zink_batch
*batch
)
231 struct zink_query
*query
;
232 LIST_FOR_EACH_ENTRY(query
, &ctx
->active_queries
, active_list
) {
233 begin_query(ctx
, query
);
238 zink_set_active_query_state(struct pipe_context
*pctx
, bool enable
)
240 struct zink_context
*ctx
= zink_context(pctx
);
241 ctx
->queries_disabled
= !enable
;
243 struct zink_batch
*batch
= zink_curr_batch(ctx
);
244 if (ctx
->queries_disabled
)
245 zink_suspend_queries(ctx
, batch
);
247 zink_resume_queries(ctx
, batch
);
251 zink_context_query_init(struct pipe_context
*pctx
)
253 struct zink_context
*ctx
= zink_context(pctx
);
254 list_inithead(&ctx
->active_queries
);
256 pctx
->create_query
= zink_create_query
;
257 pctx
->destroy_query
= zink_destroy_query
;
258 pctx
->begin_query
= zink_begin_query
;
259 pctx
->end_query
= zink_end_query
;
260 pctx
->get_query_result
= zink_get_query_result
;
261 pctx
->set_active_query_state
= zink_set_active_query_state
;