Path: blob/21.2-virgl/src/gallium/drivers/etnaviv/etnaviv_query_acc.c
4570 views
/*1* Copyright (c) 2017 Etnaviv Project2* Copyright (C) 2017 Zodiac Inflight Innovations3*4* Permission is hereby granted, free of charge, to any person obtaining a5* copy of this software and associated documentation files (the "Software"),6* to deal in the Software without restriction, including without limitation7* the rights to use, copy, modify, merge, publish, distribute, sub license,8* and/or sell copies of the Software, and to permit persons to whom the9* Software is furnished to do so, subject to the following conditions:10*11* The above copyright notice and this permission notice (including the12* next paragraph) shall be included in all copies or substantial portions13* of the Software.14*15* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR16* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,17* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL18* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER19* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING20* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER21* DEALINGS IN THE SOFTWARE.22*23* Authors:24* Rob Clark <[email protected]>25* Christian Gmeiner <[email protected]>26*/2728#include "util/u_inlines.h"29#include "util/u_memory.h"3031#include "etnaviv_context.h"32#include "etnaviv_debug.h"33#include "etnaviv_emit.h"34#include "etnaviv_query_acc.h"35#include "etnaviv_screen.h"363738extern const struct etna_acc_sample_provider occlusion_provider;39extern const struct etna_acc_sample_provider perfmon_provider;4041static const struct etna_acc_sample_provider *acc_sample_provider[] =42{43&occlusion_provider,44&perfmon_provider,45};4647static void48etna_acc_destroy_query(struct etna_context *ctx, struct etna_query *q)49{50struct etna_acc_query *aq = etna_acc_query(q);5152pipe_resource_reference(&aq->prsc, NULL);53list_del(&aq->node);5455FREE(aq);56}5758static void59realloc_query_bo(struct etna_context *ctx, struct etna_acc_query *aq)60{61struct etna_resource *rsc;62void *map;6364pipe_resource_reference(&aq->prsc, NULL);6566/* allocate resource with space for 64 * 64bit values */67aq->prsc = pipe_buffer_create(&ctx->screen->base, PIPE_BIND_QUERY_BUFFER,680, 0x1000);6970/* don't assume the buffer is zero-initialized */71rsc = etna_resource(aq->prsc);7273etna_bo_cpu_prep(rsc->bo, DRM_ETNA_PREP_WRITE);7475map = etna_bo_map(rsc->bo);76memset(map, 0, 0x1000);77etna_bo_cpu_fini(rsc->bo);78}7980static void81etna_acc_begin_query(struct etna_context *ctx, struct etna_query *q)82{83struct etna_acc_query *aq = etna_acc_query(q);84const struct etna_acc_sample_provider *p = aq->provider;8586/* ->begin_query() discards previous results, so realloc bo */87realloc_query_bo(ctx, aq);8889p->resume(aq, ctx);90aq->samples++;9192/* add to active list */93assert(list_is_empty(&aq->node));94list_addtail(&aq->node, &ctx->active_acc_queries);95}9697static void98etna_acc_end_query(struct etna_context *ctx, struct etna_query *q)99{100struct etna_acc_query *aq = etna_acc_query(q);101const struct etna_acc_sample_provider *p = aq->provider;102103p->suspend(aq, ctx);104aq->samples++;105106/* remove from active list */107list_delinit(&aq->node);108}109110static bool111etna_acc_get_query_result(struct etna_context *ctx, struct etna_query *q,112bool wait, union pipe_query_result *result)113{114struct etna_acc_query *aq = etna_acc_query(q);115struct etna_resource *rsc = etna_resource(aq->prsc);116const struct etna_acc_sample_provider *p = aq->provider;117118assert(list_is_empty(&aq->node));119120if (rsc->status & ETNA_PENDING_WRITE) {121if (!wait) {122/* piglit spec@arb_occlusion_query@occlusion_query_conform123* test, and silly apps perhaps, get stuck in a loop trying124* to get query result forever with wait==false.. we don't125* wait to flush unnecessarily but we also don't want to126* spin forever.127*/128if (aq->no_wait_cnt++ > 5) {129ctx->base.flush(&ctx->base, NULL, 0);130aq->no_wait_cnt = 0;131}132133return false;134} else {135/* flush that GPU executes all query related actions */136ctx->base.flush(&ctx->base, NULL, 0);137}138}139140/* get the result */141int ret = etna_bo_cpu_prep(rsc->bo, DRM_ETNA_PREP_READ);142if (ret)143return false;144145void *ptr = etna_bo_map(rsc->bo);146bool success = p->result(aq, ptr, result);147148if (success)149aq->samples = 0;150151etna_bo_cpu_fini(rsc->bo);152153return success;154}155156static const struct etna_query_funcs acc_query_funcs = {157.destroy_query = etna_acc_destroy_query,158.begin_query = etna_acc_begin_query,159.end_query = etna_acc_end_query,160.get_query_result = etna_acc_get_query_result,161};162163struct etna_query *164etna_acc_create_query(struct etna_context *ctx, unsigned query_type)165{166const struct etna_acc_sample_provider *p = NULL;167struct etna_acc_query *aq;168struct etna_query *q;169170/* find a sample provide for the requested query type */171for (unsigned i = 0; i < ARRAY_SIZE(acc_sample_provider); i++) {172p = acc_sample_provider[i];173174if (p->supports(query_type))175break;176else177p = NULL;178}179180if (!p)181return NULL;182183aq = p->allocate(ctx, query_type);184if (!aq)185return NULL;186187aq->provider = p;188189list_inithead(&aq->node);190191q = &aq->base;192q->funcs = &acc_query_funcs;193q->type = query_type;194195return q;196}197198199