tu: Implement multiview query interactions

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5720>
This commit is contained in:
Connor Abbott
2020-07-02 11:12:13 +02:00
committed by Marge Bot
parent ff5f460980
commit 7b53ac1c1f
+68 -1
View File
@@ -76,7 +76,7 @@ struct PACKED primitive_query_slot {
/* 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) \
@@ -726,6 +726,44 @@ emit_end_xfb_query(struct tu_cmd_buffer *cmdbuf,
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 views 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,
@@ -749,6 +787,8 @@ tu_CmdEndQuery(VkCommandBuffer commandBuffer,
assert(!"Invalid query type");
}
handle_multiview_queries(cmdbuf, pool, query);
tu_bo_list_add(&cmdbuf->bo_list, &pool->bo, MSM_SUBMIT_BO_WRITE);
}
@@ -825,4 +865,31 @@ tu_CmdWriteTimestamp(VkCommandBuffer commandBuffer,
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);
}