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 crocus_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 "crocus_context.h"
42 #include "crocus_defines.h"
43 #include "util/u_prim_restart.h"
44 #include "util/u_prim.h"
45 
46 static bool
prim_is_points_or_lines(enum pipe_prim_type mode)47 prim_is_points_or_lines(enum pipe_prim_type mode)
48 {
49    /* We don't need to worry about adjacency - it can only be used with
50     * geometry shaders, and we don't care about this info when GS is on.
51     */
52    return mode == PIPE_PRIM_POINTS ||
53           mode == PIPE_PRIM_LINES ||
54           mode == PIPE_PRIM_LINE_LOOP ||
55           mode == PIPE_PRIM_LINE_STRIP;
56 }
57 
58 static bool
can_cut_index_handle_restart_index(struct crocus_context * ice,const struct pipe_draw_info * draw)59 can_cut_index_handle_restart_index(struct crocus_context *ice,
60                                    const struct pipe_draw_info *draw)
61 {
62    switch (draw->index_size) {
63    case 1:
64       return draw->restart_index == 0xff;
65    case 2:
66       return draw->restart_index == 0xffff;
67    case 4:
68       return draw->restart_index == 0xffffffff;
69    default:
70       unreachable("illegal index size\n");
71    }
72 
73    return false;
74 }
75 
76 static bool
can_cut_index_handle_prim(struct crocus_context * ice,const struct pipe_draw_info * draw)77 can_cut_index_handle_prim(struct crocus_context *ice,
78                           const struct pipe_draw_info *draw)
79 {
80    struct crocus_screen *screen = (struct crocus_screen*)ice->ctx.screen;
81    const struct intel_device_info *devinfo = &screen->devinfo;
82 
83    /* Haswell can do it all. */
84    if (devinfo->verx10 >= 75)
85       return true;
86 
87    if (!can_cut_index_handle_restart_index(ice, draw))
88       return false;
89 
90    switch (draw->mode) {
91    case PIPE_PRIM_POINTS:
92    case PIPE_PRIM_LINES:
93    case PIPE_PRIM_LINE_STRIP:
94    case PIPE_PRIM_TRIANGLES:
95    case PIPE_PRIM_TRIANGLE_STRIP:
96    case PIPE_PRIM_LINES_ADJACENCY:
97    case PIPE_PRIM_LINE_STRIP_ADJACENCY:
98    case PIPE_PRIM_TRIANGLES_ADJACENCY:
99    case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
100       return true;
101    default:
102       break;
103    }
104    return false;
105 }
106 
107 /**
108  * Record the current primitive mode and restart information, flagging
109  * related packets as dirty if necessary.
110  *
111  * This must be called before updating compiled shaders, because the patch
112  * information informs the TCS key.
113  */
114 static void
crocus_update_draw_info(struct crocus_context * ice,const struct pipe_draw_info * info,const struct pipe_draw_start_count_bias * draw)115 crocus_update_draw_info(struct crocus_context *ice,
116                         const struct pipe_draw_info *info,
117                         const struct pipe_draw_start_count_bias *draw)
118 {
119    struct crocus_screen *screen = (struct crocus_screen *)ice->ctx.screen;
120    enum pipe_prim_type mode = info->mode;
121 
122    if (screen->devinfo.ver < 6) {
123       /* Slight optimization to avoid the GS program when not needed:
124        */
125       struct pipe_rasterizer_state *rs_state = crocus_get_rast_state(ice);
126       if (mode == PIPE_PRIM_QUAD_STRIP && !rs_state->flatshade &&
127           rs_state->fill_front == PIPE_POLYGON_MODE_FILL &&
128           rs_state->fill_back == PIPE_POLYGON_MODE_FILL)
129          mode = PIPE_PRIM_TRIANGLE_STRIP;
130       if (mode == PIPE_PRIM_QUADS &&
131           draw->count == 4 &&
132           !rs_state->flatshade &&
133           rs_state->fill_front == PIPE_POLYGON_MODE_FILL &&
134           rs_state->fill_back == PIPE_POLYGON_MODE_FILL)
135          mode = PIPE_PRIM_TRIANGLE_FAN;
136    }
137 
138    if (ice->state.prim_mode != mode) {
139       ice->state.prim_mode = mode;
140 
141       enum pipe_prim_type reduced = u_reduced_prim(mode);
142       if (ice->state.reduced_prim_mode != reduced) {
143          if (screen->devinfo.ver < 6)
144             ice->state.dirty |= CROCUS_DIRTY_GEN4_CLIP_PROG | CROCUS_DIRTY_GEN4_SF_PROG;
145          /* if the reduced prim changes the WM needs updating. */
146          ice->state.stage_dirty |= CROCUS_STAGE_DIRTY_UNCOMPILED_FS;
147          ice->state.reduced_prim_mode = reduced;
148       }
149 
150       if (screen->devinfo.ver == 8)
151          ice->state.dirty |= CROCUS_DIRTY_GEN8_VF_TOPOLOGY;
152 
153       if (screen->devinfo.ver <= 6)
154          ice->state.dirty |= CROCUS_DIRTY_GEN4_FF_GS_PROG;
155 
156       if (screen->devinfo.ver >= 7)
157          ice->state.dirty |= CROCUS_DIRTY_GEN7_SBE;
158 
159       /* For XY Clip enables */
160       bool points_or_lines = prim_is_points_or_lines(mode);
161       if (points_or_lines != ice->state.prim_is_points_or_lines) {
162          ice->state.prim_is_points_or_lines = points_or_lines;
163          ice->state.dirty |= CROCUS_DIRTY_CLIP;
164       }
165    }
166 
167    if (info->mode == PIPE_PRIM_PATCHES &&
168        ice->state.vertices_per_patch != ice->state.patch_vertices) {
169       ice->state.vertices_per_patch = ice->state.patch_vertices;
170 
171       if (screen->devinfo.ver == 8)
172          ice->state.dirty |= CROCUS_DIRTY_GEN8_VF_TOPOLOGY;
173       /* This is needed for key->input_vertices */
174       ice->state.stage_dirty |= CROCUS_STAGE_DIRTY_UNCOMPILED_TCS;
175 
176       /* Flag constants dirty for gl_PatchVerticesIn if needed. */
177       const struct shader_info *tcs_info =
178          crocus_get_shader_info(ice, MESA_SHADER_TESS_CTRL);
179       if (tcs_info &&
180           BITSET_TEST(tcs_info->system_values_read, SYSTEM_VALUE_VERTICES_IN)) {
181          ice->state.stage_dirty |= CROCUS_STAGE_DIRTY_CONSTANTS_TCS;
182          ice->state.shaders[MESA_SHADER_TESS_CTRL].sysvals_need_upload = true;
183       }
184    }
185 
186    const unsigned cut_index = info->primitive_restart ? info->restart_index :
187                                                         ice->state.cut_index;
188    if (ice->state.primitive_restart != info->primitive_restart ||
189        ice->state.cut_index != cut_index) {
190       if (screen->devinfo.verx10 >= 75)
191          ice->state.dirty |= CROCUS_DIRTY_GEN75_VF;
192       ice->state.primitive_restart = info->primitive_restart;
193       ice->state.cut_index = info->restart_index;
194    }
195 }
196 
197 /**
198  * Update shader draw parameters, flagging VF packets as dirty if necessary.
199  */
200 static void
crocus_update_draw_parameters(struct crocus_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)201 crocus_update_draw_parameters(struct crocus_context *ice,
202                               const struct pipe_draw_info *info,
203                               unsigned drawid_offset,
204                               const struct pipe_draw_indirect_info *indirect,
205                               const struct pipe_draw_start_count_bias *draw)
206 {
207    bool changed = false;
208 
209    if (ice->state.vs_uses_draw_params) {
210       struct crocus_state_ref *draw_params = &ice->draw.draw_params;
211 
212       if (indirect && indirect->buffer) {
213          pipe_resource_reference(&draw_params->res, indirect->buffer);
214          draw_params->offset =
215             indirect->offset + (info->index_size ? 12 : 8);
216 
217          changed = true;
218          ice->draw.params_valid = false;
219       } else {
220          int firstvertex = info->index_size ? draw->index_bias : draw->start;
221 
222          if (!ice->draw.params_valid ||
223              ice->draw.params.firstvertex != firstvertex ||
224              ice->draw.params.baseinstance != info->start_instance) {
225 
226             changed = true;
227             ice->draw.params.firstvertex = firstvertex;
228             ice->draw.params.baseinstance = info->start_instance;
229             ice->draw.params_valid = true;
230 
231             u_upload_data(ice->ctx.stream_uploader, 0,
232                           sizeof(ice->draw.params), 4, &ice->draw.params,
233                           &draw_params->offset, &draw_params->res);
234          }
235       }
236    }
237 
238    if (ice->state.vs_uses_derived_draw_params) {
239       struct crocus_state_ref *derived_params = &ice->draw.derived_draw_params;
240       int is_indexed_draw = info->index_size ? -1 : 0;
241 
242       if (ice->draw.derived_params.drawid != drawid_offset ||
243           ice->draw.derived_params.is_indexed_draw != is_indexed_draw) {
244 
245          changed = true;
246          ice->draw.derived_params.drawid = drawid_offset;
247          ice->draw.derived_params.is_indexed_draw = is_indexed_draw;
248 
249          u_upload_data(ice->ctx.stream_uploader, 0,
250                        sizeof(ice->draw.derived_params), 4,
251                        &ice->draw.derived_params, &derived_params->offset,
252                        &derived_params->res);
253       }
254    }
255 
256    if (changed) {
257       struct crocus_screen *screen = (struct crocus_screen *)ice->ctx.screen;
258       ice->state.dirty |= CROCUS_DIRTY_VERTEX_BUFFERS |
259                           CROCUS_DIRTY_VERTEX_ELEMENTS;
260       if (screen->devinfo.ver == 8)
261          ice->state.dirty |= CROCUS_DIRTY_GEN8_VF_SGVS;
262    }
263 }
264 
265 static void
crocus_indirect_draw_vbo(struct crocus_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 * draws)266 crocus_indirect_draw_vbo(struct crocus_context *ice,
267                          const struct pipe_draw_info *dinfo,
268                          unsigned drawid_offset,
269                          const struct pipe_draw_indirect_info *dindirect,
270                          const struct pipe_draw_start_count_bias *draws)
271 {
272    struct crocus_batch *batch = &ice->batches[CROCUS_BATCH_RENDER];
273    struct crocus_screen *screen = batch->screen;
274    struct pipe_draw_info info = *dinfo;
275    struct pipe_draw_indirect_info indirect = *dindirect;
276    const struct intel_device_info *devinfo = &batch->screen->devinfo;
277 
278    if (devinfo->verx10 >= 75 && indirect.indirect_draw_count &&
279        ice->state.predicate == CROCUS_PREDICATE_STATE_USE_BIT) {
280       /* Upload MI_PREDICATE_RESULT to GPR15.*/
281       screen->vtbl.load_register_reg64(batch, CS_GPR(15), MI_PREDICATE_RESULT);
282    }
283 
284    uint64_t orig_dirty = ice->state.dirty;
285    uint64_t orig_stage_dirty = ice->state.stage_dirty;
286 
287    for (int i = 0; i < indirect.draw_count; i++) {
288       crocus_batch_maybe_flush(batch, 1500);
289       crocus_require_statebuffer_space(batch, 2400);
290 
291       if (ice->state.vs_uses_draw_params ||
292 	  ice->state.vs_uses_derived_draw_params)
293          crocus_update_draw_parameters(ice, &info, drawid_offset + i, &indirect, draws);
294 
295       screen->vtbl.upload_render_state(ice, batch, &info, drawid_offset + i, &indirect, draws);
296 
297       ice->state.dirty &= ~CROCUS_ALL_DIRTY_FOR_RENDER;
298       ice->state.stage_dirty &= ~CROCUS_ALL_STAGE_DIRTY_FOR_RENDER;
299 
300       indirect.offset += indirect.stride;
301    }
302 
303    if (devinfo->verx10 >= 75 && indirect.indirect_draw_count &&
304        ice->state.predicate == CROCUS_PREDICATE_STATE_USE_BIT) {
305       /* Restore MI_PREDICATE_RESULT. */
306       screen->vtbl.load_register_reg64(batch, MI_PREDICATE_RESULT, CS_GPR(15));
307    }
308 
309    /* Put this back for post-draw resolves, we'll clear it again after. */
310    ice->state.dirty = orig_dirty;
311    ice->state.stage_dirty = orig_stage_dirty;
312 }
313 
314 static void
crocus_simple_draw_vbo(struct crocus_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)315 crocus_simple_draw_vbo(struct crocus_context *ice,
316                        const struct pipe_draw_info *draw,
317                        unsigned drawid_offset,
318                        const struct pipe_draw_indirect_info *indirect,
319                        const struct pipe_draw_start_count_bias *sc)
320 {
321    struct crocus_batch *batch = &ice->batches[CROCUS_BATCH_RENDER];
322    struct crocus_screen *screen = batch->screen;
323 
324    crocus_batch_maybe_flush(batch, 1500);
325    crocus_require_statebuffer_space(batch, 2400);
326 
327    if (ice->state.vs_uses_draw_params ||
328        ice->state.vs_uses_derived_draw_params)
329       crocus_update_draw_parameters(ice, draw, drawid_offset, indirect, sc);
330 
331    screen->vtbl.upload_render_state(ice, batch, draw, drawid_offset, indirect, sc);
332 }
333 
334 static void
crocus_draw_vbo_get_vertex_count(struct pipe_context * ctx,const struct pipe_draw_info * info_in,unsigned drawid_offset,const struct pipe_draw_indirect_info * indirect)335 crocus_draw_vbo_get_vertex_count(struct pipe_context *ctx,
336                                  const struct pipe_draw_info *info_in,
337                                  unsigned drawid_offset,
338                                  const struct pipe_draw_indirect_info *indirect)
339 {
340    struct crocus_screen *screen = (struct crocus_screen *)ctx->screen;
341    struct pipe_draw_info info = *info_in;
342    struct pipe_draw_start_count_bias draw;
343 
344    uint32_t val = screen->vtbl.get_so_offset(indirect->count_from_stream_output);
345 
346    draw.start = 0;
347    draw.count = val;
348    ctx->draw_vbo(ctx, &info, drawid_offset, NULL, &draw, 1);
349 }
350 
351 /**
352  * The pipe->draw_vbo() driver hook.  Performs a draw on the GPU.
353  */
354 void
crocus_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)355 crocus_draw_vbo(struct pipe_context *ctx,
356                 const struct pipe_draw_info *info,
357                 unsigned drawid_offset,
358                 const struct pipe_draw_indirect_info *indirect,
359                 const struct pipe_draw_start_count_bias *draws,
360                 unsigned num_draws)
361 {
362    if (num_draws > 1) {
363       util_draw_multi(ctx, info, drawid_offset, indirect, draws, num_draws);
364       return;
365    }
366 
367    if (!indirect && (!draws[0].count || !info->instance_count))
368       return;
369 
370    struct crocus_context *ice = (struct crocus_context *) ctx;
371    struct crocus_screen *screen = (struct crocus_screen*)ice->ctx.screen;
372    struct crocus_batch *batch = &ice->batches[CROCUS_BATCH_RENDER];
373 
374    if (!crocus_check_conditional_render(ice))
375       return;
376 
377    if (info->primitive_restart && !can_cut_index_handle_prim(ice, info)) {
378       util_draw_vbo_without_prim_restart(ctx, info, drawid_offset,
379                                          indirect, draws);
380       return;
381    }
382 
383    if (screen->devinfo.verx10 < 75 &&
384        indirect && indirect->count_from_stream_output) {
385       crocus_draw_vbo_get_vertex_count(ctx, info, drawid_offset, indirect);
386       return;
387    }
388 
389    /**
390     * The hardware is capable of removing dangling vertices on its own; however,
391     * prior to Gen6, we sometimes convert quads into trifans (and quad strips
392     * into tristrips), since pre-Gen6 hardware requires a GS to render quads.
393     * This function manually trims dangling vertices from a draw call involving
394     * quads so that those dangling vertices won't get drawn when we convert to
395     * trifans/tristrips.
396     */
397    if (screen->devinfo.ver < 6) {
398       if (info->mode == PIPE_PRIM_QUADS || info->mode == PIPE_PRIM_QUAD_STRIP) {
399          bool trim = u_trim_pipe_prim(info->mode, (unsigned *)&draws[0].count);
400          if (!trim)
401             return;
402       }
403    }
404 
405    /* We can't safely re-emit 3DSTATE_SO_BUFFERS because it may zero the
406     * write offsets, changing the behavior.
407     */
408    if (INTEL_DEBUG(DEBUG_REEMIT)) {
409       ice->state.dirty |= CROCUS_ALL_DIRTY_FOR_RENDER & ~(CROCUS_DIRTY_GEN7_SO_BUFFERS | CROCUS_DIRTY_GEN6_SVBI);
410       ice->state.stage_dirty |= CROCUS_ALL_STAGE_DIRTY_FOR_RENDER;
411    }
412 
413    /* Emit Sandybridge workaround flushes on every primitive, for safety. */
414    if (screen->devinfo.ver == 6)
415       crocus_emit_post_sync_nonzero_flush(batch);
416 
417    crocus_update_draw_info(ice, info, draws);
418 
419    if (!crocus_update_compiled_shaders(ice))
420       return;
421 
422    if (ice->state.dirty & CROCUS_DIRTY_RENDER_RESOLVES_AND_FLUSHES) {
423       bool draw_aux_buffer_disabled[BRW_MAX_DRAW_BUFFERS] = { };
424       for (gl_shader_stage stage = 0; stage < MESA_SHADER_COMPUTE; stage++) {
425          if (ice->shaders.prog[stage])
426             crocus_predraw_resolve_inputs(ice, batch, draw_aux_buffer_disabled,
427                                           stage, true);
428       }
429       crocus_predraw_resolve_framebuffer(ice, batch, draw_aux_buffer_disabled);
430    }
431 
432    crocus_handle_always_flush_cache(batch);
433 
434    if (indirect && indirect->buffer)
435       crocus_indirect_draw_vbo(ice, info, drawid_offset, indirect, draws);
436    else
437       crocus_simple_draw_vbo(ice, info, drawid_offset, indirect, draws);
438 
439    crocus_handle_always_flush_cache(batch);
440 
441    crocus_postdraw_update_resolve_tracking(ice, batch);
442 
443    ice->state.dirty &= ~CROCUS_ALL_DIRTY_FOR_RENDER;
444    ice->state.stage_dirty &= ~CROCUS_ALL_STAGE_DIRTY_FOR_RENDER;
445 }
446 
447 static void
crocus_update_grid_size_resource(struct crocus_context * ice,const struct pipe_grid_info * grid)448 crocus_update_grid_size_resource(struct crocus_context *ice,
449                                  const struct pipe_grid_info *grid)
450 {
451    struct crocus_state_ref *grid_ref = &ice->state.grid_size;
452    const struct crocus_compiled_shader *shader = ice->shaders.prog[MESA_SHADER_COMPUTE];
453    bool grid_needs_surface = shader->bt.used_mask[CROCUS_SURFACE_GROUP_CS_WORK_GROUPS];
454 
455    if (grid->indirect) {
456       pipe_resource_reference(&grid_ref->res, grid->indirect);
457       grid_ref->offset = grid->indirect_offset;
458 
459       /* Zero out the grid size so that the next non-indirect grid launch will
460        * re-upload it properly.
461        */
462       memset(ice->state.last_grid, 0, sizeof(ice->state.last_grid));
463    } else if (memcmp(ice->state.last_grid, grid->grid, sizeof(grid->grid)) != 0) {
464       memcpy(ice->state.last_grid, grid->grid, sizeof(grid->grid));
465       u_upload_data(ice->ctx.const_uploader, 0, sizeof(grid->grid), 4,
466                     grid->grid, &grid_ref->offset, &grid_ref->res);
467    }
468 
469    /* Skip surface upload if we don't need it or we already have one */
470    if (!grid_needs_surface)
471       return;
472 
473    ice->state.stage_dirty |= CROCUS_STAGE_DIRTY_BINDINGS_CS;
474 }
475 
476 
477 void
crocus_launch_grid(struct pipe_context * ctx,const struct pipe_grid_info * grid)478 crocus_launch_grid(struct pipe_context *ctx, const struct pipe_grid_info *grid)
479 {
480    struct crocus_context *ice = (struct crocus_context *) ctx;
481    struct crocus_batch *batch = &ice->batches[CROCUS_BATCH_COMPUTE];
482    struct crocus_screen *screen = batch->screen;
483 
484    if (!crocus_check_conditional_render(ice))
485       return;
486 
487    if (INTEL_DEBUG(DEBUG_REEMIT)) {
488       ice->state.dirty |= CROCUS_ALL_DIRTY_FOR_COMPUTE;
489       ice->state.stage_dirty |= CROCUS_ALL_STAGE_DIRTY_FOR_COMPUTE;
490    }
491 
492    /* We can't do resolves on the compute engine, so awkwardly, we have to
493     * do them on the render batch...
494     */
495    if (ice->state.dirty & CROCUS_DIRTY_COMPUTE_RESOLVES_AND_FLUSHES) {
496       crocus_predraw_resolve_inputs(ice, &ice->batches[CROCUS_BATCH_RENDER], NULL,
497                                     MESA_SHADER_COMPUTE, false);
498    }
499 
500    crocus_batch_maybe_flush(batch, 1500);
501    crocus_require_statebuffer_space(batch, 2500);
502    crocus_update_compiled_compute_shader(ice);
503 
504    if (memcmp(ice->state.last_block, grid->block, sizeof(grid->block)) != 0) {
505       memcpy(ice->state.last_block, grid->block, sizeof(grid->block));
506       ice->state.stage_dirty |= CROCUS_STAGE_DIRTY_CONSTANTS_CS;
507       ice->state.shaders[MESA_SHADER_COMPUTE].sysvals_need_upload = true;
508    }
509 
510    crocus_update_grid_size_resource(ice, grid);
511 
512    if (ice->state.compute_predicate) {
513       screen->vtbl.emit_compute_predicate(batch);
514       ice->state.compute_predicate = NULL;
515    }
516 
517    crocus_handle_always_flush_cache(batch);
518 
519    screen->vtbl.upload_compute_state(ice, batch, grid);
520 
521    crocus_handle_always_flush_cache(batch);
522 
523    ice->state.dirty &= ~CROCUS_ALL_DIRTY_FOR_COMPUTE;
524    ice->state.stage_dirty &= ~CROCUS_ALL_STAGE_DIRTY_FOR_COMPUTE;
525 
526    /* Note: since compute shaders can't access the framebuffer, there's
527     * no need to call crocus_postdraw_update_resolve_tracking.
528     */
529 }
530