ilo: clean up Gen6 WAs
authorChia-I Wu <olvaffe@gmail.com>
Fri, 6 Mar 2015 17:55:15 +0000 (01:55 +0800)
committerChia-I Wu <olvaffe@gmail.com>
Fri, 6 Mar 2015 18:17:54 +0000 (02:17 +0800)
Add a help function for each WA and make PIPE_CONTROL flags match the WA
descriptions.  Call gen6_wa_pre_pipe_contro() only before PIPE_CONTROLs.
Fix missing gen6_wa_pre_3dstate_vs_toggle() in the rectlist path.

src/gallium/drivers/ilo/ilo_render_gen6.c

index 902d398e0cb9a6c9f70f9f7400e3089855a976ec..1c101acb867dfb09fa3c7707eae6513655883000 100644 (file)
@@ -111,6 +111,26 @@ gen6_wa_pre_non_pipelined(struct ilo_render *r)
    gen6_wa_pre_pipe_control(r, GEN6_PIPE_CONTROL_DEPTH_STALL);
 }
 
+static void
+gen6_wa_post_3dstate_urb_no_gs(struct ilo_render *r)
+{
+   /*
+    * From the Sandy Bridge PRM, volume 2 part 1, page 27:
+    *
+    *     "Because of a urb corruption caused by allocating a previous
+    *      gsunit's urb entry to vsunit software is required to send a
+    *      "GS NULL Fence" (Send URB fence with VS URB size == 1 and GS URB
+    *      size == 0) plus a dummy DRAW call before any case where VS will
+    *      be taking over GS URB space."
+    */
+   const uint32_t dw1 = GEN6_PIPE_CONTROL_CS_STALL;
+
+   if ((r->state.current_pipe_control_dw1 & dw1) != dw1)
+      gen6_wa_pre_pipe_control(r, dw1);
+   if ((r->state.current_pipe_control_dw1 & dw1) != dw1)
+      ilo_render_pipe_control(r, dw1);
+}
+
 static void
 gen6_wa_post_3dstate_constant_vs(struct ilo_render *r)
 {
@@ -123,8 +143,31 @@ gen6_wa_post_3dstate_constant_vs(struct ilo_render *r)
                         GEN6_PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE |
                         GEN6_PIPE_CONTROL_STATE_CACHE_INVALIDATE;
 
-   gen6_wa_pre_pipe_control(r, dw1);
+   if ((r->state.current_pipe_control_dw1 & dw1) != dw1)
+      gen6_wa_pre_pipe_control(r, dw1);
+   if ((r->state.current_pipe_control_dw1 & dw1) != dw1)
+      ilo_render_pipe_control(r, dw1);
+}
+
+static void
+gen6_wa_pre_3dstate_vs_toggle(struct ilo_render *r)
+{
+   /*
+    * The classic driver has this undocumented WA:
+    *
+    * From the BSpec, 3D Pipeline > Geometry > Vertex Shader > State,
+    * 3DSTATE_VS, Dword 5.0 "VS Function Enable":
+    *
+    *   [DevSNB] A pipeline flush must be programmed prior to a 3DSTATE_VS
+    *   command that causes the VS Function Enable to toggle. Pipeline
+    *   flush can be executed by sending a PIPE_CONTROL command with CS
+    *   stall bit set and a post sync operation.
+    */
+   const uint32_t dw1 = GEN6_PIPE_CONTROL_WRITE_IMM |
+                        GEN6_PIPE_CONTROL_CS_STALL;
 
+   if ((r->state.current_pipe_control_dw1 & dw1) != dw1)
+      gen6_wa_pre_pipe_control(r, dw1);
    if ((r->state.current_pipe_control_dw1 & dw1) != dw1)
       ilo_render_pipe_control(r, dw1);
 }
@@ -143,8 +186,8 @@ gen6_wa_pre_3dstate_wm_max_threads(struct ilo_render *r)
 
    ILO_DEV_ASSERT(r->dev, 6, 6);
 
-   gen6_wa_pre_pipe_control(r, dw1);
-
+   if ((r->state.current_pipe_control_dw1 & dw1) != dw1)
+      gen6_wa_pre_pipe_control(r, dw1);
    if ((r->state.current_pipe_control_dw1 & dw1) != dw1)
       ilo_render_pipe_control(r, dw1);
 }
