summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/iris
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/iris')
-rw-r--r--src/gallium/drivers/iris/iris_context.h5
-rw-r--r--src/gallium/drivers/iris/iris_draw.c65
-rw-r--r--src/gallium/drivers/iris/iris_state.c29
3 files changed, 99 insertions, 0 deletions
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
@@ -40,6 +40,67 @@
#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), &reg_val, reg) {
+ reg.ReplayMode = enable;
+ reg.ReplayModeMask = true;
+ }
+ iris_emit_lri(batch, CS_CHICKEN1, reg_val);
+}
+#endif