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_draw.h"
36 #include "util/u_inlines.h"
37 #include "util/u_transfer.h"
38 #include "util/u_upload_mgr.h"
39 #include "intel/compiler/brw_compiler.h"
40 #include "intel/compiler/brw_eu_defines.h"
41 #include "compiler/shader_info.h"
42 #include "iris_context.h"
43 #include "iris_defines.h"
44 
45 static bool
prim_is_points_or_lines(const struct pipe_draw_info * draw)46 prim_is_points_or_lines(const struct pipe_draw_info *draw)
47 {
48    /* We don't need to worry about adjacency - it can only be used with
49     * geometry shaders, and we don't care about this info when GS is on.
50     */
51    return draw->mode == PIPE_PRIM_POINTS ||
52           draw->mode == PIPE_PRIM_LINES ||
53           draw->mode == PIPE_PRIM_LINE_LOOP ||
54           draw->mode == PIPE_PRIM_LINE_STRIP;
55 }
56 
57 /**
58  * Record the current primitive mode and restart information, flagging
59  * related packets as dirty if necessary.
60  *
61  * This must be called before updating compiled shaders, because the patch
62  * information informs the TCS key.
63  */
64 static void
iris_update_draw_info(struct iris_context * ice,const struct pipe_draw_info * info)65 iris_update_draw_info(struct iris_context *ice,
66                       const struct pipe_draw_info *info)
67 {
68    struct iris_screen *screen = (struct iris_screen *)ice->ctx.screen;
69    const struct intel_device_info *devinfo = &screen->devinfo;
70    const struct brw_compiler *compiler = screen->compiler;
71 
72    if (ice->state.prim_mode != info->mode) {
73       ice->state.prim_mode = info->mode;
74       ice->state.dirty |= IRIS_DIRTY_VF_TOPOLOGY;
75 
76 
77       /* For XY Clip enables */
78       bool points_or_lines = prim_is_points_or_lines(info);
79       if (points_or_lines != ice->state.prim_is_points_or_lines) {
80          ice->state.prim_is_points_or_lines = points_or_lines;
81          ice->state.dirty |= IRIS_DIRTY_CLIP;
82       }
83    }
84 
85    if (info->mode == PIPE_PRIM_PATCHES &&
86        ice->state.vertices_per_patch != ice->state.patch_vertices) {
87       ice->state.vertices_per_patch = ice->state.patch_vertices;
88       ice->state.dirty |= IRIS_DIRTY_VF_TOPOLOGY;
89 
90       /* 8_PATCH TCS needs this for key->input_vertices */
91       if (compiler->use_tcs_8_patch)
92          ice->state.stage_dirty |= IRIS_STAGE_DIRTY_UNCOMPILED_TCS;
93 
94       /* Flag constants dirty for gl_PatchVerticesIn if needed. */
95       const struct shader_info *tcs_info =
96          iris_get_shader_info(ice, MESA_SHADER_TESS_CTRL);
97       if (tcs_info &&
98           BITSET_TEST(tcs_info->system_values_read, SYSTEM_VALUE_VERTICES_IN)) {
99          ice->state.stage_dirty |= IRIS_STAGE_DIRTY_CONSTANTS_TCS;
100          ice->state.shaders[MESA_SHADER_TESS_CTRL].sysvals_need_upload = true;
101       }
102    }
103 
104    /* Track restart_index changes only if primitive_restart is true */
105    const unsigned cut_index = info->primitive_restart ? info->restart_index :
106                                                         ice->state.cut_index;
107    if (ice->state.primitive_restart != info->primitive_restart ||
108        ice->state.cut_index != cut_index) {
109       ice->state.dirty |= IRIS_DIRTY_VF;
110       ice->state.cut_index = cut_index;
111       ice->state.dirty |=
112          ((ice->state.primitive_restart != info->primitive_restart) &&
113           devinfo->verx10 >= 125) ? IRIS_DIRTY_VFG : 0;
114       ice->state.primitive_restart = info->primitive_restart;
115    }
116 }
117 
118 /**
119  * Update shader draw parameters, flagging VF packets as dirty if necessary.
120  */
121 static void
iris_update_draw_parameters(struct iris_context * ice,const struct pipe_draw_info * info,unsigned drawid_offset,const struct pipe_draw_indirect_info * indirect,const struct pipe_draw_start_count_bias * draw)122 iris_update_draw_parameters(struct iris_context *ice,
123                             const struct pipe_draw_info *info,
124                             unsigned drawid_offset,
125                             const struct pipe_draw_indirect_info *indirect,
126                             const struct pipe_draw_start_count_bias *draw)
127 {
128    bool changed = false;
129 
130    if (ice->state.vs_uses_draw_params) {
131       struct iris_state_ref *draw_params = &ice->draw.draw_params;
132 
133       if (indirect && indirect->buffer) {
134          pipe_resource_reference(&draw_params->res, indirect->buffer);
135          draw_params->offset =
136             indirect->offset + (info->index_size ? 12 : 8);
137 
138          changed = true;
139          ice->draw.params_valid = false;
140       } else {
141          int firstvertex = info->index_size ? draw->index_bias : draw->start;
142 
143          if (!ice->draw.params_valid ||
144              ice->draw.params.firstvertex != firstvertex ||
145              ice->draw.params.baseinstance != info->start_instance) {
146 
147             changed = true;
148             ice->draw.params.firstvertex = firstvertex;
149             ice->draw.params.baseinstance = info->start_instance;
150             ice->draw.params_valid = true;
151 
152             u_upload_data(ice->ctx.const_uploader, 0,
153                           sizeof(ice->draw.params), 4, &ice->draw.params,
154                           &draw_params->offset, &draw_params->res);
155          }
156       }
157    }
158 
159    if (ice->state.vs_uses_derived_draw_params) {
160       struct iris_state_ref *derived_params = &ice->draw.derived_draw_params;
161       int is_indexed_draw = info->index_size ? -1 : 0;
162 
163       if (ice->draw.derived_params.drawid != drawid_offset ||
164           ice->draw.derived_params.is_indexed_draw != is_indexed_draw) {
165 
166          changed = true;
167          ice->draw.derived_params.drawid = drawid_offset;
168          ice->draw.derived_params.is_indexed_draw = is_indexed_draw;
169 
170          u_upload_data(ice->ctx.const_uploader, 0,
171                        sizeof(ice->draw.derived_params), 4,
172                        &ice->draw.derived_params,
173                        &derived_params->offset, &derived_params->res);
174       }
175    }
176 
177    if (changed) {
178       ice->state.dirty |= IRIS_DIRTY_VERTEX_BUFFERS |
179                           IRIS_DIRTY_VERTEX_ELEMENTS |
180                           IRIS_DIRTY_VF_SGVS;
181    }
182 }
183 
184 static void
iris_indirect_draw_vbo(struct iris_context * ice,const struct pipe_draw_info * dinfo,unsigned drawid_offset,const struct pipe_draw_indirect_info * dindirect,const struct pipe_draw_start_count_bias * draw)185 iris_indirect_draw_vbo(struct iris_context *ice,
186                        const struct pipe_draw_info *dinfo,
187                        unsigned drawid_offset,
188                        const struct pipe_draw_indirect_info *dindirect,
189                        const struct pipe_draw_start_count_bias *draw)
190 {
191    struct iris_batch *batch = &ice->batches[IRIS_BATCH_RENDER];
192    struct pipe_draw_info info = *dinfo;
193    struct pipe_draw_indirect_info indirect = *dindirect;
194 
195    iris_emit_buffer_barrier_for(batch, iris_resource_bo(indirect.buffer),
196                                 IRIS_DOMAIN_VF_READ);
197 
198    if (indirect.indirect_draw_count) {
199       struct iris_bo *draw_count_bo =
200          iris_resource_bo(indirect.indirect_draw_count);
201       iris_emit_buffer_barrier_for(batch, draw_count_bo,
202                                    IRIS_DOMAIN_OTHER_READ);
203 
204       if (ice->state.predicate == IRIS_PREDICATE_STATE_USE_BIT) {
205          /* Upload MI_PREDICATE_RESULT to GPR15.*/
206          batch->screen->vtbl.load_register_reg64(batch, CS_GPR(15), MI_PREDICATE_RESULT);
207       }
208    }
209 
210    const uint64_t orig_dirty = ice->state.dirty;
211    const uint64_t orig_stage_dirty = ice->state.stage_dirty;
212 
213    for (int i = 0; i < indirect.draw_count; i++) {
214       iris_batch_maybe_flush(batch, 1500);
215 
216       iris_update_draw_parameters(ice, &info, drawid_offset + i, &indirect, draw);
217 
218       batch->screen->vtbl.upload_render_state(ice, batch, &info, drawid_offset + i, &indirect, draw);
219 
220       ice->state.dirty &= ~IRIS_ALL_DIRTY_FOR_RENDER;
221       ice->state.stage_dirty &= ~IRIS_ALL_STAGE_DIRTY_FOR_RENDER;
222 
223       indirect.offset += indirect.stride;
224    }
225 
226    if (indirect.indirect_draw_count &&
227        ice->state.predicate == IRIS_PREDICATE_STATE_USE_BIT) {
228       /* Restore MI_PREDICATE_RESULT. */
229       batch->screen->vtbl.load_register_reg64(batch, MI_PREDICATE_RESULT, CS_GPR(15));
230    }
231 
232    /* Put this back for post-draw resolves, we'll clear it again after. */
233    ice->state.dirty = orig_dirty;
234    ice->state.stage_dirty = orig_stage_dirty;
235 }
236 
237 static void
iris_simple_draw_vbo(struct iris_context * ice,const struct pipe_draw_info * draw,unsigned drawid_offset,const struct pipe_draw_indirect_info * indirect,const struct pipe_draw_start_count_bias * sc)238 iris_simple_draw_vbo(struct iris_context *ice,
239                      const struct pipe_draw_info *draw,
240                      unsigned drawid_offset,
241                      const struct pipe_draw_indirect_info *indirect,
242                      const struct pipe_draw_start_count_bias *sc)
243 {
244    struct iris_batch *batch = &ice->batches[IRIS_BATCH_RENDER];
245 
246    iris_batch_maybe_flush(batch, 1500);
247 
248    iris_update_draw_parameters(ice, draw, drawid_offset, indirect, sc);
249 
250    batch->screen->vtbl.upload_render_state(ice, batch, draw, drawid_offset, indirect, sc);
251 }
252 
253 /**
254  * The pipe->draw_vbo() driver hook.  Performs a draw on the GPU.
255  */
256 void
iris_draw_vbo(struct pipe_context * ctx,const struct pipe_draw_info * info,unsigned drawid_offset,const struct pipe_draw_indirect_info * indirect,const struct pipe_draw_start_count_bias * draws,unsigned num_draws)257 iris_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info,
258               unsigned drawid_offset,
259               const struct pipe_draw_indirect_info *indirect,
260               const struct pipe_draw_start_count_bias *draws,
261               unsigned num_draws)
262 {
263    if (num_draws > 1) {
264       util_draw_multi(ctx, info, drawid_offset, indirect, draws, num_draws);
265       return;
266    }
267 
268    if (!indirect && (!draws[0].count || !info->instance_count))
269       return;
270 
271    struct iris_context *ice = (struct iris_context *) ctx;
272    struct iris_screen *screen = (struct iris_screen*)ice->ctx.screen;
273    const struct intel_device_info *devinfo = &screen->devinfo;
274    struct iris_batch *batch = &ice->batches[IRIS_BATCH_RENDER];
275 
276    if (ice->state.predicate == IRIS_PREDICATE_STATE_DONT_RENDER)
277       return;
278 
279    if (INTEL_DEBUG(DEBUG_REEMIT)) {
280       ice->state.dirty |= IRIS_ALL_DIRTY_FOR_RENDER;
281       ice->state.stage_dirty |= IRIS_ALL_STAGE_DIRTY_FOR_RENDER;
282    }
283 
284    iris_update_draw_info(ice, info);
285 
286    if (devinfo->ver == 9)
287       gfx9_toggle_preemption(ice, batch, info);
288 
289    iris_update_compiled_shaders(ice);
290 
291    if (ice->state.dirty & IRIS_DIRTY_RENDER_RESOLVES_AND_FLUSHES) {
292       bool draw_aux_buffer_disabled[BRW_MAX_DRAW_BUFFERS] = { };
293       for (gl_shader_stage stage = 0; stage < MESA_SHADER_COMPUTE; stage++) {
294          if (ice->shaders.prog[stage])
295             iris_predraw_resolve_inputs(ice, batch, draw_aux_buffer_disabled,
296                                         stage, true);
297       }
298       iris_predraw_resolve_framebuffer(ice, batch, draw_aux_buffer_disabled);
299    }
300 
301    if (ice->state.dirty & IRIS_DIRTY_RENDER_MISC_BUFFER_FLUSHES) {
302       for (gl_shader_stage stage = 0; stage < MESA_SHADER_COMPUTE; stage++)
303          iris_predraw_flush_buffers(ice, batch, stage);
304    }
305 
306    iris_binder_reserve_3d(ice);
307 
308    batch->screen->vtbl.update_binder_address(batch, &ice->state.binder);
309 
310    iris_handle_always_flush_cache(batch);
311 
312    if (indirect && indirect->buffer)
313       iris_indirect_draw_vbo(ice, info, drawid_offset, indirect, &draws[0]);
314    else
315       iris_simple_draw_vbo(ice, info, drawid_offset, indirect, &draws[0]);
316 
317    iris_handle_always_flush_cache(batch);
318 
319    iris_postdraw_update_resolve_tracking(ice, batch);
320 
321    ice->state.dirty &= ~IRIS_ALL_DIRTY_FOR_RENDER;
322    ice->state.stage_dirty &= ~IRIS_ALL_STAGE_DIRTY_FOR_RENDER;
323 }
324 
325 static void
iris_update_grid_size_resource(struct iris_context * ice,const struct pipe_grid_info * grid)326 iris_update_grid_size_resource(struct iris_context *ice,
327                                const struct pipe_grid_info *grid)
328 {
329    const struct iris_screen *screen = (void *) ice->ctx.screen;
330    const struct isl_device *isl_dev = &screen->isl_dev;
331    struct iris_state_ref *grid_ref = &ice->state.grid_size;
332    struct iris_state_ref *state_ref = &ice->state.grid_surf_state;
333 
334    const struct iris_compiled_shader *shader = ice->shaders.prog[MESA_SHADER_COMPUTE];
335    bool grid_needs_surface = shader->bt.used_mask[IRIS_SURFACE_GROUP_CS_WORK_GROUPS];
336    bool grid_updated = false;
337 
338    if (grid->indirect) {
339       pipe_resource_reference(&grid_ref->res, grid->indirect);
340       grid_ref->offset = grid->indirect_offset;
341 
342       /* Zero out the grid size so that the next non-indirect grid launch will
343        * re-upload it properly.
344        */
345       memset(ice->state.last_grid, 0, sizeof(ice->state.last_grid));
346       grid_updated = true;
347    } else if (memcmp(ice->state.last_grid, grid->grid, sizeof(grid->grid)) != 0) {
348       memcpy(ice->state.last_grid, grid->grid, sizeof(grid->grid));
349       u_upload_data(ice->state.dynamic_uploader, 0, sizeof(grid->grid), 4,
350                     grid->grid, &grid_ref->offset, &grid_ref->res);
351       grid_updated = true;
352    }
353 
354    /* If we changed the grid, the old surface state is invalid. */
355    if (grid_updated)
356       pipe_resource_reference(&state_ref->res, NULL);
357 
358    /* Skip surface upload if we don't need it or we already have one */
359    if (!grid_needs_surface || state_ref->res)
360       return;
361 
362    struct iris_bo *grid_bo = iris_resource_bo(grid_ref->res);
363 
364    void *surf_map = NULL;
365    u_upload_alloc(ice->state.surface_uploader, 0, isl_dev->ss.size,
366                   isl_dev->ss.align, &state_ref->offset, &state_ref->res,
367                   &surf_map);
368    state_ref->offset +=
369       iris_bo_offset_from_base_address(iris_resource_bo(state_ref->res));
370    isl_buffer_fill_state(&screen->isl_dev, surf_map,
371                          .address = grid_ref->offset + grid_bo->address,
372                          .size_B = sizeof(grid->grid),
373                          .format = ISL_FORMAT_RAW,
374                          .stride_B = 1,
375                          .mocs = iris_mocs(grid_bo, isl_dev,
376                                            ISL_SURF_USAGE_CONSTANT_BUFFER_BIT));
377 
378    ice->state.stage_dirty |= IRIS_STAGE_DIRTY_BINDINGS_CS;
379 }
380 
381 void
iris_launch_grid(struct pipe_context * ctx,const struct pipe_grid_info * grid)382 iris_launch_grid(struct pipe_context *ctx, const struct pipe_grid_info *grid)
383 {
384    struct iris_context *ice = (struct iris_context *) ctx;
385    struct iris_batch *batch = &ice->batches[IRIS_BATCH_COMPUTE];
386 
387    if (ice->state.predicate == IRIS_PREDICATE_STATE_DONT_RENDER)
388       return;
389 
390    if (INTEL_DEBUG(DEBUG_REEMIT)) {
391       ice->state.dirty |= IRIS_ALL_DIRTY_FOR_COMPUTE;
392       ice->state.stage_dirty |= IRIS_ALL_STAGE_DIRTY_FOR_COMPUTE;
393    }
394 
395    if (ice->state.dirty & IRIS_DIRTY_COMPUTE_RESOLVES_AND_FLUSHES)
396       iris_predraw_resolve_inputs(ice, batch, NULL, MESA_SHADER_COMPUTE, false);
397 
398    if (ice->state.dirty & IRIS_DIRTY_COMPUTE_MISC_BUFFER_FLUSHES)
399       iris_predraw_flush_buffers(ice, batch, MESA_SHADER_COMPUTE);
400 
401    iris_batch_maybe_flush(batch, 1500);
402 
403    iris_update_compiled_compute_shader(ice);
404 
405    if (memcmp(ice->state.last_block, grid->block, sizeof(grid->block)) != 0) {
406       memcpy(ice->state.last_block, grid->block, sizeof(grid->block));
407       ice->state.stage_dirty |= IRIS_STAGE_DIRTY_CONSTANTS_CS;
408       ice->state.shaders[MESA_SHADER_COMPUTE].sysvals_need_upload = true;
409    }
410 
411    iris_update_grid_size_resource(ice, grid);
412 
413    iris_binder_reserve_compute(ice);
414    batch->screen->vtbl.update_binder_address(batch, &ice->state.binder);
415 
416    if (ice->state.compute_predicate) {
417       batch->screen->vtbl.load_register_mem64(batch, MI_PREDICATE_RESULT,
418                                     ice->state.compute_predicate, 0);
419       ice->state.compute_predicate = NULL;
420    }
421 
422    iris_handle_always_flush_cache(batch);
423 
424    batch->screen->vtbl.upload_compute_state(ice, batch, grid);
425 
426    iris_handle_always_flush_cache(batch);
427 
428    ice->state.dirty &= ~IRIS_ALL_DIRTY_FOR_COMPUTE;
429    ice->state.stage_dirty &= ~IRIS_ALL_STAGE_DIRTY_FOR_COMPUTE;
430 
431    /* Note: since compute shaders can't access the framebuffer, there's
432     * no need to call iris_postdraw_update_resolve_tracking.
433     */
434 }
435