@@ -165,8 +208,8 @@ gen6_wa_pre_3dstate_multisample(struct ilo_render *r)
 
    ILO_DEV_ASSERT(r->dev, 6, 6);
 
-   gen6_wa_pre_pipe_control(r, dw1);
-
+   if ((r->state.current_pipe_control_dw1 & dw1) != dw1)
+      gen6_wa_pre_pipe_control(r, dw1);
    if ((r->state.current_pipe_control_dw1 & dw1) != dw1)
       ilo_render_pipe_control(r, dw1);
 }
@@ -340,17 +383,8 @@ gen6_draw_common_urb(struct ilo_render *r,
       gen6_3DSTATE_URB(r->builder, vs_total_size, gs_total_size,
             vs_entry_size, gs_entry_size);
 
-      /*
-       * From the Sandy Bridge PRM, volume 2 part 1, page 27:
-       *
-       *     "Because of a urb corruption caused by allocating a previous
-       *      gsunit's urb entry to vsunit software is required to send a
-       *      "GS NULL Fence" (Send URB fence with VS URB size == 1 and GS URB
-       *      size == 0) plus a dummy DRAW call before any case where VS will
-       *      be taking over GS URB space."
-       */
       if (r->state.gs.active && !gs_active)
-         ilo_render_emit_flush(r);
+         gen6_wa_post_3dstate_urb_no_gs(r);
 
       r->state.gs.active = gs_active;
    }
@@ -469,30 +503,24 @@ gen6_draw_vs(struct ilo_render *r,
              const struct ilo_state_vector *vec,
              struct ilo_render_draw_session *session)
 {
-   const bool emit_3dstate_vs = (DIRTY(VS) || r->instruction_bo_changed);
-   const bool emit_3dstate_constant_vs = session->pcb_vs_changed;
-
-   /*
-    * the classic i965 does this in upload_vs_state(), citing a spec that I
-    * cannot find
-    */
-   if (emit_3dstate_vs && ilo_dev_gen(r->dev) == ILO_GEN(6))
-      gen6_wa_pre_non_pipelined(r);
-
    /* 3DSTATE_CONSTANT_VS */
-   if (emit_3dstate_constant_vs) {
+   if (session->pcb_vs_changed) {
       gen6_3DSTATE_CONSTANT_VS(r->builder,
             &r->state.vs.PUSH_CONSTANT_BUFFER,
             &r->state.vs.PUSH_CONSTANT_BUFFER_size,
             1);
+
+      if (ilo_dev_gen(r->dev) == ILO_GEN(6))
+         gen6_wa_post_3dstate_constant_vs(r);
    }
 
    /* 3DSTATE_VS */
-   if (emit_3dstate_vs)
-      gen6_3DSTATE_VS(r->builder, vec->vs);
+   if (DIRTY(VS) || r->instruction_bo_changed) {
+      if (ilo_dev_gen(r->dev) == ILO_GEN(6))
+         gen6_wa_pre_3dstate_vs_toggle(r);
 
-   if (emit_3dstate_constant_vs && ilo_dev_gen(r->dev) == ILO_GEN(6))
-      gen6_wa_post_3dstate_constant_vs(r);
+      gen6_3DSTATE_VS(r->builder, vec->vs);
+   }
 }
 
 static void
@@ -829,10 +857,11 @@ gen6_rectlist_vs_to_sf(struct ilo_render *r,
                        const struct ilo_blitter *blitter)
 {
    gen6_3DSTATE_CONSTANT_VS(r->builder, NULL, NULL, 0);
-   gen6_disable_3DSTATE_VS(r->builder);
-
    gen6_wa_post_3dstate_constant_vs(r);
 
+   gen6_wa_pre_3dstate_vs_toggle(r);
+   gen6_disable_3DSTATE_VS(r->builder);
+
    gen6_3DSTATE_CONSTANT_GS(r->builder, NULL, NULL, 0);
    gen6_disable_3DSTATE_GS(r->builder);
 
@@ -941,9 +970,8 @@ ilo_render_emit_rectlist_commands_gen6(struct ilo_render *r,
          (blitter->ve.count + blitter->ve.prepend_nosrc_cso) * 4 * sizeof(float),
          0);
 
-   /* 3DSTATE_URB workaround */
    if (r->state.gs.active) {
-      ilo_render_emit_flush(r);
+      gen6_wa_post_3dstate_urb_no_gs(r);
       r->state.gs.active = false;
    }