Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Mesa 3-D graphics library
  3.  *
  4.  * Copyright (C) 2012-2013 LunarG, Inc.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the "Software"),
  8.  * to deal in the Software without restriction, including without limitation
  9.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  10.  * and/or sell copies of the Software, and to permit persons to whom the
  11.  * Software is furnished to do so, subject to the following conditions:
  12.  *
  13.  * The above copyright notice and this permission notice shall be included
  14.  * in all copies or substantial portions of the Software.
  15.  *
  16.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  19.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  21.  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  22.  * DEALINGS IN THE SOFTWARE.
  23.  *
  24.  * Authors:
  25.  *    Chia-I Wu <olv@lunarg.com>
  26.  */
  27.  
  28. #include "core/intel_winsys.h"
  29.  
  30. #include "ilo_context.h"
  31. #include "ilo_cp.h"
  32. #include "ilo_draw.h"
  33. #include "ilo_query.h"
  34.  
  35. static const struct {
  36.    bool (*init)(struct ilo_context *ilo, struct ilo_query *q);
  37.    void (*begin)(struct ilo_context *ilo, struct ilo_query *q);
  38.    void (*end)(struct ilo_context *ilo, struct ilo_query *q);
  39.    void (*process)(struct ilo_context *ilo, struct ilo_query *q);
  40. } ilo_query_table[PIPE_QUERY_TYPES] = {
  41. #define INFO(mod) {                    \
  42.    .init = ilo_init_ ## mod ## _query,         \
  43.    .begin = ilo_begin_ ## mod ## _query,       \
  44.    .end = ilo_end_ ## mod ## _query,           \
  45.    .process = ilo_process_ ## mod ## _query,   \
  46. }
  47. #define INFOX(prefix) { NULL, NULL, NULL, NULL, }
  48.  
  49.    [PIPE_QUERY_OCCLUSION_COUNTER]      = INFO(draw),
  50.    [PIPE_QUERY_OCCLUSION_PREDICATE]    = INFOX(draw),
  51.    [PIPE_QUERY_TIMESTAMP]              = INFO(draw),
  52.    [PIPE_QUERY_TIMESTAMP_DISJOINT]     = INFOX(draw),
  53.    [PIPE_QUERY_TIME_ELAPSED]           = INFO(draw),
  54.    [PIPE_QUERY_PRIMITIVES_GENERATED]   = INFO(draw),
  55.    [PIPE_QUERY_PRIMITIVES_EMITTED]     = INFO(draw),
  56.    [PIPE_QUERY_SO_STATISTICS]          = INFOX(draw),
  57.    [PIPE_QUERY_SO_OVERFLOW_PREDICATE]  = INFOX(draw),
  58.    [PIPE_QUERY_GPU_FINISHED]           = INFOX(draw),
  59.    [PIPE_QUERY_PIPELINE_STATISTICS]    = INFO(draw),
  60.  
  61. #undef INFO
  62. #undef INFOX
  63. };
  64.  
  65. static inline struct ilo_query *
  66. ilo_query(struct pipe_query *query)
  67. {
  68.    return (struct ilo_query *) query;
  69. }
  70.  
  71. static struct pipe_query *
  72. ilo_create_query(struct pipe_context *pipe, unsigned query_type, unsigned index)
  73. {
  74.    struct ilo_query *q;
  75.  
  76.    switch (query_type) {
  77.    case PIPE_QUERY_OCCLUSION_COUNTER:
  78.    case PIPE_QUERY_TIMESTAMP:
  79.    case PIPE_QUERY_TIME_ELAPSED:
  80.    case PIPE_QUERY_PRIMITIVES_GENERATED:
  81.    case PIPE_QUERY_PRIMITIVES_EMITTED:
  82.    case PIPE_QUERY_PIPELINE_STATISTICS:
  83.       break;
  84.    default:
  85.       return NULL;
  86.    }
  87.  
  88.    q = CALLOC_STRUCT(ilo_query);
  89.    if (!q)
  90.       return NULL;
  91.  
  92.    q->type = query_type;
  93.    q->index = index;
  94.  
  95.    list_inithead(&q->list);
  96.  
  97.    if (!ilo_query_table[q->type].init(ilo_context(pipe), q)) {
  98.       FREE(q);
  99.       return NULL;
  100.    }
  101.  
  102.    return (struct pipe_query *) q;
  103. }
  104.  
  105. static void
  106. ilo_destroy_query(struct pipe_context *pipe, struct pipe_query *query)
  107. {
  108.    struct ilo_query *q = ilo_query(query);
  109.  
  110.    intel_bo_unref(q->bo);
  111.    FREE(q);
  112. }
  113.  
  114. static boolean
  115. ilo_begin_query(struct pipe_context *pipe, struct pipe_query *query)
  116. {
  117.    struct ilo_query *q = ilo_query(query);
  118.  
  119.    if (q->active)
  120.       return false;
  121.  
  122.    util_query_clear_result(&q->result, q->type);
  123.    q->used = 0;
  124.    q->active = true;
  125.  
  126.    ilo_query_table[q->type].begin(ilo_context(pipe), q);
  127.    return true;
  128. }
  129.  
  130. static void
  131. ilo_end_query(struct pipe_context *pipe, struct pipe_query *query)
  132. {
  133.    struct ilo_query *q = ilo_query(query);
  134.  
  135.    if (!q->active) {
  136.       /* require ilo_begin_query() first */
  137.       if (q->in_pairs)
  138.          return;
  139.  
  140.       ilo_begin_query(pipe, query);
  141.    }
  142.  
  143.    q->active = false;
  144.  
  145.    ilo_query_table[q->type].end(ilo_context(pipe), q);
  146. }
  147.  
  148. /**
  149.  * Serialize the result.  The size of \p buf is
  150.  * sizeof(union pipe_query_result).
  151.  */
  152. static void
  153. query_serialize(const struct ilo_query *q, void *buf)
  154. {
  155.    switch (q->type) {
  156.    case PIPE_QUERY_OCCLUSION_COUNTER:
  157.    case PIPE_QUERY_TIMESTAMP:
  158.    case PIPE_QUERY_TIME_ELAPSED:
  159.    case PIPE_QUERY_PRIMITIVES_GENERATED:
  160.    case PIPE_QUERY_PRIMITIVES_EMITTED:
  161.       {
  162.          uint64_t *dst = buf;
  163.          dst[0] = q->result.u64;
  164.       }
  165.       break;
  166.    case PIPE_QUERY_PIPELINE_STATISTICS:
  167.       {
  168.          const struct pipe_query_data_pipeline_statistics *stats =
  169.             &q->result.pipeline_statistics;
  170.          uint64_t *dst = buf;
  171.  
  172.          dst[0] = stats->ia_vertices;
  173.          dst[1] = stats->ia_primitives;
  174.          dst[2] = stats->vs_invocations;
  175.          dst[3] = stats->gs_invocations;
  176.          dst[4] = stats->gs_primitives;
  177.          dst[5] = stats->c_invocations;
  178.          dst[6] = stats->c_primitives;
  179.          dst[7] = stats->ps_invocations;
  180.          dst[8] = stats->hs_invocations;
  181.          dst[9] = stats->ds_invocations;
  182.          dst[10] = stats->cs_invocations;
  183.       }
  184.       break;
  185.    default:
  186.       memset(buf, 0, sizeof(union pipe_query_result));
  187.       break;
  188.    }
  189. }
  190.  
  191. static boolean
  192. ilo_get_query_result(struct pipe_context *pipe, struct pipe_query *query,
  193.                      boolean wait, union pipe_query_result *result)
  194. {
  195.    struct ilo_query *q = ilo_query(query);
  196.  
  197.    if (q->active)
  198.       return false;
  199.  
  200.    if (q->bo) {
  201.       struct ilo_cp *cp = ilo_context(pipe)->cp;
  202.  
  203.       if (ilo_builder_has_reloc(&cp->builder, q->bo))
  204.          ilo_cp_submit(cp, "syncing for queries");
  205.  
  206.       if (!wait && intel_bo_is_busy(q->bo))
  207.          return false;
  208.    }
  209.  
  210.    ilo_query_table[q->type].process(ilo_context(pipe), q);
  211.  
  212.    if (result)
  213.       query_serialize(q, (void *) result);
  214.  
  215.    return true;
  216. }
  217.  
  218. /**
  219.  * Initialize query-related functions.
  220.  */
  221. void
  222. ilo_init_query_functions(struct ilo_context *ilo)
  223. {
  224.    ilo->base.create_query = ilo_create_query;
  225.    ilo->base.destroy_query = ilo_destroy_query;
  226.    ilo->base.begin_query = ilo_begin_query;
  227.    ilo->base.end_query = ilo_end_query;
  228.    ilo->base.get_query_result = ilo_get_query_result;
  229. }
  230.