1bf215546Sopenharmony_ci/************************************************************************** 2bf215546Sopenharmony_ci * 3bf215546Sopenharmony_ci * Copyright 2007 VMware, Inc. 4bf215546Sopenharmony_ci * Copyright 2010 VMware, Inc. 5bf215546Sopenharmony_ci * All Rights Reserved. 6bf215546Sopenharmony_ci * 7bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 8bf215546Sopenharmony_ci * copy of this software and associated documentation files (the 9bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including 10bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 11bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to 12bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 13bf215546Sopenharmony_ci * the following conditions: 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the 16bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions 17bf215546Sopenharmony_ci * of the Software. 18bf215546Sopenharmony_ci * 19bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 22bf215546Sopenharmony_ci * IN NO EVENT SHALL THE AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR 23bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26bf215546Sopenharmony_ci * 27bf215546Sopenharmony_ci **************************************************************************/ 28bf215546Sopenharmony_ci 29bf215546Sopenharmony_ci/* Authors: 30bf215546Sopenharmony_ci * Keith Whitwell, Qicheng Christopher Li, Brian Paul 31bf215546Sopenharmony_ci */ 32bf215546Sopenharmony_ci 33bf215546Sopenharmony_ci#include "draw/draw_context.h" 34bf215546Sopenharmony_ci#include "pipe/p_defines.h" 35bf215546Sopenharmony_ci#include "util/u_memory.h" 36bf215546Sopenharmony_ci#include "util/os_time.h" 37bf215546Sopenharmony_ci#include "lp_context.h" 38bf215546Sopenharmony_ci#include "lp_flush.h" 39bf215546Sopenharmony_ci#include "lp_fence.h" 40bf215546Sopenharmony_ci#include "lp_query.h" 41bf215546Sopenharmony_ci#include "lp_screen.h" 42bf215546Sopenharmony_ci#include "lp_state.h" 43bf215546Sopenharmony_ci#include "lp_rast.h" 44bf215546Sopenharmony_ci 45bf215546Sopenharmony_ci 46bf215546Sopenharmony_cistatic struct llvmpipe_query *llvmpipe_query( struct pipe_query *p ) 47bf215546Sopenharmony_ci{ 48bf215546Sopenharmony_ci return (struct llvmpipe_query *)p; 49bf215546Sopenharmony_ci} 50bf215546Sopenharmony_ci 51bf215546Sopenharmony_cistatic struct pipe_query * 52bf215546Sopenharmony_cillvmpipe_create_query(struct pipe_context *pipe, 53bf215546Sopenharmony_ci unsigned type, 54bf215546Sopenharmony_ci unsigned index) 55bf215546Sopenharmony_ci{ 56bf215546Sopenharmony_ci struct llvmpipe_query *pq; 57bf215546Sopenharmony_ci 58bf215546Sopenharmony_ci assert(type < PIPE_QUERY_TYPES); 59bf215546Sopenharmony_ci 60bf215546Sopenharmony_ci pq = CALLOC_STRUCT( llvmpipe_query ); 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_ci if (pq) { 63bf215546Sopenharmony_ci pq->type = type; 64bf215546Sopenharmony_ci pq->index = index; 65bf215546Sopenharmony_ci } 66bf215546Sopenharmony_ci 67bf215546Sopenharmony_ci return (struct pipe_query *) pq; 68bf215546Sopenharmony_ci} 69bf215546Sopenharmony_ci 70bf215546Sopenharmony_ci 71bf215546Sopenharmony_cistatic void 72bf215546Sopenharmony_cillvmpipe_destroy_query(struct pipe_context *pipe, struct pipe_query *q) 73bf215546Sopenharmony_ci{ 74bf215546Sopenharmony_ci struct llvmpipe_query *pq = llvmpipe_query(q); 75bf215546Sopenharmony_ci 76bf215546Sopenharmony_ci /* Ideally we would refcount queries & not get destroyed until the 77bf215546Sopenharmony_ci * last scene had finished with us. 78bf215546Sopenharmony_ci */ 79bf215546Sopenharmony_ci if (pq->fence) { 80bf215546Sopenharmony_ci if (!lp_fence_issued(pq->fence)) 81bf215546Sopenharmony_ci llvmpipe_flush(pipe, NULL, __FUNCTION__); 82bf215546Sopenharmony_ci 83bf215546Sopenharmony_ci if (!lp_fence_signalled(pq->fence)) 84bf215546Sopenharmony_ci lp_fence_wait(pq->fence); 85bf215546Sopenharmony_ci 86bf215546Sopenharmony_ci lp_fence_reference(&pq->fence, NULL); 87bf215546Sopenharmony_ci } 88bf215546Sopenharmony_ci 89bf215546Sopenharmony_ci FREE(pq); 90bf215546Sopenharmony_ci} 91bf215546Sopenharmony_ci 92bf215546Sopenharmony_ci 93bf215546Sopenharmony_cistatic bool 94bf215546Sopenharmony_cillvmpipe_get_query_result(struct pipe_context *pipe, 95bf215546Sopenharmony_ci struct pipe_query *q, 96bf215546Sopenharmony_ci bool wait, 97bf215546Sopenharmony_ci union pipe_query_result *vresult) 98bf215546Sopenharmony_ci{ 99bf215546Sopenharmony_ci struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen); 100bf215546Sopenharmony_ci unsigned num_threads = MAX2(1, screen->num_threads); 101bf215546Sopenharmony_ci struct llvmpipe_query *pq = llvmpipe_query(q); 102bf215546Sopenharmony_ci uint64_t *result = (uint64_t *)vresult; 103bf215546Sopenharmony_ci int i; 104bf215546Sopenharmony_ci 105bf215546Sopenharmony_ci if (pq->fence) { 106bf215546Sopenharmony_ci /* only have a fence if there was a scene */ 107bf215546Sopenharmony_ci if (!lp_fence_signalled(pq->fence)) { 108bf215546Sopenharmony_ci if (!lp_fence_issued(pq->fence)) 109bf215546Sopenharmony_ci llvmpipe_flush(pipe, NULL, __FUNCTION__); 110bf215546Sopenharmony_ci 111bf215546Sopenharmony_ci if (!wait) 112bf215546Sopenharmony_ci return false; 113bf215546Sopenharmony_ci 114bf215546Sopenharmony_ci lp_fence_wait(pq->fence); 115bf215546Sopenharmony_ci } 116bf215546Sopenharmony_ci } 117bf215546Sopenharmony_ci 118bf215546Sopenharmony_ci /* Sum the results from each of the threads: 119bf215546Sopenharmony_ci */ 120bf215546Sopenharmony_ci *result = 0; 121bf215546Sopenharmony_ci 122bf215546Sopenharmony_ci switch (pq->type) { 123bf215546Sopenharmony_ci case PIPE_QUERY_OCCLUSION_COUNTER: 124bf215546Sopenharmony_ci for (i = 0; i < num_threads; i++) { 125bf215546Sopenharmony_ci *result += pq->end[i]; 126bf215546Sopenharmony_ci } 127bf215546Sopenharmony_ci break; 128bf215546Sopenharmony_ci case PIPE_QUERY_OCCLUSION_PREDICATE: 129bf215546Sopenharmony_ci case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE: 130bf215546Sopenharmony_ci for (i = 0; i < num_threads; i++) { 131bf215546Sopenharmony_ci /* safer (still not guaranteed) when there's an overflow */ 132bf215546Sopenharmony_ci vresult->b = vresult->b || pq->end[i]; 133bf215546Sopenharmony_ci } 134bf215546Sopenharmony_ci break; 135bf215546Sopenharmony_ci case PIPE_QUERY_TIMESTAMP: 136bf215546Sopenharmony_ci for (i = 0; i < num_threads; i++) { 137bf215546Sopenharmony_ci if (pq->end[i] > *result) { 138bf215546Sopenharmony_ci *result = pq->end[i]; 139bf215546Sopenharmony_ci } 140bf215546Sopenharmony_ci } 141bf215546Sopenharmony_ci break; 142bf215546Sopenharmony_ci case PIPE_QUERY_TIME_ELAPSED: { 143bf215546Sopenharmony_ci uint64_t start = (uint64_t)-1, end = 0; 144bf215546Sopenharmony_ci for (i = 0; i < num_threads; i++) { 145bf215546Sopenharmony_ci if (pq->start[i] && pq->start[i] < start) 146bf215546Sopenharmony_ci start = pq->start[i]; 147bf215546Sopenharmony_ci if (pq->end[i] && pq->end[i] > end) 148bf215546Sopenharmony_ci end = pq->end[i]; 149bf215546Sopenharmony_ci } 150bf215546Sopenharmony_ci *result = end - start; 151bf215546Sopenharmony_ci break; 152bf215546Sopenharmony_ci } 153bf215546Sopenharmony_ci case PIPE_QUERY_TIMESTAMP_DISJOINT: { 154bf215546Sopenharmony_ci struct pipe_query_data_timestamp_disjoint *td = 155bf215546Sopenharmony_ci (struct pipe_query_data_timestamp_disjoint *)vresult; 156bf215546Sopenharmony_ci /* os_get_time_nano return nanoseconds */ 157bf215546Sopenharmony_ci td->frequency = UINT64_C(1000000000); 158bf215546Sopenharmony_ci td->disjoint = false; 159bf215546Sopenharmony_ci } 160bf215546Sopenharmony_ci break; 161bf215546Sopenharmony_ci case PIPE_QUERY_GPU_FINISHED: 162bf215546Sopenharmony_ci vresult->b = true; 163bf215546Sopenharmony_ci break; 164bf215546Sopenharmony_ci case PIPE_QUERY_PRIMITIVES_GENERATED: 165bf215546Sopenharmony_ci *result = pq->num_primitives_generated[0]; 166bf215546Sopenharmony_ci break; 167bf215546Sopenharmony_ci case PIPE_QUERY_PRIMITIVES_EMITTED: 168bf215546Sopenharmony_ci *result = pq->num_primitives_written[0]; 169bf215546Sopenharmony_ci break; 170bf215546Sopenharmony_ci case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE: 171bf215546Sopenharmony_ci vresult->b = false; 172bf215546Sopenharmony_ci for (unsigned s = 0; s < PIPE_MAX_VERTEX_STREAMS; s++) 173bf215546Sopenharmony_ci vresult->b |= pq->num_primitives_generated[s] > pq->num_primitives_written[s]; 174bf215546Sopenharmony_ci break; 175bf215546Sopenharmony_ci case PIPE_QUERY_SO_OVERFLOW_PREDICATE: 176bf215546Sopenharmony_ci vresult->b = pq->num_primitives_generated[0] > pq->num_primitives_written[0]; 177bf215546Sopenharmony_ci break; 178bf215546Sopenharmony_ci case PIPE_QUERY_SO_STATISTICS: { 179bf215546Sopenharmony_ci struct pipe_query_data_so_statistics *stats = 180bf215546Sopenharmony_ci (struct pipe_query_data_so_statistics *)vresult; 181bf215546Sopenharmony_ci stats->num_primitives_written = pq->num_primitives_written[0]; 182bf215546Sopenharmony_ci stats->primitives_storage_needed = pq->num_primitives_generated[0]; 183bf215546Sopenharmony_ci } 184bf215546Sopenharmony_ci break; 185bf215546Sopenharmony_ci case PIPE_QUERY_PIPELINE_STATISTICS: { 186bf215546Sopenharmony_ci struct pipe_query_data_pipeline_statistics *stats = 187bf215546Sopenharmony_ci (struct pipe_query_data_pipeline_statistics *)vresult; 188bf215546Sopenharmony_ci /* only ps_invocations come from binned query */ 189bf215546Sopenharmony_ci for (i = 0; i < num_threads; i++) { 190bf215546Sopenharmony_ci pq->stats.ps_invocations += pq->end[i]; 191bf215546Sopenharmony_ci } 192bf215546Sopenharmony_ci pq->stats.ps_invocations *= LP_RASTER_BLOCK_SIZE * LP_RASTER_BLOCK_SIZE; 193bf215546Sopenharmony_ci *stats = pq->stats; 194bf215546Sopenharmony_ci } 195bf215546Sopenharmony_ci break; 196bf215546Sopenharmony_ci default: 197bf215546Sopenharmony_ci assert(0); 198bf215546Sopenharmony_ci break; 199bf215546Sopenharmony_ci } 200bf215546Sopenharmony_ci 201bf215546Sopenharmony_ci return true; 202bf215546Sopenharmony_ci} 203bf215546Sopenharmony_ci 204bf215546Sopenharmony_cistatic void 205bf215546Sopenharmony_cillvmpipe_get_query_result_resource(struct pipe_context *pipe, 206bf215546Sopenharmony_ci struct pipe_query *q, 207bf215546Sopenharmony_ci enum pipe_query_flags flags, 208bf215546Sopenharmony_ci enum pipe_query_value_type result_type, 209bf215546Sopenharmony_ci int index, 210bf215546Sopenharmony_ci struct pipe_resource *resource, 211bf215546Sopenharmony_ci unsigned offset) 212bf215546Sopenharmony_ci{ 213bf215546Sopenharmony_ci struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen); 214bf215546Sopenharmony_ci unsigned num_threads = MAX2(1, screen->num_threads); 215bf215546Sopenharmony_ci struct llvmpipe_query *pq = llvmpipe_query(q); 216bf215546Sopenharmony_ci struct llvmpipe_resource *lpr = llvmpipe_resource(resource); 217bf215546Sopenharmony_ci bool unsignalled = false; 218bf215546Sopenharmony_ci if (pq->fence) { 219bf215546Sopenharmony_ci /* only have a fence if there was a scene */ 220bf215546Sopenharmony_ci if (!lp_fence_signalled(pq->fence)) { 221bf215546Sopenharmony_ci if (!lp_fence_issued(pq->fence)) 222bf215546Sopenharmony_ci llvmpipe_flush(pipe, NULL, __FUNCTION__); 223bf215546Sopenharmony_ci 224bf215546Sopenharmony_ci if (flags & PIPE_QUERY_WAIT) 225bf215546Sopenharmony_ci lp_fence_wait(pq->fence); 226bf215546Sopenharmony_ci } 227bf215546Sopenharmony_ci unsignalled = !lp_fence_signalled(pq->fence); 228bf215546Sopenharmony_ci } 229bf215546Sopenharmony_ci 230bf215546Sopenharmony_ci 231bf215546Sopenharmony_ci uint64_t value = 0, value2 = 0; 232bf215546Sopenharmony_ci unsigned num_values = 1; 233bf215546Sopenharmony_ci if (index == -1) 234bf215546Sopenharmony_ci if (unsignalled) 235bf215546Sopenharmony_ci value = 0; 236bf215546Sopenharmony_ci else 237bf215546Sopenharmony_ci value = 1; 238bf215546Sopenharmony_ci else { 239bf215546Sopenharmony_ci unsigned i; 240bf215546Sopenharmony_ci 241bf215546Sopenharmony_ci /* don't write a value if fence hasn't signalled, 242bf215546Sopenharmony_ci and partial isn't set . */ 243bf215546Sopenharmony_ci if (unsignalled && !(flags & PIPE_QUERY_PARTIAL)) 244bf215546Sopenharmony_ci return; 245bf215546Sopenharmony_ci switch (pq->type) { 246bf215546Sopenharmony_ci case PIPE_QUERY_OCCLUSION_COUNTER: 247bf215546Sopenharmony_ci for (i = 0; i < num_threads; i++) { 248bf215546Sopenharmony_ci value += pq->end[i]; 249bf215546Sopenharmony_ci } 250bf215546Sopenharmony_ci break; 251bf215546Sopenharmony_ci case PIPE_QUERY_OCCLUSION_PREDICATE: 252bf215546Sopenharmony_ci case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE: 253bf215546Sopenharmony_ci for (i = 0; i < num_threads; i++) { 254bf215546Sopenharmony_ci /* safer (still not guaranteed) when there's an overflow */ 255bf215546Sopenharmony_ci value = value || pq->end[i]; 256bf215546Sopenharmony_ci } 257bf215546Sopenharmony_ci break; 258bf215546Sopenharmony_ci case PIPE_QUERY_PRIMITIVES_GENERATED: 259bf215546Sopenharmony_ci value = pq->num_primitives_generated[0]; 260bf215546Sopenharmony_ci break; 261bf215546Sopenharmony_ci case PIPE_QUERY_PRIMITIVES_EMITTED: 262bf215546Sopenharmony_ci value = pq->num_primitives_written[0]; 263bf215546Sopenharmony_ci break; 264bf215546Sopenharmony_ci case PIPE_QUERY_TIMESTAMP: 265bf215546Sopenharmony_ci for (i = 0; i < num_threads; i++) { 266bf215546Sopenharmony_ci if (pq->end[i] > value) { 267bf215546Sopenharmony_ci value = pq->end[i]; 268bf215546Sopenharmony_ci } 269bf215546Sopenharmony_ci } 270bf215546Sopenharmony_ci break; 271bf215546Sopenharmony_ci case PIPE_QUERY_TIME_ELAPSED: { 272bf215546Sopenharmony_ci uint64_t start = (uint64_t)-1, end = 0; 273bf215546Sopenharmony_ci for (i = 0; i < num_threads; i++) { 274bf215546Sopenharmony_ci if (pq->start[i] && pq->start[i] < start) 275bf215546Sopenharmony_ci start = pq->start[i]; 276bf215546Sopenharmony_ci if (pq->end[i] && pq->end[i] > end) 277bf215546Sopenharmony_ci end = pq->end[i]; 278bf215546Sopenharmony_ci } 279bf215546Sopenharmony_ci value = end - start; 280bf215546Sopenharmony_ci break; 281bf215546Sopenharmony_ci } 282bf215546Sopenharmony_ci case PIPE_QUERY_SO_STATISTICS: 283bf215546Sopenharmony_ci value = pq->num_primitives_written[0]; 284bf215546Sopenharmony_ci value2 = pq->num_primitives_generated[0]; 285bf215546Sopenharmony_ci num_values = 2; 286bf215546Sopenharmony_ci break; 287bf215546Sopenharmony_ci case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE: 288bf215546Sopenharmony_ci value = 0; 289bf215546Sopenharmony_ci for (unsigned s = 0; s < PIPE_MAX_VERTEX_STREAMS; s++) 290bf215546Sopenharmony_ci value |= !!(pq->num_primitives_generated[s] > pq->num_primitives_written[s]); 291bf215546Sopenharmony_ci break; 292bf215546Sopenharmony_ci case PIPE_QUERY_SO_OVERFLOW_PREDICATE: 293bf215546Sopenharmony_ci value = !!(pq->num_primitives_generated[0] > pq->num_primitives_written[0]); 294bf215546Sopenharmony_ci break; 295bf215546Sopenharmony_ci case PIPE_QUERY_PIPELINE_STATISTICS: 296bf215546Sopenharmony_ci switch ((enum pipe_statistics_query_index)index) { 297bf215546Sopenharmony_ci case PIPE_STAT_QUERY_IA_VERTICES: 298bf215546Sopenharmony_ci value = pq->stats.ia_vertices; 299bf215546Sopenharmony_ci break; 300bf215546Sopenharmony_ci case PIPE_STAT_QUERY_IA_PRIMITIVES: 301bf215546Sopenharmony_ci value = pq->stats.ia_primitives; 302bf215546Sopenharmony_ci break; 303bf215546Sopenharmony_ci case PIPE_STAT_QUERY_VS_INVOCATIONS: 304bf215546Sopenharmony_ci value = pq->stats.vs_invocations; 305bf215546Sopenharmony_ci break; 306bf215546Sopenharmony_ci case PIPE_STAT_QUERY_GS_INVOCATIONS: 307bf215546Sopenharmony_ci value = pq->stats.gs_invocations; 308bf215546Sopenharmony_ci break; 309bf215546Sopenharmony_ci case PIPE_STAT_QUERY_GS_PRIMITIVES: 310bf215546Sopenharmony_ci value = pq->stats.gs_primitives; 311bf215546Sopenharmony_ci break; 312bf215546Sopenharmony_ci case PIPE_STAT_QUERY_C_INVOCATIONS: 313bf215546Sopenharmony_ci value = pq->stats.c_invocations; 314bf215546Sopenharmony_ci break; 315bf215546Sopenharmony_ci case PIPE_STAT_QUERY_C_PRIMITIVES: 316bf215546Sopenharmony_ci value = pq->stats.c_primitives; 317bf215546Sopenharmony_ci break; 318bf215546Sopenharmony_ci case PIPE_STAT_QUERY_PS_INVOCATIONS: 319bf215546Sopenharmony_ci value = 0; 320bf215546Sopenharmony_ci for (i = 0; i < num_threads; i++) { 321bf215546Sopenharmony_ci value += pq->end[i]; 322bf215546Sopenharmony_ci } 323bf215546Sopenharmony_ci value *= LP_RASTER_BLOCK_SIZE * LP_RASTER_BLOCK_SIZE; 324bf215546Sopenharmony_ci break; 325bf215546Sopenharmony_ci case PIPE_STAT_QUERY_HS_INVOCATIONS: 326bf215546Sopenharmony_ci value = pq->stats.hs_invocations; 327bf215546Sopenharmony_ci break; 328bf215546Sopenharmony_ci case PIPE_STAT_QUERY_DS_INVOCATIONS: 329bf215546Sopenharmony_ci value = pq->stats.ds_invocations; 330bf215546Sopenharmony_ci break; 331bf215546Sopenharmony_ci case PIPE_STAT_QUERY_CS_INVOCATIONS: 332bf215546Sopenharmony_ci value = pq->stats.cs_invocations; 333bf215546Sopenharmony_ci break; 334bf215546Sopenharmony_ci } 335bf215546Sopenharmony_ci break; 336bf215546Sopenharmony_ci default: 337bf215546Sopenharmony_ci fprintf(stderr, "Unknown query type %d\n", pq->type); 338bf215546Sopenharmony_ci break; 339bf215546Sopenharmony_ci } 340bf215546Sopenharmony_ci } 341bf215546Sopenharmony_ci 342bf215546Sopenharmony_ci void *dst = (uint8_t *)lpr->data + offset; 343bf215546Sopenharmony_ci 344bf215546Sopenharmony_ci for (unsigned i = 0; i < num_values; i++) { 345bf215546Sopenharmony_ci 346bf215546Sopenharmony_ci if (i == 1) { 347bf215546Sopenharmony_ci value = value2; 348bf215546Sopenharmony_ci dst = (char *)dst + ((result_type == PIPE_QUERY_TYPE_I64 || 349bf215546Sopenharmony_ci result_type == PIPE_QUERY_TYPE_U64) ? 8 : 4); 350bf215546Sopenharmony_ci } 351bf215546Sopenharmony_ci switch (result_type) { 352bf215546Sopenharmony_ci case PIPE_QUERY_TYPE_I32: { 353bf215546Sopenharmony_ci int32_t *iptr = (int32_t *)dst; 354bf215546Sopenharmony_ci if (value > 0x7fffffff) 355bf215546Sopenharmony_ci *iptr = 0x7fffffff; 356bf215546Sopenharmony_ci else 357bf215546Sopenharmony_ci *iptr = (int32_t)value; 358bf215546Sopenharmony_ci break; 359bf215546Sopenharmony_ci } 360bf215546Sopenharmony_ci case PIPE_QUERY_TYPE_U32: { 361bf215546Sopenharmony_ci uint32_t *uptr = (uint32_t *)dst; 362bf215546Sopenharmony_ci if (value > 0xffffffff) 363bf215546Sopenharmony_ci *uptr = 0xffffffff; 364bf215546Sopenharmony_ci else 365bf215546Sopenharmony_ci *uptr = (uint32_t)value; 366bf215546Sopenharmony_ci break; 367bf215546Sopenharmony_ci } 368bf215546Sopenharmony_ci case PIPE_QUERY_TYPE_I64: { 369bf215546Sopenharmony_ci int64_t *iptr = (int64_t *)dst; 370bf215546Sopenharmony_ci *iptr = (int64_t)value; 371bf215546Sopenharmony_ci break; 372bf215546Sopenharmony_ci } 373bf215546Sopenharmony_ci case PIPE_QUERY_TYPE_U64: { 374bf215546Sopenharmony_ci uint64_t *uptr = (uint64_t *)dst; 375bf215546Sopenharmony_ci *uptr = (uint64_t)value; 376bf215546Sopenharmony_ci break; 377bf215546Sopenharmony_ci } 378bf215546Sopenharmony_ci } 379bf215546Sopenharmony_ci } 380bf215546Sopenharmony_ci} 381bf215546Sopenharmony_ci 382bf215546Sopenharmony_cistatic bool 383bf215546Sopenharmony_cillvmpipe_begin_query(struct pipe_context *pipe, struct pipe_query *q) 384bf215546Sopenharmony_ci{ 385bf215546Sopenharmony_ci struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe ); 386bf215546Sopenharmony_ci struct llvmpipe_query *pq = llvmpipe_query(q); 387bf215546Sopenharmony_ci 388bf215546Sopenharmony_ci /* Check if the query is already in the scene. If so, we need to 389bf215546Sopenharmony_ci * flush the scene now. Real apps shouldn't re-use a query in a 390bf215546Sopenharmony_ci * frame of rendering. 391bf215546Sopenharmony_ci */ 392bf215546Sopenharmony_ci if (pq->fence && !lp_fence_issued(pq->fence)) { 393bf215546Sopenharmony_ci llvmpipe_finish(pipe, __FUNCTION__); 394bf215546Sopenharmony_ci } 395bf215546Sopenharmony_ci 396bf215546Sopenharmony_ci 397bf215546Sopenharmony_ci memset(pq->start, 0, sizeof(pq->start)); 398bf215546Sopenharmony_ci memset(pq->end, 0, sizeof(pq->end)); 399bf215546Sopenharmony_ci lp_setup_begin_query(llvmpipe->setup, pq); 400bf215546Sopenharmony_ci 401bf215546Sopenharmony_ci switch (pq->type) { 402bf215546Sopenharmony_ci case PIPE_QUERY_PRIMITIVES_EMITTED: 403bf215546Sopenharmony_ci pq->num_primitives_written[0] = llvmpipe->so_stats[pq->index].num_primitives_written; 404bf215546Sopenharmony_ci break; 405bf215546Sopenharmony_ci case PIPE_QUERY_PRIMITIVES_GENERATED: 406bf215546Sopenharmony_ci pq->num_primitives_generated[0] = llvmpipe->so_stats[pq->index].primitives_storage_needed; 407bf215546Sopenharmony_ci llvmpipe->active_primgen_queries++; 408bf215546Sopenharmony_ci break; 409bf215546Sopenharmony_ci case PIPE_QUERY_SO_STATISTICS: 410bf215546Sopenharmony_ci pq->num_primitives_written[0] = llvmpipe->so_stats[pq->index].num_primitives_written; 411bf215546Sopenharmony_ci pq->num_primitives_generated[0] = llvmpipe->so_stats[pq->index].primitives_storage_needed; 412bf215546Sopenharmony_ci break; 413bf215546Sopenharmony_ci case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE: 414bf215546Sopenharmony_ci for (unsigned s = 0; s < PIPE_MAX_VERTEX_STREAMS; s++) { 415bf215546Sopenharmony_ci pq->num_primitives_written[s] = llvmpipe->so_stats[s].num_primitives_written; 416bf215546Sopenharmony_ci pq->num_primitives_generated[s] = llvmpipe->so_stats[s].primitives_storage_needed; 417bf215546Sopenharmony_ci } 418bf215546Sopenharmony_ci break; 419bf215546Sopenharmony_ci case PIPE_QUERY_SO_OVERFLOW_PREDICATE: 420bf215546Sopenharmony_ci pq->num_primitives_written[0] = llvmpipe->so_stats[pq->index].num_primitives_written; 421bf215546Sopenharmony_ci pq->num_primitives_generated[0] = llvmpipe->so_stats[pq->index].primitives_storage_needed; 422bf215546Sopenharmony_ci break; 423bf215546Sopenharmony_ci case PIPE_QUERY_PIPELINE_STATISTICS: 424bf215546Sopenharmony_ci /* reset our cache */ 425bf215546Sopenharmony_ci if (llvmpipe->active_statistics_queries == 0) { 426bf215546Sopenharmony_ci memset(&llvmpipe->pipeline_statistics, 0, 427bf215546Sopenharmony_ci sizeof(llvmpipe->pipeline_statistics)); 428bf215546Sopenharmony_ci } 429bf215546Sopenharmony_ci memcpy(&pq->stats, &llvmpipe->pipeline_statistics, sizeof(pq->stats)); 430bf215546Sopenharmony_ci llvmpipe->active_statistics_queries++; 431bf215546Sopenharmony_ci break; 432bf215546Sopenharmony_ci case PIPE_QUERY_OCCLUSION_COUNTER: 433bf215546Sopenharmony_ci case PIPE_QUERY_OCCLUSION_PREDICATE: 434bf215546Sopenharmony_ci case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE: 435bf215546Sopenharmony_ci llvmpipe->active_occlusion_queries++; 436bf215546Sopenharmony_ci llvmpipe->dirty |= LP_NEW_OCCLUSION_QUERY; 437bf215546Sopenharmony_ci break; 438bf215546Sopenharmony_ci default: 439bf215546Sopenharmony_ci break; 440bf215546Sopenharmony_ci } 441bf215546Sopenharmony_ci return true; 442bf215546Sopenharmony_ci} 443bf215546Sopenharmony_ci 444bf215546Sopenharmony_ci 445bf215546Sopenharmony_cistatic bool 446bf215546Sopenharmony_cillvmpipe_end_query(struct pipe_context *pipe, struct pipe_query *q) 447bf215546Sopenharmony_ci{ 448bf215546Sopenharmony_ci struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe ); 449bf215546Sopenharmony_ci struct llvmpipe_query *pq = llvmpipe_query(q); 450bf215546Sopenharmony_ci 451bf215546Sopenharmony_ci lp_setup_end_query(llvmpipe->setup, pq); 452bf215546Sopenharmony_ci 453bf215546Sopenharmony_ci switch (pq->type) { 454bf215546Sopenharmony_ci 455bf215546Sopenharmony_ci case PIPE_QUERY_PRIMITIVES_EMITTED: 456bf215546Sopenharmony_ci pq->num_primitives_written[0] = 457bf215546Sopenharmony_ci llvmpipe->so_stats[pq->index].num_primitives_written - pq->num_primitives_written[0]; 458bf215546Sopenharmony_ci break; 459bf215546Sopenharmony_ci case PIPE_QUERY_PRIMITIVES_GENERATED: 460bf215546Sopenharmony_ci assert(llvmpipe->active_primgen_queries); 461bf215546Sopenharmony_ci llvmpipe->active_primgen_queries--; 462bf215546Sopenharmony_ci pq->num_primitives_generated[0] = 463bf215546Sopenharmony_ci llvmpipe->so_stats[pq->index].primitives_storage_needed - pq->num_primitives_generated[0]; 464bf215546Sopenharmony_ci break; 465bf215546Sopenharmony_ci case PIPE_QUERY_SO_STATISTICS: 466bf215546Sopenharmony_ci pq->num_primitives_written[0] = 467bf215546Sopenharmony_ci llvmpipe->so_stats[pq->index].num_primitives_written - pq->num_primitives_written[0]; 468bf215546Sopenharmony_ci pq->num_primitives_generated[0] = 469bf215546Sopenharmony_ci llvmpipe->so_stats[pq->index].primitives_storage_needed - pq->num_primitives_generated[0]; 470bf215546Sopenharmony_ci break; 471bf215546Sopenharmony_ci case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE: 472bf215546Sopenharmony_ci for (unsigned s = 0; s < PIPE_MAX_VERTEX_STREAMS; s++) { 473bf215546Sopenharmony_ci pq->num_primitives_written[s] = 474bf215546Sopenharmony_ci llvmpipe->so_stats[s].num_primitives_written - pq->num_primitives_written[s]; 475bf215546Sopenharmony_ci pq->num_primitives_generated[s] = 476bf215546Sopenharmony_ci llvmpipe->so_stats[s].primitives_storage_needed - pq->num_primitives_generated[s]; 477bf215546Sopenharmony_ci } 478bf215546Sopenharmony_ci break; 479bf215546Sopenharmony_ci case PIPE_QUERY_SO_OVERFLOW_PREDICATE: 480bf215546Sopenharmony_ci pq->num_primitives_written[0] = 481bf215546Sopenharmony_ci llvmpipe->so_stats[pq->index].num_primitives_written - pq->num_primitives_written[0]; 482bf215546Sopenharmony_ci pq->num_primitives_generated[0] = 483bf215546Sopenharmony_ci llvmpipe->so_stats[pq->index].primitives_storage_needed - pq->num_primitives_generated[0]; 484bf215546Sopenharmony_ci break; 485bf215546Sopenharmony_ci case PIPE_QUERY_PIPELINE_STATISTICS: 486bf215546Sopenharmony_ci pq->stats.ia_vertices = 487bf215546Sopenharmony_ci llvmpipe->pipeline_statistics.ia_vertices - pq->stats.ia_vertices; 488bf215546Sopenharmony_ci pq->stats.ia_primitives = 489bf215546Sopenharmony_ci llvmpipe->pipeline_statistics.ia_primitives - pq->stats.ia_primitives; 490bf215546Sopenharmony_ci pq->stats.vs_invocations = 491bf215546Sopenharmony_ci llvmpipe->pipeline_statistics.vs_invocations - pq->stats.vs_invocations; 492bf215546Sopenharmony_ci pq->stats.gs_invocations = 493bf215546Sopenharmony_ci llvmpipe->pipeline_statistics.gs_invocations - pq->stats.gs_invocations; 494bf215546Sopenharmony_ci pq->stats.gs_primitives = 495bf215546Sopenharmony_ci llvmpipe->pipeline_statistics.gs_primitives - pq->stats.gs_primitives; 496bf215546Sopenharmony_ci pq->stats.c_invocations = 497bf215546Sopenharmony_ci llvmpipe->pipeline_statistics.c_invocations - pq->stats.c_invocations; 498bf215546Sopenharmony_ci pq->stats.c_primitives = 499bf215546Sopenharmony_ci llvmpipe->pipeline_statistics.c_primitives - pq->stats.c_primitives; 500bf215546Sopenharmony_ci pq->stats.ps_invocations = 501bf215546Sopenharmony_ci llvmpipe->pipeline_statistics.ps_invocations - pq->stats.ps_invocations; 502bf215546Sopenharmony_ci pq->stats.cs_invocations = 503bf215546Sopenharmony_ci llvmpipe->pipeline_statistics.cs_invocations - pq->stats.cs_invocations; 504bf215546Sopenharmony_ci pq->stats.hs_invocations = 505bf215546Sopenharmony_ci llvmpipe->pipeline_statistics.hs_invocations - pq->stats.hs_invocations; 506bf215546Sopenharmony_ci pq->stats.ds_invocations = 507bf215546Sopenharmony_ci llvmpipe->pipeline_statistics.ds_invocations - pq->stats.ds_invocations; 508bf215546Sopenharmony_ci llvmpipe->active_statistics_queries--; 509bf215546Sopenharmony_ci break; 510bf215546Sopenharmony_ci case PIPE_QUERY_OCCLUSION_COUNTER: 511bf215546Sopenharmony_ci case PIPE_QUERY_OCCLUSION_PREDICATE: 512bf215546Sopenharmony_ci case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE: 513bf215546Sopenharmony_ci assert(llvmpipe->active_occlusion_queries); 514bf215546Sopenharmony_ci llvmpipe->active_occlusion_queries--; 515bf215546Sopenharmony_ci llvmpipe->dirty |= LP_NEW_OCCLUSION_QUERY; 516bf215546Sopenharmony_ci break; 517bf215546Sopenharmony_ci default: 518bf215546Sopenharmony_ci break; 519bf215546Sopenharmony_ci } 520bf215546Sopenharmony_ci 521bf215546Sopenharmony_ci return true; 522bf215546Sopenharmony_ci} 523bf215546Sopenharmony_ci 524bf215546Sopenharmony_ciboolean 525bf215546Sopenharmony_cillvmpipe_check_render_cond(struct llvmpipe_context *lp) 526bf215546Sopenharmony_ci{ 527bf215546Sopenharmony_ci struct pipe_context *pipe = &lp->pipe; 528bf215546Sopenharmony_ci boolean b, wait; 529bf215546Sopenharmony_ci uint64_t result; 530bf215546Sopenharmony_ci 531bf215546Sopenharmony_ci if (lp->render_cond_buffer) { 532bf215546Sopenharmony_ci uint32_t data = *(uint32_t *)((char *)lp->render_cond_buffer->data + lp->render_cond_offset); 533bf215546Sopenharmony_ci return (!data) == lp->render_cond_cond; 534bf215546Sopenharmony_ci } 535bf215546Sopenharmony_ci if (!lp->render_cond_query) 536bf215546Sopenharmony_ci return TRUE; /* no query predicate, draw normally */ 537bf215546Sopenharmony_ci 538bf215546Sopenharmony_ci wait = (lp->render_cond_mode == PIPE_RENDER_COND_WAIT || 539bf215546Sopenharmony_ci lp->render_cond_mode == PIPE_RENDER_COND_BY_REGION_WAIT); 540bf215546Sopenharmony_ci 541bf215546Sopenharmony_ci b = pipe->get_query_result(pipe, lp->render_cond_query, wait, (void*)&result); 542bf215546Sopenharmony_ci if (b) 543bf215546Sopenharmony_ci return ((!result) == lp->render_cond_cond); 544bf215546Sopenharmony_ci else 545bf215546Sopenharmony_ci return TRUE; 546bf215546Sopenharmony_ci} 547bf215546Sopenharmony_ci 548bf215546Sopenharmony_cistatic void 549bf215546Sopenharmony_cillvmpipe_set_active_query_state(struct pipe_context *pipe, bool enable) 550bf215546Sopenharmony_ci{ 551bf215546Sopenharmony_ci struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); 552bf215546Sopenharmony_ci 553bf215546Sopenharmony_ci llvmpipe->queries_disabled = !enable; 554bf215546Sopenharmony_ci /* for OQs we need to regenerate the fragment shader */ 555bf215546Sopenharmony_ci llvmpipe->dirty |= LP_NEW_OCCLUSION_QUERY; 556bf215546Sopenharmony_ci} 557bf215546Sopenharmony_ci 558bf215546Sopenharmony_civoid llvmpipe_init_query_funcs(struct llvmpipe_context *llvmpipe ) 559bf215546Sopenharmony_ci{ 560bf215546Sopenharmony_ci llvmpipe->pipe.create_query = llvmpipe_create_query; 561bf215546Sopenharmony_ci llvmpipe->pipe.destroy_query = llvmpipe_destroy_query; 562bf215546Sopenharmony_ci llvmpipe->pipe.begin_query = llvmpipe_begin_query; 563bf215546Sopenharmony_ci llvmpipe->pipe.end_query = llvmpipe_end_query; 564bf215546Sopenharmony_ci llvmpipe->pipe.get_query_result = llvmpipe_get_query_result; 565bf215546Sopenharmony_ci llvmpipe->pipe.get_query_result_resource = llvmpipe_get_query_result_resource; 566bf215546Sopenharmony_ci llvmpipe->pipe.set_active_query_state = llvmpipe_set_active_query_state; 567bf215546Sopenharmony_ci} 568bf215546Sopenharmony_ci 569bf215546Sopenharmony_ci 570