gallium/cso_context: remove cso_delete_xxx_shader helpers to fix the live cache

With the live shader cache, equivalent shaders can be backed by the same
CSO. This breaks the logic that identifies whether the shader being deleted
is bound.

For example, having shaders A and B, you can bind shader A and delete
shader B. Deleting shader B will unbind shader A if they are equivalent.

Pierre-Eric figured out the root cause for this issue.

Fixes: 0db74f479b - radeonsi: use the live shader cache
Closes: #2596

Acked-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Tested-by: Marge Bot <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4078>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4078>
(cherry picked from commit 2dc300421d)
This commit is contained in:
Marek Olšák 2020-03-05 15:09:28 -05:00 committed by Dylan Baker
parent e2db4624b7
commit 35dbf55ada
11 changed files with 75 additions and 107 deletions

View file

@ -1471,7 +1471,7 @@
"description": "gallium/cso_context: remove cso_delete_xxx_shader helpers to fix the live cache",
"nominated": true,
"nomination_type": 1,
"resolution": 0,
"resolution": 1,
"master_sha": null,
"because_sha": "0db74f479b9c5efe52c5d021fe04ba5ce1f4e1bd"
},

View file

@ -662,16 +662,6 @@ void cso_set_fragment_shader_handle(struct cso_context *ctx, void *handle )
}
}
void cso_delete_fragment_shader(struct cso_context *ctx, void *handle )
{
if (handle == ctx->fragment_shader) {
/* unbind before deleting */
ctx->pipe->bind_fs_state(ctx->pipe, NULL);
ctx->fragment_shader = NULL;
}
ctx->pipe->delete_fs_state(ctx->pipe, handle);
}
static void
cso_save_fragment_shader(struct cso_context *ctx)
{
@ -698,16 +688,6 @@ void cso_set_vertex_shader_handle(struct cso_context *ctx, void *handle)
}
}
void cso_delete_vertex_shader(struct cso_context *ctx, void *handle )
{
if (handle == ctx->vertex_shader) {
/* unbind before deleting */
ctx->pipe->bind_vs_state(ctx->pipe, NULL);
ctx->vertex_shader = NULL;
}
ctx->pipe->delete_vs_state(ctx->pipe, handle);
}
static void
cso_save_vertex_shader(struct cso_context *ctx)
{
@ -914,16 +894,6 @@ void cso_set_geometry_shader_handle(struct cso_context *ctx, void *handle)
}
}
void cso_delete_geometry_shader(struct cso_context *ctx, void *handle)
{
if (handle == ctx->geometry_shader) {
/* unbind before deleting */
ctx->pipe->bind_gs_state(ctx->pipe, NULL);
ctx->geometry_shader = NULL;
}
ctx->pipe->delete_gs_state(ctx->pipe, handle);
}
static void
cso_save_geometry_shader(struct cso_context *ctx)
{
@ -959,16 +929,6 @@ void cso_set_tessctrl_shader_handle(struct cso_context *ctx, void *handle)
}
}
void cso_delete_tessctrl_shader(struct cso_context *ctx, void *handle)
{
if (handle == ctx->tessctrl_shader) {
/* unbind before deleting */
ctx->pipe->bind_tcs_state(ctx->pipe, NULL);
ctx->tessctrl_shader = NULL;
}
ctx->pipe->delete_tcs_state(ctx->pipe, handle);
}
static void
cso_save_tessctrl_shader(struct cso_context *ctx)
{
@ -1004,16 +964,6 @@ void cso_set_tesseval_shader_handle(struct cso_context *ctx, void *handle)
}
}
void cso_delete_tesseval_shader(struct cso_context *ctx, void *handle)
{
if (handle == ctx->tesseval_shader) {
/* unbind before deleting */
ctx->pipe->bind_tes_state(ctx->pipe, NULL);
ctx->tesseval_shader = NULL;
}
ctx->pipe->delete_tes_state(ctx->pipe, handle);
}
static void
cso_save_tesseval_shader(struct cso_context *ctx)
{
@ -1049,16 +999,6 @@ void cso_set_compute_shader_handle(struct cso_context *ctx, void *handle)
}
}
void cso_delete_compute_shader(struct cso_context *ctx, void *handle)
{
if (handle == ctx->compute_shader) {
/* unbind before deleting */
ctx->pipe->bind_compute_state(ctx->pipe, NULL);
ctx->compute_shader = NULL;
}
ctx->pipe->delete_compute_state(ctx->pipe, handle);
}
static void
cso_set_vertex_elements_direct(struct cso_context *ctx,
unsigned count,

View file

@ -103,27 +103,11 @@ void cso_set_stream_outputs(struct cso_context *ctx,
*/
void cso_set_fragment_shader_handle(struct cso_context *ctx, void *handle);
void cso_delete_fragment_shader(struct cso_context *ctx, void *handle );
void cso_set_vertex_shader_handle(struct cso_context *ctx, void *handle);
void cso_delete_vertex_shader(struct cso_context *ctx, void *handle );
void cso_set_geometry_shader_handle(struct cso_context *ctx, void *handle);
void cso_delete_geometry_shader(struct cso_context *ctx, void *handle);
void cso_set_tessctrl_shader_handle(struct cso_context *ctx, void *handle);
void cso_delete_tessctrl_shader(struct cso_context *ctx, void *handle);
void cso_set_tesseval_shader_handle(struct cso_context *ctx, void *handle);
void cso_delete_tesseval_shader(struct cso_context *ctx, void *handle);
void cso_set_compute_shader_handle(struct cso_context *ctx, void *handle);
void cso_delete_compute_shader(struct cso_context *ctx, void *handle);
void cso_set_framebuffer(struct cso_context *cso,

View file

@ -143,7 +143,7 @@ NineVertexShader9_dtor( struct NineVertexShader9 *This )
while (var_so && var_so->vdecl) {
if (var_so->cso) {
cso_delete_vertex_shader(This->base.device->cso_sw, var_so->cso );
This->base.device->pipe_sw->delete_vs_state(This->base.device->pipe_sw, var_so->cso);
}
var_so = var_so->next;
}

View file

@ -431,7 +431,7 @@ xa_shaders_create(struct xa_context *r)
}
static void
cache_destroy(struct cso_context *cso,
cache_destroy(struct pipe_context *pipe,
struct cso_hash *hash, unsigned processor)
{
struct cso_hash_iter iter = cso_hash_first_node(hash);
@ -440,9 +440,9 @@ cache_destroy(struct cso_context *cso,
void *shader = (void *)cso_hash_iter_data(iter);
if (processor == PIPE_SHADER_FRAGMENT) {
cso_delete_fragment_shader(cso, shader);
pipe->delete_fs_state(pipe, shader);
} else if (processor == PIPE_SHADER_VERTEX) {
cso_delete_vertex_shader(cso, shader);
pipe->delete_vs_state(pipe, shader);
}
iter = cso_hash_erase(hash, iter);
}
@ -452,8 +452,8 @@ cache_destroy(struct cso_context *cso,
void
xa_shaders_destroy(struct xa_shaders *sc)
{
cache_destroy(sc->r->cso, sc->vs_hash, PIPE_SHADER_VERTEX);
cache_destroy(sc->r->cso, sc->fs_hash, PIPE_SHADER_FRAGMENT);
cache_destroy(sc->r->pipe, sc->vs_hash, PIPE_SHADER_VERTEX);
cache_destroy(sc->r->pipe, sc->fs_hash, PIPE_SHADER_FRAGMENT);
FREE(sc);
}

View file

@ -85,19 +85,19 @@ void
st_destroy_clear(struct st_context *st)
{
if (st->clear.fs) {
cso_delete_fragment_shader(st->cso_context, st->clear.fs);
st->pipe->delete_fs_state(st->pipe, st->clear.fs);
st->clear.fs = NULL;
}
if (st->clear.vs) {
cso_delete_vertex_shader(st->cso_context, st->clear.vs);
st->pipe->delete_vs_state(st->pipe, st->clear.vs);
st->clear.vs = NULL;
}
if (st->clear.vs_layered) {
cso_delete_vertex_shader(st->cso_context, st->clear.vs_layered);
st->pipe->delete_vs_state(st->pipe, st->clear.vs_layered);
st->clear.vs_layered = NULL;
}
if (st->clear.gs_layered) {
cso_delete_geometry_shader(st->cso_context, st->clear.gs_layered);
st->pipe->delete_gs_state(st->pipe, st->clear.gs_layered);
st->clear.gs_layered = NULL;
}
}

View file

@ -1915,12 +1915,11 @@ st_destroy_drawpix(struct st_context *st)
for (i = 0; i < ARRAY_SIZE(st->drawpix.zs_shaders); i++) {
if (st->drawpix.zs_shaders[i])
cso_delete_fragment_shader(st->cso_context,
st->drawpix.zs_shaders[i]);
st->pipe->delete_fs_state(st->pipe, st->drawpix.zs_shaders[i]);
}
if (st->passthrough_vs)
cso_delete_vertex_shader(st->cso_context, st->passthrough_vs);
st->pipe->delete_vs_state(st->pipe, st->passthrough_vs);
/* Free cache data */
for (i = 0; i < ARRAY_SIZE(st->drawpix_cache.entries); i++) {

View file

@ -360,7 +360,7 @@ st_destroy_drawtex(struct st_context *st)
{
GLuint i;
for (i = 0; i < NumCachedShaders; i++) {
cso_delete_vertex_shader(st->cso_context, CachedShaders[i].handle);
st->pipe->delete_vs_state(st->pipe, CachedShaders[i].handle);
}
NumCachedShaders = 0;
}

View file

@ -396,22 +396,22 @@ free_zombie_shaders(struct st_context *st)
switch (entry->type) {
case PIPE_SHADER_VERTEX:
cso_delete_vertex_shader(st->cso_context, entry->shader);
st->pipe->delete_vs_state(st->pipe, entry->shader);
break;
case PIPE_SHADER_FRAGMENT:
cso_delete_fragment_shader(st->cso_context, entry->shader);
st->pipe->delete_fs_state(st->pipe, entry->shader);
break;
case PIPE_SHADER_GEOMETRY:
cso_delete_geometry_shader(st->cso_context, entry->shader);
st->pipe->delete_gs_state(st->pipe, entry->shader);
break;
case PIPE_SHADER_TESS_CTRL:
cso_delete_tessctrl_shader(st->cso_context, entry->shader);
st->pipe->delete_tcs_state(st->pipe, entry->shader);
break;
case PIPE_SHADER_TESS_EVAL:
cso_delete_tesseval_shader(st->cso_context, entry->shader);
st->pipe->delete_tes_state(st->pipe, entry->shader);
break;
case PIPE_SHADER_COMPUTE:
cso_delete_compute_shader(st->cso_context, entry->shader);
st->pipe->delete_compute_state(st->pipe, entry->shader);
break;
default:
unreachable("invalid shader type in free_zombie_shaders()");

View file

@ -829,7 +829,7 @@ st_destroy_pbo_helpers(struct st_context *st)
for (i = 0; i < ARRAY_SIZE(st->pbo.upload_fs); ++i) {
if (st->pbo.upload_fs[i]) {
cso_delete_fragment_shader(st->cso_context, st->pbo.upload_fs[i]);
st->pipe->delete_fs_state(st->pipe, st->pbo.upload_fs[i]);
st->pbo.upload_fs[i] = NULL;
}
}
@ -837,19 +837,19 @@ st_destroy_pbo_helpers(struct st_context *st)
for (i = 0; i < ARRAY_SIZE(st->pbo.download_fs); ++i) {
for (unsigned j = 0; j < ARRAY_SIZE(st->pbo.download_fs[0]); ++j) {
if (st->pbo.download_fs[i][j]) {
cso_delete_fragment_shader(st->cso_context, st->pbo.download_fs[i][j]);
st->pipe->delete_fs_state(st->pipe, st->pbo.download_fs[i][j]);
st->pbo.download_fs[i][j] = NULL;
}
}
}
if (st->pbo.gs) {
cso_delete_geometry_shader(st->cso_context, st->pbo.gs);
st->pipe->delete_gs_state(st->pipe, st->pbo.gs);
st->pbo.gs = NULL;
}
if (st->pbo.vs) {
cso_delete_vertex_shader(st->cso_context, st->pbo.vs);
st->pipe->delete_vs_state(st->pipe, st->pbo.vs);
st->pbo.vs = NULL;
}
}

View file

@ -228,22 +228,22 @@ delete_variant(struct st_context *st, struct st_variant *v, GLenum target)
*/
switch (target) {
case GL_VERTEX_PROGRAM_ARB:
cso_delete_vertex_shader(st->cso_context, v->driver_shader);
st->pipe->delete_vs_state(st->pipe, v->driver_shader);
break;
case GL_TESS_CONTROL_PROGRAM_NV:
cso_delete_tessctrl_shader(st->cso_context, v->driver_shader);
st->pipe->delete_tcs_state(st->pipe, v->driver_shader);
break;
case GL_TESS_EVALUATION_PROGRAM_NV:
cso_delete_tesseval_shader(st->cso_context, v->driver_shader);
st->pipe->delete_tes_state(st->pipe, v->driver_shader);
break;
case GL_GEOMETRY_PROGRAM_NV:
cso_delete_geometry_shader(st->cso_context, v->driver_shader);
st->pipe->delete_gs_state(st->pipe, v->driver_shader);
break;
case GL_FRAGMENT_PROGRAM_ARB:
cso_delete_fragment_shader(st->cso_context, v->driver_shader);
st->pipe->delete_fs_state(st->pipe, v->driver_shader);
break;
case GL_COMPUTE_PROGRAM_NV:
cso_delete_compute_shader(st->cso_context, v->driver_shader);
st->pipe->delete_compute_state(st->pipe, v->driver_shader);
break;
default:
unreachable("bad shader type in delete_basic_variant");
@ -262,6 +262,39 @@ delete_variant(struct st_context *st, struct st_variant *v, GLenum target)
free(v);
}
static void
st_unbind_program(struct st_context *st, struct st_program *p)
{
/* Unbind the shader in cso_context and re-bind in st/mesa. */
switch (p->Base.info.stage) {
case MESA_SHADER_VERTEX:
cso_set_vertex_shader_handle(st->cso_context, NULL);
st->dirty |= ST_NEW_VS_STATE;
break;
case MESA_SHADER_TESS_CTRL:
cso_set_tessctrl_shader_handle(st->cso_context, NULL);
st->dirty |= ST_NEW_TCS_STATE;
break;
case MESA_SHADER_TESS_EVAL:
cso_set_tesseval_shader_handle(st->cso_context, NULL);
st->dirty |= ST_NEW_TES_STATE;
break;
case MESA_SHADER_GEOMETRY:
cso_set_geometry_shader_handle(st->cso_context, NULL);
st->dirty |= ST_NEW_GS_STATE;
break;
case MESA_SHADER_FRAGMENT:
cso_set_fragment_shader_handle(st->cso_context, NULL);
st->dirty |= ST_NEW_FS_STATE;
break;
case MESA_SHADER_COMPUTE:
cso_set_compute_shader_handle(st->cso_context, NULL);
st->dirty |= ST_NEW_CS_STATE;
break;
default:
unreachable("invalid shader type");
}
}
/**
* Free all basic program variants.
@ -271,6 +304,12 @@ st_release_variants(struct st_context *st, struct st_program *p)
{
struct st_variant *v;
/* If we are releasing shaders, re-bind them, because we don't
* know which shaders are bound in the driver.
*/
if (p->variants)
st_unbind_program(st, p);
for (v = p->variants; v; ) {
struct st_variant *next = v->next;
delete_variant(st, v, p->Base.Target);
@ -1770,10 +1809,16 @@ destroy_program_variants(struct st_context *st, struct gl_program *target)
struct st_program *p = st_program(target);
struct st_variant *v, **prevPtr = &p->variants;
bool unbound = false;
for (v = p->variants; v; ) {
struct st_variant *next = v->next;
if (v->st == st) {
if (!unbound) {
st_unbind_program(st, p);
unbound = true;
}
/* unlink from list */
*prevPtr = next;
/* destroy this variant */