mesa/st: fix zombie shader handling for non-current programs

for drivers that don't support PIPE_CAP_SHAREABLE_SHADERS,
the zombie shader mechanism is used, storing shaders to delete after
the next flush

the zombie mechanism also calls bind_*_state(pipe, NULL) during deletion,
however, which breaks drivers in the following scenario:

* create_all_shaders(pipe_A)
* bind_vs(pipe_A, vs_A)
* bind_fs(pipe_A, fs_A)
* draw(pipe_A)
* makeCurrent(pipe_B)
* delete_vs(pipe_B, vs_B)
  * vs_B must only be deleted on pipe_A
  * zombie_shader_add(pipe_A, vs_B)
* makeCurrent(pipe_A)
  * free_zombie_shaders(pipe_A)
    * bind_vs(pipe_A, NULL)
    * delete_vs(pipe_A, vs_B)
* draw(pipe_A)
* boom

the problem being that bind_vs(pipe_A, NULL) was called when deleting
vs_B, but it was actually vs_A which was bound

to solve this, just flag the shader state for updating and let st figure it out

Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/11122

cc: mesa-stable

Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/29680>
This commit is contained in:
Mike Blumenkrantz
2024-06-11 11:15:01 -04:00
committed by Marge Bot
parent 75777f1dc8
commit 95828d8901
+6 -6
View File
@@ -284,27 +284,27 @@ free_zombie_shaders(struct st_context *st)
switch (entry->type) {
case PIPE_SHADER_VERTEX:
st->pipe->bind_vs_state(st->pipe, NULL);
st->ctx->NewDriverState |= ST_NEW_VS_STATE;
st->pipe->delete_vs_state(st->pipe, entry->shader);
break;
case PIPE_SHADER_FRAGMENT:
st->pipe->bind_fs_state(st->pipe, NULL);
st->ctx->NewDriverState |= ST_NEW_FS_STATE;
st->pipe->delete_fs_state(st->pipe, entry->shader);
break;
case PIPE_SHADER_GEOMETRY:
st->pipe->bind_gs_state(st->pipe, NULL);
st->ctx->NewDriverState |= ST_NEW_GS_STATE;
st->pipe->delete_gs_state(st->pipe, entry->shader);
break;
case PIPE_SHADER_TESS_CTRL:
st->pipe->bind_tcs_state(st->pipe, NULL);
st->ctx->NewDriverState |= ST_NEW_TCS_STATE;
st->pipe->delete_tcs_state(st->pipe, entry->shader);
break;
case PIPE_SHADER_TESS_EVAL:
st->pipe->bind_tes_state(st->pipe, NULL);
st->ctx->NewDriverState |= ST_NEW_TES_STATE;
st->pipe->delete_tes_state(st->pipe, entry->shader);
break;
case PIPE_SHADER_COMPUTE:
st->pipe->bind_compute_state(st->pipe, NULL);
st->ctx->NewDriverState |= ST_NEW_CS_STATE;
st->pipe->delete_compute_state(st->pipe, entry->shader);
break;
default: