From cbc172ecb26da0928e5e3c8133c5cc358e1af994 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Wed, 11 Mar 2026 13:32:04 -0400 Subject: [PATCH] mesa/st/samplerview: explicitly block releasing in-use samplerviews st_texture_set_sampler_view() currently allows only one samplerview for a given texobj per context. in a scenario where the same texobj is bound multiple times with different samplerviews (e.g., SRGB) for the same draw like samplerviews[] = {view0, view1} then st_texture_set_sampler_view() will release view0 while creating view1 before either view is actually set to the driver, and then the driver will explode this is gross, but the best solution which avoids infinite memory ballooning from bufferview offsets is to pass through the array of views during creation to ensure that the cache doesn't try to prune a view it just created caught by Left 4 Dead 2 Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/15045 Reviewed-by: Timothy Arceri (cherry picked from commit 3264adf863f78778974aa85799df3febedd3eeab) Part-of: --- .pick_status.json | 2 +- src/mesa/main/texturebindless.c | 4 +-- src/mesa/state_tracker/st_atom_texture.c | 13 +++++++--- src/mesa/state_tracker/st_sampler_view.c | 33 +++++++++++++++++++----- src/mesa/state_tracker/st_sampler_view.h | 8 ++++-- src/mesa/state_tracker/st_texture.c | 2 +- src/mesa/state_tracker/st_texture.h | 4 ++- 7 files changed, 49 insertions(+), 17 deletions(-) diff --git a/.pick_status.json b/.pick_status.json index fef40d3177c..2b46034aa7d 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -974,7 +974,7 @@ "description": "mesa/st/samplerview: explicitly block releasing in-use samplerviews", "nominated": false, "nomination_type": 0, - "resolution": 4, + "resolution": 1, "main_sha": null, "because_sha": null, "notes": null diff --git a/src/mesa/main/texturebindless.c b/src/mesa/main/texturebindless.c index 24c1a71a564..9c8d4079ad9 100644 --- a/src/mesa/main/texturebindless.c +++ b/src/mesa/main/texturebindless.c @@ -237,9 +237,9 @@ new_texture_handle(struct gl_context *ctx, struct gl_texture_object *texObj, /* TODO: Clarify the interaction of ARB_bindless_texture and EXT_texture_sRGB_decode */ view = st_get_texture_sampler_view_from_stobj(st, texObj, sampObj, 0, - false); + false, 0, NULL); } else { - view = st_get_buffer_sampler_view_from_stobj(st, texObj); + view = st_get_buffer_sampler_view_from_stobj(st, texObj, 0, NULL); sampler.unnormalized_coords = 0; } diff --git a/src/mesa/state_tracker/st_atom_texture.c b/src/mesa/state_tracker/st_atom_texture.c index d721603d84d..d6ced6e38ad 100644 --- a/src/mesa/state_tracker/st_atom_texture.c +++ b/src/mesa/state_tracker/st_atom_texture.c @@ -58,7 +58,9 @@ struct pipe_sampler_view * st_update_single_texture(struct st_context *st, GLuint texUnit, bool glsl130_or_later, - bool ignore_srgb_decode) + bool ignore_srgb_decode, + unsigned num_norelease_views, + const struct pipe_sampler_view **norelease_views) { struct gl_context *ctx = st->ctx; struct gl_texture_object *texObj; @@ -69,7 +71,7 @@ st_update_single_texture(struct st_context *st, GLenum target = texObj->Target; if (unlikely(target == GL_TEXTURE_BUFFER)) - return st_get_buffer_sampler_view_from_stobj(st, texObj); + return st_get_buffer_sampler_view_from_stobj(st, texObj, num_norelease_views, norelease_views); if (!st_finalize_texture(ctx, st->pipe, texObj, 0) || !texObj->pt) return NULL; /* out of mem */ @@ -81,7 +83,8 @@ st_update_single_texture(struct st_context *st, return st_get_texture_sampler_view_from_stobj(st, texObj, _mesa_get_samplerobj(ctx, texUnit), glsl130_or_later, - ignore_srgb_decode); + ignore_srgb_decode, + num_norelease_views, norelease_views); } @@ -147,7 +150,9 @@ st_get_sampler_views(struct st_context *st, */ sampler_views[unit] = st_update_single_texture(st, prog->SamplerUnits[unit], glsl130, - texel_fetch_samplers & bit); + texel_fetch_samplers & bit, + /* prevent any of these views from being released */ + unit, (const struct pipe_sampler_view **)sampler_views); } /* For any external samplers with multiplaner YUV, stuff the additional diff --git a/src/mesa/state_tracker/st_sampler_view.c b/src/mesa/state_tracker/st_sampler_view.c index 2bca7ea2a5c..3ce2cc660e7 100644 --- a/src/mesa/state_tracker/st_sampler_view.c +++ b/src/mesa/state_tracker/st_sampler_view.c @@ -40,6 +40,18 @@ #include "st_format.h" #include "st_cb_texture.h" +static bool +can_release_samplerview(const struct pipe_sampler_view *view, + unsigned num_norelease_views, + const struct pipe_sampler_view **norelease_views) +{ + for (unsigned i = 0; i < num_norelease_views; i++) { + if (norelease_views[i] == view) + return false; + } + return true; +} + /** * Set the given view as the current context's view for the texture. * @@ -56,7 +68,9 @@ st_texture_set_sampler_view(struct st_context *st, struct gl_texture_object *stObj, struct pipe_sampler_view *view, bool glsl130_or_later, - bool locked) + bool locked, + unsigned num_norelease_views, + const struct pipe_sampler_view **norelease_views) { struct st_sampler_views *views; struct st_sampler_view *free = NULL; @@ -73,7 +87,8 @@ st_texture_set_sampler_view(struct st_context *st, /* Is the array entry used ? */ if (sv->view) { /* check if the context matches */ - if (sv->view->context == st->pipe) { + if (sv->view->context == st->pipe && + can_release_samplerview(sv->view, num_norelease_views, norelease_views)) { st->pipe->sampler_view_release(st->pipe, sv->view); sv->view = NULL; goto found; @@ -527,7 +542,9 @@ st_get_texture_sampler_view_from_stobj(struct st_context *st, struct gl_texture_object *texObj, const struct gl_sampler_object *samp, bool glsl130_or_later, - bool ignore_srgb_decode) + bool ignore_srgb_decode, + unsigned num_norelease_views, + const struct pipe_sampler_view **norelease_views) { struct st_sampler_view *sv; bool srgb_skip_decode = false; @@ -571,7 +588,8 @@ st_get_texture_sampler_view_from_stobj(struct st_context *st, view = st_texture_set_sampler_view(st, texObj, view, glsl130_or_later, - true); + true, + num_norelease_views, norelease_views); simple_mtx_unlock(&texObj->validate_mutex); return view; @@ -580,7 +598,9 @@ st_get_texture_sampler_view_from_stobj(struct st_context *st, struct pipe_sampler_view * st_get_buffer_sampler_view_from_stobj(struct st_context *st, - struct gl_texture_object *texObj) + struct gl_texture_object *texObj, + unsigned num_norelease_views, + const struct pipe_sampler_view **norelease_views) { struct st_sampler_view *sv; struct gl_buffer_object *stBuf = @@ -640,7 +660,8 @@ st_get_buffer_sampler_view_from_stobj(struct st_context *st, struct pipe_sampler_view *view = st->pipe->create_sampler_view(st->pipe, buf, &templ); - view = st_texture_set_sampler_view(st, texObj, view, false, false); + view = st_texture_set_sampler_view(st, texObj, view, false, false, + num_norelease_views, norelease_views); return view; } diff --git a/src/mesa/state_tracker/st_sampler_view.h b/src/mesa/state_tracker/st_sampler_view.h index 432da56061a..55eb47c1069 100644 --- a/src/mesa/state_tracker/st_sampler_view.h +++ b/src/mesa/state_tracker/st_sampler_view.h @@ -71,11 +71,15 @@ st_get_texture_sampler_view_from_stobj(struct st_context *st, struct gl_texture_object *stObj, const struct gl_sampler_object *samp, bool glsl130_or_later, - bool ignore_srgb_decode); + bool ignore_srgb_decode, + unsigned num_norelease_views, + const struct pipe_sampler_view **norelease_views); struct pipe_sampler_view * st_get_buffer_sampler_view_from_stobj(struct st_context *st, - struct gl_texture_object *stObj); + struct gl_texture_object *stObj, + unsigned num_norelease_views, + const struct pipe_sampler_view **norelease_views); enum pipe_format st_get_sampler_view_format(const struct st_context *st, diff --git a/src/mesa/state_tracker/st_texture.c b/src/mesa/state_tracker/st_texture.c index 5153b25226f..2a95b4da22d 100644 --- a/src/mesa/state_tracker/st_texture.c +++ b/src/mesa/state_tracker/st_texture.c @@ -546,7 +546,7 @@ st_create_texture_handle_from_unit(struct st_context *st, (prog->shader_program ? prog->shader_program->GLSL_Version : 0) >= 130; /* TODO: Clarify the interaction of ARB_bindless_texture and EXT_texture_sRGB_decode */ - view = st_update_single_texture(st, texUnit, glsl130, true); + view = st_update_single_texture(st, texUnit, glsl130, true, 0, NULL); if (!view) return 0; diff --git a/src/mesa/state_tracker/st_texture.h b/src/mesa/state_tracker/st_texture.h index 32ec55c704d..e92596d7073 100644 --- a/src/mesa/state_tracker/st_texture.h +++ b/src/mesa/state_tracker/st_texture.h @@ -249,7 +249,9 @@ st_convert_sampler_from_unit(const struct st_context *st, struct pipe_sampler_view * st_update_single_texture(struct st_context *st, GLuint texUnit, bool glsl130_or_later, - bool ignore_srgb_decode); + bool ignore_srgb_decode, + unsigned num_norelease_views, + const struct pipe_sampler_view **norelease_views); unsigned st_get_sampler_views(struct st_context *st,