glthread, tc: Fix buffer release with glthread and tc

_mesa_glthread_release_upload_buffer will call _mesa_reference_buffer_object
which will then end up in tc_resource_release.

Doing so from glthread is bad because we now have 2 threads concurrently
accessing TC batch: glthread and the unmarshalling/tc thread.

Fix this by queuing the release call through an "Internal" glthread function.

Fixes: b3133e250e ("gallium: add pipe_context::resource_release to eliminate buffer refcounting")
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/37763>
This commit is contained in:
Pierre-Eric Pelloux-Prayer 2025-10-08 12:12:45 +02:00 committed by Marge Bot
parent 7b222d532b
commit ae75b59cb5
5 changed files with 27 additions and 5 deletions

View file

@ -11097,6 +11097,11 @@
<!-- Internal function for glthread to implement ancillary buffer invalidation. --> <!-- Internal function for glthread to implement ancillary buffer invalidation. -->
<function name="InternalInvalidateFramebufferAncillaryMESA" es2="3.0"> <function name="InternalInvalidateFramebufferAncillaryMESA" es2="3.0">
</function> </function>
<!-- Internal function for glthread to defer buffer release. -->
<function name="InternalReleaseBufferMESA" es2="3.0" marshal="async">
<param name="buffer" type="GLvoid *"/>
</function>
</category> </category>
<xi:include href="OES_EGL_image.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> <xi:include href="OES_EGL_image.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>

View file

@ -1612,6 +1612,7 @@ all_functions = [
"DrawArraysInstancedBaseInstanceDrawID", "DrawArraysInstancedBaseInstanceDrawID",
"DrawElementsInstancedBaseVertexBaseInstanceDrawID", "DrawElementsInstancedBaseVertexBaseInstanceDrawID",
"InternalInvalidateFramebufferAncillaryMESA", "InternalInvalidateFramebufferAncillaryMESA",
"InternalReleaseBufferMESA",
"DrawElementsPacked", "DrawElementsPacked",
"DrawElementsUserBufPacked", "DrawElementsUserBufPacked",
"TexStorageAttribs2DEXT", "TexStorageAttribs2DEXT",

View file

@ -284,7 +284,7 @@ _mesa_glthread_destroy(struct gl_context *ctx)
util_queue_fence_destroy(&glthread->batches[i].fence); util_queue_fence_destroy(&glthread->batches[i].fence);
_mesa_DeinitHashTable(&glthread->VAOs, free_vao, NULL); _mesa_DeinitHashTable(&glthread->VAOs, free_vao, NULL);
_mesa_glthread_release_upload_buffer(ctx); _mesa_glthread_release_upload_buffer(ctx, false);
} }
} }

View file

@ -331,7 +331,7 @@ void _mesa_glthread_flush_batch(struct gl_context *ctx);
void _mesa_glthread_finish(struct gl_context *ctx); void _mesa_glthread_finish(struct gl_context *ctx);
void _mesa_glthread_finish_before(struct gl_context *ctx, const char *func); void _mesa_glthread_finish_before(struct gl_context *ctx, const char *func);
bool _mesa_glthread_invalidate_zsbuf(struct gl_context *ctx); bool _mesa_glthread_invalidate_zsbuf(struct gl_context *ctx);
void _mesa_glthread_release_upload_buffer(struct gl_context *ctx); void _mesa_glthread_release_upload_buffer(struct gl_context *ctx, bool async_release);
void _mesa_glthread_upload(struct gl_context *ctx, const void *data, void _mesa_glthread_upload(struct gl_context *ctx, const void *data,
GLsizeiptr size, unsigned *out_offset, GLsizeiptr size, unsigned *out_offset,
struct gl_buffer_object **out_buffer, struct gl_buffer_object **out_buffer,
@ -405,6 +405,8 @@ void _mesa_glthread_unbind_uploaded_vbos(struct gl_context *ctx);
void _mesa_glthread_PixelStorei(struct gl_context *ctx, GLenum pname, void _mesa_glthread_PixelStorei(struct gl_context *ctx, GLenum pname,
GLint param); GLint param);
void _mesa_InternalReleaseBufferMESA(void *buffer);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -64,8 +64,15 @@ new_upload_buffer(struct gl_context *ctx, GLsizeiptr size, uint8_t **ptr)
return obj; return obj;
} }
void _mesa_InternalReleaseBufferMESA(void *buffer)
{
GET_CURRENT_CONTEXT(ctx);
struct gl_buffer_object *buf = buffer;
_mesa_reference_buffer_object(ctx, &buf, NULL);
}
void void
_mesa_glthread_release_upload_buffer(struct gl_context *ctx) _mesa_glthread_release_upload_buffer(struct gl_context *ctx, bool async_release)
{ {
struct glthread_state *glthread = &ctx->GLThread; struct glthread_state *glthread = &ctx->GLThread;
@ -79,7 +86,14 @@ _mesa_glthread_release_upload_buffer(struct gl_context *ctx)
p_atomic_add(&glthread->upload_buffer->RefCount, p_atomic_add(&glthread->upload_buffer->RefCount,
-(PRIVATE_REFCOUNT - glthread->upload_buffer->CtxRefCount)); -(PRIVATE_REFCOUNT - glthread->upload_buffer->CtxRefCount));
} }
if (async_release) {
/* Defer to avoid calling tc_resource_release from this thread. */
_mesa_marshal_InternalReleaseBufferMESA(glthread->upload_buffer);
glthread->upload_buffer = NULL;
} else {
_mesa_reference_buffer_object(ctx, &glthread->upload_buffer, NULL); _mesa_reference_buffer_object(ctx, &glthread->upload_buffer, NULL);
}
} }
void void
@ -120,7 +134,7 @@ _mesa_glthread_upload(struct gl_context *ctx, const void *data,
return; return;
} }
_mesa_glthread_release_upload_buffer(ctx); _mesa_glthread_release_upload_buffer(ctx, true);
glthread->upload_buffer = glthread->upload_buffer =
new_upload_buffer(ctx, default_size, &glthread->upload_ptr); new_upload_buffer(ctx, default_size, &glthread->upload_ptr);