14a49301eSmrg/************************************************************************** 24a49301eSmrg * 3af69d88dSmrg * Copyright 2007 VMware, Inc. 44a49301eSmrg * All Rights Reserved. 54a49301eSmrg * 64a49301eSmrg * Permission is hereby granted, free of charge, to any person obtaining a 74a49301eSmrg * copy of this software and associated documentation files (the 84a49301eSmrg * "Software"), to deal in the Software without restriction, including 94a49301eSmrg * without limitation the rights to use, copy, modify, merge, publish, 104a49301eSmrg * distribute, sub license, and/or sell copies of the Software, and to 114a49301eSmrg * permit persons to whom the Software is furnished to do so, subject to 124a49301eSmrg * the following conditions: 134a49301eSmrg * 144a49301eSmrg * The above copyright notice and this permission notice (including the 154a49301eSmrg * next paragraph) shall be included in all copies or substantial portions 164a49301eSmrg * of the Software. 174a49301eSmrg * 184a49301eSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 194a49301eSmrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 204a49301eSmrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21af69d88dSmrg * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 224a49301eSmrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 234a49301eSmrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 244a49301eSmrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 254a49301eSmrg * 264a49301eSmrg **************************************************************************/ 274a49301eSmrg 284a49301eSmrg/* Author: 29af69d88dSmrg * Keith Whitwell <keithw@vmware.com> 304a49301eSmrg */ 314a49301eSmrg 324a49301eSmrg#include "draw/draw_context.h" 3301e04c3fSmrg#include "util/os_time.h" 344a49301eSmrg#include "pipe/p_defines.h" 354a49301eSmrg#include "util/u_memory.h" 364a49301eSmrg#include "sp_context.h" 374a49301eSmrg#include "sp_query.h" 384a49301eSmrg#include "sp_state.h" 394a49301eSmrg 404a49301eSmrgstruct softpipe_query { 413464ebd5Sriastradh unsigned type; 429f464c52Smaya unsigned index; 434a49301eSmrg uint64_t start; 444a49301eSmrg uint64_t end; 457ec681f3Smrg struct pipe_query_data_so_statistics so[PIPE_MAX_VERTEX_STREAMS]; 46af69d88dSmrg struct pipe_query_data_pipeline_statistics stats; 474a49301eSmrg}; 484a49301eSmrg 494a49301eSmrg 504a49301eSmrgstatic struct softpipe_query *softpipe_query( struct pipe_query *p ) 514a49301eSmrg{ 524a49301eSmrg return (struct softpipe_query *)p; 534a49301eSmrg} 544a49301eSmrg 554a49301eSmrgstatic struct pipe_query * 564a49301eSmrgsoftpipe_create_query(struct pipe_context *pipe, 57af69d88dSmrg unsigned type, 58af69d88dSmrg unsigned index) 594a49301eSmrg{ 603464ebd5Sriastradh struct softpipe_query* sq; 613464ebd5Sriastradh 623464ebd5Sriastradh assert(type == PIPE_QUERY_OCCLUSION_COUNTER || 63af69d88dSmrg type == PIPE_QUERY_OCCLUSION_PREDICATE || 6401e04c3fSmrg type == PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE || 653464ebd5Sriastradh type == PIPE_QUERY_TIME_ELAPSED || 663464ebd5Sriastradh type == PIPE_QUERY_SO_STATISTICS || 67af69d88dSmrg type == PIPE_QUERY_SO_OVERFLOW_PREDICATE || 6801e04c3fSmrg type == PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE || 69af69d88dSmrg type == PIPE_QUERY_PRIMITIVES_EMITTED || 70af69d88dSmrg type == PIPE_QUERY_PRIMITIVES_GENERATED || 71af69d88dSmrg type == PIPE_QUERY_PIPELINE_STATISTICS || 723464ebd5Sriastradh type == PIPE_QUERY_GPU_FINISHED || 73af69d88dSmrg type == PIPE_QUERY_TIMESTAMP || 743464ebd5Sriastradh type == PIPE_QUERY_TIMESTAMP_DISJOINT); 753464ebd5Sriastradh sq = CALLOC_STRUCT( softpipe_query ); 763464ebd5Sriastradh sq->type = type; 779f464c52Smaya sq->index = index; 783464ebd5Sriastradh return (struct pipe_query *)sq; 794a49301eSmrg} 804a49301eSmrg 814a49301eSmrg 824a49301eSmrgstatic void 834a49301eSmrgsoftpipe_destroy_query(struct pipe_context *pipe, struct pipe_query *q) 844a49301eSmrg{ 854a49301eSmrg FREE(q); 864a49301eSmrg} 874a49301eSmrg 884a49301eSmrg 897ec681f3Smrgstatic bool 904a49301eSmrgsoftpipe_begin_query(struct pipe_context *pipe, struct pipe_query *q) 914a49301eSmrg{ 924a49301eSmrg struct softpipe_context *softpipe = softpipe_context( pipe ); 934a49301eSmrg struct softpipe_query *sq = softpipe_query(q); 943464ebd5Sriastradh 953464ebd5Sriastradh switch (sq->type) { 963464ebd5Sriastradh case PIPE_QUERY_OCCLUSION_COUNTER: 97af69d88dSmrg case PIPE_QUERY_OCCLUSION_PREDICATE: 9801e04c3fSmrg case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE: 993464ebd5Sriastradh sq->start = softpipe->occlusion_count; 1003464ebd5Sriastradh break; 1013464ebd5Sriastradh case PIPE_QUERY_TIME_ELAPSED: 102af69d88dSmrg sq->start = os_time_get_nano(); 1033464ebd5Sriastradh break; 1043464ebd5Sriastradh case PIPE_QUERY_SO_STATISTICS: 1057ec681f3Smrg sq->so[sq->index].num_primitives_written = softpipe->so_stats[sq->index].num_primitives_written; 1067ec681f3Smrg sq->so[sq->index].primitives_storage_needed = softpipe->so_stats[sq->index].primitives_storage_needed; 1073464ebd5Sriastradh break; 108af69d88dSmrg case PIPE_QUERY_SO_OVERFLOW_PREDICATE: 1097ec681f3Smrg sq->so[sq->index].num_primitives_written = softpipe->so_stats[sq->index].num_primitives_written; 1107ec681f3Smrg sq->so[sq->index].primitives_storage_needed = softpipe->so_stats[sq->index].primitives_storage_needed; 1117ec681f3Smrg break; 11201e04c3fSmrg case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE: 1137ec681f3Smrg for (unsigned i = 0; i < PIPE_MAX_VERTEX_STREAMS; i++) { 1147ec681f3Smrg sq->so[i].num_primitives_written = softpipe->so_stats[i].num_primitives_written; 1157ec681f3Smrg sq->so[i].primitives_storage_needed = softpipe->so_stats[i].primitives_storage_needed; 1167ec681f3Smrg } 117af69d88dSmrg break; 118af69d88dSmrg case PIPE_QUERY_PRIMITIVES_EMITTED: 1197ec681f3Smrg sq->so[sq->index].num_primitives_written = softpipe->so_stats[sq->index].num_primitives_written; 120af69d88dSmrg break; 121af69d88dSmrg case PIPE_QUERY_PRIMITIVES_GENERATED: 1227ec681f3Smrg sq->so[sq->index].primitives_storage_needed = softpipe->so_stats[sq->index].primitives_storage_needed; 1233464ebd5Sriastradh break; 124af69d88dSmrg case PIPE_QUERY_TIMESTAMP: 125af69d88dSmrg case PIPE_QUERY_GPU_FINISHED: 1263464ebd5Sriastradh case PIPE_QUERY_TIMESTAMP_DISJOINT: 127af69d88dSmrg break; 128af69d88dSmrg case PIPE_QUERY_PIPELINE_STATISTICS: 129af69d88dSmrg /* reset our cache */ 130af69d88dSmrg if (softpipe->active_statistics_queries == 0) { 131af69d88dSmrg memset(&softpipe->pipeline_statistics, 0, 132af69d88dSmrg sizeof(softpipe->pipeline_statistics)); 133af69d88dSmrg } 134af69d88dSmrg memcpy(&sq->stats, &softpipe->pipeline_statistics, 135af69d88dSmrg sizeof(sq->stats)); 136af69d88dSmrg softpipe->active_statistics_queries++; 137af69d88dSmrg break; 1383464ebd5Sriastradh default: 1393464ebd5Sriastradh assert(0); 1403464ebd5Sriastradh break; 1413464ebd5Sriastradh } 1424a49301eSmrg softpipe->active_query_count++; 1434a49301eSmrg softpipe->dirty |= SP_NEW_QUERY; 14401e04c3fSmrg return true; 1454a49301eSmrg} 1464a49301eSmrg 1474a49301eSmrg 14801e04c3fSmrgstatic bool 1494a49301eSmrgsoftpipe_end_query(struct pipe_context *pipe, struct pipe_query *q) 1504a49301eSmrg{ 1514a49301eSmrg struct softpipe_context *softpipe = softpipe_context( pipe ); 1524a49301eSmrg struct softpipe_query *sq = softpipe_query(q); 1534a49301eSmrg 1544a49301eSmrg softpipe->active_query_count--; 1553464ebd5Sriastradh switch (sq->type) { 1563464ebd5Sriastradh case PIPE_QUERY_OCCLUSION_COUNTER: 157af69d88dSmrg case PIPE_QUERY_OCCLUSION_PREDICATE: 15801e04c3fSmrg case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE: 1593464ebd5Sriastradh sq->end = softpipe->occlusion_count; 1603464ebd5Sriastradh break; 161af69d88dSmrg case PIPE_QUERY_TIMESTAMP: 162af69d88dSmrg sq->start = 0; 1637ec681f3Smrg FALLTHROUGH; 1643464ebd5Sriastradh case PIPE_QUERY_TIME_ELAPSED: 165af69d88dSmrg sq->end = os_time_get_nano(); 166af69d88dSmrg break; 167af69d88dSmrg case PIPE_QUERY_SO_OVERFLOW_PREDICATE: 1687ec681f3Smrg sq->so[sq->index].num_primitives_written = 1697ec681f3Smrg softpipe->so_stats[sq->index].num_primitives_written - sq->so[sq->index].num_primitives_written; 1707ec681f3Smrg sq->so[sq->index].primitives_storage_needed = 1717ec681f3Smrg softpipe->so_stats[sq->index].primitives_storage_needed - sq->so[sq->index].primitives_storage_needed; 1727ec681f3Smrg sq->end = sq->so[sq->index].primitives_storage_needed > sq->so[sq->index].num_primitives_written; 1737ec681f3Smrg break; 17401e04c3fSmrg case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE: 1757ec681f3Smrg sq->end = 0; 1767ec681f3Smrg for (unsigned i = 0; i < PIPE_MAX_VERTEX_STREAMS; i++) { 1777ec681f3Smrg sq->so[i].num_primitives_written = 1787ec681f3Smrg softpipe->so_stats[i].num_primitives_written - sq->so[i].num_primitives_written; 1797ec681f3Smrg sq->so[i].primitives_storage_needed = 1807ec681f3Smrg softpipe->so_stats[i].primitives_storage_needed - sq->so[i].primitives_storage_needed; 1817ec681f3Smrg sq->end |= sq->so[i].primitives_storage_needed > sq->so[i].num_primitives_written; 1827ec681f3Smrg } 1833464ebd5Sriastradh break; 1843464ebd5Sriastradh case PIPE_QUERY_SO_STATISTICS: 1857ec681f3Smrg sq->so[sq->index].num_primitives_written = 1867ec681f3Smrg softpipe->so_stats[sq->index].num_primitives_written - sq->so[sq->index].num_primitives_written; 1877ec681f3Smrg sq->so[sq->index].primitives_storage_needed = 1887ec681f3Smrg softpipe->so_stats[sq->index].primitives_storage_needed - sq->so[sq->index].primitives_storage_needed; 189af69d88dSmrg break; 190af69d88dSmrg case PIPE_QUERY_PRIMITIVES_EMITTED: 1917ec681f3Smrg sq->so[sq->index].num_primitives_written = 1927ec681f3Smrg softpipe->so_stats[sq->index].num_primitives_written - sq->so[sq->index].num_primitives_written; 193af69d88dSmrg break; 194af69d88dSmrg case PIPE_QUERY_PRIMITIVES_GENERATED: 1957ec681f3Smrg sq->so[sq->index].primitives_storage_needed = 1967ec681f3Smrg softpipe->so_stats[sq->index].primitives_storage_needed - sq->so[sq->index].primitives_storage_needed; 1973464ebd5Sriastradh break; 1983464ebd5Sriastradh case PIPE_QUERY_GPU_FINISHED: 1993464ebd5Sriastradh case PIPE_QUERY_TIMESTAMP_DISJOINT: 2003464ebd5Sriastradh break; 201af69d88dSmrg case PIPE_QUERY_PIPELINE_STATISTICS: 202af69d88dSmrg sq->stats.ia_vertices = 203af69d88dSmrg softpipe->pipeline_statistics.ia_vertices - sq->stats.ia_vertices; 204af69d88dSmrg sq->stats.ia_primitives = 205af69d88dSmrg softpipe->pipeline_statistics.ia_primitives - sq->stats.ia_primitives; 206af69d88dSmrg sq->stats.vs_invocations = 207af69d88dSmrg softpipe->pipeline_statistics.vs_invocations - sq->stats.vs_invocations; 208af69d88dSmrg sq->stats.gs_invocations = 209af69d88dSmrg softpipe->pipeline_statistics.gs_invocations - sq->stats.gs_invocations; 210af69d88dSmrg sq->stats.gs_primitives = 211af69d88dSmrg softpipe->pipeline_statistics.gs_primitives - sq->stats.gs_primitives; 212af69d88dSmrg sq->stats.c_invocations = 213af69d88dSmrg softpipe->pipeline_statistics.c_invocations - sq->stats.c_invocations; 214af69d88dSmrg sq->stats.c_primitives = 215af69d88dSmrg softpipe->pipeline_statistics.c_primitives - sq->stats.c_primitives; 216af69d88dSmrg sq->stats.ps_invocations = 217af69d88dSmrg softpipe->pipeline_statistics.ps_invocations - sq->stats.ps_invocations; 2187ec681f3Smrg sq->stats.cs_invocations = 2197ec681f3Smrg softpipe->pipeline_statistics.cs_invocations - sq->stats.cs_invocations; 220af69d88dSmrg 221af69d88dSmrg softpipe->active_statistics_queries--; 222af69d88dSmrg break; 2233464ebd5Sriastradh default: 2243464ebd5Sriastradh assert(0); 2253464ebd5Sriastradh break; 2263464ebd5Sriastradh } 2274a49301eSmrg softpipe->dirty |= SP_NEW_QUERY; 22801e04c3fSmrg return true; 2294a49301eSmrg} 2304a49301eSmrg 2314a49301eSmrg 2327ec681f3Smrgstatic bool 2334a49301eSmrgsoftpipe_get_query_result(struct pipe_context *pipe, 234af69d88dSmrg struct pipe_query *q, 2357ec681f3Smrg bool wait, 236af69d88dSmrg union pipe_query_result *vresult) 2374a49301eSmrg{ 2384a49301eSmrg struct softpipe_query *sq = softpipe_query(q); 2393464ebd5Sriastradh uint64_t *result = (uint64_t*)vresult; 2403464ebd5Sriastradh 2413464ebd5Sriastradh switch (sq->type) { 242af69d88dSmrg case PIPE_QUERY_SO_STATISTICS: { 243af69d88dSmrg struct pipe_query_data_so_statistics *stats = 244af69d88dSmrg (struct pipe_query_data_so_statistics *)vresult; 2457ec681f3Smrg stats->num_primitives_written = sq->so[sq->index].num_primitives_written; 2467ec681f3Smrg stats->primitives_storage_needed = sq->so[sq->index].primitives_storage_needed; 247af69d88dSmrg } 248af69d88dSmrg break; 249af69d88dSmrg case PIPE_QUERY_PIPELINE_STATISTICS: 250af69d88dSmrg memcpy(vresult, &sq->stats, 25101e04c3fSmrg sizeof(struct pipe_query_data_pipeline_statistics)); 2523464ebd5Sriastradh break; 2533464ebd5Sriastradh case PIPE_QUERY_GPU_FINISHED: 2547ec681f3Smrg vresult->b = true; 255af69d88dSmrg break; 256af69d88dSmrg case PIPE_QUERY_SO_OVERFLOW_PREDICATE: 25701e04c3fSmrg case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE: 258af69d88dSmrg vresult->b = sq->end != 0; 2593464ebd5Sriastradh break; 2603464ebd5Sriastradh case PIPE_QUERY_TIMESTAMP_DISJOINT: { 261af69d88dSmrg struct pipe_query_data_timestamp_disjoint *td = 262af69d88dSmrg (struct pipe_query_data_timestamp_disjoint *)vresult; 263af69d88dSmrg /* os_get_time_nano return nanoseconds */ 264af69d88dSmrg td->frequency = UINT64_C(1000000000); 2657ec681f3Smrg td->disjoint = false; 2663464ebd5Sriastradh } 2673464ebd5Sriastradh break; 268af69d88dSmrg case PIPE_QUERY_PRIMITIVES_EMITTED: 2697ec681f3Smrg *result = sq->so[sq->index].num_primitives_written; 270af69d88dSmrg break; 271af69d88dSmrg case PIPE_QUERY_PRIMITIVES_GENERATED: 2727ec681f3Smrg *result = sq->so[sq->index].primitives_storage_needed; 273af69d88dSmrg break; 274af69d88dSmrg case PIPE_QUERY_OCCLUSION_PREDICATE: 27501e04c3fSmrg case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE: 276af69d88dSmrg vresult->b = sq->end - sq->start != 0; 277af69d88dSmrg break; 2783464ebd5Sriastradh default: 2793464ebd5Sriastradh *result = sq->end - sq->start; 2803464ebd5Sriastradh break; 2813464ebd5Sriastradh } 2827ec681f3Smrg return true; 2834a49301eSmrg} 2844a49301eSmrg 2857ec681f3Smrgstatic bool 2867ec681f3Smrgis_result_nonzero(struct pipe_query *q, 2877ec681f3Smrg union pipe_query_result *vresult) 2887ec681f3Smrg{ 2897ec681f3Smrg struct softpipe_query *sq = softpipe_query(q); 2907ec681f3Smrg 2917ec681f3Smrg switch (sq->type) { 2927ec681f3Smrg case PIPE_QUERY_TIMESTAMP_DISJOINT: 2937ec681f3Smrg case PIPE_QUERY_SO_STATISTICS: 2947ec681f3Smrg case PIPE_QUERY_PIPELINE_STATISTICS: 2957ec681f3Smrg unreachable("unpossible"); 2967ec681f3Smrg break; 2977ec681f3Smrg case PIPE_QUERY_GPU_FINISHED: 2987ec681f3Smrg case PIPE_QUERY_OCCLUSION_PREDICATE: 2997ec681f3Smrg case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE: 3007ec681f3Smrg case PIPE_QUERY_SO_OVERFLOW_PREDICATE: 3017ec681f3Smrg case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE: 3027ec681f3Smrg return vresult->b; 3037ec681f3Smrg default: 3047ec681f3Smrg return !!vresult->u64; 3057ec681f3Smrg } 3067ec681f3Smrg return false; 3077ec681f3Smrg} 3084a49301eSmrg 309cdc920a0Smrg/** 310cdc920a0Smrg * Called by rendering function to check rendering is conditional. 311cdc920a0Smrg * \return TRUE if we should render, FALSE if we should skip rendering 312cdc920a0Smrg */ 313cdc920a0Smrgboolean 314cdc920a0Smrgsoftpipe_check_render_cond(struct softpipe_context *sp) 315cdc920a0Smrg{ 316cdc920a0Smrg struct pipe_context *pipe = &sp->pipe; 317cdc920a0Smrg boolean b, wait; 3187ec681f3Smrg union pipe_query_result result; 3197ec681f3Smrg memset(&result, 0, sizeof(union pipe_query_result)); 320cdc920a0Smrg 321cdc920a0Smrg if (!sp->render_cond_query) { 322cdc920a0Smrg return TRUE; /* no query predicate, draw normally */ 323cdc920a0Smrg } 324cdc920a0Smrg 325cdc920a0Smrg wait = (sp->render_cond_mode == PIPE_RENDER_COND_WAIT || 326cdc920a0Smrg sp->render_cond_mode == PIPE_RENDER_COND_BY_REGION_WAIT); 327cdc920a0Smrg 328af69d88dSmrg b = pipe->get_query_result(pipe, sp->render_cond_query, wait, 3297ec681f3Smrg &result); 330cdc920a0Smrg if (b) 3317ec681f3Smrg return !is_result_nonzero(sp->render_cond_query, &result) == sp->render_cond_cond; 332cdc920a0Smrg else 333cdc920a0Smrg return TRUE; 334cdc920a0Smrg} 335cdc920a0Smrg 336cdc920a0Smrg 33701e04c3fSmrgstatic void 3387ec681f3Smrgsoftpipe_set_active_query_state(struct pipe_context *pipe, bool enable) 33901e04c3fSmrg{ 34001e04c3fSmrg} 34101e04c3fSmrg 34201e04c3fSmrg 3434a49301eSmrgvoid softpipe_init_query_funcs(struct softpipe_context *softpipe ) 3444a49301eSmrg{ 3454a49301eSmrg softpipe->pipe.create_query = softpipe_create_query; 3464a49301eSmrg softpipe->pipe.destroy_query = softpipe_destroy_query; 3474a49301eSmrg softpipe->pipe.begin_query = softpipe_begin_query; 3484a49301eSmrg softpipe->pipe.end_query = softpipe_end_query; 3494a49301eSmrg softpipe->pipe.get_query_result = softpipe_get_query_result; 35001e04c3fSmrg softpipe->pipe.set_active_query_state = softpipe_set_active_query_state; 3514a49301eSmrg} 3524a49301eSmrg 3534a49301eSmrg 354