/* Returns the IOVA of a given uint64_t field in a given slot of a query
* pool. */
#define query_iova(type, pool, query, field, value_index) \
- pool->bo.iova + pool->stride * query + offsetof(type, field) + \
+ pool->bo.iova + pool->stride * (query) + offsetof(type, field) + \
offsetof(struct slot_value, values[value_index])
#define occlusion_query_iova(pool, query, field) \
tu_cs_emit_qw(cs, 0x1);
}
+/* Implement this bit of spec text from section 17.2 "Query Operation":
+ *
+ * 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. For example, some implementations may write
+ * each view’s results to a distinct query, while other implementations
+ * may write the total result to the first query and write zero to the
+ * other queries. However, the sum of the results in all the queries must
+ * accurately reflect the total result of the query summed over all views.
+ * Applications can sum the results from all the queries to compute the
+ * total result.
+ *
+ * Since we execute all views at once, we write zero to the other queries.
+ * Furthermore, because queries must be reset before use, and we set the
+ * result to 0 in vkCmdResetQueryPool(), we just need to mark it as available.
+ */
+
+static void
+handle_multiview_queries(struct tu_cmd_buffer *cmd,
+ struct tu_query_pool *pool,
+ uint32_t query)
+{
+ if (!cmd->state.pass || !cmd->state.subpass->multiview_mask)
+ return;
+
+ unsigned views = util_bitcount(cmd->state.subpass->multiview_mask);
+ struct tu_cs *cs = &cmd->draw_epilogue_cs;
+
+ for (uint32_t i = 1; i < views; i++) {
+ tu_cs_emit_pkt7(cs, CP_MEM_WRITE, 4);
+ tu_cs_emit_qw(cs, query_available_iova(pool, query + i));
+ tu_cs_emit_qw(cs, 0x1);
+ }
+}
+
void
tu_CmdEndQuery(VkCommandBuffer commandBuffer,
VkQueryPool queryPool,
assert(!"Invalid query type");
}
+ handle_multiview_queries(cmdbuf, pool, query);
+
tu_bo_list_add(&cmdbuf->bo_list, &pool->bo, MSM_SUBMIT_BO_WRITE);
}
tu_cs_emit_pkt7(cs, CP_MEM_WRITE, 4);
tu_cs_emit_qw(cs, query_available_iova(pool, query));
tu_cs_emit_qw(cs, 0x1);
+
+ /* From the spec for vkCmdWriteTimestamp:
+ *
+ * If vkCmdWriteTimestamp is called while executing a render pass
+ * instance that has multiview enabled, the timestamp uses N consecutive
+ * query indices in the query pool (starting at query) where N is the
+ * number of bits set in the view mask of the subpass the command is
+ * executed in. The resulting query values are determined by an
+ * implementation-dependent choice of one of the following behaviors:
+ *
+ * - The first query is a timestamp value and (if more than one bit is
+ * set in the view mask) zero is written to the remaining queries.
+ * If two timestamps are written in the same subpass, the sum of the
+ * execution time of all views between those commands is the
+ * difference between the first query written by each command.
+ *
+ * - All N queries are timestamp values. If two timestamps are written
+ * in the same subpass, the sum of the execution time of all views
+ * between those commands is the sum of the difference between
+ * corresponding queries written by each command. The difference
+ * between corresponding queries may be the execution time of a
+ * single view.
+ *
+ * We execute all views in the same draw call, so we implement the first
+ * option, the same as regular queries.
+ */
+ handle_multiview_queries(cmd, pool, query);
}