14a49301eSmrg/************************************************************************** 24a49301eSmrg * 3af69d88dSmrg * Copyright 2007 VMware, Inc. 43464ebd5Sriastradh * Copyright 2010 VMware, Inc. 54a49301eSmrg * All Rights Reserved. 64a49301eSmrg * 74a49301eSmrg * Permission is hereby granted, free of charge, to any person obtaining a 84a49301eSmrg * copy of this software and associated documentation files (the 94a49301eSmrg * "Software"), to deal in the Software without restriction, including 104a49301eSmrg * without limitation the rights to use, copy, modify, merge, publish, 114a49301eSmrg * distribute, sub license, and/or sell copies of the Software, and to 124a49301eSmrg * permit persons to whom the Software is furnished to do so, subject to 134a49301eSmrg * the following conditions: 144a49301eSmrg * 154a49301eSmrg * The above copyright notice and this permission notice (including the 164a49301eSmrg * next paragraph) shall be included in all copies or substantial portions 174a49301eSmrg * of the Software. 184a49301eSmrg * 194a49301eSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 204a49301eSmrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 214a49301eSmrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 223464ebd5Sriastradh * IN NO EVENT SHALL THE AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR 234a49301eSmrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 244a49301eSmrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 254a49301eSmrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 264a49301eSmrg * 274a49301eSmrg **************************************************************************/ 284a49301eSmrg 293464ebd5Sriastradh/* Authors: 303464ebd5Sriastradh * Keith Whitwell, Qicheng Christopher Li, Brian Paul 314a49301eSmrg */ 324a49301eSmrg 334a49301eSmrg#include "draw/draw_context.h" 344a49301eSmrg#include "pipe/p_defines.h" 354a49301eSmrg#include "util/u_memory.h" 3601e04c3fSmrg#include "util/os_time.h" 374a49301eSmrg#include "lp_context.h" 383464ebd5Sriastradh#include "lp_flush.h" 393464ebd5Sriastradh#include "lp_fence.h" 404a49301eSmrg#include "lp_query.h" 41af69d88dSmrg#include "lp_screen.h" 424a49301eSmrg#include "lp_state.h" 43af69d88dSmrg#include "lp_rast.h" 444a49301eSmrg 454a49301eSmrg 464a49301eSmrgstatic struct llvmpipe_query *llvmpipe_query( struct pipe_query *p ) 474a49301eSmrg{ 484a49301eSmrg return (struct llvmpipe_query *)p; 494a49301eSmrg} 504a49301eSmrg 514a49301eSmrgstatic struct pipe_query * 524a49301eSmrgllvmpipe_create_query(struct pipe_context *pipe, 53af69d88dSmrg unsigned type, 54af69d88dSmrg unsigned index) 554a49301eSmrg{ 563464ebd5Sriastradh struct llvmpipe_query *pq; 573464ebd5Sriastradh 58af69d88dSmrg assert(type < PIPE_QUERY_TYPES); 593464ebd5Sriastradh 603464ebd5Sriastradh pq = CALLOC_STRUCT( llvmpipe_query ); 613464ebd5Sriastradh 62af69d88dSmrg if (pq) { 63af69d88dSmrg pq->type = type; 647ec681f3Smrg pq->index = index; 65af69d88dSmrg } 66af69d88dSmrg 673464ebd5Sriastradh return (struct pipe_query *) pq; 684a49301eSmrg} 694a49301eSmrg 704a49301eSmrg 714a49301eSmrgstatic void 724a49301eSmrgllvmpipe_destroy_query(struct pipe_context *pipe, struct pipe_query *q) 734a49301eSmrg{ 743464ebd5Sriastradh struct llvmpipe_query *pq = llvmpipe_query(q); 753464ebd5Sriastradh 763464ebd5Sriastradh /* Ideally we would refcount queries & not get destroyed until the 773464ebd5Sriastradh * last scene had finished with us. 783464ebd5Sriastradh */ 793464ebd5Sriastradh if (pq->fence) { 803464ebd5Sriastradh if (!lp_fence_issued(pq->fence)) 813464ebd5Sriastradh llvmpipe_flush(pipe, NULL, __FUNCTION__); 823464ebd5Sriastradh 833464ebd5Sriastradh if (!lp_fence_signalled(pq->fence)) 843464ebd5Sriastradh lp_fence_wait(pq->fence); 853464ebd5Sriastradh 863464ebd5Sriastradh lp_fence_reference(&pq->fence, NULL); 873464ebd5Sriastradh } 883464ebd5Sriastradh 893464ebd5Sriastradh FREE(pq); 903464ebd5Sriastradh} 913464ebd5Sriastradh 923464ebd5Sriastradh 937ec681f3Smrgstatic bool 943464ebd5Sriastradhllvmpipe_get_query_result(struct pipe_context *pipe, 953464ebd5Sriastradh struct pipe_query *q, 967ec681f3Smrg bool wait, 97af69d88dSmrg union pipe_query_result *vresult) 983464ebd5Sriastradh{ 99af69d88dSmrg struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen); 100af69d88dSmrg unsigned num_threads = MAX2(1, screen->num_threads); 1013464ebd5Sriastradh struct llvmpipe_query *pq = llvmpipe_query(q); 1023464ebd5Sriastradh uint64_t *result = (uint64_t *)vresult; 1033464ebd5Sriastradh int i; 1043464ebd5Sriastradh 105af69d88dSmrg if (pq->fence) { 106af69d88dSmrg /* only have a fence if there was a scene */ 107af69d88dSmrg if (!lp_fence_signalled(pq->fence)) { 108af69d88dSmrg if (!lp_fence_issued(pq->fence)) 109af69d88dSmrg llvmpipe_flush(pipe, NULL, __FUNCTION__); 1103464ebd5Sriastradh 111af69d88dSmrg if (!wait) 1127ec681f3Smrg return false; 1133464ebd5Sriastradh 114af69d88dSmrg lp_fence_wait(pq->fence); 115af69d88dSmrg } 1163464ebd5Sriastradh } 1173464ebd5Sriastradh 1183464ebd5Sriastradh /* Sum the results from each of the threads: 1193464ebd5Sriastradh */ 1203464ebd5Sriastradh *result = 0; 121af69d88dSmrg 122af69d88dSmrg switch (pq->type) { 123af69d88dSmrg case PIPE_QUERY_OCCLUSION_COUNTER: 124af69d88dSmrg for (i = 0; i < num_threads; i++) { 125af69d88dSmrg *result += pq->end[i]; 126af69d88dSmrg } 127af69d88dSmrg break; 128af69d88dSmrg case PIPE_QUERY_OCCLUSION_PREDICATE: 12901e04c3fSmrg case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE: 130af69d88dSmrg for (i = 0; i < num_threads; i++) { 131af69d88dSmrg /* safer (still not guaranteed) when there's an overflow */ 132af69d88dSmrg vresult->b = vresult->b || pq->end[i]; 133af69d88dSmrg } 134af69d88dSmrg break; 135af69d88dSmrg case PIPE_QUERY_TIMESTAMP: 136af69d88dSmrg for (i = 0; i < num_threads; i++) { 137af69d88dSmrg if (pq->end[i] > *result) { 138af69d88dSmrg *result = pq->end[i]; 139af69d88dSmrg } 140af69d88dSmrg } 141af69d88dSmrg break; 1427ec681f3Smrg case PIPE_QUERY_TIME_ELAPSED: { 1437ec681f3Smrg uint64_t start = (uint64_t)-1, end = 0; 1447ec681f3Smrg for (i = 0; i < num_threads; i++) { 1457ec681f3Smrg if (pq->start[i] && pq->start[i] < start) 1467ec681f3Smrg start = pq->start[i]; 1477ec681f3Smrg if (pq->end[i] && pq->end[i] > end) 1487ec681f3Smrg end = pq->end[i]; 1497ec681f3Smrg } 1507ec681f3Smrg *result = end - start; 1517ec681f3Smrg break; 1527ec681f3Smrg } 153af69d88dSmrg case PIPE_QUERY_TIMESTAMP_DISJOINT: { 154af69d88dSmrg struct pipe_query_data_timestamp_disjoint *td = 155af69d88dSmrg (struct pipe_query_data_timestamp_disjoint *)vresult; 156af69d88dSmrg /* os_get_time_nano return nanoseconds */ 157af69d88dSmrg td->frequency = UINT64_C(1000000000); 1587ec681f3Smrg td->disjoint = false; 159af69d88dSmrg } 160af69d88dSmrg break; 161af69d88dSmrg case PIPE_QUERY_GPU_FINISHED: 1627ec681f3Smrg vresult->b = true; 163af69d88dSmrg break; 164af69d88dSmrg case PIPE_QUERY_PRIMITIVES_GENERATED: 1657ec681f3Smrg *result = pq->num_primitives_generated[0]; 166af69d88dSmrg break; 167af69d88dSmrg case PIPE_QUERY_PRIMITIVES_EMITTED: 1687ec681f3Smrg *result = pq->num_primitives_written[0]; 169af69d88dSmrg break; 17001e04c3fSmrg case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE: 1717ec681f3Smrg vresult->b = false; 1727ec681f3Smrg for (unsigned s = 0; s < PIPE_MAX_VERTEX_STREAMS; s++) 1737ec681f3Smrg vresult->b |= pq->num_primitives_generated[s] > pq->num_primitives_written[s]; 1747ec681f3Smrg break; 1757ec681f3Smrg case PIPE_QUERY_SO_OVERFLOW_PREDICATE: 1767ec681f3Smrg vresult->b = pq->num_primitives_generated[0] > pq->num_primitives_written[0]; 177af69d88dSmrg break; 178af69d88dSmrg case PIPE_QUERY_SO_STATISTICS: { 179af69d88dSmrg struct pipe_query_data_so_statistics *stats = 180af69d88dSmrg (struct pipe_query_data_so_statistics *)vresult; 1817ec681f3Smrg stats->num_primitives_written = pq->num_primitives_written[0]; 1827ec681f3Smrg stats->primitives_storage_needed = pq->num_primitives_generated[0]; 183af69d88dSmrg } 184af69d88dSmrg break; 185af69d88dSmrg case PIPE_QUERY_PIPELINE_STATISTICS: { 186af69d88dSmrg struct pipe_query_data_pipeline_statistics *stats = 187af69d88dSmrg (struct pipe_query_data_pipeline_statistics *)vresult; 188af69d88dSmrg /* only ps_invocations come from binned query */ 189af69d88dSmrg for (i = 0; i < num_threads; i++) { 190af69d88dSmrg pq->stats.ps_invocations += pq->end[i]; 191af69d88dSmrg } 192af69d88dSmrg pq->stats.ps_invocations *= LP_RASTER_BLOCK_SIZE * LP_RASTER_BLOCK_SIZE; 193af69d88dSmrg *stats = pq->stats; 194af69d88dSmrg } 195af69d88dSmrg break; 196af69d88dSmrg default: 197af69d88dSmrg assert(0); 198af69d88dSmrg break; 1993464ebd5Sriastradh } 2003464ebd5Sriastradh 2017ec681f3Smrg return true; 2024a49301eSmrg} 2034a49301eSmrg 2047ec681f3Smrgstatic void 2057ec681f3Smrgllvmpipe_get_query_result_resource(struct pipe_context *pipe, 2067ec681f3Smrg struct pipe_query *q, 2077ec681f3Smrg bool wait, 2087ec681f3Smrg enum pipe_query_value_type result_type, 2097ec681f3Smrg int index, 2107ec681f3Smrg struct pipe_resource *resource, 2117ec681f3Smrg unsigned offset) 2127ec681f3Smrg{ 2137ec681f3Smrg struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen); 2147ec681f3Smrg unsigned num_threads = MAX2(1, screen->num_threads); 2157ec681f3Smrg struct llvmpipe_query *pq = llvmpipe_query(q); 2167ec681f3Smrg struct llvmpipe_resource *lpr = llvmpipe_resource(resource); 2177ec681f3Smrg bool unsignalled = false; 2187ec681f3Smrg if (pq->fence) { 2197ec681f3Smrg /* only have a fence if there was a scene */ 2207ec681f3Smrg if (!lp_fence_signalled(pq->fence)) { 2217ec681f3Smrg if (!lp_fence_issued(pq->fence)) 2227ec681f3Smrg llvmpipe_flush(pipe, NULL, __FUNCTION__); 2237ec681f3Smrg 2247ec681f3Smrg if (wait) 2257ec681f3Smrg lp_fence_wait(pq->fence); 2267ec681f3Smrg } 2277ec681f3Smrg unsignalled = !lp_fence_signalled(pq->fence); 2287ec681f3Smrg } 2297ec681f3Smrg 2304a49301eSmrg 2317ec681f3Smrg uint64_t value = 0, value2 = 0; 2327ec681f3Smrg unsigned num_values = 1; 2337ec681f3Smrg if (index == -1) 2347ec681f3Smrg if (unsignalled) 2357ec681f3Smrg value = 0; 2367ec681f3Smrg else 2377ec681f3Smrg value = 1; 2387ec681f3Smrg else { 2397ec681f3Smrg unsigned i; 2407ec681f3Smrg 2417ec681f3Smrg switch (pq->type) { 2427ec681f3Smrg case PIPE_QUERY_OCCLUSION_COUNTER: 2437ec681f3Smrg for (i = 0; i < num_threads; i++) { 2447ec681f3Smrg value += pq->end[i]; 2457ec681f3Smrg } 2467ec681f3Smrg break; 2477ec681f3Smrg case PIPE_QUERY_OCCLUSION_PREDICATE: 2487ec681f3Smrg case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE: 2497ec681f3Smrg for (i = 0; i < num_threads; i++) { 2507ec681f3Smrg /* safer (still not guaranteed) when there's an overflow */ 2517ec681f3Smrg value = value || pq->end[i]; 2527ec681f3Smrg } 2537ec681f3Smrg break; 2547ec681f3Smrg case PIPE_QUERY_PRIMITIVES_GENERATED: 2557ec681f3Smrg value = pq->num_primitives_generated[0]; 2567ec681f3Smrg break; 2577ec681f3Smrg case PIPE_QUERY_PRIMITIVES_EMITTED: 2587ec681f3Smrg value = pq->num_primitives_written[0]; 2597ec681f3Smrg break; 2607ec681f3Smrg case PIPE_QUERY_TIMESTAMP: 2617ec681f3Smrg for (i = 0; i < num_threads; i++) { 2627ec681f3Smrg if (pq->end[i] > value) { 2637ec681f3Smrg value = pq->end[i]; 2647ec681f3Smrg } 2657ec681f3Smrg } 2667ec681f3Smrg break; 2677ec681f3Smrg case PIPE_QUERY_TIME_ELAPSED: { 2687ec681f3Smrg uint64_t start = (uint64_t)-1, end = 0; 2697ec681f3Smrg for (i = 0; i < num_threads; i++) { 2707ec681f3Smrg if (pq->start[i] && pq->start[i] < start) 2717ec681f3Smrg start = pq->start[i]; 2727ec681f3Smrg if (pq->end[i] && pq->end[i] > end) 2737ec681f3Smrg end = pq->end[i]; 2747ec681f3Smrg } 2757ec681f3Smrg value = end - start; 2767ec681f3Smrg break; 2777ec681f3Smrg } 2787ec681f3Smrg case PIPE_QUERY_SO_STATISTICS: 2797ec681f3Smrg value = pq->num_primitives_written[0]; 2807ec681f3Smrg value2 = pq->num_primitives_generated[0]; 2817ec681f3Smrg num_values = 2; 2827ec681f3Smrg break; 2837ec681f3Smrg case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE: 2847ec681f3Smrg value = 0; 2857ec681f3Smrg for (unsigned s = 0; s < PIPE_MAX_VERTEX_STREAMS; s++) 2867ec681f3Smrg value |= !!(pq->num_primitives_generated[s] > pq->num_primitives_written[s]); 2877ec681f3Smrg break; 2887ec681f3Smrg case PIPE_QUERY_SO_OVERFLOW_PREDICATE: 2897ec681f3Smrg value = !!(pq->num_primitives_generated[0] > pq->num_primitives_written[0]); 2907ec681f3Smrg break; 2917ec681f3Smrg case PIPE_QUERY_PIPELINE_STATISTICS: 2927ec681f3Smrg switch ((enum pipe_statistics_query_index)index) { 2937ec681f3Smrg case PIPE_STAT_QUERY_IA_VERTICES: 2947ec681f3Smrg value = pq->stats.ia_vertices; 2957ec681f3Smrg break; 2967ec681f3Smrg case PIPE_STAT_QUERY_IA_PRIMITIVES: 2977ec681f3Smrg value = pq->stats.ia_primitives; 2987ec681f3Smrg break; 2997ec681f3Smrg case PIPE_STAT_QUERY_VS_INVOCATIONS: 3007ec681f3Smrg value = pq->stats.vs_invocations; 3017ec681f3Smrg break; 3027ec681f3Smrg case PIPE_STAT_QUERY_GS_INVOCATIONS: 3037ec681f3Smrg value = pq->stats.gs_invocations; 3047ec681f3Smrg break; 3057ec681f3Smrg case PIPE_STAT_QUERY_GS_PRIMITIVES: 3067ec681f3Smrg value = pq->stats.gs_primitives; 3077ec681f3Smrg break; 3087ec681f3Smrg case PIPE_STAT_QUERY_C_INVOCATIONS: 3097ec681f3Smrg value = pq->stats.c_invocations; 3107ec681f3Smrg break; 3117ec681f3Smrg case PIPE_STAT_QUERY_C_PRIMITIVES: 3127ec681f3Smrg value = pq->stats.c_primitives; 3137ec681f3Smrg break; 3147ec681f3Smrg case PIPE_STAT_QUERY_PS_INVOCATIONS: 3157ec681f3Smrg value = 0; 3167ec681f3Smrg for (i = 0; i < num_threads; i++) { 3177ec681f3Smrg value += pq->end[i]; 3187ec681f3Smrg } 3197ec681f3Smrg value *= LP_RASTER_BLOCK_SIZE * LP_RASTER_BLOCK_SIZE; 3207ec681f3Smrg break; 3217ec681f3Smrg case PIPE_STAT_QUERY_HS_INVOCATIONS: 3227ec681f3Smrg value = pq->stats.hs_invocations; 3237ec681f3Smrg break; 3247ec681f3Smrg case PIPE_STAT_QUERY_DS_INVOCATIONS: 3257ec681f3Smrg value = pq->stats.ds_invocations; 3267ec681f3Smrg break; 3277ec681f3Smrg case PIPE_STAT_QUERY_CS_INVOCATIONS: 3287ec681f3Smrg value = pq->stats.cs_invocations; 3297ec681f3Smrg break; 3307ec681f3Smrg } 3317ec681f3Smrg break; 3327ec681f3Smrg default: 3337ec681f3Smrg fprintf(stderr, "Unknown query type %d\n", pq->type); 3347ec681f3Smrg break; 3357ec681f3Smrg } 3367ec681f3Smrg } 3377ec681f3Smrg 3387ec681f3Smrg void *dst = (uint8_t *)lpr->data + offset; 3397ec681f3Smrg 3407ec681f3Smrg for (unsigned i = 0; i < num_values; i++) { 3417ec681f3Smrg 3427ec681f3Smrg if (i == 1) { 3437ec681f3Smrg value = value2; 3447ec681f3Smrg dst = (char *)dst + ((result_type == PIPE_QUERY_TYPE_I64 || 3457ec681f3Smrg result_type == PIPE_QUERY_TYPE_U64) ? 8 : 4); 3467ec681f3Smrg } 3477ec681f3Smrg switch (result_type) { 3487ec681f3Smrg case PIPE_QUERY_TYPE_I32: { 3497ec681f3Smrg int32_t *iptr = (int32_t *)dst; 3507ec681f3Smrg if (value > 0x7fffffff) 3517ec681f3Smrg *iptr = 0x7fffffff; 3527ec681f3Smrg else 3537ec681f3Smrg *iptr = (int32_t)value; 3547ec681f3Smrg break; 3557ec681f3Smrg } 3567ec681f3Smrg case PIPE_QUERY_TYPE_U32: { 3577ec681f3Smrg uint32_t *uptr = (uint32_t *)dst; 3587ec681f3Smrg if (value > 0xffffffff) 3597ec681f3Smrg *uptr = 0xffffffff; 3607ec681f3Smrg else 3617ec681f3Smrg *uptr = (uint32_t)value; 3627ec681f3Smrg break; 3637ec681f3Smrg } 3647ec681f3Smrg case PIPE_QUERY_TYPE_I64: { 3657ec681f3Smrg int64_t *iptr = (int64_t *)dst; 3667ec681f3Smrg *iptr = (int64_t)value; 3677ec681f3Smrg break; 3687ec681f3Smrg } 3697ec681f3Smrg case PIPE_QUERY_TYPE_U64: { 3707ec681f3Smrg uint64_t *uptr = (uint64_t *)dst; 3717ec681f3Smrg *uptr = (uint64_t)value; 3727ec681f3Smrg break; 3737ec681f3Smrg } 3747ec681f3Smrg } 3757ec681f3Smrg } 3767ec681f3Smrg} 3777ec681f3Smrg 3787ec681f3Smrgstatic bool 3794a49301eSmrgllvmpipe_begin_query(struct pipe_context *pipe, struct pipe_query *q) 3804a49301eSmrg{ 3814a49301eSmrg struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe ); 3823464ebd5Sriastradh struct llvmpipe_query *pq = llvmpipe_query(q); 3833464ebd5Sriastradh 3843464ebd5Sriastradh /* Check if the query is already in the scene. If so, we need to 3853464ebd5Sriastradh * flush the scene now. Real apps shouldn't re-use a query in a 3863464ebd5Sriastradh * frame of rendering. 3873464ebd5Sriastradh */ 3883464ebd5Sriastradh if (pq->fence && !lp_fence_issued(pq->fence)) { 3893464ebd5Sriastradh llvmpipe_finish(pipe, __FUNCTION__); 3903464ebd5Sriastradh } 3913464ebd5Sriastradh 3923464ebd5Sriastradh 393af69d88dSmrg memset(pq->start, 0, sizeof(pq->start)); 394af69d88dSmrg memset(pq->end, 0, sizeof(pq->end)); 3953464ebd5Sriastradh lp_setup_begin_query(llvmpipe->setup, pq); 3963464ebd5Sriastradh 397af69d88dSmrg switch (pq->type) { 398af69d88dSmrg case PIPE_QUERY_PRIMITIVES_EMITTED: 3997ec681f3Smrg pq->num_primitives_written[0] = llvmpipe->so_stats[pq->index].num_primitives_written; 400af69d88dSmrg break; 401af69d88dSmrg case PIPE_QUERY_PRIMITIVES_GENERATED: 4027ec681f3Smrg pq->num_primitives_generated[0] = llvmpipe->so_stats[pq->index].primitives_storage_needed; 4037ec681f3Smrg llvmpipe->active_primgen_queries++; 404af69d88dSmrg break; 405af69d88dSmrg case PIPE_QUERY_SO_STATISTICS: 4067ec681f3Smrg pq->num_primitives_written[0] = llvmpipe->so_stats[pq->index].num_primitives_written; 4077ec681f3Smrg pq->num_primitives_generated[0] = llvmpipe->so_stats[pq->index].primitives_storage_needed; 408af69d88dSmrg break; 40901e04c3fSmrg case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE: 4107ec681f3Smrg for (unsigned s = 0; s < PIPE_MAX_VERTEX_STREAMS; s++) { 4117ec681f3Smrg pq->num_primitives_written[s] = llvmpipe->so_stats[s].num_primitives_written; 4127ec681f3Smrg pq->num_primitives_generated[s] = llvmpipe->so_stats[s].primitives_storage_needed; 4137ec681f3Smrg } 4147ec681f3Smrg break; 4157ec681f3Smrg case PIPE_QUERY_SO_OVERFLOW_PREDICATE: 4167ec681f3Smrg pq->num_primitives_written[0] = llvmpipe->so_stats[pq->index].num_primitives_written; 4177ec681f3Smrg pq->num_primitives_generated[0] = llvmpipe->so_stats[pq->index].primitives_storage_needed; 418af69d88dSmrg break; 419af69d88dSmrg case PIPE_QUERY_PIPELINE_STATISTICS: 420af69d88dSmrg /* reset our cache */ 421af69d88dSmrg if (llvmpipe->active_statistics_queries == 0) { 422af69d88dSmrg memset(&llvmpipe->pipeline_statistics, 0, 423af69d88dSmrg sizeof(llvmpipe->pipeline_statistics)); 424af69d88dSmrg } 425af69d88dSmrg memcpy(&pq->stats, &llvmpipe->pipeline_statistics, sizeof(pq->stats)); 426af69d88dSmrg llvmpipe->active_statistics_queries++; 427af69d88dSmrg break; 428af69d88dSmrg case PIPE_QUERY_OCCLUSION_COUNTER: 429af69d88dSmrg case PIPE_QUERY_OCCLUSION_PREDICATE: 43001e04c3fSmrg case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE: 431af69d88dSmrg llvmpipe->active_occlusion_queries++; 432af69d88dSmrg llvmpipe->dirty |= LP_NEW_OCCLUSION_QUERY; 433af69d88dSmrg break; 434af69d88dSmrg default: 435af69d88dSmrg break; 436af69d88dSmrg } 43701e04c3fSmrg return true; 4384a49301eSmrg} 4394a49301eSmrg 4404a49301eSmrg 44101e04c3fSmrgstatic bool 4424a49301eSmrgllvmpipe_end_query(struct pipe_context *pipe, struct pipe_query *q) 4434a49301eSmrg{ 4444a49301eSmrg struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe ); 4453464ebd5Sriastradh struct llvmpipe_query *pq = llvmpipe_query(q); 4463464ebd5Sriastradh 4473464ebd5Sriastradh lp_setup_end_query(llvmpipe->setup, pq); 4484a49301eSmrg 449af69d88dSmrg switch (pq->type) { 450af69d88dSmrg 451af69d88dSmrg case PIPE_QUERY_PRIMITIVES_EMITTED: 4527ec681f3Smrg pq->num_primitives_written[0] = 4537ec681f3Smrg llvmpipe->so_stats[pq->index].num_primitives_written - pq->num_primitives_written[0]; 454af69d88dSmrg break; 455af69d88dSmrg case PIPE_QUERY_PRIMITIVES_GENERATED: 4567ec681f3Smrg assert(llvmpipe->active_primgen_queries); 4577ec681f3Smrg llvmpipe->active_primgen_queries--; 4587ec681f3Smrg pq->num_primitives_generated[0] = 4597ec681f3Smrg llvmpipe->so_stats[pq->index].primitives_storage_needed - pq->num_primitives_generated[0]; 460af69d88dSmrg break; 461af69d88dSmrg case PIPE_QUERY_SO_STATISTICS: 4627ec681f3Smrg pq->num_primitives_written[0] = 4637ec681f3Smrg llvmpipe->so_stats[pq->index].num_primitives_written - pq->num_primitives_written[0]; 4647ec681f3Smrg pq->num_primitives_generated[0] = 4657ec681f3Smrg llvmpipe->so_stats[pq->index].primitives_storage_needed - pq->num_primitives_generated[0]; 466af69d88dSmrg break; 46701e04c3fSmrg case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE: 4687ec681f3Smrg for (unsigned s = 0; s < PIPE_MAX_VERTEX_STREAMS; s++) { 4697ec681f3Smrg pq->num_primitives_written[s] = 4707ec681f3Smrg llvmpipe->so_stats[s].num_primitives_written - pq->num_primitives_written[s]; 4717ec681f3Smrg pq->num_primitives_generated[s] = 4727ec681f3Smrg llvmpipe->so_stats[s].primitives_storage_needed - pq->num_primitives_generated[s]; 4737ec681f3Smrg } 4747ec681f3Smrg break; 4757ec681f3Smrg case PIPE_QUERY_SO_OVERFLOW_PREDICATE: 4767ec681f3Smrg pq->num_primitives_written[0] = 4777ec681f3Smrg llvmpipe->so_stats[pq->index].num_primitives_written - pq->num_primitives_written[0]; 4787ec681f3Smrg pq->num_primitives_generated[0] = 4797ec681f3Smrg llvmpipe->so_stats[pq->index].primitives_storage_needed - pq->num_primitives_generated[0]; 480af69d88dSmrg break; 481af69d88dSmrg case PIPE_QUERY_PIPELINE_STATISTICS: 482af69d88dSmrg pq->stats.ia_vertices = 483af69d88dSmrg llvmpipe->pipeline_statistics.ia_vertices - pq->stats.ia_vertices; 484af69d88dSmrg pq->stats.ia_primitives = 485af69d88dSmrg llvmpipe->pipeline_statistics.ia_primitives - pq->stats.ia_primitives; 486af69d88dSmrg pq->stats.vs_invocations = 487af69d88dSmrg llvmpipe->pipeline_statistics.vs_invocations - pq->stats.vs_invocations; 488af69d88dSmrg pq->stats.gs_invocations = 489af69d88dSmrg llvmpipe->pipeline_statistics.gs_invocations - pq->stats.gs_invocations; 490af69d88dSmrg pq->stats.gs_primitives = 491af69d88dSmrg llvmpipe->pipeline_statistics.gs_primitives - pq->stats.gs_primitives; 492af69d88dSmrg pq->stats.c_invocations = 493af69d88dSmrg llvmpipe->pipeline_statistics.c_invocations - pq->stats.c_invocations; 494af69d88dSmrg pq->stats.c_primitives = 495af69d88dSmrg llvmpipe->pipeline_statistics.c_primitives - pq->stats.c_primitives; 496af69d88dSmrg pq->stats.ps_invocations = 497af69d88dSmrg llvmpipe->pipeline_statistics.ps_invocations - pq->stats.ps_invocations; 4987ec681f3Smrg pq->stats.cs_invocations = 4997ec681f3Smrg llvmpipe->pipeline_statistics.cs_invocations - pq->stats.cs_invocations; 5007ec681f3Smrg pq->stats.hs_invocations = 5017ec681f3Smrg llvmpipe->pipeline_statistics.hs_invocations - pq->stats.hs_invocations; 5027ec681f3Smrg pq->stats.ds_invocations = 5037ec681f3Smrg llvmpipe->pipeline_statistics.ds_invocations - pq->stats.ds_invocations; 504af69d88dSmrg llvmpipe->active_statistics_queries--; 505af69d88dSmrg break; 506af69d88dSmrg case PIPE_QUERY_OCCLUSION_COUNTER: 507af69d88dSmrg case PIPE_QUERY_OCCLUSION_PREDICATE: 50801e04c3fSmrg case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE: 509af69d88dSmrg assert(llvmpipe->active_occlusion_queries); 510af69d88dSmrg llvmpipe->active_occlusion_queries--; 511af69d88dSmrg llvmpipe->dirty |= LP_NEW_OCCLUSION_QUERY; 512af69d88dSmrg break; 513af69d88dSmrg default: 514af69d88dSmrg break; 515af69d88dSmrg } 51601e04c3fSmrg 51701e04c3fSmrg return true; 5184a49301eSmrg} 5194a49301eSmrg 520af69d88dSmrgboolean 521af69d88dSmrgllvmpipe_check_render_cond(struct llvmpipe_context *lp) 522af69d88dSmrg{ 523af69d88dSmrg struct pipe_context *pipe = &lp->pipe; 524af69d88dSmrg boolean b, wait; 525af69d88dSmrg uint64_t result; 526af69d88dSmrg 5277ec681f3Smrg if (lp->render_cond_buffer) { 5287ec681f3Smrg uint32_t data = *(uint32_t *)((char *)lp->render_cond_buffer->data + lp->render_cond_offset); 5297ec681f3Smrg return (!data) == lp->render_cond_cond; 5307ec681f3Smrg } 531af69d88dSmrg if (!lp->render_cond_query) 532af69d88dSmrg return TRUE; /* no query predicate, draw normally */ 533af69d88dSmrg 534af69d88dSmrg wait = (lp->render_cond_mode == PIPE_RENDER_COND_WAIT || 535af69d88dSmrg lp->render_cond_mode == PIPE_RENDER_COND_BY_REGION_WAIT); 536af69d88dSmrg 537af69d88dSmrg b = pipe->get_query_result(pipe, lp->render_cond_query, wait, (void*)&result); 538af69d88dSmrg if (b) 53901e04c3fSmrg return ((!result) == lp->render_cond_cond); 540af69d88dSmrg else 541af69d88dSmrg return TRUE; 542af69d88dSmrg} 5434a49301eSmrg 54401e04c3fSmrgstatic void 5457ec681f3Smrgllvmpipe_set_active_query_state(struct pipe_context *pipe, bool enable) 54601e04c3fSmrg{ 5477ec681f3Smrg struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); 5487ec681f3Smrg 5497ec681f3Smrg llvmpipe->queries_disabled = !enable; 5507ec681f3Smrg /* for OQs we need to regenerate the fragment shader */ 5517ec681f3Smrg llvmpipe->dirty |= LP_NEW_OCCLUSION_QUERY; 55201e04c3fSmrg} 55301e04c3fSmrg 5544a49301eSmrgvoid llvmpipe_init_query_funcs(struct llvmpipe_context *llvmpipe ) 5554a49301eSmrg{ 5564a49301eSmrg llvmpipe->pipe.create_query = llvmpipe_create_query; 5574a49301eSmrg llvmpipe->pipe.destroy_query = llvmpipe_destroy_query; 5584a49301eSmrg llvmpipe->pipe.begin_query = llvmpipe_begin_query; 5594a49301eSmrg llvmpipe->pipe.end_query = llvmpipe_end_query; 5604a49301eSmrg llvmpipe->pipe.get_query_result = llvmpipe_get_query_result; 5617ec681f3Smrg llvmpipe->pipe.get_query_result_resource = llvmpipe_get_query_result_resource; 56201e04c3fSmrg llvmpipe->pipe.set_active_query_state = llvmpipe_set_active_query_state; 5634a49301eSmrg} 5644a49301eSmrg 5654a49301eSmrg 566