panfrost: Precise occlusion query support

In the "counter" occlusion query mode, each shader core has a separate
counter.

When MSAA is disabled, counter values need to be divided by four.

Reviewed-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7074>
diff --git a/src/gallium/drivers/panfrost/pan_context.c b/src/gallium/drivers/panfrost/pan_context.c
index adc0cd8..5728ec6 100644
--- a/src/gallium/drivers/panfrost/pan_context.c
+++ b/src/gallium/drivers/panfrost/pan_context.c
@@ -402,7 +402,10 @@
                 pan_emit_draw_descs(batch, &cfg, PIPE_SHADER_FRAGMENT);
 
                 if (ctx->occlusion_query) {
-                        cfg.occlusion_query = MALI_OCCLUSION_MODE_PREDICATE;
+                        if (ctx->occlusion_query->type == PIPE_QUERY_OCCLUSION_COUNTER)
+                                cfg.occlusion_query = MALI_OCCLUSION_MODE_COUNTER;
+                        else
+                                cfg.occlusion_query = MALI_OCCLUSION_MODE_PREDICATE;
                         cfg.occlusion = ctx->occlusion_query->bo->gpu;
                         panfrost_batch_add_bo(ctx->batch, ctx->occlusion_query->bo,
                                               PAN_BO_ACCESS_SHARED |
@@ -1347,23 +1350,28 @@
 panfrost_begin_query(struct pipe_context *pipe, struct pipe_query *q)
 {
         struct panfrost_context *ctx = pan_context(pipe);
+        struct panfrost_device *dev = pan_device(ctx->base.screen);
         struct panfrost_query *query = (struct panfrost_query *) q;
 
         switch (query->type) {
         case PIPE_QUERY_OCCLUSION_COUNTER:
         case PIPE_QUERY_OCCLUSION_PREDICATE:
-        case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
+        case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE: {
+                unsigned size = sizeof(uint64_t) * dev->core_count;
+
                 /* Allocate a bo for the query results to be stored */
                 if (!query->bo) {
-                        query->bo = panfrost_bo_create(
-                                        pan_device(ctx->base.screen),
-                                        sizeof(unsigned), 0);
+                        query->bo = panfrost_bo_create(dev, size, 0);
                 }
 
-                unsigned *result = (unsigned *)query->bo->cpu;
-                *result = 0; /* Default to 0 if nothing at all drawn. */
+                /* Default to 0 if nothing at all drawn. */
+                memset(query->bo->cpu, 0, size);
+
+                query->msaa = (ctx->pipe_framebuffer.samples > 1);
+
                 ctx->occlusion_query = query;
                 break;
+        }
 
         /* Geometry statistics are computed in the driver. XXX: geom/tess
          * shaders.. */
@@ -1414,7 +1422,7 @@
 {
         struct panfrost_query *query = (struct panfrost_query *) q;
         struct panfrost_context *ctx = pan_context(pipe);
-
+        struct panfrost_device *dev = pan_device(ctx->base.screen);
 
         switch (query->type) {
         case PIPE_QUERY_OCCLUSION_COUNTER:
@@ -1424,13 +1432,19 @@
                 panfrost_bo_wait(query->bo, INT64_MAX, false);
 
                 /* Read back the query results */
-                unsigned *result = (unsigned *) query->bo->cpu;
-                unsigned passed = *result;
+                uint64_t *result = (uint64_t *) query->bo->cpu;
 
                 if (query->type == PIPE_QUERY_OCCLUSION_COUNTER) {
+                        uint64_t passed = 0;
+                        for (int i = 0; i < dev->core_count; ++i)
+                                passed += result[i];
+
+                        if (!query->msaa)
+                                passed /= 4;
+
                         vresult->u64 = passed;
                 } else {
-                        vresult->b = !!passed;
+                        vresult->b = !!result[0];
                 }
 
                 break;
diff --git a/src/gallium/drivers/panfrost/pan_context.h b/src/gallium/drivers/panfrost/pan_context.h
index 4452328..3e9a150 100644
--- a/src/gallium/drivers/panfrost/pan_context.h
+++ b/src/gallium/drivers/panfrost/pan_context.h
@@ -79,6 +79,9 @@
 
         /* Memory for the GPU to writeback the value of the query */
         struct panfrost_bo *bo;
+
+        /* Whether an occlusion query is for a MSAA framebuffer */
+        bool msaa;
 };
 
 struct panfrost_fence {