2 * Copyright © 2017 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 * DEALINGS IN THE SOFTWARE.
26 * The main driver hooks for drawing and launching compute shaders.
31 #include "pipe/p_defines.h"
32 #include "pipe/p_state.h"
33 #include "pipe/p_context.h"
34 #include "pipe/p_screen.h"
35 #include "util/u_inlines.h"
36 #include "util/u_transfer.h"
37 #include "util/u_upload_mgr.h"
38 #include "intel/compiler/brw_compiler.h"
39 #include "intel/compiler/brw_eu_defines.h"
40 #include "iris_context.h"
41 #include "iris_defines.h"
44 prim_is_points_or_lines(const struct pipe_draw_info
*draw
)
46 /* We don't need to worry about adjacency - it can only be used with
47 * geometry shaders, and we don't care about this info when GS is on.
49 return draw
->mode
== PIPE_PRIM_POINTS
||
50 draw
->mode
== PIPE_PRIM_LINES
||
51 draw
->mode
== PIPE_PRIM_LINE_LOOP
||
52 draw
->mode
== PIPE_PRIM_LINE_STRIP
;
56 * Record the current primitive mode and restart information, flagging
57 * related packets as dirty if necessary.
59 * This must be called before updating compiled shaders, because the patch
60 * information informs the TCS key.
63 iris_update_draw_info(struct iris_context
*ice
,
64 const struct pipe_draw_info
*info
)
66 struct iris_screen
*screen
= (struct iris_screen
*)ice
->ctx
.screen
;
67 const struct brw_compiler
*compiler
= screen
->compiler
;
69 if (ice
->state
.prim_mode
!= info
->mode
) {
70 ice
->state
.prim_mode
= info
->mode
;
71 ice
->state
.dirty
|= IRIS_DIRTY_VF_TOPOLOGY
;
74 /* For XY Clip enables */
75 bool points_or_lines
= prim_is_points_or_lines(info
);
76 if (points_or_lines
!= ice
->state
.prim_is_points_or_lines
) {
77 ice
->state
.prim_is_points_or_lines
= points_or_lines
;
78 ice
->state
.dirty
|= IRIS_DIRTY_CLIP
;
82 if (info
->mode
== PIPE_PRIM_PATCHES
&&
83 ice
->state
.vertices_per_patch
!= info
->vertices_per_patch
) {
84 ice
->state
.vertices_per_patch
= info
->vertices_per_patch
;
85 ice
->state
.dirty
|= IRIS_DIRTY_VF_TOPOLOGY
;
87 /* 8_PATCH TCS needs this for key->input_vertices */
88 if (compiler
->use_tcs_8_patch
)
89 ice
->state
.dirty
|= IRIS_DIRTY_UNCOMPILED_TCS
;
91 /* Flag constants dirty for gl_PatchVerticesIn if needed. */
92 const struct shader_info
*tcs_info
=
93 iris_get_shader_info(ice
, MESA_SHADER_TESS_CTRL
);
95 tcs_info
->system_values_read
& (1ull << SYSTEM_VALUE_VERTICES_IN
)) {
96 ice
->state
.dirty
|= IRIS_DIRTY_CONSTANTS_TCS
;
97 ice
->state
.shaders
[MESA_SHADER_TESS_CTRL
].sysvals_need_upload
= true;
101 if (ice
->state
.primitive_restart
!= info
->primitive_restart
||
102 ice
->state
.cut_index
!= info
->restart_index
) {
103 ice
->state
.dirty
|= IRIS_DIRTY_VF
;
104 ice
->state
.primitive_restart
= info
->primitive_restart
;
105 ice
->state
.cut_index
= info
->restart_index
;
110 * Update shader draw parameters, flagging VF packets as dirty if necessary.
113 iris_update_draw_parameters(struct iris_context
*ice
,
114 const struct pipe_draw_info
*info
)
116 bool changed
= false;
118 if (ice
->state
.vs_uses_draw_params
) {
119 struct iris_state_ref
*draw_params
= &ice
->draw
.draw_params
;
121 if (info
->indirect
) {
122 pipe_resource_reference(&draw_params
->res
, info
->indirect
->buffer
);
123 draw_params
->offset
=
124 info
->indirect
->offset
+ (info
->index_size
? 12 : 8);
127 ice
->draw
.params_valid
= false;
129 int firstvertex
= info
->index_size
? info
->index_bias
: info
->start
;
131 if (!ice
->draw
.params_valid
||
132 ice
->draw
.params
.firstvertex
!= firstvertex
||
133 ice
->draw
.params
.baseinstance
!= info
->start_instance
) {
136 ice
->draw
.params
.firstvertex
= firstvertex
;
137 ice
->draw
.params
.baseinstance
= info
->start_instance
;
138 ice
->draw
.params_valid
= true;
140 u_upload_data(ice
->ctx
.stream_uploader
, 0,
141 sizeof(ice
->draw
.params
), 4, &ice
->draw
.params
,
142 &draw_params
->offset
, &draw_params
->res
);
147 if (ice
->state
.vs_uses_derived_draw_params
) {
148 struct iris_state_ref
*derived_params
= &ice
->draw
.derived_draw_params
;
149 int is_indexed_draw
= info
->index_size
? -1 : 0;
151 if (ice
->draw
.derived_params
.drawid
!= info
->drawid
||
152 ice
->draw
.derived_params
.is_indexed_draw
!= is_indexed_draw
) {
155 ice
->draw
.derived_params
.drawid
= info
->drawid
;
156 ice
->draw
.derived_params
.is_indexed_draw
= is_indexed_draw
;
158 u_upload_data(ice
->ctx
.stream_uploader
, 0,
159 sizeof(ice
->draw
.derived_params
), 4,
160 &ice
->draw
.derived_params
,
161 &derived_params
->offset
, &derived_params
->res
);
166 ice
->state
.dirty
|= IRIS_DIRTY_VERTEX_BUFFERS
|
167 IRIS_DIRTY_VERTEX_ELEMENTS
|
173 iris_indirect_draw_vbo(struct iris_context
*ice
,
174 const struct pipe_draw_info
*dinfo
)
176 struct iris_batch
*batch
= &ice
->batches
[IRIS_BATCH_RENDER
];
177 struct pipe_draw_info info
= *dinfo
;
179 if (info
.indirect
->indirect_draw_count
&&
180 ice
->state
.predicate
== IRIS_PREDICATE_STATE_USE_BIT
) {
181 /* Upload MI_PREDICATE_RESULT to GPR15.*/
182 batch
->screen
->vtbl
.load_register_reg64(batch
, CS_GPR(15), MI_PREDICATE_RESULT
);
185 uint64_t orig_dirty
= ice
->state
.dirty
;
187 for (int i
= 0; i
< info
.indirect
->draw_count
; i
++) {
190 iris_batch_maybe_flush(batch
, 1500);
192 iris_update_draw_parameters(ice
, &info
);
194 batch
->screen
->vtbl
.upload_render_state(ice
, batch
, &info
);
196 ice
->state
.dirty
&= ~IRIS_ALL_DIRTY_FOR_RENDER
;
198 info
.indirect
->offset
+= info
.indirect
->stride
;
201 if (info
.indirect
->indirect_draw_count
&&
202 ice
->state
.predicate
== IRIS_PREDICATE_STATE_USE_BIT
) {
203 /* Restore MI_PREDICATE_RESULT. */
204 batch
->screen
->vtbl
.load_register_reg64(batch
, MI_PREDICATE_RESULT
, CS_GPR(15));
207 /* Put this back for post-draw resolves, we'll clear it again after. */
208 ice
->state
.dirty
= orig_dirty
;
212 iris_simple_draw_vbo(struct iris_context
*ice
,
213 const struct pipe_draw_info
*draw
)
215 struct iris_batch
*batch
= &ice
->batches
[IRIS_BATCH_RENDER
];
217 iris_batch_maybe_flush(batch
, 1500);
219 iris_update_draw_parameters(ice
, draw
);
221 batch
->screen
->vtbl
.upload_render_state(ice
, batch
, draw
);
225 * The pipe->draw_vbo() driver hook. Performs a draw on the GPU.
228 iris_draw_vbo(struct pipe_context
*ctx
, const struct pipe_draw_info
*info
)
230 struct iris_context
*ice
= (struct iris_context
*) ctx
;
231 struct iris_screen
*screen
= (struct iris_screen
*)ice
->ctx
.screen
;
232 const struct gen_device_info
*devinfo
= &screen
->devinfo
;
233 struct iris_batch
*batch
= &ice
->batches
[IRIS_BATCH_RENDER
];
235 if (ice
->state
.predicate
== IRIS_PREDICATE_STATE_DONT_RENDER
)
238 /* We can't safely re-emit 3DSTATE_SO_BUFFERS because it may zero the
239 * write offsets, changing the behavior.
241 if (unlikely(INTEL_DEBUG
& DEBUG_REEMIT
))
242 ice
->state
.dirty
|= IRIS_ALL_DIRTY_FOR_RENDER
& ~IRIS_DIRTY_SO_BUFFERS
;
244 iris_update_draw_info(ice
, info
);
246 if (devinfo
->gen
== 9)
247 gen9_toggle_preemption(ice
, batch
, info
);
249 iris_update_compiled_shaders(ice
);
251 if (ice
->state
.dirty
& IRIS_DIRTY_RENDER_RESOLVES_AND_FLUSHES
) {
252 bool draw_aux_buffer_disabled
[BRW_MAX_DRAW_BUFFERS
] = { };
253 for (gl_shader_stage stage
= 0; stage
< MESA_SHADER_COMPUTE
; stage
++) {
254 if (ice
->shaders
.prog
[stage
])
255 iris_predraw_resolve_inputs(ice
, batch
, draw_aux_buffer_disabled
,
258 iris_predraw_resolve_framebuffer(ice
, batch
, draw_aux_buffer_disabled
);
261 iris_binder_reserve_3d(ice
);
263 batch
->screen
->vtbl
.update_surface_base_address(batch
, &ice
->state
.binder
);
265 iris_handle_always_flush_cache(batch
);
268 iris_indirect_draw_vbo(ice
, info
);
270 iris_simple_draw_vbo(ice
, info
);
272 iris_handle_always_flush_cache(batch
);
274 iris_postdraw_update_resolve_tracking(ice
, batch
);
276 ice
->state
.dirty
&= ~IRIS_ALL_DIRTY_FOR_RENDER
;
280 iris_update_grid_size_resource(struct iris_context
*ice
,
281 const struct pipe_grid_info
*grid
)
283 const struct iris_screen
*screen
= (void *) ice
->ctx
.screen
;
284 const struct isl_device
*isl_dev
= &screen
->isl_dev
;
285 struct iris_state_ref
*grid_ref
= &ice
->state
.grid_size
;
286 struct iris_state_ref
*state_ref
= &ice
->state
.grid_surf_state
;
288 const struct iris_compiled_shader
*shader
= ice
->shaders
.prog
[MESA_SHADER_COMPUTE
];
289 bool grid_needs_surface
= shader
->bt
.used_mask
[IRIS_SURFACE_GROUP_CS_WORK_GROUPS
];
290 bool grid_updated
= false;
292 if (grid
->indirect
) {
293 pipe_resource_reference(&grid_ref
->res
, grid
->indirect
);
294 grid_ref
->offset
= grid
->indirect_offset
;
296 /* Zero out the grid size so that the next non-indirect grid launch will
297 * re-upload it properly.
299 memset(ice
->state
.last_grid
, 0, sizeof(ice
->state
.last_grid
));
301 } else if (memcmp(ice
->state
.last_grid
, grid
->grid
, sizeof(grid
->grid
)) != 0) {
302 memcpy(ice
->state
.last_grid
, grid
->grid
, sizeof(grid
->grid
));
303 u_upload_data(ice
->state
.dynamic_uploader
, 0, sizeof(grid
->grid
), 4,
304 grid
->grid
, &grid_ref
->offset
, &grid_ref
->res
);
308 /* If we changed the grid, the old surface state is invalid. */
310 pipe_resource_reference(&state_ref
->res
, NULL
);
312 /* Skip surface upload if we don't need it or we already have one */
313 if (!grid_needs_surface
|| state_ref
->res
)
316 struct iris_bo
*grid_bo
= iris_resource_bo(grid_ref
->res
);
318 void *surf_map
= NULL
;
319 u_upload_alloc(ice
->state
.surface_uploader
, 0, isl_dev
->ss
.size
,
320 isl_dev
->ss
.align
, &state_ref
->offset
, &state_ref
->res
,
323 iris_bo_offset_from_base_address(iris_resource_bo(state_ref
->res
));
324 isl_buffer_fill_state(&screen
->isl_dev
, surf_map
,
325 .address
= grid_ref
->offset
+ grid_bo
->gtt_offset
,
326 .size_B
= sizeof(grid
->grid
),
327 .format
= ISL_FORMAT_RAW
,
329 .mocs
= iris_mocs(grid_bo
, isl_dev
));
331 ice
->state
.dirty
|= IRIS_DIRTY_BINDINGS_CS
;
335 iris_launch_grid(struct pipe_context
*ctx
, const struct pipe_grid_info
*grid
)
337 struct iris_context
*ice
= (struct iris_context
*) ctx
;
338 struct iris_batch
*batch
= &ice
->batches
[IRIS_BATCH_COMPUTE
];
340 if (ice
->state
.predicate
== IRIS_PREDICATE_STATE_DONT_RENDER
)
343 if (unlikely(INTEL_DEBUG
& DEBUG_REEMIT
))
344 ice
->state
.dirty
|= IRIS_ALL_DIRTY_FOR_COMPUTE
;
346 /* We can't do resolves on the compute engine, so awkwardly, we have to
347 * do them on the render batch...
349 if (ice
->state
.dirty
& IRIS_DIRTY_COMPUTE_RESOLVES_AND_FLUSHES
) {
350 iris_predraw_resolve_inputs(ice
, &ice
->batches
[IRIS_BATCH_RENDER
], NULL
,
351 MESA_SHADER_COMPUTE
, false);
354 iris_batch_maybe_flush(batch
, 1500);
356 iris_update_compiled_compute_shader(ice
);
358 iris_update_grid_size_resource(ice
, grid
);
360 iris_binder_reserve_compute(ice
);
361 batch
->screen
->vtbl
.update_surface_base_address(batch
, &ice
->state
.binder
);
363 if (ice
->state
.compute_predicate
) {
364 batch
->screen
->vtbl
.load_register_mem64(batch
, MI_PREDICATE_RESULT
,
365 ice
->state
.compute_predicate
, 0);
366 ice
->state
.compute_predicate
= NULL
;
369 iris_handle_always_flush_cache(batch
);
371 batch
->screen
->vtbl
.upload_compute_state(ice
, batch
, grid
);
373 iris_handle_always_flush_cache(batch
);
375 ice
->state
.dirty
&= ~IRIS_ALL_DIRTY_FOR_COMPUTE
;
377 /* Note: since compute shaders can't access the framebuffer, there's
378 * no need to call iris_postdraw_update_resolve_tracking.