diff --git a/src/panfrost/vulkan/csf/panvk_cmd_buffer.h b/src/panfrost/vulkan/csf/panvk_cmd_buffer.h index 0732e8f2d72..9d021ee38d8 100644 --- a/src/panfrost/vulkan/csf/panvk_cmd_buffer.h +++ b/src/panfrost/vulkan/csf/panvk_cmd_buffer.h @@ -560,42 +560,50 @@ panvk_get_subqueue_stages(enum panvk_subqueue_id subqueue) } } -static uint32_t -vk_stage_to_subqueue_mask(VkPipelineStageFlagBits2 vk_stage) -{ - assert(util_bitcount64(vk_stage) == 1); - /* Handle special stages. */ - if (vk_stage == VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT) - return BITFIELD_BIT(PANVK_SUBQUEUE_VERTEX_TILER) | - BITFIELD_BIT(PANVK_SUBQUEUE_COMPUTE); - if (vk_stage == VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT) - return BITFIELD_BIT(PANVK_SUBQUEUE_FRAGMENT) | - BITFIELD_BIT(PANVK_SUBQUEUE_COMPUTE); - if (vk_stage == VK_PIPELINE_STAGE_2_HOST_BIT) - /* We need to map host to something, so map it to compute to not interfer - * with drawing. */ - return BITFIELD_BIT(PANVK_SUBQUEUE_COMPUTE); +/* Hint for vk_stages_to_subqueue_mask if stages refer to first or second + * synchronization scope + */ +enum sync_scope { + /* First scope (sometimes called 'source' in Vulkan) + * is the first stage(s) of an execution dependency chain. + */ + SYNC_SCOPE_FIRST, + /* Second scope (sometimes called 'destination' in Vulkan) + * is the second stage(s) of an execution dependency chain. + */ + SYNC_SCOPE_SECOND, +}; +static uint32_t +vk_stages_to_subqueue_mask(VkPipelineStageFlags2 vk_stages, + enum sync_scope scope) +{ /* Handle other compound stages by expanding. */ - vk_stage = vk_expand_pipeline_stage_flags2(vk_stage); + switch (scope) { + case SYNC_SCOPE_FIRST: + vk_stages = vk_expand_src_stage_flags2(vk_stages); + break; + case SYNC_SCOPE_SECOND: + vk_stages = vk_expand_dst_stage_flags2(vk_stages); + break; + default: + UNREACHABLE("Invalid sync_scope"); + } VkPipelineStageFlags2 flags[PANVK_SUBQUEUE_COUNT]; for (uint32_t sq = 0; sq < PANVK_SUBQUEUE_COUNT; ++sq) flags[sq] = panvk_get_subqueue_stages(sq); uint32_t result = 0; - - if (flags[PANVK_SUBQUEUE_VERTEX_TILER] & vk_stage) + if (flags[PANVK_SUBQUEUE_VERTEX_TILER] & vk_stages) result |= BITFIELD_BIT(PANVK_SUBQUEUE_VERTEX_TILER); - if (flags[PANVK_SUBQUEUE_FRAGMENT] & vk_stage) + if (flags[PANVK_SUBQUEUE_FRAGMENT] & vk_stages) result |= BITFIELD_BIT(PANVK_SUBQUEUE_FRAGMENT); - if (flags[PANVK_SUBQUEUE_COMPUTE] & vk_stage) + if (flags[PANVK_SUBQUEUE_COMPUTE] & vk_stages) result |= BITFIELD_BIT(PANVK_SUBQUEUE_COMPUTE); - /* All stages should map to at least one subqueue. */ - assert(util_bitcount(result) > 0); return result; } diff --git a/src/panfrost/vulkan/csf/panvk_vX_cmd_query.c b/src/panfrost/vulkan/csf/panvk_vX_cmd_query.c index 8f50d230c15..0b49d824e23 100644 --- a/src/panfrost/vulkan/csf/panvk_vX_cmd_query.c +++ b/src/panfrost/vulkan/csf/panvk_vX_cmd_query.c @@ -368,6 +368,31 @@ panvk_cmd_reset_timestamp_queries(struct panvk_cmd_buffer *cmd, cs_flush_stores(b); } +static uint32_t +vk_stage_to_timestamp_subqueue_mask(VkPipelineStageFlagBits2 vk_stage) +{ + assert(util_bitcount64(vk_stage) == 1); + + /* Handle special stages. */ + if (vk_stage == VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT) + return BITFIELD_BIT(PANVK_SUBQUEUE_VERTEX_TILER) | + BITFIELD_BIT(PANVK_SUBQUEUE_COMPUTE); + if (vk_stage == VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT) + return BITFIELD_BIT(PANVK_SUBQUEUE_FRAGMENT) | + BITFIELD_BIT(PANVK_SUBQUEUE_COMPUTE); + if (vk_stage == VK_PIPELINE_STAGE_2_HOST_BIT) + /* We need to map host to something, so map it to compute to not interfer + * with drawing. */ + return BITFIELD_BIT(PANVK_SUBQUEUE_COMPUTE); + + uint32_t result = vk_stages_to_subqueue_mask(vk_stage, SYNC_SCOPE_FIRST); + + /* All stages should map to at least one subqueue. */ + assert(util_bitcount(result) > 0); + + return result; +} + static void panvk_cs_write_ts_info(struct panvk_cmd_buffer *cmd, VkPipelineStageFlags2 stage, @@ -386,7 +411,7 @@ panvk_cs_write_ts_info(struct panvk_cmd_buffer *cmd, uint64_t ts_info = panvk_timestamp_info_encode( stage == VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT ? PANVK_QUERY_TS_OP_MIN : PANVK_QUERY_TS_OP_MAX, - vk_stage_to_subqueue_mask(stage)); + vk_stage_to_timestamp_subqueue_mask(stage)); cs_move64_to(b, info, ts_info); for (uint32_t query = first_query; query < first_query + n_views; ++query) { @@ -431,7 +456,7 @@ panvk_cs_defer_timestamp(struct panvk_cmd_buffer *cmd, /* Deferring top of pipe doesn't make sense. */ assert(VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT != stage); - const uint32_t write_sq_mask = vk_stage_to_subqueue_mask(stage); + const uint32_t write_sq_mask = vk_stage_to_timestamp_subqueue_mask(stage); const uint32_t n_views = MAX2(1, util_bitcount(cmd->state.gfx.render.view_mask)); @@ -480,7 +505,7 @@ panvk_cs_write_timestamp(struct panvk_cmd_buffer *cmd, { struct panvk_device *dev = to_panvk_device(cmd->vk.base.device); - const uint32_t write_sq_mask = vk_stage_to_subqueue_mask(stage); + const uint32_t write_sq_mask = vk_stage_to_timestamp_subqueue_mask(stage); const uint32_t n_views = MAX2(1, util_bitcount(cmd->state.gfx.render.view_mask)); @@ -512,7 +537,7 @@ panvk_cmd_write_timestamp_query(struct panvk_cmd_buffer *cmd, struct panvk_query_pool *pool, uint32_t query) { /* Store the actual timestamp values per subqueue. */ - const uint32_t write_sq_mask = vk_stage_to_subqueue_mask(stage); + const uint32_t write_sq_mask = vk_stage_to_timestamp_subqueue_mask(stage); /* The timestamp has to be written after RUN_FRAGMENT if we are inside * a renderpass at the moment and cover the F subqueue.