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