1b8e80941Smrg/* 2b8e80941Smrg * Copyright © 2014 Broadcom 3b8e80941Smrg * 4b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5b8e80941Smrg * copy of this software and associated documentation files (the "Software"), 6b8e80941Smrg * to deal in the Software without restriction, including without limitation 7b8e80941Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8b8e80941Smrg * and/or sell copies of the Software, and to permit persons to whom the 9b8e80941Smrg * Software is furnished to do so, subject to the following conditions: 10b8e80941Smrg * 11b8e80941Smrg * The above copyright notice and this permission notice (including the next 12b8e80941Smrg * paragraph) shall be included in all copies or substantial portions of the 13b8e80941Smrg * Software. 14b8e80941Smrg * 15b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16b8e80941Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18b8e80941Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19b8e80941Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20b8e80941Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21b8e80941Smrg * IN THE SOFTWARE. 22b8e80941Smrg */ 23b8e80941Smrg 24b8e80941Smrg/** 25b8e80941Smrg * Gallium query object support. 26b8e80941Smrg * 27b8e80941Smrg * The HW has native support for occlusion queries, with the query result 28b8e80941Smrg * being loaded and stored by the TLB unit. From a SW perspective, we have to 29b8e80941Smrg * be careful to make sure that the jobs that need to be tracking queries are 30b8e80941Smrg * bracketed by the start and end of counting, even across FBO transitions. 31b8e80941Smrg * 32b8e80941Smrg * For the transform feedback PRIMITIVES_GENERATED/WRITTEN queries, we have to 33b8e80941Smrg * do the calculations in software at draw time. 34b8e80941Smrg */ 35b8e80941Smrg 36b8e80941Smrg#include "v3d_context.h" 37b8e80941Smrg#include "broadcom/cle/v3d_packet_v33_pack.h" 38b8e80941Smrg 39b8e80941Smrgstruct v3d_query 40b8e80941Smrg{ 41b8e80941Smrg enum pipe_query_type type; 42b8e80941Smrg struct v3d_bo *bo; 43b8e80941Smrg 44b8e80941Smrg uint32_t start, end; 45b8e80941Smrg}; 46b8e80941Smrg 47b8e80941Smrgstatic struct pipe_query * 48b8e80941Smrgv3d_create_query(struct pipe_context *pctx, unsigned query_type, unsigned index) 49b8e80941Smrg{ 50b8e80941Smrg struct v3d_query *q = calloc(1, sizeof(*q)); 51b8e80941Smrg 52b8e80941Smrg q->type = query_type; 53b8e80941Smrg 54b8e80941Smrg /* Note that struct pipe_query isn't actually defined anywhere. */ 55b8e80941Smrg return (struct pipe_query *)q; 56b8e80941Smrg} 57b8e80941Smrg 58b8e80941Smrgstatic void 59b8e80941Smrgv3d_destroy_query(struct pipe_context *pctx, struct pipe_query *query) 60b8e80941Smrg{ 61b8e80941Smrg struct v3d_query *q = (struct v3d_query *)query; 62b8e80941Smrg 63b8e80941Smrg v3d_bo_unreference(&q->bo); 64b8e80941Smrg free(q); 65b8e80941Smrg} 66b8e80941Smrg 67b8e80941Smrgstatic boolean 68b8e80941Smrgv3d_begin_query(struct pipe_context *pctx, struct pipe_query *query) 69b8e80941Smrg{ 70b8e80941Smrg struct v3d_context *v3d = v3d_context(pctx); 71b8e80941Smrg struct v3d_query *q = (struct v3d_query *)query; 72b8e80941Smrg 73b8e80941Smrg switch (q->type) { 74b8e80941Smrg case PIPE_QUERY_PRIMITIVES_GENERATED: 75b8e80941Smrg q->start = v3d->prims_generated; 76b8e80941Smrg break; 77b8e80941Smrg case PIPE_QUERY_PRIMITIVES_EMITTED: 78b8e80941Smrg q->start = v3d->tf_prims_generated; 79b8e80941Smrg break; 80b8e80941Smrg default: 81b8e80941Smrg q->bo = v3d_bo_alloc(v3d->screen, 4096, "query"); 82b8e80941Smrg 83b8e80941Smrg uint32_t *map = v3d_bo_map(q->bo); 84b8e80941Smrg *map = 0; 85b8e80941Smrg v3d->current_oq = q->bo; 86b8e80941Smrg v3d->dirty |= VC5_DIRTY_OQ; 87b8e80941Smrg break; 88b8e80941Smrg } 89b8e80941Smrg 90b8e80941Smrg return true; 91b8e80941Smrg} 92b8e80941Smrg 93b8e80941Smrgstatic bool 94b8e80941Smrgv3d_end_query(struct pipe_context *pctx, struct pipe_query *query) 95b8e80941Smrg{ 96b8e80941Smrg struct v3d_context *v3d = v3d_context(pctx); 97b8e80941Smrg struct v3d_query *q = (struct v3d_query *)query; 98b8e80941Smrg 99b8e80941Smrg switch (q->type) { 100b8e80941Smrg case PIPE_QUERY_PRIMITIVES_GENERATED: 101b8e80941Smrg q->end = v3d->prims_generated; 102b8e80941Smrg break; 103b8e80941Smrg case PIPE_QUERY_PRIMITIVES_EMITTED: 104b8e80941Smrg q->end = v3d->tf_prims_generated; 105b8e80941Smrg break; 106b8e80941Smrg default: 107b8e80941Smrg v3d->current_oq = NULL; 108b8e80941Smrg v3d->dirty |= VC5_DIRTY_OQ; 109b8e80941Smrg break; 110b8e80941Smrg } 111b8e80941Smrg 112b8e80941Smrg return true; 113b8e80941Smrg} 114b8e80941Smrg 115b8e80941Smrgstatic boolean 116b8e80941Smrgv3d_get_query_result(struct pipe_context *pctx, struct pipe_query *query, 117b8e80941Smrg boolean wait, union pipe_query_result *vresult) 118b8e80941Smrg{ 119b8e80941Smrg struct v3d_query *q = (struct v3d_query *)query; 120b8e80941Smrg uint32_t result = 0; 121b8e80941Smrg 122b8e80941Smrg if (q->bo) { 123b8e80941Smrg /* XXX: Only flush the jobs using this BO. */ 124b8e80941Smrg v3d_flush(pctx); 125b8e80941Smrg 126b8e80941Smrg if (wait) { 127b8e80941Smrg if (!v3d_bo_wait(q->bo, 0, "query")) 128b8e80941Smrg return false; 129b8e80941Smrg } else { 130b8e80941Smrg if (!v3d_bo_wait(q->bo, ~0ull, "query")) 131b8e80941Smrg return false; 132b8e80941Smrg } 133b8e80941Smrg 134b8e80941Smrg /* XXX: Sum up per-core values. */ 135b8e80941Smrg uint32_t *map = v3d_bo_map(q->bo); 136b8e80941Smrg result = *map; 137b8e80941Smrg 138b8e80941Smrg v3d_bo_unreference(&q->bo); 139b8e80941Smrg } 140b8e80941Smrg 141b8e80941Smrg switch (q->type) { 142b8e80941Smrg case PIPE_QUERY_OCCLUSION_COUNTER: 143b8e80941Smrg vresult->u64 = result; 144b8e80941Smrg break; 145b8e80941Smrg case PIPE_QUERY_OCCLUSION_PREDICATE: 146b8e80941Smrg case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE: 147b8e80941Smrg vresult->b = result != 0; 148b8e80941Smrg break; 149b8e80941Smrg case PIPE_QUERY_PRIMITIVES_GENERATED: 150b8e80941Smrg case PIPE_QUERY_PRIMITIVES_EMITTED: 151b8e80941Smrg vresult->u64 = q->end - q->start; 152b8e80941Smrg break; 153b8e80941Smrg default: 154b8e80941Smrg unreachable("unsupported query type"); 155b8e80941Smrg } 156b8e80941Smrg 157b8e80941Smrg return true; 158b8e80941Smrg} 159b8e80941Smrg 160b8e80941Smrgstatic void 161b8e80941Smrgv3d_set_active_query_state(struct pipe_context *pctx, boolean enable) 162b8e80941Smrg{ 163b8e80941Smrg struct v3d_context *v3d = v3d_context(pctx); 164b8e80941Smrg 165b8e80941Smrg v3d->active_queries = enable; 166b8e80941Smrg v3d->dirty |= VC5_DIRTY_OQ; 167b8e80941Smrg v3d->dirty |= VC5_DIRTY_STREAMOUT; 168b8e80941Smrg} 169b8e80941Smrg 170b8e80941Smrgvoid 171b8e80941Smrgv3d_query_init(struct pipe_context *pctx) 172b8e80941Smrg{ 173b8e80941Smrg pctx->create_query = v3d_create_query; 174b8e80941Smrg pctx->destroy_query = v3d_destroy_query; 175b8e80941Smrg pctx->begin_query = v3d_begin_query; 176b8e80941Smrg pctx->end_query = v3d_end_query; 177b8e80941Smrg pctx->get_query_result = v3d_get_query_result; 178b8e80941Smrg pctx->set_active_query_state = v3d_set_active_query_state; 179b8e80941Smrg} 180b8e80941Smrg 181