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 "core/ilo_builder.h"
30 #include "core/ilo_builder_mi.h"
31 #include "core/ilo_builder_render.h"
32 #include "core/intel_winsys.h"
33 #include "util/u_prim.h"
35 #include "ilo_query.h"
36 #include "ilo_render_gen.h"
39 ilo_render_create(struct ilo_builder
*builder
)
41 struct ilo_render
*render
;
43 render
= CALLOC_STRUCT(ilo_render
);
47 render
->dev
= builder
->dev
;
48 render
->builder
= builder
;
50 render
->workaround_bo
= intel_winsys_alloc_bo(builder
->winsys
,
51 "PIPE_CONTROL workaround", 4096, false);
52 if (!render
->workaround_bo
) {
53 ilo_warn("failed to allocate PIPE_CONTROL workaround bo\n");
58 ilo_state_sample_pattern_init_default(&render
->sample_pattern
,
61 ilo_render_invalidate_hw(render
);
62 ilo_render_invalidate_builder(render
);
68 ilo_render_destroy(struct ilo_render
*render
)
70 intel_bo_unref(render
->vs_scratch
.bo
);
71 intel_bo_unref(render
->gs_scratch
.bo
);
72 intel_bo_unref(render
->fs_scratch
.bo
);
74 intel_bo_unref(render
->workaround_bo
);
79 resize_scratch_space(struct ilo_render
*render
,
80 struct ilo_render_scratch_space
*scratch
,
81 const char *name
, int new_size
)
85 if (scratch
->size
>= new_size
)
88 bo
= intel_winsys_alloc_bo(render
->builder
->winsys
, name
, new_size
, false);
92 intel_bo_unref(scratch
->bo
);
94 scratch
->size
= new_size
;
100 ilo_render_prepare_scratch_spaces(struct ilo_render
*render
,
105 return (resize_scratch_space(render
, &render
->vs_scratch
,
106 "vs scratch", vs_scratch_size
) &&
107 resize_scratch_space(render
, &render
->gs_scratch
,
108 "gs scratch", gs_scratch_size
) &&
109 resize_scratch_space(render
, &render
->fs_scratch
,
110 "fs scratch", fs_scratch_size
));
114 ilo_render_get_sample_position(const struct ilo_render
*render
,
115 unsigned sample_count
,
116 unsigned sample_index
,
119 uint8_t off_x
, off_y
;
121 ilo_state_sample_pattern_get_offset(&render
->sample_pattern
, render
->dev
,
122 sample_count
, sample_index
, &off_x
, &off_y
);
124 *x
= (float) off_x
/ 16.0f
;
125 *y
= (float) off_y
/ 16.0f
;
129 ilo_render_invalidate_hw(struct ilo_render
*render
)
131 render
->hw_ctx_changed
= true;
135 ilo_render_invalidate_builder(struct ilo_render
*render
)
137 render
->batch_bo_changed
= true;
138 render
->state_bo_changed
= true;
139 render
->instruction_bo_changed
= true;
141 /* Kernel flushes everything. Shouldn't we set all bits here? */
142 render
->state
.current_pipe_control_dw1
= 0;
146 * Return the command length of ilo_render_emit_flush().
149 ilo_render_get_flush_len(const struct ilo_render
*render
)
153 ILO_DEV_ASSERT(render
->dev
, 6, 8);
155 len
= GEN6_PIPE_CONTROL__SIZE
;
157 /* plus gen6_wa_pre_pipe_control() */
158 if (ilo_dev_gen(render
->dev
) == ILO_GEN(6))
165 * Emit PIPE_CONTROLs to flush all caches.
168 ilo_render_emit_flush(struct ilo_render
*render
)
170 const uint32_t dw1
= GEN6_PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE
|
171 GEN6_PIPE_CONTROL_RENDER_CACHE_FLUSH
|
172 GEN6_PIPE_CONTROL_DEPTH_CACHE_FLUSH
|
173 GEN6_PIPE_CONTROL_VF_CACHE_INVALIDATE
|
174 GEN6_PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE
|
175 GEN6_PIPE_CONTROL_CS_STALL
;
176 const unsigned batch_used
= ilo_builder_batch_used(render
->builder
);
178 ILO_DEV_ASSERT(render
->dev
, 6, 8);
180 if (ilo_dev_gen(render
->dev
) == ILO_GEN(6))
181 gen6_wa_pre_pipe_control(render
, dw1
);
183 ilo_render_pipe_control(render
, dw1
);
185 assert(ilo_builder_batch_used(render
->builder
) <= batch_used
+
186 ilo_render_get_flush_len(render
));
190 * Return the command length of ilo_render_emit_query().
193 ilo_render_get_query_len(const struct ilo_render
*render
,
198 ILO_DEV_ASSERT(render
->dev
, 6, 8);
200 /* always a flush or a variant of flush */
201 len
= ilo_render_get_flush_len(render
);
203 switch (query_type
) {
204 case PIPE_QUERY_OCCLUSION_COUNTER
:
205 case PIPE_QUERY_TIMESTAMP
:
206 case PIPE_QUERY_TIME_ELAPSED
:
209 case PIPE_QUERY_PRIMITIVES_GENERATED
:
210 case PIPE_QUERY_PRIMITIVES_EMITTED
:
211 len
+= GEN6_MI_STORE_REGISTER_MEM__SIZE
* 2;
213 case PIPE_QUERY_PIPELINE_STATISTICS
:
216 (ilo_dev_gen(render
->dev
) >= ILO_GEN(7)) ? 10 : 8;
218 (ilo_dev_gen(render
->dev
) >= ILO_GEN(7)) ? 1 : 3;
220 len
+= GEN6_MI_STORE_REGISTER_MEM__SIZE
* 2 * num_regs
+
221 GEN6_MI_STORE_DATA_IMM__SIZE
* num_pads
;
233 * Emit PIPE_CONTROLs or MI_STORE_REGISTER_MEMs to store register values.
236 ilo_render_emit_query(struct ilo_render
*render
,
237 struct ilo_query
*q
, uint32_t offset
)
239 const uint32_t pipeline_statistics_regs
[11] = {
240 GEN6_REG_IA_VERTICES_COUNT
,
241 GEN6_REG_IA_PRIMITIVES_COUNT
,
242 GEN6_REG_VS_INVOCATION_COUNT
,
243 GEN6_REG_GS_INVOCATION_COUNT
,
244 GEN6_REG_GS_PRIMITIVES_COUNT
,
245 GEN6_REG_CL_INVOCATION_COUNT
,
246 GEN6_REG_CL_PRIMITIVES_COUNT
,
247 GEN6_REG_PS_INVOCATION_COUNT
,
248 (ilo_dev_gen(render
->dev
) >= ILO_GEN(7)) ?
249 GEN7_REG_HS_INVOCATION_COUNT
: 0,
250 (ilo_dev_gen(render
->dev
) >= ILO_GEN(7)) ?
251 GEN7_REG_DS_INVOCATION_COUNT
: 0,
254 const uint32_t primitives_generated_reg
=
255 (ilo_dev_gen(render
->dev
) >= ILO_GEN(7) && q
->index
> 0) ?
256 GEN7_REG_SO_PRIM_STORAGE_NEEDED(q
->index
) :
257 GEN6_REG_CL_INVOCATION_COUNT
;
258 const uint32_t primitives_emitted_reg
=
259 (ilo_dev_gen(render
->dev
) >= ILO_GEN(7)) ?
260 GEN7_REG_SO_NUM_PRIMS_WRITTEN(q
->index
) :
261 GEN6_REG_SO_NUM_PRIMS_WRITTEN
;
262 const unsigned batch_used
= ilo_builder_batch_used(render
->builder
);
263 const uint32_t *regs
;
264 int reg_count
= 0, i
;
265 uint32_t pipe_control_dw1
= 0;
267 ILO_DEV_ASSERT(render
->dev
, 6, 8);
270 case PIPE_QUERY_OCCLUSION_COUNTER
:
271 pipe_control_dw1
= GEN6_PIPE_CONTROL_DEPTH_STALL
|
272 GEN6_PIPE_CONTROL_WRITE_PS_DEPTH_COUNT
;
274 case PIPE_QUERY_TIMESTAMP
:
275 case PIPE_QUERY_TIME_ELAPSED
:
276 pipe_control_dw1
= GEN6_PIPE_CONTROL_WRITE_TIMESTAMP
;
278 case PIPE_QUERY_PRIMITIVES_GENERATED
:
279 regs
= &primitives_generated_reg
;
282 case PIPE_QUERY_PRIMITIVES_EMITTED
:
283 regs
= &primitives_emitted_reg
;
286 case PIPE_QUERY_PIPELINE_STATISTICS
:
287 regs
= pipeline_statistics_regs
;
288 reg_count
= Elements(pipeline_statistics_regs
);
294 if (pipe_control_dw1
) {
297 if (ilo_dev_gen(render
->dev
) == ILO_GEN(6))
298 gen6_wa_pre_pipe_control(render
, pipe_control_dw1
);
300 gen6_PIPE_CONTROL(render
->builder
, pipe_control_dw1
, q
->bo
, offset
, 0);
302 render
->state
.current_pipe_control_dw1
|= pipe_control_dw1
;
303 render
->state
.deferred_pipe_control_dw1
&= ~pipe_control_dw1
;
304 } else if (reg_count
) {
305 ilo_render_emit_flush(render
);
308 for (i
= 0; i
< reg_count
; i
++) {
310 /* store lower 32 bits */
311 gen6_MI_STORE_REGISTER_MEM(render
->builder
, regs
[i
], q
->bo
, offset
);
312 /* store higher 32 bits */
313 gen6_MI_STORE_REGISTER_MEM(render
->builder
, regs
[i
] + 4,
316 gen6_MI_STORE_DATA_IMM(render
->builder
, q
->bo
, offset
, 0);
322 assert(ilo_builder_batch_used(render
->builder
) <= batch_used
+
323 ilo_render_get_query_len(render
, q
->type
));
327 ilo_render_get_rectlist_len(const struct ilo_render
*render
,
328 const struct ilo_blitter
*blitter
)
330 ILO_DEV_ASSERT(render
->dev
, 6, 8);
332 return ilo_render_get_rectlist_dynamic_states_len(render
, blitter
) +
333 ilo_render_get_rectlist_commands_len(render
, blitter
);
337 ilo_render_emit_rectlist(struct ilo_render
*render
,
338 const struct ilo_blitter
*blitter
)
340 struct ilo_render_rectlist_session session
;
342 ILO_DEV_ASSERT(render
->dev
, 6, 8);
344 memset(&session
, 0, sizeof(session
));
345 ilo_render_emit_rectlist_dynamic_states(render
, blitter
, &session
);
346 ilo_render_emit_rectlist_commands(render
, blitter
, &session
);
350 ilo_render_get_draw_len(const struct ilo_render
*render
,
351 const struct ilo_state_vector
*vec
)
353 ILO_DEV_ASSERT(render
->dev
, 6, 8);
355 return ilo_render_get_draw_dynamic_states_len(render
, vec
) +
356 ilo_render_get_draw_surface_states_len(render
, vec
) +
357 ilo_render_get_draw_commands_len(render
, vec
);
361 draw_session_prepare(struct ilo_render
*render
,
362 const struct ilo_state_vector
*vec
,
363 struct ilo_render_draw_session
*session
)
365 memset(session
, 0, sizeof(*session
));
366 session
->pipe_dirty
= vec
->dirty
;
367 session
->reduced_prim
= u_reduced_prim(vec
->draw
->mode
);
369 if (render
->hw_ctx_changed
) {
370 /* these should be enough to make everything uploaded */
371 render
->batch_bo_changed
= true;
372 render
->state_bo_changed
= true;
373 render
->instruction_bo_changed
= true;
375 session
->prim_changed
= true;
377 ilo_state_urb_full_delta(&vec
->urb
, render
->dev
, &session
->urb_delta
);
378 ilo_state_vf_full_delta(&vec
->ve
->vf
, render
->dev
, &session
->vf_delta
);
380 ilo_state_raster_full_delta(&vec
->rasterizer
->rs
, render
->dev
,
383 ilo_state_viewport_full_delta(&vec
->viewport
.vp
, render
->dev
,
386 ilo_state_cc_full_delta(&vec
->blend
->cc
, render
->dev
,
389 session
->prim_changed
=
390 (render
->state
.reduced_prim
!= session
->reduced_prim
);
392 ilo_state_urb_get_delta(&vec
->urb
, render
->dev
,
393 &render
->state
.urb
, &session
->urb_delta
);
395 if (vec
->dirty
& ILO_DIRTY_VE
) {
396 ilo_state_vf_full_delta(&vec
->ve
->vf
, render
->dev
,
400 if (vec
->dirty
& ILO_DIRTY_RASTERIZER
) {
401 ilo_state_raster_get_delta(&vec
->rasterizer
->rs
, render
->dev
,
402 &render
->state
.rs
, &session
->rs_delta
);
405 if (vec
->dirty
& ILO_DIRTY_VIEWPORT
) {
406 ilo_state_viewport_full_delta(&vec
->viewport
.vp
, render
->dev
,
410 if (vec
->dirty
& ILO_DIRTY_BLEND
) {
411 ilo_state_cc_get_delta(&vec
->blend
->cc
, render
->dev
,
412 &render
->state
.cc
, &session
->cc_delta
);
418 draw_session_end(struct ilo_render
*render
,
419 const struct ilo_state_vector
*vec
,
420 struct ilo_render_draw_session
*session
)
422 render
->hw_ctx_changed
= false;
424 render
->batch_bo_changed
= false;
425 render
->state_bo_changed
= false;
426 render
->instruction_bo_changed
= false;
428 render
->state
.reduced_prim
= session
->reduced_prim
;
430 render
->state
.urb
= vec
->urb
;
431 render
->state
.rs
= vec
->rasterizer
->rs
;
432 render
->state
.cc
= vec
->blend
->cc
;
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, 8);
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
);