17ec681f3Smrg/* 27ec681f3Smrg * Copyright © 2017 Intel Corporation 37ec681f3Smrg * 47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a 57ec681f3Smrg * copy of this software and associated documentation files (the "Software"), 67ec681f3Smrg * to deal in the Software without restriction, including without limitation 77ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 87ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the 97ec681f3Smrg * Software is furnished to do so, subject to the following conditions: 107ec681f3Smrg * 117ec681f3Smrg * The above copyright notice and this permission notice shall be included 127ec681f3Smrg * in all copies or substantial portions of the Software. 137ec681f3Smrg * 147ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 157ec681f3Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 167ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 177ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 187ec681f3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 197ec681f3Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 207ec681f3Smrg * DEALINGS IN THE SOFTWARE. 217ec681f3Smrg */ 227ec681f3Smrg 237ec681f3Smrg/** 247ec681f3Smrg * @file crocus_draw.c 257ec681f3Smrg * 267ec681f3Smrg * The main driver hooks for drawing and launching compute shaders. 277ec681f3Smrg */ 287ec681f3Smrg 297ec681f3Smrg#include <stdio.h> 307ec681f3Smrg#include <errno.h> 317ec681f3Smrg#include "pipe/p_defines.h" 327ec681f3Smrg#include "pipe/p_state.h" 337ec681f3Smrg#include "pipe/p_context.h" 347ec681f3Smrg#include "pipe/p_screen.h" 357ec681f3Smrg#include "util/u_draw.h" 367ec681f3Smrg#include "util/u_inlines.h" 377ec681f3Smrg#include "util/u_transfer.h" 387ec681f3Smrg#include "util/u_upload_mgr.h" 397ec681f3Smrg#include "intel/compiler/brw_compiler.h" 407ec681f3Smrg#include "intel/compiler/brw_eu_defines.h" 417ec681f3Smrg#include "crocus_context.h" 427ec681f3Smrg#include "crocus_defines.h" 437ec681f3Smrg#include "util/u_prim_restart.h" 447ec681f3Smrg#include "util/u_prim.h" 457ec681f3Smrg 467ec681f3Smrgstatic bool 477ec681f3Smrgprim_is_points_or_lines(enum pipe_prim_type mode) 487ec681f3Smrg{ 497ec681f3Smrg /* We don't need to worry about adjacency - it can only be used with 507ec681f3Smrg * geometry shaders, and we don't care about this info when GS is on. 517ec681f3Smrg */ 527ec681f3Smrg return mode == PIPE_PRIM_POINTS || 537ec681f3Smrg mode == PIPE_PRIM_LINES || 547ec681f3Smrg mode == PIPE_PRIM_LINE_LOOP || 557ec681f3Smrg mode == PIPE_PRIM_LINE_STRIP; 567ec681f3Smrg} 577ec681f3Smrg 587ec681f3Smrgstatic bool 597ec681f3Smrgcan_cut_index_handle_restart_index(struct crocus_context *ice, 607ec681f3Smrg const struct pipe_draw_info *draw) 617ec681f3Smrg{ 627ec681f3Smrg switch (draw->index_size) { 637ec681f3Smrg case 1: 647ec681f3Smrg return draw->restart_index == 0xff; 657ec681f3Smrg case 2: 667ec681f3Smrg return draw->restart_index == 0xffff; 677ec681f3Smrg case 4: 687ec681f3Smrg return draw->restart_index == 0xffffffff; 697ec681f3Smrg default: 707ec681f3Smrg unreachable("illegal index size\n"); 717ec681f3Smrg } 727ec681f3Smrg 737ec681f3Smrg return false; 747ec681f3Smrg} 757ec681f3Smrg 767ec681f3Smrgstatic bool 777ec681f3Smrgcan_cut_index_handle_prim(struct crocus_context *ice, 787ec681f3Smrg const struct pipe_draw_info *draw) 797ec681f3Smrg{ 807ec681f3Smrg struct crocus_screen *screen = (struct crocus_screen*)ice->ctx.screen; 817ec681f3Smrg const struct intel_device_info *devinfo = &screen->devinfo; 827ec681f3Smrg 837ec681f3Smrg /* Haswell can do it all. */ 847ec681f3Smrg if (devinfo->verx10 >= 75) 857ec681f3Smrg return true; 867ec681f3Smrg 877ec681f3Smrg if (!can_cut_index_handle_restart_index(ice, draw)) 887ec681f3Smrg return false; 897ec681f3Smrg 907ec681f3Smrg switch (draw->mode) { 917ec681f3Smrg case PIPE_PRIM_POINTS: 927ec681f3Smrg case PIPE_PRIM_LINES: 937ec681f3Smrg case PIPE_PRIM_LINE_STRIP: 947ec681f3Smrg case PIPE_PRIM_TRIANGLES: 957ec681f3Smrg case PIPE_PRIM_TRIANGLE_STRIP: 967ec681f3Smrg case PIPE_PRIM_LINES_ADJACENCY: 977ec681f3Smrg case PIPE_PRIM_LINE_STRIP_ADJACENCY: 987ec681f3Smrg case PIPE_PRIM_TRIANGLES_ADJACENCY: 997ec681f3Smrg case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY: 1007ec681f3Smrg return true; 1017ec681f3Smrg default: 1027ec681f3Smrg break; 1037ec681f3Smrg } 1047ec681f3Smrg return false; 1057ec681f3Smrg} 1067ec681f3Smrg 1077ec681f3Smrg/** 1087ec681f3Smrg * Record the current primitive mode and restart information, flagging 1097ec681f3Smrg * related packets as dirty if necessary. 1107ec681f3Smrg * 1117ec681f3Smrg * This must be called before updating compiled shaders, because the patch 1127ec681f3Smrg * information informs the TCS key. 1137ec681f3Smrg */ 1147ec681f3Smrgstatic void 1157ec681f3Smrgcrocus_update_draw_info(struct crocus_context *ice, 1167ec681f3Smrg const struct pipe_draw_info *info, 1177ec681f3Smrg const struct pipe_draw_start_count_bias *draw) 1187ec681f3Smrg{ 1197ec681f3Smrg struct crocus_screen *screen = (struct crocus_screen *)ice->ctx.screen; 1207ec681f3Smrg enum pipe_prim_type mode = info->mode; 1217ec681f3Smrg 1227ec681f3Smrg if (screen->devinfo.ver < 6) { 1237ec681f3Smrg /* Slight optimization to avoid the GS program when not needed: 1247ec681f3Smrg */ 1257ec681f3Smrg struct pipe_rasterizer_state *rs_state = crocus_get_rast_state(ice); 1267ec681f3Smrg if (mode == PIPE_PRIM_QUAD_STRIP && !rs_state->flatshade && 1277ec681f3Smrg rs_state->fill_front == PIPE_POLYGON_MODE_FILL && 1287ec681f3Smrg rs_state->fill_back == PIPE_POLYGON_MODE_FILL) 1297ec681f3Smrg mode = PIPE_PRIM_TRIANGLE_STRIP; 1307ec681f3Smrg if (mode == PIPE_PRIM_QUADS && 1317ec681f3Smrg draw->count == 4 && 1327ec681f3Smrg !rs_state->flatshade && 1337ec681f3Smrg rs_state->fill_front == PIPE_POLYGON_MODE_FILL && 1347ec681f3Smrg rs_state->fill_back == PIPE_POLYGON_MODE_FILL) 1357ec681f3Smrg mode = PIPE_PRIM_TRIANGLE_FAN; 1367ec681f3Smrg } 1377ec681f3Smrg 1387ec681f3Smrg if (ice->state.prim_mode != mode) { 1397ec681f3Smrg ice->state.prim_mode = mode; 1407ec681f3Smrg 1417ec681f3Smrg enum pipe_prim_type reduced = u_reduced_prim(mode); 1427ec681f3Smrg if (ice->state.reduced_prim_mode != reduced) { 1437ec681f3Smrg if (screen->devinfo.ver < 6) 1447ec681f3Smrg ice->state.dirty |= CROCUS_DIRTY_GEN4_CLIP_PROG | CROCUS_DIRTY_GEN4_SF_PROG; 1457ec681f3Smrg /* if the reduced prim changes the WM needs updating. */ 1467ec681f3Smrg ice->state.stage_dirty |= CROCUS_STAGE_DIRTY_UNCOMPILED_FS; 1477ec681f3Smrg ice->state.reduced_prim_mode = reduced; 1487ec681f3Smrg } 1497ec681f3Smrg 1507ec681f3Smrg if (screen->devinfo.ver == 8) 1517ec681f3Smrg ice->state.dirty |= CROCUS_DIRTY_GEN8_VF_TOPOLOGY; 1527ec681f3Smrg 1537ec681f3Smrg if (screen->devinfo.ver <= 6) 1547ec681f3Smrg ice->state.dirty |= CROCUS_DIRTY_GEN4_FF_GS_PROG; 1557ec681f3Smrg 1567ec681f3Smrg if (screen->devinfo.ver >= 7) 1577ec681f3Smrg ice->state.dirty |= CROCUS_DIRTY_GEN7_SBE; 1587ec681f3Smrg 1597ec681f3Smrg /* For XY Clip enables */ 1607ec681f3Smrg bool points_or_lines = prim_is_points_or_lines(mode); 1617ec681f3Smrg if (points_or_lines != ice->state.prim_is_points_or_lines) { 1627ec681f3Smrg ice->state.prim_is_points_or_lines = points_or_lines; 1637ec681f3Smrg ice->state.dirty |= CROCUS_DIRTY_CLIP; 1647ec681f3Smrg } 1657ec681f3Smrg } 1667ec681f3Smrg 1677ec681f3Smrg if (info->mode == PIPE_PRIM_PATCHES && 1687ec681f3Smrg ice->state.vertices_per_patch != ice->state.patch_vertices) { 1697ec681f3Smrg ice->state.vertices_per_patch = ice->state.patch_vertices; 1707ec681f3Smrg 1717ec681f3Smrg if (screen->devinfo.ver == 8) 1727ec681f3Smrg ice->state.dirty |= CROCUS_DIRTY_GEN8_VF_TOPOLOGY; 1737ec681f3Smrg /* This is needed for key->input_vertices */ 1747ec681f3Smrg ice->state.stage_dirty |= CROCUS_STAGE_DIRTY_UNCOMPILED_TCS; 1757ec681f3Smrg 1767ec681f3Smrg /* Flag constants dirty for gl_PatchVerticesIn if needed. */ 1777ec681f3Smrg const struct shader_info *tcs_info = 1787ec681f3Smrg crocus_get_shader_info(ice, MESA_SHADER_TESS_CTRL); 1797ec681f3Smrg if (tcs_info && 1807ec681f3Smrg BITSET_TEST(tcs_info->system_values_read, SYSTEM_VALUE_VERTICES_IN)) { 1817ec681f3Smrg ice->state.stage_dirty |= CROCUS_STAGE_DIRTY_CONSTANTS_TCS; 1827ec681f3Smrg ice->state.shaders[MESA_SHADER_TESS_CTRL].sysvals_need_upload = true; 1837ec681f3Smrg } 1847ec681f3Smrg } 1857ec681f3Smrg 1867ec681f3Smrg const unsigned cut_index = info->primitive_restart ? info->restart_index : 1877ec681f3Smrg ice->state.cut_index; 1887ec681f3Smrg if (ice->state.primitive_restart != info->primitive_restart || 1897ec681f3Smrg ice->state.cut_index != cut_index) { 1907ec681f3Smrg if (screen->devinfo.verx10 >= 75) 1917ec681f3Smrg ice->state.dirty |= CROCUS_DIRTY_GEN75_VF; 1927ec681f3Smrg ice->state.primitive_restart = info->primitive_restart; 1937ec681f3Smrg ice->state.cut_index = info->restart_index; 1947ec681f3Smrg } 1957ec681f3Smrg} 1967ec681f3Smrg 1977ec681f3Smrg/** 1987ec681f3Smrg * Update shader draw parameters, flagging VF packets as dirty if necessary. 1997ec681f3Smrg */ 2007ec681f3Smrgstatic void 2017ec681f3Smrgcrocus_update_draw_parameters(struct crocus_context *ice, 2027ec681f3Smrg const struct pipe_draw_info *info, 2037ec681f3Smrg unsigned drawid_offset, 2047ec681f3Smrg const struct pipe_draw_indirect_info *indirect, 2057ec681f3Smrg const struct pipe_draw_start_count_bias *draw) 2067ec681f3Smrg{ 2077ec681f3Smrg bool changed = false; 2087ec681f3Smrg 2097ec681f3Smrg if (ice->state.vs_uses_draw_params) { 2107ec681f3Smrg struct crocus_state_ref *draw_params = &ice->draw.draw_params; 2117ec681f3Smrg 2127ec681f3Smrg if (indirect && indirect->buffer) { 2137ec681f3Smrg pipe_resource_reference(&draw_params->res, indirect->buffer); 2147ec681f3Smrg draw_params->offset = 2157ec681f3Smrg indirect->offset + (info->index_size ? 12 : 8); 2167ec681f3Smrg 2177ec681f3Smrg changed = true; 2187ec681f3Smrg ice->draw.params_valid = false; 2197ec681f3Smrg } else { 2207ec681f3Smrg int firstvertex = info->index_size ? draw->index_bias : draw->start; 2217ec681f3Smrg 2227ec681f3Smrg if (!ice->draw.params_valid || 2237ec681f3Smrg ice->draw.params.firstvertex != firstvertex || 2247ec681f3Smrg ice->draw.params.baseinstance != info->start_instance) { 2257ec681f3Smrg 2267ec681f3Smrg changed = true; 2277ec681f3Smrg ice->draw.params.firstvertex = firstvertex; 2287ec681f3Smrg ice->draw.params.baseinstance = info->start_instance; 2297ec681f3Smrg ice->draw.params_valid = true; 2307ec681f3Smrg 2317ec681f3Smrg u_upload_data(ice->ctx.stream_uploader, 0, 2327ec681f3Smrg sizeof(ice->draw.params), 4, &ice->draw.params, 2337ec681f3Smrg &draw_params->offset, &draw_params->res); 2347ec681f3Smrg } 2357ec681f3Smrg } 2367ec681f3Smrg } 2377ec681f3Smrg 2387ec681f3Smrg if (ice->state.vs_uses_derived_draw_params) { 2397ec681f3Smrg struct crocus_state_ref *derived_params = &ice->draw.derived_draw_params; 2407ec681f3Smrg int is_indexed_draw = info->index_size ? -1 : 0; 2417ec681f3Smrg 2427ec681f3Smrg if (ice->draw.derived_params.drawid != drawid_offset || 2437ec681f3Smrg ice->draw.derived_params.is_indexed_draw != is_indexed_draw) { 2447ec681f3Smrg 2457ec681f3Smrg changed = true; 2467ec681f3Smrg ice->draw.derived_params.drawid = drawid_offset; 2477ec681f3Smrg ice->draw.derived_params.is_indexed_draw = is_indexed_draw; 2487ec681f3Smrg 2497ec681f3Smrg u_upload_data(ice->ctx.stream_uploader, 0, 2507ec681f3Smrg sizeof(ice->draw.derived_params), 4, 2517ec681f3Smrg &ice->draw.derived_params, &derived_params->offset, 2527ec681f3Smrg &derived_params->res); 2537ec681f3Smrg } 2547ec681f3Smrg } 2557ec681f3Smrg 2567ec681f3Smrg if (changed) { 2577ec681f3Smrg struct crocus_screen *screen = (struct crocus_screen *)ice->ctx.screen; 2587ec681f3Smrg ice->state.dirty |= CROCUS_DIRTY_VERTEX_BUFFERS | 2597ec681f3Smrg CROCUS_DIRTY_VERTEX_ELEMENTS; 2607ec681f3Smrg if (screen->devinfo.ver == 8) 2617ec681f3Smrg ice->state.dirty |= CROCUS_DIRTY_GEN8_VF_SGVS; 2627ec681f3Smrg } 2637ec681f3Smrg} 2647ec681f3Smrg 2657ec681f3Smrgstatic void 2667ec681f3Smrgcrocus_indirect_draw_vbo(struct crocus_context *ice, 2677ec681f3Smrg const struct pipe_draw_info *dinfo, 2687ec681f3Smrg unsigned drawid_offset, 2697ec681f3Smrg const struct pipe_draw_indirect_info *dindirect, 2707ec681f3Smrg const struct pipe_draw_start_count_bias *draws) 2717ec681f3Smrg{ 2727ec681f3Smrg struct crocus_batch *batch = &ice->batches[CROCUS_BATCH_RENDER]; 2737ec681f3Smrg struct crocus_screen *screen = batch->screen; 2747ec681f3Smrg struct pipe_draw_info info = *dinfo; 2757ec681f3Smrg struct pipe_draw_indirect_info indirect = *dindirect; 2767ec681f3Smrg const struct intel_device_info *devinfo = &batch->screen->devinfo; 2777ec681f3Smrg 2787ec681f3Smrg if (devinfo->verx10 >= 75 && indirect.indirect_draw_count && 2797ec681f3Smrg ice->state.predicate == CROCUS_PREDICATE_STATE_USE_BIT) { 2807ec681f3Smrg /* Upload MI_PREDICATE_RESULT to GPR15.*/ 2817ec681f3Smrg screen->vtbl.load_register_reg64(batch, CS_GPR(15), MI_PREDICATE_RESULT); 2827ec681f3Smrg } 2837ec681f3Smrg 2847ec681f3Smrg uint64_t orig_dirty = ice->state.dirty; 2857ec681f3Smrg uint64_t orig_stage_dirty = ice->state.stage_dirty; 2867ec681f3Smrg 2877ec681f3Smrg for (int i = 0; i < indirect.draw_count; i++) { 2887ec681f3Smrg crocus_batch_maybe_flush(batch, 1500); 2897ec681f3Smrg crocus_require_statebuffer_space(batch, 2400); 2907ec681f3Smrg 2917ec681f3Smrg if (ice->state.vs_uses_draw_params || 2927ec681f3Smrg ice->state.vs_uses_derived_draw_params) 2937ec681f3Smrg crocus_update_draw_parameters(ice, &info, drawid_offset + i, &indirect, draws); 2947ec681f3Smrg 2957ec681f3Smrg screen->vtbl.upload_render_state(ice, batch, &info, drawid_offset + i, &indirect, draws); 2967ec681f3Smrg 2977ec681f3Smrg ice->state.dirty &= ~CROCUS_ALL_DIRTY_FOR_RENDER; 2987ec681f3Smrg ice->state.stage_dirty &= ~CROCUS_ALL_STAGE_DIRTY_FOR_RENDER; 2997ec681f3Smrg 3007ec681f3Smrg indirect.offset += indirect.stride; 3017ec681f3Smrg } 3027ec681f3Smrg 3037ec681f3Smrg if (devinfo->verx10 >= 75 && indirect.indirect_draw_count && 3047ec681f3Smrg ice->state.predicate == CROCUS_PREDICATE_STATE_USE_BIT) { 3057ec681f3Smrg /* Restore MI_PREDICATE_RESULT. */ 3067ec681f3Smrg screen->vtbl.load_register_reg64(batch, MI_PREDICATE_RESULT, CS_GPR(15)); 3077ec681f3Smrg } 3087ec681f3Smrg 3097ec681f3Smrg /* Put this back for post-draw resolves, we'll clear it again after. */ 3107ec681f3Smrg ice->state.dirty = orig_dirty; 3117ec681f3Smrg ice->state.stage_dirty = orig_stage_dirty; 3127ec681f3Smrg} 3137ec681f3Smrg 3147ec681f3Smrgstatic void 3157ec681f3Smrgcrocus_simple_draw_vbo(struct crocus_context *ice, 3167ec681f3Smrg const struct pipe_draw_info *draw, 3177ec681f3Smrg unsigned drawid_offset, 3187ec681f3Smrg const struct pipe_draw_indirect_info *indirect, 3197ec681f3Smrg const struct pipe_draw_start_count_bias *sc) 3207ec681f3Smrg{ 3217ec681f3Smrg struct crocus_batch *batch = &ice->batches[CROCUS_BATCH_RENDER]; 3227ec681f3Smrg struct crocus_screen *screen = batch->screen; 3237ec681f3Smrg 3247ec681f3Smrg crocus_batch_maybe_flush(batch, 1500); 3257ec681f3Smrg crocus_require_statebuffer_space(batch, 2400); 3267ec681f3Smrg 3277ec681f3Smrg if (ice->state.vs_uses_draw_params || 3287ec681f3Smrg ice->state.vs_uses_derived_draw_params) 3297ec681f3Smrg crocus_update_draw_parameters(ice, draw, drawid_offset, indirect, sc); 3307ec681f3Smrg 3317ec681f3Smrg screen->vtbl.upload_render_state(ice, batch, draw, drawid_offset, indirect, sc); 3327ec681f3Smrg} 3337ec681f3Smrg 3347ec681f3Smrgstatic void 3357ec681f3Smrgcrocus_draw_vbo_get_vertex_count(struct pipe_context *ctx, 3367ec681f3Smrg const struct pipe_draw_info *info_in, 3377ec681f3Smrg unsigned drawid_offset, 3387ec681f3Smrg const struct pipe_draw_indirect_info *indirect) 3397ec681f3Smrg{ 3407ec681f3Smrg struct crocus_screen *screen = (struct crocus_screen *)ctx->screen; 3417ec681f3Smrg struct pipe_draw_info info = *info_in; 3427ec681f3Smrg struct pipe_draw_start_count_bias draw; 3437ec681f3Smrg 3447ec681f3Smrg uint32_t val = screen->vtbl.get_so_offset(indirect->count_from_stream_output); 3457ec681f3Smrg 3467ec681f3Smrg draw.start = 0; 3477ec681f3Smrg draw.count = val; 3487ec681f3Smrg ctx->draw_vbo(ctx, &info, drawid_offset, NULL, &draw, 1); 3497ec681f3Smrg} 3507ec681f3Smrg 3517ec681f3Smrg/** 3527ec681f3Smrg * The pipe->draw_vbo() driver hook. Performs a draw on the GPU. 3537ec681f3Smrg */ 3547ec681f3Smrgvoid 3557ec681f3Smrgcrocus_draw_vbo(struct pipe_context *ctx, 3567ec681f3Smrg const struct pipe_draw_info *info, 3577ec681f3Smrg unsigned drawid_offset, 3587ec681f3Smrg const struct pipe_draw_indirect_info *indirect, 3597ec681f3Smrg const struct pipe_draw_start_count_bias *draws, 3607ec681f3Smrg unsigned num_draws) 3617ec681f3Smrg{ 3627ec681f3Smrg if (num_draws > 1) { 3637ec681f3Smrg util_draw_multi(ctx, info, drawid_offset, indirect, draws, num_draws); 3647ec681f3Smrg return; 3657ec681f3Smrg } 3667ec681f3Smrg 3677ec681f3Smrg if (!indirect && (!draws[0].count || !info->instance_count)) 3687ec681f3Smrg return; 3697ec681f3Smrg 3707ec681f3Smrg struct crocus_context *ice = (struct crocus_context *) ctx; 3717ec681f3Smrg struct crocus_screen *screen = (struct crocus_screen*)ice->ctx.screen; 3727ec681f3Smrg struct crocus_batch *batch = &ice->batches[CROCUS_BATCH_RENDER]; 3737ec681f3Smrg 3747ec681f3Smrg if (!crocus_check_conditional_render(ice)) 3757ec681f3Smrg return; 3767ec681f3Smrg 3777ec681f3Smrg if (info->primitive_restart && !can_cut_index_handle_prim(ice, info)) { 3787ec681f3Smrg util_draw_vbo_without_prim_restart(ctx, info, drawid_offset, 3797ec681f3Smrg indirect, draws); 3807ec681f3Smrg return; 3817ec681f3Smrg } 3827ec681f3Smrg 3837ec681f3Smrg if (screen->devinfo.verx10 < 75 && 3847ec681f3Smrg indirect && indirect->count_from_stream_output) { 3857ec681f3Smrg crocus_draw_vbo_get_vertex_count(ctx, info, drawid_offset, indirect); 3867ec681f3Smrg return; 3877ec681f3Smrg } 3887ec681f3Smrg 3897ec681f3Smrg /** 3907ec681f3Smrg * The hardware is capable of removing dangling vertices on its own; however, 3917ec681f3Smrg * prior to Gen6, we sometimes convert quads into trifans (and quad strips 3927ec681f3Smrg * into tristrips), since pre-Gen6 hardware requires a GS to render quads. 3937ec681f3Smrg * This function manually trims dangling vertices from a draw call involving 3947ec681f3Smrg * quads so that those dangling vertices won't get drawn when we convert to 3957ec681f3Smrg * trifans/tristrips. 3967ec681f3Smrg */ 3977ec681f3Smrg if (screen->devinfo.ver < 6) { 3987ec681f3Smrg if (info->mode == PIPE_PRIM_QUADS || info->mode == PIPE_PRIM_QUAD_STRIP) { 3997ec681f3Smrg bool trim = u_trim_pipe_prim(info->mode, (unsigned *)&draws[0].count); 4007ec681f3Smrg if (!trim) 4017ec681f3Smrg return; 4027ec681f3Smrg } 4037ec681f3Smrg } 4047ec681f3Smrg 4057ec681f3Smrg /* We can't safely re-emit 3DSTATE_SO_BUFFERS because it may zero the 4067ec681f3Smrg * write offsets, changing the behavior. 4077ec681f3Smrg */ 4087ec681f3Smrg if (INTEL_DEBUG(DEBUG_REEMIT)) { 4097ec681f3Smrg ice->state.dirty |= CROCUS_ALL_DIRTY_FOR_RENDER & ~(CROCUS_DIRTY_GEN7_SO_BUFFERS | CROCUS_DIRTY_GEN6_SVBI); 4107ec681f3Smrg ice->state.stage_dirty |= CROCUS_ALL_STAGE_DIRTY_FOR_RENDER; 4117ec681f3Smrg } 4127ec681f3Smrg 4137ec681f3Smrg /* Emit Sandybridge workaround flushes on every primitive, for safety. */ 4147ec681f3Smrg if (screen->devinfo.ver == 6) 4157ec681f3Smrg crocus_emit_post_sync_nonzero_flush(batch); 4167ec681f3Smrg 4177ec681f3Smrg crocus_update_draw_info(ice, info, draws); 4187ec681f3Smrg 4197ec681f3Smrg if (!crocus_update_compiled_shaders(ice)) 4207ec681f3Smrg return; 4217ec681f3Smrg 4227ec681f3Smrg if (ice->state.dirty & CROCUS_DIRTY_RENDER_RESOLVES_AND_FLUSHES) { 4237ec681f3Smrg bool draw_aux_buffer_disabled[BRW_MAX_DRAW_BUFFERS] = { }; 4247ec681f3Smrg for (gl_shader_stage stage = 0; stage < MESA_SHADER_COMPUTE; stage++) { 4257ec681f3Smrg if (ice->shaders.prog[stage]) 4267ec681f3Smrg crocus_predraw_resolve_inputs(ice, batch, draw_aux_buffer_disabled, 4277ec681f3Smrg stage, true); 4287ec681f3Smrg } 4297ec681f3Smrg crocus_predraw_resolve_framebuffer(ice, batch, draw_aux_buffer_disabled); 4307ec681f3Smrg } 4317ec681f3Smrg 4327ec681f3Smrg crocus_handle_always_flush_cache(batch); 4337ec681f3Smrg 4347ec681f3Smrg if (indirect && indirect->buffer) 4357ec681f3Smrg crocus_indirect_draw_vbo(ice, info, drawid_offset, indirect, draws); 4367ec681f3Smrg else 4377ec681f3Smrg crocus_simple_draw_vbo(ice, info, drawid_offset, indirect, draws); 4387ec681f3Smrg 4397ec681f3Smrg crocus_handle_always_flush_cache(batch); 4407ec681f3Smrg 4417ec681f3Smrg crocus_postdraw_update_resolve_tracking(ice, batch); 4427ec681f3Smrg 4437ec681f3Smrg ice->state.dirty &= ~CROCUS_ALL_DIRTY_FOR_RENDER; 4447ec681f3Smrg ice->state.stage_dirty &= ~CROCUS_ALL_STAGE_DIRTY_FOR_RENDER; 4457ec681f3Smrg} 4467ec681f3Smrg 4477ec681f3Smrgstatic void 4487ec681f3Smrgcrocus_update_grid_size_resource(struct crocus_context *ice, 4497ec681f3Smrg const struct pipe_grid_info *grid) 4507ec681f3Smrg{ 4517ec681f3Smrg struct crocus_state_ref *grid_ref = &ice->state.grid_size; 4527ec681f3Smrg const struct crocus_compiled_shader *shader = ice->shaders.prog[MESA_SHADER_COMPUTE]; 4537ec681f3Smrg bool grid_needs_surface = shader->bt.used_mask[CROCUS_SURFACE_GROUP_CS_WORK_GROUPS]; 4547ec681f3Smrg 4557ec681f3Smrg if (grid->indirect) { 4567ec681f3Smrg pipe_resource_reference(&grid_ref->res, grid->indirect); 4577ec681f3Smrg grid_ref->offset = grid->indirect_offset; 4587ec681f3Smrg 4597ec681f3Smrg /* Zero out the grid size so that the next non-indirect grid launch will 4607ec681f3Smrg * re-upload it properly. 4617ec681f3Smrg */ 4627ec681f3Smrg memset(ice->state.last_grid, 0, sizeof(ice->state.last_grid)); 4637ec681f3Smrg } else if (memcmp(ice->state.last_grid, grid->grid, sizeof(grid->grid)) != 0) { 4647ec681f3Smrg memcpy(ice->state.last_grid, grid->grid, sizeof(grid->grid)); 4657ec681f3Smrg u_upload_data(ice->ctx.const_uploader, 0, sizeof(grid->grid), 4, 4667ec681f3Smrg grid->grid, &grid_ref->offset, &grid_ref->res); 4677ec681f3Smrg } 4687ec681f3Smrg 4697ec681f3Smrg /* Skip surface upload if we don't need it or we already have one */ 4707ec681f3Smrg if (!grid_needs_surface) 4717ec681f3Smrg return; 4727ec681f3Smrg 4737ec681f3Smrg ice->state.stage_dirty |= CROCUS_STAGE_DIRTY_BINDINGS_CS; 4747ec681f3Smrg} 4757ec681f3Smrg 4767ec681f3Smrg 4777ec681f3Smrgvoid 4787ec681f3Smrgcrocus_launch_grid(struct pipe_context *ctx, const struct pipe_grid_info *grid) 4797ec681f3Smrg{ 4807ec681f3Smrg struct crocus_context *ice = (struct crocus_context *) ctx; 4817ec681f3Smrg struct crocus_batch *batch = &ice->batches[CROCUS_BATCH_COMPUTE]; 4827ec681f3Smrg struct crocus_screen *screen = batch->screen; 4837ec681f3Smrg 4847ec681f3Smrg if (!crocus_check_conditional_render(ice)) 4857ec681f3Smrg return; 4867ec681f3Smrg 4877ec681f3Smrg if (INTEL_DEBUG(DEBUG_REEMIT)) { 4887ec681f3Smrg ice->state.dirty |= CROCUS_ALL_DIRTY_FOR_COMPUTE; 4897ec681f3Smrg ice->state.stage_dirty |= CROCUS_ALL_STAGE_DIRTY_FOR_COMPUTE; 4907ec681f3Smrg } 4917ec681f3Smrg 4927ec681f3Smrg /* We can't do resolves on the compute engine, so awkwardly, we have to 4937ec681f3Smrg * do them on the render batch... 4947ec681f3Smrg */ 4957ec681f3Smrg if (ice->state.dirty & CROCUS_DIRTY_COMPUTE_RESOLVES_AND_FLUSHES) { 4967ec681f3Smrg crocus_predraw_resolve_inputs(ice, &ice->batches[CROCUS_BATCH_RENDER], NULL, 4977ec681f3Smrg MESA_SHADER_COMPUTE, false); 4987ec681f3Smrg } 4997ec681f3Smrg 5007ec681f3Smrg crocus_batch_maybe_flush(batch, 1500); 5017ec681f3Smrg crocus_require_statebuffer_space(batch, 2500); 5027ec681f3Smrg crocus_update_compiled_compute_shader(ice); 5037ec681f3Smrg 5047ec681f3Smrg if (memcmp(ice->state.last_block, grid->block, sizeof(grid->block)) != 0) { 5057ec681f3Smrg memcpy(ice->state.last_block, grid->block, sizeof(grid->block)); 5067ec681f3Smrg ice->state.stage_dirty |= CROCUS_STAGE_DIRTY_CONSTANTS_CS; 5077ec681f3Smrg ice->state.shaders[MESA_SHADER_COMPUTE].sysvals_need_upload = true; 5087ec681f3Smrg } 5097ec681f3Smrg 5107ec681f3Smrg crocus_update_grid_size_resource(ice, grid); 5117ec681f3Smrg 5127ec681f3Smrg if (ice->state.compute_predicate) { 5137ec681f3Smrg screen->vtbl.emit_compute_predicate(batch); 5147ec681f3Smrg ice->state.compute_predicate = NULL; 5157ec681f3Smrg } 5167ec681f3Smrg 5177ec681f3Smrg crocus_handle_always_flush_cache(batch); 5187ec681f3Smrg 5197ec681f3Smrg screen->vtbl.upload_compute_state(ice, batch, grid); 5207ec681f3Smrg 5217ec681f3Smrg crocus_handle_always_flush_cache(batch); 5227ec681f3Smrg 5237ec681f3Smrg ice->state.dirty &= ~CROCUS_ALL_DIRTY_FOR_COMPUTE; 5247ec681f3Smrg ice->state.stage_dirty &= ~CROCUS_ALL_STAGE_DIRTY_FOR_COMPUTE; 5257ec681f3Smrg 5267ec681f3Smrg /* Note: since compute shaders can't access the framebuffer, there's 5277ec681f3Smrg * no need to call crocus_postdraw_update_resolve_tracking. 5287ec681f3Smrg */ 5297ec681f3Smrg} 530