2 * Copyright © 2017 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 * DEALINGS IN THE SOFTWARE.
26 * XXX: this file is EMPTY. it will eventually implement query objects!
31 #include "pipe/p_defines.h"
32 #include "pipe/p_state.h"
33 #include "pipe/p_context.h"
34 #include "pipe/p_screen.h"
35 #include "util/u_inlines.h"
36 #include "iris_context.h"
37 #include "iris_defines.h"
38 #include "iris_resource.h"
39 #include "iris_screen.h"
41 #define CS_GPR(n) (0x2600 + (n) * 8)
43 #define MI_MATH (0x1a << 23)
45 #define MI_ALU_LOAD 0x080
46 #define MI_ALU_LOADINV 0x480
47 #define MI_ALU_LOAD0 0x081
48 #define MI_ALU_LOAD1 0x481
49 #define MI_ALU_ADD 0x100
50 #define MI_ALU_SUB 0x101
51 #define MI_ALU_AND 0x102
52 #define MI_ALU_OR 0x103
53 #define MI_ALU_XOR 0x104
54 #define MI_ALU_STORE 0x180
55 #define MI_ALU_STOREINV 0x580
57 #define MI_ALU_R0 0x00
58 #define MI_ALU_R1 0x01
59 #define MI_ALU_R2 0x02
60 #define MI_ALU_R3 0x03
61 #define MI_ALU_R4 0x04
62 #define MI_ALU_SRCA 0x20
63 #define MI_ALU_SRCB 0x21
64 #define MI_ALU_ACCU 0x31
65 #define MI_ALU_ZF 0x32
66 #define MI_ALU_CF 0x33
68 #define MI_ALU0(op) ((MI_ALU_##op << 20))
69 #define MI_ALU1(op, x) ((MI_ALU_##op << 20) | (MI_ALU_##x << 10)
70 #define MI_ALU2(op, x, y) \
71 ((MI_ALU_##op << 20) | (MI_ALU_##x << 10) | (MI_ALU_##y))
74 enum pipe_query_type type
;
81 struct iris_query_snapshots
*map
;
84 struct iris_query_snapshots
{
87 uint64_t snapshots_landed
;
91 * Is this type of query written by PIPE_CONTROL?
94 iris_is_query_pipelined(struct iris_query
*q
)
97 case PIPE_QUERY_OCCLUSION_COUNTER
:
98 case PIPE_QUERY_OCCLUSION_PREDICATE
:
99 case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE
:
100 case PIPE_QUERY_TIMESTAMP
:
101 case PIPE_QUERY_TIMESTAMP_DISJOINT
:
102 case PIPE_QUERY_TIME_ELAPSED
:
111 write_availability(struct iris_context
*ice
,
112 struct iris_query
*q
,
115 struct iris_batch
*batch
= &ice
->render_batch
;
116 unsigned flags
= PIPE_CONTROL_WRITE_IMMEDIATE
;
117 unsigned offset
= offsetof(struct iris_query_snapshots
, snapshots_landed
);
119 if (!iris_is_query_pipelined(q
)) {
120 ice
->vtbl
.store_data_imm64(batch
, q
->bo
, offset
, available
);
123 /* Order available *after* the query results. */
124 flags
|= PIPE_CONTROL_FLUSH_ENABLE
;
126 /* Make it unavailable *before* any pipelined reads. */
127 flags
|= PIPE_CONTROL_CS_STALL
;
129 iris_emit_pipe_control_write(batch
, flags
, q
->bo
, offset
, available
);
134 * Write PS_DEPTH_COUNT to q->(dest) via a PIPE_CONTROL.
137 iris_pipelined_write(struct iris_batch
*batch
,
138 struct iris_query
*q
,
139 enum pipe_control_flags flags
,
142 const struct gen_device_info
*devinfo
= &batch
->screen
->devinfo
;
143 const unsigned optional_cs_stall
=
144 devinfo
->gen
== 9 && devinfo
->gt
== 4 ? PIPE_CONTROL_CS_STALL
: 0;
146 iris_emit_pipe_control_write(batch
, flags
| optional_cs_stall
,
147 q
->bo
, offset
, 0ull);
151 write_value(struct iris_context
*ice
, struct iris_query
*q
, unsigned offset
)
153 iris_use_pinned_bo(&ice
->render_batch
, q
->bo
, true);
156 case PIPE_QUERY_OCCLUSION_COUNTER
:
157 case PIPE_QUERY_OCCLUSION_PREDICATE
:
158 case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE
:
159 iris_pipelined_write(&ice
->render_batch
, q
,
160 PIPE_CONTROL_WRITE_DEPTH_COUNT
|
161 PIPE_CONTROL_DEPTH_STALL
,
163 case PIPE_QUERY_TIME_ELAPSED
:
164 iris_pipelined_write(&ice
->render_batch
, q
,
165 PIPE_CONTROL_WRITE_TIMESTAMP
,
174 calculate_result_on_cpu(struct iris_query
*q
)
177 case PIPE_QUERY_OCCLUSION_PREDICATE
:
178 case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE
:
179 q
->result
= q
->map
->end
!= q
->map
->start
;
181 case PIPE_QUERY_OCCLUSION_COUNTER
:
182 case PIPE_QUERY_TIME_ELAPSED
:
183 case PIPE_QUERY_PRIMITIVES_GENERATED
:
184 case PIPE_QUERY_PRIMITIVES_EMITTED
:
186 q
->result
= q
->map
->end
- q
->map
->start
;
194 * Calculate the result and store it to CS_GPR0.
197 calculate_result_on_gpu(struct iris_context
*ice
, struct iris_query
*q
)
199 struct iris_batch
*batch
= &ice
->render_batch
;
201 ice
->vtbl
.load_register_mem64(batch
, CS_GPR(1), q
->bo
,
202 offsetof(struct iris_query_snapshots
, start
));
203 ice
->vtbl
.load_register_mem64(batch
, CS_GPR(2), q
->bo
,
204 offsetof(struct iris_query_snapshots
, end
));
206 static const uint32_t math
[] = {
208 MI_ALU2(LOAD
, SRCA
, R2
),
209 MI_ALU2(LOAD
, SRCB
, R1
),
211 MI_ALU2(STORE
, R0
, ACCU
),
213 iris_batch_emit(batch
, math
, sizeof(math
));
216 static struct pipe_query
*
217 iris_create_query(struct pipe_context
*ctx
,
221 struct iris_query
*q
= calloc(1, sizeof(struct iris_query
));
223 q
->type
= query_type
;
225 return (struct pipe_query
*) q
;
229 iris_destroy_query(struct pipe_context
*ctx
, struct pipe_query
*p_query
)
231 struct iris_query
*query
= (void *) p_query
;
232 iris_bo_unreference(query
->bo
);
238 iris_begin_query(struct pipe_context
*ctx
, struct pipe_query
*query
)
240 struct iris_screen
*screen
= (void *) ctx
->screen
;
241 struct iris_context
*ice
= (void *) ctx
;
242 struct iris_query
*q
= (void *) query
;
244 iris_bo_unreference(q
->bo
);
245 q
->bo
= iris_bo_alloc(screen
->bufmgr
, "query object", 4096,
250 q
->map
= iris_bo_map(&ice
->dbg
, q
->bo
, MAP_READ
| MAP_ASYNC
);
257 write_availability(ice
, q
, false);
258 write_value(ice
, q
, offsetof(struct iris_query_snapshots
, start
));
264 iris_end_query(struct pipe_context
*ctx
, struct pipe_query
*query
)
266 struct iris_context
*ice
= (void *) ctx
;
267 struct iris_query
*q
= (void *) query
;
269 write_value(ice
, q
, offsetof(struct iris_query_snapshots
, end
));
270 write_availability(ice
, q
, true);
276 iris_get_query_result(struct pipe_context
*ctx
,
277 struct pipe_query
*query
,
279 union pipe_query_result
*result
)
281 struct iris_context
*ice
= (void *) ctx
;
282 struct iris_query
*q
= (void *) query
;
285 if (iris_batch_references(&ice
->render_batch
, q
->bo
))
286 iris_batch_flush(&ice
->render_batch
);
288 if (!q
->map
->snapshots_landed
) {
290 iris_bo_wait_rendering(q
->bo
);
295 assert(q
->map
->snapshots_landed
);
296 calculate_result_on_cpu(q
);
300 result
->u64
= q
->result
;
306 iris_get_query_result_resource(struct pipe_context
*ctx
,
307 struct pipe_query
*query
,
309 enum pipe_query_value_type result_type
,
311 struct pipe_resource
*p_res
,
314 struct iris_context
*ice
= (void *) ctx
;
315 struct iris_query
*q
= (void *) query
;
316 struct iris_batch
*batch
= &ice
->render_batch
;
318 if (!q
->ready
&& q
->map
->snapshots_landed
) {
319 /* The final snapshots happen to have landed, so let's just compute
320 * the result on the CPU now...
322 calculate_result_on_cpu(q
);
326 /* We happen to have the result on the CPU, so just copy it. */
327 if (result_type
<= PIPE_QUERY_TYPE_U32
) {
328 ice
->vtbl
.store_data_imm32(batch
, iris_resource_bo(p_res
), offset
,
331 ice
->vtbl
.store_data_imm64(batch
, iris_resource_bo(p_res
), offset
,
337 /* Calculate the result to CS_GPR0 */
338 calculate_result_on_gpu(ice
, q
);
340 bool predicated
= !wait
&& iris_is_query_pipelined(q
);
343 ice
->vtbl
.load_register_imm64(batch
, MI_PREDICATE_SRC1
, 0ull);
344 ice
->vtbl
.load_register_mem64(batch
, MI_PREDICATE_SRC0
, q
->bo
,
345 offsetof(struct iris_query_snapshots
,
347 uint32_t predicate
= MI_PREDICATE
|
348 MI_PREDICATE_LOADOP_LOADINV
|
349 MI_PREDICATE_COMBINEOP_SET
|
350 MI_PREDICATE_COMPAREOP_SRCS_EQUAL
;
351 iris_batch_emit(batch
, &predicate
, sizeof(uint32_t));
354 if (result_type
<= PIPE_QUERY_TYPE_U32
) {
355 ice
->vtbl
.store_register_mem32(batch
, CS_GPR(0),
356 iris_resource_bo(p_res
),
359 ice
->vtbl
.store_register_mem64(batch
, CS_GPR(0),
360 iris_resource_bo(p_res
),
366 iris_set_active_query_state(struct pipe_context
*pipe
, boolean enable
)
368 /* Do nothing, intentionally - only u_blitter uses this. */
372 iris_init_query_functions(struct pipe_context
*ctx
)
374 ctx
->create_query
= iris_create_query
;
375 ctx
->destroy_query
= iris_destroy_query
;
376 ctx
->begin_query
= iris_begin_query
;
377 ctx
->end_query
= iris_end_query
;
378 ctx
->get_query_result
= iris_get_query_result
;
379 ctx
->get_query_result_resource
= iris_get_query_result_resource
;
380 ctx
->set_active_query_state
= iris_set_active_query_state
;