From 815a603889b812edc94bed61a260c76c264a8b9d Mon Sep 17 00:00:00 2001 From: Brian Ho Date: Sun, 26 Jan 2020 19:50:42 -0800 Subject: [PATCH] anv: Handle unavailable queries in vkCmdCopyQueryPoolResults If VK_QUERY_RESULT_WAIT_BIT is not set, there is currently no special handling of unavailable queries in vkCmdCopyQueryPoolResults, and anv will write an invalid value for the query result. This commit updates vkCmdCopyQueryPoolResults for unavailable queries to return 0 if the VK_QUERY_RESULT_PARTIAL_BIT flag is set and if not, skip writing altogether. Cc: Reviewed-by: Lionel Landwerlin Tested-by: Marge Bot Part-of: --- src/intel/vulkan/genX_query.c | 54 +++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/src/intel/vulkan/genX_query.c b/src/intel/vulkan/genX_query.c index c549b13960b..77a04605867 100644 --- a/src/intel/vulkan/genX_query.c +++ b/src/intel/vulkan/genX_query.c @@ -863,6 +863,45 @@ void genX(CmdWriteTimestamp)( #if GEN_GEN > 7 || GEN_IS_HASWELL +#if GEN_GEN >= 8 || GEN_IS_HASWELL + +#define MI_PREDICATE_SRC0 0x2400 +#define MI_PREDICATE_SRC1 0x2408 +#define MI_PREDICATE_RESULT 0x2418 + +/** + * Writes the results of a query to dst_addr is the value at poll_addr is equal + * to the reference value. + */ +static void +gpu_write_query_result_cond(struct anv_cmd_buffer *cmd_buffer, + struct gen_mi_builder *b, + struct anv_address poll_addr, + struct anv_address dst_addr, + uint64_t ref_value, + VkQueryResultFlags flags, + uint32_t value_index, + struct gen_mi_value query_result) +{ + gen_mi_store(b, gen_mi_reg64(MI_PREDICATE_SRC0), gen_mi_mem64(poll_addr)); + gen_mi_store(b, gen_mi_reg64(MI_PREDICATE_SRC1), gen_mi_imm(ref_value)); + anv_batch_emit(&cmd_buffer->batch, GENX(MI_PREDICATE), mip) { + mip.LoadOperation = LOAD_LOAD; + mip.CombineOperation = COMBINE_SET; + mip.CompareOperation = COMPARE_SRCS_EQUAL; + } + + if (flags & VK_QUERY_RESULT_64_BIT) { + struct anv_address res_addr = anv_address_add(dst_addr, value_index * 8); + gen_mi_store_if(b, gen_mi_mem64(res_addr), query_result); + } else { + struct anv_address res_addr = anv_address_add(dst_addr, value_index * 4); + gen_mi_store_if(b, gen_mi_mem32(res_addr), query_result); + } +} + +#endif /* GEN_GEN >= 8 || GEN_IS_HASWELL */ + static void gpu_write_query_result(struct gen_mi_builder *b, struct anv_address dst_addr, @@ -939,7 +978,22 @@ void genX(CmdCopyQueryPoolResults)( switch (pool->type) { case VK_QUERY_TYPE_OCCLUSION: result = compute_query_result(&b, anv_address_add(query_addr, 8)); +#if GEN_GEN >= 8 || GEN_IS_HASWELL + /* Like in the case of vkGetQueryPoolResults, if the query is + * unavailable and the VK_QUERY_RESULT_PARTIAL_BIT flag is set, + * conservatively write 0 as the query result. If the + * VK_QUERY_RESULT_PARTIAL_BIT isn't set, don't write any value. + */ + gpu_write_query_result_cond(cmd_buffer, &b, query_addr, dest_addr, + 1 /* available */, flags, idx, result); + if (flags & VK_QUERY_RESULT_PARTIAL_BIT) { + gpu_write_query_result_cond(cmd_buffer, &b, query_addr, dest_addr, + 0 /* unavailable */, flags, idx, gen_mi_imm(0)); + } + idx++; +#else /* GEN_GEN < 8 && !GEN_IS_HASWELL */ gpu_write_query_result(&b, dest_addr, flags, idx++, result); +#endif break; case VK_QUERY_TYPE_PIPELINE_STATISTICS: { -- 2.30.2