zink: rework xfb queries for drivers with poor primgen support

for drivers lacking one of:
* EXT_color_write_enable
* primitivesGeneratedQueryWithRasterizerDiscard

terrible things must happen. specifically, dummy surfaces have to
be used in a framebuffer with rast-discard enabled for the duration
of the query

now that queries are only started/stopped in renderpasses, however,
there are new hurdles. with tc renderpass optimizing, queries can be
started outside the renderpass, which would trigger recursion when
trying to start a primgen query outside the renderpass if any clears
are enabled, as those must be flushed onto the real surfaces

to solve all of this:
* block tc renderpass optimizing if at least one of the above features is missing
* detect a pending primgen query start during renderpass start
* activate rast-discard and set dummy surfaces before beginning renderpass
  * this recurses and automatically flushes clears
* finally, start the real renderpass

BUT WAIT THERE'S MORE!

because there's also drivers that support EXT_color_write_enable and don't support
primitivesGeneratedQueryWithRasterizerDiscard, which means they do need rast-discard,
but they don't need dummy surfaces, and so the clears still have to be flushed,
so they need an explicit (recursive) renderpass start/stop in advance to
ensure the clears are applied as expected

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21628>
This commit is contained in:
Mike Blumenkrantz
2023-03-01 09:34:41 -05:00
committed by Marge Bot
parent 5144c8a858
commit 7f956435a0
2 changed files with 17 additions and 7 deletions

View File

@@ -2740,9 +2740,20 @@ zink_batch_rp(struct zink_context *ctx)
ctx->queries_in_rp = maybe_has_query_ends;
/* if possible, out-of-renderpass resume any queries that were stopped when previous rp ended */
if (!ctx->queries_disabled && !maybe_has_query_ends) {
if (ctx->primitives_generated_suspended && ctx->clears_enabled) {
/* this is a driver that doesn't need dummy surfaces but does need rasterization discard, so flush clears first */
ctx->queries_disabled = true;
zink_batch_rp(ctx);
zink_batch_no_rp(ctx);
ctx->queries_disabled = false;
}
zink_resume_queries(ctx, &ctx->batch);
zink_query_update_gs_states(ctx);
}
if (!ctx->queries_disabled && ctx->primitives_generated_suspended && !zink_screen(ctx->base.screen)->info.have_EXT_color_write_enable) {
if (zink_set_rasterizer_discard(ctx, true))
zink_set_color_write_enables(ctx);
}
unsigned clear_buffers;
/* use renderpass for multisample-to-singlesample or fbfetch:
* - msrtss is TODO
@@ -3167,18 +3178,17 @@ unbind_fb_surface(struct zink_context *ctx, struct pipe_surface *surf, unsigned
void
zink_set_color_write_enables(struct zink_context *ctx)
{
bool disable_color_writes = ctx->rast_state && ctx->rast_state->base.rasterizer_discard && ctx->primitives_generated_active;
bool disable_color_writes = ctx->rast_state && ctx->rast_state->base.rasterizer_discard &&
(ctx->primitives_generated_active || (!ctx->queries_disabled && ctx->primitives_generated_suspended));
if (ctx->disable_color_writes == disable_color_writes)
return;
/* flush all pending clears: these have already occurred */
if (disable_color_writes && ctx->clears_enabled)
zink_batch_rp(ctx);
/* this should have been handled already */
assert(!disable_color_writes || !ctx->clears_enabled);
ctx->disable_color_writes = disable_color_writes;
if (!zink_screen(ctx->base.screen)->info.have_EXT_color_write_enable) {
/* use dummy color buffers instead of the more sane option */
zink_batch_no_rp(ctx);
ctx->rp_changed = true;
zink_update_framebuffer_state(ctx);
ctx->fb_changed = true;
} else {
reapply_color_write(ctx);
}

View File

@@ -2538,7 +2538,7 @@ init_driver_workarounds(struct zink_screen *screen)
case VK_DRIVER_ID_QUALCOMM_PROPRIETARY:
case VK_DRIVER_ID_BROADCOM_PROPRIETARY:
case VK_DRIVER_ID_ARM_PROPRIETARY:
screen->driver_workarounds.track_renderpasses = true;
screen->driver_workarounds.track_renderpasses = screen->info.primgen_feats.primitivesGeneratedQueryWithRasterizerDiscard || screen->info.have_EXT_color_write_enable;
break;
default:
break;