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