Subversion Repositories Kolibri OS

Rev

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

  1. /*
  2.  * Mesa 3-D graphics library
  3.  *
  4.  * Copyright (C) 2012-2013 LunarG, Inc.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the "Software"),
  8.  * to deal in the Software without restriction, including without limitation
  9.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  10.  * and/or sell copies of the Software, and to permit persons to whom the
  11.  * Software is furnished to do so, subject to the following conditions:
  12.  *
  13.  * The above copyright notice and this permission notice shall be included
  14.  * in all copies or substantial portions of the Software.
  15.  *
  16.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  19.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  21.  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  22.  * DEALINGS IN THE SOFTWARE.
  23.  *
  24.  * Authors:
  25.  *    Chia-I Wu <olv@lunarg.com>
  26.  */
  27.  
  28. #include "intel_winsys.h"
  29.  
  30. #include "ilo_3d.h"
  31. #include "ilo_context.h"
  32. #include "ilo_cp.h"
  33. #include "ilo_query.h"
  34.  
  35. static const struct {
  36.    const char *name;
  37.  
  38.    void (*begin)(struct ilo_context *ilo, struct ilo_query *q);
  39.    void (*end)(struct ilo_context *ilo, struct ilo_query *q);
  40.    void (*process)(struct ilo_context *ilo, struct ilo_query *q);
  41. } query_info[PIPE_QUERY_TYPES] = {
  42. #define INFO(prefix, desc) {        \
  43.    .name = desc,                    \
  44.    .begin = prefix ## _begin_query, \
  45.    .end = prefix ## _end_query,     \
  46.    .process = prefix ## _process_query, \
  47. }
  48. #define INFOX(prefix, desc) { desc, NULL, NULL, NULL, }
  49.  
  50.    [PIPE_QUERY_OCCLUSION_COUNTER]      = INFO(ilo_3d, "occlusion counter"),
  51.    [PIPE_QUERY_OCCLUSION_PREDICATE]    = INFOX(ilo_3d, "occlusion pred."),
  52.    [PIPE_QUERY_TIMESTAMP]              = INFO(ilo_3d, "timestamp"),
  53.    [PIPE_QUERY_TIMESTAMP_DISJOINT]     = INFOX(ilo_3d, "timestamp disjoint"),
  54.    [PIPE_QUERY_TIME_ELAPSED]           = INFO(ilo_3d, "time elapsed"),
  55.    [PIPE_QUERY_PRIMITIVES_GENERATED]   = INFO(ilo_3d, "primitives generated"),
  56.    [PIPE_QUERY_PRIMITIVES_EMITTED]     = INFO(ilo_3d, "primitives emitted"),
  57.    [PIPE_QUERY_SO_STATISTICS]          = INFOX(ilo_3d, "so statistics"),
  58.    [PIPE_QUERY_SO_OVERFLOW_PREDICATE]  = INFOX(ilo_3d, "so overflow pred."),
  59.    [PIPE_QUERY_GPU_FINISHED]           = INFOX(ilo_3d, "gpu finished"),
  60.    [PIPE_QUERY_PIPELINE_STATISTICS]    = INFOX(ilo_3d, "pipeline statistics"),
  61.  
  62. #undef INFO
  63. #undef INFOX
  64. };
  65.  
  66. static inline struct ilo_query *
  67. ilo_query(struct pipe_query *query)
  68. {
  69.    return (struct ilo_query *) query;
  70. }
  71.  
  72. static struct pipe_query *
  73. ilo_create_query(struct pipe_context *pipe, unsigned query_type)
  74. {
  75.    struct ilo_query *q;
  76.  
  77.    switch (query_type) {
  78.    case PIPE_QUERY_OCCLUSION_COUNTER:
  79.    case PIPE_QUERY_TIMESTAMP:
  80.    case PIPE_QUERY_TIME_ELAPSED:
  81.    case PIPE_QUERY_PRIMITIVES_GENERATED:
  82.    case PIPE_QUERY_PRIMITIVES_EMITTED:
  83.       break;
  84.    default:
  85.       return NULL;
  86.    }
  87.  
  88.    q = CALLOC_STRUCT(ilo_query);
  89.    if (!q)
  90.       return NULL;
  91.  
  92.    q->type = query_type;
  93.    list_inithead(&q->list);
  94.  
  95.    return (struct pipe_query *) q;
  96. }
  97.  
  98. static void
  99. ilo_destroy_query(struct pipe_context *pipe, struct pipe_query *query)
  100. {
  101.    struct ilo_query *q = ilo_query(query);
  102.  
  103.    if (q->bo)
  104.       intel_bo_unreference(q->bo);
  105.  
  106.    FREE(q);
  107. }
  108.  
  109. static void
  110. ilo_begin_query(struct pipe_context *pipe, struct pipe_query *query)
  111. {
  112.    struct ilo_context *ilo = ilo_context(pipe);
  113.    struct ilo_query *q = ilo_query(query);
  114.  
  115.    q->active = true;
  116.  
  117.    query_info[q->type].begin(ilo, q);
  118. }
  119.  
  120. static void
  121. ilo_end_query(struct pipe_context *pipe, struct pipe_query *query)
  122. {
  123.    struct ilo_context *ilo = ilo_context(pipe);
  124.    struct ilo_query *q = ilo_query(query);
  125.  
  126.    query_info[q->type].end(ilo, q);
  127.  
  128.    /*
  129.     * some queries such as timestamp query does not require a call to
  130.     * begin_query() so q->active is always false
  131.     */
  132.    q->active = false;
  133. }
  134.  
  135. /**
  136.  * The type (union pipe_query_result) indicates only the size of the buffer.
  137.  * Callers expect the result to be "serialized".
  138.  */
  139. static void
  140. serialize_query_data(unsigned type, const union pipe_query_result *data,
  141.                      void *buf)
  142. {
  143.    switch (type) {
  144.    case PIPE_QUERY_OCCLUSION_COUNTER:
  145.    case PIPE_QUERY_TIMESTAMP:
  146.    case PIPE_QUERY_TIME_ELAPSED:
  147.    case PIPE_QUERY_PRIMITIVES_GENERATED:
  148.    case PIPE_QUERY_PRIMITIVES_EMITTED:
  149.       {
  150.          uint64_t *r = buf;
  151.          r[0] = data->u64;
  152.       }
  153.       break;
  154.    default:
  155.       memset(buf, 0, sizeof(union pipe_query_result));
  156.       break;
  157.    }
  158. }
  159.  
  160. static boolean
  161. ilo_get_query_result(struct pipe_context *pipe, struct pipe_query *query,
  162.                      boolean wait, union pipe_query_result *result)
  163. {
  164.    struct ilo_context *ilo = ilo_context(pipe);
  165.    struct ilo_query *q = ilo_query(query);
  166.  
  167.    if (q->active)
  168.       return false;
  169.  
  170.    if (q->bo) {
  171.       if (intel_bo_references(ilo->cp->bo, q->bo))
  172.          ilo_cp_flush(ilo->cp);
  173.  
  174.       if (!wait && intel_bo_is_busy(q->bo))
  175.          return false;
  176.  
  177.       query_info[q->type].process(ilo, q);
  178.    }
  179.  
  180.    if (result)
  181.       serialize_query_data(q->type, &q->data, (void *) result);
  182.  
  183.    return true;
  184. }
  185.  
  186. /**
  187.  * Allocate a query bo for reading hardware statistics.
  188.  *
  189.  * \param reg_count specifies how many registers need to be read.
  190.  * \param repeat_count specifies how many times the registers are read.  If
  191.  *        zero or negative, a 4KB bo is allocated.
  192.  */
  193. bool
  194. ilo_query_alloc_bo(struct ilo_query *q, int reg_count, int repeat_count,
  195.                    struct intel_winsys *winsys)
  196. {
  197.    const char *name;
  198.    int reg_total;
  199.  
  200.    name = query_info[q->type].name;
  201.  
  202.    reg_total = reg_count * repeat_count;
  203.    if (reg_total <= 0)
  204.       reg_total = 4096 / sizeof(uint64_t);
  205.  
  206.    /* (re-)allocate the bo */
  207.    if (q->reg_total < reg_total) {
  208.       /* registers are 64-bit */
  209.       const int size = reg_total * sizeof(uint64_t);
  210.  
  211.       if (q->bo)
  212.          intel_bo_unreference(q->bo);
  213.  
  214.       q->bo = intel_winsys_alloc_buffer(winsys, name, size, 0);
  215.       q->reg_total = (q->bo) ? reg_total : 0;
  216.    }
  217.  
  218.    /* avoid partial reads */
  219.    if (reg_count)
  220.       q->reg_total -= q->reg_total % reg_count;
  221.  
  222.    q->reg_read = 0;
  223.  
  224.    return (q->bo != NULL);
  225. }
  226.  
  227. /**
  228.  * Initialize query-related functions.
  229.  */
  230. void
  231. ilo_init_query_functions(struct ilo_context *ilo)
  232. {
  233.    ilo->base.create_query = ilo_create_query;
  234.    ilo->base.destroy_query = ilo_destroy_query;
  235.    ilo->base.begin_query = ilo_begin_query;
  236.    ilo->base.end_query = ilo_end_query;
  237.    ilo->base.get_query_result = ilo_get_query_result;
  238. }
  239.