From 7315882023806e5326601bdbe21c7db5862a5d58 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Thu, 11 Apr 2019 10:07:15 -0400 Subject: [PATCH] iris: add preemption support on gen9 this is basically just porting the following two commits to gallium: d8b50e152a0d5df0971c05b8db132fa688794001 5c454661c66fa2624cf4bba1071175070724869a resolves kwg/mesa#49 Reviewed-by: Anuj Phogat Reviewed-by: Rafael Antognolli --- src/gallium/drivers/iris/iris_context.h | 5 ++ src/gallium/drivers/iris/iris_draw.c | 65 +++++++++++++++++++++++++ src/gallium/drivers/iris/iris_state.c | 29 +++++++++++ 3 files changed, 99 insertions(+) diff --git a/src/gallium/drivers/iris/iris_context.h b/src/gallium/drivers/iris/iris_context.h index f660c9ae251..79e78d0adb7 100644 --- a/src/gallium/drivers/iris/iris_context.h +++ b/src/gallium/drivers/iris/iris_context.h @@ -542,6 +542,8 @@ struct iris_context { /** Bitfield of which vertex buffers are bound (non-null). */ uint64_t bound_vertex_buffers; + bool object_preemption; /**< Object level preemption enabled. */ + bool primitive_restart; unsigned cut_index; enum pipe_prim_type prim_mode:8; @@ -816,4 +818,7 @@ void iris_render_cache_add_bo(struct iris_batch *batch, void iris_cache_flush_for_depth(struct iris_batch *batch, struct iris_bo *bo); void iris_depth_cache_add_bo(struct iris_batch *batch, struct iris_bo *bo); +/* iris_state.c */ +void gen9_iris_enable_obj_preemption(struct iris_context *ice, struct iris_batch *batch, bool enable); +void gen10_iris_enable_obj_preemption(struct iris_context *ice, struct iris_batch *batch, bool enable); #endif diff --git a/src/gallium/drivers/iris/iris_draw.c b/src/gallium/drivers/iris/iris_draw.c index e94346f33f0..c859d93c009 100644 --- a/src/gallium/drivers/iris/iris_draw.c +++ b/src/gallium/drivers/iris/iris_draw.c @@ -39,6 +39,67 @@ #include "iris_context.h" #include "iris_defines.h" +/** + * Implement workarounds for preemption: + * - WaDisableMidObjectPreemptionForGSLineStripAdj + * - WaDisableMidObjectPreemptionForTrifanOrPolygon + * - WaDisableMidObjectPreemptionForLineLoop + * - WA#0798 + */ +static void +gen9_emit_preempt_wa(struct iris_context *ice, struct iris_batch *batch, + const struct pipe_draw_info *info) +{ + bool object_preemption = true; + struct iris_screen *screen = (struct iris_screen *)ice->ctx.screen; + + /* Only apply these workarounds for gen9 */ + assert(screen->devinfo.gen == 9); + + /* WaDisableMidObjectPreemptionForGSLineStripAdj + * + * WA: Disable mid-draw preemption when draw-call is a linestrip_adj and + * GS is enabled. + */ + if (ice->state.prim_mode == PIPE_PRIM_LINE_STRIP_ADJACENCY && + ice->shaders.prog[MESA_SHADER_GEOMETRY]) + object_preemption = false; + + /* WaDisableMidObjectPreemptionForTrifanOrPolygon + * + * TriFan miscompare in Execlist Preemption test. Cut index that is on a + * previous context. End the previous, the resume another context with a + * tri-fan or polygon, and the vertex count is corrupted. If we prempt + * again we will cause corruption. + * + * WA: Disable mid-draw preemption when draw-call has a tri-fan. + */ + if (ice->state.prim_mode == PIPE_PRIM_TRIANGLE_FAN) + object_preemption = false; + + /* WaDisableMidObjectPreemptionForLineLoop + * + * VF Stats Counters Missing a vertex when preemption enabled. + * + * WA: Disable mid-draw preemption when the draw uses a lineloop + * topology. + */ + if (ice->state.prim_mode == PIPE_PRIM_LINE_LOOP) + object_preemption = false; + + /* WA#0798 + * + * VF is corrupting GAFS data when preempted on an instance boundary and + * replayed with instancing enabled. + * + * WA: Disable preemption when using instanceing. + */ + if (info->instance_count > 1) + object_preemption = false; + + gen9_iris_enable_obj_preemption(ice, batch, object_preemption); +} + /** * Record the current primitive mode and restart information, flagging * related packets as dirty if necessary. @@ -116,6 +177,7 @@ void iris_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info) { struct iris_context *ice = (struct iris_context *) ctx; + struct iris_screen *screen = (struct iris_screen*)ice->ctx.screen; struct iris_batch *batch = &ice->batches[IRIS_BATCH_RENDER]; if (ice->state.predicate == IRIS_PREDICATE_STATE_DONT_RENDER) @@ -131,6 +193,9 @@ iris_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info) iris_update_draw_info(ice, info); + if (screen->devinfo.gen == 9) + gen9_emit_preempt_wa(ice, batch, info); + iris_update_compiled_shaders(ice); if (ice->state.dirty & IRIS_DIRTY_RENDER_RESOLVES_AND_FLUSHES) { diff --git a/src/gallium/drivers/iris/iris_state.c b/src/gallium/drivers/iris/iris_state.c index 4760da09c45..92275b48a4d 100644 --- a/src/gallium/drivers/iris/iris_state.c +++ b/src/gallium/drivers/iris/iris_state.c @@ -6278,3 +6278,32 @@ genX(init_state)(struct iris_context *ice) }; } } + +#if GEN_GEN >= 9 +/* not called externally */ +void gen11_iris_enable_obj_preemption(struct iris_context *ice, struct iris_batch *batch, bool enable); + +void +genX(iris_enable_obj_preemption)(struct iris_context *ice, struct iris_batch *batch, bool enable) +{ + uint32_t reg_val; + struct iris_screen *screen = (struct iris_screen *)ice->ctx.screen; + + assert(screen->devinfo.gen >= 9); + + if (enable == ice->state.object_preemption) + return; + ice->state.object_preemption = enable; + + /* A fixed function pipe flush is required before modifying this field */ + iris_emit_end_of_pipe_sync(batch, + PIPE_CONTROL_RENDER_TARGET_FLUSH); + + /* enable object level preemption */ + iris_pack_state(GENX(CS_CHICKEN1), ®_val, reg) { + reg.ReplayMode = enable; + reg.ReplayModeMask = true; + } + iris_emit_lri(batch, CS_CHICKEN1, reg_val); +} +#endif -- 2.30.2