anv: further optimize dirty state after secondary emission

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Reviewed-by: Ivan Briano <ivan.briano@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/41581>
This commit is contained in:
Lionel Landwerlin 2026-05-18 13:40:57 +03:00 committed by Marge Bot
parent 94a7d50433
commit d6751f2a3b
6 changed files with 30 additions and 4 deletions

View file

@ -1984,6 +1984,7 @@ enum anv_gfx_state_bits {
ANV_GFX_STATE_WM,
ANV_GFX_STATE_WM_DEPTH_STENCIL,
ANV_GFX_STATE_PS_EXTRA,
ANV_GFX_STATE_PMA_FIX, /* Fake state to implement workaround */
ANV_GFX_STATE_WA_18019816803, /* Fake state to implement workaround */
ANV_GFX_STATE_WA_14018283232, /* Fake state to implement workaround */
@ -2492,6 +2493,9 @@ struct anv_gfx_dynamic_state {
/** Dirty bits of what needs to be reemitted */
BITSET_DECLARE(emit_dirty, ANV_GFX_STATE_MAX);
/** Emitted bits */
BITSET_DECLARE(emitted, ANV_GFX_STATE_MAX);
};
enum anv_internal_kernel_name {

View file

@ -432,6 +432,9 @@ blorp_exec_on_render(struct blorp_batch *batch,
BITSET_SET(hw_state->emit_dirty, ANV_GFX_STATE_PS_BLEND);
}
/* Add the flagged instructions as emitted */
BITSET_OR(hw_state->emitted, hw_state->emitted, hw_state->emit_dirty);
anv_cmd_dirty_mask_t dirty = ~(ANV_CMD_DIRTY_INDEX_BUFFER |
ANV_CMD_DIRTY_XFB_ENABLE |
ANV_CMD_DIRTY_OCCLUSION_QUERY_ACTIVE |

View file

@ -4415,6 +4415,20 @@ genX(CmdExecuteCommands)(
container->state.compute.trace_rays_active |=
secondary->state.compute.trace_rays_active;
/* For each GFX instruction emitted in the secondary, mark it dirty in
* the container, so it's reemited. Even though Vulkan spec says that
* after a secondary command buffer is executed the state in the primary
* is undefined, our emission optimization code will avoid dirtying an
* instruction if the values inside an instruction haven't changed, but
* it doesn't see that this was potentially changed by the secondary.
*
* TODO: do an ultimate version of this by diffing secondary/container
* emitted instructions
*/
BITSET_OR(container->state.gfx.dyn_state.emit_dirty,
container->state.gfx.dyn_state.emit_dirty,
secondary->state.gfx.dyn_state.emitted);
}
/* The secondary isn't counted in our VF cache tracking so we need to
@ -4446,10 +4460,6 @@ genX(CmdExecuteCommands)(
memset(&container->state.gfx.urb_cfg, 0, sizeof(struct intel_urb_config));
/* Reemit all GFX instructions in container */
BITSET_OR(container->state.gfx.dyn_state.emit_dirty,
container->state.gfx.dyn_state.emit_dirty,
device->gfx_dirty_state);
if (container->device->vk.enabled_extensions.KHR_fragment_shading_rate) {
/* Also recompute the CPS_STATE offset */
struct vk_dynamic_graphics_state *dyn =

View file

@ -3646,6 +3646,9 @@ cmd_buffer_gfx_state_emission(struct anv_cmd_buffer *cmd_buffer)
mi_builder_set_mocs(&b, isl_mocs(&device->isl_dev, 0, false));
}
/* Save all the instructions we're about to emit */
BITSET_OR(hw_state->emitted, hw_state->emitted, hw_state->emit_dirty);
#if INTEL_WA_16011107343_GFX_VER
/* Will be emitted in front of every draw instead */
if (intel_needs_workaround(device->info, 16011107343) &&

View file

@ -373,6 +373,9 @@ genX(emit_so_memcpy_fini)(struct anv_memcpy_state *state,
BITSET_SET(hw_state->emit_dirty, ANV_GFX_STATE_TASK_CONTROL);
}
/* Add the flagged instructions as emitted */
BITSET_OR(hw_state->emitted, hw_state->emitted, hw_state->emit_dirty);
state->cmd_buffer->state.gfx.dirty |=
~(ANV_CMD_DIRTY_ALL_SHADERS(state->device) |
ANV_CMD_DIRTY_INDEX_BUFFER |

View file

@ -358,6 +358,9 @@ genX(emit_simpler_shader_init_fragment)(struct anv_simple_shader *state)
BITSET_SET(hw_state->emit_dirty, ANV_GFX_STATE_TASK_CONTROL);
}
/* Add the flagged instructions as emitted */
BITSET_OR(hw_state->emitted, hw_state->emitted, hw_state->emit_dirty);
/* Update urb config after simple shader. */
memcpy(&state->cmd_buffer->state.gfx.urb_cfg, &urb_cfg,
sizeof(urb_cfg));