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