1 #include "zink_query.h"
3 #include "zink_context.h"
4 #include "zink_resource.h"
5 #include "zink_screen.h"
7 #include "util/u_dump.h"
8 #include "util/u_inlines.h"
9 #include "util/u_memory.h"
12 enum pipe_query_type type
;
14 VkQueryPool query_pool
;
15 unsigned curr_query
, num_queries
;
21 struct list_head active_list
;
25 convert_query_type(unsigned query_type
, bool *use_64bit
, bool *precise
)
30 case PIPE_QUERY_OCCLUSION_COUNTER
:
33 case PIPE_QUERY_OCCLUSION_PREDICATE
:
34 case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE
:
35 return VK_QUERY_TYPE_OCCLUSION
;
36 case PIPE_QUERY_TIMESTAMP
:
38 return VK_QUERY_TYPE_TIMESTAMP
;
39 case PIPE_QUERY_PIPELINE_STATISTICS
:
40 return VK_QUERY_TYPE_PIPELINE_STATISTICS
;
42 debug_printf("unknown query: %s\n",
43 util_str_query_type(query_type
, true));
44 unreachable("zink: unknown query type");
48 static struct pipe_query
*
49 zink_create_query(struct pipe_context
*pctx
,
50 unsigned query_type
, unsigned index
)
52 struct zink_screen
*screen
= zink_screen(pctx
->screen
);
53 struct zink_query
*query
= CALLOC_STRUCT(zink_query
);
54 VkQueryPoolCreateInfo pool_create
= {};
59 query
->type
= query_type
;
60 query
->vkqtype
= convert_query_type(query_type
, &query
->use_64bit
, &query
->precise
);
61 if (query
->vkqtype
== -1)
64 query
->num_queries
= query_type
== PIPE_QUERY_TIMESTAMP
? 1 : 100;
65 query
->curr_query
= 0;
67 pool_create
.sType
= VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO
;
68 pool_create
.queryType
= query
->vkqtype
;
69 pool_create
.queryCount
= query
->num_queries
;
71 VkResult status
= vkCreateQueryPool(screen
->dev
, &pool_create
, NULL
, &query
->query_pool
);
72 if (status
!= VK_SUCCESS
) {
76 return (struct pipe_query
*)query
;
79 /* TODO: rework this to be less hammer-ish using deferred destroy */
81 wait_query(struct pipe_context
*pctx
, struct zink_query
*query
)
83 struct pipe_fence_handle
*fence
= NULL
;
85 pctx
->flush(pctx
, &fence
, PIPE_FLUSH_HINT_FINISH
);
87 pctx
->screen
->fence_finish(pctx
->screen
, NULL
, fence
,
88 PIPE_TIMEOUT_INFINITE
);
89 pctx
->screen
->fence_reference(pctx
->screen
, &fence
, NULL
);
94 zink_destroy_query(struct pipe_context
*pctx
,
97 struct zink_screen
*screen
= zink_screen(pctx
->screen
);
98 struct zink_query
*query
= (struct zink_query
*)q
;
100 if (!list_is_empty(&query
->active_list
)) {
101 wait_query(pctx
, query
);
104 vkDestroyQueryPool(screen
->dev
, query
->query_pool
, NULL
);
109 begin_query(struct zink_batch
*batch
, struct zink_query
*q
)
111 VkQueryControlFlags flags
= 0;
113 flags
|= VK_QUERY_CONTROL_PRECISE_BIT
;
115 vkCmdBeginQuery(batch
->cmdbuf
, q
->query_pool
, q
->curr_query
, flags
);
119 zink_begin_query(struct pipe_context
*pctx
,
120 struct pipe_query
*q
)
122 struct zink_context
*ctx
= zink_context(pctx
);
123 struct zink_query
*query
= (struct zink_query
*)q
;
125 /* ignore begin_query for timestamps */
126 if (query
->type
== PIPE_QUERY_TIMESTAMP
)
129 /* TODO: resetting on begin isn't ideal, as it forces render-pass exit...
130 * should instead reset on creation (if possible?)... Or perhaps maintain
131 * the pool in the batch instead?
133 struct zink_batch
*batch
= zink_batch_no_rp(zink_context(pctx
));
134 vkCmdResetQueryPool(batch
->cmdbuf
, query
->query_pool
, 0, MIN2(query
->curr_query
+ 1, query
->num_queries
));
135 query
->curr_query
= 0;
137 begin_query(batch
, query
);
138 list_addtail(&query
->active_list
, &ctx
->active_queries
);
144 end_query(struct zink_batch
*batch
, struct zink_query
*q
)
146 assert(q
->type
!= PIPE_QUERY_TIMESTAMP
);
147 vkCmdEndQuery(batch
->cmdbuf
, q
->query_pool
, q
->curr_query
);
148 if (++q
->curr_query
== q
->num_queries
) {
150 /* need to reset pool! */
155 zink_end_query(struct pipe_context
*pctx
,
156 struct pipe_query
*q
)
158 struct zink_context
*ctx
= zink_context(pctx
);
159 struct zink_batch
*batch
= zink_curr_batch(ctx
);
160 struct zink_query
*query
= (struct zink_query
*)q
;
162 if (query
->type
== PIPE_QUERY_TIMESTAMP
) {
163 assert(query
->curr_query
== 0);
164 vkCmdWriteTimestamp(batch
->cmdbuf
, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT
,
165 query
->query_pool
, 0);
167 end_query(batch
, query
);
168 list_delinit(&query
->active_list
);
175 zink_get_query_result(struct pipe_context
*pctx
,
176 struct pipe_query
*q
,
178 union pipe_query_result
*result
)
180 struct zink_screen
*screen
= zink_screen(pctx
->screen
);
181 struct zink_query
*query
= (struct zink_query
*)q
;
182 VkQueryResultFlagBits flags
= 0;
185 wait_query(pctx
, query
);
186 flags
|= VK_QUERY_RESULT_WAIT_BIT
;
188 pctx
->flush(pctx
, NULL
, 0);
190 if (query
->use_64bit
)
191 flags
|= VK_QUERY_RESULT_64_BIT
;
193 // TODO: handle curr_query > 100
194 // union pipe_query_result results[100];
195 uint64_t results
[100];
196 memset(results
, 0, sizeof(results
));
197 assert(query
->curr_query
<= ARRAY_SIZE(results
));
198 if (vkGetQueryPoolResults(screen
->dev
, query
->query_pool
,
199 0, query
->curr_query
,
203 flags
) != VK_SUCCESS
)
206 util_query_clear_result(result
, query
->type
);
207 for (int i
= 0; i
< query
->curr_query
; ++i
) {
208 switch (query
->type
) {
209 case PIPE_QUERY_OCCLUSION_PREDICATE
:
210 case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE
:
211 case PIPE_QUERY_SO_OVERFLOW_PREDICATE
:
212 case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE
:
213 case PIPE_QUERY_GPU_FINISHED
:
214 result
->b
|= results
[i
] != 0;
217 case PIPE_QUERY_OCCLUSION_COUNTER
:
218 result
->u64
+= results
[i
];
222 debug_printf("unhangled query type: %s\n",
223 util_str_query_type(query
->type
, true));
224 unreachable("unexpected query type");
232 zink_suspend_queries(struct zink_context
*ctx
, struct zink_batch
*batch
)
234 struct zink_query
*query
;
235 LIST_FOR_EACH_ENTRY(query
, &ctx
->active_queries
, active_list
) {
236 end_query(batch
, query
);
241 zink_resume_queries(struct zink_context
*ctx
, struct zink_batch
*batch
)
243 struct zink_query
*query
;
244 LIST_FOR_EACH_ENTRY(query
, &ctx
->active_queries
, active_list
) {
245 vkCmdResetQueryPool(batch
->cmdbuf
, query
->query_pool
, query
->curr_query
, 1);
246 begin_query(batch
, query
);
251 zink_set_active_query_state(struct pipe_context
*pctx
, bool enable
)
253 struct zink_context
*ctx
= zink_context(pctx
);
254 ctx
->queries_disabled
= !enable
;
256 struct zink_batch
*batch
= zink_curr_batch(ctx
);
257 if (ctx
->queries_disabled
)
258 zink_suspend_queries(ctx
, batch
);
260 zink_resume_queries(ctx
, batch
);
264 zink_render_condition(struct pipe_context
*pctx
,
265 struct pipe_query
*pquery
,
267 enum pipe_render_cond_flag mode
)
269 struct zink_context
*ctx
= zink_context(pctx
);
270 struct zink_screen
*screen
= zink_screen(pctx
->screen
);
271 struct zink_query
*query
= (struct zink_query
*)pquery
;
272 struct zink_batch
*batch
= zink_curr_batch(ctx
);
273 VkQueryResultFlagBits flags
= 0;
276 screen
->vk_CmdEndConditionalRenderingEXT(batch
->cmdbuf
);
280 struct pipe_resource
*pres
;
281 struct zink_resource
*res
;
282 struct pipe_resource templ
= {};
286 templ
.format
= PIPE_FORMAT_R8_UINT
;
287 templ
.target
= PIPE_BUFFER
;
289 /* need to create a vulkan buffer to copy the data into */
290 pres
= pctx
->screen
->resource_create(pctx
->screen
, &templ
);
294 res
= (struct zink_resource
*)pres
;
296 if (mode
== PIPE_RENDER_COND_WAIT
|| mode
== PIPE_RENDER_COND_BY_REGION_WAIT
)
297 flags
|= VK_QUERY_RESULT_WAIT_BIT
;
299 if (query
->use_64bit
)
300 flags
|= VK_QUERY_RESULT_64_BIT
;
301 vkCmdCopyQueryPoolResults(batch
->cmdbuf
, query
->query_pool
, 0, 1,
302 res
->buffer
, 0, 0, flags
);
304 VkConditionalRenderingFlagsEXT begin_flags
= 0;
306 begin_flags
= VK_CONDITIONAL_RENDERING_INVERTED_BIT_EXT
;
307 VkConditionalRenderingBeginInfoEXT begin_info
= {};
308 begin_info
.sType
= VK_STRUCTURE_TYPE_CONDITIONAL_RENDERING_BEGIN_INFO_EXT
;
309 begin_info
.buffer
= res
->buffer
;
310 begin_info
.flags
= begin_flags
;
311 screen
->vk_CmdBeginConditionalRenderingEXT(batch
->cmdbuf
, &begin_info
);
313 zink_batch_reference_resoure(batch
, res
);
315 pipe_resource_reference(&pres
, NULL
);
319 zink_context_query_init(struct pipe_context
*pctx
)
321 struct zink_context
*ctx
= zink_context(pctx
);
322 list_inithead(&ctx
->active_queries
);
324 pctx
->create_query
= zink_create_query
;
325 pctx
->destroy_query
= zink_destroy_query
;
326 pctx
->begin_query
= zink_begin_query
;
327 pctx
->end_query
= zink_end_query
;
328 pctx
->get_query_result
= zink_get_query_result
;
329 pctx
->set_active_query_state
= zink_set_active_query_state
;
330 pctx
->render_condition
= zink_render_condition
;