1848b8605Smrg/************************************************************************** 2848b8605Smrg * 3848b8605Smrg * Copyright 2007 VMware, Inc. 4848b8605Smrg * Copyright 2010 VMware, Inc. 5848b8605Smrg * All Rights Reserved. 6848b8605Smrg * 7848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 8848b8605Smrg * copy of this software and associated documentation files (the 9848b8605Smrg * "Software"), to deal in the Software without restriction, including 10848b8605Smrg * without limitation the rights to use, copy, modify, merge, publish, 11848b8605Smrg * distribute, sub license, and/or sell copies of the Software, and to 12848b8605Smrg * permit persons to whom the Software is furnished to do so, subject to 13848b8605Smrg * the following conditions: 14848b8605Smrg * 15848b8605Smrg * The above copyright notice and this permission notice (including the 16848b8605Smrg * next paragraph) shall be included in all copies or substantial portions 17848b8605Smrg * of the Software. 18848b8605Smrg * 19848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21848b8605Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 22848b8605Smrg * IN NO EVENT SHALL THE AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR 23848b8605Smrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24848b8605Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25848b8605Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26848b8605Smrg * 27848b8605Smrg **************************************************************************/ 28848b8605Smrg 29848b8605Smrg/* Authors: 30848b8605Smrg * Keith Whitwell, Qicheng Christopher Li, Brian Paul 31848b8605Smrg */ 32848b8605Smrg 33848b8605Smrg#include "draw/draw_context.h" 34848b8605Smrg#include "pipe/p_defines.h" 35848b8605Smrg#include "util/u_memory.h" 36b8e80941Smrg#include "util/os_time.h" 37848b8605Smrg#include "lp_context.h" 38848b8605Smrg#include "lp_flush.h" 39848b8605Smrg#include "lp_fence.h" 40848b8605Smrg#include "lp_query.h" 41848b8605Smrg#include "lp_screen.h" 42848b8605Smrg#include "lp_state.h" 43848b8605Smrg#include "lp_rast.h" 44848b8605Smrg 45848b8605Smrg 46848b8605Smrgstatic struct llvmpipe_query *llvmpipe_query( struct pipe_query *p ) 47848b8605Smrg{ 48848b8605Smrg return (struct llvmpipe_query *)p; 49848b8605Smrg} 50848b8605Smrg 51848b8605Smrgstatic struct pipe_query * 52848b8605Smrgllvmpipe_create_query(struct pipe_context *pipe, 53848b8605Smrg unsigned type, 54848b8605Smrg unsigned index) 55848b8605Smrg{ 56848b8605Smrg struct llvmpipe_query *pq; 57848b8605Smrg 58848b8605Smrg assert(type < PIPE_QUERY_TYPES); 59848b8605Smrg 60848b8605Smrg pq = CALLOC_STRUCT( llvmpipe_query ); 61848b8605Smrg 62848b8605Smrg if (pq) { 63848b8605Smrg pq->type = type; 64848b8605Smrg } 65848b8605Smrg 66848b8605Smrg return (struct pipe_query *) pq; 67848b8605Smrg} 68848b8605Smrg 69848b8605Smrg 70848b8605Smrgstatic void 71848b8605Smrgllvmpipe_destroy_query(struct pipe_context *pipe, struct pipe_query *q) 72848b8605Smrg{ 73848b8605Smrg struct llvmpipe_query *pq = llvmpipe_query(q); 74848b8605Smrg 75848b8605Smrg /* Ideally we would refcount queries & not get destroyed until the 76848b8605Smrg * last scene had finished with us. 77848b8605Smrg */ 78848b8605Smrg if (pq->fence) { 79848b8605Smrg if (!lp_fence_issued(pq->fence)) 80848b8605Smrg llvmpipe_flush(pipe, NULL, __FUNCTION__); 81848b8605Smrg 82848b8605Smrg if (!lp_fence_signalled(pq->fence)) 83848b8605Smrg lp_fence_wait(pq->fence); 84848b8605Smrg 85848b8605Smrg lp_fence_reference(&pq->fence, NULL); 86848b8605Smrg } 87848b8605Smrg 88848b8605Smrg FREE(pq); 89848b8605Smrg} 90848b8605Smrg 91848b8605Smrg 92848b8605Smrgstatic boolean 93848b8605Smrgllvmpipe_get_query_result(struct pipe_context *pipe, 94848b8605Smrg struct pipe_query *q, 95848b8605Smrg boolean wait, 96848b8605Smrg union pipe_query_result *vresult) 97848b8605Smrg{ 98848b8605Smrg struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen); 99848b8605Smrg unsigned num_threads = MAX2(1, screen->num_threads); 100848b8605Smrg struct llvmpipe_query *pq = llvmpipe_query(q); 101848b8605Smrg uint64_t *result = (uint64_t *)vresult; 102848b8605Smrg int i; 103848b8605Smrg 104848b8605Smrg if (pq->fence) { 105848b8605Smrg /* only have a fence if there was a scene */ 106848b8605Smrg if (!lp_fence_signalled(pq->fence)) { 107848b8605Smrg if (!lp_fence_issued(pq->fence)) 108848b8605Smrg llvmpipe_flush(pipe, NULL, __FUNCTION__); 109848b8605Smrg 110848b8605Smrg if (!wait) 111848b8605Smrg return FALSE; 112848b8605Smrg 113848b8605Smrg lp_fence_wait(pq->fence); 114848b8605Smrg } 115848b8605Smrg } 116848b8605Smrg 117848b8605Smrg /* Sum the results from each of the threads: 118848b8605Smrg */ 119848b8605Smrg *result = 0; 120848b8605Smrg 121848b8605Smrg switch (pq->type) { 122848b8605Smrg case PIPE_QUERY_OCCLUSION_COUNTER: 123848b8605Smrg for (i = 0; i < num_threads; i++) { 124848b8605Smrg *result += pq->end[i]; 125848b8605Smrg } 126848b8605Smrg break; 127848b8605Smrg case PIPE_QUERY_OCCLUSION_PREDICATE: 128b8e80941Smrg case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE: 129848b8605Smrg for (i = 0; i < num_threads; i++) { 130848b8605Smrg /* safer (still not guaranteed) when there's an overflow */ 131848b8605Smrg vresult->b = vresult->b || pq->end[i]; 132848b8605Smrg } 133848b8605Smrg break; 134848b8605Smrg case PIPE_QUERY_TIMESTAMP: 135848b8605Smrg for (i = 0; i < num_threads; i++) { 136848b8605Smrg if (pq->end[i] > *result) { 137848b8605Smrg *result = pq->end[i]; 138848b8605Smrg } 139848b8605Smrg } 140848b8605Smrg break; 141848b8605Smrg case PIPE_QUERY_TIMESTAMP_DISJOINT: { 142848b8605Smrg struct pipe_query_data_timestamp_disjoint *td = 143848b8605Smrg (struct pipe_query_data_timestamp_disjoint *)vresult; 144848b8605Smrg /* os_get_time_nano return nanoseconds */ 145848b8605Smrg td->frequency = UINT64_C(1000000000); 146848b8605Smrg td->disjoint = FALSE; 147848b8605Smrg } 148848b8605Smrg break; 149848b8605Smrg case PIPE_QUERY_GPU_FINISHED: 150848b8605Smrg vresult->b = TRUE; 151848b8605Smrg break; 152848b8605Smrg case PIPE_QUERY_PRIMITIVES_GENERATED: 153848b8605Smrg *result = pq->num_primitives_generated; 154848b8605Smrg break; 155848b8605Smrg case PIPE_QUERY_PRIMITIVES_EMITTED: 156848b8605Smrg *result = pq->num_primitives_written; 157848b8605Smrg break; 158848b8605Smrg case PIPE_QUERY_SO_OVERFLOW_PREDICATE: 159b8e80941Smrg case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE: 160848b8605Smrg vresult->b = pq->num_primitives_generated > pq->num_primitives_written; 161848b8605Smrg break; 162848b8605Smrg case PIPE_QUERY_SO_STATISTICS: { 163848b8605Smrg struct pipe_query_data_so_statistics *stats = 164848b8605Smrg (struct pipe_query_data_so_statistics *)vresult; 165848b8605Smrg stats->num_primitives_written = pq->num_primitives_written; 166848b8605Smrg stats->primitives_storage_needed = pq->num_primitives_generated; 167848b8605Smrg } 168848b8605Smrg break; 169848b8605Smrg case PIPE_QUERY_PIPELINE_STATISTICS: { 170848b8605Smrg struct pipe_query_data_pipeline_statistics *stats = 171848b8605Smrg (struct pipe_query_data_pipeline_statistics *)vresult; 172848b8605Smrg /* only ps_invocations come from binned query */ 173848b8605Smrg for (i = 0; i < num_threads; i++) { 174848b8605Smrg pq->stats.ps_invocations += pq->end[i]; 175848b8605Smrg } 176848b8605Smrg pq->stats.ps_invocations *= LP_RASTER_BLOCK_SIZE * LP_RASTER_BLOCK_SIZE; 177848b8605Smrg *stats = pq->stats; 178848b8605Smrg } 179848b8605Smrg break; 180848b8605Smrg default: 181848b8605Smrg assert(0); 182848b8605Smrg break; 183848b8605Smrg } 184848b8605Smrg 185848b8605Smrg return TRUE; 186848b8605Smrg} 187848b8605Smrg 188848b8605Smrg 189b8e80941Smrgstatic boolean 190848b8605Smrgllvmpipe_begin_query(struct pipe_context *pipe, struct pipe_query *q) 191848b8605Smrg{ 192848b8605Smrg struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe ); 193848b8605Smrg struct llvmpipe_query *pq = llvmpipe_query(q); 194848b8605Smrg 195848b8605Smrg /* Check if the query is already in the scene. If so, we need to 196848b8605Smrg * flush the scene now. Real apps shouldn't re-use a query in a 197848b8605Smrg * frame of rendering. 198848b8605Smrg */ 199848b8605Smrg if (pq->fence && !lp_fence_issued(pq->fence)) { 200848b8605Smrg llvmpipe_finish(pipe, __FUNCTION__); 201848b8605Smrg } 202848b8605Smrg 203848b8605Smrg 204848b8605Smrg memset(pq->start, 0, sizeof(pq->start)); 205848b8605Smrg memset(pq->end, 0, sizeof(pq->end)); 206848b8605Smrg lp_setup_begin_query(llvmpipe->setup, pq); 207848b8605Smrg 208848b8605Smrg switch (pq->type) { 209848b8605Smrg case PIPE_QUERY_PRIMITIVES_EMITTED: 210848b8605Smrg pq->num_primitives_written = llvmpipe->so_stats.num_primitives_written; 211848b8605Smrg break; 212848b8605Smrg case PIPE_QUERY_PRIMITIVES_GENERATED: 213848b8605Smrg pq->num_primitives_generated = llvmpipe->so_stats.primitives_storage_needed; 214848b8605Smrg break; 215848b8605Smrg case PIPE_QUERY_SO_STATISTICS: 216848b8605Smrg pq->num_primitives_written = llvmpipe->so_stats.num_primitives_written; 217848b8605Smrg pq->num_primitives_generated = llvmpipe->so_stats.primitives_storage_needed; 218848b8605Smrg break; 219848b8605Smrg case PIPE_QUERY_SO_OVERFLOW_PREDICATE: 220b8e80941Smrg case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE: 221848b8605Smrg pq->num_primitives_written = llvmpipe->so_stats.num_primitives_written; 222848b8605Smrg pq->num_primitives_generated = llvmpipe->so_stats.primitives_storage_needed; 223848b8605Smrg break; 224848b8605Smrg case PIPE_QUERY_PIPELINE_STATISTICS: 225848b8605Smrg /* reset our cache */ 226848b8605Smrg if (llvmpipe->active_statistics_queries == 0) { 227848b8605Smrg memset(&llvmpipe->pipeline_statistics, 0, 228848b8605Smrg sizeof(llvmpipe->pipeline_statistics)); 229848b8605Smrg } 230848b8605Smrg memcpy(&pq->stats, &llvmpipe->pipeline_statistics, sizeof(pq->stats)); 231848b8605Smrg llvmpipe->active_statistics_queries++; 232848b8605Smrg break; 233848b8605Smrg case PIPE_QUERY_OCCLUSION_COUNTER: 234848b8605Smrg case PIPE_QUERY_OCCLUSION_PREDICATE: 235b8e80941Smrg case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE: 236848b8605Smrg llvmpipe->active_occlusion_queries++; 237848b8605Smrg llvmpipe->dirty |= LP_NEW_OCCLUSION_QUERY; 238848b8605Smrg break; 239848b8605Smrg default: 240848b8605Smrg break; 241848b8605Smrg } 242b8e80941Smrg return true; 243848b8605Smrg} 244848b8605Smrg 245848b8605Smrg 246b8e80941Smrgstatic bool 247848b8605Smrgllvmpipe_end_query(struct pipe_context *pipe, struct pipe_query *q) 248848b8605Smrg{ 249848b8605Smrg struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe ); 250848b8605Smrg struct llvmpipe_query *pq = llvmpipe_query(q); 251848b8605Smrg 252848b8605Smrg lp_setup_end_query(llvmpipe->setup, pq); 253848b8605Smrg 254848b8605Smrg switch (pq->type) { 255848b8605Smrg 256848b8605Smrg case PIPE_QUERY_PRIMITIVES_EMITTED: 257848b8605Smrg pq->num_primitives_written = 258848b8605Smrg llvmpipe->so_stats.num_primitives_written - pq->num_primitives_written; 259848b8605Smrg break; 260848b8605Smrg case PIPE_QUERY_PRIMITIVES_GENERATED: 261848b8605Smrg pq->num_primitives_generated = 262848b8605Smrg llvmpipe->so_stats.primitives_storage_needed - pq->num_primitives_generated; 263848b8605Smrg break; 264848b8605Smrg case PIPE_QUERY_SO_STATISTICS: 265848b8605Smrg pq->num_primitives_written = 266848b8605Smrg llvmpipe->so_stats.num_primitives_written - pq->num_primitives_written; 267848b8605Smrg pq->num_primitives_generated = 268848b8605Smrg llvmpipe->so_stats.primitives_storage_needed - pq->num_primitives_generated; 269848b8605Smrg break; 270848b8605Smrg case PIPE_QUERY_SO_OVERFLOW_PREDICATE: 271b8e80941Smrg case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE: 272848b8605Smrg pq->num_primitives_written = 273848b8605Smrg llvmpipe->so_stats.num_primitives_written - pq->num_primitives_written; 274848b8605Smrg pq->num_primitives_generated = 275848b8605Smrg llvmpipe->so_stats.primitives_storage_needed - pq->num_primitives_generated; 276848b8605Smrg break; 277848b8605Smrg case PIPE_QUERY_PIPELINE_STATISTICS: 278848b8605Smrg pq->stats.ia_vertices = 279848b8605Smrg llvmpipe->pipeline_statistics.ia_vertices - pq->stats.ia_vertices; 280848b8605Smrg pq->stats.ia_primitives = 281848b8605Smrg llvmpipe->pipeline_statistics.ia_primitives - pq->stats.ia_primitives; 282848b8605Smrg pq->stats.vs_invocations = 283848b8605Smrg llvmpipe->pipeline_statistics.vs_invocations - pq->stats.vs_invocations; 284848b8605Smrg pq->stats.gs_invocations = 285848b8605Smrg llvmpipe->pipeline_statistics.gs_invocations - pq->stats.gs_invocations; 286848b8605Smrg pq->stats.gs_primitives = 287848b8605Smrg llvmpipe->pipeline_statistics.gs_primitives - pq->stats.gs_primitives; 288848b8605Smrg pq->stats.c_invocations = 289848b8605Smrg llvmpipe->pipeline_statistics.c_invocations - pq->stats.c_invocations; 290848b8605Smrg pq->stats.c_primitives = 291848b8605Smrg llvmpipe->pipeline_statistics.c_primitives - pq->stats.c_primitives; 292848b8605Smrg pq->stats.ps_invocations = 293848b8605Smrg llvmpipe->pipeline_statistics.ps_invocations - pq->stats.ps_invocations; 294848b8605Smrg 295848b8605Smrg llvmpipe->active_statistics_queries--; 296848b8605Smrg break; 297848b8605Smrg case PIPE_QUERY_OCCLUSION_COUNTER: 298848b8605Smrg case PIPE_QUERY_OCCLUSION_PREDICATE: 299b8e80941Smrg case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE: 300848b8605Smrg assert(llvmpipe->active_occlusion_queries); 301848b8605Smrg llvmpipe->active_occlusion_queries--; 302848b8605Smrg llvmpipe->dirty |= LP_NEW_OCCLUSION_QUERY; 303848b8605Smrg break; 304848b8605Smrg default: 305848b8605Smrg break; 306848b8605Smrg } 307b8e80941Smrg 308b8e80941Smrg return true; 309848b8605Smrg} 310848b8605Smrg 311848b8605Smrgboolean 312848b8605Smrgllvmpipe_check_render_cond(struct llvmpipe_context *lp) 313848b8605Smrg{ 314848b8605Smrg struct pipe_context *pipe = &lp->pipe; 315848b8605Smrg boolean b, wait; 316848b8605Smrg uint64_t result; 317848b8605Smrg 318848b8605Smrg if (!lp->render_cond_query) 319848b8605Smrg return TRUE; /* no query predicate, draw normally */ 320848b8605Smrg 321848b8605Smrg wait = (lp->render_cond_mode == PIPE_RENDER_COND_WAIT || 322848b8605Smrg lp->render_cond_mode == PIPE_RENDER_COND_BY_REGION_WAIT); 323848b8605Smrg 324848b8605Smrg b = pipe->get_query_result(pipe, lp->render_cond_query, wait, (void*)&result); 325848b8605Smrg if (b) 326b8e80941Smrg return ((!result) == lp->render_cond_cond); 327848b8605Smrg else 328848b8605Smrg return TRUE; 329848b8605Smrg} 330848b8605Smrg 331b8e80941Smrgstatic void 332b8e80941Smrgllvmpipe_set_active_query_state(struct pipe_context *pipe, boolean enable) 333b8e80941Smrg{ 334b8e80941Smrg} 335b8e80941Smrg 336848b8605Smrgvoid llvmpipe_init_query_funcs(struct llvmpipe_context *llvmpipe ) 337848b8605Smrg{ 338848b8605Smrg llvmpipe->pipe.create_query = llvmpipe_create_query; 339848b8605Smrg llvmpipe->pipe.destroy_query = llvmpipe_destroy_query; 340848b8605Smrg llvmpipe->pipe.begin_query = llvmpipe_begin_query; 341848b8605Smrg llvmpipe->pipe.end_query = llvmpipe_end_query; 342848b8605Smrg llvmpipe->pipe.get_query_result = llvmpipe_get_query_result; 343b8e80941Smrg llvmpipe->pipe.set_active_query_state = llvmpipe_set_active_query_state; 344848b8605Smrg} 345848b8605Smrg 346848b8605Smrg 347