From 38dfedccb2a2b695a600350a75113e8c35683498 Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Thu, 1 Sep 2011 04:18:20 -0700 Subject: [PATCH] i965: Emit depth stalls and flushes before changing depth state on Gen6+. Fixes OpenArena on Gen7. Technically, adding only the first depth stall fixes it, but the documentation says to do all three, and the Windows driver seems to do it. Not observed to fix anything on Gen6 yet. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=38863 Signed-off-by: Kenneth Graunke Reviewed-by: Eric Anholt (cherry picked from commit 02c4dc807e91640c69c8addc3c797300a3c536ad) --- src/mesa/drivers/dri/i965/brw_misc_state.c | 4 +- src/mesa/drivers/dri/i965/gen7_misc_state.c | 2 + .../drivers/dri/intel/intel_batchbuffer.c | 39 +++++++++++++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/src/mesa/drivers/dri/i965/brw_misc_state.c b/src/mesa/drivers/dri/i965/brw_misc_state.c index e5748060de7..a1429ce5c70 100644 --- a/src/mesa/drivers/dri/i965/brw_misc_state.c +++ b/src/mesa/drivers/dri/i965/brw_misc_state.c @@ -226,8 +226,10 @@ static void emit_depthbuffer(struct brw_context *brw) /* 3DSTATE_DEPTH_BUFFER, 3DSTATE_STENCIL_BUFFER are both * non-pipelined state that will need the PIPE_CONTROL workaround. */ - if (intel->gen == 6) + if (intel->gen == 6) { intel_emit_post_sync_nonzero_flush(intel); + intel_emit_depth_stall_flushes(intel); + } /* * If either depth or stencil buffer has packed depth/stencil format, diff --git a/src/mesa/drivers/dri/i965/gen7_misc_state.c b/src/mesa/drivers/dri/i965/gen7_misc_state.c index 7544f961da9..9eb75e2a76d 100644 --- a/src/mesa/drivers/dri/i965/gen7_misc_state.c +++ b/src/mesa/drivers/dri/i965/gen7_misc_state.c @@ -80,6 +80,8 @@ static void emit_depthbuffer(struct brw_context *brw) struct intel_renderbuffer *drb = intel_get_renderbuffer(fb, BUFFER_DEPTH); struct intel_renderbuffer *srb = intel_get_renderbuffer(fb, BUFFER_STENCIL); + intel_emit_depth_stall_flushes(intel); + /* Gen7 doesn't support packed depth/stencil */ assert(srb == NULL || srb != drb); diff --git a/src/mesa/drivers/dri/intel/intel_batchbuffer.c b/src/mesa/drivers/dri/intel/intel_batchbuffer.c index 7ee802be9de..7ef8e6596b1 100644 --- a/src/mesa/drivers/dri/intel/intel_batchbuffer.c +++ b/src/mesa/drivers/dri/intel/intel_batchbuffer.c @@ -293,6 +293,45 @@ emit: item->header = intel->batch.emit; } +/** + * Restriction [DevSNB, DevIVB]: + * + * Prior to changing Depth/Stencil Buffer state (i.e. any combination of + * 3DSTATE_DEPTH_BUFFER, 3DSTATE_CLEAR_PARAMS, 3DSTATE_STENCIL_BUFFER, + * 3DSTATE_HIER_DEPTH_BUFFER) SW must first issue a pipelined depth stall + * (PIPE_CONTROL with Depth Stall bit set), followed by a pipelined depth + * cache flush (PIPE_CONTROL with Depth Flush Bit set), followed by + * another pipelined depth stall (PIPE_CONTROL with Depth Stall bit set), + * unless SW can otherwise guarantee that the pipeline from WM onwards is + * already flushed (e.g., via a preceding MI_FLUSH). + */ +void +intel_emit_depth_stall_flushes(struct intel_context *intel) +{ + assert(intel->gen >= 6 && intel->gen <= 7); + + BEGIN_BATCH(4); + OUT_BATCH(_3DSTATE_PIPE_CONTROL); + OUT_BATCH(PIPE_CONTROL_DEPTH_STALL); + OUT_BATCH(0); /* address */ + OUT_BATCH(0); /* write data */ + ADVANCE_BATCH() + + BEGIN_BATCH(4); + OUT_BATCH(_3DSTATE_PIPE_CONTROL); + OUT_BATCH(PIPE_CONTROL_DEPTH_CACHE_FLUSH); + OUT_BATCH(0); /* address */ + OUT_BATCH(0); /* write data */ + ADVANCE_BATCH(); + + BEGIN_BATCH(4); + OUT_BATCH(_3DSTATE_PIPE_CONTROL); + OUT_BATCH(PIPE_CONTROL_DEPTH_STALL); + OUT_BATCH(0); /* address */ + OUT_BATCH(0); /* write data */ + ADVANCE_BATCH(); +} + /** * Emits a PIPE_CONTROL with a non-zero post-sync operation, for * implementing two workarounds on gen6. From section 1.4.7.1