2 * Mesa 3-D graphics library
4 * Copyright (C) 2012-2013 LunarG, Inc.
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:
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
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.
25 * Chia-I Wu <olv@lunarg.com>
28 #include "intel_winsys.h"
31 #include "ilo_context.h"
33 #include "ilo_query.h"
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) { \
44 .begin = prefix ## _begin_query, \
45 .end = prefix ## _end_query, \
46 .process = prefix ## _process_query, \
48 #define INFOX(prefix, desc) { desc, NULL, NULL, NULL, }
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
] = INFO(ilo_3d
, "pipeline statistics"),
66 static inline struct ilo_query
*
67 ilo_query(struct pipe_query
*query
)
69 return (struct ilo_query
*) query
;
72 static struct pipe_query
*
73 ilo_create_query(struct pipe_context
*pipe
, unsigned query_type
, unsigned index
)
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 case PIPE_QUERY_PIPELINE_STATISTICS
:
89 q
= CALLOC_STRUCT(ilo_query
);
94 list_inithead(&q
->list
);
96 return (struct pipe_query
*) q
;
100 ilo_destroy_query(struct pipe_context
*pipe
, struct pipe_query
*query
)
102 struct ilo_query
*q
= ilo_query(query
);
105 intel_bo_unreference(q
->bo
);
111 ilo_begin_query(struct pipe_context
*pipe
, struct pipe_query
*query
)
113 struct ilo_context
*ilo
= ilo_context(pipe
);
114 struct ilo_query
*q
= ilo_query(query
);
118 query_info
[q
->type
].begin(ilo
, q
);
122 ilo_end_query(struct pipe_context
*pipe
, struct pipe_query
*query
)
124 struct ilo_context
*ilo
= ilo_context(pipe
);
125 struct ilo_query
*q
= ilo_query(query
);
127 query_info
[q
->type
].end(ilo
, q
);
130 * some queries such as timestamp query does not require a call to
131 * begin_query() so q->active is always false
137 * The type (union pipe_query_result) indicates only the size of the buffer.
138 * Callers expect the result to be "serialized".
141 serialize_query_data(unsigned type
, const union pipe_query_result
*data
,
145 case PIPE_QUERY_OCCLUSION_COUNTER
:
146 case PIPE_QUERY_TIMESTAMP
:
147 case PIPE_QUERY_TIME_ELAPSED
:
148 case PIPE_QUERY_PRIMITIVES_GENERATED
:
149 case PIPE_QUERY_PRIMITIVES_EMITTED
:
155 case PIPE_QUERY_PIPELINE_STATISTICS
:
158 r
[0] = data
->pipeline_statistics
.ia_vertices
;
159 r
[1] = data
->pipeline_statistics
.ia_primitives
;
160 r
[2] = data
->pipeline_statistics
.vs_invocations
;
161 r
[3] = data
->pipeline_statistics
.gs_invocations
;
162 r
[4] = data
->pipeline_statistics
.gs_primitives
;
163 r
[5] = data
->pipeline_statistics
.c_invocations
;
164 r
[6] = data
->pipeline_statistics
.c_primitives
;
165 r
[7] = data
->pipeline_statistics
.ps_invocations
;
166 r
[8] = data
->pipeline_statistics
.hs_invocations
;
167 r
[9] = data
->pipeline_statistics
.ds_invocations
;
168 r
[10] = data
->pipeline_statistics
.cs_invocations
;
172 memset(buf
, 0, sizeof(union pipe_query_result
));
178 ilo_get_query_result(struct pipe_context
*pipe
, struct pipe_query
*query
,
179 boolean wait
, union pipe_query_result
*result
)
181 struct ilo_context
*ilo
= ilo_context(pipe
);
182 struct ilo_query
*q
= ilo_query(query
);
188 if (intel_bo_has_reloc(ilo
->cp
->bo
, q
->bo
))
189 ilo_cp_flush(ilo
->cp
, "syncing for queries");
191 if (!wait
&& intel_bo_is_busy(q
->bo
))
194 query_info
[q
->type
].process(ilo
, q
);
198 serialize_query_data(q
->type
, &q
->data
, (void *) result
);
204 * Allocate a query bo for reading hardware statistics.
206 * \param reg_count specifies how many registers need to be read.
207 * \param repeat_count specifies how many times the registers are read. If
208 * zero or negative, a 4KB bo is allocated.
211 ilo_query_alloc_bo(struct ilo_query
*q
, int reg_count
, int repeat_count
,
212 struct intel_winsys
*winsys
)
217 name
= query_info
[q
->type
].name
;
219 reg_total
= reg_count
* repeat_count
;
221 reg_total
= 4096 / sizeof(uint64_t);
223 /* (re-)allocate the bo */
224 if (q
->reg_total
< reg_total
) {
225 /* registers are 64-bit */
226 const int size
= reg_total
* sizeof(uint64_t);
229 intel_bo_unreference(q
->bo
);
231 q
->bo
= intel_winsys_alloc_buffer(winsys
,
232 name
, size
, INTEL_DOMAIN_INSTRUCTION
);
233 q
->reg_total
= (q
->bo
) ? reg_total
: 0;
236 /* avoid partial reads */
238 q
->reg_total
-= q
->reg_total
% reg_count
;
242 return (q
->bo
!= NULL
);
246 * Initialize query-related functions.
249 ilo_init_query_functions(struct ilo_context
*ilo
)
251 ilo
->base
.create_query
= ilo_create_query
;
252 ilo
->base
.destroy_query
= ilo_destroy_query
;
253 ilo
->base
.begin_query
= ilo_begin_query
;
254 ilo
->base
.end_query
= ilo_end_query
;
255 ilo
->base
.get_query_result
= ilo_get_query_result
;