info->pool = pool;
info->query = query;
+
+ /* From the Vulkan spec:
+ *
+ * "If queries are used while executing a render pass instance that has
+ * multiview enabled, the query uses N consecutive query indices in
+ * the query pool (starting at query) where N is the number of bits set
+ * in the view mask in the subpass the query is used in. How the
+ * numerical results of the query are distributed among the queries is
+ * implementation-dependent."
+ *
+ * In our case, only the first query is used but this means we still need
+ * to flag the other queries as available so we don't emit errors when
+ * the applications attempt to retrive values from them.
+ */
+ struct v3dv_render_pass *pass = cmd_buffer->state.pass;
+ if (!pass->multiview_enabled) {
+ info->count = 1;
+ } else {
+ struct v3dv_subpass *subpass = &pass->subpasses[state->subpass_idx];
+ info->count = util_bitcount(subpass->view_mask);
+ }
} else {
/* Otherwise, schedule the CPU job immediately */
struct v3dv_job *job =
job->cpu.query_end.pool = pool;
job->cpu.query_end.query = query;
+
+ /* Multiview queries cannot cross subpass boundaries */
+ job->cpu.query_end.count = 1;
+
list_addtail(&job->list_link, &cmd_buffer->jobs);
}
/* If this is called inside a render pass we need to finish the current
* job here...
*/
- if (cmd_buffer->state.pass)
+ struct v3dv_render_pass *pass = cmd_buffer->state.pass;
+ if (pass)
v3dv_cmd_buffer_finish_job(cmd_buffer);
struct v3dv_job *job =
job->cpu.query_timestamp.pool = query_pool;
job->cpu.query_timestamp.query = query;
+ if (!pass || !pass->multiview_enabled) {
+ job->cpu.query_timestamp.count = 1;
+ } else {
+ struct v3dv_subpass *subpass =
+ &pass->subpasses[cmd_buffer->state.subpass_idx];
+ job->cpu.query_timestamp.count = util_bitcount(subpass->view_mask);
+ }
+
list_addtail(&job->list_link, &cmd_buffer->jobs);
cmd_buffer->state.job = NULL;
struct v3dv_end_query_cpu_job_info {
struct v3dv_query_pool *pool;
uint32_t query;
+
+ /* This is one unless multiview is used */
+ uint32_t count;
};
struct v3dv_copy_query_results_cpu_job_info {
struct v3dv_timestamp_query_cpu_job_info {
struct v3dv_query_pool *pool;
uint32_t query;
+
+ /* This is one unless multiview is used */
+ uint32_t count;
};
struct v3dv_job {
handle_end_query_cpu_job(struct v3dv_job *job)
{
struct v3dv_end_query_cpu_job_info *info = &job->cpu.query_end;
- assert(info->query < info->pool->query_count);
- struct v3dv_query *query = &info->pool->queries[info->query];
- query->maybe_available = true;
+ for (uint32_t i = 0; i < info->count; i++) {
+ assert(info->query + i < info->pool->query_count);
+ struct v3dv_query *query = &info->pool->queries[info->query + i];
+ query->maybe_available = true;
+ }
return VK_SUCCESS;
}
/* Compute timestamp */
struct timespec t;
clock_gettime(CLOCK_MONOTONIC, &t);
- assert(info->query < info->pool->query_count);
- struct v3dv_query *query = &info->pool->queries[info->query];
- query->maybe_available = true;
- query->value = t.tv_sec * 1000000000ull + t.tv_nsec;
+
+ for (uint32_t i = 0; i < info->count; i++) {
+ assert(info->query + i < info->pool->query_count);
+ struct v3dv_query *query = &info->pool->queries[info->query + i];
+ query->maybe_available = true;
+ if (i == 0)
+ query->value = t.tv_sec * 1000000000ull + t.tv_nsec;
+ }
return VK_SUCCESS;
}