Home | History | Annotate | Line # | Download | only in iris
      1 /*
      2  * Copyright  2017 Intel Corporation
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8  * and/or sell copies of the Software, and to permit persons to whom the
      9  * Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice shall be included
     12  * in all copies or substantial portions of the Software.
     13  *
     14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     15  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     17  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     20  * DEALINGS IN THE SOFTWARE.
     21  */
     22 
     23 /**
     24  * @file iris_query.c
     25  *
     26  * ============================= GENXML CODE =============================
     27  *              [This file is compiled once per generation.]
     28  * =======================================================================
     29  *
     30  * Query object support.  This allows measuring various simple statistics
     31  * via counters on the GPU.  We use GenX code for MI_MATH calculations.
     32  */
     33 
     34 #include <stdio.h>
     35 #include <errno.h>
     36 #include "pipe/p_defines.h"
     37 #include "pipe/p_state.h"
     38 #include "pipe/p_context.h"
     39 #include "pipe/p_screen.h"
     40 #include "util/u_inlines.h"
     41 #include "util/u_upload_mgr.h"
     42 #include "iris_context.h"
     43 #include "iris_defines.h"
     44 #include "iris_fence.h"
     45 #include "iris_monitor.h"
     46 #include "iris_resource.h"
     47 #include "iris_screen.h"
     48 
     49 #include "iris_genx_macros.h"
     50 
     51 #define SO_PRIM_STORAGE_NEEDED(n) (GENX(SO_PRIM_STORAGE_NEEDED0_num) + (n) * 8)
     52 #define SO_NUM_PRIMS_WRITTEN(n)   (GENX(SO_NUM_PRIMS_WRITTEN0_num) + (n) * 8)
     53 
     54 struct iris_query {
     55    struct threaded_query b;
     56 
     57    enum pipe_query_type type;
     58    int index;
     59 
     60    bool ready;
     61 
     62    bool stalled;
     63 
     64    uint64_t result;
     65 
     66    struct iris_state_ref query_state_ref;
     67    struct iris_query_snapshots *map;
     68    struct iris_syncobj *syncobj;
     69 
     70    int batch_idx;
     71 
     72    struct iris_monitor_object *monitor;
     73 
     74    /* Fence for PIPE_QUERY_GPU_FINISHED. */
     75    struct pipe_fence_handle *fence;
     76 };
     77 
     78 struct iris_query_snapshots {
     79    /** iris_render_condition's saved MI_PREDICATE_RESULT value. */
     80    uint64_t predicate_result;
     81 
     82    /** Have the start/end snapshots landed? */
     83    uint64_t snapshots_landed;
     84 
     85    /** Starting and ending counter snapshots */
     86    uint64_t start;
     87    uint64_t end;
     88 };
     89 
     90 struct iris_query_so_overflow {
     91    uint64_t predicate_result;
     92    uint64_t snapshots_landed;
     93 
     94    struct {
     95       uint64_t prim_storage_needed[2];
     96       uint64_t num_prims[2];
     97    } stream[4];
     98 };
     99 
    100 static struct mi_value
    101 query_mem64(struct iris_query *q, uint32_t offset)
    102 {
    103    struct iris_address addr = {
    104       .bo = iris_resource_bo(q->query_state_ref.res),
    105       .offset = q->query_state_ref.offset + offset,
    106       .access = IRIS_DOMAIN_OTHER_WRITE
    107    };
    108    return mi_mem64(addr);
    109 }
    110 
    111 /**
    112  * Is this type of query written by PIPE_CONTROL?
    113  */
    114 static bool
    115 iris_is_query_pipelined(struct iris_query *q)
    116 {
    117    switch (q->type) {
    118    case PIPE_QUERY_OCCLUSION_COUNTER:
    119    case PIPE_QUERY_OCCLUSION_PREDICATE:
    120    case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
    121    case PIPE_QUERY_TIMESTAMP:
    122    case PIPE_QUERY_TIMESTAMP_DISJOINT:
    123    case PIPE_QUERY_TIME_ELAPSED:
    124       return true;
    125 
    126    default:
    127       return false;
    128    }
    129 }
    130 
    131 static void
    132 mark_available(struct iris_context *ice, struct iris_query *q)
    133 {
    134    struct iris_batch *batch = &ice->batches[q->batch_idx];
    135    unsigned flags = PIPE_CONTROL_WRITE_IMMEDIATE;
    136    unsigned offset = offsetof(struct iris_query_snapshots, snapshots_landed);
    137    struct iris_bo *bo = iris_resource_bo(q->query_state_ref.res);
    138    offset += q->query_state_ref.offset;
    139 
    140    if (!iris_is_query_pipelined(q)) {
    141       batch->screen->vtbl.store_data_imm64(batch, bo, offset, true);
    142    } else {
    143       /* Order available *after* the query results. */
    144       flags |= PIPE_CONTROL_FLUSH_ENABLE;
    145       iris_emit_pipe_control_write(batch, "query: mark available",
    146                                    flags, bo, offset, true);
    147    }
    148 }
    149 
    150 /**
    151  * Write PS_DEPTH_COUNT to q->(dest) via a PIPE_CONTROL.
    152  */
    153 static void
    154 iris_pipelined_write(struct iris_batch *batch,
    155                      struct iris_query *q,
    156                      enum pipe_control_flags flags,
    157                      unsigned offset)
    158 {
    159    const struct intel_device_info *devinfo = &batch->screen->devinfo;
    160    const unsigned optional_cs_stall =
    161       GFX_VER == 9 && devinfo->gt == 4 ?  PIPE_CONTROL_CS_STALL : 0;
    162    struct iris_bo *bo = iris_resource_bo(q->query_state_ref.res);
    163 
    164    iris_emit_pipe_control_write(batch, "query: pipelined snapshot write",
    165                                 flags | optional_cs_stall,
    166                                 bo, offset, 0ull);
    167 }
    168 
    169 static void
    170 write_value(struct iris_context *ice, struct iris_query *q, unsigned offset)
    171 {
    172    struct iris_batch *batch = &ice->batches[q->batch_idx];
    173    struct iris_bo *bo = iris_resource_bo(q->query_state_ref.res);
    174 
    175    if (!iris_is_query_pipelined(q)) {
    176       iris_emit_pipe_control_flush(batch,
    177                                    "query: non-pipelined snapshot write",
    178                                    PIPE_CONTROL_CS_STALL |
    179                                    PIPE_CONTROL_STALL_AT_SCOREBOARD);
    180       q->stalled = true;
    181    }
    182 
    183    switch (q->type) {
    184    case PIPE_QUERY_OCCLUSION_COUNTER:
    185    case PIPE_QUERY_OCCLUSION_PREDICATE:
    186    case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
    187       if (GFX_VER >= 10) {
    188          /* "Driver must program PIPE_CONTROL with only Depth Stall Enable
    189           *  bit set prior to programming a PIPE_CONTROL with Write PS Depth
    190           *  Count sync operation."
    191           */
    192          iris_emit_pipe_control_flush(batch,
    193                                       "workaround: depth stall before writing "
    194                                       "PS_DEPTH_COUNT",
    195                                       PIPE_CONTROL_DEPTH_STALL);
    196       }
    197       iris_pipelined_write(&ice->batches[IRIS_BATCH_RENDER], q,
    198                            PIPE_CONTROL_WRITE_DEPTH_COUNT |
    199                            PIPE_CONTROL_DEPTH_STALL,
    200                            offset);
    201       break;
    202    case PIPE_QUERY_TIME_ELAPSED:
    203    case PIPE_QUERY_TIMESTAMP:
    204    case PIPE_QUERY_TIMESTAMP_DISJOINT:
    205       iris_pipelined_write(&ice->batches[IRIS_BATCH_RENDER], q,
    206                            PIPE_CONTROL_WRITE_TIMESTAMP,
    207                            offset);
    208       break;
    209    case PIPE_QUERY_PRIMITIVES_GENERATED:
    210       batch->screen->vtbl.store_register_mem64(batch,
    211                                      q->index == 0 ?
    212                                      GENX(CL_INVOCATION_COUNT_num) :
    213                                      SO_PRIM_STORAGE_NEEDED(q->index),
    214                                      bo, offset, false);
    215       break;
    216    case PIPE_QUERY_PRIMITIVES_EMITTED:
    217       batch->screen->vtbl.store_register_mem64(batch,
    218                                      SO_NUM_PRIMS_WRITTEN(q->index),
    219                                      bo, offset, false);
    220       break;
    221    case PIPE_QUERY_PIPELINE_STATISTICS_SINGLE: {
    222       static const uint32_t index_to_reg[] = {
    223          GENX(IA_VERTICES_COUNT_num),
    224          GENX(IA_PRIMITIVES_COUNT_num),
    225          GENX(VS_INVOCATION_COUNT_num),
    226          GENX(GS_INVOCATION_COUNT_num),
    227          GENX(GS_PRIMITIVES_COUNT_num),
    228          GENX(CL_INVOCATION_COUNT_num),
    229          GENX(CL_PRIMITIVES_COUNT_num),
    230          GENX(PS_INVOCATION_COUNT_num),
    231          GENX(HS_INVOCATION_COUNT_num),
    232          GENX(DS_INVOCATION_COUNT_num),
    233          GENX(CS_INVOCATION_COUNT_num),
    234       };
    235       const uint32_t reg = index_to_reg[q->index];
    236 
    237       batch->screen->vtbl.store_register_mem64(batch, reg, bo, offset, false);
    238       break;
    239    }
    240    default:
    241       assert(false);
    242    }
    243 }
    244 
    245 static void
    246 write_overflow_values(struct iris_context *ice, struct iris_query *q, bool end)
    247 {
    248    struct iris_batch *batch = &ice->batches[IRIS_BATCH_RENDER];
    249    uint32_t count = q->type == PIPE_QUERY_SO_OVERFLOW_PREDICATE ? 1 : 4;
    250    struct iris_bo *bo = iris_resource_bo(q->query_state_ref.res);
    251    uint32_t offset = q->query_state_ref.offset;
    252 
    253    iris_emit_pipe_control_flush(batch,
    254                                 "query: write SO overflow snapshots",
    255                                 PIPE_CONTROL_CS_STALL |
    256                                 PIPE_CONTROL_STALL_AT_SCOREBOARD);
    257    for (uint32_t i = 0; i < count; i++) {
    258       int s = q->index + i;
    259       int g_idx = offset + offsetof(struct iris_query_so_overflow,
    260                            stream[s].num_prims[end]);
    261       int w_idx = offset + offsetof(struct iris_query_so_overflow,
    262                            stream[s].prim_storage_needed[end]);
    263       batch->screen->vtbl.store_register_mem64(batch, SO_NUM_PRIMS_WRITTEN(s),
    264                                      bo, g_idx, false);
    265       batch->screen->vtbl.store_register_mem64(batch, SO_PRIM_STORAGE_NEEDED(s),
    266                                      bo, w_idx, false);
    267    }
    268 }
    269 
    270 static uint64_t
    271 iris_raw_timestamp_delta(uint64_t time0, uint64_t time1)
    272 {
    273    if (time0 > time1) {
    274       return (1ULL << TIMESTAMP_BITS) + time1 - time0;
    275    } else {
    276       return time1 - time0;
    277    }
    278 }
    279 
    280 static bool
    281 stream_overflowed(struct iris_query_so_overflow *so, int s)
    282 {
    283    return (so->stream[s].prim_storage_needed[1] -
    284            so->stream[s].prim_storage_needed[0]) !=
    285           (so->stream[s].num_prims[1] - so->stream[s].num_prims[0]);
    286 }
    287 
    288 static void
    289 calculate_result_on_cpu(const struct intel_device_info *devinfo,
    290                         struct iris_query *q)
    291 {
    292    switch (q->type) {
    293    case PIPE_QUERY_OCCLUSION_PREDICATE:
    294    case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
    295       q->result = q->map->end != q->map->start;
    296       break;
    297    case PIPE_QUERY_TIMESTAMP:
    298    case PIPE_QUERY_TIMESTAMP_DISJOINT:
    299       /* The timestamp is the single starting snapshot. */
    300       q->result = intel_device_info_timebase_scale(devinfo, q->map->start);
    301       q->result &= (1ull << TIMESTAMP_BITS) - 1;
    302       break;
    303    case PIPE_QUERY_TIME_ELAPSED:
    304       q->result = iris_raw_timestamp_delta(q->map->start, q->map->end);
    305       q->result = intel_device_info_timebase_scale(devinfo, q->result);
    306       q->result &= (1ull << TIMESTAMP_BITS) - 1;
    307       break;
    308    case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
    309       q->result = stream_overflowed((void *) q->map, q->index);
    310       break;
    311    case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE:
    312       q->result = false;
    313       for (int i = 0; i < MAX_VERTEX_STREAMS; i++)
    314          q->result |= stream_overflowed((void *) q->map, i);
    315       break;
    316    case PIPE_QUERY_PIPELINE_STATISTICS_SINGLE:
    317       q->result = q->map->end - q->map->start;
    318 
    319       /* WaDividePSInvocationCountBy4:HSW,BDW */
    320       if (GFX_VER == 8 && q->index == PIPE_STAT_QUERY_PS_INVOCATIONS)
    321          q->result /= 4;
    322       break;
    323    case PIPE_QUERY_OCCLUSION_COUNTER:
    324    case PIPE_QUERY_PRIMITIVES_GENERATED:
    325    case PIPE_QUERY_PRIMITIVES_EMITTED:
    326    default:
    327       q->result = q->map->end - q->map->start;
    328       break;
    329    }
    330 
    331    q->ready = true;
    332 }
    333 
    334 /**
    335  * Calculate the streamout overflow for stream \p idx:
    336  *
    337  * (num_prims[1] - num_prims[0]) - (storage_needed[1] - storage_needed[0])
    338  */
    339 static struct mi_value
    340 calc_overflow_for_stream(struct mi_builder *b,
    341                          struct iris_query *q,
    342                          int idx)
    343 {
    344 #define C(counter, i) query_mem64(q, \
    345    offsetof(struct iris_query_so_overflow, stream[idx].counter[i]))
    346 
    347    return mi_isub(b, mi_isub(b, C(num_prims, 1), C(num_prims, 0)),
    348                      mi_isub(b, C(prim_storage_needed, 1),
    349                                 C(prim_storage_needed, 0)));
    350 #undef C
    351 }
    352 
    353 /**
    354  * Calculate whether any stream has overflowed.
    355  */
    356 static struct mi_value
    357 calc_overflow_any_stream(struct mi_builder *b, struct iris_query *q)
    358 {
    359    struct mi_value stream_result[MAX_VERTEX_STREAMS];
    360    for (int i = 0; i < MAX_VERTEX_STREAMS; i++)
    361       stream_result[i] = calc_overflow_for_stream(b, q, i);
    362 
    363    struct mi_value result = stream_result[0];
    364    for (int i = 1; i < MAX_VERTEX_STREAMS; i++)
    365       result = mi_ior(b, result, stream_result[i]);
    366 
    367    return result;
    368 }
    369 
    370 static bool
    371 query_is_boolean(enum pipe_query_type type)
    372 {
    373    switch (type) {
    374    case PIPE_QUERY_OCCLUSION_PREDICATE:
    375    case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
    376    case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
    377    case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE:
    378       return true;
    379    default:
    380       return false;
    381    }
    382 }
    383 
    384 /**
    385  * Calculate the result using MI_MATH.
    386  */
    387 static struct mi_value
    388 calculate_result_on_gpu(const struct intel_device_info *devinfo,
    389                         struct mi_builder *b,
    390                         struct iris_query *q)
    391 {
    392    struct mi_value result;
    393    struct mi_value start_val =
    394       query_mem64(q, offsetof(struct iris_query_snapshots, start));
    395    struct mi_value end_val =
    396       query_mem64(q, offsetof(struct iris_query_snapshots, end));
    397 
    398    switch (q->type) {
    399    case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
    400       result = calc_overflow_for_stream(b, q, q->index);
    401       break;
    402    case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE:
    403       result = calc_overflow_any_stream(b, q);
    404       break;
    405    case PIPE_QUERY_TIMESTAMP: {
    406       /* TODO: This discards any fractional bits of the timebase scale.
    407        * We would need to do a bit of fixed point math on the CS ALU, or
    408        * launch an actual shader to calculate this with full precision.
    409        */
    410       uint32_t scale = 1000000000ull / devinfo->timestamp_frequency;
    411       result = mi_iand(b, mi_imm((1ull << 36) - 1),
    412                           mi_imul_imm(b, start_val, scale));
    413       break;
    414    }
    415    case PIPE_QUERY_TIME_ELAPSED: {
    416       /* TODO: This discards fractional bits (see above). */
    417       uint32_t scale = 1000000000ull / devinfo->timestamp_frequency;
    418       result = mi_imul_imm(b, mi_isub(b, end_val, start_val), scale);
    419       break;
    420    }
    421    default:
    422       result = mi_isub(b, end_val, start_val);
    423       break;
    424    }
    425 
    426    /* WaDividePSInvocationCountBy4:HSW,BDW */
    427    if (GFX_VER == 8 &&
    428        q->type == PIPE_QUERY_PIPELINE_STATISTICS_SINGLE &&
    429        q->index == PIPE_STAT_QUERY_PS_INVOCATIONS)
    430       result = mi_ushr32_imm(b, result, 2);
    431 
    432    if (query_is_boolean(q->type))
    433       result = mi_iand(b, mi_nz(b, result), mi_imm(1));
    434 
    435    return result;
    436 }
    437 
    438 static struct pipe_query *
    439 iris_create_query(struct pipe_context *ctx,
    440                   unsigned query_type,
    441                   unsigned index)
    442 {
    443    struct iris_query *q = calloc(1, sizeof(struct iris_query));
    444 
    445    q->type = query_type;
    446    q->index = index;
    447    q->monitor = NULL;
    448 
    449    if (q->type == PIPE_QUERY_PIPELINE_STATISTICS_SINGLE &&
    450        q->index == PIPE_STAT_QUERY_CS_INVOCATIONS)
    451       q->batch_idx = IRIS_BATCH_COMPUTE;
    452    else
    453       q->batch_idx = IRIS_BATCH_RENDER;
    454    return (struct pipe_query *) q;
    455 }
    456 
    457 static struct pipe_query *
    458 iris_create_batch_query(struct pipe_context *ctx,
    459                         unsigned num_queries,
    460                         unsigned *query_types)
    461 {
    462    struct iris_context *ice = (void *) ctx;
    463    struct iris_query *q = calloc(1, sizeof(struct iris_query));
    464    if (unlikely(!q))
    465       return NULL;
    466    q->type = PIPE_QUERY_DRIVER_SPECIFIC;
    467    q->index = -1;
    468    q->monitor = iris_create_monitor_object(ice, num_queries, query_types);
    469    if (unlikely(!q->monitor)) {
    470       free(q);
    471       return NULL;
    472    }
    473 
    474    return (struct pipe_query *) q;
    475 }
    476 
    477 static void
    478 iris_destroy_query(struct pipe_context *ctx, struct pipe_query *p_query)
    479 {
    480    struct iris_query *query = (void *) p_query;
    481    struct iris_screen *screen = (void *) ctx->screen;
    482    if (query->monitor) {
    483       iris_destroy_monitor_object(ctx, query->monitor);
    484       query->monitor = NULL;
    485    } else {
    486       iris_syncobj_reference(screen->bufmgr, &query->syncobj, NULL);
    487       screen->base.fence_reference(ctx->screen, &query->fence, NULL);
    488    }
    489    pipe_resource_reference(&query->query_state_ref.res, NULL);
    490    free(query);
    491 }
    492 
    493 
    494 static bool
    495 iris_begin_query(struct pipe_context *ctx, struct pipe_query *query)
    496 {
    497    struct iris_context *ice = (void *) ctx;
    498    struct iris_query *q = (void *) query;
    499 
    500    if (q->monitor)
    501       return iris_begin_monitor(ctx, q->monitor);
    502 
    503    void *ptr = NULL;
    504    uint32_t size;
    505 
    506    if (q->type == PIPE_QUERY_SO_OVERFLOW_PREDICATE ||
    507        q->type == PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE)
    508       size = sizeof(struct iris_query_so_overflow);
    509    else
    510       size = sizeof(struct iris_query_snapshots);
    511 
    512    u_upload_alloc(ice->query_buffer_uploader, 0,
    513                   size, size, &q->query_state_ref.offset,
    514                   &q->query_state_ref.res, &ptr);
    515 
    516    if (!iris_resource_bo(q->query_state_ref.res))
    517       return false;
    518 
    519    q->map = ptr;
    520    if (!q->map)
    521       return false;
    522 
    523    q->result = 0ull;
    524    q->ready = false;
    525    WRITE_ONCE(q->map->snapshots_landed, false);
    526 
    527    if (q->type == PIPE_QUERY_PRIMITIVES_GENERATED && q->index == 0) {
    528       ice->state.prims_generated_query_active = true;
    529       ice->state.dirty |= IRIS_DIRTY_STREAMOUT | IRIS_DIRTY_CLIP;
    530    }
    531 
    532    if (q->type == PIPE_QUERY_SO_OVERFLOW_PREDICATE ||
    533        q->type == PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE)
    534       write_overflow_values(ice, q, false);
    535    else
    536       write_value(ice, q,
    537                   q->query_state_ref.offset +
    538                   offsetof(struct iris_query_snapshots, start));
    539 
    540    return true;
    541 }
    542 
    543 static bool
    544 iris_end_query(struct pipe_context *ctx, struct pipe_query *query)
    545 {
    546    struct iris_context *ice = (void *) ctx;
    547    struct iris_query *q = (void *) query;
    548 
    549    if (q->monitor)
    550       return iris_end_monitor(ctx, q->monitor);
    551 
    552    if (q->type == PIPE_QUERY_GPU_FINISHED) {
    553       ctx->flush(ctx, &q->fence, PIPE_FLUSH_DEFERRED);
    554       return true;
    555    }
    556 
    557    struct iris_batch *batch = &ice->batches[q->batch_idx];
    558 
    559    if (q->type == PIPE_QUERY_TIMESTAMP) {
    560       iris_begin_query(ctx, query);
    561       iris_batch_reference_signal_syncobj(batch, &q->syncobj);
    562       mark_available(ice, q);
    563       return true;
    564    }
    565 
    566    if (q->type == PIPE_QUERY_PRIMITIVES_GENERATED && q->index == 0) {
    567       ice->state.prims_generated_query_active = false;
    568       ice->state.dirty |= IRIS_DIRTY_STREAMOUT | IRIS_DIRTY_CLIP;
    569    }
    570 
    571    if (q->type == PIPE_QUERY_SO_OVERFLOW_PREDICATE ||
    572        q->type == PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE)
    573       write_overflow_values(ice, q, true);
    574    else
    575       write_value(ice, q,
    576                   q->query_state_ref.offset +
    577                   offsetof(struct iris_query_snapshots, end));
    578 
    579    iris_batch_reference_signal_syncobj(batch, &q->syncobj);
    580    mark_available(ice, q);
    581 
    582    return true;
    583 }
    584 
    585 /**
    586  * See if the snapshots have landed for a query, and if so, compute the
    587  * result and mark it ready.  Does not flush (unlike iris_get_query_result).
    588  */
    589 static void
    590 iris_check_query_no_flush(struct iris_context *ice, struct iris_query *q)
    591 {
    592    struct iris_screen *screen = (void *) ice->ctx.screen;
    593    const struct intel_device_info *devinfo = &screen->devinfo;
    594 
    595    if (!q->ready && READ_ONCE(q->map->snapshots_landed)) {
    596       calculate_result_on_cpu(devinfo, q);
    597    }
    598 }
    599 
    600 static bool
    601 iris_get_query_result(struct pipe_context *ctx,
    602                       struct pipe_query *query,
    603                       bool wait,
    604                       union pipe_query_result *result)
    605 {
    606    struct iris_context *ice = (void *) ctx;
    607    struct iris_query *q = (void *) query;
    608 
    609    if (q->monitor)
    610       return iris_get_monitor_result(ctx, q->monitor, wait, result->batch);
    611 
    612    struct iris_screen *screen = (void *) ctx->screen;
    613    const struct intel_device_info *devinfo = &screen->devinfo;
    614 
    615    if (unlikely(screen->devinfo.no_hw)) {
    616       result->u64 = 0;
    617       return true;
    618    }
    619 
    620    if (q->type == PIPE_QUERY_GPU_FINISHED) {
    621       struct pipe_screen *screen = ctx->screen;
    622 
    623       result->b = screen->fence_finish(screen, ctx, q->fence,
    624                                        wait ? PIPE_TIMEOUT_INFINITE : 0);
    625       return result->b;
    626    }
    627 
    628    if (!q->ready) {
    629       struct iris_batch *batch = &ice->batches[q->batch_idx];
    630       if (q->syncobj == iris_batch_get_signal_syncobj(batch))
    631          iris_batch_flush(batch);
    632 
    633       while (!READ_ONCE(q->map->snapshots_landed)) {
    634          if (wait)
    635             iris_wait_syncobj(screen->bufmgr, q->syncobj, INT64_MAX);
    636          else
    637             return false;
    638       }
    639 
    640       assert(READ_ONCE(q->map->snapshots_landed));
    641       calculate_result_on_cpu(devinfo, q);
    642    }
    643 
    644    assert(q->ready);
    645 
    646    result->u64 = q->result;
    647 
    648    return true;
    649 }
    650 
    651 static void
    652 iris_get_query_result_resource(struct pipe_context *ctx,
    653                                struct pipe_query *query,
    654                                bool wait,
    655                                enum pipe_query_value_type result_type,
    656                                int index,
    657                                struct pipe_resource *p_res,
    658                                unsigned offset)
    659 {
    660    struct iris_context *ice = (void *) ctx;
    661    struct iris_query *q = (void *) query;
    662    struct iris_batch *batch = &ice->batches[q->batch_idx];
    663    const struct intel_device_info *devinfo = &batch->screen->devinfo;
    664    struct iris_resource *res = (void *) p_res;
    665    struct iris_bo *query_bo = iris_resource_bo(q->query_state_ref.res);
    666    struct iris_bo *dst_bo = iris_resource_bo(p_res);
    667    unsigned snapshots_landed_offset =
    668       offsetof(struct iris_query_snapshots, snapshots_landed);
    669 
    670    res->bind_history |= PIPE_BIND_QUERY_BUFFER;
    671 
    672    if (index == -1) {
    673       /* They're asking for the availability of the result.  If we still
    674        * have commands queued up which produce the result, submit them
    675        * now so that progress happens.  Either way, copy the snapshots
    676        * landed field to the destination resource.
    677        */
    678       if (q->syncobj == iris_batch_get_signal_syncobj(batch))
    679          iris_batch_flush(batch);
    680 
    681       batch->screen->vtbl.copy_mem_mem(batch, dst_bo, offset,
    682                              query_bo, snapshots_landed_offset,
    683                              result_type <= PIPE_QUERY_TYPE_U32 ? 4 : 8);
    684       return;
    685    }
    686 
    687    if (!q->ready && READ_ONCE(q->map->snapshots_landed)) {
    688       /* The final snapshots happen to have landed, so let's just compute
    689        * the result on the CPU now...
    690        */
    691       calculate_result_on_cpu(devinfo, q);
    692    }
    693 
    694    if (q->ready) {
    695       /* We happen to have the result on the CPU, so just copy it. */
    696       if (result_type <= PIPE_QUERY_TYPE_U32) {
    697          batch->screen->vtbl.store_data_imm32(batch, dst_bo, offset, q->result);
    698       } else {
    699          batch->screen->vtbl.store_data_imm64(batch, dst_bo, offset, q->result);
    700       }
    701 
    702       /* Make sure the result lands before they use bind the QBO elsewhere
    703        * and use the result.
    704        */
    705       // XXX: Why?  i965 doesn't do this.
    706       iris_emit_pipe_control_flush(batch,
    707                                    "query: unknown QBO flushing hack",
    708                                    PIPE_CONTROL_CS_STALL);
    709       return;
    710    }
    711 
    712    bool predicated = !wait && !q->stalled;
    713 
    714    struct mi_builder b;
    715    mi_builder_init(&b, &batch->screen->devinfo, batch);
    716 
    717    iris_batch_sync_region_start(batch);
    718 
    719    struct mi_value result = calculate_result_on_gpu(devinfo, &b, q);
    720    struct mi_value dst =
    721       result_type <= PIPE_QUERY_TYPE_U32 ?
    722       mi_mem32(rw_bo(dst_bo, offset, IRIS_DOMAIN_OTHER_WRITE)) :
    723       mi_mem64(rw_bo(dst_bo, offset, IRIS_DOMAIN_OTHER_WRITE));
    724 
    725    if (predicated) {
    726       mi_store(&b, mi_reg32(MI_PREDICATE_RESULT),
    727                    mi_mem64(ro_bo(query_bo, snapshots_landed_offset)));
    728       mi_store_if(&b, dst, result);
    729    } else {
    730       mi_store(&b, dst, result);
    731    }
    732 
    733    iris_batch_sync_region_end(batch);
    734 }
    735 
    736 static void
    737 iris_set_active_query_state(struct pipe_context *ctx, bool enable)
    738 {
    739    struct iris_context *ice = (void *) ctx;
    740 
    741    if (ice->state.statistics_counters_enabled == enable)
    742       return;
    743 
    744    // XXX: most packets aren't paying attention to this yet, because it'd
    745    // have to be done dynamically at draw time, which is a pain
    746    ice->state.statistics_counters_enabled = enable;
    747    ice->state.dirty |= IRIS_DIRTY_CLIP |
    748                        IRIS_DIRTY_RASTER |
    749                        IRIS_DIRTY_STREAMOUT |
    750                        IRIS_DIRTY_WM;
    751    ice->state.stage_dirty |= IRIS_STAGE_DIRTY_GS |
    752                              IRIS_STAGE_DIRTY_TCS |
    753                              IRIS_STAGE_DIRTY_TES |
    754                              IRIS_STAGE_DIRTY_VS;
    755 }
    756 
    757 static void
    758 set_predicate_enable(struct iris_context *ice, bool value)
    759 {
    760    if (value)
    761       ice->state.predicate = IRIS_PREDICATE_STATE_RENDER;
    762    else
    763       ice->state.predicate = IRIS_PREDICATE_STATE_DONT_RENDER;
    764 }
    765 
    766 static void
    767 set_predicate_for_result(struct iris_context *ice,
    768                          struct iris_query *q,
    769                          bool inverted)
    770 {
    771    struct iris_batch *batch = &ice->batches[IRIS_BATCH_RENDER];
    772    struct iris_bo *bo = iris_resource_bo(q->query_state_ref.res);
    773 
    774    iris_batch_sync_region_start(batch);
    775 
    776    /* The CPU doesn't have the query result yet; use hardware predication */
    777    ice->state.predicate = IRIS_PREDICATE_STATE_USE_BIT;
    778 
    779    /* Ensure the memory is coherent for MI_LOAD_REGISTER_* commands. */
    780    iris_emit_pipe_control_flush(batch,
    781                                 "conditional rendering: set predicate",
    782                                 PIPE_CONTROL_FLUSH_ENABLE);
    783    q->stalled = true;
    784 
    785    struct mi_builder b;
    786    mi_builder_init(&b, &batch->screen->devinfo, batch);
    787 
    788    struct mi_value result;
    789 
    790    switch (q->type) {
    791    case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
    792       result = calc_overflow_for_stream(&b, q, q->index);
    793       break;
    794    case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE:
    795       result = calc_overflow_any_stream(&b, q);
    796       break;
    797    default: {
    798       /* PIPE_QUERY_OCCLUSION_* */
    799       struct mi_value start =
    800          query_mem64(q, offsetof(struct iris_query_snapshots, start));
    801       struct mi_value end =
    802          query_mem64(q, offsetof(struct iris_query_snapshots, end));
    803       result = mi_isub(&b, end, start);
    804       break;
    805    }
    806    }
    807 
    808    result = inverted ? mi_z(&b, result) : mi_nz(&b, result);
    809    result = mi_iand(&b, result, mi_imm(1));
    810 
    811    /* We immediately set the predicate on the render batch, as all the
    812     * counters come from 3D operations.  However, we may need to predicate
    813     * a compute dispatch, which executes in a different GEM context and has
    814     * a different MI_PREDICATE_RESULT register.  So, we save the result to
    815     * memory and reload it in iris_launch_grid.
    816     */
    817    mi_value_ref(&b, result);
    818    mi_store(&b, mi_reg32(MI_PREDICATE_RESULT), result);
    819    mi_store(&b, query_mem64(q, offsetof(struct iris_query_snapshots,
    820                                         predicate_result)), result);
    821    ice->state.compute_predicate = bo;
    822 
    823    iris_batch_sync_region_end(batch);
    824 }
    825 
    826 static void
    827 iris_render_condition(struct pipe_context *ctx,
    828                       struct pipe_query *query,
    829                       bool condition,
    830                       enum pipe_render_cond_flag mode)
    831 {
    832    struct iris_context *ice = (void *) ctx;
    833    struct iris_query *q = (void *) query;
    834 
    835    /* The old condition isn't relevant; we'll update it if necessary */
    836    ice->state.compute_predicate = NULL;
    837 
    838    if (!q) {
    839       ice->state.predicate = IRIS_PREDICATE_STATE_RENDER;
    840       return;
    841    }
    842 
    843    iris_check_query_no_flush(ice, q);
    844 
    845    if (q->result || q->ready) {
    846       set_predicate_enable(ice, (q->result != 0) ^ condition);
    847    } else {
    848       if (mode == PIPE_RENDER_COND_NO_WAIT ||
    849           mode == PIPE_RENDER_COND_BY_REGION_NO_WAIT) {
    850          perf_debug(&ice->dbg, "Conditional rendering demoted from "
    851                     "\"no wait\" to \"wait\".");
    852       }
    853       set_predicate_for_result(ice, q, condition);
    854    }
    855 }
    856 
    857 void
    858 genX(init_query)(struct iris_context *ice)
    859 {
    860    struct pipe_context *ctx = &ice->ctx;
    861 
    862    ctx->create_query = iris_create_query;
    863    ctx->create_batch_query = iris_create_batch_query;
    864    ctx->destroy_query = iris_destroy_query;
    865    ctx->begin_query = iris_begin_query;
    866    ctx->end_query = iris_end_query;
    867    ctx->get_query_result = iris_get_query_result;
    868    ctx->get_query_result_resource = iris_get_query_result_resource;
    869    ctx->set_active_query_state = iris_set_active_query_state;
    870    ctx->render_condition = iris_render_condition;
    871 }
    872