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