gallium: Properly handle non-contiguous used sampler view indexes
Some checks are pending
macOS-CI / macOS-CI (dri) (push) Waiting to run
macOS-CI / macOS-CI (xlib) (push) Waiting to run

There is nothing guaranteeing that the currently used sampler view
indexes will be contiguous, which means the resulting extra sampler
views created by st_get_sampler_views may not be placed at the end of
the resulting array. Therefore, the exact indexes of these views must
be passed to the caller for releasing instead of simply assuming that
they will always be placed at the end.

Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Reviewed-by: Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/13363
Fixes: 73da0dcddc ("gallium: eliminate frontend refcounting from samplerviews")
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/36397>
This commit is contained in:
Myrrh Periwinkle 2025-07-27 17:47:40 +07:00 committed by Marge Bot
parent 9fc2f71501
commit abcd02a07d
5 changed files with 21 additions and 21 deletions

View file

@ -91,7 +91,7 @@ st_get_sampler_views(struct st_context *st,
enum pipe_shader_type shader_stage,
const struct gl_program *prog,
struct pipe_sampler_view **sampler_views,
unsigned *num_owned_views)
unsigned *extra_sampler_views)
{
struct pipe_context *pipe = st->pipe;
const GLuint old_max = st->state.num_sampler_views[shader_stage];
@ -100,7 +100,7 @@ st_get_sampler_views(struct st_context *st,
GLbitfield free_slots = ~prog->SamplersUsed;
GLbitfield external_samplers_used = prog->ExternalSamplersUsed;
GLuint unit;
*num_owned_views = 0;
*extra_sampler_views = 0;
if (samplers_used == 0x0 && old_max == 0)
return 0;
@ -302,7 +302,7 @@ st_get_sampler_views(struct st_context *st,
}
if (extra)
(*num_owned_views) = extra;
(*extra_sampler_views) |= 1 << extra;
num_textures = MAX2(num_textures, extra + 1);
}
@ -317,9 +317,9 @@ update_textures(struct st_context *st,
{
struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS];
struct pipe_context *pipe = st->pipe;
unsigned num_owned_views = 0;
unsigned extra_sampler_views = 0;
unsigned num_textures =
st_get_sampler_views(st, shader_stage, prog, sampler_views, &num_owned_views);
st_get_sampler_views(st, shader_stage, prog, sampler_views, &extra_sampler_views);
unsigned old_num_textures = st->state.num_sampler_views[shader_stage];
unsigned num_unbind = old_num_textures > num_textures ?
@ -331,9 +331,9 @@ update_textures(struct st_context *st,
/* release YUV views back to driver */
if (pipe->sampler_view_release) {
unsigned base_idx = num_textures - num_owned_views;
for (unsigned i = 0; i < num_owned_views; i++)
pipe->sampler_view_release(pipe, sampler_views[base_idx + i]);
u_foreach_bit (i, extra_sampler_views) {
pipe->sampler_view_release(pipe, sampler_views[i]);
}
}
}

View file

@ -243,10 +243,10 @@ setup_render_state(struct gl_context *ctx,
/* user textures, plus the bitmap texture */
{
unsigned num_owned_views = 0;
unsigned extra_sampler_views = 0;
struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS];
unsigned num_views =
st_get_sampler_views(st, PIPE_SHADER_FRAGMENT, fp, sampler_views, &num_owned_views);
st_get_sampler_views(st, PIPE_SHADER_FRAGMENT, fp, sampler_views, &extra_sampler_views);
num_views = MAX2(fpv->bitmap_sampler + 1, num_views);
sampler_views[fpv->bitmap_sampler] = sv;

View file

@ -849,11 +849,11 @@ draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
/* user textures, plus the drawpix textures */
if (fpv) {
struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS];
unsigned num_owned_views = 0;
unsigned extra_sampler_views = 0;
/* drawing a color image */
unsigned num_views =
st_get_sampler_views(st, PIPE_SHADER_FRAGMENT,
ctx->FragmentProgram._Current, sampler_views, &num_owned_views);
ctx->FragmentProgram._Current, sampler_views, &extra_sampler_views);
num_views = MAX3(fpv->drawpix_sampler + 1, fpv->pixelmap_sampler + 1,
num_views);
@ -866,9 +866,9 @@ draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
st->state.num_sampler_views[PIPE_SHADER_FRAGMENT] = num_views;
/* release YUV views back to driver */
unsigned base_idx = num_views - num_owned_views;
for (unsigned i = 0; i < num_owned_views; i++)
pipe->sampler_view_release(pipe, sampler_views[base_idx + i]);
u_foreach_bit (i, extra_sampler_views) {
pipe->sampler_view_release(pipe, sampler_views[i]);
}
} else {
/* drawing a depth/stencil image */
pipe->set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, 0, num_sampler_view,

View file

@ -259,9 +259,9 @@ st_feedback_draw_vbo(struct gl_context *ctx,
/* sampler views */
struct pipe_sampler_view *views[PIPE_MAX_SAMPLERS];
unsigned num_owned_views = 0;
unsigned extra_sampler_views = 0;
unsigned num_views =
st_get_sampler_views(st, PIPE_SHADER_VERTEX, prog, views, &num_owned_views);
st_get_sampler_views(st, PIPE_SHADER_VERTEX, prog, views, &extra_sampler_views);
draw_set_sampler_views(draw, PIPE_SHADER_VERTEX, views, num_views);
@ -423,9 +423,9 @@ st_feedback_draw_vbo(struct gl_context *ctx,
draw_set_sampler_views(draw, PIPE_SHADER_VERTEX, NULL, 0);
/* release YUV views back to driver */
unsigned base_idx = num_views - num_owned_views;
for (unsigned i = 0; i < num_owned_views; i++)
pipe->sampler_view_release(pipe, views[base_idx + i]);
u_foreach_bit (i, extra_sampler_views) {
pipe->sampler_view_release(pipe, views[i]);
}
for (unsigned i = 0; i < prog->info.num_ssbos; i++) {
if (ssbo_transfer[i]) {

View file

@ -257,7 +257,7 @@ st_get_sampler_views(struct st_context *st,
enum pipe_shader_type shader_stage,
const struct gl_program *prog,
struct pipe_sampler_view **sampler_views,
unsigned *num_owned_views);
unsigned *extra_sampler_views);
void
st_make_bound_samplers_resident(struct st_context *st,