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 "util/u_prim.h"
29 #include "intel_winsys.h"
31 #include "ilo_render.h"
33 #include "ilo_context.h"
35 #include "ilo_query.h"
36 #include "ilo_shader.h"
37 #include "ilo_state.h"
41 ilo_draw_set_owner(struct ilo_context
*ilo
)
43 ilo_cp_set_owner(ilo
->cp
, INTEL_RING_RENDER
, &ilo
->draw
.cp_owner
);
47 query_timestamp_to_ns(const struct ilo_context
*ilo
, uint64_t timestamp
)
49 /* see ilo_get_timestamp() */
50 return (timestamp
& 0xffffffff) * 80;
54 * Process the bo and accumulate the result. The bo is emptied.
57 query_process_bo(const struct ilo_context
*ilo
, struct ilo_query
*q
)
66 vals
= intel_bo_map(q
->bo
, false);
73 case PIPE_QUERY_OCCLUSION_COUNTER
:
74 case PIPE_QUERY_TIME_ELAPSED
:
75 case PIPE_QUERY_PRIMITIVES_GENERATED
:
76 case PIPE_QUERY_PRIMITIVES_EMITTED
:
77 assert(q
->stride
== sizeof(*vals
) * 2);
80 for (i
= 0; i
< q
->used
; i
++)
81 tmp
+= vals
[2 * i
+ 1] - vals
[2 * i
];
83 if (q
->type
== PIPE_QUERY_TIME_ELAPSED
)
84 tmp
= query_timestamp_to_ns(ilo
, tmp
);
88 case PIPE_QUERY_TIMESTAMP
:
89 assert(q
->stride
== sizeof(*vals
));
91 q
->result
.u64
= query_timestamp_to_ns(ilo
, vals
[q
->used
- 1]);
93 case PIPE_QUERY_PIPELINE_STATISTICS
:
94 assert(q
->stride
== sizeof(*vals
) * 22);
96 for (i
= 0; i
< q
->used
; i
++) {
97 struct pipe_query_data_pipeline_statistics
*stats
=
98 &q
->result
.pipeline_statistics
;
99 const uint64_t *begin
= vals
+ 22 * i
;
100 const uint64_t *end
= begin
+ 11;
102 stats
->ia_vertices
+= end
[0] - begin
[0];
103 stats
->ia_primitives
+= end
[1] - begin
[1];
104 stats
->vs_invocations
+= end
[2] - begin
[2];
105 stats
->gs_invocations
+= end
[3] - begin
[3];
106 stats
->gs_primitives
+= end
[4] - begin
[4];
107 stats
->c_invocations
+= end
[5] - begin
[5];
108 stats
->c_primitives
+= end
[6] - begin
[6];
109 stats
->ps_invocations
+= end
[7] - begin
[7];
110 stats
->hs_invocations
+= end
[8] - begin
[8];
111 stats
->ds_invocations
+= end
[9] - begin
[9];
112 stats
->cs_invocations
+= end
[10] - begin
[10];
119 intel_bo_unmap(q
->bo
);
125 query_begin_bo(struct ilo_context
*ilo
, struct ilo_query
*q
)
128 if (q
->used
>= q
->count
)
129 query_process_bo(ilo
, q
);
131 /* write the beginning value to the bo */
133 ilo_render_emit_query(ilo
->render
, q
, q
->stride
* q
->used
);
137 query_end_bo(struct ilo_context
*ilo
, struct ilo_query
*q
)
141 assert(q
->used
< q
->count
);
143 offset
= q
->stride
* q
->used
;
145 offset
+= q
->stride
>> 1;
149 /* write the ending value to the bo */
150 ilo_render_emit_query(ilo
->render
, q
, offset
);
154 ilo_init_draw_query(struct ilo_context
*ilo
, struct ilo_query
*q
)
159 case PIPE_QUERY_OCCLUSION_COUNTER
:
160 case PIPE_QUERY_TIME_ELAPSED
:
161 case PIPE_QUERY_PRIMITIVES_GENERATED
:
162 case PIPE_QUERY_PRIMITIVES_EMITTED
:
163 q
->stride
= sizeof(uint64_t);
166 case PIPE_QUERY_TIMESTAMP
:
167 q
->stride
= sizeof(uint64_t);
170 case PIPE_QUERY_PIPELINE_STATISTICS
:
171 q
->stride
= sizeof(uint64_t) * 11;
179 q
->cmd_len
= ilo_render_get_query_len(ilo
->render
, q
->type
);
181 /* double cmd_len and stride if in pairs */
182 q
->cmd_len
<<= q
->in_pairs
;
183 q
->stride
<<= q
->in_pairs
;
185 bo_size
= (q
->stride
> 4096) ? q
->stride
: 4096;
186 q
->bo
= intel_winsys_alloc_buffer(ilo
->winsys
, "query", bo_size
, false);
190 q
->count
= bo_size
/ q
->stride
;
196 ilo_begin_draw_query(struct ilo_context
*ilo
, struct ilo_query
*q
)
198 ilo_draw_set_owner(ilo
);
200 /* need to submit first */
201 if (!ilo_builder_validate(&ilo
->cp
->builder
, 1, &q
->bo
) ||
202 ilo_cp_space(ilo
->cp
) < q
->cmd_len
) {
203 ilo_cp_submit(ilo
->cp
, "out of aperture or space");
205 assert(ilo_builder_validate(&ilo
->cp
->builder
, 1, &q
->bo
));
206 assert(ilo_cp_space(ilo
->cp
) >= q
->cmd_len
);
208 ilo_draw_set_owner(ilo
);
211 /* reserve the space for ending/pausing the query */
212 ilo
->draw
.cp_owner
.reserve
+= q
->cmd_len
>> q
->in_pairs
;
214 query_begin_bo(ilo
, q
);
217 list_add(&q
->list
, &ilo
->draw
.queries
);
221 ilo_end_draw_query(struct ilo_context
*ilo
, struct ilo_query
*q
)
223 ilo_draw_set_owner(ilo
);
225 /* reclaim the reserved space */
226 ilo
->draw
.cp_owner
.reserve
-= q
->cmd_len
>> q
->in_pairs
;
227 assert(ilo
->draw
.cp_owner
.reserve
>= 0);
229 query_end_bo(ilo
, q
);
231 list_delinit(&q
->list
);
235 * Process the raw query data.
238 ilo_process_draw_query(struct ilo_context
*ilo
, struct ilo_query
*q
)
240 query_process_bo(ilo
, q
);
244 ilo_draw_own_cp(struct ilo_cp
*cp
, void *data
)
246 struct ilo_context
*ilo
= data
;
248 /* multiply by 2 for both resuming and pausing */
249 if (ilo_cp_space(ilo
->cp
) < ilo
->draw
.cp_owner
.reserve
* 2) {
250 ilo_cp_submit(ilo
->cp
, "out of space");
251 assert(ilo_cp_space(ilo
->cp
) >= ilo
->draw
.cp_owner
.reserve
* 2);
255 struct ilo_builder_snapshot snapshot
;
258 ilo_builder_batch_snapshot(&ilo
->cp
->builder
, &snapshot
);
261 LIST_FOR_EACH_ENTRY(q
, &ilo
->draw
.queries
, list
)
262 query_begin_bo(ilo
, q
);
264 if (!ilo_builder_validate(&ilo
->cp
->builder
, 0, NULL
)) {
265 ilo_builder_batch_restore(&ilo
->cp
->builder
, &snapshot
);
267 if (ilo_builder_batch_used(&ilo
->cp
->builder
)) {
268 ilo_cp_submit(ilo
->cp
, "out of aperture");
276 assert(ilo_cp_space(ilo
->cp
) >= ilo
->draw
.cp_owner
.reserve
);
280 ilo_draw_release_cp(struct ilo_cp
*cp
, void *data
)
282 struct ilo_context
*ilo
= data
;
285 assert(ilo_cp_space(ilo
->cp
) >= ilo
->draw
.cp_owner
.reserve
);
288 LIST_FOR_EACH_ENTRY(q
, &ilo
->draw
.queries
, list
)
289 query_end_bo(ilo
, q
);
293 draw_vbo(struct ilo_context
*ilo
, const struct ilo_state_vector
*vec
)
295 bool need_flush
= false;
297 int max_len
, before_space
;
299 /* on GEN7+, we need SOL_RESET to reset the SO write offsets */
300 if (ilo_dev_gen(ilo
->dev
) >= ILO_GEN(7) &&
301 (vec
->dirty
& ILO_DIRTY_SO
) && vec
->so
.enabled
&&
302 !vec
->so
.append_bitmask
) {
303 ilo_cp_submit(ilo
->cp
, "SOL_RESET");
304 ilo_cp_set_one_off_flags(ilo
->cp
, INTEL_EXEC_GEN7_SOL_RESET
);
307 if (ilo_builder_batch_used(&ilo
->cp
->builder
)) {
309 * Without a better tracking mechanism, when the framebuffer changes, we
310 * have to assume that the old framebuffer may be sampled from. If that
311 * happens in the middle of a batch buffer, we need to insert manual
314 need_flush
= (vec
->dirty
& ILO_DIRTY_FB
);
316 /* same to SO target changes */
317 need_flush
|= (vec
->dirty
& ILO_DIRTY_SO
);
320 ilo_draw_set_owner(ilo
);
322 /* make sure there is enough room first */
323 max_len
= ilo_render_estimate_size(ilo
->render
,
324 ILO_RENDER_DRAW
, vec
);
326 max_len
+= ilo_render_get_flush_len(ilo
->render
);
328 if (max_len
> ilo_cp_space(ilo
->cp
)) {
329 ilo_cp_submit(ilo
->cp
, "out of space");
331 assert(max_len
<= ilo_cp_space(ilo
->cp
));
334 /* space available before emission */
335 before_space
= ilo_cp_space(ilo
->cp
);
338 ilo_render_emit_flush(ilo
->render
);
341 struct ilo_builder_snapshot snapshot
;
343 ilo_builder_batch_snapshot(&ilo
->cp
->builder
, &snapshot
);
345 ilo_render_emit_draw(ilo
->render
, vec
);
347 if (!ilo_builder_validate(&ilo
->cp
->builder
, 0, NULL
)) {
348 ilo_builder_batch_restore(&ilo
->cp
->builder
, &snapshot
);
350 /* flush and try again */
351 if (ilo_builder_batch_used(&ilo
->cp
->builder
)) {
352 ilo_cp_submit(ilo
->cp
, "out of aperture");
362 /* sanity check size estimation */
363 assert(before_space
- ilo_cp_space(ilo
->cp
) <= max_len
);
369 ilo_draw_rectlist(struct ilo_context
*ilo
)
371 int max_len
, before_space
;
374 need_flush
= ilo_builder_batch_used(&ilo
->cp
->builder
);
376 ilo_draw_set_owner(ilo
);
378 max_len
= ilo_render_get_rectlist_len(ilo
->render
, ilo
->blitter
);
379 max_len
+= ilo_render_get_flush_len(ilo
->render
) * 2;
381 if (max_len
> ilo_cp_space(ilo
->cp
)) {
382 ilo_cp_submit(ilo
->cp
, "out of space");
384 assert(max_len
<= ilo_cp_space(ilo
->cp
));
387 before_space
= ilo_cp_space(ilo
->cp
);
390 * From the Sandy Bridge PRM, volume 2 part 1, page 313:
392 * "If other rendering operations have preceded this clear, a
393 * PIPE_CONTROL with write cache flush enabled and Z-inhibit
394 * disabled must be issued before the rectangle primitive used for
395 * the depth buffer clear operation."
397 * From the Sandy Bridge PRM, volume 2 part 1, page 314:
399 * "Depth buffer clear pass must be followed by a PIPE_CONTROL
400 * command with DEPTH_STALL bit set and Then followed by Depth
403 * But the pipeline has to be flushed both before and after not only
404 * because of these workarounds. We need them for reasons such as
406 * - we may sample from a texture that was rendered to
407 * - we may sample from the fb shortly after
409 * Skip checking blitter->op and do the flushes.
412 ilo_render_emit_flush(ilo
->render
);
415 struct ilo_builder_snapshot snapshot
;
417 ilo_builder_batch_snapshot(&ilo
->cp
->builder
, &snapshot
);
419 ilo_render_emit_rectlist(ilo
->render
, ilo
->blitter
);
421 if (!ilo_builder_validate(&ilo
->cp
->builder
, 0, NULL
)) {
422 ilo_builder_batch_restore(&ilo
->cp
->builder
, &snapshot
);
424 /* flush and try again */
425 if (ilo_builder_batch_used(&ilo
->cp
->builder
)) {
426 ilo_cp_submit(ilo
->cp
, "out of aperture");
434 ilo_render_invalidate_hw(ilo
->render
);
436 ilo_render_emit_flush(ilo
->render
);
438 /* sanity check size estimation */
439 assert(before_space
- ilo_cp_space(ilo
->cp
) <= max_len
);
443 draw_vbo_with_sw_restart(struct ilo_context
*ilo
,
444 const struct pipe_draw_info
*info
)
446 const struct ilo_ib_state
*ib
= &ilo
->state_vector
.ib
;
454 /* we will draw with IB mapped */
456 u
.ptr
= intel_bo_map(ilo_buffer(ib
->buffer
)->bo
, false);
460 u
.ptr
= ib
->user_buffer
;
466 #define DRAW_VBO_WITH_SW_RESTART(pipe, info, ptr) do { \
467 const unsigned end = (info)->start + (info)->count; \
468 struct pipe_draw_info subinfo; \
472 subinfo.primitive_restart = false; \
473 for (i = (info)->start; i < end; i++) { \
474 if ((ptr)[i] == (info)->restart_index) { \
475 subinfo.count = i - subinfo.start; \
477 (pipe)->draw_vbo(pipe, &subinfo); \
478 subinfo.start = i + 1; \
481 subinfo.count = i - subinfo.start; \
483 (pipe)->draw_vbo(pipe, &subinfo); \
486 switch (ib
->index_size
) {
488 DRAW_VBO_WITH_SW_RESTART(&ilo
->base
, info
, u
.u8
);
491 DRAW_VBO_WITH_SW_RESTART(&ilo
->base
, info
, u
.u16
);
494 DRAW_VBO_WITH_SW_RESTART(&ilo
->base
, info
, u
.u32
);
497 assert(!"unsupported index size");
501 #undef DRAW_VBO_WITH_SW_RESTART
504 intel_bo_unmap(ilo_buffer(ib
->buffer
)->bo
);
508 draw_vbo_need_sw_restart(const struct ilo_context
*ilo
,
509 const struct pipe_draw_info
*info
)
511 /* the restart index is fixed prior to GEN7.5 */
512 if (ilo_dev_gen(ilo
->dev
) < ILO_GEN(7.5)) {
513 const unsigned cut_index
=
514 (ilo
->state_vector
.ib
.index_size
== 1) ? 0xff :
515 (ilo
->state_vector
.ib
.index_size
== 2) ? 0xffff :
516 (ilo
->state_vector
.ib
.index_size
== 4) ? 0xffffffff : 0;
518 if (info
->restart_index
< cut_index
)
522 switch (info
->mode
) {
523 case PIPE_PRIM_POINTS
:
524 case PIPE_PRIM_LINES
:
525 case PIPE_PRIM_LINE_STRIP
:
526 case PIPE_PRIM_TRIANGLES
:
527 case PIPE_PRIM_TRIANGLE_STRIP
:
528 /* these never need software fallback */
530 case PIPE_PRIM_LINE_LOOP
:
531 case PIPE_PRIM_POLYGON
:
532 case PIPE_PRIM_QUAD_STRIP
:
533 case PIPE_PRIM_QUADS
:
534 case PIPE_PRIM_TRIANGLE_FAN
:
535 /* these need software fallback prior to GEN7.5 */
536 return (ilo_dev_gen(ilo
->dev
) < ILO_GEN(7.5));
538 /* the rest always needs software fallback */
544 ilo_draw_vbo(struct pipe_context
*pipe
, const struct pipe_draw_info
*info
)
546 struct ilo_context
*ilo
= ilo_context(pipe
);
548 if (ilo_debug
& ILO_DEBUG_DRAW
) {
550 ilo_printf("indexed draw %s: "
551 "index start %d, count %d, vertex range [%d, %d]\n",
552 u_prim_name(info
->mode
), info
->start
, info
->count
,
553 info
->min_index
, info
->max_index
);
556 ilo_printf("draw %s: vertex start %d, count %d\n",
557 u_prim_name(info
->mode
), info
->start
, info
->count
);
560 ilo_state_vector_dump_dirty(&ilo
->state_vector
);
563 if (ilo_skip_rendering(ilo
))
566 if (info
->primitive_restart
&& info
->indexed
&&
567 draw_vbo_need_sw_restart(ilo
, info
)) {
568 draw_vbo_with_sw_restart(ilo
, info
);
572 ilo_finalize_3d_states(ilo
, info
);
574 ilo_shader_cache_upload(ilo
->shader_cache
, &ilo
->cp
->builder
);
576 ilo_blit_resolve_framebuffer(ilo
);
578 /* If draw_vbo ever fails, return immediately. */
579 if (!draw_vbo(ilo
, &ilo
->state_vector
))
582 /* clear dirty status */
583 ilo
->state_vector
.dirty
= 0x0;
585 /* avoid dangling pointer reference */
586 ilo
->state_vector
.draw
= NULL
;
588 if (ilo_debug
& ILO_DEBUG_NOCACHE
)
589 ilo_render_emit_flush(ilo
->render
);
593 ilo_texture_barrier(struct pipe_context
*pipe
)
595 struct ilo_context
*ilo
= ilo_context(pipe
);
597 if (ilo
->cp
->ring
!= INTEL_RING_RENDER
)
600 ilo_render_emit_flush(ilo
->render
);
603 if (ilo_dev_gen(ilo
->dev
) >= ILO_GEN(7))
604 ilo_cp_submit(ilo
->cp
, "texture barrier");
608 ilo_get_sample_position(struct pipe_context
*pipe
,
609 unsigned sample_count
,
610 unsigned sample_index
,
613 struct ilo_context
*ilo
= ilo_context(pipe
);
615 ilo_render_get_sample_position(ilo
->render
,
616 sample_count
, sample_index
,
617 &out_value
[0], &out_value
[1]);
621 ilo_init_draw(struct ilo_context
*ilo
)
623 ilo
->draw
.cp_owner
.own
= ilo_draw_own_cp
;
624 ilo
->draw
.cp_owner
.release
= ilo_draw_release_cp
;
625 ilo
->draw
.cp_owner
.data
= (void *) ilo
;
626 ilo
->draw
.cp_owner
.reserve
= 0;
628 list_inithead(&ilo
->draw
.queries
);
632 * Initialize 3D-related functions.
635 ilo_init_draw_functions(struct ilo_context
*ilo
)
637 ilo
->base
.draw_vbo
= ilo_draw_vbo
;
638 ilo
->base
.texture_barrier
= ilo_texture_barrier
;
639 ilo
->base
.get_sample_position
= ilo_get_sample_position
;