1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright (C) 2014 Rob Clark <robclark@freedesktop.org> 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21bf215546Sopenharmony_ci * SOFTWARE. 22bf215546Sopenharmony_ci * 23bf215546Sopenharmony_ci * Authors: 24bf215546Sopenharmony_ci * Rob Clark <robclark@freedesktop.org> 25bf215546Sopenharmony_ci */ 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci#include "pipe/p_state.h" 28bf215546Sopenharmony_ci#include "util/u_inlines.h" 29bf215546Sopenharmony_ci#include "util/u_memory.h" 30bf215546Sopenharmony_ci 31bf215546Sopenharmony_ci#include "freedreno_context.h" 32bf215546Sopenharmony_ci#include "freedreno_query_hw.h" 33bf215546Sopenharmony_ci#include "freedreno_resource.h" 34bf215546Sopenharmony_ci#include "freedreno_util.h" 35bf215546Sopenharmony_ci 36bf215546Sopenharmony_cistruct fd_hw_sample_period { 37bf215546Sopenharmony_ci struct fd_hw_sample *start, *end; 38bf215546Sopenharmony_ci struct list_head list; 39bf215546Sopenharmony_ci}; 40bf215546Sopenharmony_ci 41bf215546Sopenharmony_cistatic struct fd_hw_sample * 42bf215546Sopenharmony_ciget_sample(struct fd_batch *batch, struct fd_ringbuffer *ring, 43bf215546Sopenharmony_ci unsigned query_type) assert_dt 44bf215546Sopenharmony_ci{ 45bf215546Sopenharmony_ci struct fd_context *ctx = batch->ctx; 46bf215546Sopenharmony_ci struct fd_hw_sample *samp = NULL; 47bf215546Sopenharmony_ci int idx = pidx(query_type); 48bf215546Sopenharmony_ci 49bf215546Sopenharmony_ci assume(idx >= 0); /* query never would have been created otherwise */ 50bf215546Sopenharmony_ci 51bf215546Sopenharmony_ci if (!batch->sample_cache[idx]) { 52bf215546Sopenharmony_ci struct fd_hw_sample *new_samp = 53bf215546Sopenharmony_ci ctx->hw_sample_providers[idx]->get_sample(batch, ring); 54bf215546Sopenharmony_ci fd_hw_sample_reference(ctx, &batch->sample_cache[idx], new_samp); 55bf215546Sopenharmony_ci util_dynarray_append(&batch->samples, struct fd_hw_sample *, new_samp); 56bf215546Sopenharmony_ci fd_batch_needs_flush(batch); 57bf215546Sopenharmony_ci } 58bf215546Sopenharmony_ci 59bf215546Sopenharmony_ci fd_hw_sample_reference(ctx, &samp, batch->sample_cache[idx]); 60bf215546Sopenharmony_ci 61bf215546Sopenharmony_ci return samp; 62bf215546Sopenharmony_ci} 63bf215546Sopenharmony_ci 64bf215546Sopenharmony_cistatic void 65bf215546Sopenharmony_ciclear_sample_cache(struct fd_batch *batch) 66bf215546Sopenharmony_ci{ 67bf215546Sopenharmony_ci int i; 68bf215546Sopenharmony_ci 69bf215546Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(batch->sample_cache); i++) 70bf215546Sopenharmony_ci fd_hw_sample_reference(batch->ctx, &batch->sample_cache[i], NULL); 71bf215546Sopenharmony_ci} 72bf215546Sopenharmony_ci 73bf215546Sopenharmony_cistatic bool 74bf215546Sopenharmony_ciquery_active_in_batch(struct fd_batch *batch, struct fd_hw_query *hq) 75bf215546Sopenharmony_ci{ 76bf215546Sopenharmony_ci int idx = pidx(hq->provider->query_type); 77bf215546Sopenharmony_ci return batch->query_providers_active & (1 << idx); 78bf215546Sopenharmony_ci} 79bf215546Sopenharmony_ci 80bf215546Sopenharmony_cistatic void 81bf215546Sopenharmony_ciresume_query(struct fd_batch *batch, struct fd_hw_query *hq, 82bf215546Sopenharmony_ci struct fd_ringbuffer *ring) assert_dt 83bf215546Sopenharmony_ci{ 84bf215546Sopenharmony_ci int idx = pidx(hq->provider->query_type); 85bf215546Sopenharmony_ci DBG("%p", hq); 86bf215546Sopenharmony_ci assert(idx >= 0); /* query never would have been created otherwise */ 87bf215546Sopenharmony_ci assert(!hq->period); 88bf215546Sopenharmony_ci batch->query_providers_used |= (1 << idx); 89bf215546Sopenharmony_ci batch->query_providers_active |= (1 << idx); 90bf215546Sopenharmony_ci hq->period = slab_alloc_st(&batch->ctx->sample_period_pool); 91bf215546Sopenharmony_ci list_inithead(&hq->period->list); 92bf215546Sopenharmony_ci hq->period->start = get_sample(batch, ring, hq->base.type); 93bf215546Sopenharmony_ci /* NOTE: slab_alloc_st() does not zero out the buffer: */ 94bf215546Sopenharmony_ci hq->period->end = NULL; 95bf215546Sopenharmony_ci} 96bf215546Sopenharmony_ci 97bf215546Sopenharmony_cistatic void 98bf215546Sopenharmony_cipause_query(struct fd_batch *batch, struct fd_hw_query *hq, 99bf215546Sopenharmony_ci struct fd_ringbuffer *ring) assert_dt 100bf215546Sopenharmony_ci{ 101bf215546Sopenharmony_ci ASSERTED int idx = pidx(hq->provider->query_type); 102bf215546Sopenharmony_ci DBG("%p", hq); 103bf215546Sopenharmony_ci assert(idx >= 0); /* query never would have been created otherwise */ 104bf215546Sopenharmony_ci assert(hq->period && !hq->period->end); 105bf215546Sopenharmony_ci assert(query_active_in_batch(batch, hq)); 106bf215546Sopenharmony_ci batch->query_providers_active &= ~(1 << idx); 107bf215546Sopenharmony_ci hq->period->end = get_sample(batch, ring, hq->base.type); 108bf215546Sopenharmony_ci list_addtail(&hq->period->list, &hq->periods); 109bf215546Sopenharmony_ci hq->period = NULL; 110bf215546Sopenharmony_ci} 111bf215546Sopenharmony_ci 112bf215546Sopenharmony_cistatic void 113bf215546Sopenharmony_cidestroy_periods(struct fd_context *ctx, struct fd_hw_query *hq) 114bf215546Sopenharmony_ci{ 115bf215546Sopenharmony_ci struct fd_hw_sample_period *period, *s; 116bf215546Sopenharmony_ci LIST_FOR_EACH_ENTRY_SAFE (period, s, &hq->periods, list) { 117bf215546Sopenharmony_ci fd_hw_sample_reference(ctx, &period->start, NULL); 118bf215546Sopenharmony_ci fd_hw_sample_reference(ctx, &period->end, NULL); 119bf215546Sopenharmony_ci list_del(&period->list); 120bf215546Sopenharmony_ci slab_free_st(&ctx->sample_period_pool, period); 121bf215546Sopenharmony_ci } 122bf215546Sopenharmony_ci} 123bf215546Sopenharmony_ci 124bf215546Sopenharmony_cistatic void 125bf215546Sopenharmony_cifd_hw_destroy_query(struct fd_context *ctx, struct fd_query *q) 126bf215546Sopenharmony_ci{ 127bf215546Sopenharmony_ci struct fd_hw_query *hq = fd_hw_query(q); 128bf215546Sopenharmony_ci 129bf215546Sopenharmony_ci DBG("%p", q); 130bf215546Sopenharmony_ci 131bf215546Sopenharmony_ci destroy_periods(ctx, hq); 132bf215546Sopenharmony_ci list_del(&hq->list); 133bf215546Sopenharmony_ci 134bf215546Sopenharmony_ci free(hq); 135bf215546Sopenharmony_ci} 136bf215546Sopenharmony_ci 137bf215546Sopenharmony_cistatic void 138bf215546Sopenharmony_cifd_hw_begin_query(struct fd_context *ctx, struct fd_query *q) assert_dt 139bf215546Sopenharmony_ci{ 140bf215546Sopenharmony_ci struct fd_batch *batch = fd_context_batch_locked(ctx); 141bf215546Sopenharmony_ci struct fd_hw_query *hq = fd_hw_query(q); 142bf215546Sopenharmony_ci 143bf215546Sopenharmony_ci DBG("%p", q); 144bf215546Sopenharmony_ci 145bf215546Sopenharmony_ci /* begin_query() should clear previous results: */ 146bf215546Sopenharmony_ci destroy_periods(ctx, hq); 147bf215546Sopenharmony_ci 148bf215546Sopenharmony_ci if (batch && (ctx->active_queries || hq->provider->always)) 149bf215546Sopenharmony_ci resume_query(batch, hq, batch->draw); 150bf215546Sopenharmony_ci 151bf215546Sopenharmony_ci /* add to active list: */ 152bf215546Sopenharmony_ci assert(list_is_empty(&hq->list)); 153bf215546Sopenharmony_ci list_addtail(&hq->list, &ctx->hw_active_queries); 154bf215546Sopenharmony_ci 155bf215546Sopenharmony_ci fd_batch_unlock_submit(batch); 156bf215546Sopenharmony_ci fd_batch_reference(&batch, NULL); 157bf215546Sopenharmony_ci} 158bf215546Sopenharmony_ci 159bf215546Sopenharmony_cistatic void 160bf215546Sopenharmony_cifd_hw_end_query(struct fd_context *ctx, struct fd_query *q) assert_dt 161bf215546Sopenharmony_ci{ 162bf215546Sopenharmony_ci struct fd_batch *batch = fd_context_batch_locked(ctx); 163bf215546Sopenharmony_ci struct fd_hw_query *hq = fd_hw_query(q); 164bf215546Sopenharmony_ci 165bf215546Sopenharmony_ci DBG("%p", q); 166bf215546Sopenharmony_ci 167bf215546Sopenharmony_ci if (batch && (ctx->active_queries || hq->provider->always)) 168bf215546Sopenharmony_ci pause_query(batch, hq, batch->draw); 169bf215546Sopenharmony_ci 170bf215546Sopenharmony_ci /* remove from active list: */ 171bf215546Sopenharmony_ci list_delinit(&hq->list); 172bf215546Sopenharmony_ci 173bf215546Sopenharmony_ci fd_batch_unlock_submit(batch); 174bf215546Sopenharmony_ci fd_batch_reference(&batch, NULL); 175bf215546Sopenharmony_ci} 176bf215546Sopenharmony_ci 177bf215546Sopenharmony_ci/* helper to get ptr to specified sample: */ 178bf215546Sopenharmony_cistatic void * 179bf215546Sopenharmony_cisampptr(struct fd_hw_sample *samp, uint32_t n, void *ptr) 180bf215546Sopenharmony_ci{ 181bf215546Sopenharmony_ci return ((char *)ptr) + (samp->tile_stride * n) + samp->offset; 182bf215546Sopenharmony_ci} 183bf215546Sopenharmony_ci 184bf215546Sopenharmony_cistatic bool 185bf215546Sopenharmony_cifd_hw_get_query_result(struct fd_context *ctx, struct fd_query *q, bool wait, 186bf215546Sopenharmony_ci union pipe_query_result *result) 187bf215546Sopenharmony_ci{ 188bf215546Sopenharmony_ci struct fd_hw_query *hq = fd_hw_query(q); 189bf215546Sopenharmony_ci const struct fd_hw_sample_provider *p = hq->provider; 190bf215546Sopenharmony_ci struct fd_hw_sample_period *period, *tmp; 191bf215546Sopenharmony_ci 192bf215546Sopenharmony_ci DBG("%p: wait=%d", q, wait); 193bf215546Sopenharmony_ci 194bf215546Sopenharmony_ci if (list_is_empty(&hq->periods)) 195bf215546Sopenharmony_ci return true; 196bf215546Sopenharmony_ci 197bf215546Sopenharmony_ci assert(list_is_empty(&hq->list)); 198bf215546Sopenharmony_ci assert(!hq->period); 199bf215546Sopenharmony_ci 200bf215546Sopenharmony_ci /* sum the result across all sample periods. Start with the last period 201bf215546Sopenharmony_ci * so that no-wait will bail quickly. 202bf215546Sopenharmony_ci */ 203bf215546Sopenharmony_ci LIST_FOR_EACH_ENTRY_SAFE_REV (period, tmp, &hq->periods, list) { 204bf215546Sopenharmony_ci struct fd_hw_sample *start = period->start; 205bf215546Sopenharmony_ci ASSERTED struct fd_hw_sample *end = period->end; 206bf215546Sopenharmony_ci unsigned i; 207bf215546Sopenharmony_ci 208bf215546Sopenharmony_ci /* start and end samples should be from same batch: */ 209bf215546Sopenharmony_ci assert(start->prsc == end->prsc); 210bf215546Sopenharmony_ci assert(start->num_tiles == end->num_tiles); 211bf215546Sopenharmony_ci 212bf215546Sopenharmony_ci struct fd_resource *rsc = fd_resource(start->prsc); 213bf215546Sopenharmony_ci 214bf215546Sopenharmony_ci /* ARB_occlusion_query says: 215bf215546Sopenharmony_ci * 216bf215546Sopenharmony_ci * "Querying the state for a given occlusion query forces that 217bf215546Sopenharmony_ci * occlusion query to complete within a finite amount of time." 218bf215546Sopenharmony_ci * 219bf215546Sopenharmony_ci * So, regardless of whether we are supposed to wait or not, we do need to 220bf215546Sopenharmony_ci * flush now. 221bf215546Sopenharmony_ci */ 222bf215546Sopenharmony_ci if (fd_get_query_result_in_driver_thread(q)) { 223bf215546Sopenharmony_ci tc_assert_driver_thread(ctx->tc); 224bf215546Sopenharmony_ci fd_context_access_begin(ctx); 225bf215546Sopenharmony_ci fd_bc_flush_writer(ctx, rsc); 226bf215546Sopenharmony_ci fd_context_access_end(ctx); 227bf215546Sopenharmony_ci } 228bf215546Sopenharmony_ci 229bf215546Sopenharmony_ci /* some piglit tests at least do query with no draws, I guess: */ 230bf215546Sopenharmony_ci if (!rsc->bo) 231bf215546Sopenharmony_ci continue; 232bf215546Sopenharmony_ci 233bf215546Sopenharmony_ci if (!wait) { 234bf215546Sopenharmony_ci int ret = fd_resource_wait( 235bf215546Sopenharmony_ci ctx, rsc, FD_BO_PREP_READ | FD_BO_PREP_NOSYNC | FD_BO_PREP_FLUSH); 236bf215546Sopenharmony_ci if (ret) 237bf215546Sopenharmony_ci return false; 238bf215546Sopenharmony_ci } else { 239bf215546Sopenharmony_ci fd_resource_wait(ctx, rsc, FD_BO_PREP_READ); 240bf215546Sopenharmony_ci } 241bf215546Sopenharmony_ci 242bf215546Sopenharmony_ci void *ptr = fd_bo_map(rsc->bo); 243bf215546Sopenharmony_ci 244bf215546Sopenharmony_ci for (i = 0; i < start->num_tiles; i++) { 245bf215546Sopenharmony_ci p->accumulate_result(ctx, sampptr(period->start, i, ptr), 246bf215546Sopenharmony_ci sampptr(period->end, i, ptr), result); 247bf215546Sopenharmony_ci } 248bf215546Sopenharmony_ci 249bf215546Sopenharmony_ci fd_bo_cpu_fini(rsc->bo); 250bf215546Sopenharmony_ci } 251bf215546Sopenharmony_ci 252bf215546Sopenharmony_ci return true; 253bf215546Sopenharmony_ci} 254bf215546Sopenharmony_ci 255bf215546Sopenharmony_cistatic const struct fd_query_funcs hw_query_funcs = { 256bf215546Sopenharmony_ci .destroy_query = fd_hw_destroy_query, 257bf215546Sopenharmony_ci .begin_query = fd_hw_begin_query, 258bf215546Sopenharmony_ci .end_query = fd_hw_end_query, 259bf215546Sopenharmony_ci .get_query_result = fd_hw_get_query_result, 260bf215546Sopenharmony_ci}; 261bf215546Sopenharmony_ci 262bf215546Sopenharmony_cistruct fd_query * 263bf215546Sopenharmony_cifd_hw_create_query(struct fd_context *ctx, unsigned query_type, unsigned index) 264bf215546Sopenharmony_ci{ 265bf215546Sopenharmony_ci struct fd_hw_query *hq; 266bf215546Sopenharmony_ci struct fd_query *q; 267bf215546Sopenharmony_ci int idx = pidx(query_type); 268bf215546Sopenharmony_ci 269bf215546Sopenharmony_ci if ((idx < 0) || !ctx->hw_sample_providers[idx]) 270bf215546Sopenharmony_ci return NULL; 271bf215546Sopenharmony_ci 272bf215546Sopenharmony_ci hq = CALLOC_STRUCT(fd_hw_query); 273bf215546Sopenharmony_ci if (!hq) 274bf215546Sopenharmony_ci return NULL; 275bf215546Sopenharmony_ci 276bf215546Sopenharmony_ci DBG("%p: query_type=%u", hq, query_type); 277bf215546Sopenharmony_ci 278bf215546Sopenharmony_ci hq->provider = ctx->hw_sample_providers[idx]; 279bf215546Sopenharmony_ci 280bf215546Sopenharmony_ci list_inithead(&hq->periods); 281bf215546Sopenharmony_ci list_inithead(&hq->list); 282bf215546Sopenharmony_ci 283bf215546Sopenharmony_ci q = &hq->base; 284bf215546Sopenharmony_ci q->funcs = &hw_query_funcs; 285bf215546Sopenharmony_ci q->type = query_type; 286bf215546Sopenharmony_ci q->index = index; 287bf215546Sopenharmony_ci 288bf215546Sopenharmony_ci return q; 289bf215546Sopenharmony_ci} 290bf215546Sopenharmony_ci 291bf215546Sopenharmony_cistruct fd_hw_sample * 292bf215546Sopenharmony_cifd_hw_sample_init(struct fd_batch *batch, uint32_t size) 293bf215546Sopenharmony_ci{ 294bf215546Sopenharmony_ci struct fd_hw_sample *samp = slab_alloc_st(&batch->ctx->sample_pool); 295bf215546Sopenharmony_ci pipe_reference_init(&samp->reference, 1); 296bf215546Sopenharmony_ci samp->size = size; 297bf215546Sopenharmony_ci assert(util_is_power_of_two_or_zero(size)); 298bf215546Sopenharmony_ci batch->next_sample_offset = align(batch->next_sample_offset, size); 299bf215546Sopenharmony_ci samp->offset = batch->next_sample_offset; 300bf215546Sopenharmony_ci /* NOTE: slab_alloc_st() does not zero out the buffer: */ 301bf215546Sopenharmony_ci samp->prsc = NULL; 302bf215546Sopenharmony_ci samp->num_tiles = 0; 303bf215546Sopenharmony_ci samp->tile_stride = 0; 304bf215546Sopenharmony_ci batch->next_sample_offset += size; 305bf215546Sopenharmony_ci 306bf215546Sopenharmony_ci if (!batch->query_buf) { 307bf215546Sopenharmony_ci struct pipe_screen *pscreen = &batch->ctx->screen->base; 308bf215546Sopenharmony_ci struct pipe_resource templ = { 309bf215546Sopenharmony_ci .target = PIPE_BUFFER, 310bf215546Sopenharmony_ci .format = PIPE_FORMAT_R8_UNORM, 311bf215546Sopenharmony_ci .bind = PIPE_BIND_QUERY_BUFFER, 312bf215546Sopenharmony_ci .width0 = 0, /* create initially zero size buffer */ 313bf215546Sopenharmony_ci .height0 = 1, 314bf215546Sopenharmony_ci .depth0 = 1, 315bf215546Sopenharmony_ci .array_size = 1, 316bf215546Sopenharmony_ci .last_level = 0, 317bf215546Sopenharmony_ci .nr_samples = 1, 318bf215546Sopenharmony_ci }; 319bf215546Sopenharmony_ci batch->query_buf = pscreen->resource_create(pscreen, &templ); 320bf215546Sopenharmony_ci } 321bf215546Sopenharmony_ci 322bf215546Sopenharmony_ci pipe_resource_reference(&samp->prsc, batch->query_buf); 323bf215546Sopenharmony_ci 324bf215546Sopenharmony_ci return samp; 325bf215546Sopenharmony_ci} 326bf215546Sopenharmony_ci 327bf215546Sopenharmony_civoid 328bf215546Sopenharmony_ci__fd_hw_sample_destroy(struct fd_context *ctx, struct fd_hw_sample *samp) 329bf215546Sopenharmony_ci{ 330bf215546Sopenharmony_ci pipe_resource_reference(&samp->prsc, NULL); 331bf215546Sopenharmony_ci slab_free_st(&ctx->sample_pool, samp); 332bf215546Sopenharmony_ci} 333bf215546Sopenharmony_ci 334bf215546Sopenharmony_ci/* called from gmem code once total storage requirements are known (ie. 335bf215546Sopenharmony_ci * number of samples times number of tiles) 336bf215546Sopenharmony_ci */ 337bf215546Sopenharmony_civoid 338bf215546Sopenharmony_cifd_hw_query_prepare(struct fd_batch *batch, uint32_t num_tiles) 339bf215546Sopenharmony_ci{ 340bf215546Sopenharmony_ci uint32_t tile_stride = batch->next_sample_offset; 341bf215546Sopenharmony_ci 342bf215546Sopenharmony_ci if (tile_stride > 0) 343bf215546Sopenharmony_ci fd_resource_resize(batch->query_buf, tile_stride * num_tiles); 344bf215546Sopenharmony_ci 345bf215546Sopenharmony_ci batch->query_tile_stride = tile_stride; 346bf215546Sopenharmony_ci 347bf215546Sopenharmony_ci while (batch->samples.size > 0) { 348bf215546Sopenharmony_ci struct fd_hw_sample *samp = 349bf215546Sopenharmony_ci util_dynarray_pop(&batch->samples, struct fd_hw_sample *); 350bf215546Sopenharmony_ci samp->num_tiles = num_tiles; 351bf215546Sopenharmony_ci samp->tile_stride = tile_stride; 352bf215546Sopenharmony_ci fd_hw_sample_reference(batch->ctx, &samp, NULL); 353bf215546Sopenharmony_ci } 354bf215546Sopenharmony_ci 355bf215546Sopenharmony_ci /* reset things for next batch: */ 356bf215546Sopenharmony_ci batch->next_sample_offset = 0; 357bf215546Sopenharmony_ci} 358bf215546Sopenharmony_ci 359bf215546Sopenharmony_civoid 360bf215546Sopenharmony_cifd_hw_query_prepare_tile(struct fd_batch *batch, uint32_t n, 361bf215546Sopenharmony_ci struct fd_ringbuffer *ring) 362bf215546Sopenharmony_ci{ 363bf215546Sopenharmony_ci uint32_t tile_stride = batch->query_tile_stride; 364bf215546Sopenharmony_ci uint32_t offset = tile_stride * n; 365bf215546Sopenharmony_ci 366bf215546Sopenharmony_ci /* bail if no queries: */ 367bf215546Sopenharmony_ci if (tile_stride == 0) 368bf215546Sopenharmony_ci return; 369bf215546Sopenharmony_ci 370bf215546Sopenharmony_ci fd_wfi(batch, ring); 371bf215546Sopenharmony_ci OUT_PKT0(ring, HW_QUERY_BASE_REG, 1); 372bf215546Sopenharmony_ci OUT_RELOC(ring, fd_resource(batch->query_buf)->bo, offset, 0, 0); 373bf215546Sopenharmony_ci} 374bf215546Sopenharmony_ci 375bf215546Sopenharmony_civoid 376bf215546Sopenharmony_cifd_hw_query_update_batch(struct fd_batch *batch, bool disable_all) 377bf215546Sopenharmony_ci{ 378bf215546Sopenharmony_ci struct fd_context *ctx = batch->ctx; 379bf215546Sopenharmony_ci 380bf215546Sopenharmony_ci if (disable_all || ctx->update_active_queries) { 381bf215546Sopenharmony_ci struct fd_hw_query *hq; 382bf215546Sopenharmony_ci LIST_FOR_EACH_ENTRY (hq, &batch->ctx->hw_active_queries, list) { 383bf215546Sopenharmony_ci bool was_active = query_active_in_batch(batch, hq); 384bf215546Sopenharmony_ci bool now_active = 385bf215546Sopenharmony_ci !disable_all && (ctx->active_queries || hq->provider->always); 386bf215546Sopenharmony_ci 387bf215546Sopenharmony_ci if (now_active && !was_active) 388bf215546Sopenharmony_ci resume_query(batch, hq, batch->draw); 389bf215546Sopenharmony_ci else if (was_active && !now_active) 390bf215546Sopenharmony_ci pause_query(batch, hq, batch->draw); 391bf215546Sopenharmony_ci } 392bf215546Sopenharmony_ci } 393bf215546Sopenharmony_ci clear_sample_cache(batch); 394bf215546Sopenharmony_ci} 395bf215546Sopenharmony_ci 396bf215546Sopenharmony_ci/* call the provider->enable() for all the hw queries that were active 397bf215546Sopenharmony_ci * in the current batch. This sets up perfctr selector regs statically 398bf215546Sopenharmony_ci * for the duration of the batch. 399bf215546Sopenharmony_ci */ 400bf215546Sopenharmony_civoid 401bf215546Sopenharmony_cifd_hw_query_enable(struct fd_batch *batch, struct fd_ringbuffer *ring) 402bf215546Sopenharmony_ci{ 403bf215546Sopenharmony_ci struct fd_context *ctx = batch->ctx; 404bf215546Sopenharmony_ci for (int idx = 0; idx < MAX_HW_SAMPLE_PROVIDERS; idx++) { 405bf215546Sopenharmony_ci if (batch->query_providers_used & (1 << idx)) { 406bf215546Sopenharmony_ci assert(ctx->hw_sample_providers[idx]); 407bf215546Sopenharmony_ci if (ctx->hw_sample_providers[idx]->enable) 408bf215546Sopenharmony_ci ctx->hw_sample_providers[idx]->enable(ctx, ring); 409bf215546Sopenharmony_ci } 410bf215546Sopenharmony_ci } 411bf215546Sopenharmony_ci} 412bf215546Sopenharmony_ci 413bf215546Sopenharmony_civoid 414bf215546Sopenharmony_cifd_hw_query_register_provider(struct pipe_context *pctx, 415bf215546Sopenharmony_ci const struct fd_hw_sample_provider *provider) 416bf215546Sopenharmony_ci{ 417bf215546Sopenharmony_ci struct fd_context *ctx = fd_context(pctx); 418bf215546Sopenharmony_ci int idx = pidx(provider->query_type); 419bf215546Sopenharmony_ci 420bf215546Sopenharmony_ci assert((0 <= idx) && (idx < MAX_HW_SAMPLE_PROVIDERS)); 421bf215546Sopenharmony_ci assert(!ctx->hw_sample_providers[idx]); 422bf215546Sopenharmony_ci 423bf215546Sopenharmony_ci ctx->hw_sample_providers[idx] = provider; 424bf215546Sopenharmony_ci} 425bf215546Sopenharmony_ci 426bf215546Sopenharmony_civoid 427bf215546Sopenharmony_cifd_hw_query_init(struct pipe_context *pctx) 428bf215546Sopenharmony_ci{ 429bf215546Sopenharmony_ci struct fd_context *ctx = fd_context(pctx); 430bf215546Sopenharmony_ci 431bf215546Sopenharmony_ci slab_create(&ctx->sample_pool, sizeof(struct fd_hw_sample), 16); 432bf215546Sopenharmony_ci slab_create(&ctx->sample_period_pool, sizeof(struct fd_hw_sample_period), 433bf215546Sopenharmony_ci 16); 434bf215546Sopenharmony_ci} 435bf215546Sopenharmony_ci 436bf215546Sopenharmony_civoid 437bf215546Sopenharmony_cifd_hw_query_fini(struct pipe_context *pctx) 438bf215546Sopenharmony_ci{ 439bf215546Sopenharmony_ci struct fd_context *ctx = fd_context(pctx); 440bf215546Sopenharmony_ci 441bf215546Sopenharmony_ci slab_destroy(&ctx->sample_pool); 442bf215546Sopenharmony_ci slab_destroy(&ctx->sample_period_pool); 443bf215546Sopenharmony_ci} 444