Home | History | Annotate | Download | only in softpipe
      1 /**************************************************************************
      2  *
      3  * Copyright 2007 VMware, Inc.
      4  * All Rights Reserved.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the
      8  * "Software"), to deal in the Software without restriction, including
      9  * without limitation the rights to use, copy, modify, merge, publish,
     10  * distribute, sub license, and/or sell copies of the Software, and to
     11  * permit persons to whom the Software is furnished to do so, subject to
     12  * the following conditions:
     13  *
     14  * The above copyright notice and this permission notice (including the
     15  * next paragraph) shall be included in all copies or substantial portions
     16  * of the Software.
     17  *
     18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
     21  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
     22  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     25  *
     26  **************************************************************************/
     27 
     28 /* Author:
     29  *    Keith Whitwell <keithw (at) vmware.com>
     30  */
     31 
     32 #include "draw/draw_context.h"
     33 #include "os/os_time.h"
     34 #include "pipe/p_defines.h"
     35 #include "util/u_memory.h"
     36 #include "sp_context.h"
     37 #include "sp_query.h"
     38 #include "sp_state.h"
     39 
     40 struct softpipe_query {
     41    unsigned type;
     42    uint64_t start;
     43    uint64_t end;
     44    struct pipe_query_data_so_statistics so;
     45    struct pipe_query_data_pipeline_statistics stats;
     46 };
     47 
     48 
     49 static struct softpipe_query *softpipe_query( struct pipe_query *p )
     50 {
     51    return (struct softpipe_query *)p;
     52 }
     53 
     54 static struct pipe_query *
     55 softpipe_create_query(struct pipe_context *pipe,
     56 		      unsigned type,
     57 		      unsigned index)
     58 {
     59    struct softpipe_query* sq;
     60 
     61    assert(type == PIPE_QUERY_OCCLUSION_COUNTER ||
     62           type == PIPE_QUERY_OCCLUSION_PREDICATE ||
     63           type == PIPE_QUERY_TIME_ELAPSED ||
     64           type == PIPE_QUERY_SO_STATISTICS ||
     65           type == PIPE_QUERY_SO_OVERFLOW_PREDICATE ||
     66           type == PIPE_QUERY_PRIMITIVES_EMITTED ||
     67           type == PIPE_QUERY_PRIMITIVES_GENERATED ||
     68           type == PIPE_QUERY_PIPELINE_STATISTICS ||
     69           type == PIPE_QUERY_GPU_FINISHED ||
     70           type == PIPE_QUERY_TIMESTAMP ||
     71           type == PIPE_QUERY_TIMESTAMP_DISJOINT);
     72    sq = CALLOC_STRUCT( softpipe_query );
     73    sq->type = type;
     74 
     75    return (struct pipe_query *)sq;
     76 }
     77 
     78 
     79 static void
     80 softpipe_destroy_query(struct pipe_context *pipe, struct pipe_query *q)
     81 {
     82    FREE(q);
     83 }
     84 
     85 
     86 static boolean
     87 softpipe_begin_query(struct pipe_context *pipe, struct pipe_query *q)
     88 {
     89    struct softpipe_context *softpipe = softpipe_context( pipe );
     90    struct softpipe_query *sq = softpipe_query(q);
     91 
     92    switch (sq->type) {
     93    case PIPE_QUERY_OCCLUSION_COUNTER:
     94    case PIPE_QUERY_OCCLUSION_PREDICATE:
     95       sq->start = softpipe->occlusion_count;
     96       break;
     97    case PIPE_QUERY_TIME_ELAPSED:
     98       sq->start = os_time_get_nano();
     99       break;
    100    case PIPE_QUERY_SO_STATISTICS:
    101       sq->so.num_primitives_written = softpipe->so_stats.num_primitives_written;
    102       sq->so.primitives_storage_needed = softpipe->so_stats.primitives_storage_needed;
    103       break;
    104    case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
    105       sq->end = FALSE;
    106       break;
    107    case PIPE_QUERY_PRIMITIVES_EMITTED:
    108       sq->so.num_primitives_written = softpipe->so_stats.num_primitives_written;
    109       break;
    110    case PIPE_QUERY_PRIMITIVES_GENERATED:
    111       sq->so.primitives_storage_needed = softpipe->so_stats.primitives_storage_needed;
    112       break;
    113    case PIPE_QUERY_TIMESTAMP:
    114    case PIPE_QUERY_GPU_FINISHED:
    115    case PIPE_QUERY_TIMESTAMP_DISJOINT:
    116       break;
    117    case PIPE_QUERY_PIPELINE_STATISTICS:
    118       /* reset our cache */
    119       if (softpipe->active_statistics_queries == 0) {
    120          memset(&softpipe->pipeline_statistics, 0,
    121                 sizeof(softpipe->pipeline_statistics));
    122       }
    123       memcpy(&sq->stats, &softpipe->pipeline_statistics,
    124              sizeof(sq->stats));
    125       softpipe->active_statistics_queries++;
    126       break;
    127    default:
    128       assert(0);
    129       break;
    130    }
    131    softpipe->active_query_count++;
    132    softpipe->dirty |= SP_NEW_QUERY;
    133    return true;
    134 }
    135 
    136 
    137 static bool
    138 softpipe_end_query(struct pipe_context *pipe, struct pipe_query *q)
    139 {
    140    struct softpipe_context *softpipe = softpipe_context( pipe );
    141    struct softpipe_query *sq = softpipe_query(q);
    142 
    143    softpipe->active_query_count--;
    144    switch (sq->type) {
    145    case PIPE_QUERY_OCCLUSION_COUNTER:
    146    case PIPE_QUERY_OCCLUSION_PREDICATE:
    147       sq->end = softpipe->occlusion_count;
    148       break;
    149    case PIPE_QUERY_TIMESTAMP:
    150       sq->start = 0;
    151       /* fall through */
    152    case PIPE_QUERY_TIME_ELAPSED:
    153       sq->end = os_time_get_nano();
    154       break;
    155    case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
    156       sq->so.num_primitives_written =
    157          softpipe->so_stats.num_primitives_written - sq->so.num_primitives_written;
    158       sq->so.primitives_storage_needed =
    159          softpipe->so_stats.primitives_storage_needed - sq->so.primitives_storage_needed;
    160       sq->end = sq->so.primitives_storage_needed > sq->so.num_primitives_written;
    161       break;
    162    case PIPE_QUERY_SO_STATISTICS:
    163       sq->so.num_primitives_written =
    164          softpipe->so_stats.num_primitives_written - sq->so.num_primitives_written;
    165       sq->so.primitives_storage_needed =
    166          softpipe->so_stats.primitives_storage_needed - sq->so.primitives_storage_needed;
    167       break;
    168    case PIPE_QUERY_PRIMITIVES_EMITTED:
    169       sq->so.num_primitives_written =
    170          softpipe->so_stats.num_primitives_written - sq->so.num_primitives_written;
    171       break;
    172    case PIPE_QUERY_PRIMITIVES_GENERATED:
    173       sq->so.primitives_storage_needed =
    174          softpipe->so_stats.primitives_storage_needed - sq->so.primitives_storage_needed;
    175       break;
    176    case PIPE_QUERY_GPU_FINISHED:
    177    case PIPE_QUERY_TIMESTAMP_DISJOINT:
    178       break;
    179    case PIPE_QUERY_PIPELINE_STATISTICS:
    180       sq->stats.ia_vertices =
    181          softpipe->pipeline_statistics.ia_vertices - sq->stats.ia_vertices;
    182       sq->stats.ia_primitives =
    183          softpipe->pipeline_statistics.ia_primitives - sq->stats.ia_primitives;
    184       sq->stats.vs_invocations =
    185          softpipe->pipeline_statistics.vs_invocations - sq->stats.vs_invocations;
    186       sq->stats.gs_invocations =
    187          softpipe->pipeline_statistics.gs_invocations - sq->stats.gs_invocations;
    188       sq->stats.gs_primitives =
    189          softpipe->pipeline_statistics.gs_primitives - sq->stats.gs_primitives;
    190       sq->stats.c_invocations =
    191          softpipe->pipeline_statistics.c_invocations - sq->stats.c_invocations;
    192       sq->stats.c_primitives =
    193          softpipe->pipeline_statistics.c_primitives - sq->stats.c_primitives;
    194       sq->stats.ps_invocations =
    195          softpipe->pipeline_statistics.ps_invocations - sq->stats.ps_invocations;
    196 
    197       softpipe->active_statistics_queries--;
    198       break;
    199    default:
    200       assert(0);
    201       break;
    202    }
    203    softpipe->dirty |= SP_NEW_QUERY;
    204    return true;
    205 }
    206 
    207 
    208 static boolean
    209 softpipe_get_query_result(struct pipe_context *pipe,
    210                           struct pipe_query *q,
    211                           boolean wait,
    212                           union pipe_query_result *vresult)
    213 {
    214    struct softpipe_query *sq = softpipe_query(q);
    215    uint64_t *result = (uint64_t*)vresult;
    216 
    217    switch (sq->type) {
    218    case PIPE_QUERY_SO_STATISTICS: {
    219       struct pipe_query_data_so_statistics *stats =
    220          (struct pipe_query_data_so_statistics *)vresult;
    221       stats->num_primitives_written = sq->so.num_primitives_written;
    222       stats->primitives_storage_needed = sq->so.primitives_storage_needed;
    223    }
    224       break;
    225    case PIPE_QUERY_PIPELINE_STATISTICS:
    226       memcpy(vresult, &sq->stats,
    227              sizeof(struct pipe_query_data_pipeline_statistics));
    228       break;
    229    case PIPE_QUERY_GPU_FINISHED:
    230       vresult->b = TRUE;
    231       break;
    232    case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
    233       vresult->b = sq->end != 0;
    234       break;
    235    case PIPE_QUERY_TIMESTAMP_DISJOINT: {
    236       struct pipe_query_data_timestamp_disjoint *td =
    237           (struct pipe_query_data_timestamp_disjoint *)vresult;
    238       /* os_get_time_nano return nanoseconds */
    239       td->frequency = UINT64_C(1000000000);
    240       td->disjoint = FALSE;
    241    }
    242       break;
    243    case PIPE_QUERY_PRIMITIVES_EMITTED:
    244       *result = sq->so.num_primitives_written;
    245       break;
    246    case PIPE_QUERY_PRIMITIVES_GENERATED:
    247       *result = sq->so.primitives_storage_needed;
    248       break;
    249    case PIPE_QUERY_OCCLUSION_PREDICATE:
    250       vresult->b = sq->end - sq->start != 0;
    251       break;
    252    default:
    253       *result = sq->end - sq->start;
    254       break;
    255    }
    256    return TRUE;
    257 }
    258 
    259 
    260 /**
    261  * Called by rendering function to check rendering is conditional.
    262  * \return TRUE if we should render, FALSE if we should skip rendering
    263  */
    264 boolean
    265 softpipe_check_render_cond(struct softpipe_context *sp)
    266 {
    267    struct pipe_context *pipe = &sp->pipe;
    268    boolean b, wait;
    269    uint64_t result;
    270 
    271    if (!sp->render_cond_query) {
    272       return TRUE;  /* no query predicate, draw normally */
    273    }
    274 
    275    wait = (sp->render_cond_mode == PIPE_RENDER_COND_WAIT ||
    276            sp->render_cond_mode == PIPE_RENDER_COND_BY_REGION_WAIT);
    277 
    278    b = pipe->get_query_result(pipe, sp->render_cond_query, wait,
    279                               (void*)&result);
    280    if (b)
    281       return (!result) == sp->render_cond_cond;
    282    else
    283       return TRUE;
    284 }
    285 
    286 
    287 static void
    288 softpipe_set_active_query_state(struct pipe_context *pipe, boolean enable)
    289 {
    290 }
    291 
    292 
    293 void softpipe_init_query_funcs(struct softpipe_context *softpipe )
    294 {
    295    softpipe->pipe.create_query = softpipe_create_query;
    296    softpipe->pipe.destroy_query = softpipe_destroy_query;
    297    softpipe->pipe.begin_query = softpipe_begin_query;
    298    softpipe->pipe.end_query = softpipe_end_query;
    299    softpipe->pipe.get_query_result = softpipe_get_query_result;
    300    softpipe->pipe.set_active_query_state = softpipe_set_active_query_state;
    301 }
    302 
    303 
    304