2 * Mesa 3-D graphics library
4 * Copyright (C) 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 "genhw/genhw.h"
29 #include "util/u_prim.h"
30 #include "intel_winsys.h"
32 #include "ilo_builder.h"
33 #include "ilo_builder_mi.h"
34 #include "ilo_builder_render.h"
35 #include "ilo_query.h"
36 #include "ilo_render_gen.h"
39 struct sample_position
{
43 static const struct sample_position ilo_sample_pattern_1x
[1] = {
47 static const struct sample_position ilo_sample_pattern_4x
[4] = {
54 /* \see brw_multisample_positions_8x */
55 static const struct sample_position ilo_sample_pattern_8x
[8] = {
67 pack_sample_position(const struct sample_position
*pos
)
69 return (pos
->x
+ 8) << 4 | (pos
->y
+ 8);
73 get_sample_position(const struct sample_position
*pos
, float *x
, float *y
)
75 *x
= (float) (pos
->x
+ 8) / 16.0f
;
76 *y
= (float) (pos
->y
+ 8) / 16.0f
;
80 ilo_render_create(struct ilo_builder
*builder
)
82 struct ilo_render
*render
;
85 render
= CALLOC_STRUCT(ilo_render
);
89 render
->dev
= builder
->dev
;
90 render
->builder
= builder
;
92 render
->workaround_bo
= intel_winsys_alloc_buffer(builder
->winsys
,
93 "PIPE_CONTROL workaround", 4096, false);
94 if (!render
->workaround_bo
) {
95 ilo_warn("failed to allocate PIPE_CONTROL workaround bo\n");
100 /* pack into dwords */
101 render
->sample_pattern_1x
= pack_sample_position(ilo_sample_pattern_1x
);
102 for (i
= 0; i
< 4; i
++) {
103 render
->sample_pattern_4x
|=
104 pack_sample_position(&ilo_sample_pattern_4x
[i
]) << (8 * i
);
106 render
->sample_pattern_8x
[0] |=
107 pack_sample_position(&ilo_sample_pattern_8x
[i
]) << (8 * i
);
108 render
->sample_pattern_8x
[1] |=
109 pack_sample_position(&ilo_sample_pattern_8x
[i
+ 4]) << (8 * i
);
112 ilo_render_invalidate_hw(render
);
113 ilo_render_invalidate_builder(render
);
119 ilo_render_destroy(struct ilo_render
*render
)
121 if (render
->workaround_bo
)
122 intel_bo_unreference(render
->workaround_bo
);
128 ilo_render_get_sample_position(const struct ilo_render
*render
,
129 unsigned sample_count
,
130 unsigned sample_index
,
133 const struct sample_position
*pattern
;
135 switch (sample_count
) {
137 assert(sample_index
< Elements(ilo_sample_pattern_1x
));
138 pattern
= ilo_sample_pattern_1x
;
141 assert(sample_index
< Elements(ilo_sample_pattern_4x
));
142 pattern
= ilo_sample_pattern_4x
;
145 assert(sample_index
< Elements(ilo_sample_pattern_8x
));
146 pattern
= ilo_sample_pattern_8x
;
149 assert(!"unknown sample count");
156 get_sample_position(&pattern
[sample_index
], x
, y
);
160 ilo_render_invalidate_hw(struct ilo_render
*render
)
162 render
->hw_ctx_changed
= true;
166 ilo_render_invalidate_builder(struct ilo_render
*render
)
168 render
->batch_bo_changed
= true;
169 render
->state_bo_changed
= true;
170 render
->instruction_bo_changed
= true;
172 /* Kernel flushes everything. Shouldn't we set all bits here? */
173 render
->state
.current_pipe_control_dw1
= 0;
177 * Return the command length of ilo_render_emit_flush().
180 ilo_render_get_flush_len(const struct ilo_render
*render
)
184 ILO_DEV_ASSERT(render
->dev
, 6, 7.5);
186 len
= GEN6_PIPE_CONTROL__SIZE
;
188 /* plus gen6_wa_pre_pipe_control() */
189 if (ilo_dev_gen(render
->dev
) == ILO_GEN(6))
196 * Emit PIPE_CONTROLs to flush all caches.
199 ilo_render_emit_flush(struct ilo_render
*render
)
201 const uint32_t dw1
= GEN6_PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE
|
202 GEN6_PIPE_CONTROL_RENDER_CACHE_FLUSH
|
203 GEN6_PIPE_CONTROL_DEPTH_CACHE_FLUSH
|
204 GEN6_PIPE_CONTROL_VF_CACHE_INVALIDATE
|
205 GEN6_PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE
|
206 GEN6_PIPE_CONTROL_CS_STALL
;
207 const unsigned batch_used
= ilo_builder_batch_used(render
->builder
);
209 ILO_DEV_ASSERT(render
->dev
, 6, 7.5);
211 if (ilo_dev_gen(render
->dev
) == ILO_GEN(6))
212 gen6_wa_pre_pipe_control(render
, dw1
);
214 gen6_PIPE_CONTROL(render
->builder
, dw1
, NULL
, 0, false);
216 render
->state
.current_pipe_control_dw1
|= dw1
;
217 render
->state
.deferred_pipe_control_dw1
&= ~dw1
;
219 assert(ilo_builder_batch_used(render
->builder
) <= batch_used
+
220 ilo_render_get_flush_len(render
));
224 * Return the command length of ilo_render_emit_query().
227 ilo_render_get_query_len(const struct ilo_render
*render
,
232 ILO_DEV_ASSERT(render
->dev
, 6, 7.5);
234 /* always a flush or a variant of flush */
235 len
= ilo_render_get_flush_len(render
);
237 switch (query_type
) {
238 case PIPE_QUERY_OCCLUSION_COUNTER
:
239 case PIPE_QUERY_TIMESTAMP
:
240 case PIPE_QUERY_TIME_ELAPSED
:
243 case PIPE_QUERY_PRIMITIVES_GENERATED
:
244 case PIPE_QUERY_PRIMITIVES_EMITTED
:
245 len
+= GEN6_MI_STORE_REGISTER_MEM__SIZE
* 2;
247 case PIPE_QUERY_PIPELINE_STATISTICS
:
250 (ilo_dev_gen(render
->dev
) >= ILO_GEN(7)) ? 10 : 8;
252 (ilo_dev_gen(render
->dev
) >= ILO_GEN(7)) ? 1 : 3;
254 len
+= GEN6_MI_STORE_REGISTER_MEM__SIZE
* 2 * num_regs
+
255 GEN6_MI_STORE_DATA_IMM__SIZE
* num_pads
;
267 * Emit PIPE_CONTROLs or MI_STORE_REGISTER_MEMs to store register values.
270 ilo_render_emit_query(struct ilo_render
*render
,
271 struct ilo_query
*q
, uint32_t offset
)
273 const uint32_t pipeline_statistics_regs
[11] = {
274 GEN6_REG_IA_VERTICES_COUNT
,
275 GEN6_REG_IA_PRIMITIVES_COUNT
,
276 GEN6_REG_VS_INVOCATION_COUNT
,
277 GEN6_REG_GS_INVOCATION_COUNT
,
278 GEN6_REG_GS_PRIMITIVES_COUNT
,
279 GEN6_REG_CL_INVOCATION_COUNT
,
280 GEN6_REG_CL_PRIMITIVES_COUNT
,
281 GEN6_REG_PS_INVOCATION_COUNT
,
282 (ilo_dev_gen(render
->dev
) >= ILO_GEN(7)) ?
283 GEN7_REG_HS_INVOCATION_COUNT
: 0,
284 (ilo_dev_gen(render
->dev
) >= ILO_GEN(7)) ?
285 GEN7_REG_DS_INVOCATION_COUNT
: 0,
288 const uint32_t primitives_generated_reg
=
289 (ilo_dev_gen(render
->dev
) >= ILO_GEN(7) && q
->index
> 0) ?
290 GEN7_REG_SO_PRIM_STORAGE_NEEDED(q
->index
) :
291 GEN6_REG_CL_INVOCATION_COUNT
;
292 const uint32_t primitives_emitted_reg
=
293 (ilo_dev_gen(render
->dev
) >= ILO_GEN(7)) ?
294 GEN7_REG_SO_NUM_PRIMS_WRITTEN(q
->index
) :
295 GEN6_REG_SO_NUM_PRIMS_WRITTEN
;
296 const unsigned batch_used
= ilo_builder_batch_used(render
->builder
);
297 const uint32_t *regs
;
298 int reg_count
= 0, i
;
299 uint32_t pipe_control_dw1
= 0;
301 ILO_DEV_ASSERT(render
->dev
, 6, 7.5);
304 case PIPE_QUERY_OCCLUSION_COUNTER
:
305 pipe_control_dw1
= GEN6_PIPE_CONTROL_DEPTH_STALL
|
306 GEN6_PIPE_CONTROL_WRITE_PS_DEPTH_COUNT
;
308 case PIPE_QUERY_TIMESTAMP
:
309 case PIPE_QUERY_TIME_ELAPSED
:
310 pipe_control_dw1
= GEN6_PIPE_CONTROL_WRITE_TIMESTAMP
;
312 case PIPE_QUERY_PRIMITIVES_GENERATED
:
313 regs
= &primitives_generated_reg
;
316 case PIPE_QUERY_PRIMITIVES_EMITTED
:
317 regs
= &primitives_emitted_reg
;
320 case PIPE_QUERY_PIPELINE_STATISTICS
:
321 regs
= pipeline_statistics_regs
;
322 reg_count
= Elements(pipeline_statistics_regs
);
328 if (pipe_control_dw1
) {
331 if (ilo_dev_gen(render
->dev
) == ILO_GEN(6))
332 gen6_wa_pre_pipe_control(render
, pipe_control_dw1
);
334 gen6_PIPE_CONTROL(render
->builder
, pipe_control_dw1
,
335 q
->bo
, offset
, true);
337 render
->state
.current_pipe_control_dw1
|= pipe_control_dw1
;
338 render
->state
.deferred_pipe_control_dw1
&= ~pipe_control_dw1
;
339 } else if (reg_count
) {
340 ilo_render_emit_flush(render
);
343 for (i
= 0; i
< reg_count
; i
++) {
345 /* store lower 32 bits */
346 gen6_MI_STORE_REGISTER_MEM(render
->builder
, regs
[i
], q
->bo
, offset
);
347 /* store higher 32 bits */
348 gen6_MI_STORE_REGISTER_MEM(render
->builder
, regs
[i
] + 4,
351 gen6_MI_STORE_DATA_IMM(render
->builder
, q
->bo
, offset
, 0);
357 assert(ilo_builder_batch_used(render
->builder
) <= batch_used
+
358 ilo_render_get_query_len(render
, q
->type
));
362 ilo_render_get_rectlist_len(const struct ilo_render
*render
,
363 const struct ilo_blitter
*blitter
)
365 ILO_DEV_ASSERT(render
->dev
, 6, 7.5);
367 return ilo_render_get_rectlist_dynamic_states_len(render
, blitter
) +
368 ilo_render_get_rectlist_commands_len(render
, blitter
);
372 ilo_render_emit_rectlist(struct ilo_render
*render
,
373 const struct ilo_blitter
*blitter
)
375 struct ilo_render_rectlist_session session
;
377 ILO_DEV_ASSERT(render
->dev
, 6, 7.5);
379 memset(&session
, 0, sizeof(session
));
380 ilo_render_emit_rectlist_dynamic_states(render
, blitter
, &session
);
381 ilo_render_emit_rectlist_commands(render
, blitter
, &session
);
385 ilo_render_get_draw_len(const struct ilo_render
*render
,
386 const struct ilo_state_vector
*vec
)
388 ILO_DEV_ASSERT(render
->dev
, 6, 7.5);
390 return ilo_render_get_draw_dynamic_states_len(render
, vec
) +
391 ilo_render_get_draw_surface_states_len(render
, vec
) +
392 ilo_render_get_draw_commands_len(render
, vec
);
396 draw_session_prepare(struct ilo_render
*render
,
397 const struct ilo_state_vector
*vec
,
398 struct ilo_render_draw_session
*session
)
400 memset(session
, 0, sizeof(*session
));
401 session
->pipe_dirty
= vec
->dirty
;
402 session
->reduced_prim
= u_reduced_prim(vec
->draw
->mode
);
404 if (render
->hw_ctx_changed
) {
405 /* these should be enough to make everything uploaded */
406 render
->batch_bo_changed
= true;
407 render
->state_bo_changed
= true;
408 render
->instruction_bo_changed
= true;
410 session
->prim_changed
= true;
411 session
->primitive_restart_changed
= true;
413 session
->prim_changed
=
414 (render
->state
.reduced_prim
!= session
->reduced_prim
);
415 session
->primitive_restart_changed
=
416 (render
->state
.primitive_restart
!= vec
->draw
->primitive_restart
);
421 draw_session_end(struct ilo_render
*render
,
422 const struct ilo_state_vector
*vec
,
423 struct ilo_render_draw_session
*session
)
425 render
->hw_ctx_changed
= false;
427 render
->batch_bo_changed
= false;
428 render
->state_bo_changed
= false;
429 render
->instruction_bo_changed
= false;
431 render
->state
.reduced_prim
= session
->reduced_prim
;
432 render
->state
.primitive_restart
= vec
->draw
->primitive_restart
;
436 ilo_render_emit_draw(struct ilo_render
*render
,
437 const struct ilo_state_vector
*vec
)
439 struct ilo_render_draw_session session
;
441 ILO_DEV_ASSERT(render
->dev
, 6, 7.5);
443 draw_session_prepare(render
, vec
, &session
);
445 /* force all states to be uploaded if the state bo changed */
446 if (render
->state_bo_changed
)
447 session
.pipe_dirty
= ILO_DIRTY_ALL
;
449 session
.pipe_dirty
= vec
->dirty
;
451 ilo_render_emit_draw_dynamic_states(render
, vec
, &session
);
452 ilo_render_emit_draw_surface_states(render
, vec
, &session
);
454 /* force all commands to be uploaded if the HW context changed */
455 if (render
->hw_ctx_changed
)
456 session
.pipe_dirty
= ILO_DIRTY_ALL
;
458 session
.pipe_dirty
= vec
->dirty
;
460 ilo_render_emit_draw_commands(render
, vec
, &session
);
462 draw_session_end(render
, vec
, &session
);
466 ilo_render_get_launch_grid_len(const struct ilo_render
*render
,
467 const struct ilo_state_vector
*vec
)
469 ILO_DEV_ASSERT(render
->dev
, 7, 7.5);
471 return ilo_render_get_launch_grid_surface_states_len(render
, vec
) +
472 ilo_render_get_launch_grid_dynamic_states_len(render
, vec
) +
473 ilo_render_get_launch_grid_commands_len(render
, vec
);
477 ilo_render_emit_launch_grid(struct ilo_render
*render
,
478 const struct ilo_state_vector
*vec
,
479 const unsigned thread_group_offset
[3],
480 const unsigned thread_group_dim
[3],
481 unsigned thread_group_size
,
482 const struct pipe_constant_buffer
*input
,
485 struct ilo_render_launch_grid_session session
;
487 ILO_DEV_ASSERT(render
->dev
, 7, 7.5);
489 assert(input
->buffer
);
491 memset(&session
, 0, sizeof(session
));
493 session
.thread_group_offset
= thread_group_offset
;
494 session
.thread_group_dim
= thread_group_dim
;
495 session
.thread_group_size
= thread_group_size
;
496 session
.input
= input
;
499 ilo_render_emit_launch_grid_surface_states(render
, vec
, &session
);
500 ilo_render_emit_launch_grid_dynamic_states(render
, vec
, &session
);
501 ilo_render_emit_launch_grid_commands(render
, vec
, &session
);