Home | History | Annotate | Download | only in ilo
      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 (at) 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]    = INFO(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_OCCLUSION_PREDICATE:
     79    case PIPE_QUERY_TIMESTAMP:
     80    case PIPE_QUERY_TIME_ELAPSED:
     81    case PIPE_QUERY_PRIMITIVES_GENERATED:
     82    case PIPE_QUERY_PRIMITIVES_EMITTED:
     83    case PIPE_QUERY_PIPELINE_STATISTICS:
     84       break;
     85    default:
     86       return NULL;
     87    }
     88 
     89    q = CALLOC_STRUCT(ilo_query);
     90    if (!q)
     91       return NULL;
     92 
     93    q->type = query_type;
     94    q->index = index;
     95 
     96    list_inithead(&q->list);
     97 
     98    if (!ilo_query_table[q->type].init(ilo_context(pipe), q)) {
     99       FREE(q);
    100       return NULL;
    101    }
    102 
    103    return (struct pipe_query *) q;
    104 }
    105 
    106 static void
    107 ilo_destroy_query(struct pipe_context *pipe, struct pipe_query *query)
    108 {
    109    struct ilo_query *q = ilo_query(query);
    110 
    111    intel_bo_unref(q->bo);
    112    FREE(q);
    113 }
    114 
    115 static boolean
    116 ilo_begin_query(struct pipe_context *pipe, struct pipe_query *query)
    117 {
    118    struct ilo_query *q = ilo_query(query);
    119 
    120    if (q->active)
    121       return false;
    122 
    123    util_query_clear_result(&q->result, q->type);
    124    q->used = 0;
    125    q->active = true;
    126 
    127    ilo_query_table[q->type].begin(ilo_context(pipe), q);
    128    return true;
    129 }
    130 
    131 static bool
    132 ilo_end_query(struct pipe_context *pipe, struct pipe_query *query)
    133 {
    134    struct ilo_query *q = ilo_query(query);
    135 
    136    if (!q->active) {
    137       /* require ilo_begin_query() first */
    138       if (q->in_pairs)
    139          return false;
    140 
    141       ilo_begin_query(pipe, query);
    142    }
    143 
    144    q->active = false;
    145 
    146    ilo_query_table[q->type].end(ilo_context(pipe), q);
    147 
    148    return true;
    149 }
    150 
    151 /**
    152  * Serialize the result.  The size of \p buf is
    153  * sizeof(union pipe_query_result).
    154  */
    155 static void
    156 query_serialize(const struct ilo_query *q, void *buf)
    157 {
    158    switch (q->type) {
    159    case PIPE_QUERY_OCCLUSION_COUNTER:
    160    case PIPE_QUERY_TIMESTAMP:
    161    case PIPE_QUERY_TIME_ELAPSED:
    162    case PIPE_QUERY_PRIMITIVES_GENERATED:
    163    case PIPE_QUERY_PRIMITIVES_EMITTED:
    164       {
    165          uint64_t *dst = buf;
    166          dst[0] = q->result.u64;
    167       }
    168       break;
    169    case PIPE_QUERY_OCCLUSION_PREDICATE:
    170       {
    171          uint64_t *dst = buf;
    172          dst[0] = !!q->result.u64;
    173       }
    174       break;
    175    case PIPE_QUERY_PIPELINE_STATISTICS:
    176       {
    177          const struct pipe_query_data_pipeline_statistics *stats =
    178             &q->result.pipeline_statistics;
    179          uint64_t *dst = buf;
    180 
    181          dst[0] = stats->ia_vertices;
    182          dst[1] = stats->ia_primitives;
    183          dst[2] = stats->vs_invocations;
    184          dst[3] = stats->gs_invocations;
    185          dst[4] = stats->gs_primitives;
    186          dst[5] = stats->c_invocations;
    187          dst[6] = stats->c_primitives;
    188          dst[7] = stats->ps_invocations;
    189          dst[8] = stats->hs_invocations;
    190          dst[9] = stats->ds_invocations;
    191          dst[10] = stats->cs_invocations;
    192       }
    193       break;
    194    default:
    195       memset(buf, 0, sizeof(union pipe_query_result));
    196       break;
    197    }
    198 }
    199 
    200 static boolean
    201 ilo_get_query_result(struct pipe_context *pipe, struct pipe_query *query,
    202                      boolean wait, union pipe_query_result *result)
    203 {
    204    struct ilo_query *q = ilo_query(query);
    205 
    206    if (q->active)
    207       return false;
    208 
    209    if (q->bo) {
    210       struct ilo_cp *cp = ilo_context(pipe)->cp;
    211 
    212       if (ilo_builder_has_reloc(&cp->builder, q->bo))
    213          ilo_cp_submit(cp, "syncing for queries");
    214 
    215       if (!wait && intel_bo_is_busy(q->bo))
    216          return false;
    217    }
    218 
    219    ilo_query_table[q->type].process(ilo_context(pipe), q);
    220 
    221    if (result)
    222       query_serialize(q, (void *) result);
    223 
    224    return true;
    225 }
    226 
    227 static void
    228 ilo_set_active_query_state(struct pipe_context *pipe, boolean enable)
    229 {
    230 }
    231 
    232 /**
    233  * Initialize query-related functions.
    234  */
    235 void
    236 ilo_init_query_functions(struct ilo_context *ilo)
    237 {
    238    ilo->base.create_query = ilo_create_query;
    239    ilo->base.destroy_query = ilo_destroy_query;
    240    ilo->base.begin_query = ilo_begin_query;
    241    ilo->base.end_query = ilo_end_query;
    242    ilo->base.get_query_result = ilo_get_query_result;
    243    ilo->base.set_active_query_state = ilo_set_active_query_state;
    244 }
    245