panvk: refactor vk_stage_to_subqueue_mask

- rename vk_stage_to_subqueue_mask -> vk_stages_to_subqueue_mask
- handle stage masks instead of single stages.
- Add which sync scope it is reading to better reason with the mask semantics.
- Handle ALL_COMMANDS as well as TOP/BOTTOM (using sync scopes)
- add timestamp utility vk_stage_to_timestamp_subqueue_mask

Reviewed-by: Lars-Ivar Hesselberg Simonsen <lars-ivar.simonsen@arm.com>
Reviewed-by: Yiwei Zhang <zzyiwei@chromium.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/37810>
This commit is contained in:
Aksel Hjerpbakk 2025-10-13 13:27:09 +00:00 committed by Marge Bot
parent 9fde755357
commit 1381228329
2 changed files with 59 additions and 26 deletions

View file

@ -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;
}

View file

@ -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.