diff --git a/src/broadcom/vulkan/v3dv_cmd_buffer.c b/src/broadcom/vulkan/v3dv_cmd_buffer.c index 194ddc07b99..c52c9093814 100644 --- a/src/broadcom/vulkan/v3dv_cmd_buffer.c +++ b/src/broadcom/vulkan/v3dv_cmd_buffer.c @@ -3061,6 +3061,27 @@ v3dv_cmd_buffer_end_query(struct v3dv_cmd_buffer *cmd_buffer, 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 = @@ -3071,6 +3092,10 @@ v3dv_cmd_buffer_end_query(struct v3dv_cmd_buffer *cmd_buffer, 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); } @@ -3249,7 +3274,8 @@ v3dv_CmdWriteTimestamp(VkCommandBuffer commandBuffer, /* 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 = @@ -3261,6 +3287,14 @@ v3dv_CmdWriteTimestamp(VkCommandBuffer commandBuffer, 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; diff --git a/src/broadcom/vulkan/v3dv_private.h b/src/broadcom/vulkan/v3dv_private.h index 650fcec36db..26585ec72de 100644 --- a/src/broadcom/vulkan/v3dv_private.h +++ b/src/broadcom/vulkan/v3dv_private.h @@ -896,6 +896,9 @@ struct v3dv_reset_query_cpu_job_info { 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 { @@ -947,6 +950,9 @@ struct v3dv_csd_indirect_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 { diff --git a/src/broadcom/vulkan/v3dv_queue.c b/src/broadcom/vulkan/v3dv_queue.c index 11a2585ee6e..dfa14f39c67 100644 --- a/src/broadcom/vulkan/v3dv_queue.c +++ b/src/broadcom/vulkan/v3dv_queue.c @@ -198,9 +198,11 @@ static VkResult 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; } @@ -452,10 +454,14 @@ handle_timestamp_query_cpu_job(struct v3dv_job *job) /* 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; }