summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gallium/drivers/ilo/ilo_render_gen6.c96
1 files changed, 62 insertions, 34 deletions
diff --git a/src/gallium/drivers/ilo/ilo_render_gen6.c b/src/gallium/drivers/ilo/ilo_render_gen6.c
index 902d398e0cb..1c101acb867 100644
--- a/src/gallium/drivers/ilo/ilo_render_gen6.c
+++ b/src/gallium/drivers/ilo/ilo_render_gen6.c
@@ -112,6 +112,26 @@ gen6_wa_pre_non_pipelined(struct ilo_render *r)
}
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,9 +143,32 @@ 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;
}