From 285223d0fd07e9313ad5166d43f3d828408849af Mon Sep 17 00:00:00 2001 From: Samuel Pitoiset Date: Tue, 5 Sep 2023 10:03:13 +0200 Subject: [PATCH] radv: fix interactions with primitives generated queries and pipeline stats SAMPLE_STREAMOUTSTATS requires PIPELINESTAT_START to be enabled, otherwise the hw doesn't count anything. This fixes dEQP-VK.transform_feedback.primitives_generated_query.concurrent.pipeline_statistics_2.* on GFX8. GFX6-9 are probably also affected by this bug, but with NGG these queries are slightly different and don't use legacy streamout. Signed-off-by: Samuel Pitoiset Part-of: --- src/amd/vulkan/meta/radv_meta.c | 16 ++++++++++---- src/amd/vulkan/radv_private.h | 9 ++++++++ src/amd/vulkan/radv_query.c | 39 ++++++++++++++++++++++++++------- 3 files changed, 52 insertions(+), 12 deletions(-) diff --git a/src/amd/vulkan/meta/radv_meta.c b/src/amd/vulkan/meta/radv_meta.c index 35ae14f98de..20695c8a003 100644 --- a/src/amd/vulkan/meta/radv_meta.c +++ b/src/amd/vulkan/meta/radv_meta.c @@ -39,11 +39,15 @@ static void radv_suspend_queries(struct radv_meta_saved_state *state, struct radv_cmd_buffer *cmd_buffer) { - /* Pipeline statistics queries. */ - if (cmd_buffer->state.active_pipeline_queries > 0) { + const uint32_t num_pipeline_stat_queries = radv_get_num_pipeline_stat_queries(cmd_buffer); + + if (num_pipeline_stat_queries > 0) { cmd_buffer->state.flush_bits &= ~RADV_CMD_FLAG_START_PIPELINE_STATS; cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_STOP_PIPELINE_STATS; + } + /* Pipeline statistics queries. */ + if (cmd_buffer->state.active_pipeline_queries > 0) { state->active_pipeline_gds_queries = cmd_buffer->state.active_pipeline_gds_queries; cmd_buffer->state.active_pipeline_gds_queries = 0; cmd_buffer->state.dirty |= RADV_CMD_DIRTY_SHADER_QUERY; @@ -80,11 +84,15 @@ radv_suspend_queries(struct radv_meta_saved_state *state, struct radv_cmd_buffer static void radv_resume_queries(const struct radv_meta_saved_state *state, struct radv_cmd_buffer *cmd_buffer) { - /* Pipeline statistics queries. */ - if (cmd_buffer->state.active_pipeline_queries > 0) { + const uint32_t num_pipeline_stat_queries = radv_get_num_pipeline_stat_queries(cmd_buffer); + + if (num_pipeline_stat_queries > 0) { cmd_buffer->state.flush_bits &= ~RADV_CMD_FLAG_STOP_PIPELINE_STATS; cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_START_PIPELINE_STATS; + } + /* Pipeline statistics queries. */ + if (cmd_buffer->state.active_pipeline_queries > 0) { cmd_buffer->state.active_pipeline_gds_queries = state->active_pipeline_gds_queries; cmd_buffer->state.dirty |= RADV_CMD_DIRTY_SHADER_QUERY; } diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h index 35e791dcad8..919f44b89a7 100644 --- a/src/amd/vulkan/radv_private.h +++ b/src/amd/vulkan/radv_private.h @@ -1655,6 +1655,7 @@ struct radv_cmd_state { unsigned active_pipeline_queries; unsigned active_pipeline_gds_queries; unsigned active_prims_gen_queries; + unsigned active_prims_xfb_queries; unsigned active_prims_gen_gds_queries; unsigned active_prims_xfb_gds_queries; uint32_t trace_id; @@ -1877,6 +1878,14 @@ radv_cmdbuf_has_stage(const struct radv_cmd_buffer *cmd_buffer, gl_shader_stage return !!(cmd_buffer->state.active_stages & mesa_to_vk_shader_stage(stage)); } +static inline uint32_t +radv_get_num_pipeline_stat_queries(struct radv_cmd_buffer *cmd_buffer) +{ + /* SAMPLE_STREAMOUTSTATS also requires PIPELINESTAT_START to be enabled. */ + return cmd_buffer->state.active_pipeline_queries + cmd_buffer->state.active_prims_gen_queries + + cmd_buffer->state.active_prims_xfb_queries; +} + extern const struct vk_command_buffer_ops radv_cmd_buffer_ops; struct radv_dispatch_info { diff --git a/src/amd/vulkan/radv_query.c b/src/amd/vulkan/radv_query.c index 3f3f2c88018..cba50cd4f90 100644 --- a/src/amd/vulkan/radv_query.c +++ b/src/amd/vulkan/radv_query.c @@ -1670,6 +1670,20 @@ gfx10_copy_gds_query(struct radv_cmd_buffer *cmd_buffer, uint32_t gds_offset, ui radeon_emit(cs, va >> 32); } +static void +radv_update_hw_pipelinestat(struct radv_cmd_buffer *cmd_buffer) +{ + const uint32_t num_pipeline_stat_queries = radv_get_num_pipeline_stat_queries(cmd_buffer); + + if (num_pipeline_stat_queries == 0) { + cmd_buffer->state.flush_bits &= ~RADV_CMD_FLAG_START_PIPELINE_STATS; + cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_STOP_PIPELINE_STATS; + } else if (num_pipeline_stat_queries == 1) { + cmd_buffer->state.flush_bits &= ~RADV_CMD_FLAG_STOP_PIPELINE_STATS; + cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_START_PIPELINE_STATS; + } +} + static void emit_begin_query(struct radv_cmd_buffer *cmd_buffer, struct radv_query_pool *pool, uint64_t va, VkQueryType query_type, VkQueryControlFlags flags, uint32_t index) @@ -1719,10 +1733,8 @@ emit_begin_query(struct radv_cmd_buffer *cmd_buffer, struct radv_query_pool *poo radeon_check_space(cmd_buffer->device->ws, cs, 4); ++cmd_buffer->state.active_pipeline_queries; - if (cmd_buffer->state.active_pipeline_queries == 1) { - cmd_buffer->state.flush_bits &= ~RADV_CMD_FLAG_STOP_PIPELINE_STATS; - cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_START_PIPELINE_STATS; - } + + radv_update_hw_pipelinestat(cmd_buffer); radeon_emit(cs, PKT3(PKT3_EVENT_WRITE, 2, 0)); radeon_emit(cs, EVENT_TYPE(V_028A90_SAMPLE_PIPELINESTAT) | EVENT_INDEX(2)); @@ -1768,6 +1780,10 @@ emit_begin_query(struct radv_cmd_buffer *cmd_buffer, struct radv_query_pool *poo cmd_buffer->state.active_prims_xfb_gds_queries++; } else { + cmd_buffer->state.active_prims_xfb_queries++; + + radv_update_hw_pipelinestat(cmd_buffer); + emit_sample_streamout(cmd_buffer, va, index); } break; @@ -1797,6 +1813,8 @@ emit_begin_query(struct radv_cmd_buffer *cmd_buffer, struct radv_query_pool *poo cmd_buffer->state.active_prims_gen_queries++; } + radv_update_hw_pipelinestat(cmd_buffer); + if (pool->uses_gds) { /* generated prim counter */ gfx10_copy_gds_query(cmd_buffer, RADV_SHADER_QUERY_PRIM_GEN_OFFSET(index), va + 32); @@ -1863,10 +1881,9 @@ emit_end_query(struct radv_cmd_buffer *cmd_buffer, struct radv_query_pool *pool, radeon_check_space(cmd_buffer->device->ws, cs, 16); cmd_buffer->state.active_pipeline_queries--; - if (cmd_buffer->state.active_pipeline_queries == 0) { - cmd_buffer->state.flush_bits &= ~RADV_CMD_FLAG_START_PIPELINE_STATS; - cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_STOP_PIPELINE_STATS; - } + + radv_update_hw_pipelinestat(cmd_buffer); + va += pipelinestat_block_size; radeon_emit(cs, PKT3(PKT3_EVENT_WRITE, 2, 0)); @@ -1914,6 +1931,10 @@ emit_end_query(struct radv_cmd_buffer *cmd_buffer, struct radv_query_pool *pool, if (!cmd_buffer->state.active_prims_xfb_gds_queries) cmd_buffer->state.dirty |= RADV_CMD_DIRTY_SHADER_QUERY; } else { + cmd_buffer->state.active_prims_xfb_queries--; + + radv_update_hw_pipelinestat(cmd_buffer); + emit_sample_streamout(cmd_buffer, va + 16, index); } break; @@ -1940,6 +1961,8 @@ emit_end_query(struct radv_cmd_buffer *cmd_buffer, struct radv_query_pool *pool, cmd_buffer->state.active_prims_gen_queries--; } + radv_update_hw_pipelinestat(cmd_buffer); + if (pool->uses_gds) { /* generated prim counter */ gfx10_copy_gds_query(cmd_buffer, RADV_SHADER_QUERY_PRIM_GEN_OFFSET(index), va + 36);