19f464c52Smaya/* 29f464c52Smaya * Copyright © 2017 Intel Corporation 39f464c52Smaya * 49f464c52Smaya * Permission is hereby granted, free of charge, to any person obtaining a 59f464c52Smaya * copy of this software and associated documentation files (the "Software"), 69f464c52Smaya * to deal in the Software without restriction, including without limitation 79f464c52Smaya * the rights to use, copy, modify, merge, publish, distribute, sublicense, 89f464c52Smaya * and/or sell copies of the Software, and to permit persons to whom the 99f464c52Smaya * Software is furnished to do so, subject to the following conditions: 109f464c52Smaya * 119f464c52Smaya * The above copyright notice and this permission notice shall be included 129f464c52Smaya * in all copies or substantial portions of the Software. 139f464c52Smaya * 149f464c52Smaya * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 159f464c52Smaya * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 169f464c52Smaya * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 179f464c52Smaya * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 189f464c52Smaya * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 199f464c52Smaya * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 209f464c52Smaya * DEALINGS IN THE SOFTWARE. 219f464c52Smaya */ 229f464c52Smaya 239f464c52Smaya/** 249f464c52Smaya * @file iris_query.c 259f464c52Smaya * 267ec681f3Smrg * ============================= GENXML CODE ============================= 277ec681f3Smrg * [This file is compiled once per generation.] 287ec681f3Smrg * ======================================================================= 297ec681f3Smrg * 309f464c52Smaya * Query object support. This allows measuring various simple statistics 317ec681f3Smrg * via counters on the GPU. We use GenX code for MI_MATH calculations. 329f464c52Smaya */ 339f464c52Smaya 349f464c52Smaya#include <stdio.h> 359f464c52Smaya#include <errno.h> 369f464c52Smaya#include "pipe/p_defines.h" 379f464c52Smaya#include "pipe/p_state.h" 389f464c52Smaya#include "pipe/p_context.h" 399f464c52Smaya#include "pipe/p_screen.h" 409f464c52Smaya#include "util/u_inlines.h" 419f464c52Smaya#include "util/u_upload_mgr.h" 429f464c52Smaya#include "iris_context.h" 439f464c52Smaya#include "iris_defines.h" 449f464c52Smaya#include "iris_fence.h" 457ec681f3Smrg#include "iris_monitor.h" 469f464c52Smaya#include "iris_resource.h" 479f464c52Smaya#include "iris_screen.h" 487ec681f3Smrg 497ec681f3Smrg#include "iris_genx_macros.h" 507ec681f3Smrg 517ec681f3Smrg#define SO_PRIM_STORAGE_NEEDED(n) (GENX(SO_PRIM_STORAGE_NEEDED0_num) + (n) * 8) 527ec681f3Smrg#define SO_NUM_PRIMS_WRITTEN(n) (GENX(SO_NUM_PRIMS_WRITTEN0_num) + (n) * 8) 539f464c52Smaya 549f464c52Smayastruct iris_query { 557ec681f3Smrg struct threaded_query b; 567ec681f3Smrg 579f464c52Smaya enum pipe_query_type type; 589f464c52Smaya int index; 599f464c52Smaya 609f464c52Smaya bool ready; 619f464c52Smaya 629f464c52Smaya bool stalled; 639f464c52Smaya 649f464c52Smaya uint64_t result; 659f464c52Smaya 669f464c52Smaya struct iris_state_ref query_state_ref; 679f464c52Smaya struct iris_query_snapshots *map; 687ec681f3Smrg struct iris_syncobj *syncobj; 699f464c52Smaya 709f464c52Smaya int batch_idx; 717ec681f3Smrg 727ec681f3Smrg struct iris_monitor_object *monitor; 737ec681f3Smrg 747ec681f3Smrg /* Fence for PIPE_QUERY_GPU_FINISHED. */ 757ec681f3Smrg struct pipe_fence_handle *fence; 769f464c52Smaya}; 779f464c52Smaya 789f464c52Smayastruct iris_query_snapshots { 799f464c52Smaya /** iris_render_condition's saved MI_PREDICATE_RESULT value. */ 809f464c52Smaya uint64_t predicate_result; 819f464c52Smaya 829f464c52Smaya /** Have the start/end snapshots landed? */ 839f464c52Smaya uint64_t snapshots_landed; 849f464c52Smaya 859f464c52Smaya /** Starting and ending counter snapshots */ 869f464c52Smaya uint64_t start; 879f464c52Smaya uint64_t end; 889f464c52Smaya}; 899f464c52Smaya 909f464c52Smayastruct iris_query_so_overflow { 919f464c52Smaya uint64_t predicate_result; 929f464c52Smaya uint64_t snapshots_landed; 939f464c52Smaya 949f464c52Smaya struct { 959f464c52Smaya uint64_t prim_storage_needed[2]; 969f464c52Smaya uint64_t num_prims[2]; 979f464c52Smaya } stream[4]; 989f464c52Smaya}; 999f464c52Smaya 1007ec681f3Smrgstatic struct mi_value 1017ec681f3Smrgquery_mem64(struct iris_query *q, uint32_t offset) 1027ec681f3Smrg{ 1037ec681f3Smrg struct iris_address addr = { 1047ec681f3Smrg .bo = iris_resource_bo(q->query_state_ref.res), 1057ec681f3Smrg .offset = q->query_state_ref.offset + offset, 1067ec681f3Smrg .access = IRIS_DOMAIN_OTHER_WRITE 1077ec681f3Smrg }; 1087ec681f3Smrg return mi_mem64(addr); 1097ec681f3Smrg} 1107ec681f3Smrg 1119f464c52Smaya/** 1129f464c52Smaya * Is this type of query written by PIPE_CONTROL? 1139f464c52Smaya */ 1149f464c52Smayastatic bool 1159f464c52Smayairis_is_query_pipelined(struct iris_query *q) 1169f464c52Smaya{ 1179f464c52Smaya switch (q->type) { 1189f464c52Smaya case PIPE_QUERY_OCCLUSION_COUNTER: 1199f464c52Smaya case PIPE_QUERY_OCCLUSION_PREDICATE: 1209f464c52Smaya case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE: 1219f464c52Smaya case PIPE_QUERY_TIMESTAMP: 1229f464c52Smaya case PIPE_QUERY_TIMESTAMP_DISJOINT: 1239f464c52Smaya case PIPE_QUERY_TIME_ELAPSED: 1249f464c52Smaya return true; 1259f464c52Smaya 1269f464c52Smaya default: 1279f464c52Smaya return false; 1289f464c52Smaya } 1299f464c52Smaya} 1309f464c52Smaya 1319f464c52Smayastatic void 1329f464c52Smayamark_available(struct iris_context *ice, struct iris_query *q) 1339f464c52Smaya{ 1349f464c52Smaya struct iris_batch *batch = &ice->batches[q->batch_idx]; 1359f464c52Smaya unsigned flags = PIPE_CONTROL_WRITE_IMMEDIATE; 1369f464c52Smaya unsigned offset = offsetof(struct iris_query_snapshots, snapshots_landed); 1379f464c52Smaya struct iris_bo *bo = iris_resource_bo(q->query_state_ref.res); 1389f464c52Smaya offset += q->query_state_ref.offset; 1399f464c52Smaya 1409f464c52Smaya if (!iris_is_query_pipelined(q)) { 1417ec681f3Smrg batch->screen->vtbl.store_data_imm64(batch, bo, offset, true); 1429f464c52Smaya } else { 1439f464c52Smaya /* Order available *after* the query results. */ 1449f464c52Smaya flags |= PIPE_CONTROL_FLUSH_ENABLE; 1457ec681f3Smrg iris_emit_pipe_control_write(batch, "query: mark available", 1467ec681f3Smrg flags, bo, offset, true); 1479f464c52Smaya } 1489f464c52Smaya} 1499f464c52Smaya 1509f464c52Smaya/** 1519f464c52Smaya * Write PS_DEPTH_COUNT to q->(dest) via a PIPE_CONTROL. 1529f464c52Smaya */ 1539f464c52Smayastatic void 1549f464c52Smayairis_pipelined_write(struct iris_batch *batch, 1559f464c52Smaya struct iris_query *q, 1569f464c52Smaya enum pipe_control_flags flags, 1579f464c52Smaya unsigned offset) 1589f464c52Smaya{ 1597ec681f3Smrg const struct intel_device_info *devinfo = &batch->screen->devinfo; 1609f464c52Smaya const unsigned optional_cs_stall = 1617ec681f3Smrg GFX_VER == 9 && devinfo->gt == 4 ? PIPE_CONTROL_CS_STALL : 0; 1629f464c52Smaya struct iris_bo *bo = iris_resource_bo(q->query_state_ref.res); 1639f464c52Smaya 1647ec681f3Smrg iris_emit_pipe_control_write(batch, "query: pipelined snapshot write", 1657ec681f3Smrg flags | optional_cs_stall, 1669f464c52Smaya bo, offset, 0ull); 1679f464c52Smaya} 1689f464c52Smaya 1699f464c52Smayastatic void 1709f464c52Smayawrite_value(struct iris_context *ice, struct iris_query *q, unsigned offset) 1719f464c52Smaya{ 1729f464c52Smaya struct iris_batch *batch = &ice->batches[q->batch_idx]; 1739f464c52Smaya struct iris_bo *bo = iris_resource_bo(q->query_state_ref.res); 1749f464c52Smaya 1759f464c52Smaya if (!iris_is_query_pipelined(q)) { 1769f464c52Smaya iris_emit_pipe_control_flush(batch, 1777ec681f3Smrg "query: non-pipelined snapshot write", 1789f464c52Smaya PIPE_CONTROL_CS_STALL | 1799f464c52Smaya PIPE_CONTROL_STALL_AT_SCOREBOARD); 1809f464c52Smaya q->stalled = true; 1819f464c52Smaya } 1829f464c52Smaya 1839f464c52Smaya switch (q->type) { 1849f464c52Smaya case PIPE_QUERY_OCCLUSION_COUNTER: 1859f464c52Smaya case PIPE_QUERY_OCCLUSION_PREDICATE: 1869f464c52Smaya case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE: 1877ec681f3Smrg if (GFX_VER >= 10) { 1889f464c52Smaya /* "Driver must program PIPE_CONTROL with only Depth Stall Enable 1899f464c52Smaya * bit set prior to programming a PIPE_CONTROL with Write PS Depth 1909f464c52Smaya * Count sync operation." 1919f464c52Smaya */ 1927ec681f3Smrg iris_emit_pipe_control_flush(batch, 1937ec681f3Smrg "workaround: depth stall before writing " 1947ec681f3Smrg "PS_DEPTH_COUNT", 1957ec681f3Smrg PIPE_CONTROL_DEPTH_STALL); 1969f464c52Smaya } 1979f464c52Smaya iris_pipelined_write(&ice->batches[IRIS_BATCH_RENDER], q, 1989f464c52Smaya PIPE_CONTROL_WRITE_DEPTH_COUNT | 1999f464c52Smaya PIPE_CONTROL_DEPTH_STALL, 2009f464c52Smaya offset); 2019f464c52Smaya break; 2029f464c52Smaya case PIPE_QUERY_TIME_ELAPSED: 2039f464c52Smaya case PIPE_QUERY_TIMESTAMP: 2049f464c52Smaya case PIPE_QUERY_TIMESTAMP_DISJOINT: 2059f464c52Smaya iris_pipelined_write(&ice->batches[IRIS_BATCH_RENDER], q, 2069f464c52Smaya PIPE_CONTROL_WRITE_TIMESTAMP, 2079f464c52Smaya offset); 2089f464c52Smaya break; 2099f464c52Smaya case PIPE_QUERY_PRIMITIVES_GENERATED: 2107ec681f3Smrg batch->screen->vtbl.store_register_mem64(batch, 2117ec681f3Smrg q->index == 0 ? 2127ec681f3Smrg GENX(CL_INVOCATION_COUNT_num) : 2139f464c52Smaya SO_PRIM_STORAGE_NEEDED(q->index), 2149f464c52Smaya bo, offset, false); 2159f464c52Smaya break; 2169f464c52Smaya case PIPE_QUERY_PRIMITIVES_EMITTED: 2177ec681f3Smrg batch->screen->vtbl.store_register_mem64(batch, 2189f464c52Smaya SO_NUM_PRIMS_WRITTEN(q->index), 2199f464c52Smaya bo, offset, false); 2209f464c52Smaya break; 2219f464c52Smaya case PIPE_QUERY_PIPELINE_STATISTICS_SINGLE: { 2229f464c52Smaya static const uint32_t index_to_reg[] = { 2237ec681f3Smrg GENX(IA_VERTICES_COUNT_num), 2247ec681f3Smrg GENX(IA_PRIMITIVES_COUNT_num), 2257ec681f3Smrg GENX(VS_INVOCATION_COUNT_num), 2267ec681f3Smrg GENX(GS_INVOCATION_COUNT_num), 2277ec681f3Smrg GENX(GS_PRIMITIVES_COUNT_num), 2287ec681f3Smrg GENX(CL_INVOCATION_COUNT_num), 2297ec681f3Smrg GENX(CL_PRIMITIVES_COUNT_num), 2307ec681f3Smrg GENX(PS_INVOCATION_COUNT_num), 2317ec681f3Smrg GENX(HS_INVOCATION_COUNT_num), 2327ec681f3Smrg GENX(DS_INVOCATION_COUNT_num), 2337ec681f3Smrg GENX(CS_INVOCATION_COUNT_num), 2349f464c52Smaya }; 2359f464c52Smaya const uint32_t reg = index_to_reg[q->index]; 2369f464c52Smaya 2377ec681f3Smrg batch->screen->vtbl.store_register_mem64(batch, reg, bo, offset, false); 2389f464c52Smaya break; 2399f464c52Smaya } 2409f464c52Smaya default: 2419f464c52Smaya assert(false); 2429f464c52Smaya } 2439f464c52Smaya} 2449f464c52Smaya 2459f464c52Smayastatic void 2469f464c52Smayawrite_overflow_values(struct iris_context *ice, struct iris_query *q, bool end) 2479f464c52Smaya{ 2489f464c52Smaya struct iris_batch *batch = &ice->batches[IRIS_BATCH_RENDER]; 2499f464c52Smaya uint32_t count = q->type == PIPE_QUERY_SO_OVERFLOW_PREDICATE ? 1 : 4; 2509f464c52Smaya struct iris_bo *bo = iris_resource_bo(q->query_state_ref.res); 2519f464c52Smaya uint32_t offset = q->query_state_ref.offset; 2529f464c52Smaya 2539f464c52Smaya iris_emit_pipe_control_flush(batch, 2547ec681f3Smrg "query: write SO overflow snapshots", 2559f464c52Smaya PIPE_CONTROL_CS_STALL | 2569f464c52Smaya PIPE_CONTROL_STALL_AT_SCOREBOARD); 2579f464c52Smaya for (uint32_t i = 0; i < count; i++) { 2589f464c52Smaya int s = q->index + i; 2599f464c52Smaya int g_idx = offset + offsetof(struct iris_query_so_overflow, 2609f464c52Smaya stream[s].num_prims[end]); 2619f464c52Smaya int w_idx = offset + offsetof(struct iris_query_so_overflow, 2629f464c52Smaya stream[s].prim_storage_needed[end]); 2637ec681f3Smrg batch->screen->vtbl.store_register_mem64(batch, SO_NUM_PRIMS_WRITTEN(s), 2649f464c52Smaya bo, g_idx, false); 2657ec681f3Smrg batch->screen->vtbl.store_register_mem64(batch, SO_PRIM_STORAGE_NEEDED(s), 2669f464c52Smaya bo, w_idx, false); 2679f464c52Smaya } 2689f464c52Smaya} 2699f464c52Smaya 2709f464c52Smayastatic uint64_t 2719f464c52Smayairis_raw_timestamp_delta(uint64_t time0, uint64_t time1) 2729f464c52Smaya{ 2739f464c52Smaya if (time0 > time1) { 2749f464c52Smaya return (1ULL << TIMESTAMP_BITS) + time1 - time0; 2759f464c52Smaya } else { 2769f464c52Smaya return time1 - time0; 2779f464c52Smaya } 2789f464c52Smaya} 2799f464c52Smaya 2809f464c52Smayastatic bool 2819f464c52Smayastream_overflowed(struct iris_query_so_overflow *so, int s) 2829f464c52Smaya{ 2839f464c52Smaya return (so->stream[s].prim_storage_needed[1] - 2849f464c52Smaya so->stream[s].prim_storage_needed[0]) != 2859f464c52Smaya (so->stream[s].num_prims[1] - so->stream[s].num_prims[0]); 2869f464c52Smaya} 2879f464c52Smaya 2889f464c52Smayastatic void 2897ec681f3Smrgcalculate_result_on_cpu(const struct intel_device_info *devinfo, 2909f464c52Smaya struct iris_query *q) 2919f464c52Smaya{ 2929f464c52Smaya switch (q->type) { 2939f464c52Smaya case PIPE_QUERY_OCCLUSION_PREDICATE: 2949f464c52Smaya case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE: 2959f464c52Smaya q->result = q->map->end != q->map->start; 2969f464c52Smaya break; 2979f464c52Smaya case PIPE_QUERY_TIMESTAMP: 2989f464c52Smaya case PIPE_QUERY_TIMESTAMP_DISJOINT: 2999f464c52Smaya /* The timestamp is the single starting snapshot. */ 3007ec681f3Smrg q->result = intel_device_info_timebase_scale(devinfo, q->map->start); 3019f464c52Smaya q->result &= (1ull << TIMESTAMP_BITS) - 1; 3029f464c52Smaya break; 3039f464c52Smaya case PIPE_QUERY_TIME_ELAPSED: 3049f464c52Smaya q->result = iris_raw_timestamp_delta(q->map->start, q->map->end); 3057ec681f3Smrg q->result = intel_device_info_timebase_scale(devinfo, q->result); 3069f464c52Smaya q->result &= (1ull << TIMESTAMP_BITS) - 1; 3079f464c52Smaya break; 3089f464c52Smaya case PIPE_QUERY_SO_OVERFLOW_PREDICATE: 3099f464c52Smaya q->result = stream_overflowed((void *) q->map, q->index); 3109f464c52Smaya break; 3119f464c52Smaya case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE: 3129f464c52Smaya q->result = false; 3139f464c52Smaya for (int i = 0; i < MAX_VERTEX_STREAMS; i++) 3149f464c52Smaya q->result |= stream_overflowed((void *) q->map, i); 3159f464c52Smaya break; 3169f464c52Smaya case PIPE_QUERY_PIPELINE_STATISTICS_SINGLE: 3179f464c52Smaya q->result = q->map->end - q->map->start; 3189f464c52Smaya 3199f464c52Smaya /* WaDividePSInvocationCountBy4:HSW,BDW */ 3207ec681f3Smrg if (GFX_VER == 8 && q->index == PIPE_STAT_QUERY_PS_INVOCATIONS) 3219f464c52Smaya q->result /= 4; 3229f464c52Smaya break; 3239f464c52Smaya case PIPE_QUERY_OCCLUSION_COUNTER: 3249f464c52Smaya case PIPE_QUERY_PRIMITIVES_GENERATED: 3259f464c52Smaya case PIPE_QUERY_PRIMITIVES_EMITTED: 3269f464c52Smaya default: 3279f464c52Smaya q->result = q->map->end - q->map->start; 3289f464c52Smaya break; 3299f464c52Smaya } 3309f464c52Smaya 3319f464c52Smaya q->ready = true; 3329f464c52Smaya} 3339f464c52Smaya 3347ec681f3Smrg/** 3357ec681f3Smrg * Calculate the streamout overflow for stream \p idx: 3367ec681f3Smrg * 3377ec681f3Smrg * (num_prims[1] - num_prims[0]) - (storage_needed[1] - storage_needed[0]) 3389f464c52Smaya */ 3397ec681f3Smrgstatic struct mi_value 3407ec681f3Smrgcalc_overflow_for_stream(struct mi_builder *b, 3417ec681f3Smrg struct iris_query *q, 3427ec681f3Smrg int idx) 3439f464c52Smaya{ 3447ec681f3Smrg#define C(counter, i) query_mem64(q, \ 3457ec681f3Smrg offsetof(struct iris_query_so_overflow, stream[idx].counter[i])) 3469f464c52Smaya 3477ec681f3Smrg return mi_isub(b, mi_isub(b, C(num_prims, 1), C(num_prims, 0)), 3487ec681f3Smrg mi_isub(b, C(prim_storage_needed, 1), 3497ec681f3Smrg C(prim_storage_needed, 0))); 3507ec681f3Smrg#undef C 3519f464c52Smaya} 3529f464c52Smaya 3537ec681f3Smrg/** 3547ec681f3Smrg * Calculate whether any stream has overflowed. 3559f464c52Smaya */ 3567ec681f3Smrgstatic struct mi_value 3577ec681f3Smrgcalc_overflow_any_stream(struct mi_builder *b, struct iris_query *q) 3589f464c52Smaya{ 3597ec681f3Smrg struct mi_value stream_result[MAX_VERTEX_STREAMS]; 3607ec681f3Smrg for (int i = 0; i < MAX_VERTEX_STREAMS; i++) 3617ec681f3Smrg stream_result[i] = calc_overflow_for_stream(b, q, i); 3629f464c52Smaya 3637ec681f3Smrg struct mi_value result = stream_result[0]; 3647ec681f3Smrg for (int i = 1; i < MAX_VERTEX_STREAMS; i++) 3657ec681f3Smrg result = mi_ior(b, result, stream_result[i]); 3669f464c52Smaya 3677ec681f3Smrg return result; 3689f464c52Smaya} 3699f464c52Smaya 3707ec681f3Smrgstatic bool 3717ec681f3Smrgquery_is_boolean(enum pipe_query_type type) 3729f464c52Smaya{ 3737ec681f3Smrg switch (type) { 3747ec681f3Smrg case PIPE_QUERY_OCCLUSION_PREDICATE: 3757ec681f3Smrg case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE: 3767ec681f3Smrg case PIPE_QUERY_SO_OVERFLOW_PREDICATE: 3777ec681f3Smrg case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE: 3787ec681f3Smrg return true; 3797ec681f3Smrg default: 3807ec681f3Smrg return false; 3819f464c52Smaya } 3829f464c52Smaya} 3839f464c52Smaya 3849f464c52Smaya/** 3857ec681f3Smrg * Calculate the result using MI_MATH. 3869f464c52Smaya */ 3877ec681f3Smrgstatic struct mi_value 3887ec681f3Smrgcalculate_result_on_gpu(const struct intel_device_info *devinfo, 3897ec681f3Smrg struct mi_builder *b, 3907ec681f3Smrg struct iris_query *q) 3919f464c52Smaya{ 3927ec681f3Smrg struct mi_value result; 3937ec681f3Smrg struct mi_value start_val = 3947ec681f3Smrg query_mem64(q, offsetof(struct iris_query_snapshots, start)); 3957ec681f3Smrg struct mi_value end_val = 3967ec681f3Smrg query_mem64(q, offsetof(struct iris_query_snapshots, end)); 3979f464c52Smaya 3987ec681f3Smrg switch (q->type) { 3997ec681f3Smrg case PIPE_QUERY_SO_OVERFLOW_PREDICATE: 4007ec681f3Smrg result = calc_overflow_for_stream(b, q, q->index); 4017ec681f3Smrg break; 4027ec681f3Smrg case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE: 4037ec681f3Smrg result = calc_overflow_any_stream(b, q); 4047ec681f3Smrg break; 4057ec681f3Smrg case PIPE_QUERY_TIMESTAMP: { 4069f464c52Smaya /* TODO: This discards any fractional bits of the timebase scale. 4079f464c52Smaya * We would need to do a bit of fixed point math on the CS ALU, or 4089f464c52Smaya * launch an actual shader to calculate this with full precision. 4099f464c52Smaya */ 4107ec681f3Smrg uint32_t scale = 1000000000ull / devinfo->timestamp_frequency; 4117ec681f3Smrg result = mi_iand(b, mi_imm((1ull << 36) - 1), 4127ec681f3Smrg mi_imul_imm(b, start_val, scale)); 4137ec681f3Smrg break; 4147ec681f3Smrg } 4157ec681f3Smrg case PIPE_QUERY_TIME_ELAPSED: { 4167ec681f3Smrg /* TODO: This discards fractional bits (see above). */ 4177ec681f3Smrg uint32_t scale = 1000000000ull / devinfo->timestamp_frequency; 4187ec681f3Smrg result = mi_imul_imm(b, mi_isub(b, end_val, start_val), scale); 4197ec681f3Smrg break; 4207ec681f3Smrg } 4217ec681f3Smrg default: 4227ec681f3Smrg result = mi_isub(b, end_val, start_val); 4237ec681f3Smrg break; 4249f464c52Smaya } 4259f464c52Smaya 4269f464c52Smaya /* WaDividePSInvocationCountBy4:HSW,BDW */ 4277ec681f3Smrg if (GFX_VER == 8 && 4289f464c52Smaya q->type == PIPE_QUERY_PIPELINE_STATISTICS_SINGLE && 4299f464c52Smaya q->index == PIPE_STAT_QUERY_PS_INVOCATIONS) 4307ec681f3Smrg result = mi_ushr32_imm(b, result, 2); 4319f464c52Smaya 4327ec681f3Smrg if (query_is_boolean(q->type)) 4337ec681f3Smrg result = mi_iand(b, mi_nz(b, result), mi_imm(1)); 4349f464c52Smaya 4357ec681f3Smrg return result; 4369f464c52Smaya} 4379f464c52Smaya 4389f464c52Smayastatic struct pipe_query * 4399f464c52Smayairis_create_query(struct pipe_context *ctx, 4409f464c52Smaya unsigned query_type, 4419f464c52Smaya unsigned index) 4429f464c52Smaya{ 4439f464c52Smaya struct iris_query *q = calloc(1, sizeof(struct iris_query)); 4449f464c52Smaya 4459f464c52Smaya q->type = query_type; 4469f464c52Smaya q->index = index; 4477ec681f3Smrg q->monitor = NULL; 4489f464c52Smaya 4499f464c52Smaya if (q->type == PIPE_QUERY_PIPELINE_STATISTICS_SINGLE && 4509f464c52Smaya q->index == PIPE_STAT_QUERY_CS_INVOCATIONS) 4519f464c52Smaya q->batch_idx = IRIS_BATCH_COMPUTE; 4529f464c52Smaya else 4539f464c52Smaya q->batch_idx = IRIS_BATCH_RENDER; 4549f464c52Smaya return (struct pipe_query *) q; 4559f464c52Smaya} 4569f464c52Smaya 4577ec681f3Smrgstatic struct pipe_query * 4587ec681f3Smrgiris_create_batch_query(struct pipe_context *ctx, 4597ec681f3Smrg unsigned num_queries, 4607ec681f3Smrg unsigned *query_types) 4617ec681f3Smrg{ 4627ec681f3Smrg struct iris_context *ice = (void *) ctx; 4637ec681f3Smrg struct iris_query *q = calloc(1, sizeof(struct iris_query)); 4647ec681f3Smrg if (unlikely(!q)) 4657ec681f3Smrg return NULL; 4667ec681f3Smrg q->type = PIPE_QUERY_DRIVER_SPECIFIC; 4677ec681f3Smrg q->index = -1; 4687ec681f3Smrg q->monitor = iris_create_monitor_object(ice, num_queries, query_types); 4697ec681f3Smrg if (unlikely(!q->monitor)) { 4707ec681f3Smrg free(q); 4717ec681f3Smrg return NULL; 4727ec681f3Smrg } 4737ec681f3Smrg 4747ec681f3Smrg return (struct pipe_query *) q; 4757ec681f3Smrg} 4767ec681f3Smrg 4779f464c52Smayastatic void 4789f464c52Smayairis_destroy_query(struct pipe_context *ctx, struct pipe_query *p_query) 4799f464c52Smaya{ 4809f464c52Smaya struct iris_query *query = (void *) p_query; 4819f464c52Smaya struct iris_screen *screen = (void *) ctx->screen; 4827ec681f3Smrg if (query->monitor) { 4837ec681f3Smrg iris_destroy_monitor_object(ctx, query->monitor); 4847ec681f3Smrg query->monitor = NULL; 4857ec681f3Smrg } else { 4867ec681f3Smrg iris_syncobj_reference(screen->bufmgr, &query->syncobj, NULL); 4877ec681f3Smrg screen->base.fence_reference(ctx->screen, &query->fence, NULL); 4887ec681f3Smrg } 4897ec681f3Smrg pipe_resource_reference(&query->query_state_ref.res, NULL); 4909f464c52Smaya free(query); 4919f464c52Smaya} 4929f464c52Smaya 4939f464c52Smaya 4947ec681f3Smrgstatic bool 4959f464c52Smayairis_begin_query(struct pipe_context *ctx, struct pipe_query *query) 4969f464c52Smaya{ 4979f464c52Smaya struct iris_context *ice = (void *) ctx; 4989f464c52Smaya struct iris_query *q = (void *) query; 4997ec681f3Smrg 5007ec681f3Smrg if (q->monitor) 5017ec681f3Smrg return iris_begin_monitor(ctx, q->monitor); 5027ec681f3Smrg 5039f464c52Smaya void *ptr = NULL; 5049f464c52Smaya uint32_t size; 5059f464c52Smaya 5069f464c52Smaya if (q->type == PIPE_QUERY_SO_OVERFLOW_PREDICATE || 5079f464c52Smaya q->type == PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE) 5089f464c52Smaya size = sizeof(struct iris_query_so_overflow); 5099f464c52Smaya else 5109f464c52Smaya size = sizeof(struct iris_query_snapshots); 5119f464c52Smaya 5129f464c52Smaya u_upload_alloc(ice->query_buffer_uploader, 0, 5139f464c52Smaya size, size, &q->query_state_ref.offset, 5149f464c52Smaya &q->query_state_ref.res, &ptr); 5159f464c52Smaya 5169f464c52Smaya if (!iris_resource_bo(q->query_state_ref.res)) 5179f464c52Smaya return false; 5189f464c52Smaya 5199f464c52Smaya q->map = ptr; 5209f464c52Smaya if (!q->map) 5219f464c52Smaya return false; 5229f464c52Smaya 5239f464c52Smaya q->result = 0ull; 5249f464c52Smaya q->ready = false; 5259f464c52Smaya WRITE_ONCE(q->map->snapshots_landed, false); 5269f464c52Smaya 5279f464c52Smaya if (q->type == PIPE_QUERY_PRIMITIVES_GENERATED && q->index == 0) { 5289f464c52Smaya ice->state.prims_generated_query_active = true; 5299f464c52Smaya ice->state.dirty |= IRIS_DIRTY_STREAMOUT | IRIS_DIRTY_CLIP; 5309f464c52Smaya } 5319f464c52Smaya 5329f464c52Smaya if (q->type == PIPE_QUERY_SO_OVERFLOW_PREDICATE || 5339f464c52Smaya q->type == PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE) 5349f464c52Smaya write_overflow_values(ice, q, false); 5359f464c52Smaya else 5369f464c52Smaya write_value(ice, q, 5379f464c52Smaya q->query_state_ref.offset + 5389f464c52Smaya offsetof(struct iris_query_snapshots, start)); 5399f464c52Smaya 5409f464c52Smaya return true; 5419f464c52Smaya} 5429f464c52Smaya 5439f464c52Smayastatic bool 5449f464c52Smayairis_end_query(struct pipe_context *ctx, struct pipe_query *query) 5459f464c52Smaya{ 5469f464c52Smaya struct iris_context *ice = (void *) ctx; 5479f464c52Smaya struct iris_query *q = (void *) query; 5487ec681f3Smrg 5497ec681f3Smrg if (q->monitor) 5507ec681f3Smrg return iris_end_monitor(ctx, q->monitor); 5517ec681f3Smrg 5527ec681f3Smrg if (q->type == PIPE_QUERY_GPU_FINISHED) { 5537ec681f3Smrg ctx->flush(ctx, &q->fence, PIPE_FLUSH_DEFERRED); 5547ec681f3Smrg return true; 5557ec681f3Smrg } 5567ec681f3Smrg 5579f464c52Smaya struct iris_batch *batch = &ice->batches[q->batch_idx]; 5589f464c52Smaya 5599f464c52Smaya if (q->type == PIPE_QUERY_TIMESTAMP) { 5609f464c52Smaya iris_begin_query(ctx, query); 5617ec681f3Smrg iris_batch_reference_signal_syncobj(batch, &q->syncobj); 5629f464c52Smaya mark_available(ice, q); 5639f464c52Smaya return true; 5649f464c52Smaya } 5659f464c52Smaya 5669f464c52Smaya if (q->type == PIPE_QUERY_PRIMITIVES_GENERATED && q->index == 0) { 5679f464c52Smaya ice->state.prims_generated_query_active = false; 5689f464c52Smaya ice->state.dirty |= IRIS_DIRTY_STREAMOUT | IRIS_DIRTY_CLIP; 5699f464c52Smaya } 5709f464c52Smaya 5719f464c52Smaya if (q->type == PIPE_QUERY_SO_OVERFLOW_PREDICATE || 5729f464c52Smaya q->type == PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE) 5739f464c52Smaya write_overflow_values(ice, q, true); 5749f464c52Smaya else 5759f464c52Smaya write_value(ice, q, 5769f464c52Smaya q->query_state_ref.offset + 5779f464c52Smaya offsetof(struct iris_query_snapshots, end)); 5789f464c52Smaya 5797ec681f3Smrg iris_batch_reference_signal_syncobj(batch, &q->syncobj); 5809f464c52Smaya mark_available(ice, q); 5819f464c52Smaya 5829f464c52Smaya return true; 5839f464c52Smaya} 5849f464c52Smaya 5859f464c52Smaya/** 5869f464c52Smaya * See if the snapshots have landed for a query, and if so, compute the 5879f464c52Smaya * result and mark it ready. Does not flush (unlike iris_get_query_result). 5889f464c52Smaya */ 5899f464c52Smayastatic void 5909f464c52Smayairis_check_query_no_flush(struct iris_context *ice, struct iris_query *q) 5919f464c52Smaya{ 5929f464c52Smaya struct iris_screen *screen = (void *) ice->ctx.screen; 5937ec681f3Smrg const struct intel_device_info *devinfo = &screen->devinfo; 5949f464c52Smaya 5959f464c52Smaya if (!q->ready && READ_ONCE(q->map->snapshots_landed)) { 5969f464c52Smaya calculate_result_on_cpu(devinfo, q); 5979f464c52Smaya } 5989f464c52Smaya} 5999f464c52Smaya 6007ec681f3Smrgstatic bool 6019f464c52Smayairis_get_query_result(struct pipe_context *ctx, 6029f464c52Smaya struct pipe_query *query, 6037ec681f3Smrg bool wait, 6049f464c52Smaya union pipe_query_result *result) 6059f464c52Smaya{ 6069f464c52Smaya struct iris_context *ice = (void *) ctx; 6079f464c52Smaya struct iris_query *q = (void *) query; 6087ec681f3Smrg 6097ec681f3Smrg if (q->monitor) 6107ec681f3Smrg return iris_get_monitor_result(ctx, q->monitor, wait, result->batch); 6117ec681f3Smrg 6129f464c52Smaya struct iris_screen *screen = (void *) ctx->screen; 6137ec681f3Smrg const struct intel_device_info *devinfo = &screen->devinfo; 6147ec681f3Smrg 6157ec681f3Smrg if (unlikely(screen->devinfo.no_hw)) { 6167ec681f3Smrg result->u64 = 0; 6177ec681f3Smrg return true; 6187ec681f3Smrg } 6197ec681f3Smrg 6207ec681f3Smrg if (q->type == PIPE_QUERY_GPU_FINISHED) { 6217ec681f3Smrg struct pipe_screen *screen = ctx->screen; 6227ec681f3Smrg 6237ec681f3Smrg result->b = screen->fence_finish(screen, ctx, q->fence, 6247ec681f3Smrg wait ? PIPE_TIMEOUT_INFINITE : 0); 6257ec681f3Smrg return result->b; 6267ec681f3Smrg } 6279f464c52Smaya 6289f464c52Smaya if (!q->ready) { 6297ec681f3Smrg struct iris_batch *batch = &ice->batches[q->batch_idx]; 6307ec681f3Smrg if (q->syncobj == iris_batch_get_signal_syncobj(batch)) 6317ec681f3Smrg iris_batch_flush(batch); 6329f464c52Smaya 6339f464c52Smaya while (!READ_ONCE(q->map->snapshots_landed)) { 6349f464c52Smaya if (wait) 6357ec681f3Smrg iris_wait_syncobj(screen->bufmgr, q->syncobj, INT64_MAX); 6369f464c52Smaya else 6379f464c52Smaya return false; 6389f464c52Smaya } 6399f464c52Smaya 6409f464c52Smaya assert(READ_ONCE(q->map->snapshots_landed)); 6419f464c52Smaya calculate_result_on_cpu(devinfo, q); 6429f464c52Smaya } 6439f464c52Smaya 6449f464c52Smaya assert(q->ready); 6459f464c52Smaya 6469f464c52Smaya result->u64 = q->result; 6479f464c52Smaya 6489f464c52Smaya return true; 6499f464c52Smaya} 6509f464c52Smaya 6519f464c52Smayastatic void 6529f464c52Smayairis_get_query_result_resource(struct pipe_context *ctx, 6539f464c52Smaya struct pipe_query *query, 6547ec681f3Smrg bool wait, 6559f464c52Smaya enum pipe_query_value_type result_type, 6569f464c52Smaya int index, 6579f464c52Smaya struct pipe_resource *p_res, 6589f464c52Smaya unsigned offset) 6599f464c52Smaya{ 6609f464c52Smaya struct iris_context *ice = (void *) ctx; 6619f464c52Smaya struct iris_query *q = (void *) query; 6629f464c52Smaya struct iris_batch *batch = &ice->batches[q->batch_idx]; 6637ec681f3Smrg const struct intel_device_info *devinfo = &batch->screen->devinfo; 6649f464c52Smaya struct iris_resource *res = (void *) p_res; 6657ec681f3Smrg struct iris_bo *query_bo = iris_resource_bo(q->query_state_ref.res); 6667ec681f3Smrg struct iris_bo *dst_bo = iris_resource_bo(p_res); 6679f464c52Smaya unsigned snapshots_landed_offset = 6689f464c52Smaya offsetof(struct iris_query_snapshots, snapshots_landed); 6699f464c52Smaya 6709f464c52Smaya res->bind_history |= PIPE_BIND_QUERY_BUFFER; 6719f464c52Smaya 6729f464c52Smaya if (index == -1) { 6739f464c52Smaya /* They're asking for the availability of the result. If we still 6749f464c52Smaya * have commands queued up which produce the result, submit them 6759f464c52Smaya * now so that progress happens. Either way, copy the snapshots 6769f464c52Smaya * landed field to the destination resource. 6779f464c52Smaya */ 6787ec681f3Smrg if (q->syncobj == iris_batch_get_signal_syncobj(batch)) 6799f464c52Smaya iris_batch_flush(batch); 6809f464c52Smaya 6817ec681f3Smrg batch->screen->vtbl.copy_mem_mem(batch, dst_bo, offset, 6827ec681f3Smrg query_bo, snapshots_landed_offset, 6839f464c52Smaya result_type <= PIPE_QUERY_TYPE_U32 ? 4 : 8); 6849f464c52Smaya return; 6859f464c52Smaya } 6869f464c52Smaya 6879f464c52Smaya if (!q->ready && READ_ONCE(q->map->snapshots_landed)) { 6889f464c52Smaya /* The final snapshots happen to have landed, so let's just compute 6899f464c52Smaya * the result on the CPU now... 6909f464c52Smaya */ 6919f464c52Smaya calculate_result_on_cpu(devinfo, q); 6929f464c52Smaya } 6939f464c52Smaya 6949f464c52Smaya if (q->ready) { 6959f464c52Smaya /* We happen to have the result on the CPU, so just copy it. */ 6969f464c52Smaya if (result_type <= PIPE_QUERY_TYPE_U32) { 6977ec681f3Smrg batch->screen->vtbl.store_data_imm32(batch, dst_bo, offset, q->result); 6989f464c52Smaya } else { 6997ec681f3Smrg batch->screen->vtbl.store_data_imm64(batch, dst_bo, offset, q->result); 7009f464c52Smaya } 7019f464c52Smaya 7029f464c52Smaya /* Make sure the result lands before they use bind the QBO elsewhere 7039f464c52Smaya * and use the result. 7049f464c52Smaya */ 7059f464c52Smaya // XXX: Why? i965 doesn't do this. 7067ec681f3Smrg iris_emit_pipe_control_flush(batch, 7077ec681f3Smrg "query: unknown QBO flushing hack", 7087ec681f3Smrg PIPE_CONTROL_CS_STALL); 7099f464c52Smaya return; 7109f464c52Smaya } 7119f464c52Smaya 7129f464c52Smaya bool predicated = !wait && !q->stalled; 7139f464c52Smaya 7147ec681f3Smrg struct mi_builder b; 7157ec681f3Smrg mi_builder_init(&b, &batch->screen->devinfo, batch); 7167ec681f3Smrg 7177ec681f3Smrg iris_batch_sync_region_start(batch); 7189f464c52Smaya 7197ec681f3Smrg struct mi_value result = calculate_result_on_gpu(devinfo, &b, q); 7207ec681f3Smrg struct mi_value dst = 7217ec681f3Smrg result_type <= PIPE_QUERY_TYPE_U32 ? 7227ec681f3Smrg mi_mem32(rw_bo(dst_bo, offset, IRIS_DOMAIN_OTHER_WRITE)) : 7237ec681f3Smrg mi_mem64(rw_bo(dst_bo, offset, IRIS_DOMAIN_OTHER_WRITE)); 7247ec681f3Smrg 7257ec681f3Smrg if (predicated) { 7267ec681f3Smrg mi_store(&b, mi_reg32(MI_PREDICATE_RESULT), 7277ec681f3Smrg mi_mem64(ro_bo(query_bo, snapshots_landed_offset))); 7287ec681f3Smrg mi_store_if(&b, dst, result); 7299f464c52Smaya } else { 7307ec681f3Smrg mi_store(&b, dst, result); 7319f464c52Smaya } 7327ec681f3Smrg 7337ec681f3Smrg iris_batch_sync_region_end(batch); 7349f464c52Smaya} 7359f464c52Smaya 7369f464c52Smayastatic void 7377ec681f3Smrgiris_set_active_query_state(struct pipe_context *ctx, bool enable) 7389f464c52Smaya{ 7399f464c52Smaya struct iris_context *ice = (void *) ctx; 7409f464c52Smaya 7419f464c52Smaya if (ice->state.statistics_counters_enabled == enable) 7429f464c52Smaya return; 7439f464c52Smaya 7449f464c52Smaya // XXX: most packets aren't paying attention to this yet, because it'd 7459f464c52Smaya // have to be done dynamically at draw time, which is a pain 7469f464c52Smaya ice->state.statistics_counters_enabled = enable; 7479f464c52Smaya ice->state.dirty |= IRIS_DIRTY_CLIP | 7489f464c52Smaya IRIS_DIRTY_RASTER | 7499f464c52Smaya IRIS_DIRTY_STREAMOUT | 7509f464c52Smaya IRIS_DIRTY_WM; 7517ec681f3Smrg ice->state.stage_dirty |= IRIS_STAGE_DIRTY_GS | 7527ec681f3Smrg IRIS_STAGE_DIRTY_TCS | 7537ec681f3Smrg IRIS_STAGE_DIRTY_TES | 7547ec681f3Smrg IRIS_STAGE_DIRTY_VS; 7559f464c52Smaya} 7569f464c52Smaya 7579f464c52Smayastatic void 7589f464c52Smayaset_predicate_enable(struct iris_context *ice, bool value) 7599f464c52Smaya{ 7609f464c52Smaya if (value) 7619f464c52Smaya ice->state.predicate = IRIS_PREDICATE_STATE_RENDER; 7629f464c52Smaya else 7639f464c52Smaya ice->state.predicate = IRIS_PREDICATE_STATE_DONT_RENDER; 7649f464c52Smaya} 7659f464c52Smaya 7669f464c52Smayastatic void 7679f464c52Smayaset_predicate_for_result(struct iris_context *ice, 7689f464c52Smaya struct iris_query *q, 7699f464c52Smaya bool inverted) 7709f464c52Smaya{ 7719f464c52Smaya struct iris_batch *batch = &ice->batches[IRIS_BATCH_RENDER]; 7729f464c52Smaya struct iris_bo *bo = iris_resource_bo(q->query_state_ref.res); 7739f464c52Smaya 7747ec681f3Smrg iris_batch_sync_region_start(batch); 7757ec681f3Smrg 7769f464c52Smaya /* The CPU doesn't have the query result yet; use hardware predication */ 7779f464c52Smaya ice->state.predicate = IRIS_PREDICATE_STATE_USE_BIT; 7789f464c52Smaya 7799f464c52Smaya /* Ensure the memory is coherent for MI_LOAD_REGISTER_* commands. */ 7807ec681f3Smrg iris_emit_pipe_control_flush(batch, 7817ec681f3Smrg "conditional rendering: set predicate", 7827ec681f3Smrg PIPE_CONTROL_FLUSH_ENABLE); 7839f464c52Smaya q->stalled = true; 7849f464c52Smaya 7857ec681f3Smrg struct mi_builder b; 7867ec681f3Smrg mi_builder_init(&b, &batch->screen->devinfo, batch); 7877ec681f3Smrg 7887ec681f3Smrg struct mi_value result; 7897ec681f3Smrg 7909f464c52Smaya switch (q->type) { 7919f464c52Smaya case PIPE_QUERY_SO_OVERFLOW_PREDICATE: 7927ec681f3Smrg result = calc_overflow_for_stream(&b, q, q->index); 7937ec681f3Smrg break; 7949f464c52Smaya case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE: 7957ec681f3Smrg result = calc_overflow_any_stream(&b, q); 7969f464c52Smaya break; 7977ec681f3Smrg default: { 7989f464c52Smaya /* PIPE_QUERY_OCCLUSION_* */ 7997ec681f3Smrg struct mi_value start = 8007ec681f3Smrg query_mem64(q, offsetof(struct iris_query_snapshots, start)); 8017ec681f3Smrg struct mi_value end = 8027ec681f3Smrg query_mem64(q, offsetof(struct iris_query_snapshots, end)); 8037ec681f3Smrg result = mi_isub(&b, end, start); 8049f464c52Smaya break; 8059f464c52Smaya } 8067ec681f3Smrg } 8079f464c52Smaya 8087ec681f3Smrg result = inverted ? mi_z(&b, result) : mi_nz(&b, result); 8097ec681f3Smrg result = mi_iand(&b, result, mi_imm(1)); 8109f464c52Smaya 8119f464c52Smaya /* We immediately set the predicate on the render batch, as all the 8129f464c52Smaya * counters come from 3D operations. However, we may need to predicate 8139f464c52Smaya * a compute dispatch, which executes in a different GEM context and has 8149f464c52Smaya * a different MI_PREDICATE_RESULT register. So, we save the result to 8159f464c52Smaya * memory and reload it in iris_launch_grid. 8169f464c52Smaya */ 8177ec681f3Smrg mi_value_ref(&b, result); 8187ec681f3Smrg mi_store(&b, mi_reg32(MI_PREDICATE_RESULT), result); 8197ec681f3Smrg mi_store(&b, query_mem64(q, offsetof(struct iris_query_snapshots, 8207ec681f3Smrg predicate_result)), result); 8219f464c52Smaya ice->state.compute_predicate = bo; 8227ec681f3Smrg 8237ec681f3Smrg iris_batch_sync_region_end(batch); 8249f464c52Smaya} 8259f464c52Smaya 8269f464c52Smayastatic void 8279f464c52Smayairis_render_condition(struct pipe_context *ctx, 8289f464c52Smaya struct pipe_query *query, 8297ec681f3Smrg bool condition, 8309f464c52Smaya enum pipe_render_cond_flag mode) 8319f464c52Smaya{ 8329f464c52Smaya struct iris_context *ice = (void *) ctx; 8339f464c52Smaya struct iris_query *q = (void *) query; 8349f464c52Smaya 8359f464c52Smaya /* The old condition isn't relevant; we'll update it if necessary */ 8369f464c52Smaya ice->state.compute_predicate = NULL; 8379f464c52Smaya 8389f464c52Smaya if (!q) { 8399f464c52Smaya ice->state.predicate = IRIS_PREDICATE_STATE_RENDER; 8409f464c52Smaya return; 8419f464c52Smaya } 8429f464c52Smaya 8439f464c52Smaya iris_check_query_no_flush(ice, q); 8449f464c52Smaya 8459f464c52Smaya if (q->result || q->ready) { 8469f464c52Smaya set_predicate_enable(ice, (q->result != 0) ^ condition); 8479f464c52Smaya } else { 8489f464c52Smaya if (mode == PIPE_RENDER_COND_NO_WAIT || 8499f464c52Smaya mode == PIPE_RENDER_COND_BY_REGION_NO_WAIT) { 8509f464c52Smaya perf_debug(&ice->dbg, "Conditional rendering demoted from " 8519f464c52Smaya "\"no wait\" to \"wait\"."); 8529f464c52Smaya } 8539f464c52Smaya set_predicate_for_result(ice, q, condition); 8549f464c52Smaya } 8559f464c52Smaya} 8569f464c52Smaya 8579f464c52Smayavoid 8587ec681f3SmrggenX(init_query)(struct iris_context *ice) 8599f464c52Smaya{ 8607ec681f3Smrg struct pipe_context *ctx = &ice->ctx; 8619f464c52Smaya 8629f464c52Smaya ctx->create_query = iris_create_query; 8637ec681f3Smrg ctx->create_batch_query = iris_create_batch_query; 8649f464c52Smaya ctx->destroy_query = iris_destroy_query; 8659f464c52Smaya ctx->begin_query = iris_begin_query; 8669f464c52Smaya ctx->end_query = iris_end_query; 8679f464c52Smaya ctx->get_query_result = iris_get_query_result; 8689f464c52Smaya ctx->get_query_result_resource = iris_get_query_result_resource; 8699f464c52Smaya ctx->set_active_query_state = iris_set_active_query_state; 8709f464c52Smaya ctx->render_condition = iris_render_condition; 8719f464c52Smaya} 872