From 7b53ac1c1f46046d31577fbc866931ec54a5c4eb Mon Sep 17 00:00:00 2001 From: Connor Abbott Date: Thu, 2 Jul 2020 11:12:13 +0200 Subject: [PATCH] tu: Implement multiview query interactions Part-of: --- src/freedreno/vulkan/tu_query.c | 69 ++++++++++++++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/src/freedreno/vulkan/tu_query.c b/src/freedreno/vulkan/tu_query.c index 66f18a1ede5..24643401f57 100644 --- a/src/freedreno/vulkan/tu_query.c +++ b/src/freedreno/vulkan/tu_query.c @@ -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 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, @@ -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); } -- 2.30.2