• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "core/intel_winsys.h"
29 
30 #include "ilo_context.h"
31 #include "ilo_cp.h"
32 #include "ilo_draw.h"
33 #include "ilo_query.h"
34 
35 static const struct {
36    bool (*init)(struct ilo_context *ilo, struct ilo_query *q);
37    void (*begin)(struct ilo_context *ilo, struct ilo_query *q);
38    void (*end)(struct ilo_context *ilo, struct ilo_query *q);
39    void (*process)(struct ilo_context *ilo, struct ilo_query *q);
40 } ilo_query_table[PIPE_QUERY_TYPES] = {
41 #define INFO(mod) {                    \
42    .init = ilo_init_ ## mod ## _query,         \
43    .begin = ilo_begin_ ## mod ## _query,       \
44    .end = ilo_end_ ## mod ## _query,           \
45    .process = ilo_process_ ## mod ## _query,   \
46 }
47 #define INFOX(prefix) { NULL, NULL, NULL, NULL, }
48 
49    [PIPE_QUERY_OCCLUSION_COUNTER]      = INFO(draw),
50    [PIPE_QUERY_OCCLUSION_PREDICATE]    = INFO(draw),
51    [PIPE_QUERY_TIMESTAMP]              = INFO(draw),
52    [PIPE_QUERY_TIMESTAMP_DISJOINT]     = INFOX(draw),
53    [PIPE_QUERY_TIME_ELAPSED]           = INFO(draw),
54    [PIPE_QUERY_PRIMITIVES_GENERATED]   = INFO(draw),
55    [PIPE_QUERY_PRIMITIVES_EMITTED]     = INFO(draw),
56    [PIPE_QUERY_SO_STATISTICS]          = INFOX(draw),
57    [PIPE_QUERY_SO_OVERFLOW_PREDICATE]  = INFOX(draw),
58    [PIPE_QUERY_GPU_FINISHED]           = INFOX(draw),
59    [PIPE_QUERY_PIPELINE_STATISTICS]    = INFO(draw),
60 
61 #undef INFO
62 #undef INFOX
63 };
64 
65 static inline struct ilo_query *
ilo_query(struct pipe_query * query)66 ilo_query(struct pipe_query *query)
67 {
68    return (struct ilo_query *) query;
69 }
70 
71 static struct pipe_query *
ilo_create_query(struct pipe_context * pipe,unsigned query_type,unsigned index)72 ilo_create_query(struct pipe_context *pipe, unsigned query_type, unsigned index)
73 {
74    struct ilo_query *q;
75 
76    switch (query_type) {
77    case PIPE_QUERY_OCCLUSION_COUNTER:
78    case PIPE_QUERY_OCCLUSION_PREDICATE:
79    case PIPE_QUERY_TIMESTAMP:
80    case PIPE_QUERY_TIME_ELAPSED:
81    case PIPE_QUERY_PRIMITIVES_GENERATED:
82    case PIPE_QUERY_PRIMITIVES_EMITTED:
83    case PIPE_QUERY_PIPELINE_STATISTICS:
84       break;
85    default:
86       return NULL;
87    }
88 
89    q = CALLOC_STRUCT(ilo_query);
90    if (!q)
91       return NULL;
92 
93    q->type = query_type;
94    q->index = index;
95 
96    list_inithead(&q->list);
97 
98    if (!ilo_query_table[q->type].init(ilo_context(pipe), q)) {
99       FREE(q);
100       return NULL;
101    }
102 
103    return (struct pipe_query *) q;
104 }
105 
106 static void
ilo_destroy_query(struct pipe_context * pipe,struct pipe_query * query)107 ilo_destroy_query(struct pipe_context *pipe, struct pipe_query *query)
108 {
109    struct ilo_query *q = ilo_query(query);
110 
111    intel_bo_unref(q->bo);
112    FREE(q);
113 }
114 
115 static boolean
ilo_begin_query(struct pipe_context * pipe,struct pipe_query * query)116 ilo_begin_query(struct pipe_context *pipe, struct pipe_query *query)
117 {
118    struct ilo_query *q = ilo_query(query);
119 
120    if (q->active)
121       return false;
122 
123    util_query_clear_result(&q->result, q->type);
124    q->used = 0;
125    q->active = true;
126 
127    ilo_query_table[q->type].begin(ilo_context(pipe), q);
128    return true;
129 }
130 
131 static bool
ilo_end_query(struct pipe_context * pipe,struct pipe_query * query)132 ilo_end_query(struct pipe_context *pipe, struct pipe_query *query)
133 {
134    struct ilo_query *q = ilo_query(query);
135 
136    if (!q->active) {
137       /* require ilo_begin_query() first */
138       if (q->in_pairs)
139          return false;
140 
141       ilo_begin_query(pipe, query);
142    }
143 
144    q->active = false;
145 
146    ilo_query_table[q->type].end(ilo_context(pipe), q);
147 
148    return true;
149 }
150 
151 /**
152  * Serialize the result.  The size of \p buf is
153  * sizeof(union pipe_query_result).
154  */
155 static void
query_serialize(const struct ilo_query * q,void * buf)156 query_serialize(const struct ilo_query *q, void *buf)
157 {
158    switch (q->type) {
159    case PIPE_QUERY_OCCLUSION_COUNTER:
160    case PIPE_QUERY_TIMESTAMP:
161    case PIPE_QUERY_TIME_ELAPSED:
162    case PIPE_QUERY_PRIMITIVES_GENERATED:
163    case PIPE_QUERY_PRIMITIVES_EMITTED:
164       {
165          uint64_t *dst = buf;
166          dst[0] = q->result.u64;
167       }
168       break;
169    case PIPE_QUERY_OCCLUSION_PREDICATE:
170       {
171          uint64_t *dst = buf;
172          dst[0] = !!q->result.u64;
173       }
174       break;
175    case PIPE_QUERY_PIPELINE_STATISTICS:
176       {
177          const struct pipe_query_data_pipeline_statistics *stats =
178             &q->result.pipeline_statistics;
179          uint64_t *dst = buf;
180 
181          dst[0] = stats->ia_vertices;
182          dst[1] = stats->ia_primitives;
183          dst[2] = stats->vs_invocations;
184          dst[3] = stats->gs_invocations;
185          dst[4] = stats->gs_primitives;
186          dst[5] = stats->c_invocations;
187          dst[6] = stats->c_primitives;
188          dst[7] = stats->ps_invocations;
189          dst[8] = stats->hs_invocations;
190          dst[9] = stats->ds_invocations;
191          dst[10] = stats->cs_invocations;
192       }
193       break;
194    default:
195       memset(buf, 0, sizeof(union pipe_query_result));
196       break;
197    }
198 }
199 
200 static boolean
ilo_get_query_result(struct pipe_context * pipe,struct pipe_query * query,boolean wait,union pipe_query_result * result)201 ilo_get_query_result(struct pipe_context *pipe, struct pipe_query *query,
202                      boolean wait, union pipe_query_result *result)
203 {
204    struct ilo_query *q = ilo_query(query);
205 
206    if (q->active)
207       return false;
208 
209    if (q->bo) {
210       struct ilo_cp *cp = ilo_context(pipe)->cp;
211 
212       if (ilo_builder_has_reloc(&cp->builder, q->bo))
213          ilo_cp_submit(cp, "syncing for queries");
214 
215       if (!wait && intel_bo_is_busy(q->bo))
216          return false;
217    }
218 
219    ilo_query_table[q->type].process(ilo_context(pipe), q);
220 
221    if (result)
222       query_serialize(q, (void *) result);
223 
224    return true;
225 }
226 
227 static void
ilo_set_active_query_state(struct pipe_context * pipe,boolean enable)228 ilo_set_active_query_state(struct pipe_context *pipe, boolean enable)
229 {
230 }
231 
232 /**
233  * Initialize query-related functions.
234  */
235 void
ilo_init_query_functions(struct ilo_context * ilo)236 ilo_init_query_functions(struct ilo_context *ilo)
237 {
238    ilo->base.create_query = ilo_create_query;
239    ilo->base.destroy_query = ilo_destroy_query;
240    ilo->base.begin_query = ilo_begin_query;
241    ilo->base.end_query = ilo_end_query;
242    ilo->base.get_query_result = ilo_get_query_result;
243    ilo->base.set_active_query_state = ilo_set_active_query_state;
244 }
245