From 1d8847afcf37964fa2d31b8ebb8c6ef8fd7d4674 Mon Sep 17 00:00:00 2001 From: Lionel Landwerlin Date: Tue, 9 Sep 2025 14:22:56 +0300 Subject: [PATCH] anv: fix streamout config comparison Signed-off-by: Lionel Landwerlin Fixes: e76ed91d3f ("anv: switch over to runtime pipelines") Acked-by: Mike Blumenkrantz Part-of: --- .../drivers/zink/ci/zink-anv-adl-fails.txt | 1 - src/intel/vulkan/anv_cmd_buffer.c | 93 ++++++++++--------- 2 files changed, 49 insertions(+), 45 deletions(-) diff --git a/src/gallium/drivers/zink/ci/zink-anv-adl-fails.txt b/src/gallium/drivers/zink/ci/zink-anv-adl-fails.txt index b84f646f84a..1bc8b8b0b9c 100644 --- a/src/gallium/drivers/zink/ci/zink-anv-adl-fails.txt +++ b/src/gallium/drivers/zink/ci/zink-anv-adl-fails.txt @@ -668,7 +668,6 @@ wayland-dEQP-EGL.functional.resize.surface_size.stretch_width,Fail # shader objects #13839 -KHR-GL46.separable_programs_tf.tessellation_active,Fail spec@arb_fragment_program@fog-modes,Crash spec@arb_occlusion_query@occlusion_query_meta_fragments,Fail spec@arb_occlusion_query@occlusion_query_meta_save,Fail diff --git a/src/intel/vulkan/anv_cmd_buffer.c b/src/intel/vulkan/anv_cmd_buffer.c index 66e3c9966f8..416436864b3 100644 --- a/src/intel/vulkan/anv_cmd_buffer.c +++ b/src/intel/vulkan/anv_cmd_buffer.c @@ -53,6 +53,7 @@ anv_cmd_state_init(struct anv_cmd_buffer *cmd_buffer) state->gfx.restart_index = UINT32_MAX; state->gfx.object_preemption = true; state->gfx.dirty = 0; + state->gfx.streamout_stage = MESA_SHADER_NONE; state->compute.pixel_async_compute_thread_limit = UINT8_MAX; state->compute.z_pass_async_compute_thread_limit = UINT8_MAX; @@ -1480,7 +1481,7 @@ bind_graphics_shaders(struct anv_cmd_buffer *cmd_buffer, gfx->active_stages = 0; gfx->instance_multiplier = 0; - mesa_shader_stage new_streamout_stage = -1; + mesa_shader_stage new_streamout_stage = MESA_SHADER_NONE; /* Find the last pre-rasterization stage */ for (uint32_t i = 0; i < ANV_GRAPHICS_SHADER_STAGE_COUNT; i++) { mesa_shader_stage s = ANV_GRAPHICS_SHADER_STAGE_COUNT - i - 1; @@ -1500,6 +1501,53 @@ bind_graphics_shaders(struct anv_cmd_buffer *cmd_buffer, new_streamout_stage = MAX2(new_streamout_stage, s); } +#define diff_fix_state_stage(bit, name, old_stage, shader) \ + do { \ + /* Fixed states should always have matching sizes */ \ + assert(old_stage == MESA_SHADER_NONE || \ + gfx->shaders[old_stage] == NULL || \ + gfx->shaders[old_stage]->name.len == shader->name.len); \ + /* Don't bother memcmp if the state is already dirty */ \ + if (!BITSET_TEST(hw_state->pack_dirty, ANV_GFX_STATE_##bit) && \ + (old_stage == MESA_SHADER_NONE || \ + gfx->shaders[old_stage] == NULL || \ + memcmp(&gfx->shaders[old_stage]->cmd_data[ \ + gfx->shaders[old_stage]->name.offset], \ + &shader->cmd_data[ \ + shader->name.offset], \ + 4 * shader->name.len) != 0)) \ + BITSET_SET(hw_state->pack_dirty, ANV_GFX_STATE_##bit); \ + } while (0) +#define diff_var_state_stage(bit, name, old_stage,shader) \ + do { \ + /* Don't bother memcmp if the state is already dirty */ \ + /* Also if the new state is empty, avoid marking dirty */ \ + if (!BITSET_TEST(hw_state->pack_dirty, ANV_GFX_STATE_##bit) && \ + shader->name.len != 0 && \ + (gfx->shaders[old_stage] == NULL || \ + gfx->shaders[old_stage]->name.len != shader->name.len || \ + memcmp(&gfx->shaders[old_stage]->cmd_data[ \ + gfx->shaders[old_stage]->name.offset], \ + &shader->cmd_data[shader->name.offset], \ + 4 * shader->name.len) != 0)) \ + BITSET_SET(hw_state->pack_dirty, ANV_GFX_STATE_##bit); \ + } while (0) + + if (new_streamout_stage != MESA_SHADER_NONE) { + /* Compare the stream instructions first because we go through the + * stages of shaders and update gfx->shaders[], we can't compare the old + * streamout configuration from the old vertex shader with the new + * configuration of the tessellation shader. + */ + diff_fix_state_stage(STREAMOUT, so, gfx->streamout_stage, new_shaders[new_streamout_stage]); + diff_var_state_stage(SO_DECL_LIST, so_decl_list, gfx->streamout_stage, new_shaders[new_streamout_stage]); + + gfx->streamout_stage = new_streamout_stage; + } + +#undef diff_fix_state_stage +#undef diff_var_state_stage + for (uint32_t s = 0; s < ANV_GRAPHICS_SHADER_STAGE_COUNT; s++) { struct anv_shader *shader = new_shaders[s]; @@ -1547,39 +1595,6 @@ bind_graphics_shaders(struct anv_cmd_buffer *cmd_buffer, 4 * shader->name.len) != 0)) \ BITSET_SET(hw_state->pack_dirty, ANV_GFX_STATE_##bit); \ } while (0) -#define diff_fix_state_stage(bit, name, old_stage) \ - do { \ - /* Fixed states should always have matching sizes */ \ - assert(old_stage == MESA_SHADER_NONE || \ - gfx->shaders[old_stage] == NULL || \ - gfx->shaders[old_stage]->name.len == shader->name.len); \ - /* Don't bother memcmp if the state is already dirty */ \ - if (!BITSET_TEST(hw_state->pack_dirty, \ - ANV_GFX_STATE_##bit) && \ - (old_stage == MESA_SHADER_NONE || \ - gfx->shaders[old_stage] == NULL || \ - memcmp(&gfx->shaders[old_stage]->cmd_data[ \ - gfx->shaders[old_stage]->name.offset], \ - &shader->cmd_data[ \ - shader->name.offset], \ - 4 * shader->name.len) != 0)) \ - BITSET_SET(hw_state->pack_dirty, ANV_GFX_STATE_##bit); \ - } while (0) -#define diff_var_state_stage(bit, name, old_stage) \ - do { \ - /* Don't bother memcmp if the state is already dirty */ \ - /* Also if the new state is empty, avoid marking dirty */ \ - if (!BITSET_TEST(hw_state->pack_dirty, \ - ANV_GFX_STATE_##bit) && \ - shader->name.len != 0 && \ - (gfx->shaders[old_stage] == NULL || \ - gfx->shaders[old_stage]->name.len != shader->name.len || \ - memcmp(&gfx->shaders[old_stage]->cmd_data[ \ - gfx->shaders[old_stage]->name.offset], \ - &shader->cmd_data[shader->name.offset], \ - 4 * shader->name.len) != 0)) \ - BITSET_SET(hw_state->pack_dirty, ANV_GFX_STATE_##bit); \ - } while (0) switch (s) { case MESA_SHADER_VERTEX: @@ -1656,21 +1671,11 @@ bind_graphics_shaders(struct anv_cmd_buffer *cmd_buffer, UNREACHABLE("Invalid shader stage"); } - /* Only diff those field on the streamout stage */ - if (s == new_streamout_stage) { - diff_fix_state_stage(STREAMOUT, so, gfx->streamout_stage); - diff_var_state_stage(SO_DECL_LIST, so_decl_list, gfx->streamout_stage); - } - gfx->shaders[s] = shader; } - gfx->streamout_stage = new_streamout_stage; - #undef diff_fix_state #undef diff_var_state -#undef diff_fix_state_stage -#undef diff_var_state_stage update_push_descriptor_flags(&gfx->base, cmd_buffer->state.gfx.shaders,