gallium: Make upload_cb0 return a releasebuf

pipe_upload_constant_buffer0() was immediately releasing the
u_upload_alloc() releasebuf.  But it is used in various call-
paths where the release needs to be deferred further.

Fixes crashes in firefox for any driver that uses the same
u_upload_mgr instance for pipe->const_uploader and
pipe->stream_uploader.

Fixes: b3133e250e ("gallium: add pipe_context::resource_release to eliminate buffer refcounting")
Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/14309
Signed-off-by: Rob Clark <rob.clark@oss.qualcomm.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/38896>
This commit is contained in:
Rob Clark 2025-12-10 14:44:20 -08:00 committed by Marge Bot
parent b2daaaec81
commit 51605bfac2
9 changed files with 56 additions and 27 deletions

View file

@ -106,18 +106,20 @@ hud_draw_colored_prims(struct hud_context *hud, unsigned prim,
hud->constants.translate[1] = (float) (yoffset * hud_scale);
hud->constants.scale[0] = hud_scale;
hud->constants.scale[1] = yscale * hud_scale;
pipe_upload_constant_buffer0(pipe, MESA_SHADER_VERTEX, &hud->constbuf);
struct pipe_resource *cb_releasebuf = NULL;
pipe_upload_constant_buffer0(pipe, MESA_SHADER_VERTEX, &hud->constbuf, &cb_releasebuf);
struct pipe_resource *releasebuf = NULL;
struct pipe_resource *vb_releasebuf = NULL;
u_upload_data(hud->pipe->stream_uploader, 0,
num_vertices * 2 * sizeof(float), 16, buffer,
&vbuffer.buffer_offset, &vbuffer.buffer.resource, &releasebuf);
&vbuffer.buffer_offset, &vbuffer.buffer.resource, &vb_releasebuf);
u_upload_unmap(hud->pipe->stream_uploader);
cso_set_vertex_buffers(cso, 1, &vbuffer);
cso_set_fragment_shader_handle(hud->cso, hud->fs_color);
cso_draw_arrays(cso, prim, 0, num_vertices);
pipe_resource_release(hud->pipe, releasebuf);
pipe_resource_release(hud->pipe, vb_releasebuf);
pipe_resource_release(hud->pipe, cb_releasebuf);
}
static void
@ -493,6 +495,7 @@ hud_draw_results(struct hud_context *hud, struct pipe_resource *tex)
const struct pipe_sampler_state *sampler_states[] =
{ &hud->font_sampler_state };
struct hud_pane *pane;
struct pipe_resource *releasebuf[3] = {};
if (!huds_visible)
return;
@ -580,7 +583,7 @@ hud_draw_results(struct hud_context *hud, struct pipe_resource *tex)
pipe->set_sampler_views(pipe, MESA_SHADER_FRAGMENT, 0, 1, 0,
&hud->font_sampler_view);
cso_set_samplers(cso, MESA_SHADER_FRAGMENT, 1, sampler_states);
pipe_upload_constant_buffer0(pipe, MESA_SHADER_VERTEX, &hud->constbuf);
pipe_upload_constant_buffer0(pipe, MESA_SHADER_VERTEX, &hud->constbuf, &releasebuf[0]);
/* draw accumulated vertices for background quads */
cso_set_blend(cso, &hud->alpha_blend);
@ -596,7 +599,7 @@ hud_draw_results(struct hud_context *hud, struct pipe_resource *tex)
hud->constants.scale[0] = hud_scale;
hud->constants.scale[1] = hud_scale;
pipe_upload_constant_buffer0(pipe, MESA_SHADER_VERTEX, &hud->constbuf);
pipe_upload_constant_buffer0(pipe, MESA_SHADER_VERTEX, &hud->constbuf, &releasebuf[1]);
cso_set_vertex_buffers(cso, 1, &hud->bg.vbuf);
cso_draw_arrays(cso, MESA_PRIM_QUADS, 0, hud->bg.num_vertices);
@ -628,7 +631,7 @@ hud_draw_results(struct hud_context *hud, struct pipe_resource *tex)
hud->constants.translate[1] = 0;
hud->constants.scale[0] = hud_scale;
hud->constants.scale[1] = hud_scale;
pipe_upload_constant_buffer0(pipe, MESA_SHADER_VERTEX, &hud->constbuf);
pipe_upload_constant_buffer0(pipe, MESA_SHADER_VERTEX, &hud->constbuf, &releasebuf[2]);
if (hud->whitelines.num_vertices) {
cso_set_vertex_shader_handle(cso, hud->vs_color);
@ -647,6 +650,9 @@ hud_draw_results(struct hud_context *hud, struct pipe_resource *tex)
}
done:
pipe_resource_release(pipe, releasebuf[2]);
pipe_resource_release(pipe, releasebuf[1]);
pipe_resource_release(pipe, releasebuf[0]);
cso_restore_state(cso, CSO_UNBIND_FS_SAMPLERVIEW0 | CSO_UNBIND_VS_CONSTANTS);
/* restore states not restored by cso */

