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 /* \see gen6_get_sample_position() */
44 static const struct sample_position sample_position_1x
[1] = {
48 static const struct sample_position sample_position_4x
[4] = {
49 { 6, 2 }, /* distance from the center is sqrt(40) */
50 { 14, 6 }, /* distance from the center is sqrt(40) */
51 { 2, 10 }, /* distance from the center is sqrt(40) */
52 { 10, 14 }, /* distance from the center is sqrt(40) */
55 static const struct sample_position sample_position_8x
[8] = {
56 { 7, 9 }, /* distance from the center is sqrt(2) */
57 { 9, 13 }, /* distance from the center is sqrt(26) */
58 { 11, 3 }, /* distance from the center is sqrt(34) */
59 { 13, 11 }, /* distance from the center is sqrt(34) */
60 { 1, 7 }, /* distance from the center is sqrt(50) */
61 { 5, 1 }, /* distance from the center is sqrt(58) */
62 { 15, 5 }, /* distance from the center is sqrt(58) */
63 { 3, 15 }, /* distance from the center is sqrt(74) */
67 ilo_render_create(struct ilo_builder
*builder
)
69 struct ilo_render
*render
;
72 render
= CALLOC_STRUCT(ilo_render
);
76 render
->dev
= builder
->dev
;
77 render
->builder
= builder
;
79 render
->workaround_bo
= intel_winsys_alloc_buffer(builder
->winsys
,
80 "PIPE_CONTROL workaround", 4096, false);
81 if (!render
->workaround_bo
) {
82 ilo_warn("failed to allocate PIPE_CONTROL workaround bo\n");
87 render
->packed_sample_position_1x
=
88 sample_position_1x
[0].x
<< 4 |
89 sample_position_1x
[0].y
;
91 /* pack into dwords */
92 for (i
= 0; i
< 4; i
++) {
93 render
->packed_sample_position_4x
|=
94 sample_position_4x
[i
].x
<< (8 * i
+ 4) |
95 sample_position_4x
[i
].y
<< (8 * i
);
97 render
->packed_sample_position_8x
[0] |=
98 sample_position_8x
[i
].x
<< (8 * i
+ 4) |
99 sample_position_8x
[i
].y
<< (8 * i
);
101 render
->packed_sample_position_8x
[1] |=
102 sample_position_8x
[4 + i
].x
<< (8 * i
+ 4) |
103 sample_position_8x
[4 + i
].y
<< (8 * i
);
106 ilo_render_invalidate_hw(render
);
107 ilo_render_invalidate_builder(render
);
113 ilo_render_destroy(struct ilo_render
*render
)
115 if (render
->workaround_bo
)
116 intel_bo_unreference(render
->workaround_bo
);
122 ilo_render_get_sample_position(const struct ilo_render
*render
,
123 unsigned sample_count
,
124 unsigned sample_index
,
127 const struct sample_position
*pos
;
129 switch (sample_count
) {
131 assert(sample_index
< Elements(sample_position_1x
));
132 pos
= sample_position_1x
;
135 assert(sample_index
< Elements(sample_position_4x
));
136 pos
= sample_position_4x
;
139 assert(sample_index
< Elements(sample_position_8x
));
140 pos
= sample_position_8x
;
143 assert(!"unknown sample count");
150 *x
= (float) pos
[sample_index
].x
/ 16.0f
;
151 *y
= (float) pos
[sample_index
].y
/ 16.0f
;
155 ilo_render_invalidate_hw(struct ilo_render
*render
)
157 render
->hw_ctx_changed
= true;
161 ilo_render_invalidate_builder(struct ilo_render
*render
)
163 render
->batch_bo_changed
= true;
164 render
->state_bo_changed
= true;
165 render
->instruction_bo_changed
= true;
167 /* Kernel flushes everything. Shouldn't we set all bits here? */
168 render
->state
.current_pipe_control_dw1
= 0;
172 * Return the command length of ilo_render_emit_flush().
175 ilo_render_get_flush_len(const struct ilo_render
*render
)
179 ILO_DEV_ASSERT(render
->dev
, 6, 7.5);
181 len
= GEN6_PIPE_CONTROL__SIZE
;
183 /* plus gen6_wa_pre_pipe_control() */
184 if (ilo_dev_gen(render
->dev
) == ILO_GEN(6))
191 * Emit PIPE_CONTROLs to flush all caches.
194 ilo_render_emit_flush(struct ilo_render
*render
)
196 const uint32_t dw1
= GEN6_PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE
|
197 GEN6_PIPE_CONTROL_RENDER_CACHE_FLUSH
|
198 GEN6_PIPE_CONTROL_DEPTH_CACHE_FLUSH
|
199 GEN6_PIPE_CONTROL_VF_CACHE_INVALIDATE
|
200 GEN6_PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE
|
201 GEN6_PIPE_CONTROL_CS_STALL
;
202 const unsigned batch_used
= ilo_builder_batch_used(render
->builder
);
204 ILO_DEV_ASSERT(render
->dev
, 6, 7.5);
206 if (ilo_dev_gen(render
->dev
) == ILO_GEN(6))
207 gen6_wa_pre_pipe_control(render
, dw1
);
209 gen6_PIPE_CONTROL(render
->builder
, dw1
, NULL
, 0, false);
211 render
->state
.current_pipe_control_dw1
|= dw1
;
212 render
->state
.deferred_pipe_control_dw1
&= ~dw1
;
214 assert(ilo_builder_batch_used(render
->builder
) <= batch_used
+
215 ilo_render_get_flush_len(render
));
219 * Return the command length of ilo_render_emit_query().
222 ilo_render_get_query_len(const struct ilo_render
*render
,
227 ILO_DEV_ASSERT(render
->dev
, 6, 7.5);
229 /* always a flush or a variant of flush */
230 len
= ilo_render_get_flush_len(render
);
232 switch (query_type
) {
233 case PIPE_QUERY_OCCLUSION_COUNTER
:
234 case PIPE_QUERY_TIMESTAMP
:
235 case PIPE_QUERY_TIME_ELAPSED
:
238 case PIPE_QUERY_PRIMITIVES_GENERATED
:
239 case PIPE_QUERY_PRIMITIVES_EMITTED
:
240 len
+= GEN6_MI_STORE_REGISTER_MEM__SIZE
* 2;
242 case PIPE_QUERY_PIPELINE_STATISTICS
:
245 (ilo_dev_gen(render
->dev
) >= ILO_GEN(7)) ? 10 : 8;
247 (ilo_dev_gen(render
->dev
) >= ILO_GEN(7)) ? 1 : 3;
249 len
+= GEN6_MI_STORE_REGISTER_MEM__SIZE
* 2 * num_regs
+
250 GEN6_MI_STORE_DATA_IMM__SIZE
* num_pads
;
262 * Emit PIPE_CONTROLs or MI_STORE_REGISTER_MEMs to store register values.
265 ilo_render_emit_query(struct ilo_render
*render
,
266 struct ilo_query
*q
, uint32_t offset
)
268 const uint32_t pipeline_statistics_regs
[11] = {
269 GEN6_REG_IA_VERTICES_COUNT
,
270 GEN6_REG_IA_PRIMITIVES_COUNT
,
271 GEN6_REG_VS_INVOCATION_COUNT
,
272 GEN6_REG_GS_INVOCATION_COUNT
,
273 GEN6_REG_GS_PRIMITIVES_COUNT
,
274 GEN6_REG_CL_INVOCATION_COUNT
,
275 GEN6_REG_CL_PRIMITIVES_COUNT
,
276 GEN6_REG_PS_INVOCATION_COUNT
,
277 (ilo_dev_gen(render
->dev
) >= ILO_GEN(7)) ?
278 GEN7_REG_HS_INVOCATION_COUNT
: 0,
279 (ilo_dev_gen(render
->dev
) >= ILO_GEN(7)) ?
280 GEN7_REG_DS_INVOCATION_COUNT
: 0,
283 const uint32_t primitives_generated_reg
=
284 (ilo_dev_gen(render
->dev
) >= ILO_GEN(7) && q
->index
> 0) ?
285 GEN7_REG_SO_PRIM_STORAGE_NEEDED(q
->index
) :
286 GEN6_REG_CL_INVOCATION_COUNT
;
287 const uint32_t primitives_emitted_reg
=
288 (ilo_dev_gen(render
->dev
) >= ILO_GEN(7)) ?
289 GEN7_REG_SO_NUM_PRIMS_WRITTEN(q
->index
) :
290 GEN6_REG_SO_NUM_PRIMS_WRITTEN
;
291 const unsigned batch_used
= ilo_builder_batch_used(render
->builder
);
292 const uint32_t *regs
;
293 int reg_count
= 0, i
;
294 uint32_t pipe_control_dw1
= 0;
296 ILO_DEV_ASSERT(render
->dev
, 6, 7.5);
299 case PIPE_QUERY_OCCLUSION_COUNTER
:
300 pipe_control_dw1
= GEN6_PIPE_CONTROL_DEPTH_STALL
|
301 GEN6_PIPE_CONTROL_WRITE_PS_DEPTH_COUNT
;
303 case PIPE_QUERY_TIMESTAMP
:
304 case PIPE_QUERY_TIME_ELAPSED
:
305 pipe_control_dw1
= GEN6_PIPE_CONTROL_WRITE_TIMESTAMP
;
307 case PIPE_QUERY_PRIMITIVES_GENERATED
:
308 regs
= &primitives_generated_reg
;
311 case PIPE_QUERY_PRIMITIVES_EMITTED
:
312 regs
= &primitives_emitted_reg
;
315 case PIPE_QUERY_PIPELINE_STATISTICS
:
316 regs
= pipeline_statistics_regs
;
317 reg_count
= Elements(pipeline_statistics_regs
);
323 if (pipe_control_dw1
) {
326 if (ilo_dev_gen(render
->dev
) == ILO_GEN(6))
327 gen6_wa_pre_pipe_control(render
, pipe_control_dw1
);
329 gen6_PIPE_CONTROL(render
->builder
, pipe_control_dw1
,
330 q
->bo
, offset
, true);
332 render
->state
.current_pipe_control_dw1
|= pipe_control_dw1
;
333 render
->state
.deferred_pipe_control_dw1
&= ~pipe_control_dw1
;
334 } else if (reg_count
) {
335 ilo_render_emit_flush(render
);
338 for (i
= 0; i
< reg_count
; i
++) {
340 /* store lower 32 bits */
341 gen6_MI_STORE_REGISTER_MEM(render
->builder
, q
->bo
, offset
, regs
[i
]);
342 /* store higher 32 bits */
343 gen6_MI_STORE_REGISTER_MEM(render
->builder
, q
->bo
,
344 offset
+ 4, regs
[i
] + 4);
346 gen6_MI_STORE_DATA_IMM(render
->builder
, q
->bo
, offset
, 0, true);
352 assert(ilo_builder_batch_used(render
->builder
) <= batch_used
+
353 ilo_render_get_query_len(render
, q
->type
));
357 ilo_render_get_rectlist_len(const struct ilo_render
*render
,
358 const struct ilo_blitter
*blitter
)
360 ILO_DEV_ASSERT(render
->dev
, 6, 7.5);
362 return ilo_render_get_rectlist_dynamic_states_len(render
, blitter
) +
363 ilo_render_get_rectlist_commands_len(render
, blitter
);
367 ilo_render_emit_rectlist(struct ilo_render
*render
,
368 const struct ilo_blitter
*blitter
)
370 struct ilo_render_rectlist_session session
;
372 ILO_DEV_ASSERT(render
->dev
, 6, 7.5);
374 memset(&session
, 0, sizeof(session
));
375 ilo_render_emit_rectlist_dynamic_states(render
, blitter
, &session
);
376 ilo_render_emit_rectlist_commands(render
, blitter
, &session
);
380 ilo_render_get_draw_len(const struct ilo_render
*render
,
381 const struct ilo_state_vector
*vec
)
383 ILO_DEV_ASSERT(render
->dev
, 6, 7.5);
385 return ilo_render_get_draw_dynamic_states_len(render
, vec
) +
386 ilo_render_get_draw_surface_states_len(render
, vec
) +
387 ilo_render_get_draw_commands_len(render
, vec
);
391 draw_session_prepare(struct ilo_render
*render
,
392 const struct ilo_state_vector
*vec
,
393 struct ilo_render_draw_session
*session
)
395 memset(session
, 0, sizeof(*session
));
396 session
->pipe_dirty
= vec
->dirty
;
397 session
->reduced_prim
= u_reduced_prim(vec
->draw
->mode
);
399 if (render
->hw_ctx_changed
) {
400 /* these should be enough to make everything uploaded */
401 render
->batch_bo_changed
= true;
402 render
->state_bo_changed
= true;
403 render
->instruction_bo_changed
= true;
405 session
->prim_changed
= true;
406 session
->primitive_restart_changed
= true;
408 session
->prim_changed
=
409 (render
->state
.reduced_prim
!= session
->reduced_prim
);
410 session
->primitive_restart_changed
=
411 (render
->state
.primitive_restart
!= vec
->draw
->primitive_restart
);
416 draw_session_end(struct ilo_render
*render
,
417 const struct ilo_state_vector
*vec
,
418 struct ilo_render_draw_session
*session
)
420 render
->hw_ctx_changed
= false;
422 render
->batch_bo_changed
= false;
423 render
->state_bo_changed
= false;
424 render
->instruction_bo_changed
= false;
426 render
->state
.reduced_prim
= session
->reduced_prim
;
427 render
->state
.primitive_restart
= vec
->draw
->primitive_restart
;
431 ilo_render_emit_draw(struct ilo_render
*render
,
432 const struct ilo_state_vector
*vec
)
434 struct ilo_render_draw_session session
;
436 ILO_DEV_ASSERT(render
->dev
, 6, 7.5);
438 draw_session_prepare(render
, vec
, &session
);
440 /* force all states to be uploaded if the state bo changed */
441 if (render
->state_bo_changed
)
442 session
.pipe_dirty
= ILO_DIRTY_ALL
;
444 session
.pipe_dirty
= vec
->dirty
;
446 ilo_render_emit_draw_dynamic_states(render
, vec
, &session
);
447 ilo_render_emit_draw_surface_states(render
, vec
, &session
);
449 /* force all commands to be uploaded if the HW context changed */
450 if (render
->hw_ctx_changed
)
451 session
.pipe_dirty
= ILO_DIRTY_ALL
;
453 session
.pipe_dirty
= vec
->dirty
;
455 ilo_render_emit_draw_commands(render
, vec
, &session
);
457 draw_session_end(render
, vec
, &session
);
461 ilo_render_get_launch_grid_len(const struct ilo_render
*render
,
462 const struct ilo_state_vector
*vec
)
464 ILO_DEV_ASSERT(render
->dev
, 7, 7.5);
466 return ilo_render_get_launch_grid_surface_states_len(render
, vec
) +
467 ilo_render_get_launch_grid_dynamic_states_len(render
, vec
) +
468 ilo_render_get_launch_grid_commands_len(render
, vec
);
472 ilo_render_emit_launch_grid(struct ilo_render
*render
,
473 const struct ilo_state_vector
*vec
,
474 const unsigned thread_group_offset
[3],
475 const unsigned thread_group_dim
[3],
476 unsigned thread_group_size
,
477 const struct pipe_constant_buffer
*input
,
480 struct ilo_render_launch_grid_session session
;
482 ILO_DEV_ASSERT(render
->dev
, 7, 7.5);
484 assert(input
->buffer
);
486 memset(&session
, 0, sizeof(session
));
488 session
.thread_group_offset
= thread_group_offset
;
489 session
.thread_group_dim
= thread_group_dim
;
490 session
.thread_group_size
= thread_group_size
;
491 session
.input
= input
;
494 ilo_render_emit_launch_grid_surface_states(render
, vec
, &session
);
495 ilo_render_emit_launch_grid_dynamic_states(render
, vec
, &session
);
496 ilo_render_emit_launch_grid_commands(render
, vec
, &session
);