1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright 2011 Nouveau Project 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 shall be included in 12bf215546Sopenharmony_ci * all copies or substantial portions of the Software. 13bf215546Sopenharmony_ci * 14bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 18bf215546Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19bf215546Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20bf215546Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE. 21bf215546Sopenharmony_ci * 22bf215546Sopenharmony_ci * Authors: Christoph Bumiller 23bf215546Sopenharmony_ci */ 24bf215546Sopenharmony_ci 25bf215546Sopenharmony_ci#define NVC0_PUSH_EXPLICIT_SPACE_CHECKING 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci#include "nvc0/nvc0_context.h" 28bf215546Sopenharmony_ci#include "nvc0/nvc0_query.h" 29bf215546Sopenharmony_ci#include "nvc0/nvc0_query_sw.h" 30bf215546Sopenharmony_ci#include "nvc0/nvc0_query_hw.h" 31bf215546Sopenharmony_ci#include "nvc0/nvc0_query_hw_metric.h" 32bf215546Sopenharmony_ci#include "nvc0/nvc0_query_hw_sm.h" 33bf215546Sopenharmony_ci 34bf215546Sopenharmony_cistatic struct pipe_query * 35bf215546Sopenharmony_cinvc0_create_query(struct pipe_context *pipe, unsigned type, unsigned index) 36bf215546Sopenharmony_ci{ 37bf215546Sopenharmony_ci struct nvc0_context *nvc0 = nvc0_context(pipe); 38bf215546Sopenharmony_ci struct nvc0_query *q; 39bf215546Sopenharmony_ci 40bf215546Sopenharmony_ci q = nvc0_sw_create_query(nvc0, type, index); 41bf215546Sopenharmony_ci if (!q) 42bf215546Sopenharmony_ci q = nvc0_hw_create_query(nvc0, type, index); 43bf215546Sopenharmony_ci 44bf215546Sopenharmony_ci return (struct pipe_query *)q; 45bf215546Sopenharmony_ci} 46bf215546Sopenharmony_ci 47bf215546Sopenharmony_cistatic void 48bf215546Sopenharmony_cinvc0_destroy_query(struct pipe_context *pipe, struct pipe_query *pq) 49bf215546Sopenharmony_ci{ 50bf215546Sopenharmony_ci struct nvc0_query *q = nvc0_query(pq); 51bf215546Sopenharmony_ci q->funcs->destroy_query(nvc0_context(pipe), q); 52bf215546Sopenharmony_ci} 53bf215546Sopenharmony_ci 54bf215546Sopenharmony_cistatic bool 55bf215546Sopenharmony_cinvc0_begin_query(struct pipe_context *pipe, struct pipe_query *pq) 56bf215546Sopenharmony_ci{ 57bf215546Sopenharmony_ci struct nvc0_query *q = nvc0_query(pq); 58bf215546Sopenharmony_ci return q->funcs->begin_query(nvc0_context(pipe), q); 59bf215546Sopenharmony_ci} 60bf215546Sopenharmony_ci 61bf215546Sopenharmony_cistatic bool 62bf215546Sopenharmony_cinvc0_end_query(struct pipe_context *pipe, struct pipe_query *pq) 63bf215546Sopenharmony_ci{ 64bf215546Sopenharmony_ci struct nvc0_query *q = nvc0_query(pq); 65bf215546Sopenharmony_ci q->funcs->end_query(nvc0_context(pipe), q); 66bf215546Sopenharmony_ci return true; 67bf215546Sopenharmony_ci} 68bf215546Sopenharmony_ci 69bf215546Sopenharmony_cistatic bool 70bf215546Sopenharmony_cinvc0_get_query_result(struct pipe_context *pipe, struct pipe_query *pq, 71bf215546Sopenharmony_ci bool wait, union pipe_query_result *result) 72bf215546Sopenharmony_ci{ 73bf215546Sopenharmony_ci struct nvc0_query *q = nvc0_query(pq); 74bf215546Sopenharmony_ci return q->funcs->get_query_result(nvc0_context(pipe), q, wait, result); 75bf215546Sopenharmony_ci} 76bf215546Sopenharmony_ci 77bf215546Sopenharmony_cistatic void 78bf215546Sopenharmony_cinvc0_get_query_result_resource(struct pipe_context *pipe, 79bf215546Sopenharmony_ci struct pipe_query *pq, 80bf215546Sopenharmony_ci enum pipe_query_flags flags, 81bf215546Sopenharmony_ci enum pipe_query_value_type result_type, 82bf215546Sopenharmony_ci int index, 83bf215546Sopenharmony_ci struct pipe_resource *resource, 84bf215546Sopenharmony_ci unsigned offset) 85bf215546Sopenharmony_ci{ 86bf215546Sopenharmony_ci struct nvc0_query *q = nvc0_query(pq); 87bf215546Sopenharmony_ci if (!q->funcs->get_query_result_resource) { 88bf215546Sopenharmony_ci assert(!"Unexpected lack of get_query_result_resource"); 89bf215546Sopenharmony_ci return; 90bf215546Sopenharmony_ci } 91bf215546Sopenharmony_ci q->funcs->get_query_result_resource(nvc0_context(pipe), q, flags, result_type, 92bf215546Sopenharmony_ci index, resource, offset); 93bf215546Sopenharmony_ci} 94bf215546Sopenharmony_ci 95bf215546Sopenharmony_cistatic void 96bf215546Sopenharmony_cinvc0_render_condition(struct pipe_context *pipe, 97bf215546Sopenharmony_ci struct pipe_query *pq, 98bf215546Sopenharmony_ci bool condition, enum pipe_render_cond_flag mode) 99bf215546Sopenharmony_ci{ 100bf215546Sopenharmony_ci struct nvc0_context *nvc0 = nvc0_context(pipe); 101bf215546Sopenharmony_ci struct nouveau_pushbuf *push = nvc0->base.pushbuf; 102bf215546Sopenharmony_ci struct nvc0_query *q = nvc0_query(pq); 103bf215546Sopenharmony_ci struct nvc0_hw_query *hq = nvc0_hw_query(q); 104bf215546Sopenharmony_ci uint32_t cond; 105bf215546Sopenharmony_ci bool wait = 106bf215546Sopenharmony_ci mode != PIPE_RENDER_COND_NO_WAIT && 107bf215546Sopenharmony_ci mode != PIPE_RENDER_COND_BY_REGION_NO_WAIT; 108bf215546Sopenharmony_ci 109bf215546Sopenharmony_ci if (!pq) { 110bf215546Sopenharmony_ci cond = NVC0_3D_COND_MODE_ALWAYS; 111bf215546Sopenharmony_ci } 112bf215546Sopenharmony_ci else { 113bf215546Sopenharmony_ci /* NOTE: comparison of 2 queries only works if both have completed */ 114bf215546Sopenharmony_ci switch (q->type) { 115bf215546Sopenharmony_ci case PIPE_QUERY_SO_OVERFLOW_PREDICATE: 116bf215546Sopenharmony_ci case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE: 117bf215546Sopenharmony_ci cond = condition ? NVC0_3D_COND_MODE_EQUAL : 118bf215546Sopenharmony_ci NVC0_3D_COND_MODE_NOT_EQUAL; 119bf215546Sopenharmony_ci wait = true; 120bf215546Sopenharmony_ci break; 121bf215546Sopenharmony_ci case PIPE_QUERY_OCCLUSION_COUNTER: 122bf215546Sopenharmony_ci case PIPE_QUERY_OCCLUSION_PREDICATE: 123bf215546Sopenharmony_ci case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE: 124bf215546Sopenharmony_ci if (hq->state == NVC0_HW_QUERY_STATE_READY) 125bf215546Sopenharmony_ci wait = true; 126bf215546Sopenharmony_ci if (likely(!condition)) { 127bf215546Sopenharmony_ci cond = wait ? NVC0_3D_COND_MODE_NOT_EQUAL : NVC0_3D_COND_MODE_ALWAYS; 128bf215546Sopenharmony_ci } else { 129bf215546Sopenharmony_ci cond = wait ? NVC0_3D_COND_MODE_EQUAL : NVC0_3D_COND_MODE_ALWAYS; 130bf215546Sopenharmony_ci } 131bf215546Sopenharmony_ci break; 132bf215546Sopenharmony_ci default: 133bf215546Sopenharmony_ci assert(!"render condition query not a predicate"); 134bf215546Sopenharmony_ci cond = NVC0_3D_COND_MODE_ALWAYS; 135bf215546Sopenharmony_ci break; 136bf215546Sopenharmony_ci } 137bf215546Sopenharmony_ci } 138bf215546Sopenharmony_ci 139bf215546Sopenharmony_ci nvc0->cond_query = pq; 140bf215546Sopenharmony_ci nvc0->cond_cond = condition; 141bf215546Sopenharmony_ci nvc0->cond_condmode = cond; 142bf215546Sopenharmony_ci nvc0->cond_mode = mode; 143bf215546Sopenharmony_ci 144bf215546Sopenharmony_ci if (!pq) { 145bf215546Sopenharmony_ci PUSH_SPACE(push, 2); 146bf215546Sopenharmony_ci IMMED_NVC0(push, NVC0_3D(COND_MODE), cond); 147bf215546Sopenharmony_ci if (nvc0->screen->compute) 148bf215546Sopenharmony_ci IMMED_NVC0(push, NVC0_CP(COND_MODE), cond); 149bf215546Sopenharmony_ci return; 150bf215546Sopenharmony_ci } 151bf215546Sopenharmony_ci 152bf215546Sopenharmony_ci if (wait && hq->state != NVC0_HW_QUERY_STATE_READY) 153bf215546Sopenharmony_ci nvc0_hw_query_fifo_wait(nvc0, q); 154bf215546Sopenharmony_ci 155bf215546Sopenharmony_ci PUSH_SPACE(push, 10); 156bf215546Sopenharmony_ci PUSH_REFN (push, hq->bo, NOUVEAU_BO_GART | NOUVEAU_BO_RD); 157bf215546Sopenharmony_ci BEGIN_NVC0(push, NVC0_3D(COND_ADDRESS_HIGH), 3); 158bf215546Sopenharmony_ci PUSH_DATAh(push, hq->bo->offset + hq->offset); 159bf215546Sopenharmony_ci PUSH_DATA (push, hq->bo->offset + hq->offset); 160bf215546Sopenharmony_ci PUSH_DATA (push, cond); 161bf215546Sopenharmony_ci BEGIN_NVC0(push, NVC0_2D(COND_ADDRESS_HIGH), 2); 162bf215546Sopenharmony_ci PUSH_DATAh(push, hq->bo->offset + hq->offset); 163bf215546Sopenharmony_ci PUSH_DATA (push, hq->bo->offset + hq->offset); 164bf215546Sopenharmony_ci if (nvc0->screen->compute) { 165bf215546Sopenharmony_ci BEGIN_NVC0(push, NVC0_CP(COND_ADDRESS_HIGH), 3); 166bf215546Sopenharmony_ci PUSH_DATAh(push, hq->bo->offset + hq->offset); 167bf215546Sopenharmony_ci PUSH_DATA (push, hq->bo->offset + hq->offset); 168bf215546Sopenharmony_ci PUSH_DATA (push, cond); 169bf215546Sopenharmony_ci } 170bf215546Sopenharmony_ci} 171bf215546Sopenharmony_ci 172bf215546Sopenharmony_ciint 173bf215546Sopenharmony_cinvc0_screen_get_driver_query_info(struct pipe_screen *pscreen, 174bf215546Sopenharmony_ci unsigned id, 175bf215546Sopenharmony_ci struct pipe_driver_query_info *info) 176bf215546Sopenharmony_ci{ 177bf215546Sopenharmony_ci struct nvc0_screen *screen = nvc0_screen(pscreen); 178bf215546Sopenharmony_ci int num_sw_queries = 0, num_hw_queries = 0; 179bf215546Sopenharmony_ci 180bf215546Sopenharmony_ci num_sw_queries = nvc0_sw_get_driver_query_info(screen, 0, NULL); 181bf215546Sopenharmony_ci num_hw_queries = nvc0_hw_get_driver_query_info(screen, 0, NULL); 182bf215546Sopenharmony_ci 183bf215546Sopenharmony_ci if (!info) 184bf215546Sopenharmony_ci return num_sw_queries + num_hw_queries; 185bf215546Sopenharmony_ci 186bf215546Sopenharmony_ci /* Init default values. */ 187bf215546Sopenharmony_ci info->name = "this_is_not_the_query_you_are_looking_for"; 188bf215546Sopenharmony_ci info->query_type = 0xdeadd01d; 189bf215546Sopenharmony_ci info->max_value.u64 = 0; 190bf215546Sopenharmony_ci info->type = PIPE_DRIVER_QUERY_TYPE_UINT64; 191bf215546Sopenharmony_ci info->group_id = -1; 192bf215546Sopenharmony_ci info->flags = 0; 193bf215546Sopenharmony_ci 194bf215546Sopenharmony_ci#ifdef NOUVEAU_ENABLE_DRIVER_STATISTICS 195bf215546Sopenharmony_ci if (id < num_sw_queries) 196bf215546Sopenharmony_ci return nvc0_sw_get_driver_query_info(screen, id, info); 197bf215546Sopenharmony_ci#endif 198bf215546Sopenharmony_ci 199bf215546Sopenharmony_ci return nvc0_hw_get_driver_query_info(screen, id - num_sw_queries, info); 200bf215546Sopenharmony_ci} 201bf215546Sopenharmony_ci 202bf215546Sopenharmony_ciint 203bf215546Sopenharmony_cinvc0_screen_get_driver_query_group_info(struct pipe_screen *pscreen, 204bf215546Sopenharmony_ci unsigned id, 205bf215546Sopenharmony_ci struct pipe_driver_query_group_info *info) 206bf215546Sopenharmony_ci{ 207bf215546Sopenharmony_ci struct nvc0_screen *screen = nvc0_screen(pscreen); 208bf215546Sopenharmony_ci int count = 0; 209bf215546Sopenharmony_ci int map[3] = {}; 210bf215546Sopenharmony_ci 211bf215546Sopenharmony_ci if (screen->base.drm->version >= 0x01000101) { 212bf215546Sopenharmony_ci if (screen->compute) { 213bf215546Sopenharmony_ci if (screen->base.class_3d <= GM200_3D_CLASS) { 214bf215546Sopenharmony_ci map[count++] = NVC0_HW_SM_QUERY_GROUP; 215bf215546Sopenharmony_ci map[count++] = NVC0_HW_METRIC_QUERY_GROUP; 216bf215546Sopenharmony_ci } 217bf215546Sopenharmony_ci } 218bf215546Sopenharmony_ci } 219bf215546Sopenharmony_ci 220bf215546Sopenharmony_ci#ifdef NOUVEAU_ENABLE_DRIVER_STATISTICS 221bf215546Sopenharmony_ci map[count++] = NVC0_SW_QUERY_DRV_STAT_GROUP; 222bf215546Sopenharmony_ci#endif 223bf215546Sopenharmony_ci 224bf215546Sopenharmony_ci if (!info) 225bf215546Sopenharmony_ci return count; 226bf215546Sopenharmony_ci 227bf215546Sopenharmony_ci switch (map[id]) { 228bf215546Sopenharmony_ci case NVC0_HW_SM_QUERY_GROUP: 229bf215546Sopenharmony_ci if (screen->compute && screen->base.class_3d <= GM200_3D_CLASS) { 230bf215546Sopenharmony_ci info->name = "MP counters"; 231bf215546Sopenharmony_ci 232bf215546Sopenharmony_ci /* Expose the maximum number of hardware counters available, although 233bf215546Sopenharmony_ci * some queries use more than one counter. Expect failures in that 234bf215546Sopenharmony_ci * case but as performance counters are for developers, this should 235bf215546Sopenharmony_ci * not have a real impact. */ 236bf215546Sopenharmony_ci info->max_active_queries = 8; 237bf215546Sopenharmony_ci info->num_queries = nvc0_hw_sm_get_num_queries(screen); 238bf215546Sopenharmony_ci return 1; 239bf215546Sopenharmony_ci } 240bf215546Sopenharmony_ci break; 241bf215546Sopenharmony_ci case NVC0_HW_METRIC_QUERY_GROUP: 242bf215546Sopenharmony_ci if (screen->compute && screen->base.class_3d <= GM200_3D_CLASS) { 243bf215546Sopenharmony_ci info->name = "Performance metrics"; 244bf215546Sopenharmony_ci info->max_active_queries = 4; /* A metric uses at least 2 queries */ 245bf215546Sopenharmony_ci info->num_queries = nvc0_hw_metric_get_num_queries(screen); 246bf215546Sopenharmony_ci return 1; 247bf215546Sopenharmony_ci } 248bf215546Sopenharmony_ci break; 249bf215546Sopenharmony_ci#ifdef NOUVEAU_ENABLE_DRIVER_STATISTICS 250bf215546Sopenharmony_ci case NVC0_SW_QUERY_DRV_STAT_GROUP: 251bf215546Sopenharmony_ci info->name = "Driver statistics"; 252bf215546Sopenharmony_ci info->max_active_queries = NVC0_SW_QUERY_DRV_STAT_COUNT; 253bf215546Sopenharmony_ci info->num_queries = NVC0_SW_QUERY_DRV_STAT_COUNT; 254bf215546Sopenharmony_ci return 1; 255bf215546Sopenharmony_ci#endif 256bf215546Sopenharmony_ci } 257bf215546Sopenharmony_ci 258bf215546Sopenharmony_ci /* user asked for info about non-existing query group */ 259bf215546Sopenharmony_ci info->name = "this_is_not_the_query_group_you_are_looking_for"; 260bf215546Sopenharmony_ci info->max_active_queries = 0; 261bf215546Sopenharmony_ci info->num_queries = 0; 262bf215546Sopenharmony_ci return 0; 263bf215546Sopenharmony_ci} 264bf215546Sopenharmony_ci 265bf215546Sopenharmony_cistatic void 266bf215546Sopenharmony_cinvc0_set_active_query_state(struct pipe_context *pipe, bool enable) 267bf215546Sopenharmony_ci{ 268bf215546Sopenharmony_ci} 269bf215546Sopenharmony_ci 270bf215546Sopenharmony_civoid 271bf215546Sopenharmony_cinvc0_init_query_functions(struct nvc0_context *nvc0) 272bf215546Sopenharmony_ci{ 273bf215546Sopenharmony_ci struct pipe_context *pipe = &nvc0->base.pipe; 274bf215546Sopenharmony_ci 275bf215546Sopenharmony_ci pipe->create_query = nvc0_create_query; 276bf215546Sopenharmony_ci pipe->destroy_query = nvc0_destroy_query; 277bf215546Sopenharmony_ci pipe->begin_query = nvc0_begin_query; 278bf215546Sopenharmony_ci pipe->end_query = nvc0_end_query; 279bf215546Sopenharmony_ci pipe->get_query_result = nvc0_get_query_result; 280bf215546Sopenharmony_ci pipe->get_query_result_resource = nvc0_get_query_result_resource; 281bf215546Sopenharmony_ci pipe->set_active_query_state = nvc0_set_active_query_state; 282bf215546Sopenharmony_ci pipe->render_condition = nvc0_render_condition; 283bf215546Sopenharmony_ci nvc0->cond_condmode = NVC0_3D_COND_MODE_ALWAYS; 284bf215546Sopenharmony_ci} 285