From 002b4a3273645ef9c83b46dbb5ee938fe3cec0fd Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Tue, 1 Jul 2014 17:25:33 -0700 Subject: [PATCH 2/2] i965: Disable SOL buffers and decls when not doing transform feedback. Previously, we only emitted 3DSTATE_SO_BUFFER and 3DSTATE_SO_DECL_LIST when transform feedback was active. When it was inactive, we disabled the SOL stage in 3DSTATE_SOL so the other state would be ignored. In commit 3178d2474ae5bdd1102fb3d76a60d1d63c961ff5, Iago enabled the SOL stage universally, so we could implement the GL_PRIMITIVES_GENERATED statistics counter. This caused every Piglit test to trigger assertions in the simulator, and apparently caused GPU hangs for some users. Apparently, we're supposed to program 3DSTATE_SO_DECL_LIST to zero when output streams are inactive, but we hadn't been doing so. Now that SOL is on, we need to do that properly. Experimentally, it looks like we also need to program 3DSTATE_SO_BUFFER to zero as well, or else I get many GPU hangs on Haswell. Signed-off-by: Kenneth Graunke Cc: Iago Toral Quiroga Cc: Chris Forbes Cc: Steven Newbury --- src/mesa/drivers/dri/i965/brw_state.h | 3 ++- src/mesa/drivers/dri/i965/gen7_sol_state.c | 36 ++++++++++++++++++++++-------- src/mesa/drivers/dri/i965/gen8_sol_state.c | 2 +- 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/src/mesa/drivers/dri/i965/brw_state.h b/src/mesa/drivers/dri/i965/brw_state.h index c52a977..2c1fc87 100644 --- a/src/mesa/drivers/dri/i965/brw_state.h +++ b/src/mesa/drivers/dri/i965/brw_state.h @@ -237,7 +237,8 @@ void gen7_init_vtable_surface_functions(struct brw_context *brw); /* gen7_sol_state.c */ void gen7_upload_3dstate_so_decl_list(struct brw_context *brw, - const struct brw_vue_map *vue_map); + const struct brw_vue_map *vue_map, + bool active); /* gen8_surface_state.c */ void gen8_init_vtable_surface_functions(struct brw_context *brw); diff --git a/src/mesa/drivers/dri/i965/gen7_sol_state.c b/src/mesa/drivers/dri/i965/gen7_sol_state.c index 1c8dc0a..5284567 100644 --- a/src/mesa/drivers/dri/i965/gen7_sol_state.c +++ b/src/mesa/drivers/dri/i965/gen7_sol_state.c @@ -36,7 +36,7 @@ #include "main/transformfeedback.h" static void -upload_3dstate_so_buffers(struct brw_context *brw) +upload_3dstate_so_buffers(struct brw_context *brw, bool active) { struct gl_context *ctx = &brw->ctx; /* BRW_NEW_TRANSFORM_FEEDBACK */ @@ -56,7 +56,7 @@ upload_3dstate_so_buffers(struct brw_context *brw) uint32_t start, end; uint32_t stride; - if (!xfb_obj->Buffers[i]) { + if (!xfb_obj->Buffers[i] || !active) { /* The pitch of 0 in this command indicates that the buffer is * unbound and won't be written to. */ @@ -96,10 +96,30 @@ upload_3dstate_so_buffers(struct brw_context *brw) */ void gen7_upload_3dstate_so_decl_list(struct brw_context *brw, - const struct brw_vue_map *vue_map) + const struct brw_vue_map *vue_map, + bool active) { - struct gl_context *ctx = &brw->ctx; + if (!active) { + /* If inactive, disable all SO outputs. + * + * From the Ivybridge PRM, Volume 2, Part 1, page 202 + * (3DSTATE_SO_DECL_LIST packet definition), DWord 1, bits 3:0: + * "Note: For 'inactive' streams, software must program this field to + * all zero (no buffers written to) and the corresponding Num Entries + * field to zero (no valid SO_DECLs)." + */ + BEGIN_BATCH(5); + OUT_BATCH(_3DSTATE_SO_DECL_LIST << 16 | (5 - 2)); + OUT_BATCH(0); + OUT_BATCH(0); + OUT_BATCH(0); + OUT_BATCH(0); + ADVANCE_BATCH(); + return; + } + /* BRW_NEW_TRANSFORM_FEEDBACK */ + struct gl_context *ctx = &brw->ctx; struct gl_transform_feedback_object *xfb_obj = ctx->TransformFeedback.CurrentObject; const struct gl_transform_feedback_info *linked_xfb_info = @@ -287,11 +307,9 @@ upload_sol_state(struct brw_context *brw) /* BRW_NEW_TRANSFORM_FEEDBACK */ bool active = _mesa_is_xfb_active_and_unpaused(ctx); - if (active) { - upload_3dstate_so_buffers(brw); - /* BRW_NEW_VUE_MAP_GEOM_OUT */ - gen7_upload_3dstate_so_decl_list(brw, &brw->vue_map_geom_out); - } + upload_3dstate_so_buffers(brw, active); + /* BRW_NEW_VUE_MAP_GEOM_OUT */ + gen7_upload_3dstate_so_decl_list(brw, &brw->vue_map_geom_out, active); /* Finally, set up the SOL stage. This command must always follow updates to * the nonpipelined SOL state (3DSTATE_SO_BUFFER, 3DSTATE_SO_DECL_LIST) or diff --git a/src/mesa/drivers/dri/i965/gen8_sol_state.c b/src/mesa/drivers/dri/i965/gen8_sol_state.c index ebcdaf8..ff85bf2 100644 --- a/src/mesa/drivers/dri/i965/gen8_sol_state.c +++ b/src/mesa/drivers/dri/i965/gen8_sol_state.c @@ -157,7 +157,7 @@ upload_sol_state(struct brw_context *brw) if (active) { gen8_upload_3dstate_so_buffers(brw); /* BRW_NEW_VUE_MAP_GEOM_OUT */ - gen7_upload_3dstate_so_decl_list(brw, &brw->vue_map_geom_out); + gen7_upload_3dstate_so_decl_list(brw, &brw->vue_map_geom_out, active); } gen8_upload_3dstate_streamout(brw, active, &brw->vue_map_geom_out); -- 1.9.1