From 35f031db4bf3dfaab7ed0df2a824261de253e306 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Tue, 5 Aug 2025 11:16:41 -0400 Subject: [PATCH] tc: don't clobber CSO info when renderpass has ended MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit if a renderpass has ended, the info is signaled and cannot be modified for anything but resolves and invalidates. when a CSO is then bound before the next fb state change, there is no way to increment rp info in a way which keeps it in lockstep with the consumer thread, so storing the new states until a new rp info is incremented ensures that everything works as expected Fixes: 4989a40e890 ("tc: explicitly terminate renderpasses on fb access") Acked-by: Marek Olšák Part-of: (cherry picked from commit 84fb88e5e79030f68684bacf93f4b454d633fd1f) --- .pick_status.json | 2 +- .../auxiliary/util/u_threaded_context.c | 72 ++++++++++++++----- .../auxiliary/util/u_threaded_context.h | 2 + 3 files changed, 57 insertions(+), 19 deletions(-) diff --git a/.pick_status.json b/.pick_status.json index a000f030596..865f15cef69 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -554,7 +554,7 @@ "description": "tc: don't clobber CSO info when renderpass has ended", "nominated": true, "nomination_type": 2, - "resolution": 0, + "resolution": 1, "main_sha": null, "because_sha": "4989a40e890f38de99376bd5344aba05a0ee9fe4", "notes": null diff --git a/src/gallium/auxiliary/util/u_threaded_context.c b/src/gallium/auxiliary/util/u_threaded_context.c index 704ea1652a8..c1de2345703 100644 --- a/src/gallium/auxiliary/util/u_threaded_context.c +++ b/src/gallium/auxiliary/util/u_threaded_context.c @@ -135,6 +135,45 @@ tc_batch_rp_info(struct tc_renderpass_info *info) return (struct tc_batch_rp_info *)info; } +static void +tc_parse_dsa(struct threaded_context *tc, void *dsa) +{ + /* dsa info is only ever added during a renderpass; + * changes outside of a renderpass reset the data + */ + if (!tc->in_renderpass) { + tc->renderpass_info_recording->zsbuf_write_dsa = 0; + tc->renderpass_info_recording->zsbuf_read_dsa = 0; + } + /* let the driver parse its own state */ + tc->options.dsa_parse(dsa, tc->renderpass_info_recording); +} + +static void +tc_parse_fs(struct threaded_context *tc, void *fs) +{ + /* fs info is only ever added during a renderpass; + * changes outside of a renderpass reset the data + */ + if (!tc->in_renderpass) { + tc->renderpass_info_recording->cbuf_fbfetch = 0; + tc->renderpass_info_recording->zsbuf_write_fs = 0; + } + /* let the driver parse its own state */ + tc->options.fs_parse(fs, tc->renderpass_info_recording); +} + +static void +tc_parse_pending_rp_info(struct threaded_context *tc) +{ + if (tc->pending_renderpass_dsa) + tc_parse_dsa(tc, tc->pending_renderpass_dsa); + if (tc->pending_renderpass_fs) + tc_parse_fs(tc, tc->pending_renderpass_fs); + tc->pending_renderpass_dsa = NULL; + tc->pending_renderpass_fs = NULL; +} + static void tc_sanitize_renderpass_info(struct threaded_context *tc) { @@ -265,6 +304,8 @@ tc_batch_increment_renderpass_info(struct threaded_context *tc, unsigned batch_i /* this is now the current recording renderpass info */ tc->renderpass_info_recording = &tc_info[batch->renderpass_info_idx].info; batch->max_renderpass_info_idx = batch->renderpass_info_idx; + + tc_parse_pending_rp_info(tc); } static ALWAYS_INLINE struct tc_renderpass_info * @@ -1343,15 +1384,12 @@ TC_CSO_WHOLE(rasterizer) TC_CSO_CREATE(depth_stencil_alpha, depth_stencil_alpha) TC_CSO_BIND(depth_stencil_alpha, if (param && tc->options.parse_renderpass_info) { - /* dsa info is only ever added during a renderpass; - * changes outside of a renderpass reset the data - */ - if (!tc->in_renderpass) { - tc_get_renderpass_info(tc)->zsbuf_write_dsa = 0; - tc_get_renderpass_info(tc)->zsbuf_read_dsa = 0; - } - /* let the driver parse its own state */ - tc->options.dsa_parse(param, tc_get_renderpass_info(tc)); + if (tc->renderpass_info_recording->ended) + tc->pending_renderpass_dsa = param; + else + tc_parse_dsa(tc, param); + } else { + tc->pending_renderpass_dsa = NULL; } ) TC_CSO_DELETE(depth_stencil_alpha) @@ -1359,15 +1397,12 @@ TC_CSO_WHOLE(compute) TC_CSO_CREATE(fs, shader) TC_CSO_BIND(fs, if (param && tc->options.parse_renderpass_info) { - /* fs info is only ever added during a renderpass; - * changes outside of a renderpass reset the data - */ - if (!tc->in_renderpass) { - tc_get_renderpass_info(tc)->cbuf_fbfetch = 0; - tc_get_renderpass_info(tc)->zsbuf_write_fs = 0; - } - /* let the driver parse its own state */ - tc->options.fs_parse(param, tc_get_renderpass_info(tc)); + if (tc->renderpass_info_recording->ended) + tc->pending_renderpass_fs = param; + else + tc_parse_fs(tc, param); + } else { + tc->pending_renderpass_fs = NULL; } ) TC_CSO_DELETE(fs) @@ -1514,6 +1549,7 @@ tc_set_framebuffer_state(struct pipe_context *_pipe, */ tc->batch_slots[tc->next].renderpass_info_idx = 0; tc->renderpass_info_recording->has_resolve = false; + tc_parse_pending_rp_info(tc); } assert(!tc->renderpass_info_recording->resolve[0] && !tc->renderpass_info_recording->resolve[1]); diff --git a/src/gallium/auxiliary/util/u_threaded_context.h b/src/gallium/auxiliary/util/u_threaded_context.h index 4cad69edea4..8cb83b90ed1 100644 --- a/src/gallium/auxiliary/util/u_threaded_context.h +++ b/src/gallium/auxiliary/util/u_threaded_context.h @@ -685,6 +685,8 @@ struct threaded_context { struct tc_renderpass_info *renderpass_info_recording; /* accessed by driver thread */ struct tc_renderpass_info *renderpass_info; + /* internal-only: if dsa/fs are bound between render passes */ + void *pending_renderpass_dsa, *pending_renderpass_fs; };