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_OCCLUSION_PREDICATE
:
206 case PIPE_QUERY_TIMESTAMP
:
207 case PIPE_QUERY_TIME_ELAPSED
:
210 case PIPE_QUERY_PRIMITIVES_GENERATED
:
211 case PIPE_QUERY_PRIMITIVES_EMITTED
:
212 len
+= GEN6_MI_STORE_REGISTER_MEM__SIZE
* 2;
214 case PIPE_QUERY_PIPELINE_STATISTICS
:
217 (ilo_dev_gen(render
->dev
) >= ILO_GEN(7)) ? 10 : 8;
219 (ilo_dev_gen(render
->dev
) >= ILO_GEN(7)) ? 1 : 3;
221 len
+= GEN6_MI_STORE_REGISTER_MEM__SIZE
* 2 * num_regs
+
222 GEN6_MI_STORE_DATA_IMM__SIZE
* num_pads
;
234 * Emit PIPE_CONTROLs or MI_STORE_REGISTER_MEMs to store register values.
237 ilo_render_emit_query(struct ilo_render
*render
,
238 struct ilo_query
*q
, uint32_t offset
)
240 const uint32_t pipeline_statistics_regs
[11] = {
241 GEN6_REG_IA_VERTICES_COUNT
,
242 GEN6_REG_IA_PRIMITIVES_COUNT
,
243 GEN6_REG_VS_INVOCATION_COUNT
,
244 GEN6_REG_GS_INVOCATION_COUNT
,
245 GEN6_REG_GS_PRIMITIVES_COUNT
,
246 GEN6_REG_CL_INVOCATION_COUNT
,
247 GEN6_REG_CL_PRIMITIVES_COUNT
,
248 GEN6_REG_PS_INVOCATION_COUNT
,
249 (ilo_dev_gen(render
->dev
) >= ILO_GEN(7)) ?
250 GEN7_REG_HS_INVOCATION_COUNT
: 0,
251 (ilo_dev_gen(render
->dev
) >= ILO_GEN(7)) ?
252 GEN7_REG_DS_INVOCATION_COUNT
: 0,
255 const uint32_t primitives_generated_reg
=
256 (ilo_dev_gen(render
->dev
) >= ILO_GEN(7) && q
->index
> 0) ?
257 GEN7_REG_SO_PRIM_STORAGE_NEEDED(q
->index
) :
258 GEN6_REG_CL_INVOCATION_COUNT
;
259 const uint32_t primitives_emitted_reg
=
260 (ilo_dev_gen(render
->dev
) >= ILO_GEN(7)) ?
261 GEN7_REG_SO_NUM_PRIMS_WRITTEN(q
->index
) :
262 GEN6_REG_SO_NUM_PRIMS_WRITTEN
;
263 const unsigned batch_used
= ilo_builder_batch_used(render
->builder
);
264 const uint32_t *regs
;
265 int reg_count
= 0, i
;
266 uint32_t pipe_control_dw1
= 0;
268 ILO_DEV_ASSERT(render
->dev
, 6, 8);
271 case PIPE_QUERY_OCCLUSION_COUNTER
:
272 case PIPE_QUERY_OCCLUSION_PREDICATE
:
273 pipe_control_dw1
= GEN6_PIPE_CONTROL_DEPTH_STALL
|
274 GEN6_PIPE_CONTROL_WRITE_PS_DEPTH_COUNT
;
276 case PIPE_QUERY_TIMESTAMP
:
277 case PIPE_QUERY_TIME_ELAPSED
:
278 pipe_control_dw1
= GEN6_PIPE_CONTROL_WRITE_TIMESTAMP
;
280 case PIPE_QUERY_PRIMITIVES_GENERATED
:
281 regs
= &primitives_generated_reg
;
284 case PIPE_QUERY_PRIMITIVES_EMITTED
:
285 regs
= &primitives_emitted_reg
;
288 case PIPE_QUERY_PIPELINE_STATISTICS
:
289 regs
= pipeline_statistics_regs
;
290 reg_count
= Elements(pipeline_statistics_regs
);
296 if (pipe_control_dw1
) {
299 if (ilo_dev_gen(render
->dev
) == ILO_GEN(6))
300 gen6_wa_pre_pipe_control(render
, pipe_control_dw1
);
302 gen6_PIPE_CONTROL(render
->builder
, pipe_control_dw1
, q
->bo
, offset
, 0);
304 render
->state
.current_pipe_control_dw1
|= pipe_control_dw1
;
305 render
->state
.deferred_pipe_control_dw1
&= ~pipe_control_dw1
;
306 } else if (reg_count
) {
307 ilo_render_emit_flush(render
);
310 for (i
= 0; i
< reg_count
; i
++) {
312 /* store lower 32 bits */
313 gen6_MI_STORE_REGISTER_MEM(render
->builder
, regs
[i
], q
->bo
, offset
);
314 /* store higher 32 bits */
315 gen6_MI_STORE_REGISTER_MEM(render
->builder
, regs
[i
] + 4,
318 gen6_MI_STORE_DATA_IMM(render
->builder
, q
->bo
, offset
, 0);
324 assert(ilo_builder_batch_used(render
->builder
) <= batch_used
+
325 ilo_render_get_query_len(render
, q
->type
));
329 ilo_render_get_rectlist_len(const struct ilo_render
*render
,
330 const struct ilo_blitter
*blitter
)
332 ILO_DEV_ASSERT(render
->dev
, 6, 8);
334 return ilo_render_get_rectlist_dynamic_states_len(render
, blitter
) +
335 ilo_render_get_rectlist_commands_len(render
, blitter
);
339 ilo_render_emit_rectlist(struct ilo_render
*render
,
340 const struct ilo_blitter
*blitter
)
342 struct ilo_render_rectlist_session session
;
344 ILO_DEV_ASSERT(render
->dev
, 6, 8);
346 memset(&session
, 0, sizeof(session
));
347 ilo_render_emit_rectlist_dynamic_states(render
, blitter
, &session
);
348 ilo_render_emit_rectlist_commands(render
, blitter
, &session
);
352 ilo_render_get_draw_len(const struct ilo_render
*render
,
353 const struct ilo_state_vector
*vec
)
355 ILO_DEV_ASSERT(render
->dev
, 6, 8);
357 return ilo_render_get_draw_dynamic_states_len(render
, vec
) +
358 ilo_render_get_draw_surface_states_len(render
, vec
) +
359 ilo_render_get_draw_commands_len(render
, vec
);
363 draw_session_prepare(struct ilo_render
*render
,
364 const struct ilo_state_vector
*vec
,
365 struct ilo_render_draw_session
*session
)
367 memset(session
, 0, sizeof(*session
));
368 session
->pipe_dirty
= vec
->dirty
;
369 session
->reduced_prim
= u_reduced_prim(vec
->draw
->mode
);
371 if (render
->hw_ctx_changed
) {
372 /* these should be enough to make everything uploaded */
373 render
->batch_bo_changed
= true;
374 render
->state_bo_changed
= true;
375 render
->instruction_bo_changed
= true;
377 session
->prim_changed
= true;
379 ilo_state_urb_full_delta(&vec
->urb
, render
->dev
, &session
->urb_delta
);
380 ilo_state_vf_full_delta(&vec
->ve
->vf
, render
->dev
, &session
->vf_delta
);
382 ilo_state_raster_full_delta(&vec
->rasterizer
->rs
, render
->dev
,
385 ilo_state_viewport_full_delta(&vec
->viewport
.vp
, render
->dev
,
388 ilo_state_cc_full_delta(&vec
->blend
->cc
, render
->dev
,
391 session
->prim_changed
=
392 (render
->state
.reduced_prim
!= session
->reduced_prim
);
394 ilo_state_urb_get_delta(&vec
->urb
, render
->dev
,
395 &render
->state
.urb
, &session
->urb_delta
);
397 if (vec
->dirty
& ILO_DIRTY_VE
) {
398 ilo_state_vf_full_delta(&vec
->ve
->vf
, render
->dev
,
402 if (vec
->dirty
& ILO_DIRTY_RASTERIZER
) {
403 ilo_state_raster_get_delta(&vec
->rasterizer
->rs
, render
->dev
,
404 &render
->state
.rs
, &session
->rs_delta
);
407 if (vec
->dirty
& ILO_DIRTY_VIEWPORT
) {
408 ilo_state_viewport_full_delta(&vec
->viewport
.vp
, render
->dev
,
412 if (vec
->dirty
& ILO_DIRTY_BLEND
) {
413 ilo_state_cc_get_delta(&vec
->blend
->cc
, render
->dev
,
414 &render
->state
.cc
, &session
->cc_delta
);
420 draw_session_end(struct ilo_render
*render
,
421 const struct ilo_state_vector
*vec
,
422 struct ilo_render_draw_session
*session
)
424 render
->hw_ctx_changed
= false;
426 render
->batch_bo_changed
= false;
427 render
->state_bo_changed
= false;
428 render
->instruction_bo_changed
= false;
430 render
->state
.reduced_prim
= session
->reduced_prim
;
432 render
->state
.urb
= vec
->urb
;
433 render
->state
.rs
= vec
->rasterizer
->rs
;
434 render
->state
.cc
= vec
->blend
->cc
;
438 ilo_render_emit_draw(struct ilo_render
*render
,
439 const struct ilo_state_vector
*vec
)
441 struct ilo_render_draw_session session
;
443 ILO_DEV_ASSERT(render
->dev
, 6, 8);
445 draw_session_prepare(render
, vec
, &session
);
447 /* force all states to be uploaded if the state bo changed */
448 if (render
->state_bo_changed
)
449 session
.pipe_dirty
= ILO_DIRTY_ALL
;
451 session
.pipe_dirty
= vec
->dirty
;
453 ilo_render_emit_draw_dynamic_states(render
, vec
, &session
);
454 ilo_render_emit_draw_surface_states(render
, vec
, &session
);
456 /* force all commands to be uploaded if the HW context changed */
457 if (render
->hw_ctx_changed
)
458 session
.pipe_dirty
= ILO_DIRTY_ALL
;
460 session
.pipe_dirty
= vec
->dirty
;
462 ilo_render_emit_draw_commands(render
, vec
, &session
);
464 draw_session_end(render
, vec
, &session
);
468 ilo_render_get_launch_grid_len(const struct ilo_render
*render
,
469 const struct ilo_state_vector
*vec
)
471 ILO_DEV_ASSERT(render
->dev
, 7, 7.5);
473 return ilo_render_get_launch_grid_surface_states_len(render
, vec
) +
474 ilo_render_get_launch_grid_dynamic_states_len(render
, vec
) +
475 ilo_render_get_launch_grid_commands_len(render
, vec
);
479 ilo_render_emit_launch_grid(struct ilo_render
*render
,
480 const struct ilo_state_vector
*vec
,
481 const unsigned thread_group_offset
[3],
482 const unsigned thread_group_dim
[3],
483 unsigned thread_group_size
,
484 const struct pipe_constant_buffer
*input
,
487 struct ilo_render_launch_grid_session session
;
489 ILO_DEV_ASSERT(render
->dev
, 7, 7.5);
491 assert(input
->buffer
);
493 memset(&session
, 0, sizeof(session
));
495 session
.thread_group_offset
= thread_group_offset
;
496 session
.thread_group_dim
= thread_group_dim
;
497 session
.thread_group_size
= thread_group_size
;
498 session
.input
= input
;
501 ilo_render_emit_launch_grid_surface_states(render
, vec
, &session
);
502 ilo_render_emit_launch_grid_dynamic_states(render
, vec
, &session
);
503 ilo_render_emit_launch_grid_commands(render
, vec
, &session
);