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
->workaround_bo
);
75 ilo_render_get_sample_position(const struct ilo_render
*render
,
76 unsigned sample_count
,
77 unsigned sample_index
,
82 ilo_state_sample_pattern_get_offset(&render
->sample_pattern
, render
->dev
,
83 sample_count
, sample_index
, &off_x
, &off_y
);
85 *x
= (float) off_x
/ 16.0f
;
86 *y
= (float) off_y
/ 16.0f
;
90 ilo_render_invalidate_hw(struct ilo_render
*render
)
92 render
->hw_ctx_changed
= true;
96 ilo_render_invalidate_builder(struct ilo_render
*render
)
98 render
->batch_bo_changed
= true;
99 render
->state_bo_changed
= true;
100 render
->instruction_bo_changed
= true;
102 /* Kernel flushes everything. Shouldn't we set all bits here? */
103 render
->state
.current_pipe_control_dw1
= 0;
107 * Return the command length of ilo_render_emit_flush().
110 ilo_render_get_flush_len(const struct ilo_render
*render
)
114 ILO_DEV_ASSERT(render
->dev
, 6, 8);
116 len
= GEN6_PIPE_CONTROL__SIZE
;
118 /* plus gen6_wa_pre_pipe_control() */
119 if (ilo_dev_gen(render
->dev
) == ILO_GEN(6))
126 * Emit PIPE_CONTROLs to flush all caches.
129 ilo_render_emit_flush(struct ilo_render
*render
)
131 const uint32_t dw1
= GEN6_PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE
|
132 GEN6_PIPE_CONTROL_RENDER_CACHE_FLUSH
|
133 GEN6_PIPE_CONTROL_DEPTH_CACHE_FLUSH
|
134 GEN6_PIPE_CONTROL_VF_CACHE_INVALIDATE
|
135 GEN6_PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE
|
136 GEN6_PIPE_CONTROL_CS_STALL
;
137 const unsigned batch_used
= ilo_builder_batch_used(render
->builder
);
139 ILO_DEV_ASSERT(render
->dev
, 6, 8);
141 if (ilo_dev_gen(render
->dev
) == ILO_GEN(6))
142 gen6_wa_pre_pipe_control(render
, dw1
);
144 ilo_render_pipe_control(render
, dw1
);
146 assert(ilo_builder_batch_used(render
->builder
) <= batch_used
+
147 ilo_render_get_flush_len(render
));
151 * Return the command length of ilo_render_emit_query().
154 ilo_render_get_query_len(const struct ilo_render
*render
,
159 ILO_DEV_ASSERT(render
->dev
, 6, 8);
161 /* always a flush or a variant of flush */
162 len
= ilo_render_get_flush_len(render
);
164 switch (query_type
) {
165 case PIPE_QUERY_OCCLUSION_COUNTER
:
166 case PIPE_QUERY_TIMESTAMP
:
167 case PIPE_QUERY_TIME_ELAPSED
:
170 case PIPE_QUERY_PRIMITIVES_GENERATED
:
171 case PIPE_QUERY_PRIMITIVES_EMITTED
:
172 len
+= GEN6_MI_STORE_REGISTER_MEM__SIZE
* 2;
174 case PIPE_QUERY_PIPELINE_STATISTICS
:
177 (ilo_dev_gen(render
->dev
) >= ILO_GEN(7)) ? 10 : 8;
179 (ilo_dev_gen(render
->dev
) >= ILO_GEN(7)) ? 1 : 3;
181 len
+= GEN6_MI_STORE_REGISTER_MEM__SIZE
* 2 * num_regs
+
182 GEN6_MI_STORE_DATA_IMM__SIZE
* num_pads
;
194 * Emit PIPE_CONTROLs or MI_STORE_REGISTER_MEMs to store register values.
197 ilo_render_emit_query(struct ilo_render
*render
,
198 struct ilo_query
*q
, uint32_t offset
)
200 const uint32_t pipeline_statistics_regs
[11] = {
201 GEN6_REG_IA_VERTICES_COUNT
,
202 GEN6_REG_IA_PRIMITIVES_COUNT
,
203 GEN6_REG_VS_INVOCATION_COUNT
,
204 GEN6_REG_GS_INVOCATION_COUNT
,
205 GEN6_REG_GS_PRIMITIVES_COUNT
,
206 GEN6_REG_CL_INVOCATION_COUNT
,
207 GEN6_REG_CL_PRIMITIVES_COUNT
,
208 GEN6_REG_PS_INVOCATION_COUNT
,
209 (ilo_dev_gen(render
->dev
) >= ILO_GEN(7)) ?
210 GEN7_REG_HS_INVOCATION_COUNT
: 0,
211 (ilo_dev_gen(render
->dev
) >= ILO_GEN(7)) ?
212 GEN7_REG_DS_INVOCATION_COUNT
: 0,
215 const uint32_t primitives_generated_reg
=
216 (ilo_dev_gen(render
->dev
) >= ILO_GEN(7) && q
->index
> 0) ?
217 GEN7_REG_SO_PRIM_STORAGE_NEEDED(q
->index
) :
218 GEN6_REG_CL_INVOCATION_COUNT
;
219 const uint32_t primitives_emitted_reg
=
220 (ilo_dev_gen(render
->dev
) >= ILO_GEN(7)) ?
221 GEN7_REG_SO_NUM_PRIMS_WRITTEN(q
->index
) :
222 GEN6_REG_SO_NUM_PRIMS_WRITTEN
;
223 const unsigned batch_used
= ilo_builder_batch_used(render
->builder
);
224 const uint32_t *regs
;
225 int reg_count
= 0, i
;
226 uint32_t pipe_control_dw1
= 0;
228 ILO_DEV_ASSERT(render
->dev
, 6, 8);
231 case PIPE_QUERY_OCCLUSION_COUNTER
:
232 pipe_control_dw1
= GEN6_PIPE_CONTROL_DEPTH_STALL
|
233 GEN6_PIPE_CONTROL_WRITE_PS_DEPTH_COUNT
;
235 case PIPE_QUERY_TIMESTAMP
:
236 case PIPE_QUERY_TIME_ELAPSED
:
237 pipe_control_dw1
= GEN6_PIPE_CONTROL_WRITE_TIMESTAMP
;
239 case PIPE_QUERY_PRIMITIVES_GENERATED
:
240 regs
= &primitives_generated_reg
;
243 case PIPE_QUERY_PRIMITIVES_EMITTED
:
244 regs
= &primitives_emitted_reg
;
247 case PIPE_QUERY_PIPELINE_STATISTICS
:
248 regs
= pipeline_statistics_regs
;
249 reg_count
= Elements(pipeline_statistics_regs
);
255 if (pipe_control_dw1
) {
258 if (ilo_dev_gen(render
->dev
) == ILO_GEN(6))
259 gen6_wa_pre_pipe_control(render
, pipe_control_dw1
);
261 gen6_PIPE_CONTROL(render
->builder
, pipe_control_dw1
, q
->bo
, offset
, 0);
263 render
->state
.current_pipe_control_dw1
|= pipe_control_dw1
;
264 render
->state
.deferred_pipe_control_dw1
&= ~pipe_control_dw1
;
265 } else if (reg_count
) {
266 ilo_render_emit_flush(render
);
269 for (i
= 0; i
< reg_count
; i
++) {
271 /* store lower 32 bits */
272 gen6_MI_STORE_REGISTER_MEM(render
->builder
, regs
[i
], q
->bo
, offset
);
273 /* store higher 32 bits */
274 gen6_MI_STORE_REGISTER_MEM(render
->builder
, regs
[i
] + 4,
277 gen6_MI_STORE_DATA_IMM(render
->builder
, q
->bo
, offset
, 0);
283 assert(ilo_builder_batch_used(render
->builder
) <= batch_used
+
284 ilo_render_get_query_len(render
, q
->type
));
288 ilo_render_get_rectlist_len(const struct ilo_render
*render
,
289 const struct ilo_blitter
*blitter
)
291 ILO_DEV_ASSERT(render
->dev
, 6, 8);
293 return ilo_render_get_rectlist_dynamic_states_len(render
, blitter
) +
294 ilo_render_get_rectlist_commands_len(render
, blitter
);
298 ilo_render_emit_rectlist(struct ilo_render
*render
,
299 const struct ilo_blitter
*blitter
)
301 struct ilo_render_rectlist_session session
;
303 ILO_DEV_ASSERT(render
->dev
, 6, 8);
305 memset(&session
, 0, sizeof(session
));
306 ilo_render_emit_rectlist_dynamic_states(render
, blitter
, &session
);
307 ilo_render_emit_rectlist_commands(render
, blitter
, &session
);
311 ilo_render_get_draw_len(const struct ilo_render
*render
,
312 const struct ilo_state_vector
*vec
)
314 ILO_DEV_ASSERT(render
->dev
, 6, 8);
316 return ilo_render_get_draw_dynamic_states_len(render
, vec
) +
317 ilo_render_get_draw_surface_states_len(render
, vec
) +
318 ilo_render_get_draw_commands_len(render
, vec
);
322 draw_session_prepare(struct ilo_render
*render
,
323 const struct ilo_state_vector
*vec
,
324 struct ilo_render_draw_session
*session
)
326 memset(session
, 0, sizeof(*session
));
327 session
->pipe_dirty
= vec
->dirty
;
328 session
->reduced_prim
= u_reduced_prim(vec
->draw
->mode
);
330 if (render
->hw_ctx_changed
) {
331 /* these should be enough to make everything uploaded */
332 render
->batch_bo_changed
= true;
333 render
->state_bo_changed
= true;
334 render
->instruction_bo_changed
= true;
336 session
->prim_changed
= true;
337 session
->primitive_restart_changed
= true;
339 ilo_state_urb_full_delta(&vec
->urb
, render
->dev
, &session
->urb_delta
);
340 ilo_state_vf_full_delta(&vec
->ve
->vf
, render
->dev
, &session
->vf_delta
);
342 ilo_state_raster_full_delta(&vec
->rasterizer
->rs
, render
->dev
,
345 ilo_state_viewport_full_delta(&vec
->viewport
.vp
, render
->dev
,
348 ilo_state_cc_full_delta(&vec
->blend
->cc
, render
->dev
,
351 session
->prim_changed
=
352 (render
->state
.reduced_prim
!= session
->reduced_prim
);
353 session
->primitive_restart_changed
=
354 (render
->state
.primitive_restart
!= vec
->draw
->primitive_restart
);
356 ilo_state_urb_get_delta(&vec
->urb
, render
->dev
,
357 &render
->state
.urb
, &session
->urb_delta
);
359 if (vec
->dirty
& ILO_DIRTY_VE
) {
360 ilo_state_vf_full_delta(&vec
->ve
->vf
, render
->dev
,
364 if (vec
->dirty
& ILO_DIRTY_RASTERIZER
) {
365 ilo_state_raster_get_delta(&vec
->rasterizer
->rs
, render
->dev
,
366 &render
->state
.rs
, &session
->rs_delta
);
369 if (vec
->dirty
& ILO_DIRTY_VIEWPORT
) {
370 ilo_state_viewport_full_delta(&vec
->viewport
.vp
, render
->dev
,
374 if (vec
->dirty
& ILO_DIRTY_BLEND
) {
375 ilo_state_cc_get_delta(&vec
->blend
->cc
, render
->dev
,
376 &render
->state
.cc
, &session
->cc_delta
);
382 draw_session_end(struct ilo_render
*render
,
383 const struct ilo_state_vector
*vec
,
384 struct ilo_render_draw_session
*session
)
386 render
->hw_ctx_changed
= false;
388 render
->batch_bo_changed
= false;
389 render
->state_bo_changed
= false;
390 render
->instruction_bo_changed
= false;
392 render
->state
.reduced_prim
= session
->reduced_prim
;
393 render
->state
.primitive_restart
= vec
->draw
->primitive_restart
;
395 render
->state
.urb
= vec
->urb
;
396 render
->state
.rs
= vec
->rasterizer
->rs
;
397 render
->state
.cc
= vec
->blend
->cc
;
401 ilo_render_emit_draw(struct ilo_render
*render
,
402 const struct ilo_state_vector
*vec
)
404 struct ilo_render_draw_session session
;
406 ILO_DEV_ASSERT(render
->dev
, 6, 8);
408 draw_session_prepare(render
, vec
, &session
);
410 /* force all states to be uploaded if the state bo changed */
411 if (render
->state_bo_changed
)
412 session
.pipe_dirty
= ILO_DIRTY_ALL
;
414 session
.pipe_dirty
= vec
->dirty
;
416 ilo_render_emit_draw_dynamic_states(render
, vec
, &session
);
417 ilo_render_emit_draw_surface_states(render
, vec
, &session
);
419 /* force all commands to be uploaded if the HW context changed */
420 if (render
->hw_ctx_changed
)
421 session
.pipe_dirty
= ILO_DIRTY_ALL
;
423 session
.pipe_dirty
= vec
->dirty
;
425 ilo_render_emit_draw_commands(render
, vec
, &session
);
427 draw_session_end(render
, vec
, &session
);
431 ilo_render_get_launch_grid_len(const struct ilo_render
*render
,
432 const struct ilo_state_vector
*vec
)
434 ILO_DEV_ASSERT(render
->dev
, 7, 7.5);
436 return ilo_render_get_launch_grid_surface_states_len(render
, vec
) +
437 ilo_render_get_launch_grid_dynamic_states_len(render
, vec
) +
438 ilo_render_get_launch_grid_commands_len(render
, vec
);
442 ilo_render_emit_launch_grid(struct ilo_render
*render
,
443 const struct ilo_state_vector
*vec
,
444 const unsigned thread_group_offset
[3],
445 const unsigned thread_group_dim
[3],
446 unsigned thread_group_size
,
447 const struct pipe_constant_buffer
*input
,
450 struct ilo_render_launch_grid_session session
;
452 ILO_DEV_ASSERT(render
->dev
, 7, 7.5);
454 assert(input
->buffer
);
456 memset(&session
, 0, sizeof(session
));
458 session
.thread_group_offset
= thread_group_offset
;
459 session
.thread_group_dim
= thread_group_dim
;
460 session
.thread_group_size
= thread_group_size
;
461 session
.input
= input
;
464 ilo_render_emit_launch_grid_surface_states(render
, vec
, &session
);
465 ilo_render_emit_launch_grid_dynamic_states(render
, vec
, &session
);
466 ilo_render_emit_launch_grid_commands(render
, vec
, &session
);