Module: Mesa
Branch: main
Commit: 7f956435a039f4729c776a0172bffe7c8b6207b7
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=7f956435a039f4729c776a0172bffe7c8b6207b7

Author: Mike Blumenkrantz <[email protected]>
Date:   Wed Mar  1 09:34:41 2023 -0500

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>

---

 src/gallium/drivers/zink/zink_context.c | 22 ++++++++++++++++------
 src/gallium/drivers/zink/zink_screen.c  |  2 +-
 2 files changed, 17 insertions(+), 7 deletions(-)

diff --git a/src/gallium/drivers/zink/zink_context.c 
b/src/gallium/drivers/zink/zink_context.c
index 0a97ce3886d..e6ef2070d6d 100644
--- a/src/gallium/drivers/zink/zink_context.c
+++ b/src/gallium/drivers/zink/zink_context.c
@@ -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);
    }
diff --git a/src/gallium/drivers/zink/zink_screen.c 
b/src/gallium/drivers/zink/zink_screen.c
index 40f4fad23fb..b2101550780 100644
--- a/src/gallium/drivers/zink/zink_screen.c
+++ b/src/gallium/drivers/zink/zink_screen.c
@@ -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;

Reply via email to