View file

@ -73,6 +73,8 @@ pp_jimenezmlaa_run(struct pp_queue_t *ppq, struct pipe_resource *in,
const struct pipe_stencil_ref ref = { {1} };
struct pipe_resource *releasebuf[2] = {};
/* Insufficient initialization checks. */
assert(p);
assert(ppq);
@ -104,8 +106,8 @@ pp_jimenezmlaa_run(struct pp_queue_t *ppq, struct pipe_resource *in,
cb.user_buffer = constants;
struct pipe_context *pipe = ppq->p->pipe;
pipe_upload_constant_buffer0(pipe, MESA_SHADER_VERTEX, &cb);
pipe_upload_constant_buffer0(pipe, MESA_SHADER_FRAGMENT, &cb);
pipe_upload_constant_buffer0(pipe, MESA_SHADER_VERTEX, &cb, &releasebuf[0]);
pipe_upload_constant_buffer0(pipe, MESA_SHADER_FRAGMENT, &cb, &releasebuf[1]);
mstencil.stencil[0].enabled = 1;
mstencil.stencil[0].valuemask = mstencil.stencil[0].writemask = ~0;
@ -212,6 +214,9 @@ pp_jimenezmlaa_run(struct pp_queue_t *ppq, struct pipe_resource *in,
p->blend.rt[0].blend_enable = 0;
memset(&p->framebuffer.zsbuf, 0, sizeof(p->framebuffer.zsbuf));
pipe_resource_release(pipe, releasebuf[1]);
pipe_resource_release(pipe, releasebuf[0]);
}
/** The init function of the MLAA filter. */

View file

@ -706,23 +706,23 @@ pipe_set_constant_buffer(struct pipe_context *pipe,
}
static inline void
pipe_upload_constant_buffer0(struct pipe_context *pipe, mesa_shader_stage stage, struct pipe_constant_buffer *cb)
pipe_upload_constant_buffer0(struct pipe_context *pipe, mesa_shader_stage stage,
struct pipe_constant_buffer *cb,
struct pipe_resource **releasebuf)
{
struct pipe_constant_buffer cbuf = *cb;
cbuf.buffer = NULL;
const unsigned alignment = MAX2(pipe->screen->caps.constant_buffer_offset_alignment, 64);
void *ptr;
struct pipe_resource *releasebuf = NULL;
if (pipe->screen->caps.prefer_real_buffer_in_constbuf0) {
u_upload_alloc(pipe->const_uploader, 0, cbuf.buffer_size,
alignment, &cbuf.buffer_offset, &cbuf.buffer, &releasebuf, (void**)&ptr);
alignment, &cbuf.buffer_offset, &cbuf.buffer, releasebuf, (void**)&ptr);
memcpy(ptr, cbuf.user_buffer, cbuf.buffer_size);
cbuf.user_buffer = NULL;
u_upload_unmap(pipe->const_uploader);
pipe->set_constant_buffer(pipe, stage, 0, &cbuf);
pipe_resource_release(pipe, releasebuf);
} else {
pipe->set_constant_buffer(pipe, stage, 0, cb);
}

View file

@ -107,13 +107,14 @@ st_destroy_clear(struct st_context *st)
* Helper function to set the clear color fragment shader.
*/
static void
set_clearcolor_fs(struct st_context *st, union pipe_color_union *color)
set_clearcolor_fs(struct st_context *st, union pipe_color_union *color,
struct pipe_resource **releasebuf)
{
struct pipe_constant_buffer cb = {
.user_buffer = color->f,
.buffer_size = 4 * sizeof(float),
};
pipe_upload_constant_buffer0(st->pipe, MESA_SHADER_FRAGMENT, &cb);
pipe_upload_constant_buffer0(st->pipe, MESA_SHADER_FRAGMENT, &cb, releasebuf);
if (!st->clear.fs) {
st->clear.fs = st_nir_make_clearcolor_shader(st);
@ -294,7 +295,8 @@ clear_with_quad(struct gl_context *ctx, unsigned clear_buffers)
_mesa_fb_orientation(fb) == Y_0_TOP);
/* Set constant buffer */
set_clearcolor_fs(st, (union pipe_color_union*)&ctx->Color.ClearColor);
struct pipe_resource *releasebuf = NULL;
set_clearcolor_fs(st, (union pipe_color_union*)&ctx->Color.ClearColor, &releasebuf);
cso_set_tessctrl_shader_handle(cso, NULL);
cso_set_tesseval_shader_handle(cso, NULL);
cso_set_mesh_shader_handle(cso, NULL);
@ -320,6 +322,8 @@ clear_with_quad(struct gl_context *ctx, unsigned clear_buffers)
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glClear");
}
pipe_resource_release(cso->pipe, releasebuf);
/* Restore pipe state */
cso_restore_state(cso, 0);
ctx->Array.NewVertexElements = true;

View file

@ -371,9 +371,10 @@ st_hw_select_draw_gallium(struct gl_context *ctx,
unsigned num_draws)
{
struct st_context *st = st_context(ctx);
struct pipe_resource *releasebuf = NULL;
enum mesa_prim old_mode = info->mode;
if (st_draw_hw_select_prepare_common(ctx) &&
if (st_draw_hw_select_prepare_common(ctx, &releasebuf) &&
/* Removing "const" is fine because we restore the changed mode
* at the end. */
st_draw_hw_select_prepare_mode(ctx, ((struct pipe_draw_info*)info))) {
@ -381,6 +382,8 @@ st_hw_select_draw_gallium(struct gl_context *ctx,
num_draws);
}
pipe_resource_release(st->pipe, releasebuf);
((struct pipe_draw_info*)info)->mode = old_mode;
}
@ -392,9 +395,10 @@ st_hw_select_draw_gallium_multimode(struct gl_context *ctx,
unsigned num_draws)
{
struct st_context *st = st_context(ctx);
struct pipe_resource *releasebuf = NULL;
if (!st_draw_hw_select_prepare_common(ctx))
return;
if (!st_draw_hw_select_prepare_common(ctx, &releasebuf))
goto out;
unsigned i, first;
struct cso_context *cso = st->cso_context;
@ -410,6 +414,9 @@ st_hw_select_draw_gallium_multimode(struct gl_context *ctx,
first = i;
}
}
out:
pipe_resource_release(st->pipe, releasebuf);
}
void

View file

@ -100,7 +100,8 @@ st_indirect_draw_vbo(struct gl_context *ctx,
GLsizei draw_count, GLsizei stride);
bool
st_draw_hw_select_prepare_common(struct gl_context *ctx);
st_draw_hw_select_prepare_common(struct gl_context *ctx,
struct pipe_resource **releasebuf);
bool
st_draw_hw_select_prepare_mode(struct gl_context *ctx, struct pipe_draw_info *info);
void

View file

@ -654,7 +654,8 @@ hw_select_create_gs(struct st_context *st, union state_key state)
}
bool
st_draw_hw_select_prepare_common(struct gl_context *ctx)
st_draw_hw_select_prepare_common(struct gl_context *ctx,
struct pipe_resource **releasebuf)
{
struct st_context *st = st_context(ctx);
if (ctx->GeometryProgram._Current ||
@ -692,7 +693,7 @@ st_draw_hw_select_prepare_common(struct gl_context *ctx)
cb.buffer_size = sizeof(consts) - (MAX_CLIP_PLANES - num_planes) * 4 * sizeof(float);
struct pipe_context *pipe = st->pipe;
pipe_upload_constant_buffer0(pipe, MESA_SHADER_GEOMETRY, &cb);
pipe_upload_constant_buffer0(pipe, MESA_SHADER_GEOMETRY, &cb, releasebuf);
struct pipe_shader_buffer buffer;
memset(&buffer, 0, sizeof(buffer));

View file

@ -217,7 +217,7 @@ st_pbo_draw(struct st_context *st, const struct st_pbo_addresses *addr,
cso_set_mesh_shader_handle(cso, NULL);
/* Upload vertices */
struct pipe_resource *releasebuf = NULL;
struct pipe_resource *vb_releasebuf = NULL;
{
struct pipe_vertex_buffer vbo = {0};
struct cso_velems_state velem;
@ -230,7 +230,7 @@ st_pbo_draw(struct st_context *st, const struct st_pbo_addresses *addr,
float *verts = NULL;
u_upload_alloc(st->pipe->stream_uploader, 0, 8 * sizeof(float), 4,
&vbo.buffer_offset, &vbo.buffer.resource, &releasebuf, (void **) &verts);
&vbo.buffer_offset, &vbo.buffer.resource, &vb_releasebuf, (void **) &verts);
if (!verts)
return false;
@ -258,6 +258,7 @@ st_pbo_draw(struct st_context *st, const struct st_pbo_addresses *addr,
}
/* Upload constants */
struct pipe_resource *cb_releasebuf = NULL;
{
struct pipe_constant_buffer cb;
@ -266,7 +267,7 @@ st_pbo_draw(struct st_context *st, const struct st_pbo_addresses *addr,
cb.buffer_offset = 0;
cb.buffer_size = sizeof(addr->constants);
pipe_upload_constant_buffer0(st->pipe, MESA_SHADER_FRAGMENT, &cb);
pipe_upload_constant_buffer0(st->pipe, MESA_SHADER_FRAGMENT, &cb, &cb_releasebuf);
}
/* Rasterizer state */
@ -281,7 +282,8 @@ st_pbo_draw(struct st_context *st, const struct st_pbo_addresses *addr,
cso_draw_arrays_instanced(cso, MESA_PRIM_TRIANGLE_STRIP,
0, 4, 0, addr->depth);
}
pipe_resource_release(st->pipe, releasebuf);
pipe_resource_release(st->pipe, cb_releasebuf);
pipe_resource_release(st->pipe, vb_releasebuf);
return true;
}

View file

@ -1004,7 +1004,8 @@ download_texture_compute(struct st_context *st,
assert(cs);
struct cso_context *cso = st->cso_context;
pipe_upload_constant_buffer0(st->pipe, MESA_SHADER_COMPUTE, &cb);
struct pipe_resource *releasebuf = NULL;
pipe_upload_constant_buffer0(st->pipe, MESA_SHADER_COMPUTE, &cb, &releasebuf);
cso_save_compute_state(cso, CSO_BIT_COMPUTE_SHADER | CSO_BIT_COMPUTE_SAMPLERS);
cso_set_compute_shader_handle(cso, cs);
@ -1174,6 +1175,8 @@ fail:
ST_SET_STATE3(st->ctx->NewDriverState, ST_NEW_CS_CONSTANTS,
ST_NEW_CS_SSBOS, ST_NEW_CS_SAMPLER_VIEWS);
pipe_resource_release(pipe, releasebuf);
return dst;
}