"Fossies" - the Fresh Open Source Software Archive

Member "mesa-20.1.8/src/gallium/drivers/zink/zink_query.c" (16 Sep 2020, 7586 Bytes) of package /linux/misc/mesa-20.1.8.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "zink_query.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 20.1.5_vs_20.2.0-rc1.

    1 #include "zink_query.h"
    2 
    3 #include "zink_context.h"
    4 #include "zink_screen.h"
    5 
    6 #include "util/u_dump.h"
    7 #include "util/u_inlines.h"
    8 #include "util/u_memory.h"
    9 
   10 struct zink_query {
   11    enum pipe_query_type type;
   12 
   13    VkQueryPool query_pool;
   14    unsigned curr_query, num_queries;
   15 
   16    VkQueryType vkqtype;
   17    bool use_64bit;
   18    bool precise;
   19 
   20    struct list_head active_list;
   21 };
   22 
   23 static VkQueryType
   24 convert_query_type(unsigned query_type, bool *use_64bit, bool *precise)
   25 {
   26    *use_64bit = false;
   27    *precise = false;
   28    switch (query_type) {
   29    case PIPE_QUERY_OCCLUSION_COUNTER:
   30       *precise = true;
   31       *use_64bit = true;
   32    case PIPE_QUERY_OCCLUSION_PREDICATE:
   33    case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
   34       return VK_QUERY_TYPE_OCCLUSION;
   35    case PIPE_QUERY_TIMESTAMP:
   36       *use_64bit = true;
   37       return VK_QUERY_TYPE_TIMESTAMP;
   38    case PIPE_QUERY_PIPELINE_STATISTICS:
   39       return VK_QUERY_TYPE_PIPELINE_STATISTICS;
   40    default:
   41       debug_printf("unknown query: %s\n",
   42                    util_str_query_type(query_type, true));
   43       unreachable("zink: unknown query type");
   44    }
   45 }
   46 
   47 static struct pipe_query *
   48 zink_create_query(struct pipe_context *pctx,
   49                   unsigned query_type, unsigned index)
   50 {
   51    struct zink_screen *screen = zink_screen(pctx->screen);
   52    struct zink_query *query = CALLOC_STRUCT(zink_query);
   53    VkQueryPoolCreateInfo pool_create = {};
   54 
   55    if (!query)
   56       return NULL;
   57 
   58    query->type = query_type;
   59    query->vkqtype = convert_query_type(query_type, &query->use_64bit, &query->precise);
   60    if (query->vkqtype == -1)
   61       return NULL;
   62 
   63    query->num_queries = query_type == PIPE_QUERY_TIMESTAMP ? 1 : 100;
   64    query->curr_query = 0;
   65 
   66    pool_create.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO;
   67    pool_create.queryType = query->vkqtype;
   68    pool_create.queryCount = query->num_queries;
   69 
   70    VkResult status = vkCreateQueryPool(screen->dev, &pool_create, NULL, &query->query_pool);
   71    if (status != VK_SUCCESS) {
   72       FREE(query);
   73       return NULL;
   74    }
   75    return (struct pipe_query *)query;
   76 }
   77 
   78 static void
   79 zink_destroy_query(struct pipe_context *pctx,
   80                    struct pipe_query *q)
   81 {
   82    struct zink_screen *screen = zink_screen(pctx->screen);
   83    struct zink_query *query = (struct zink_query *)q;
   84 
   85    vkDestroyQueryPool(screen->dev, query->query_pool, NULL);
   86 }
   87 
   88 static void
   89 begin_query(struct zink_context *ctx, struct zink_query *q)
   90 {
   91    VkQueryControlFlags flags = 0;
   92    if (q->precise)
   93       flags |= VK_QUERY_CONTROL_PRECISE_BIT;
   94 
   95    struct zink_batch *batch = zink_curr_batch(ctx);
   96    vkCmdBeginQuery(batch->cmdbuf, q->query_pool, q->curr_query, flags);
   97 }
   98 
   99 static bool
  100 zink_begin_query(struct pipe_context *pctx,
  101                  struct pipe_query *q)
  102 {
  103    struct zink_context *ctx = zink_context(pctx);
  104    struct zink_query *query = (struct zink_query *)q;
  105 
  106    /* ignore begin_query for timestamps */
  107    if (query->type == PIPE_QUERY_TIMESTAMP)
  108       return true;
  109 
  110    /* TODO: resetting on begin isn't ideal, as it forces render-pass exit...
  111     * should instead reset on creation (if possible?)... Or perhaps maintain
  112     * the pool in the batch instead?
  113     */
  114    struct zink_batch *batch = zink_batch_no_rp(zink_context(pctx));
  115    vkCmdResetQueryPool(batch->cmdbuf, query->query_pool, 0, query->curr_query);
  116    query->curr_query = 0;
  117 
  118    begin_query(ctx, query);
  119    list_addtail(&query->active_list, &ctx->active_queries);
  120 
  121    return true;
  122 }
  123 
  124 static void
  125 end_query(struct zink_context *ctx, struct zink_query *q)
  126 {
  127    struct zink_batch *batch = zink_curr_batch(ctx);
  128    assert(q->type != PIPE_QUERY_TIMESTAMP);
  129    vkCmdEndQuery(batch->cmdbuf, q->query_pool, q->curr_query);
  130    if (++q->curr_query == q->num_queries) {
  131       assert(0);
  132       /* need to reset pool! */
  133    }
  134 }
  135 
  136 static bool
  137 zink_end_query(struct pipe_context *pctx,
  138                struct pipe_query *q)
  139 {
  140    struct zink_context *ctx = zink_context(pctx);
  141    struct zink_query *query = (struct zink_query *)q;
  142 
  143    if (query->type == PIPE_QUERY_TIMESTAMP) {
  144       assert(query->curr_query == 0);
  145       struct zink_batch *batch = zink_curr_batch(ctx);
  146       vkCmdWriteTimestamp(batch->cmdbuf, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
  147                           query->query_pool, 0);
  148    } else {
  149       end_query(ctx, query);
  150       list_delinit(&query->active_list);
  151    }
  152 
  153    return true;
  154 }
  155 
  156 static bool
  157 zink_get_query_result(struct pipe_context *pctx,
  158                       struct pipe_query *q,
  159                       bool wait,
  160                       union pipe_query_result *result)
  161 {
  162    struct zink_screen *screen = zink_screen(pctx->screen);
  163    struct zink_query *query = (struct zink_query *)q;
  164    VkQueryResultFlagBits flags = 0;
  165 
  166    if (wait) {
  167       struct pipe_fence_handle *fence = NULL;
  168       pctx->flush(pctx, &fence, PIPE_FLUSH_HINT_FINISH);
  169       if (fence) {
  170          pctx->screen->fence_finish(pctx->screen, NULL, fence,
  171                                     PIPE_TIMEOUT_INFINITE);
  172          pctx->screen->fence_reference(pctx->screen, &fence, NULL);
  173       }
  174       flags |= VK_QUERY_RESULT_WAIT_BIT;
  175    } else
  176       pctx->flush(pctx, NULL, 0);
  177 
  178    if (query->use_64bit)
  179       flags |= VK_QUERY_RESULT_64_BIT;
  180 
  181    // TODO: handle curr_query > 100
  182    // union pipe_query_result results[100];
  183    uint64_t results[100];
  184    memset(results, 0, sizeof(results));
  185    assert(query->curr_query <= ARRAY_SIZE(results));
  186    if (vkGetQueryPoolResults(screen->dev, query->query_pool,
  187                              0, query->curr_query,
  188                              sizeof(results),
  189                              results,
  190                              sizeof(uint64_t),
  191                              flags) != VK_SUCCESS)
  192       return false;
  193 
  194    util_query_clear_result(result, query->type);
  195    for (int i = 0; i < query->curr_query; ++i) {
  196       switch (query->type) {
  197       case PIPE_QUERY_OCCLUSION_PREDICATE:
  198       case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
  199       case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
  200       case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE:
  201       case PIPE_QUERY_GPU_FINISHED:
  202          result->b |= results[i] != 0;
  203          break;
  204 
  205       case PIPE_QUERY_OCCLUSION_COUNTER:
  206          result->u64 += results[i];
  207          break;
  208 
  209       default:
  210          debug_printf("unhangled query type: %s\n",
  211                       util_str_query_type(query->type, true));
  212          unreachable("unexpected query type");
  213       }
  214    }
  215 
  216    return TRUE;
  217 }
  218 
  219 void
  220 zink_suspend_queries(struct zink_context *ctx, struct zink_batch *batch)
  221 {
  222    struct zink_query *query;
  223    LIST_FOR_EACH_ENTRY(query, &ctx->active_queries, active_list) {
  224       end_query(ctx, query);
  225    }
  226 }
  227 
  228 void
  229 zink_resume_queries(struct zink_context *ctx, struct zink_batch *batch)
  230 {
  231    struct zink_query *query;
  232    LIST_FOR_EACH_ENTRY(query, &ctx->active_queries, active_list) {
  233       begin_query(ctx, query);
  234    }
  235 }
  236 
  237 static void
  238 zink_set_active_query_state(struct pipe_context *pctx, bool enable)
  239 {
  240    struct zink_context *ctx = zink_context(pctx);
  241    ctx->queries_disabled = !enable;
  242 
  243    struct zink_batch *batch = zink_curr_batch(ctx);
  244    if (ctx->queries_disabled)
  245       zink_suspend_queries(ctx, batch);
  246    else
  247       zink_resume_queries(ctx, batch);
  248 }
  249 
  250 void
  251 zink_context_query_init(struct pipe_context *pctx)
  252 {
  253    struct zink_context *ctx = zink_context(pctx);
  254    list_inithead(&ctx->active_queries);
  255 
  256    pctx->create_query = zink_create_query;
  257    pctx->destroy_query = zink_destroy_query;
  258    pctx->begin_query = zink_begin_query;
  259    pctx->end_query = zink_end_query;
  260    pctx->get_query_result = zink_get_query_result;
  261    pctx->set_active_query_state = zink_set_active_query_state;
  262 }