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
] = INFOX(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
)
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
:
88 q
= CALLOC_STRUCT(ilo_query
);
93 list_inithead(&q
->list
);
95 return (struct pipe_query
*) q
;
99 ilo_destroy_query(struct pipe_context
*pipe
, struct pipe_query
*query
)
101 struct ilo_query
*q
= ilo_query(query
);
104 intel_bo_unreference(q
->bo
);
110 ilo_begin_query(struct pipe_context
*pipe
, struct pipe_query
*query
)
112 struct ilo_context
*ilo
= ilo_context(pipe
);
113 struct ilo_query
*q
= ilo_query(query
);
117 query_info
[q
->type
].begin(ilo
, q
);
121 ilo_end_query(struct pipe_context
*pipe
, struct pipe_query
*query
)
123 struct ilo_context
*ilo
= ilo_context(pipe
);
124 struct ilo_query
*q
= ilo_query(query
);
126 query_info
[q
->type
].end(ilo
, q
);
129 * some queries such as timestamp query does not require a call to
130 * begin_query() so q->active is always false
136 * The type (union pipe_query_result) indicates only the size of the buffer.
137 * Callers expect the result to be "serialized".
140 serialize_query_data(unsigned type
, const union pipe_query_result
*data
,
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
:
155 memset(buf
, 0, sizeof(union pipe_query_result
));
161 ilo_get_query_result(struct pipe_context
*pipe
, struct pipe_query
*query
,
162 boolean wait
, union pipe_query_result
*result
)
164 struct ilo_context
*ilo
= ilo_context(pipe
);
165 struct ilo_query
*q
= ilo_query(query
);
171 if (intel_bo_references(ilo
->cp
->bo
, q
->bo
))
172 ilo_cp_flush(ilo
->cp
);
174 if (!wait
&& intel_bo_is_busy(q
->bo
))
177 query_info
[q
->type
].process(ilo
, q
);
181 serialize_query_data(q
->type
, &q
->data
, (void *) result
);
187 * Allocate a query bo for reading hardware statistics.
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.
194 ilo_query_alloc_bo(struct ilo_query
*q
, int reg_count
, int repeat_count
,
195 struct intel_winsys
*winsys
)
200 name
= query_info
[q
->type
].name
;
202 reg_total
= reg_count
* repeat_count
;
204 reg_total
= 4096 / sizeof(uint64_t);
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);
212 intel_bo_unreference(q
->bo
);
214 q
->bo
= intel_winsys_alloc_buffer(winsys
, name
, size
, 0);
215 q
->reg_total
= (q
->bo
) ? reg_total
: 0;
218 /* avoid partial reads */
220 q
->reg_total
-= q
->reg_total
% reg_count
;
224 return (q
->bo
!= NULL
);
228 * Initialize query-related functions.
231 ilo_init_query_functions(struct ilo_context
*ilo
)
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
;