#include "etnaviv_query_acc.h"
#include "etnaviv_screen.h"
-/*
- * Occlusion Query:
- *
- * OCCLUSION_COUNTER and OCCLUSION_PREDICATE differ only in how they
- * interpret results
- */
-
-static void
-occlusion_resume(struct etna_acc_query *aq, struct etna_context *ctx)
-{
- struct etna_resource *rsc = etna_resource(aq->prsc);
- struct etna_reloc r = {
- .bo = rsc->bo,
- .flags = ETNA_RELOC_WRITE
- };
-
- if (aq->samples > 63) {
- aq->samples = 63;
- BUG("samples overflow");
- }
- r.offset = aq->samples * 8; /* 64bit value */
-
- etna_set_state_reloc(ctx->stream, VIVS_GL_OCCLUSION_QUERY_ADDR, &r);
- resource_written(ctx, aq->prsc);
-}
+extern const struct etna_acc_sample_provider occlusion_provider;
+extern const struct etna_acc_sample_provider perfmon_provider;
-static void
-occlusion_suspend(struct etna_acc_query *aq, struct etna_context *ctx)
-{
- /* 0x1DF5E76 is the value used by blob - but any random value will work */
- etna_set_state(ctx->stream, VIVS_GL_OCCLUSION_QUERY_CONTROL, 0x1DF5E76);
- resource_written(ctx, aq->prsc);
-}
-
-static void
-occlusion_result(struct etna_acc_query *aq, void *buf,
- union pipe_query_result *result)
+static const struct etna_acc_sample_provider *acc_sample_provider[] =
{
- uint64_t sum = 0;
- uint64_t *ptr = (uint64_t *)buf;
-
- for (unsigned i = 0; i < aq->samples; i++)
- sum += *(ptr + i);
-
- if (aq->base.type == PIPE_QUERY_OCCLUSION_COUNTER)
- result->u64 = sum;
- else
- result->b = !!sum;
-}
+ &occlusion_provider,
+ &perfmon_provider,
+};
static void
etna_acc_destroy_query(struct etna_context *ctx, struct etna_query *q)
FREE(aq);
}
-static const struct etna_acc_sample_provider occlusion_provider = {
- .suspend = occlusion_suspend,
- .resume = occlusion_resume,
- .result = occlusion_result,
-};
-
static void
realloc_query_bo(struct etna_context *ctx, struct etna_acc_query *aq)
{
etna_bo_cpu_fini(rsc->bo);
}
-static bool
+static void
etna_acc_begin_query(struct etna_context *ctx, struct etna_query *q)
{
struct etna_acc_query *aq = etna_acc_query(q);
/* add to active list */
assert(list_is_empty(&aq->node));
list_addtail(&aq->node, &ctx->active_acc_queries);
-
- return true;
}
static void
assert(list_is_empty(&aq->node));
- if (!wait) {
- int ret;
-
- if (rsc->status & ETNA_PENDING_WRITE) {
+ if (rsc->status & ETNA_PENDING_WRITE) {
+ if (!wait) {
/* piglit spec@arb_occlusion_query@occlusion_query_conform
* test, and silly apps perhaps, get stuck in a loop trying
* to get query result forever with wait==false.. we don't
}
return false;
+ } else {
+ /* flush that GPU executes all query related actions */
+ ctx->base.flush(&ctx->base, NULL, 0);
}
-
- ret = etna_bo_cpu_prep(rsc->bo, DRM_ETNA_PREP_READ | DRM_ETNA_PREP_NOSYNC);
- if (ret)
- return false;
-
- etna_bo_cpu_fini(rsc->bo);
}
- /* flush that GPU executes all query related actions */
- ctx->base.flush(&ctx->base, NULL, 0);
-
/* get the result */
- etna_bo_cpu_prep(rsc->bo, DRM_ETNA_PREP_READ);
+ int ret = etna_bo_cpu_prep(rsc->bo, DRM_ETNA_PREP_READ);
+ if (ret)
+ return false;
void *ptr = etna_bo_map(rsc->bo);
- p->result(aq, ptr, result);
- aq->samples = 0;
+ bool success = p->result(aq, ptr, result);
+
+ if (success)
+ aq->samples = 0;
etna_bo_cpu_fini(rsc->bo);
- return true;
+ return success;
}
static const struct etna_query_funcs acc_query_funcs = {
.get_query_result = etna_acc_get_query_result,
};
-static inline const struct etna_acc_sample_provider *
-query_sample_provider(unsigned query_type)
-{
- switch (query_type) {
- case PIPE_QUERY_OCCLUSION_COUNTER:
- /* fallthrough */
- case PIPE_QUERY_OCCLUSION_PREDICATE:
- /* fallthrough */
- case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
- return &occlusion_provider;
- default:
- return NULL;
- }
-}
-
struct etna_query *
etna_acc_create_query(struct etna_context *ctx, unsigned query_type)
{
+ const struct etna_acc_sample_provider *p = NULL;
struct etna_acc_query *aq;
struct etna_query *q;
- const struct etna_acc_sample_provider *p;
- p = query_sample_provider(query_type);
+ /* find a sample provide for the requested query type */
+ for (unsigned i = 0; i < ARRAY_SIZE(acc_sample_provider); i++) {
+ p = acc_sample_provider[i];
+
+ if (p->supports(query_type))
+ break;
+ else
+ p = NULL;
+ }
+
if (!p)
return NULL;
- aq = CALLOC_STRUCT(etna_acc_query);
+ aq = p->allocate(ctx, query_type);
if (!aq)
return NULL;