diff options
-rw-r--r-- | src/gallium/drivers/ilo/ilo_render_gen6.c | 96 |
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; } |