• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2017 Intel Corporation
3  *
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:
10  *
11  * The above copyright notice and this permission notice shall be included
12  * in all copies or substantial portions of the Software.
13  *
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.
21  */
22 
23 /**
24  * @file iris_draw.c
25  *
26  * The main driver hooks for drawing and launching compute shaders.
27  */
28 
29 #include <stdio.h>
30 #include <errno.h>
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"
42 
43 static bool
prim_is_points_or_lines(const struct pipe_draw_info * draw)44 prim_is_points_or_lines(const struct pipe_draw_info *draw)
45 {
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.
48     */
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;
53 }
54 
55 /**
56  * Record the current primitive mode and restart information, flagging
57  * related packets as dirty if necessary.
58  *
59  * This must be called before updating compiled shaders, because the patch
60  * information informs the TCS key.
61  */
62 static void
iris_update_draw_info(struct iris_context * ice,const struct pipe_draw_info * info)63 iris_update_draw_info(struct iris_context *ice,
64                       const struct pipe_draw_info *info)
65 {
66    struct iris_screen *screen = (struct iris_screen *)ice->ctx.screen;
67    const struct brw_compiler *compiler = screen->compiler;
68 
69    if (ice->state.prim_mode != info->mode) {
70       ice->state.prim_mode = info->mode;
71       ice->state.dirty |= IRIS_DIRTY_VF_TOPOLOGY;
72 
73 
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;
79       }
80    }
81 
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;
86 
87       /* 8_PATCH TCS needs this for key->input_vertices */
88       if (compiler->use_tcs_8_patch)
89          ice->state.stage_dirty |= IRIS_STAGE_DIRTY_UNCOMPILED_TCS;
90 
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);
94       if (tcs_info &&
95           BITSET_TEST(tcs_info->system_values_read, SYSTEM_VALUE_VERTICES_IN)) {
96          ice->state.stage_dirty |= IRIS_STAGE_DIRTY_CONSTANTS_TCS;
97          ice->state.shaders[MESA_SHADER_TESS_CTRL].sysvals_need_upload = true;
98       }
99    }
100 
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;
106    }
107 }
108 
109 /**
110  * Update shader draw parameters, flagging VF packets as dirty if necessary.
111  */
112 static void
iris_update_draw_parameters(struct iris_context * ice,const struct pipe_draw_info * info)113 iris_update_draw_parameters(struct iris_context *ice,
114                             const struct pipe_draw_info *info)
115 {
116    bool changed = false;
117 
118    if (ice->state.vs_uses_draw_params) {
119       struct iris_state_ref *draw_params = &ice->draw.draw_params;
120 
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);
125 
126          changed = true;
127          ice->draw.params_valid = false;
128       } else {
129          int firstvertex = info->index_size ? info->index_bias : info->start;
130 
131          if (!ice->draw.params_valid ||
132              ice->draw.params.firstvertex != firstvertex ||
133              ice->draw.params.baseinstance != info->start_instance) {
134 
135             changed = true;
136             ice->draw.params.firstvertex = firstvertex;
137             ice->draw.params.baseinstance = info->start_instance;
138             ice->draw.params_valid = true;
139 
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);
143          }
144       }
145    }
146 
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;
150 
151       if (ice->draw.derived_params.drawid != info->drawid ||
152           ice->draw.derived_params.is_indexed_draw != is_indexed_draw) {
153 
154          changed = true;
155          ice->draw.derived_params.drawid = info->drawid;
156          ice->draw.derived_params.is_indexed_draw = is_indexed_draw;
157 
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);
162       }
163    }
164 
165    if (changed) {
166       ice->state.dirty |= IRIS_DIRTY_VERTEX_BUFFERS |
167                           IRIS_DIRTY_VERTEX_ELEMENTS |
168                           IRIS_DIRTY_VF_SGVS;
169    }
170 }
171 
172 static void
iris_indirect_draw_vbo(struct iris_context * ice,const struct pipe_draw_info * dinfo)173 iris_indirect_draw_vbo(struct iris_context *ice,
174                        const struct pipe_draw_info *dinfo)
175 {
176    struct iris_batch *batch = &ice->batches[IRIS_BATCH_RENDER];
177    struct pipe_draw_info info = *dinfo;
178 
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);
183    }
184 
185    const uint64_t orig_dirty = ice->state.dirty;
186    const uint64_t orig_stage_dirty = ice->state.stage_dirty;
187 
188    for (int i = 0; i < info.indirect->draw_count; i++) {
189       info.drawid = i;
190 
191       iris_batch_maybe_flush(batch, 1500);
192 
193       iris_update_draw_parameters(ice, &info);
194 
195       batch->screen->vtbl.upload_render_state(ice, batch, &info);
196 
197       ice->state.dirty &= ~IRIS_ALL_DIRTY_FOR_RENDER;
198       ice->state.stage_dirty &= ~IRIS_ALL_STAGE_DIRTY_FOR_RENDER;
199 
200       info.indirect->offset += info.indirect->stride;
201    }
202 
203    if (info.indirect->indirect_draw_count &&
204        ice->state.predicate == IRIS_PREDICATE_STATE_USE_BIT) {
205       /* Restore MI_PREDICATE_RESULT. */
206       batch->screen->vtbl.load_register_reg64(batch, MI_PREDICATE_RESULT, CS_GPR(15));
207    }
208 
209    /* Put this back for post-draw resolves, we'll clear it again after. */
210    ice->state.dirty = orig_dirty;
211    ice->state.stage_dirty = orig_stage_dirty;
212 }
213 
214 static void
iris_simple_draw_vbo(struct iris_context * ice,const struct pipe_draw_info * draw)215 iris_simple_draw_vbo(struct iris_context *ice,
216                      const struct pipe_draw_info *draw)
217 {
218    struct iris_batch *batch = &ice->batches[IRIS_BATCH_RENDER];
219 
220    iris_batch_maybe_flush(batch, 1500);
221 
222    iris_update_draw_parameters(ice, draw);
223 
224    batch->screen->vtbl.upload_render_state(ice, batch, draw);
225 }
226 
227 /**
228  * The pipe->draw_vbo() driver hook.  Performs a draw on the GPU.
229  */
230 void
iris_draw_vbo(struct pipe_context * ctx,const struct pipe_draw_info * info)231 iris_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info)
232 {
233    struct iris_context *ice = (struct iris_context *) ctx;
234    struct iris_screen *screen = (struct iris_screen*)ice->ctx.screen;
235    const struct gen_device_info *devinfo = &screen->devinfo;
236    struct iris_batch *batch = &ice->batches[IRIS_BATCH_RENDER];
237 
238    if (ice->state.predicate == IRIS_PREDICATE_STATE_DONT_RENDER)
239       return;
240 
241    /* We can't safely re-emit 3DSTATE_SO_BUFFERS because it may zero the
242     * write offsets, changing the behavior.
243     */
244    if (INTEL_DEBUG & DEBUG_REEMIT) {
245       ice->state.dirty |= IRIS_ALL_DIRTY_FOR_RENDER & ~IRIS_DIRTY_SO_BUFFERS;
246       ice->state.stage_dirty |= IRIS_ALL_STAGE_DIRTY_FOR_RENDER;
247    }
248 
249    iris_update_draw_info(ice, info);
250 
251    if (devinfo->gen == 9)
252       gen9_toggle_preemption(ice, batch, info);
253 
254    iris_update_compiled_shaders(ice);
255 
256    if (ice->state.dirty & IRIS_DIRTY_RENDER_RESOLVES_AND_FLUSHES) {
257       bool draw_aux_buffer_disabled[BRW_MAX_DRAW_BUFFERS] = { };
258       for (gl_shader_stage stage = 0; stage < MESA_SHADER_COMPUTE; stage++) {
259          if (ice->shaders.prog[stage])
260             iris_predraw_resolve_inputs(ice, batch, draw_aux_buffer_disabled,
261                                         stage, true);
262       }
263       iris_predraw_resolve_framebuffer(ice, batch, draw_aux_buffer_disabled);
264    }
265 
266    iris_binder_reserve_3d(ice);
267 
268    batch->screen->vtbl.update_surface_base_address(batch, &ice->state.binder);
269 
270    iris_handle_always_flush_cache(batch);
271 
272    if (info->indirect)
273       iris_indirect_draw_vbo(ice, info);
274    else
275       iris_simple_draw_vbo(ice, info);
276 
277    iris_handle_always_flush_cache(batch);
278 
279    iris_postdraw_update_resolve_tracking(ice, batch);
280 
281    ice->state.dirty &= ~IRIS_ALL_DIRTY_FOR_RENDER;
282    ice->state.stage_dirty &= ~IRIS_ALL_STAGE_DIRTY_FOR_RENDER;
283 }
284 
285 static void
iris_update_grid_size_resource(struct iris_context * ice,const struct pipe_grid_info * grid)286 iris_update_grid_size_resource(struct iris_context *ice,
287                                const struct pipe_grid_info *grid)
288 {
289    const struct iris_screen *screen = (void *) ice->ctx.screen;
290    const struct isl_device *isl_dev = &screen->isl_dev;
291    struct iris_state_ref *grid_ref = &ice->state.grid_size;
292    struct iris_state_ref *state_ref = &ice->state.grid_surf_state;
293 
294    const struct iris_compiled_shader *shader = ice->shaders.prog[MESA_SHADER_COMPUTE];
295    bool grid_needs_surface = shader->bt.used_mask[IRIS_SURFACE_GROUP_CS_WORK_GROUPS];
296    bool grid_updated = false;
297 
298    if (grid->indirect) {
299       pipe_resource_reference(&grid_ref->res, grid->indirect);
300       grid_ref->offset = grid->indirect_offset;
301 
302       /* Zero out the grid size so that the next non-indirect grid launch will
303        * re-upload it properly.
304        */
305       memset(ice->state.last_grid, 0, sizeof(ice->state.last_grid));
306       grid_updated = true;
307    } else if (memcmp(ice->state.last_grid, grid->grid, sizeof(grid->grid)) != 0) {
308       memcpy(ice->state.last_grid, grid->grid, sizeof(grid->grid));
309       u_upload_data(ice->state.dynamic_uploader, 0, sizeof(grid->grid), 4,
310                     grid->grid, &grid_ref->offset, &grid_ref->res);
311       grid_updated = true;
312    }
313 
314    /* If we changed the grid, the old surface state is invalid. */
315    if (grid_updated)
316       pipe_resource_reference(&state_ref->res, NULL);
317 
318    /* Skip surface upload if we don't need it or we already have one */
319    if (!grid_needs_surface || state_ref->res)
320       return;
321 
322    struct iris_bo *grid_bo = iris_resource_bo(grid_ref->res);
323 
324    void *surf_map = NULL;
325    u_upload_alloc(ice->state.surface_uploader, 0, isl_dev->ss.size,
326                   isl_dev->ss.align, &state_ref->offset, &state_ref->res,
327                   &surf_map);
328    state_ref->offset +=
329       iris_bo_offset_from_base_address(iris_resource_bo(state_ref->res));
330    isl_buffer_fill_state(&screen->isl_dev, surf_map,
331                          .address = grid_ref->offset + grid_bo->gtt_offset,
332                          .size_B = sizeof(grid->grid),
333                          .format = ISL_FORMAT_RAW,
334                          .stride_B = 1,
335                          .mocs = iris_mocs(grid_bo, isl_dev,
336                                            ISL_SURF_USAGE_CONSTANT_BUFFER_BIT));
337 
338    ice->state.stage_dirty |= IRIS_STAGE_DIRTY_BINDINGS_CS;
339 }
340 
341 void
iris_launch_grid(struct pipe_context * ctx,const struct pipe_grid_info * grid)342 iris_launch_grid(struct pipe_context *ctx, const struct pipe_grid_info *grid)
343 {
344    struct iris_context *ice = (struct iris_context *) ctx;
345    struct iris_batch *batch = &ice->batches[IRIS_BATCH_COMPUTE];
346 
347    if (ice->state.predicate == IRIS_PREDICATE_STATE_DONT_RENDER)
348       return;
349 
350    if (INTEL_DEBUG & DEBUG_REEMIT) {
351       ice->state.dirty |= IRIS_ALL_DIRTY_FOR_COMPUTE;
352       ice->state.stage_dirty |= IRIS_ALL_STAGE_DIRTY_FOR_COMPUTE;
353    }
354 
355    if (ice->state.dirty & IRIS_DIRTY_COMPUTE_RESOLVES_AND_FLUSHES)
356       iris_predraw_resolve_inputs(ice, batch, NULL, MESA_SHADER_COMPUTE, false);
357 
358    iris_batch_maybe_flush(batch, 1500);
359 
360    iris_update_compiled_compute_shader(ice);
361 
362    if (memcmp(ice->state.last_block, grid->block, sizeof(grid->block)) != 0) {
363       memcpy(ice->state.last_block, grid->block, sizeof(grid->block));
364       ice->state.stage_dirty |= IRIS_STAGE_DIRTY_CONSTANTS_CS;
365       ice->state.shaders[MESA_SHADER_COMPUTE].sysvals_need_upload = true;
366    }
367 
368    iris_update_grid_size_resource(ice, grid);
369 
370    iris_binder_reserve_compute(ice);
371    batch->screen->vtbl.update_surface_base_address(batch, &ice->state.binder);
372 
373    if (ice->state.compute_predicate) {
374       batch->screen->vtbl.load_register_mem64(batch, MI_PREDICATE_RESULT,
375                                     ice->state.compute_predicate, 0);
376       ice->state.compute_predicate = NULL;
377    }
378 
379    iris_handle_always_flush_cache(batch);
380 
381    batch->screen->vtbl.upload_compute_state(ice, batch, grid);
382 
383    iris_handle_always_flush_cache(batch);
384 
385    ice->state.dirty &= ~IRIS_ALL_DIRTY_FOR_COMPUTE;
386    ice->state.stage_dirty &= ~IRIS_ALL_STAGE_DIRTY_FOR_COMPUTE;
387 
388    /* Note: since compute shaders can't access the framebuffer, there's
389     * no need to call iris_postdraw_update_resolve_tracking.
390     */
391 }
392