Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
  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 "os/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.  
  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 *
  52. llvmpipe_create_query(struct pipe_context *pipe,
  53.                       unsigned type)
  54. {
  55.    struct llvmpipe_query *pq;
  56.  
  57.    assert(type < PIPE_QUERY_TYPES);
  58.  
  59.    pq = CALLOC_STRUCT( llvmpipe_query );
  60.  
  61.    if (pq) {
  62.       pq->type = type;
  63.    }
  64.  
  65.    return (struct pipe_query *) pq;
  66. }
  67.  
  68.  
  69. static void
  70. llvmpipe_destroy_query(struct pipe_context *pipe, struct pipe_query *q)
  71. {
  72.    struct llvmpipe_query *pq = llvmpipe_query(q);
  73.  
  74.    /* Ideally we would refcount queries & not get destroyed until the
  75.     * last scene had finished with us.
  76.     */
  77.    if (pq->fence) {
  78.       if (!lp_fence_issued(pq->fence))
  79.          llvmpipe_flush(pipe, NULL, __FUNCTION__);
  80.  
  81.       if (!lp_fence_signalled(pq->fence))
  82.          lp_fence_wait(pq->fence);
  83.  
  84.       lp_fence_reference(&pq->fence, NULL);
  85.    }
  86.  
  87.    FREE(pq);
  88. }
  89.  
  90.  
  91. static boolean
  92. llvmpipe_get_query_result(struct pipe_context *pipe,
  93.                           struct pipe_query *q,
  94.                           boolean wait,
  95.                           union pipe_query_result *vresult)
  96. {
  97.    struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen);
  98.    unsigned num_threads = MAX2(1, screen->num_threads);
  99.    struct llvmpipe_query *pq = llvmpipe_query(q);
  100.    uint64_t *result = (uint64_t *)vresult;
  101.    int i;
  102.  
  103.    if (pq->fence) {
  104.       /* only have a fence if there was a scene */
  105.       if (!lp_fence_signalled(pq->fence)) {
  106.          if (!lp_fence_issued(pq->fence))
  107.             llvmpipe_flush(pipe, NULL, __FUNCTION__);
  108.  
  109.          if (!wait)
  110.             return FALSE;
  111.  
  112.          lp_fence_wait(pq->fence);
  113.       }
  114.    }
  115.  
  116.    /* Sum the results from each of the threads:
  117.     */
  118.    *result = 0;
  119.  
  120.    switch (pq->type) {
  121.    case PIPE_QUERY_OCCLUSION_COUNTER:
  122.       for (i = 0; i < num_threads; i++) {
  123.          *result += pq->end[i];
  124.       }
  125.       break;
  126.    case PIPE_QUERY_OCCLUSION_PREDICATE:
  127.       for (i = 0; i < num_threads; i++) {
  128.          /* safer (still not guaranteed) when there's an overflow */
  129.          vresult->b = vresult->b || pq->end[i];
  130.       }
  131.       break;
  132.    case PIPE_QUERY_TIMESTAMP:
  133.       for (i = 0; i < num_threads; i++) {
  134.          if (pq->end[i] > *result) {
  135.             *result = pq->end[i];
  136.          }
  137.       }
  138.       break;
  139.    case PIPE_QUERY_TIMESTAMP_DISJOINT: {
  140.       struct pipe_query_data_timestamp_disjoint *td =
  141.          (struct pipe_query_data_timestamp_disjoint *)vresult;
  142.       /* os_get_time_nano return nanoseconds */
  143.       td->frequency = UINT64_C(1000000000);
  144.       td->disjoint = FALSE;
  145.    }
  146.       break;
  147.    case PIPE_QUERY_GPU_FINISHED:
  148.       vresult->b = TRUE;
  149.       break;
  150.    case PIPE_QUERY_PRIMITIVES_GENERATED:
  151.       *result = pq->num_primitives_generated;
  152.       break;
  153.    case PIPE_QUERY_PRIMITIVES_EMITTED:
  154.       *result = pq->num_primitives_written;
  155.       break;
  156.    case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
  157.       vresult->b = pq->so_has_overflown;
  158.       break;
  159.    case PIPE_QUERY_SO_STATISTICS: {
  160.       struct pipe_query_data_so_statistics *stats =
  161.          (struct pipe_query_data_so_statistics *)vresult;
  162.       stats->num_primitives_written = pq->num_primitives_written;
  163.       stats->primitives_storage_needed = pq->num_primitives_generated;
  164.    }
  165.       break;
  166.    case PIPE_QUERY_PIPELINE_STATISTICS: {
  167.       struct pipe_query_data_pipeline_statistics *stats =
  168.          (struct pipe_query_data_pipeline_statistics *)vresult;
  169.       /* only ps_invocations come from binned query */
  170.       for (i = 0; i < num_threads; i++) {
  171.          pq->stats.ps_invocations += pq->end[i];
  172.       }
  173.       pq->stats.ps_invocations *= LP_RASTER_BLOCK_SIZE * LP_RASTER_BLOCK_SIZE;
  174.       *stats = pq->stats;
  175.    }
  176.       break;
  177.    default:
  178.       assert(0);
  179.       break;
  180.    }
  181.  
  182.    return TRUE;
  183. }
  184.  
  185.  
  186. static void
  187. llvmpipe_begin_query(struct pipe_context *pipe, struct pipe_query *q)
  188. {
  189.    struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe );
  190.    struct llvmpipe_query *pq = llvmpipe_query(q);
  191.  
  192.    /* Check if the query is already in the scene.  If so, we need to
  193.     * flush the scene now.  Real apps shouldn't re-use a query in a
  194.     * frame of rendering.
  195.     */
  196.    if (pq->fence && !lp_fence_issued(pq->fence)) {
  197.       llvmpipe_finish(pipe, __FUNCTION__);
  198.    }
  199.  
  200.  
  201.    memset(pq->start, 0, sizeof(pq->start));
  202.    memset(pq->end, 0, sizeof(pq->end));
  203.    lp_setup_begin_query(llvmpipe->setup, pq);
  204.  
  205.    switch (pq->type) {
  206.    case PIPE_QUERY_PRIMITIVES_EMITTED:
  207.       pq->num_primitives_written = 0;
  208.       llvmpipe->so_stats.num_primitives_written = 0;
  209.       break;
  210.    case PIPE_QUERY_PRIMITIVES_GENERATED:
  211.       pq->num_primitives_generated = 0;
  212.       llvmpipe->num_primitives_generated = 0;
  213.       break;
  214.    case PIPE_QUERY_SO_STATISTICS:
  215.       pq->num_primitives_written = 0;
  216.       llvmpipe->so_stats.num_primitives_written = 0;
  217.       pq->num_primitives_generated = 0;
  218.       llvmpipe->num_primitives_generated = 0;
  219.       break;
  220.    case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
  221.       pq->so_has_overflown = FALSE;
  222.       break;
  223.    case PIPE_QUERY_PIPELINE_STATISTICS:
  224.       /* reset our cache */
  225.       if (llvmpipe->active_statistics_queries == 0) {
  226.          memset(&llvmpipe->pipeline_statistics, 0,
  227.                 sizeof(llvmpipe->pipeline_statistics));
  228.       }
  229.       memcpy(&pq->stats, &llvmpipe->pipeline_statistics, sizeof(pq->stats));
  230.       llvmpipe->active_statistics_queries++;
  231.       break;
  232.    case PIPE_QUERY_OCCLUSION_COUNTER:
  233.    case PIPE_QUERY_OCCLUSION_PREDICATE:
  234.       llvmpipe->active_occlusion_queries++;
  235.       llvmpipe->dirty |= LP_NEW_OCCLUSION_QUERY;
  236.       break;
  237.    default:
  238.       break;
  239.    }
  240. }
  241.  
  242.  
  243. static void
  244. llvmpipe_end_query(struct pipe_context *pipe, struct pipe_query *q)
  245. {
  246.    struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe );
  247.    struct llvmpipe_query *pq = llvmpipe_query(q);
  248.  
  249.    lp_setup_end_query(llvmpipe->setup, pq);
  250.  
  251.    switch (pq->type) {
  252.  
  253.    case PIPE_QUERY_PRIMITIVES_EMITTED:
  254.       pq->num_primitives_written = llvmpipe->so_stats.num_primitives_written;
  255.       break;
  256.    case PIPE_QUERY_PRIMITIVES_GENERATED:
  257.       pq->num_primitives_generated = llvmpipe->num_primitives_generated;
  258.       break;
  259.    case PIPE_QUERY_SO_STATISTICS:
  260.       pq->num_primitives_written = llvmpipe->so_stats.num_primitives_written;
  261.       pq->num_primitives_generated = llvmpipe->num_primitives_generated;
  262.       break;
  263.    case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
  264.       pq->so_has_overflown = (llvmpipe->num_primitives_generated >
  265.                               llvmpipe->so_stats.num_primitives_written);
  266.       break;
  267.    case PIPE_QUERY_PIPELINE_STATISTICS:
  268.       pq->stats.ia_vertices =
  269.          llvmpipe->pipeline_statistics.ia_vertices - pq->stats.ia_vertices;
  270.       pq->stats.ia_primitives =
  271.          llvmpipe->pipeline_statistics.ia_primitives - pq->stats.ia_primitives;
  272.       pq->stats.vs_invocations =
  273.          llvmpipe->pipeline_statistics.vs_invocations - pq->stats.vs_invocations;
  274.       pq->stats.gs_invocations =
  275.          llvmpipe->pipeline_statistics.gs_invocations - pq->stats.gs_invocations;
  276.       pq->stats.gs_primitives =
  277.          llvmpipe->pipeline_statistics.gs_primitives - pq->stats.gs_primitives;
  278.       pq->stats.c_invocations =
  279.          llvmpipe->pipeline_statistics.c_invocations - pq->stats.c_invocations;
  280.       pq->stats.c_primitives =
  281.          llvmpipe->pipeline_statistics.c_primitives - pq->stats.c_primitives;
  282.       pq->stats.ps_invocations =
  283.          llvmpipe->pipeline_statistics.ps_invocations - pq->stats.ps_invocations;
  284.  
  285.       llvmpipe->active_statistics_queries--;
  286.       break;
  287.    case PIPE_QUERY_OCCLUSION_COUNTER:
  288.    case PIPE_QUERY_OCCLUSION_PREDICATE:
  289.       assert(llvmpipe->active_occlusion_queries);
  290.       llvmpipe->active_occlusion_queries--;
  291.       llvmpipe->dirty |= LP_NEW_OCCLUSION_QUERY;
  292.       break;
  293.    default:
  294.       break;
  295.    }
  296. }
  297.  
  298. boolean
  299. llvmpipe_check_render_cond(struct llvmpipe_context *lp)
  300. {
  301.    struct pipe_context *pipe = &lp->pipe;
  302.    boolean b, wait;
  303.    uint64_t result;
  304.  
  305.    if (!lp->render_cond_query)
  306.       return TRUE; /* no query predicate, draw normally */
  307.  
  308.    wait = (lp->render_cond_mode == PIPE_RENDER_COND_WAIT ||
  309.            lp->render_cond_mode == PIPE_RENDER_COND_BY_REGION_WAIT);
  310.  
  311.    b = pipe->get_query_result(pipe, lp->render_cond_query, wait, (void*)&result);
  312.    if (b)
  313.       return (!result == lp->render_cond_cond);
  314.    else
  315.       return TRUE;
  316. }
  317.  
  318. void llvmpipe_init_query_funcs(struct llvmpipe_context *llvmpipe )
  319. {
  320.    llvmpipe->pipe.create_query = llvmpipe_create_query;
  321.    llvmpipe->pipe.destroy_query = llvmpipe_destroy_query;
  322.    llvmpipe->pipe.begin_query = llvmpipe_begin_query;
  323.    llvmpipe->pipe.end_query = llvmpipe_end_query;
  324.    llvmpipe->pipe.get_query_result = llvmpipe_get_query_result;
  325. }
  326.  
  327.  
  328.