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 {