diff --git a/src/gallium/drivers/iris/iris_context.h b/src/gallium/drivers/iris/iris_context.h index 51bbdb681e7..31f345d36b0 100644 --- a/src/gallium/drivers/iris/iris_context.h +++ b/src/gallium/drivers/iris/iris_context.h @@ -504,6 +504,9 @@ struct iris_context { unsigned urb_size; + /** Is a GS or TES outputting points or lines? */ + bool output_topology_is_points_or_lines; + /* Track last VS URB entry size */ unsigned last_vs_entry_size; @@ -548,6 +551,7 @@ struct iris_context { bool primitive_restart; unsigned cut_index; enum pipe_prim_type prim_mode:8; + bool prim_is_points_or_lines; uint8_t vertices_per_patch; /** The last compute grid size */ diff --git a/src/gallium/drivers/iris/iris_draw.c b/src/gallium/drivers/iris/iris_draw.c index 94af728c693..86fc95cac0c 100644 --- a/src/gallium/drivers/iris/iris_draw.c +++ b/src/gallium/drivers/iris/iris_draw.c @@ -36,9 +36,22 @@ #include "util/u_transfer.h" #include "util/u_upload_mgr.h" #include "intel/compiler/brw_compiler.h" +#include "intel/compiler/brw_eu_defines.h" #include "iris_context.h" #include "iris_defines.h" +static bool +prim_is_points_or_lines(const struct pipe_draw_info *draw) +{ + /* We don't need to worry about adjacency - it can only be used with + * geometry shaders, and we don't care about this info when GS is on. + */ + return draw->mode == PIPE_PRIM_POINTS || + draw->mode == PIPE_PRIM_LINES || + draw->mode == PIPE_PRIM_LINE_LOOP || + draw->mode == PIPE_PRIM_LINE_STRIP; +} + /** * Record the current primitive mode and restart information, flagging * related packets as dirty if necessary. @@ -50,6 +63,14 @@ iris_update_draw_info(struct iris_context *ice, if (ice->state.prim_mode != info->mode) { ice->state.prim_mode = info->mode; ice->state.dirty |= IRIS_DIRTY_VF_TOPOLOGY; + + + /* For XY Clip enables */ + bool points_or_lines = prim_is_points_or_lines(info); + if (points_or_lines != ice->state.prim_is_points_or_lines) { + ice->state.prim_is_points_or_lines = points_or_lines; + ice->state.dirty |= IRIS_DIRTY_CLIP; + } } if (info->mode == PIPE_PRIM_PATCHES && diff --git a/src/gallium/drivers/iris/iris_program.c b/src/gallium/drivers/iris/iris_program.c index eff7c775212..30ec3f1ff86 100644 --- a/src/gallium/drivers/iris/iris_program.c +++ b/src/gallium/drivers/iris/iris_program.c @@ -1241,6 +1241,33 @@ iris_update_compiled_shaders(struct iris_context *ice) if (dirty & IRIS_DIRTY_UNCOMPILED_GS) iris_update_compiled_gs(ice); + if (dirty & (IRIS_DIRTY_UNCOMPILED_GS | IRIS_DIRTY_UNCOMPILED_TES)) { + const struct iris_compiled_shader *gs = + ice->shaders.prog[MESA_SHADER_GEOMETRY]; + const struct iris_compiled_shader *tes = + ice->shaders.prog[MESA_SHADER_TESS_EVAL]; + + bool points_or_lines = false; + + if (gs) { + const struct brw_gs_prog_data *gs_prog_data = (void *) gs->prog_data; + points_or_lines = + gs_prog_data->output_topology == _3DPRIM_POINTLIST || + gs_prog_data->output_topology == _3DPRIM_LINESTRIP; + } else if (tes) { + const struct brw_tes_prog_data *tes_data = (void *) tes->prog_data; + points_or_lines = + tes_data->output_topology == BRW_TESS_OUTPUT_TOPOLOGY_LINE || + tes_data->output_topology == BRW_TESS_OUTPUT_TOPOLOGY_POINT; + } + + if (ice->shaders.output_topology_is_points_or_lines != points_or_lines) { + /* Outbound to XY Clip enables */ + ice->shaders.output_topology_is_points_or_lines = points_or_lines; + ice->state.dirty |= IRIS_DIRTY_CLIP; + } + } + gl_shader_stage last_stage = last_vue_stage(ice); struct iris_compiled_shader *shader = ice->shaders.prog[last_stage]; struct iris_uncompiled_shader *ish = ice->shaders.uncompiled[last_stage]; @@ -1261,7 +1288,6 @@ iris_update_compiled_shaders(struct iris_context *ice) if (dirty & IRIS_DIRTY_UNCOMPILED_FS) iris_update_compiled_fs(ice); - // ... /* Changing shader interfaces may require a URB configuration. */ if (!(dirty & IRIS_DIRTY_URB)) { diff --git a/src/gallium/drivers/iris/iris_state.c b/src/gallium/drivers/iris/iris_state.c index 479703f30fa..91659f4f67b 100644 --- a/src/gallium/drivers/iris/iris_state.c +++ b/src/gallium/drivers/iris/iris_state.c @@ -1182,6 +1182,7 @@ struct iris_rasterizer_state { bool multisample; bool force_persample_interp; bool conservative_rasterization; + bool fill_mode_point_or_line; enum pipe_sprite_coord_mode sprite_coord_mode; /* PIPE_SPRITE_* */ uint16_t sprite_coord_enable; }; @@ -1244,6 +1245,12 @@ iris_create_rasterizer_state(struct pipe_context *ctx, cso->conservative_rasterization = state->conservative_raster_mode == PIPE_CONSERVATIVE_RASTER_POST_SNAP; + cso->fill_mode_point_or_line = + state->fill_front == PIPE_POLYGON_MODE_LINE || + state->fill_front == PIPE_POLYGON_MODE_POINT || + state->fill_back == PIPE_POLYGON_MODE_LINE || + state->fill_back == PIPE_POLYGON_MODE_POINT; + if (state->clip_plane_enable != 0) cso->num_clip_plane_consts = util_logbase2(state->clip_plane_enable) + 1; else @@ -1308,7 +1315,6 @@ iris_create_rasterizer_state(struct pipe_context *ctx, cl.APIMode = state->clip_halfz ? APIMODE_D3D : APIMODE_OGL; cl.GuardbandClipTestEnable = true; cl.ClipEnable = true; - cl.ViewportXYClipTestEnable = state->point_tri_clip; cl.MinimumPointWidth = 0.125; cl.MaximumPointWidth = 255.875; @@ -4770,11 +4776,19 @@ iris_upload_dirty_render_state(struct iris_context *ice, struct iris_rasterizer_state *cso_rast = ice->state.cso_rast; struct pipe_framebuffer_state *cso_fb = &ice->state.framebuffer; + bool gs_or_tes = ice->shaders.prog[MESA_SHADER_GEOMETRY] || + ice->shaders.prog[MESA_SHADER_TESS_EVAL]; + bool points_or_lines = cso_rast->fill_mode_point_or_line || + (gs_or_tes ? ice->shaders.output_topology_is_points_or_lines + : ice->state.prim_is_points_or_lines); + uint32_t dynamic_clip[GENX(3DSTATE_CLIP_length)]; iris_pack_command(GENX(3DSTATE_CLIP), &dynamic_clip, cl) { cl.StatisticsEnable = ice->state.statistics_counters_enabled; cl.ClipMode = cso_rast->rasterizer_discard ? CLIPMODE_REJECT_ALL : CLIPMODE_NORMAL; + cl.ViewportXYClipTestEnable = !points_or_lines; + if (wm_prog_data->barycentric_interp_modes & BRW_BARYCENTRIC_NONPERSPECTIVE_BITS) cl.NonPerspectiveBarycentricEnable = true;